Large integer addition and subtraction -- dramatically improved

Geoff Canyon gcanyon at gmail.com
Mon Dec 14 13:22:23 EST 2015


I've created new routines for adding and subtracting large numbers. They
work on positive and negative integers, and are 10x to 20x and up faster
than any other routines I've seen (they are faster than routines I've
posted in the past). Also, they are optimized for mismatched arguments --
adding a 10 digit and 1000 digit number is substantially faster than adding
two 1000 digit numbers. The order of the arguments to the add function does
not matter: 10 digit plus 1000 digit will be as fast as 1000 digit plus 10
digit.

I have tested the results from these over thousands of example numbers
against other large number libraries to ensure accuracy, but more testing
for edge cases is always appropriate. And of course if anyone has any
suggestions or questions I'm all ears.

I'll work on multiplication and division later.

Here they are:

function bAdd x,y
   if char 1 of x is "-" then
      delete char 1 of x
      if char 1 of y is "-" then
         delete char 1 of y
         put "-" into theSign
      else
         return bSubtract(y,x)
      end if
   else
      if char 1 of y is "-" then
         delete char 1 of y
         return bSubtract(x,y)
      else
         put empty into theSign
      end if
   end if
   put length(x) into lenX
   put length(y) into lenY
   if lenX > lenY then
      put x into r
      put lenX into lenR
   else
      put y into r
      put lenY into lenR
      put x into y
      put lenX into lenY
   end if
   put 0 into c
   repeat with i = 14 to lenR step 14
      add char -i to 13 - i of r + char -i to 13 - i of y to c
      put char -14 to -1 of ("00000000000000" & c) into char -i to 13 - i
of r
      delete char -14 to -1 of c
      if i > lenY and c is empty then exit repeat
   end repeat
   put c before r
   put 0 + char 1 to 14 of r into char 1 to 14 of r
   return theSign & r
end bAdd

function bSubtract x,y
   if char 1 of x is "-" then
      if char 1 of y is "-" then
         delete char 1 of x
         delete char 1 of y
         put "-" into theSign
      else
         return bAdd(x,"-" & y)
      end if
   else
      if char 1 of y is "-" then
         return bAdd(x,char 2 to -1 of y)
      else
         put empty into theSign
      end if
   end if
   put length(x) into lenX
   put length(y) into lenY
   if lenX > lenY then
      put x into r
      put lenX into lenR
   else if lenX < lenY then
      if theSign is "-" then put empty into theSign else put "-" into
theSign
      put y into r
      put lenY into lenR
      put x into y
      put lenX into lenY
   else
      get bCompare(x,y)
      if it is "greater" then
         put x into r
         put lenX into lenR
      else if it is "less" then
         if theSign is "-" then put empty into theSign else put "-" into
theSign
         put y into r
         put lenY into lenR
         put x into y
         put lenX into lenY
      else
         return 0
      end if
   end if
   put 0 into c
   repeat with i = 14 to lenR step 14
      put char -i to 13 - i of r into s
      add char -i to 13 - i of y to c
      if s >= c then
         put s - c into s
         put 0 into c
      else
         put ("1" & s) - c into s
         put 1 into c
      end if
      put char -14 to -1 of ("00000000000000" & s) into char -i to 13 - i
of r
      if i > lenY and c = 0 then exit repeat
   end repeat
   put 0 + char 1 to 15 of r into char 1 to 15 of r
   return theSign & r
end bSubtract

function bCompare x,y -- only works on unsigned values
   put length(x) into lenX
   put length(y) into lenY
   if lenX > lenY then return "greater"
   if lenX < lenY then return "less"
   repeat with i = 1 to lenX step 14
      put char i to i + 13 of x into x1
      put char i to i + 13 of y into y1
      if x1 > y1 then return "greater"
      if x1 < y1 then return "less"
   end repeat
   return "equal"
end bCompare



More information about the use-livecode mailing list