Snippets
  • Uploaded By: maroon
  • Author: maroon
  • Added: 7 months ago
  • Last Updated: Never
  • mIRC Version: used 6.35 & 7.52
  • Hits: 340
  • Size: 7.52KB
  • Downloads: 6
  • Review By: entropy

Big Integer Math v1.0

Basic support for ADD SUB MUL and EXP math supports only Integers.
Requires exactly two inputs, both be integers with NO period NO fraction. Accepts negative inputs except EXP's n2.
Beginning effort to support accuracy above 2^53 that's...
not present in $calc: //var %a $calc(2^48 -1) | echo -a $calc(%a * %a) vs $bigint_mul(%a,%a)
not present in $base: //echo -a $base($base($sha1(abc),16,10),10,16)
not present in "if (a = b)": //var %a $str(9,15) | if (%a $+ 0 == %a $+ 1) echo -a match
$calc(n1 + n2) = $bigint_add(n1,n2)
$calc(n1 - n2) = $bigint_sub(n1,n2)
$calc(n1 * n2) = $bigint_mul(n1,n2)
$calc(n1 ^ n2) = $bigint_exp(n1,n2)
calc(a*b+c) = $bigint_add($bigint_mul(a,b),c)


  
  3    0  Login to Vote.


Source Code:
  1. ; $bigint_mul(n1,n2) $bigint_add(n1,n2) $bigint_sub(n1,n2) $bigint_exp(n1,n2)
  2. ; by maroon
  3. ; mIRC's math operations used in $calc, $base, etc is not accurate above 2^53, and returns 0 for 2^1024 and above
  4. ; Exactly TWO inputs - this isn't a replacement for $calc(), and can be much slower
  5. ; first 3 need n1 and n2 BOTH be integers either positive or negative, containing no period or fractions.
  6. ; exp() also needs n2 positive - exp(n1,n2) just calls mul() to mutiply n1 times-itself n2-1 times
  7. ;
  8. ; $calc(%a + %b) -> $bigint_add(%a,%b) ; $calc(%a - %b) -> $bigint_sub(%a,%b)
  9. ; $calc(%a * %b) -> $bigint_mul(%a,%b) ; $calc(%a ^ %b) -> $bigint_exp(%a,%b)
  10. ; $calc(%a * %b + %c) -> $bigint_add($bigint_mul(%a,%b),%c)
  11. ;
  12. ; accuracy not limited below 2^53, can be numeric strings as long they and/or the reply are allowed by mIRC line length
  13. ; Compare: //var %a $calc(2^48 -1) | echo -a $calc(%a * %a) vs $bigint_mul(%a,%a)
  14. ; Divides large numbers into multi-digit groups to avoid $calc() math using numbers above 2^53
  15. ; For compatibility with $calc: If n1 is non-numeric, answer is 0. If n2 is non-numeric, answer is n1 <math-operation> 0.
  16. ; //var %a 1 , %b x | echo -a add $calc(%a +%b) $calc(%b +%a) sub $calc(%a -%b) $calc(%b -%a) mul $calc(%a *%b) $calc(%b *%a)
  17. ; "if (b > a)" isn't accurate when b and a are larger than 2^53 and $calc(a) is same as $calc(b)
  18. ; so if b=a and they're > 2^53, prepending identical text to each, followed by compare as if text
  19. ; handling negative n1 or n2 means sub() and add() could use each other for the answer:
  20. ; sub(+a,-b) returns add(+a,+b). sub(-a,+b) returns -add(+a,+b). sub(-a,-b) = add(-a,+b) -> returns sub(+b,+a)
  21. ; add(+a,-b) or add(-a,+b) return sub(+a,+b) or sub(+b,+a). add(-a,-b) returns -add(+a,+b).
  22. ; mul(-a,-b) returns mul(+a,+b). mul(+a,-b) or mul(-a,+b) return -mul(+a,+b).
  23. ; All 3 subcontract the entire math to $calc() if both terms small enough that neither n1,n2,output are > 2^53 by:
  24. ; mul= if combined lengths of n1 $+ n2 <= 15 then answer is < 2^53 because $len($calc(2^53)) is 16
  25. ; add= if larger term <= 2^52 then answer also < 2^53
  26. ; sub= if larger term < 2^53 then answer also < 2^53
  27. ; $bigint_exp(2,1024) isn't optimized, it calls bigint_mul 1023 times.
  28.  
  29. alias bigint_exp {
  30. if (($1 !isnum) || ($2 !isnum) || ($2 !isnum 1-)) { return 0 }
  31. var %exp = $int($2) - 1 , %output = $abs($1) , %minus
  32. if ($1 < 0) var %minus = $remove($str(-,$count($2,-)),--)
  33. while (%exp) { var %output = $bigint_mul(%output,$1) | dec %exp }
  34. return %output
  35. }
  36.  
  37. alias bigint_mul {
  38. var %minus
  39. if (($1 !isnum) || ($2 !isnum)) { return 0 }
  40. if (- isin $1 $2) { if ((-* iswm $1) && (-* iswm $2)) noop | else var %minus = - | tokenize 32 $remove($1,-) $remove($2,-) }
  41. if ($len($1 $+ $2) < 16) return %minus $+ $calc($1 * $2)
  42. if ((!$1) || (!$2)) return 0
  43. var %p = 1 , %a | if ($calc($len($1) % 7)) { inc %p $v1 | var %a = $mid($1,1,$v1) } | while ($mid($1,%p,7) != $null) { var %a = $v1 %a | inc %p 7 }
  44. var %p = 1 , %b | if ($calc($len($2) % 7)) { inc %p $v1 | var %b = $mid($2,1,$v1) } | while ($mid($2,%p,7) != $null) { var %b = $v1 %b | inc %p 7 }
  45. var %p = $numtok(%a,32) , %q = $numtok(%b,32) , %b_i = 1 , %output = $str(0 $chr(32),$calc(%p + %q))
  46. while (%b_i isnum 1- $+ %q) {
  47. var %carry = 0 , %a_i = 1
  48. while (%a_i isnum 1- $+ %p) {
  49. var %c = $calc(%a_i + %b_i -1)
  50. var %temp = $calc( $gettok(%output,%c,32) + %carry + $gettok(%a,%a_i,32) * $gettok(%b,%b_i,32) )
  51. var %carry = $left(%temp,-7) | if (%carry) var %temp = $right(%temp,7)
  52. var %output = $puttok(%output,$base(%temp,10,10,7),%c,32)
  53. inc %a_i
  54. }
  55. var %p2 = %b_i + %p
  56. if (%carry) var %output = $puttok(%output,$calc(%carry + $gettok(%output,%p2,32)),%p2,32)
  57. inc %b_i
  58. }
  59. var %output = $remove($regsubex(%output,/(\d+)/g, $gettok(%output, - $+ \n ,32) ) ,$chr(32))
  60. while (0?* iswm %output) { var %output = $mid(%output,2-) }
  61. if (!$isid) echo 5 -s bigint_mul: $1 * $2 %minus %output
  62. return %minus $+ %output
  63. }
  64.  
  65. ; next line optional for bigmul - can insert line just above the last line to track largest # calc'ed - divide it by $log(2) to find 2^N exponent
  66. ; var %l = $log(%output) | if (!%maxbigmul) set %maxbigmul 0 | if (%l > %maxbigmul) { set %maxbigmul $v1 | echo 3 -s new bigmax 2^ $calc(%maxbigmul / $log(2) ) }
  67.  
  68. alias bigint_add {
  69. var %minus
  70. if (($1 !isnum) || ($2 !isnum)) { return $iif($1 isnum,$1,0) }
  71. if (- isin $1 $2) {
  72. if ((-* iswm $1) && (-* iswm $2)) { tokenize 32 $remove($1,-) $remove($2,-) | var %minus = - }
  73. elseif (-* iswm $2) return $bigint_sub($1,$remove($2,-))
  74. else return $bigint_sub($2,$remove($1,-))
  75. }
  76. if ($2 > $1) tokenize 32 $2 $1
  77. if ($1 < 4503599627370497) return %minus $+ $calc($1 + $2)
  78. var %p = 1 , %a | if ($calc($len($1) % 15)) { inc %p $v1 | var %a = $mid($1,1,$v1) } | while ($mid($1,%p,15) != $null) { var %a = $v1 %a | inc %p 15 }
  79. var %p = 1 , %b | if ($calc($len($2) % 15)) { inc %p $v1 | var %b = $mid($2,1,$v1) } | while ($mid($2,%p,15) != $null) { var %b = $v1 %b | inc %p 15 }
  80. var %at = $numtok(%a,32) , %output = $str(0 $chr(32),%at) , %carry = 0
  81. var %i = 0 | while (%i < %at) { inc %i
  82. var %temp = $calc($gettok(%a,%i,32) + $gettok(%b,%i,32) + %carry)
  83. if (%temp > 999999999999999) { var %carry = 1 , %temp = $mid(%temp,2) }
  84. else { var %carry = 0 }
  85. var %output = $puttok(%output,$base(%temp,10,10,15),%i,32)
  86. }
  87. if (%carry) var %output = %output %carry
  88. var %output = $remove($regsubex(%output,/(\d+)/g, $gettok(%output, - $+ \n ,32) ) ,$chr(32))
  89. while (0?* iswm %output) { var %output = $mid(%output,2-) }
  90. if (!$isid) echo 5 -s bigint_add: %minus $1 + $2 = %minus $+ %output
  91. return %minus $+ %output
  92. }
  93.  
  94. alias bigint_sub {
  95. if (($1 !isnum) || ($2 !isnum)) { return $iif($1 isnum,$1,0) }
  96. var %minus
  97. if (- isin $1 $2) {
  98. ; sub(-a,-b) -> add(-a,b) -> sub(b,a)
  99. if ((-* iswm $1) && (-* iswm $2)) { tokenize 32 $remove($2,-) $remove($1,-) }
  100. ; sub(a,-b) -> add(a,b)
  101. elseif (-* iswm $2) return $bigint_add($1,$remove($2,-))
  102. ; sub(-a,b) -> -add(a,b)
  103. else return - $+ $bigint_add($remove($1,-),$2)
  104. }
  105. var %a = $1 , %b = $2
  106. if ((%a == %b) && ($+(x,%a) != $+(x,%b))) {
  107. ; handles case where both numbers > 2^53 but are close enough that if() considers them 'equal' because $calc() makes them equal
  108. while ($len(%a) < $len(%b)) { var %a = 0 $+ %a }
  109. while ($len(%a) > $len(%b)) { var %b = 0 $+ %a }
  110. var %a = x $+ %a , %b = x $+ %b
  111. }
  112. if (%a == %b) return 0
  113. if (%b > %a) { tokenize 32 $2 $1 | if (%minus) var %minus | else var %minus = - }
  114. if ($1 < 9007199254740992) return %minus $+ $calc($1 - $2)
  115. var %p = 1 , %a | if ($calc($len($1) % 15)) { inc %p $v1 | var %a = $mid($1,1,$v1) } | while ($mid($1,%p,15) != $null) { var %a = $v1 %a | inc %p 15 }
  116. var %p = 1 , %b | if ($calc($len($2) % 15)) { inc %p $v1 | var %b = $mid($2,1,$v1) } | while ($mid($2,%p,15) != $null) { var %b = $v1 0 $+ %b | inc %p 15 }
  117. var %at = $numtok(%a,32) , %carry = 0 , %output
  118. var %i = 0 | while (%i < %at) { inc %i
  119. var %temp = $calc($gettok(%a,%i,32) - $gettok(%b,%i,32) - %carry)
  120. if (%temp < 0) { var %carry = 1 , %temp = %temp + 1000000000000000 }
  121. else { var %carry = 0 }
  122. var %output = $base(%temp,10,10,15) $+ %output
  123. }
  124. while (0?* iswm %output) var %output = $mid(%output,2-)
  125. if (!$isid) echo 5 -s bigint_sub: $1 - $2 = %minus $+ %output
  126. return %minus $+ %output
  127. }
  128.  


Comments
No Comments.

Login to Comment.