-
-
Notifications
You must be signed in to change notification settings - Fork 5
/
Script_Calc.cmd
449 lines (394 loc) · 12.8 KB
/
Script_Calc.cmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
@echo off
rem =====
rem For more information on ScriptTiger and more ScriptTiger scripts visit the following URL:
rem https://scripttiger.github.io/
rem Or visit the following URL for the latest information on this ScriptTiger script:
rem https://github.com/ScriptTiger/IP
rem =====
setlocal ENABLEDELAYEDEXPANSION
set bdat=%temp%\bits.dat
set label=%1
if not "%3"=="" goto !label:~1!
if "!label:~,1!"=="/" set external=1&shift&goto !label:~1!
rem The default operation of this script is to add two numbers
rem Subtraction is thus treated as addition by adding a positive with a negative
rem Script_Calc 1 1 results in 2
rem Script_Calc 1 -1 results in 0
:add
call :detect_sign "%1" sign1
call :detect_sign "%2" sign2
call :remove_sign "%1" string1
call :remove_sign "%2" string2
set digit4=0
set string3=
if "!sign1!"=="!sign2!" (
call :add_calc
) else (
call :subtract_calc
)
if "%3"=="" (
echo !string3!
) else (
set %3=!string3!
)
exit /b
rem Stacked bitwise function
rem Converts all numbers to hexidecimal first to keep bit integrity
rem Calculates 8 hexidecimal numbers at a time
rem Outputs in hexidecimal
:and
:or
:xor
call :dec2hex "%2" bitwise1
call :dec2hex "%3" bitwise2
set bitwise1=!bitwise1:~2!
set bitwise2=!bitwise2:~2!
set bitwise4=
:bin_loop
call :shift_right "!bitwise1!" bitwise1 oct1
call :shift_right "!bitwise2!" bitwise2 oct2
if "%1"=="/and" set /a bitwise3="0x!oct1!&0x!oct2!"
if "%1"=="/or" set /a bitwise3="0x!oct1!|0x!oct2!"
if "%1"=="/xor" set /a bitwise3="0x!oct1!^^0x!oct2!"
call :dec2hex !bitwise3! bitwise3
set bitwise4=!bitwise3:~2!!bitwise4!
if "!bitwise1!"=="" if "!bitwise2!"=="" (
call :zeros !bitwise4! bitwise4
echo 0x!bitwise4!
exit /b
)
goto bin_loop
rem Sign detection function to designate positive or negative
:detect_sign
set string=%~1
if "!string:~,1!"=="-" (set %2=-) else (set %2=+)
exit /b
rem Sign stripping function
:remove_sign
set string=%~1
if "!string:~,1!"=="-" (set %2=!string:~1!) else (set %2=!string!)
exit /b
rem Positive on positive and nagative on negative addition calculations
:add_calc
call :shift_right "!string1!" string1 oct1
call :shift_right "!string2!" string2 oct2
call :zeros !oct1! oct1
call :zeros !oct2! oct2
set /a oct3=100000000+!oct1!+!oct2!+!digit4!
set string3=!oct3:~-8!!string3!
if !oct3! geq 200000000 (set digit4=1) else (set digit4=0)
if "!string1!"=="" if "!string2!"=="" if "!digit4!"=="0" (
call :zeros !string3! string3
if "!sign1!"=="-" set string3=-!string3!
exit /b
)
goto add_calc
rem Positive on negative subtraction calculations
:subtract_calc
call :eval !string1! !string2! string
if "!string!"=="eq" (
set string3=0
exit /b
)
if "!string!"=="gtr" (
set sign=!sign1!
) else (
set sign=!sign2!
set string=!string1!
set string1=!string2!
set string2=!string!
)
:subtract_loop
call :shift_right "!string1!" string1 oct1
call :shift_right "!string2!" string2 oct2
call :zeros !oct1! oct1
call :zeros !oct2! oct2
set /a oct3=100000000+!oct1!-!oct2!-!digit4!
if !oct3! lss 100000000 (set /a oct3=!oct3!+100000000&set digit4=1) else (set digit4=0)
set string3=!oct3:~-8!!string3!
if "!string1!"=="" if "!string2!"=="" (
call :zeros !string3! string3
if "!sign!"=="-" set string3=-!string3!
exit /b
)
goto subtract_loop
rem Evaluate two numbers
rem This function is a necessity to replace native evaluations for "if X gtr/lss/eq Y" for numbers larger than 32 bits
rem For "or equal to" evaluations, just use "if X not gtr/lss/eq Y" and pick the one you are NOT looking for of the three choices
:eval
if "%1"=="%2" (
call :return eq %3
exit /b
)
if "!sign1!"=="" if "!sign2!"=="" (
call :detect_sign "%1" sign1
call :detect_sign "%2" sign2
if not "!sign1!"=="!sign2!" (
if "!sign1!"=="-" (
call :return lss %3
) else (
call :return gtr %3
)
exit /b
)
)
call :count_digits %1 count1
call :count_digits %2 count2
if not !count1!==!count2! (
if !count1! gtr !count2! (
call :return gtr %3
) else (
call :return lss %3)
exit /b
)
call :sort_digits %1 %2
if "!string!"=="%1" (
call :return gtr %3
) else (
call :return lss %3
)
exit /b
rem Return function to handle interactive or scripted mode
:return
if "%2"=="" (echo %1) else (set %2=%1)
exit /b
rem Count how many characters in a string
:count_digits
set count=
call :expand_string %1 string
for %%0 in (!string!) do set /a count=!count!+1
set %2=!count!
exit /b
rem Sort automatically evaluates strings character by character going from left to right
rem Useful for evaluating numbers of the same character length quickly
:sort_digits
for /f %%0 in ('^(echo %1^&echo %2^) ^| sort') do set string=%%0
exit /b
rem Separate number characters into substrings to iterate character-to-character calculations in for loops
:expand_string
set string=%1
set string=!string:0= 0 !
set string=!string:1= 1 !
set string=!string:2= 2 !
set string=!string:3= 3 !
set string=!string:4= 4 !
set string=!string:5= 5 !
set string=!string:6= 6 !
set string=!string:7= 7 !
set string=!string:8= 8 !
set string=!string:9= 9 !
set string=!string:A= A !
set string=!string:B= B !
set string=!string:C= C !
set string=!string:D= D !
set string=!string:E= E !
set string=!string:F= F !
set %2=!string!
exit /b
rem Condense an expanded number back to a single string
:condense_string
set string=%~1
set string=!string: =!
set %2=!string!
exit /b
rem Segments a string to be calculated in groups of 8 characters at a time
:shift_right
if "%~1"=="" (
set %3=0
) else (
set string=%~1
if "!string:~,-8!"=="" (
set %~3=!string!
set %~2=
) else (
set %3=!string:~-8!
set %2=!string:~,-8!
)
)
exit /b
rem Strip leading zeros
rem Example: 010 -> stripped -> 10 -> reversed -> 01 -> stripped -> 1
:zeros
if "%1"=="0" exit /b
set string=%1
:zeros_loop
if "!string:~,1!"=="0" if not "!string!"=="0" (
set string=!string:~1!
goto zeros_loop
)
set %2=!string!
exit /b
rem Reverse an expanded number to calculate substring characters backwards
:reverse_expanded
set string=
for %%0 in (%~1) do set string=%%0 !string!
set %2=!string!
exit /b
rem Convert decimal to hexidecimal
:dec2hex
if !external!==1 set external=2
call :dec2bin %1 hex
call :bin2hex !hex! hex
if !external!==2 (echo !hex!) else (set %2=!hex!)
exit /b
rem Convert binary to hexidecimal
:bin2hex
if "%1"=="" (
set %2=0x0
exit /b
)
set string=%1
set hex=
:bin2hex_loop
if "!string:~,-4!"=="" (
set nibble=!string!
set string=
) else (
set nibble=!string:~-4!
set string=!string:~,-4!
)
if "!nibble!"=="0" set nibble=0
if "!nibble!"=="1" set nibble=1
if "!nibble!"=="00" set nibble=0
if "!nibble!"=="01" set nibble=1
if "!nibble!"=="10" set nibble=2
if "!nibble!"=="11" set nibble=3
if "!nibble!"=="000" set nibble=0
if "!nibble!"=="001" set nibble=1
if "!nibble!"=="010" set nibble=2
if "!nibble!"=="011" set nibble=3
if "!nibble!"=="100" set nibble=4
if "!nibble!"=="101" set nibble=5
if "!nibble!"=="110" set nibble=6
if "!nibble!"=="111" set nibble=7
if "!nibble!"=="0000" set nibble=0
if "!nibble!"=="0001" set nibble=1
if "!nibble!"=="0010" set nibble=2
if "!nibble!"=="0011" set nibble=3
if "!nibble!"=="0100" set nibble=4
if "!nibble!"=="0101" set nibble=5
if "!nibble!"=="0110" set nibble=6
if "!nibble!"=="0111" set nibble=7
if "!nibble!"=="1000" set nibble=8
if "!nibble!"=="1001" set nibble=9
if "!nibble!"=="1010" set nibble=A
if "!nibble!"=="1011" set nibble=B
if "!nibble!"=="1100" set nibble=C
if "!nibble!"=="1101" set nibble=D
if "!nibble!"=="1110" set nibble=E
if "!nibble!"=="1111" set nibble=F
set hex=!nibble!!hex!
if "!string!"=="" (
set %2=0x!hex!
exit /b
)
goto bin2hex_loop
rem Convert hexidecimal to binary
:hex2bin
if "%1"=="" (
set %2=0
exit /b
)
set string=%1
set string=!string:0x=!
set string=!string:0=0000!
set string=!string:1=0001!
set string=!string:2=0010!
set string=!string:3=0011!
set string=!string:4=0100!
set string=!string:5=0101!
set string=!string:6=0110!
set string=!string:7=0111!
set string=!string:8=1000!
set string=!string:9=1001!
set string=!string:A=1010!
set string=!string:B=1011!
set string=!string:C=1100!
set string=!string:D=1101!
set string=!string:E=1110!
set string=!string:F=1111!
set %2=!string!
exit /b
rem If a 32-bit number is negative, this will break it out to be a true 32-bit number with no bit for sign control
:32bit
call :detect_sign "%1" sign
call :remove_sign "%1" dec
if "!sign!"=="-" (call :add 4294967296 %~1 dec)
echo !dec!
exit /b
rem If a 32-bit positive number takes up 32 bits, this converts it to a 32-bit negative with sign control
:32bitp
set dec=%1
call :eval %1 2147483648 string
if not "!string!"=="lss" (call :add -4294967296 %~1 dec)
echo !dec!
exit /b
rem Converts decimal to binary
:dec2bin
if "%1"=="0" (
if "!external!"=="1" (echo 0) else (set %2=0)
exit /b
)
call :detect_sign "%1" sign
call :remove_sign "%1" dec
if "!sign!"=="-" (call :add 4294967296 %~1 dec)
rem Load default 32-bit number set
set bits=2147483648
set bit=2147483648
rem Load 64-bit number set if the number is larger than 32 bits
call :eval !dec! 2147483648 string
if "!string!"=="gtr" (
set bits=9223372036854775808 4611686018427387904 2305843009213693952 1152921504606846976 576460752303423488 288230376151711744 144115188075855872 72057594037927936 36028797018963968 18014398509481984 9007199254740992 4503599627370496 2251799813685248 1125899906842624 562949953421312 281474976710656 140737488355328 70368744177664 35184372088832 17592186044416 8796093022208 4398046511104 2199023255552 1099511627776 549755813888 274877906944 137438953472 68719476736 34359738368 17179869184 8589934592 4294967296 !bits!
set bit=9223372036854775808
rem Load 128-bit number set if the number is larger than 64 bits
call :eval !dec! 9223372036854775808 string
if "!string!"=="gtr" (
set bits=170141183460469231731687303715884105728 85070591730234615865843651857942052864 42535295865117307932921825928971026432 21267647932558653966460912964485513216 10633823966279326983230456482242756608 5316911983139663491615228241121378304 2658455991569831745807614120560689152 1329227995784915872903807060280344576 664613997892457936451903530140172288 332306998946228968225951765070086144 166153499473114484112975882535043072 83076749736557242056487941267521536 41538374868278621028243970633760768 20769187434139310514121985316880384 10384593717069655257060992658440192 5192296858534827628530496329220096 2596148429267413814265248164610048 1298074214633706907132624082305024 649037107316853453566312041152512 324518553658426726783156020576256 162259276829213363391578010288128 81129638414606681695789005144064 40564819207303340847894502572032 20282409603651670423947251286016 10141204801825835211973625643008 5070602400912917605986812821504 2535301200456458802993406410752 1267650600228229401496703205376 633825300114114700748351602688 316912650057057350374175801344 158456325028528675187087900672 79228162514264337593543950336 39614081257132168796771975168 19807040628566084398385987584 9903520314283042199192993792 4951760157141521099596496896 2475880078570760549798248448 1237940039285380274899124224 618970019642690137449562112 309485009821345068724781056 154742504910672534362390528 77371252455336267181195264 38685626227668133590597632 19342813113834066795298816 9671406556917033397649408 4835703278458516698824704 2417851639229258349412352 1208925819614629174706176 604462909807314587353088 302231454903657293676544 151115727451828646838272 75557863725914323419136 37778931862957161709568 18889465931478580854784 9444732965739290427392 4722366482869645213696 2361183241434822606848 1180591620717411303424 590295810358705651712 295147905179352825856 147573952589676412928 73786976294838206464 36893488147419103232 18446744073709551616 !bits!
set bit=170141183460469231731687303715884105728
rem If the number is higher than 128 bits, check if there is a cache file with a higher number set
rem If the cache file exists, load the number set
call :eval !dec! 170141183460469231731687303715884105728 string
if "!string!"=="gtr" (
if exist !bdat! (
set /p bits=<!bdat!
for /f %%0 in (!bdat!) do set bit=%%0
) else (
set bit=1
set bits=1
)
) else (
goto dec2bin_return
)
)
)
rem If the number set is still not high enough, calculate it real time
rem Save the number set in the cache for later to speed up the operaton next time
:dec2bin_loop
call :eval !dec! !bit! string
if "!string!"=="gtr" (
call :add !bit! !bit! bit
set bits=!bit! !bits!
if not !cache!==1 set cache=1
goto dec2bin_loop
)
if !cache!==1 (
echo !bits!>!bdat!
set cache=
)
rem Begin evaluating input number against number set to calculate bits
:dec2bin_return
set bin=
rem Loop to calculate numbers 32 bits and higher
for %%0 in (!bits!) do (
call :eval !dec! %%0 string
if "!string!"=="lss" (set bin=!bin!0) else (set bin=!bin!1&call :add !dec! -%%0 dec)
)
rem Loop to calculate 31 bits and lower
for /l %%0 in (30,-1,0) do (
set /a bit="!dec!&(1<<%%0)"
if !bit!==0 (set bin=!bin!0) else (set bin=!bin!1)
)
rem Clean up leading zeros and return result
call :zeros !bin! bin
if "!external!"=="1" (echo !bin!) else (set %2=!bin!)
exit /b