Dos Batch Math Library

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
einstein1969
Expert
Posts: 941
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: Dos Batch Math Library

#61 Post by einstein1969 » 18 Oct 2022 06:18

Hello everybody,

this thread has been dead since about 2015. I got sick and I couldn't work on anything anymore. But now I feel better and even though the batch dos is dying by now, I would like to give it the finishing touches. I have seen that many threads have been born over time and they are very interesting and I will make a collection of these on the first or second page so as to have them all present.

Lately I took an old project of mine (a porting of http://www.p01.org/128b_raytraced_checkboard/ ) and readjusted it to the new features of windows 10 (the escape sequences similar to the very old ansi.sys)

Take everything I do as a way to practice doing things at the limit of dos bach power.

All ancillary features have been developed by aGerman (steffen) and has chosen the new windows powershell engine. The rest is pure dos batch. Thanks again aGerman!

Code: Select all

@echo off & setlocal EnableDelayedExpansion 

rem save how utf8

call :GetInfo

set /a X=ccx/2, Y=ccy/2

for /L %%L in (1,1,15) do (
	set /a nx=ccx/%%L, ny=ccy/%%L
        if !nx! leq 15 set nx=15
	mode con cols=!nx! lines=!ny!
)

call :init_fade

%fade% 0 10 100 1

call  :init_setfont

%setfont% 8 Terminal

mode con cols=82 lines=50

call :GetInfo
call :AndCenter

%fade% 100 -5 0 20

chcp 65001 >nul

for /f "delims=" %%E in (
    'forfiles /p "%~dp0." /m "%~nx0" /c "cmd /c echo(0x1B"'
  ) do (
    cls
    echo(
    <nul set /p "=%%E7"
    set "cls=<nul set /p "=%%E8""
    set "col=%%E[38;2;"
:: Hide the cursor
   <nul set /p "=%%E[?25l"
)

for /F "delims==" %%f in ('set') do if /i not "%%f"=="cls" if /i not "%%f"=="col" if /i not "%%f"=="Path" if not %%f==SystemRoot if not %%f==TMP set "%%f="

rem ALT+219
set "P=█ "
set /a n=0

set "c1=((( ( ((((15625*(4054-%%Y*128-%%X)) %% 2000000)/10000*(2048000000/(4054-%%Y*128-%%X)*2)/100)/100)-((2048000000/(4054-%%Y*128-%%X)*2)/100) + (%%N*10000/64) )/3000 ^ (2048000000/(4054-%%Y*128-%%X)*2)/100000) ) & 1)*10000000"
set "c2=((( ( ((((15625*(4053-%%Y*128-%%X)) %% 2000000)/10000*(2048000000/(4053-%%Y*128-%%X)*2)/100)/100)-((2048000000/(4053-%%Y*128-%%X)*2)/100) + (%%N*10000/64) )/3000 ^ (2048000000/(4053-%%Y*128-%%X)*2)/100000) ) & 1)*1000000" 
set "c3=((( ( ((((15625*(4052-%%Y*128-%%X)) %% 2000000)/10000*(2048000000/(4052-%%Y*128-%%X)*2)/100)/100)-((2048000000/(4052-%%Y*128-%%X)*2)/100) + (%%N*10000/64) )/3000 ^ (2048000000/(4052-%%Y*128-%%X)*2)/100000) ) & 1)*100000"
set "c4=((( ( ((((15625*(4051-%%Y*128-%%X)) %% 2000000)/10000*(2048000000/(4051-%%Y*128-%%X)*2)/100)/100)-((2048000000/(4051-%%Y*128-%%X)*2)/100) + (%%N*10000/64) )/3000 ^ (2048000000/(4051-%%Y*128-%%X)*2)/100000) ) & 1)*10000"
set "c5=((( ( ((((15625*(4050-%%Y*128-%%X)) %% 2000000)/10000*(2048000000/(4050-%%Y*128-%%X)*2)/100)/100)-((2048000000/(4050-%%Y*128-%%X)*2)/100) + (%%N*10000/64) )/3000 ^ (2048000000/(4050-%%Y*128-%%X)*2)/100000) ) & 1)*1000"
set "c6=((( ( ((((15625*(4049-%%Y*128-%%X)) %% 2000000)/10000*(2048000000/(4049-%%Y*128-%%X)*2)/100)/100)-((2048000000/(4049-%%Y*128-%%X)*2)/100) + (%%N*10000/64) )/3000 ^ (2048000000/(4049-%%Y*128-%%X)*2)/100000) ) & 1)*100"
set "c7=((( ( ((((15625*(4048-%%Y*128-%%X)) %% 2000000)/10000*(2048000000/(4048-%%Y*128-%%X)*2)/100)/100)-((2048000000/(4048-%%Y*128-%%X)*2)/100) + (%%N*10000/64) )/3000 ^ (2048000000/(4048-%%Y*128-%%X)*2)/100000) ) & 1)*10"
set "c8=((( ( ((((15625*(4047-%%Y*128-%%X)) %% 2000000)/10000*(2048000000/(4047-%%Y*128-%%X)*2)/100)/100)-((2048000000/(4047-%%Y*128-%%X)*2)/100) + (%%N*10000/64) )/3000 ^ (2048000000/(4047-%%Y*128-%%X)*2)/100000) ) & 1)"

rem 6.90fps, 8.55fps, 9.30fps, 9.74fps, 10,25fps

(
set cls=
set col=
set c1=
set c2=
set c3=
set c4=
set c5=
set c6=
set c7=
set c8=

for /L %%N in (-65,-1,-10000) do (


  %cls% 
  For /L %%Y in (6,-1,-33) do (
	set St=
	For /L %%X in (-20,8,52) do (

		set /a "a=100000000 + %c1% + %c2% + %c3% + %c4% + %c5% + %c6% + %c7% + %c8%"

		for /f "tokens=1-8" %%i in ("!a:~1,1! !a:~2,1! !a:~3,1! !a:~4,1! !a:~5,1! !a:~6,1! !a:~7,1! !a:~8,1!") do set St=!St!!P:~%%~i,1!!P:~%%~j,1!!P:~%%~k,1!!P:~%%~l,1!!P:~%%~m,1!!P:~%%~n,1!!P:~%%~o,1!!P:~%%~p,1!

	)
	
	set /a "H=H=(%%Y+33)*(2560/28)/10, V=(n+10)*40"

	if !V! gtr 10000 set V=10000

	set /a "mm = (h*10000/60 %% 20000) - 10000, mm=(mm>>31|1)*mm, C = V, X = C *(10000 - mm)/10000, C=C*255/10000, X=X*255/10000"

	if !H! lss 60 (set /a R=C, G=X, B=0) else (
   		if !H! lss 120 (set /a R=X, G=C, B=0) else (
      			if !H! lss 180 (set /a R=0, G=C, B=X) else (
         			if !H! lss 240 (set /a R=0, G=X, B=C) else (
            				if !H! lss 300 (set /a R=X, G=0, B=C) else (
               					if !H! lss 360 (set /a R=C, G=0, B=X) else (echo ERROR!)
            				)
         			)
      			)
   		)
	)

	echo( %col%!R!;!G!;!B!m!St!
  )

  set /a n+=1
 
  for /F "tokens=1-8 delims=:.," %%a in ("%time: =0%:!time: =0!") do set /a "a=(((1%%e-1%%a)*60)+1%%f-1%%b)*6000+1%%g%%h-1%%c%%d, a+=(a>>31) & 8640000, FPS=10000*n/a"
  title FPS=!FPS:~0,-2!.!FPS:~-2! &set "a="& set "FPS="
  
)
)

pause
goto :eof

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:init_transparent
setlocal DisableDelayedExpansion
:: Define the transparency of the console window.
:: Usage:
:: %transparent% percentage
::   percentage  0 (opaque) to 100 (limpid)
set transparent=for %%- in (1 2) do if %%-==2 (for /f %%. in ("^^!arg^^! x") do ^
%=% powershell -nop -ep Bypass -c ^"^
%===% $w=Add-Type -Name WAPI -PassThru -MemberDefinition '^
%=====% [DllImport(\"user32.dll\")]^
%=======% public static extern void SetWindowLong(IntPtr wnd, int idx, int newLong);^
%=====% [DllImport(\"user32.dll\")]^
%=======% public static extern void SetWindowLongPtr(IntPtr wnd, int idx, Int64 newLong);^
%=====% [DllImport(\"user32.dll\")]^
%=======% public static extern int GetWindowLong(IntPtr wnd, int idx);^
%=====% [DllImport(\"user32.dll\")]^
%=======% public static extern Int64 GetWindowLongPtr(IntPtr wnd, int idx);^
%=====% [DllImport(\"user32.dll\")]^
%=======% public static extern int SetLayeredWindowAttributes(IntPtr wnd, int color, byte alpha, int flags);^
%=====% [DllImport(\"kernel32.dll\")]^
%=======% public static extern IntPtr GetConsoleWindow();^
%===% ';^
%===% $val=0;^
%===% if (-not [Int32]::TryParse(\"%%~.\", [ref]$val) -or $val -lt 0 -or $val -gt 100) {exit 1;}^
%===% $GWL_EXSTYLE=-20;^
%===% $WS_EX_LAYERED=0x80000;^
%===% $wnd=$w::GetConsoleWindow();^
%===% if ([IntPtr]::Size -eq 4) { %= Win x86 =%^
%=====% $w::SetWindowLong($wnd, $GWL_EXSTYLE, $w::GetWindowLong($wnd, $GWL_EXSTYLE) -bOr $WS_EX_LAYERED);^
%===% } else { %= Win x64 =%^
%=====% $w::SetWindowLongPtr($wnd, $GWL_EXSTYLE, $w::GetWindowLongPtr($wnd, $GWL_EXSTYLE) -bOr [Int64]$WS_EX_LAYERED);^
%===% }^
%===% $LWA_ALPHA=2;^
%===% exit ($w::SetLayeredWindowAttributes($wnd, 0, [byte](2.55 * (100 - $val) + 0.5), $LWA_ALPHA) -eq 0);^
%=% ^" ^&endlocal) else setlocal EnableDelayedExpansion ^&set arg=

endlocal &set "transparent=%transparent%"
if !!# neq # set "transparent=%transparent:^^=%"
exit /b
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:init_setfont
:: - BRIEF -
::  Get or set the console font size and font name.
:: - SYNTAX -
::  %setfont% [fontSize [fontName]]
::    fontSize   Size of the font. (Can be 0 to preserve the size.)
::    fontName   Name of the font. (Can be omitted to preserve the name.)
:: - EXAMPLES -
::  Output the current console font size and font name:
::    %setfont%
::  Set the console font size to 14 and the font name to Lucida Console:
::    %setfont% 14 Lucida Console
setlocal DisableDelayedExpansion
set setfont=for /l %%# in (1 1 2) do if %%#==2 (^
%=% for /f "tokens=1,2*" %%- in ("? ^^!arg^^!") do endlocal^&powershell.exe -nop -ep Bypass -c ^"Add-Type '^
%===% using System;^
%===% using System.Runtime.InteropServices;^
%===% [StructLayout(LayoutKind.Sequential,CharSet=CharSet.Unicode)] public struct FontInfo{^
%=====% public int objSize;^
%=====% public int nFont;^
%=====% public short fontSizeX;^
%=====% public short fontSizeY;^
%=====% public int fontFamily;^
%=====% public int fontWeight;^
%=====% [MarshalAs(UnmanagedType.ByValTStr,SizeConst=32)] public string faceName;}^
%===% public class WApi{^
%=====% [DllImport(\"kernel32.dll\")] public static extern IntPtr CreateFile(string name,int acc,int share,IntPtr sec,int how,int flags,IntPtr tmplt);^
%=====% [DllImport(\"kernel32.dll\")] public static extern void GetCurrentConsoleFontEx(IntPtr hOut,int maxWnd,ref FontInfo info);^
%=====% [DllImport(\"kernel32.dll\")] public static extern void SetCurrentConsoleFontEx(IntPtr hOut,int maxWnd,ref FontInfo info);^
%=====% [DllImport(\"kernel32.dll\")] public static extern void CloseHandle(IntPtr handle);}';^
%=% $hOut=[WApi]::CreateFile('CONOUT$',-1073741824,2,[IntPtr]::Zero,3,0,[IntPtr]::Zero);^
%=% $fInf=New-Object FontInfo;^
%=% $fInf.objSize=84;^
%=% [WApi]::GetCurrentConsoleFontEx($hOut,0,[ref]$fInf);^
%=% If('%%~.'){^
%===% $fInf.nFont=0; $fInf.fontSizeX=0; $fInf.fontFamily=0; $fInf.fontWeight=0;^
%===% If([Int16]'%%~.' -gt 0){$fInf.fontSizeX=[Int16]'%%~.';$fInf.fontSizeY=[Int16]'%%~.'}^
%===% If('%%~/'){$fInf.faceName='%%~/'}^
%===% [WApi]::SetCurrentConsoleFontEx($hOut,0,[ref]$fInf);}^
%=% Else{(''+$fInf.fontSizeY+' '+$fInf.faceName)}^
%=% [WApi]::CloseHandle($hOut);^") else setlocal EnableDelayedExpansion^&set arg=
endlocal &set "setfont=%setfont%"
if !!# neq # set "setfont=%setfont:^^!=!%"
goto :eof
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:GetInfo

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: The %ConsoleInfo% macro collects properties of the console window and its environment.
:: It prints a string in the following format to StdOut:
::   cml=N,cmt=N,cmr=N,cmb=N,cwx=N,cwy=N,cvx=N,cvy=N,cfx=N,cfy=N,chx=N,chy=N,ccx=N,ccy=N,clx=N,cly=N
:: With:
::   N    different integral values of the below properties
::   cml  left dots boundary of the monitor's workspace
::   cmt  top dots boundary of the monitor's workspace
::   cmr  right dots boundary of the monitor's workspace
::   cmb  bottom dots boundary of the monitor's workspace
::   cwx  current width of the console window as number of dots
::   cwy  current height of the console window as number of dots
::   cvx  current width of the console viewport as number of dots
::   cvy  current height of the console viewport as number of dots
::   cfx  console font width as number of pixels
::   cfy  console font height as number of pixels
::   chx  approximated console charcell width as number of dots
::   chy  approximated console charcell height as number of dots
::   ccx  current width of the console client window as number of character cells
::   ccy  current height of the console client window as number of character cells
::   clx  largest width of the console client window as number of character cells
::   cly  largest height of the console client window as number of character cells
:: To define variables %cfx% .. %cly%, execute the macro in a FOR /F loop like that:
::   FOR /F %%I IN ('%ConsoleInfo%') DO SET /A "%%I"
set ConsoleInfo=^
powershell -nop -ep Bypass -c ^"^
%=% $w=Add-Type -Name WAPI -PassThru -MemberDefinition '^
%===% [DllImport(\"user32.dll\"^)]^
%=====% public static extern void SetProcessDPIAware(^);^
%===% [DllImport(\"shcore.dll\"^)]^
%=====% public static extern void SetProcessDpiAwareness(int value^);^
%===% [DllImport(\"kernel32.dll\"^)]^
%=====% public static extern IntPtr GetConsoleWindow(^);^
%===% [DllImport(\"user32.dll\"^)]^
%=====% public static extern void GetWindowRect(IntPtr hwnd, int[] rect^);^
%===% [DllImport(\"user32.dll\"^)]^
%=====% public static extern void GetClientRect(IntPtr hwnd, int[] rect^);^
%===% [DllImport(\"user32.dll\"^)]^
%=====% public static extern void GetMonitorInfoW(IntPtr hMonitor, int[] lpmi^);^
%===% [DllImport(\"user32.dll\"^)]^
%=====% public static extern IntPtr MonitorFromWindow(IntPtr hwnd, int dwFlags^);^
%===% [DllImport(\"kernel32.dll\"^)]^
%=====% public static extern IntPtr CreateFile(string name, int acc, int share, IntPtr sec, int how, int flags, IntPtr tmplt^);^
%===% [DllImport(\"kernel32.dll\"^)]^
%=====% public static extern void GetCurrentConsoleFont(IntPtr hOut, int isMax, int[] info^);^
%===% [DllImport(\"kernel32.dll\"^)]^
%=====% public static extern void CloseHandle(IntPtr h^);^
%=% ';^
 ^
%=% $PROCESS_PER_MONITOR_DPI_AWARE=2;^
%=% try {$w::SetProcessDpiAwareness($PROCESS_PER_MONITOR_DPI_AWARE^)} catch {$w::SetProcessDPIAware(^)}^
 ^
%=% $hwnd=$w::GetConsoleWindow(^);^
%=   The $moninf array is a replacement for the MONITORINFO structure. The elements at index         =% ^
%=   5, 6, 7, and 8 represent left, top, right, and bottom boundaries of the monitor's work space.   =% ^
%=% $moninf=[int[]]::new(10^);^
%=% $moninf[0]=40;^
%=% $MONITOR_DEFAULTTONEAREST=2;^
%=% $w::GetMonitorInfoW($w::MonitorFromWindow($hwnd, $MONITOR_DEFAULTTONEAREST^), $moninf^);^
 ^
%=   The $wrect array is a replacement for the RECT structure. The elements at index    =% ^
%=   0, 1, 2, and 3 represent left, top, right, and bottom boundaries of the window.   =% ^
%=% $wrect=[int[]]::new(4^);^
%=% $w::GetWindowRect($hwnd, $wrect^);^
 ^
%=   The $crect array is a replacement for the RECT structure. The elements at index          =% ^
%=   0, 1, 2, and 3 represent left, top, right, and bottom boundaries of the client window.   =% ^
%=% $crect=[int[]]::new(4^);^
%=% $w::GetClientRect($hwnd, $crect^);^
 ^
%=% $NIL=[IntPtr]::Zero;^
%=% $GENERIC_READ=0x80000000;^
%=% $GENERIC_WRITE=0x40000000;^
%=% $FILE_SHARE_WRITE=0x00000002;^
%=% $OPEN_EXISTING=3;^
%=   Because the StdOut stream is redirected to a pipe behind the scenes of a FOR /F loop,   =% ^
%=   we need to explicitly open a handle to the console output device (alias 'CONOUT$').     =% ^
%=% $out=$w::CreateFile('CONOUT$', $GENERIC_READ -bor $GENERIC_WRITE, $FILE_SHARE_WRITE, $NIL, $OPEN_EXISTING, 0, $NIL^);^
%=   The $fntinf array is a replacement for the CONSOLE_FONT_INFO structure. The 16 low order bits of the   =% ^
%=   second element represent the font width, while its 16 high order bits represent the font height.       =% ^
%=% $fntinf=[int[]]::new(2^);^
%=% $w::GetCurrentConsoleFont($out, 0, $fntinf^);^
%=% $w::CloseHandle($out^);^
 ^
%=% $raw=$host.UI.RawUI;^
%=% $cur=$raw.WindowSize;^
%=% $lrg=$raw.MaxPhysicalWindowSize;^
 ^
%=% 'cml={0},cmt={1},cmr={2},cmb={3},cwx={4},cwy={5},cvx={6},cvy={7},cfx={8},cfy={9},chx={10},chy={11},ccx={12},ccy={13},clx={14},cly={15}' -f^
%===% $moninf[5], $moninf[6], $moninf[7], $moninf[8],^
%===% ($wrect[2]-$wrect[0]^), ($wrect[3]-$wrect[1]^),^
%===% ($crect[2]-$crect[0]^), ($crect[3]-$crect[1]^),^
%===% ($fntinf[1] -band 0xFFFF^), ($fntinf[1] -shr 16^),^
%===% [math]::Round(($crect[2]-$crect[0]^)/$cur.Width^), [math]::Round(($crect[3]-$crect[1]^)/$cur.Height^),^
%===% $cur.Width, $cur.Height,^
%===% $lrg.Width, $lrg.Height;^
 ^"
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: %MoveWindow% X Y
::   X  left side of the window
::   Y  top of the window
set MoveWindow=for %%i in (1 2) do if %%i==2 (^
%=% for /f "tokens=1*" %%j in ("^!arg^!") do (powershell.exe -nop -ep Bypass -Command ^"^
%===% try {$w=Add-Type -Name WAPI -PassThru -MemberDefinition '^
%=====% [DllImport(\"user32.dll\"^)]^
%=======% public static extern void SetProcessDPIAware(^);^
%=====% [DllImport(\"shcore.dll\"^)]^
%=======% public static extern void SetProcessDpiAwareness(int value^);^
%=====% [DllImport(\"user32.dll\"^)]^
%=======% public static extern int SetWindowPos(IntPtr hWnd^, IntPtr hWndInsertAfter^, int X^, int Y^, int cx^, int cy^, uint uFlags^);^
%=====% [DllImport(\"kernel32.dll\"^)]^
%=======% public static extern IntPtr GetConsoleWindow(^);^
%===% ';^
%===% $PROCESS_PER_MONITOR_DPI_AWARE=2;^
%===% try {$w::SetProcessDpiAwareness($PROCESS_PER_MONITOR_DPI_AWARE^)} catch {$w::SetProcessDPIAware(^)}^
%===% $x=0; $y=0;^
%===% if (([Int32]::TryParse(\"%%~j\"^, [ref]$x^) -eq $false^) -or ([Int32]::TryParse(\"%%~k\"^, [ref]$y^) -eq $false^)^){^
%=====% [Console]::Error.WriteLine(\"Syntax Error`r`n Usage:`r`n%%MoveWindow%% X Y`r`n   X  left side of the window`r`n   Y  top of the window\"^);^
%=====% exit 1;^
%===% }^
%===% exit [int]($w::SetWindowPos($w::GetConsoleWindow(^)^, [IntPtr]::Zero^, $x^, $y^, 0^, 0^, 5^) -eq 0^)} catch {exit 1}^"^
%=% )^
%=% ^&endlocal^
) else setlocal EnableDelayedExpansion ^&set arg=
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::
for /f %%i in ('%ConsoleInfo%') do set /a "%%i"
goto :eof
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:AndCenter

:: center the window
set /a "newX=cml+(cmr-cml)/2-cwx/2, newY=cmt+(cmb-cmt)/2-cwy/2"
%MoveWindow% %newX% %newY%

rem title Move to %newX%,%newY%

goto :eof
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:init_fade
setlocal DisableDelayedExpansion
:: fade the window in or out
:: Usage:
:: %fade% start step end delay
::   start  percentage of transparency to begin with
::   step   number of percents the start value is changed in each iteration
::   end    percentage of transparency to end with
::   delay  milliseconds to wait between each step
set fade=for %%# in (1 2) do if %%#==2 (for /f "tokens=1-4" %%- in ("^^!args^^! x x x x") do ^
%=% powershell -nop -ep Bypass -c ^"^
%===% $w=Add-Type -Name WAPI -PassThru -MemberDefinition '^
%=====% [DllImport(\"user32.dll\")]^
%=======% public static extern void SetWindowLong(IntPtr wnd, int idx, int newLong);^
%=====% [DllImport(\"user32.dll\")]^
%=======% public static extern void SetWindowLongPtr(IntPtr wnd, int idx, Int64 newLong);^
%=====% [DllImport(\"user32.dll\")]^
%=======% public static extern int GetWindowLong(IntPtr wnd, int idx);^
%=====% [DllImport(\"user32.dll\")]^
%=======% public static extern Int64 GetWindowLongPtr(IntPtr wnd, int idx);^
%=====% [DllImport(\"user32.dll\")]^
%=======% public static extern void SetLayeredWindowAttributes(IntPtr wnd, int color, byte alpha, int flags);^
%=====% [DllImport(\"kernel32.dll\")]^
%=======% public static extern IntPtr GetConsoleWindow();^
%===% ';^
%===% $b=0; $s=0; $e=0; $d=0;^
%===% if (-not [Int32]::TryParse(\"%%~-\", [ref]$b) -or^
%=====% -not [Int32]::TryParse(\"%%~.\", [ref]$s) -or^
%=====% -not [Int32]::TryParse(\"%%~/\", [ref]$e) -or^
%=====% -not [Int32]::TryParse(\"%%~0\", [ref]$d) -or^
%=====% $b -lt 0 -or $b -gt 100 -or^
%=====% $e -lt 0 -or $e -gt 100 -or^
%=====% $d -lt 0^
%===% ) {exit 1;}^
%===% $GWL_EXSTYLE=-20;^
%===% $WS_EX_LAYERED=0x80000;^
%===% $wnd=$w::GetConsoleWindow();^
%===% if ([IntPtr]::Size -eq 4) { %= Win x86 =%^
%=====% $w::SetWindowLong($wnd, $GWL_EXSTYLE, $w::GetWindowLong($wnd, $GWL_EXSTYLE) -bOr $WS_EX_LAYERED);^
%===% } else { %= Win x64 =%^
%=====% $w::SetWindowLongPtr($wnd, $GWL_EXSTYLE, $w::GetWindowLongPtr($wnd, $GWL_EXSTYLE) -bOr [Int64]$WS_EX_LAYERED);^
%===% }^
%===% $LWA_ALPHA=2;^
%===% if (($b -lt $e) -and ($s -gt 0)) {^
%=====% for ($val=$b; $val -lt $e; $val=$val + $s) {^
%=======% $w::SetLayeredWindowAttributes($wnd, 0, [byte](2.55 * (100 - $val) + 0.5), $LWA_ALPHA);^
%=======% [Threading.Thread]::Sleep($d);^
%=====% }^
%===% } elseif (($b -gt $e) -and ($s -lt 0)) {^
%=====% for ($val=$b; $val -gt $e; $val=$val + $s) {^
%=======% $w::SetLayeredWindowAttributes($wnd, 0, [byte](2.55 * (100 - $val) + 0.5), $LWA_ALPHA);^
%=======% [Threading.Thread]::Sleep($d);^
%=====% }^
%===% } else {exit 1;}^
%===% $w::SetLayeredWindowAttributes($wnd, 0, [byte](2.55 * (100 - $e) + 0.5), $LWA_ALPHA);^
%=% ^" ^&endlocal) else setlocal EnableDelayedExpansion ^&set args=

endlocal &set "fade=%fade%"
if !!# neq # set "fade=%fade:^^=%"
exit /b
EDIT:

I post here a work I did with Honguito98 on fixed point math with a part that uses the karatsuba method for multiplication

Code: Select all

@Echo off
	Setlocal EnableExtensions
	Call :Flush
	Set "Game=%~0"
	Set Err=-1
	Set LF=^


	::
	Set Macros=Calc;Kar;
	For %%# in (%Macros%) Do (
		Call :AutoMacro %%#
	)
	Setlocal EnabledelayedExpansion
		For %%# in (%Macros%) Do (
		Set ^"%%#=!%%#:[LF]=^%LF%%LF%!"
	)
	Set Macros=

goto :sub
Set/p Sum1=int1:
Set/p Sum2=int2:
:Main
:: Acc = Accuracy
:: .0 = decimals .00 = cents .000 = milli
:: Test: sum -> 2 + 2.5 = 4.5
:: Set sum1=2.5
:: Set sum2=2

:: Real proccessment

:: Set sum1=2.5
:: Set sum2=2.0
:sub

Rem Some functional Tests:

set "DBG=" & rem debug var

%calc% 999.99 * 200.99
%kar% 999.99 * 200.99

%calc% 0 + 0
%calc% . + 1
%calc% . + .
%calc% 1 + 0
%calc% .03 / .5
%calc% 2.2 + 2.2
%calc% 8.888 + 0.82000
%calc% 120.52 * 2.21
%kar% 120.52 * 2.21
%calc% 99.5 + 100.012
%calc% 14797.109 - 15213.132

%calc% 25586.17 * 13697.27
%kar% 25586.17 * 13697.27
%calc% 3151.27 * 567.60
%kar% 3151.27 * 567.60

%calc% !random!.!Random:~0,3! + !random!.!Random:~0,3!
%calc% !random!.!Random:~0,3! - !random!.!Random:~0,3!
%calc% !random!.!Random:~0,2! * !random!.!Random:~0,2!
%kar% !random!.!Random:~0,2! * !random!.!Random:~0,2!
%calc% !random!.!Random:~0,3! / !random!.!Random:~0,3!

%calc% 999.99 * 999.99
%kar% 999.99 * 999.99
%calc% 13 * 14.00
%kar% 13 * 14.00
%calc% 32768.99 * 32768.99
%kar% 32768.99 * 32768.99

%kar% !random!.!Random:~0,2! * !random!.!Random:~0,2!
%kar% 992.95 * 100.85
%kar% 992.95 * 100.05
%kar% 25 * 1000.05
%kar% 16789.2 * 3.5
%kar% 5.05 * .05
%kar% .03 * .5
%kar% 09 * 08080
%kar% 8.08 * .08
%kar% 9.09 * .09

pause

Rem Performance Tests:

set "DBG=rem "

set N_CYCLES=300
set t0=!time!

for /l %%a in (1,1,!N_CYCLES!) Do (
%calc% !random!.!Random:~0,3! + !random!.!Random:~0,3!
%calc% 992.95 + 100.85
%calc% 992.95 - 100.05
%kar% 25 * 1000.05
%calc% 1.2 / 3.5
%calc% 5.05 + .05
%calc% .03 / .5
%calc% 09 / 08
%calc% 8.08 + .08
%calc% 9.09 + .09
)

for /F "tokens=1-8 delims=:.," %%a in ("%t0: =0%:%time: =0%") do set /a "a=(((1%%e-1%%a)*60)+1%%f-1%%b)*6000+1%%g%%h-1%%c%%d, a+=(a>>31) & 8640000, FLOPS=%N_CYCLES%*10*1000/a"

echo Elapsed:%a% centiseconds - Flops:%FLOPS:~0,-1%.%FLOPS:~-1%

Rem Test Karatsuba only

set t0=!time!

for /l %%a in (1,1,!N_CYCLES!) Do (
%kar% !random!.!Random:~0,2! * !random!.!Random:~0,2!
%kar% 992.95 * 100.85
%kar% 992.95 * 100.05
%kar% 25 * 1000.05
%kar% 16789.2 * 3.5
%kar% 5.05 * .05
%kar% .03 * .5
%kar% 09 * 08080
%kar% 8.08 * .08
%kar% 9.09 * .09
)

for /F "tokens=1-8 delims=:.," %%a in ("%t0: =0%:%time: =0%") do set /a "a=(((1%%e-1%%a)*60)+1%%f-1%%b)*6000+1%%g%%h-1%%c%%d, a+=(a>>31) & 8640000, FLOPS=%N_CYCLES%*10*1000/a"

echo Elapsed:%a% centiseconds - Flops:%FLOPS:~0,-1%.%FLOPS:~-1% [KAR.]

Rem With BURST MODE

::BURST MODE ON
(setlocal & for /F "Tokens=1 delims==" %%v in ('set') do set "%%v="

set "DBG=rem "

set t0=!time!

for /l %%a in (1,1,%N_CYCLES%) Do (
%calc% !random!.!Random:~0,3! + !random!.!Random:~0,3!
%calc% 992.95 + 100.85
%calc% 992.95 - 100.05
%kar% 25 * 1000.05
%calc% 1.2 / 3.5
%calc% 5.05 + .05
%calc% .03 / .5
%calc% 09 / 08
%calc% 8.08 + .08
%calc% 9.09 + .09
)

rem set

for /F "tokens=1-8 delims=:.," %%a in ("!t0: =0!:!time: =0!") do set /a "a=(((1%%e-1%%a)*60)+1%%f-1%%b)*6000+1%%g%%h-1%%c%%d, a+=(a>>31) & 8640000, FLOPS=%N_CYCLES%*10*1000/a"

echo Elapsed:!a! centiseconds - Flops:!FLOPS:~0,-1!.!FLOPS:~-1! [BURST MODE]

endlocal)
::BURST MODE OFF

pause
exit /b

<Function=Calc|2>
set Sum1=%1
set Mode=%2
set Sum2=%3
set prec=2
For %P in (!prec!) do (

    For %T in (1;2) Do (

	for /f tokens^=1-4^ delims^=+^"^  %f in ("!Sum%T!") do set Sum%T=0000000000%~f%~g%~h%~i

	set i%T=!Sum%T:*.=!0!Sum%T:~0,%P!
        For %I in ("!Sum%T:*.=!") do if not "%~I" == "!Sum%T!" set i%T=!Sum%T:.%~I=!!i%T:~0,1!!i%T:~1,%P!
	
	for /f "tokens=* delims=0" %z in ("!i%T!") do set /a "i%T=(%z+5)/10"

    )
	set Div.acc=1!Sum1:~0,%P!

	if "!Mode!" equ "/" (
		set /a Total=!i1!*!Div.acc!/!i2!
	) else (
	 if "!Mode!" equ "*" (
		set /a Total=!i1!*!i2!/!Div.acc!
	 ) else set /a Total=!i1!!Mode!!i2!
	)
		
	If !total! geq 0 (
		set /a "Int=Total/Div.acc, Float=Total % Div.acc"
	) else  set /a "Int=Total/Div.acc, Float=-(Total % Div.acc)"

	set Float=!Sum1:~0,%P!!Float!
	set Float=!Float:~-%P!
)
!DBG!echo;%1 %2 %3 : !Int!.!Float!
</Function=Calc>

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::
::  P=precision , number of digit after decimal point
::  DA=Div.acc  , contain a number that is 100 for prec=2 ora 1000 for prec=3 etc.
::		  ex division accurancy.
::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
<Function=Kar|2>
set Sum1=%1
set Mode=%2
set Sum2=%3
set P=3
For %P in (!P!) do (

    For %T in (1;2) Do (

	for /f tokens^=1-4^ delims^=+^"^  %f in ("!Sum%T!") do set Sum%T=0000000000%~f%~g%~h%~i

	set i%T=!Sum%T:*.=!0!Sum%T:~0,%P!

        For %I in ("!Sum%T:*.=!") do if not "%~I" == "!Sum%T!" set i%T=!Sum%T:.%~I=!!i%T:~0,1!!i%T:~1,%P!

	for /f "tokens=* delims=0" %z in ("!i%T!") do set /a "i%T=(%z+5)/10"

    )

    set DA=1!Sum1:~0,%P!

    set /a "a=(!i1:~0,-4!+0), b=1!i1:~-4!-(11!i1:~-4!-1!i1:~-4!)/10, c=(!i2:~0,-4!+0), d=1!i2:~-4!-(11!i2:~-4!-1!i2:~-4!)/10, KFloat=(10000/DA*((a+b)*(c+d)-a*c-b*d)+b*d/DA) % DA, KInt=100000000/DA/DA*a*c+10000/DA/DA*((a+b)*(c+d)-a*c-b*d)+b*d/DA/DA"
    If !KInt! lss 0 set /a KFloat=-KFloat
    set KFloat=!Sum1:~0,%P!!KFloat!
    set KFloat=!KFloat:~-%P!
)
!DBG!echo;%1 %2 %3 : !KInt!.!KFloat!			[KAR.]
</Function=Kar>

:Flush
	For /f "Tokens=1 Delims==" %%a in ('Set') Do (
	If /i "%%a" Neq "Comspec" (
	If /i "%%a" Neq "Tmp" (
	If /i "%%a" Neq "Userprofile" (
	IF /i "%%a" Neq "SystemRoot" (
	Set "%%a="))))
	)
	Set "Path=%comspec:~0,-8%;%SystemRoot%;%Comspec:~0,-8%\Wbem"
	Goto :Eof

:: -> AutoMacro helps you to set variables with functions then be ready to use <- ::

:AutoMacro
	Set "Start="
	set "Tm=%Tmp%\Tmp.dat"
	Set "End="
	Set "%~1="
	For /F "Tokens=1,3 Delims=>|:" %%a in ('Findstr /N /B "</*Function=%~1" "%Game%"') Do (
		If Not Defined Start (
			Set Start=%%a
			Set Type=%%b
		) Else (
			Set End=%%a
		)
	)
	If %Type% Equ 1 (
		<Nul Set/p=([LF]>>"%Tm%"
	)
	If %Type% Equ 2 (
		<Nul Set/p=For %%` in (0;1^) Do If %%` Equ 1 (For /F "Tokens=1-9" %%1 in ("!Argv!"^) Do ([LF]>>"%Tm%"
	)
	Set/a Start+=2
	For /F "Tokens=1* Skip=%Start% Delims=[]" %%a in ('Find /N /V "" "%Game%"') do (
		If %%a Geq %End% Goto :End
		<Nul Set/p=%%b[LF]>>"%Tm%"
	)
:End
	If %Type% Equ 1 (
		<Nul Set/p=^)>>"%Tm%"
	)
	If %Type% Equ 2 (
		<Nul Set/p=^)^) Else Set Argv=>>"%Tm%"
	)

	(
	For /F "Delims=" %%a in ('Type "%Tm%"') Do Set "%~1=%%a"
	) >Nul 2>&1 || Goto :ErrMacro
	Del "%Tm%">Nul 2>&1
	rem Changed: add set Type=

	Set Tm=& Set Start=& Set End=&set Type=
	Goto :Eof
:ErrMacro
	Set/a Start-=2
	For %%a in (
	"Macro Setup Failure from line:"
	"	Start: '%Start%'"
	"	End:   '%End%'"
	"	Expected '%~1' macro with size less than 8KB {8010B} (8100 Letters)"
	) Do Echo;%%~a
	Pause>Nul
	Exit


exit/B
.
Last edited by einstein1969 on 18 Oct 2022 15:42, edited 1 time in total.

einstein1969
Expert
Posts: 941
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: Dos Batch Math Library

#62 Post by einstein1969 » 18 Oct 2022 07:29

@Aacini e others

I put links of your works in the first post. Could you put me here other links on the topic you have dealt with?

einstein1969
Expert
Posts: 941
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: Dos Batch Math Library

#63 Post by einstein1969 » 23 May 2023 01:56

I recently developed the atan(x) function with two decimal places after the decimal point. It's pretty accurate but I have a problem. In the calculation I had to set a division. ( 1/x ) or (10000000/x). Obviously when x=0 an exception is thrown and the value is not assigned. I wanted to know if it's possible to bypass the problem without using "if" or "||" code.

For the moment it is managed like this but if you have a better idea it would be nice.
Atan(x):

Code: Select all

@echo off
setlocal EnableDelayedExpansion

:: Define simple macros to support JavaScript within batch
set "beginJS=mshta "javascript:code(close(new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1).Write("
set "endJS=)));""

rem for imput use x*1000 example: 0.5=500 1=1000 1.73=1730  etc.
	
rem set "Atan(x)=( t=((((x>>31|1)*x)-1077)>>31)+1, s=x>>31|-x>>31&1, y=10000000/x, t*((s*90000-((y*100000+43205*y/2000*y/10000*y/5)/(((1000000000+7649*y/1000*y)+(584*y/50*y/10000*y/10000*y/10/2) )/100000) )*180*100/31416)/10)+(1-t)*((x*1000000+43205*x/100*x/1000*x)/(((1000000000+7649*x/10*x)+(584*x/10*x/100*x/1000*x/10))/100000)*180*100/314159) )"
set "Atan(x)=( t=((((x>>31|1)*x)-1077)>>31)+1, y=10000000/x, t*(((x>>31|-x>>31&1)*90000-((y*100000+43205*y/2000*y/10000*y/5)/(((1000000000+7649*y/1000*y)+(584*y/50*y/10000*y/10000*y/10/2) )/100000) )*180*100/31416)/10)+(1-t)*((x*1000000+43205*x/100*x/1000*x)/(((1000000000+7649*x/10*x)+(584*x/10*x/100*x/1000*x/10))/100000)*180*100/314159) )"

for %%V in (-100000,-10000,-1000,-500,0,1,2,3,4,5,6,10,20,30,100,200,300,500,700,800,925,1000,1070,1075,1076,1077,1080,1200,1730,2000,3000,4000,5000,10000,50000,100000,10000000,20000000) do (

:: FOR /F does not need pipe
	for /f "tokens=*" %%M in (
		'%beginJS% Math.atan(%%V/1000)*180/Math.PI %endJS%'
	) do set "atan=                      %%M"

:: Calculate Atan
	rem set "tan=%%V"
	rem if !tan! equ 0 (set "atan_int=0") else set /a "atan_int=%Atan(x):x=tan%"
	rem set /a "tan=%%V, atan_int=%Atan(x):x=tan%" 2>nul || set /a "atan_int=0"
	set /a "tan=%%V, atan_int=0, atan_int=%Atan(x):x=tan%" 2>nul

:: Stuff for nice output
	set "v=       %%V"
	for %%I in (1 2) do if "!atan_int:~0,-2!" equ "" set "atan_int=0!atan_int!"
	set "atan_int=      !atan_int:~0,-2!.!atan_int:~-2!"
	echo Atan(!v:~-8!^) = !atan_int:~-6! 	js-fp:!atan:~-22!
) 
pause

goto :eof

Aacini
Expert
Posts: 1885
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Dos Batch Math Library

#64 Post by Aacini » 23 May 2023 10:54

The method to avoid that error is the way you already are doing: before the possible zero division assign to the result variable the value you want if the error happens (and redirect the error message to NUL).

Your method/formula looks pretty good! 8) The only change I would do it is to rename the "tan" variable to "ang" (or "angle")... :wink:

I think at first that the 10000*y/10/2 part could be changed to 10000*y/5, but doing that cause errors in the angles 1077..4000

+1 :D

Antonio

einstein1969
Expert
Posts: 941
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: Dos Batch Math Library

#65 Post by einstein1969 » 28 May 2023 03:10

Hi Antonio,

I have found a method that use the max or min between +1/-1 and x

Code: Select all

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
@echo off
setlocal EnableDelayedExpansion

:: Define simple macros to support JavaScript within batch
set "beginJS=mshta "javascript:code(close(new ActiveXObject('Scripting.FileSystemObject').GetStandardStream(1).Write("
set "endJS=)));""

rem for imput use x*1000 example: 0.5=500 1=1000 1.73=1730  etc.

rem if x=0 return 1/-1 otherwise return x

set "Atan(x)=( t=((((x>>31|1)*x)-1077)>>31)+1, y=(x>>31)+1, y=10000000/(y*(x-((x-1)&((x-1)>>31)))+(1-y)*(x-((x+1)&((-1-x)>>31)))), t*(((x>>31|-x>>31&1)*90000-((y*100000+43205*y/2000*y/10000*y/5)/(((1000000000+7649*y/1000*y)+(584*y/50*y/10000*y/10000*y/10/2) )/100000) )*180*100/31416)/10)+(1-t)*((x*1000000+43205*x/100*x/1000*x)/(((1000000000+7649*x/10*x)+(584*x/10*x/100*x/1000*x/10))/100000)*180*100/314159) )"

for %%V in (-100000,-10000,-1000,-500,-1,0,1,2,3,4,5,6,10,20,30,100,200,300,500,700,800,925,1000,1070,1075,1076,1077,1080,1200,1730,2000,3000,4000,5000,10000,50000,100000,10000000,20000000) do (

:: FOR /F does not need pipe
	for /f "tokens=*" %%M in (
		'%beginJS% Math.atan(%%V/1000)*180/Math.PI %endJS%'
	) do set "atan=                      %%M"

:: Calculate Atan
	set /a "tan=%%V, atan_int=%Atan(x):x=tan%"

:: Stuff for nice output
	set "v=       %%V"
	for %%I in (1 2) do if "!atan_int:~0,-2!" equ "" set "atan_int=0!atan_int!"
	set "atan_int=      !atan_int:~0,-2!.!atan_int:~-2!"
	echo Atan(!v:~-8!^) = !atan_int:~-6! 	js-fp:!atan:~-22!
) 
pause

goto :eof
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
this piece of code

Code: Select all

y=(x>>31)+1, y=10000000/(y*(x-((x-1)&((x-1)>>31)))+(1-y)*(x-((x+1)&((-1-x)>>31))))
PS: I have update the first post with MIN and MAX function

IcarusLives
Posts: 161
Joined: 17 Jan 2016 23:55

Re: Dos Batch Math Library

#66 Post by IcarusLives » 31 May 2023 09:09

Here's a macro to CLAMP an integer between a low and high value.

Given a value x and upper and lower bounds a and b respectively, the clamp function clamp(x, a, b) restricts the value of x within the range [a,b] by returning the nearest value to x that lies within this range.

The clamp formula can be written as follows:

clamp(x, a, b) = max(a, min(b, x))

In this formula:

max(a, b) returns the maximum value between a and b.
min(a, b) returns the minimum value between a and b.

Therefore, by applying the max and min functions, the clamp formula ensures that x is restricted to the range [a, b]. If x is less than a, it will be set to a, and if x is greater than b, it will be set to b. Otherwise, x remains unchanged.

Code: Select all

@echo off & setlocal enableDelayedExpansion

rem predefine x, low, and high
set "clamp=(low - ((((low - (x - ((((high - x) >> 31) & 1) * (x - high)))) >> 31) & 1) * (low - (x - ((((high - x) >> 31) & 1) * (x - high))))))"

set "low=10"
set "high=20"

for /l %%i in (0,1,30) do (
    set "x=%%i"
    set /a "out=%clamp%"
    echo !out!
)


pause

Aacini
Expert
Posts: 1885
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Dos Batch Math Library

#67 Post by Aacini » 31 May 2023 20:25

The same, written in a slightly different (and simpler, I think) way:

Code: Select all

@echo off
setlocal EnableDelayedExpansion

set "clamp= (leq=((low-x)>>31)+1)*low  +  (geq=((x-high)>>31)+1)*high  +  ^^^!(leq+geq)*x "

set /A low=10, high=20

for /L %%i in (0,1,30) do (
    set /A "x=%%i, out=%clamp%"
    echo %%i- !out!
)
In this formula:

leq is 1 if x is leq than low or 0 otherwise, so the first term is low if x is leq low
geq is 1 if x is geq than high or 0 otherwise, so the second term is high if x is geq high
leq+geq is 1 if anyone of leq or geq is 1 but it is 0 if x is in range, so ^^^!(leq+geq) is 1 if x is in range, giving the same x

The three parts represents the three different values that the formula returns: low when x leq low, high when x geq high, and x when x is in range, so just add they!

Antonio

IcarusLives
Posts: 161
Joined: 17 Jan 2016 23:55

Re: Dos Batch Math Library

#68 Post by IcarusLives » 01 Jun 2023 04:15

Hey thanks, Aacini! The formula written this way makes much more sense!

einstein1969
Expert
Posts: 941
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: Dos Batch Math Library

#69 Post by einstein1969 » 09 Jun 2023 12:57

I'm working on creating the 4 main operations (+,-,/,*) for a number of about 40 digits. but it can be extended to a larger number. I chose this number because it is equivalent to a 128 bit system. This is not a finished work, but only a first approach. For now I have implemented +,-,* and I think they have already been covered elsewhere in this forum by others. I have to thank Aacini because he helped me indirectly in this work.

Code: Select all

@echo off
setlocal enabledelayedexpansion

mode 100,30

rem 2^127-1 = 170,141,183,460,469,231,731,687,303,715,884,105,727  = 39 digit

rem              1         2         3         4
rem     1234567890123456789012345678901234567890
rem op1=  12345678999955557777789654325775756567
rem op2=     88884444321646546796746546756897800
rem --------------------------------------------
rem       12434563444277204324586400872532654367 sum
rem       12256794555633911230992907779018858767 sub

rem 
set /a op1_9=6567, op1_8=7575, op1_7=3257, op1_6=9654, op1_5=7778, op1_4=5577, op1_3=9955, op1_2=7899, op1_1=3456, op1_0=12
set /a op2_9=7800, op2_8=5689, op2_7=5467, op2_6=6746, op2_5=4679, op2_4=6465, op2_3=4321, op2_2=8444, op2_1=888 , op2_0=0

echo op1=  12345678999955557777789654325775756567
echo op2=     88884444321646546796746546756897800
echo(

rem sum, c=carry, d=digit
set /a "c=0" & for /L %%# in (9,-1,0) do set /a "d=c+(op1_%%#+op2_%%#), sum_%%#=d %% 10000, c=d/10000"

set "print=" & (for /L %%# in (0,1,9) do set "print=!print!!sum_%%#!") & echo op1+op2=!print!

rem sub, b=borrow, d=digit
set /a "b=0" & for /L %%# in (9,-1,0) do ( 
	set /a "d=(op1_%%#-op2_%%#)-b"
	if !d! lss 0 (set /a "d+=10000, b=1, sub_%%#=d") else set /a "b=0, sub_%%#=d"
)
rem if borrow is 1 than op2>op1

set "print=" & (for /L %%# in (0,1,9) do set "print=!print!!sub_%%#!") & echo op1-op2=!print!

echo(

rem multiplication, non negative numbers

set "$strlen=FOR %%# in (1 2) DO if %%#==2 (set "$str=!$str:~1!FEDCBA9876543210FEDCBA9876543210FEDCBA9876543210222222222222222211111111111111110000000000000000" & set /a "$len=0x!$str:~0x5f,1!!$str:~0x2f,1!" ) else set $str="

rem set base
set radix=10000

set "u=64352342242"
set "v=42342656464564"

echo op1=64352342242
echo op2=42342656464564
echo(

rem u*v=2-7248-4912-0243-0562-7331-2488

rem %rem $strlen% !num1!
set /a "m=3, mm=m-1"
rem %rem $strlen% !num2!
set /a "n=4, nn=n-1"

set /a u_0=2242, u_1=5234, u_2=643, u_3=0, u_4=0, u_5=0, u_6=0, u_7=0, u_8=0, u_9=0
set /a v_0=4564, v_1=5646, v_2=3426, v_3=42, v_4=0, v_5=0, v_6=0, v_7=0, v_8=0, v_9=0

rem set /a w=m+n-1
set /a w_0=0, w_1=0, w_2=0, w_3=0, w_4=0, w_5=0, w_6=0

for /l %%J in (0,1,!nn!) do (
	set /a "k=0"
	for /l %%I in (0,1,!mm!) do (
		set /a "i=%%I+%%J"
		set /a "t=u_%%I * v_%%J + w_!i! + k, w_!i!=t %% radix, k=t/radix"
	)
	set /a "i=%%J+m"
	set /a "w_!i!=k"
)

set "print=" & (for /L %%# in (9,-1,0) do set "w=0000!w_%%#!" & set "print=!print!!w:~-4!") & echo op1*op2=!print!

pause
goto:eof

Post Reply