Advertisement
programcreator

BigNum

Feb 6th, 2016
148
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 25.34 KB | None | 0 0
  1. --%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{1
  2. --
  3. --  File Name:              bignum.lua
  4. --  Package Name:           BigNum
  5. --
  6. --  Project:    Big Numbers library for Lua
  7. --  Mantainers: fmp - Frederico Macedo Pessoa
  8. --              msm - Marco Serpa Molinaro
  9. --
  10. --  History:
  11. --     Version      Autor       Date            Notes
  12. --      1.1      fmp/msm    12/11/2004   Some bug fixes (thanks Isaac Gouy)
  13. --      alfa     fmp/msm    03/22/2003   Start of Development
  14. --      beta     fmp/msm    07/11/2003   Release
  15. --
  16. --  Description:
  17. --    Big numbers manipulation library for Lua.
  18. --    A Big Number is a table with as many numbers as necessary to represent
  19. --       its value in base 'RADIX'. It has a field 'len' containing the num-
  20. --       ber of such numbers and a field 'signal' that may assume the values
  21. --       '+' and '-'.
  22. --
  23. --$.%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  24.  
  25.  
  26. --%%%%%%%%  Constants used in the file %%%%%%%%--{{{1
  27.    RADIX = 10^7 ;
  28.    RADIX_LEN = math.floor( math.log10 ( RADIX ) ) ;
  29.  
  30.  
  31. --%%%%%%%%        Start of Code        %%%%%%%%--
  32.  
  33. BigNum = {} ;
  34. BigNum.mt = {} ;
  35.  
  36.  
  37. --BigNum.new{{{1
  38. --%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  39. --
  40. --  Function: New
  41. --
  42. --
  43. --  Description:
  44. --     Creates a new Big Number based on the parameter num.
  45. --
  46. --  Parameters:
  47. --     num - a string, number or BigNumber.
  48. --
  49. --  Returns:
  50. --     A Big Number, or a nil value if an error occured.
  51. --
  52. --
  53. --  %%%%%%%% --
  54.  
  55. function BigNum.new( num ) --{{{2
  56.    local bignum = {} ;
  57.    setmetatable( bignum , BigNum.mt ) ;
  58.    BigNum.change( bignum , num ) ;
  59.    return bignum ;
  60. end
  61.  
  62. --%%%%%%%%%%%%%%%%%%%% Functions for metatable %%%%%%%%%%%%%%%%%%%%--{{{1
  63. --BigNum.mt.sub{{{2
  64. function BigNum.mt.sub( num1 , num2 )
  65.    local temp = BigNum.new() ;
  66.    local bnum1 = BigNum.new( num1 ) ;
  67.    local bnum2 = BigNum.new( num2 ) ;
  68.    BigNum.sub( bnum1 , bnum2 , temp ) ;
  69.    return temp ;
  70. end
  71.  
  72. --BigNum.mt.add{{{2
  73. function BigNum.mt.add( num1 , num2 )
  74.    local temp = BigNum.new() ;
  75.    local bnum1 = BigNum.new( num1 ) ;
  76.    local bnum2 = BigNum.new( num2 ) ;
  77.    BigNum.add( bnum1 , bnum2 , temp ) ;
  78.    return temp ;
  79. end
  80.  
  81. --BigNum.mt.mul{{{2
  82. function BigNum.mt.mul( num1 , num2 )
  83.    local temp = BigNum.new() ;
  84.    local bnum1 = BigNum.new( num1 ) ;
  85.    local bnum2 = BigNum.new( num2 ) ;
  86.    BigNum.mul( bnum1 , bnum2 , temp ) ;
  87.    return temp ;
  88. end
  89.  
  90. --BigNum.mt.div{{{2
  91. function BigNum.mt.div( num1 , num2 )
  92.    local bnum1 = {} ;
  93.    local bnum2 = {} ;
  94.    local bnum3 = BigNum.new() ;
  95.    local bnum4 = BigNum.new() ;
  96.    bnum1 = BigNum.new( num1 ) ;
  97.    bnum2 = BigNum.new( num2 ) ;
  98.    BigNum.div( bnum1 , bnum2 , bnum3 , bnum4 ) ;
  99.    return bnum3 , bnum4 ;
  100. end
  101.  
  102. --BigNum.mt.tostring{{{2
  103. function BigNum.mt.tostring( bnum )
  104.    local i = 0 ;
  105.    local j = 0 ;
  106.    local str = "" ;
  107.    local temp = "" ;
  108.    if bnum == nil then
  109.       return "nil" ;
  110.    elseif bnum.len > 0 then
  111.       for i = bnum.len - 2 , 0 , -1  do
  112.          for j = 0 , RADIX_LEN - string.len( bnum[i] ) - 1 do
  113.             temp = temp .. '0' ;
  114.          end
  115.          temp = temp .. bnum[i] ;
  116.       end
  117.       temp = bnum[bnum.len - 1] .. temp ;
  118.       if bnum.signal == '-' then
  119.          temp = bnum.signal .. temp ;
  120.       end
  121.       return temp ;
  122.    else
  123.       return "" ;
  124.    end
  125. end
  126.  
  127. --BigNum.mt.pow{{{2
  128. function BigNum.mt.pow( num1 , num2 )
  129.    local bnum1 = BigNum.new( num1 ) ;
  130.    local bnum2 = BigNum.new( num2 ) ;
  131.    return BigNum.pow( bnum1 , bnum2 ) ;
  132. end
  133.  
  134. --BigNum.mt.eq{{{2
  135. function BigNum.mt.eq( num1 , num2 )
  136.    local bnum1 = BigNum.new( num1 ) ;
  137.    local bnum2 = BigNum.new( num2 ) ;
  138.    return BigNum.eq( bnum1 , bnum2 ) ;
  139. end
  140.  
  141. --BigNum.mt.lt{{{2
  142. function BigNum.mt.lt( num1 , num2 )
  143.    local bnum1 = BigNum.new( num1 ) ;
  144.    local bnum2 = BigNum.new( num2 ) ;
  145.    return BigNum.lt( bnum1 , bnum2 ) ;
  146. end
  147.  
  148. --BigNum.mt.le{{{2
  149. function BigNum.mt.le( num1 , num2 )
  150.    local bnum1 = BigNum.new( num1 ) ;
  151.    local bnum2 = BigNum.new( num2 ) ;
  152.    return BigNum.le( bnum1 , bnum2 ) ;
  153. end
  154.  
  155. --BigNum.mt.unm{{{2
  156. function BigNum.mt.unm( num )
  157.    local ret = BigNum.new( num )
  158.    if ret.signal == '+' then
  159.       ret.signal = '-'
  160.    else
  161.       ret.signal = '+'
  162.    end
  163.    return ret
  164. end
  165.  
  166. --%%%%%%%%%%%%%%%%%%%% Metatable Definitions %%%%%%%%%%%%%%%%%%%%--{{{1
  167.  
  168. BigNum.mt.__metatable = "hidden"           ; -- answer to getmetatable(aBignum)
  169. -- BigNum.mt.__index     = "inexistent field" ; -- attempt to acess nil valued field
  170. -- BigNum.mt.__newindex  = "not available"    ; -- attempt to create new field
  171. BigNum.mt.__tostring  = BigNum.mt.tostring ;
  172. -- arithmetics
  173. BigNum.mt.__add = BigNum.mt.add ;
  174. BigNum.mt.__sub = BigNum.mt.sub ;
  175. BigNum.mt.__mul = BigNum.mt.mul ;
  176. BigNum.mt.__div = BigNum.mt.div ;
  177. BigNum.mt.__pow = BigNum.mt.pow ;
  178. BigNum.mt.__unm = BigNum.mt.unm ;
  179. -- Comparisons
  180. BigNum.mt.__eq = BigNum.mt.eq   ;
  181. BigNum.mt.__le = BigNum.mt.le   ;
  182. BigNum.mt.__lt = BigNum.mt.lt   ;
  183. --concatenation
  184. -- BigNum.me.__concat = ???
  185.  
  186. setmetatable( BigNum.mt, { __index = "inexistent field", __newindex = "not available", __metatable="hidden" } ) ;
  187.  
  188. --%%%%%%%%%%%%%%%%%%%% Basic Functions %%%%%%%%%%%%%%%%%%%%--{{{1
  189. --%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
  190. --
  191. --  Function: ADD
  192. --
  193. --
  194. --  Description:
  195. --     Adds two Big Numbers.
  196. --
  197. --  Parameters:
  198. --     bnum1, bnum2 - Numbers to be added.
  199. --     bnum3 - result
  200. --
  201. --  Returns:
  202. --     0
  203. --
  204. --  Exit assertions:
  205. --     bnum3 is the result of the sum.
  206. --
  207. --  %%%%%%%% --
  208. --Funcao BigNum.add{{{2
  209. function BigNum.add( bnum1 , bnum2 , bnum3 )
  210.    local maxlen = 0 ;
  211.    local i = 0 ;
  212.    local carry = 0 ;
  213.    local signal = '+' ;
  214.    local old_len = 0 ;
  215.    --Handle the signals
  216.    if bnum1 == nil or bnum2 == nil or bnum3 == nil then
  217.       error("Function BigNum.add: parameter nil") ;
  218.    elseif bnum1.signal == '-' and bnum2.signal == '+' then
  219.       bnum1.signal = '+' ;
  220.       BigNum.sub( bnum2 , bnum1 , bnum3 ) ;
  221.  
  222.       if not rawequal(bnum1, bnum3) then
  223.          bnum1.signal = '-' ;
  224.       end
  225.       return 0 ;
  226.    elseif bnum1.signal == '+' and bnum2.signal == '-' then  
  227.       bnum2.signal = '+' ;
  228.       BigNum.sub( bnum1 , bnum2 , bnum3 ) ;
  229.       if not rawequal(bnum2, bnum3) then
  230.          bnum2.signal = '-' ;
  231.       end
  232.       return 0 ;
  233.    elseif bnum1.signal == '-' and bnum2.signal == '-' then
  234.       signal = '-' ;
  235.    end
  236.    --
  237.    old_len = bnum3.len ;
  238.    if bnum1.len > bnum2.len then
  239.       maxlen = bnum1.len ;
  240.    else
  241.       maxlen = bnum2.len ;
  242.       bnum1 , bnum2 = bnum2 , bnum1 ;
  243.    end
  244.    --School grade sum
  245.    for i = 0 , maxlen - 1 do
  246.       if bnum2[i] ~= nil then
  247.          bnum3[i] = bnum1[i] + bnum2[i] + carry ;
  248.       else
  249.          bnum3[i] = bnum1[i] + carry ;
  250.       end
  251.       if bnum3[i] >= RADIX then
  252.          bnum3[i] = bnum3[i] - RADIX ;
  253.          carry = 1 ;
  254.       else
  255.          carry = 0 ;
  256.       end
  257.    end
  258.    --Update the answer's size
  259.    if carry == 1 then
  260.       bnum3[maxlen] = 1 ;
  261.    end
  262.    bnum3.len = maxlen + carry ;
  263.    bnum3.signal = signal ;
  264.    for i = bnum3.len, old_len do
  265.       bnum3[i] = nil ;
  266.    end
  267.    return 0 ;
  268. end
  269.  
  270.  
  271. --%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
  272. --
  273. --  Function: SUB
  274. --
  275. --
  276. --  Description:
  277. --     Subtracts two Big Numbers.
  278. --
  279. --  Parameters:
  280. --     bnum1, bnum2 - Numbers to be subtracted.
  281. --     bnum3 - result
  282. --
  283. --  Returns:
  284. --     0
  285. --
  286. --  Exit assertions:
  287. --     bnum3 is the result of the subtraction.
  288. --
  289. --  %%%%%%%% --
  290. --Funcao BigNum.sub{{{2
  291. function BigNum.sub( bnum1 , bnum2 , bnum3 )
  292.    local maxlen = 0 ;
  293.    local i = 0 ;
  294.    local carry = 0 ;
  295.    local old_len = 0 ;
  296.    --Handle the signals
  297.    
  298.    if bnum1 == nil or bnum2 == nil or bnum3 == nil then
  299.       error("Function BigNum.sub: parameter nil") ;
  300.    elseif bnum1.signal == '-' and bnum2.signal == '+' then
  301.       bnum1.signal = '+' ;
  302.       BigNum.add( bnum1 , bnum2 , bnum3 ) ;
  303.       bnum3.signal = '-' ;
  304.       if not rawequal(bnum1, bnum3) then
  305.          bnum1.signal = '-' ;
  306.       end
  307.       return 0 ;
  308.    elseif bnum1.signal == '-' and bnum2.signal == '-' then
  309.       bnum1.signal = '+' ;
  310.       bnum2.signal = '+' ;
  311.       BigNum.sub( bnum2, bnum1 , bnum3 ) ;
  312.       if not rawequal(bnum1, bnum3) then
  313.          bnum1.signal = '-' ;
  314.       end
  315.       if not rawequal(bnum2, bnum3) then
  316.          bnum2.signal = '-' ;
  317.       end
  318.       return 0 ;
  319.    elseif bnum1.signal == '+' and bnum2.signal == '-' then
  320.       bnum2.signal = '+' ;
  321.       BigNum.add( bnum1 , bnum2 , bnum3 ) ;
  322.       if not rawequal(bnum2, bnum3) then
  323.          bnum2.signal = '-' ;
  324.       end
  325.       return 0 ;
  326.    end
  327.    --Tests if bnum2 > bnum1
  328.    if BigNum.compareAbs( bnum1 , bnum2 ) == 2 then
  329.       BigNum.sub( bnum2 , bnum1 , bnum3 ) ;
  330.       bnum3.signal = '-' ;
  331.       return 0 ;
  332.    else
  333.       maxlen = bnum1.len ;
  334.    end
  335.    old_len = bnum3.len ;
  336.    bnum3.len = 0 ;
  337.    --School grade subtraction
  338.    for i = 0 , maxlen - 1 do
  339.       if bnum2[i] ~= nil then
  340.          bnum3[i] = bnum1[i] - bnum2[i] - carry ;
  341.       else
  342.          bnum3[i] = bnum1[i] - carry ;
  343.       end
  344.       if bnum3[i] < 0 then
  345.          bnum3[i] = RADIX + bnum3[i] ;
  346.          carry = 1 ;
  347.       else
  348.          carry = 0 ;
  349.       end
  350.  
  351.       if bnum3[i] ~= 0 then
  352.          bnum3.len = i + 1 ;
  353.       end
  354.    end
  355.    bnum3.signal = '+' ;
  356.    --Check if answer's size if zero
  357.    if bnum3.len == 0 then
  358.       bnum3.len = 1 ;
  359.       bnum3[0]  = 0 ;
  360.    end
  361.    if carry == 1 then
  362.       error( "Error in function sub" ) ;
  363.    end
  364.    for i = bnum3.len , max( old_len , maxlen - 1 ) do
  365.       bnum3[i] = nil ;
  366.    end
  367.    return 0 ;
  368. end
  369.  
  370.  
  371. --%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
  372. --
  373. --  Function: MUL
  374. --
  375. --
  376. --  Description:
  377. --     Multiplies two Big Numbers.
  378. --
  379. --  Parameters:
  380. --     bnum1, bnum2 - Numbers to be multiplied.
  381. --     bnum3 - result
  382. --
  383. --  Returns:
  384. --     0
  385. --
  386. --  Exit assertions:
  387. --     bnum3 is the result of the multiplication.
  388. --
  389. --  %%%%%%%% --
  390. --BigNum.mul{{{2
  391. --can't be made in place
  392. function BigNum.mul( bnum1 , bnum2 , bnum3 )
  393.    local i = 0 ; j = 0 ;
  394.    local temp = BigNum.new( ) ;
  395.    local temp2 = 0 ;
  396.    local carry = 0 ;
  397.    local oldLen = bnum3.len ;
  398.    if bnum1 == nil or bnum2 == nil or bnum3 == nil then
  399.       error("Function BigNum.mul: parameter nil") ;
  400.    --Handle the signals
  401.    elseif bnum1.signal ~= bnum2.signal then
  402.       BigNum.mul( bnum1 , -bnum2 , bnum3 ) ;
  403.       bnum3.signal = '-' ;
  404.       return 0 ;
  405.    end
  406.    bnum3.len =  ( bnum1.len ) + ( bnum2.len ) ;
  407.    --Fill with zeros
  408.    for i = 1 , bnum3.len do
  409.       bnum3[i - 1] = 0 ;
  410.    end
  411.    --Places nil where passes through this
  412.    for i = bnum3.len , oldLen do
  413.       bnum3[i] = nil ;
  414.    end
  415.    --School grade multiplication
  416.    for i = 0 , bnum1.len - 1 do
  417.       for j = 0 , bnum2.len - 1 do
  418.          carry =  ( bnum1[i] * bnum2[j] + carry ) ;
  419.          carry = carry + bnum3[i + j] ;
  420.          bnum3[i + j] = ( carry % RADIX ) ;
  421.          temp2 = bnum3[i + j] ;
  422.          carry =  math.floor ( carry / RADIX ) ;
  423.       end
  424.       if carry ~= 0 then
  425.          bnum3[i + bnum2.len] = carry ;
  426.       end
  427.       carry = 0 ;
  428.    end
  429.  
  430.    --Update the answer's size
  431.    for i = bnum3.len - 1 , 1 , -1 do
  432.       if bnum3[i] ~= nil and bnum3[i] ~= 0 then
  433.          break ;
  434.       else
  435.          bnum3[i] = nil ;
  436.       end
  437.       bnum3.len = bnum3.len - 1 ;
  438.    end
  439.    return 0 ;
  440. end
  441.  
  442.  
  443. --%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
  444. --
  445. --  Function: DIV
  446. --
  447. --
  448. --  Description:
  449. --     Divides bnum1 by bnum2.
  450. --
  451. --  Parameters:
  452. --     bnum1, bnum2 - Numbers to be divided.
  453. --     bnum3 - result
  454. --     bnum4 - remainder
  455. --
  456. --  Returns:
  457. --     0
  458. --
  459. --  Exit assertions:
  460. --     bnum3 is the result of the division.
  461. --     bnum4 is the remainder of the division.
  462. --
  463. --  %%%%%%%% --
  464. --BigNum.div{{{2
  465. function BigNum.div( bnum1 , bnum2 , bnum3 , bnum4 )
  466.    local temp = BigNum.new() ;
  467.    local temp2 = BigNum.new() ;
  468.    local one = BigNum.new( "1" ) ;
  469.    local zero = BigNum.new( "0" ) ;
  470.    --Check division by zero
  471.    if BigNum.compareAbs( bnum2 , zero ) == 0 then
  472.       error( "Function BigNum.div: Division by zero" ) ;
  473.    end    
  474.    --Handle the signals
  475.    if bnum1 == nil or bnum2 == nil or bnum3 == nil or bnum4 == nil then
  476.       error( "Function BigNum.div: parameter nil" ) ;
  477.    elseif bnum1.signal == "+" and bnum2.signal == "-" then
  478.       bnum2.signal = "+" ;
  479.       BigNum.div( bnum1 , bnum2 , bnum3 , bnum4 ) ;
  480.       bnum2.signal = "-" ;
  481.       bnum3.signal = "-" ;
  482.       return 0 ;
  483.    elseif bnum1.signal == "-" and bnum2.signal == "+" then
  484.       bnum1.signal = "+" ;
  485.       BigNum.div( bnum1 , bnum2 , bnum3 , bnum4 ) ;
  486.       bnum1.signal = "-" ;
  487.       if bnum4 < zero then --Check if remainder is negative
  488.          BigNum.add( bnum3 , one , bnum3 ) ;
  489.          BigNum.sub( bnum2 , bnum4 , bnum4 ) ;
  490.       end
  491.       bnum3.signal = "-" ;
  492.       return 0 ;
  493.    elseif bnum1.signal == "-" and bnum2.signal == "-" then
  494.       bnum1.signal = "+" ;
  495.       bnum2.signal = "+" ;
  496.       BigNum.div( bnum1 , bnum2 , bnum3 , bnum4 ) ;
  497.       bnum1.signal = "-" ;
  498.       if bnum4 < zero then --Check if remainder is negative      
  499.          BigNum.add( bnum3 , one , bnum3 ) ;
  500.          BigNum.sub( bnum2 , bnum4 , bnum4 ) ;
  501.       end
  502.       bnum2.signal = "-" ;
  503.       return 0 ;
  504.    end
  505.    temp.len = bnum1.len - bnum2.len - 1 ;
  506.  
  507.    --Reset variables
  508.    BigNum.change( bnum3 , "0" ) ;
  509.    BigNum.change( bnum4 , "0" ) ;
  510.  
  511.    BigNum.copy( bnum1 , bnum4 ) ;
  512.  
  513.    --Check if can continue dividing
  514.    while( BigNum.compareAbs( bnum4 , bnum2 ) ~= 2 ) do
  515.       if bnum4[bnum4.len - 1] >= bnum2[bnum2.len - 1] then
  516.          BigNum.put( temp , math.floor( bnum4[bnum4.len - 1] / bnum2[bnum2.len - 1] ) , bnum4.len - bnum2.len ) ;
  517.          temp.len = bnum4.len - bnum2.len + 1 ;
  518.       else
  519.          BigNum.put( temp , math.floor( ( bnum4[bnum4.len - 1] * RADIX + bnum4[bnum4.len - 2] ) / bnum2[bnum2.len -1] ) , bnum4.len - bnum2.len - 1 ) ;
  520.          temp.len = bnum4.len - bnum2.len ;
  521.       end
  522.    
  523.       if bnum4.signal ~= bnum2.signal then
  524.          temp.signal = "-";
  525.       else
  526.          temp.signal = "+";
  527.       end
  528.       BigNum.add( temp , bnum3 , bnum3 )  ;
  529.       temp = temp * bnum2 ;
  530.       BigNum.sub( bnum4 , temp , bnum4 ) ;
  531.    end
  532.  
  533.    --Update if the remainder is negative
  534.    if bnum4.signal == '-' then
  535.       decr( bnum3 ) ;
  536.       BigNum.add( bnum2 , bnum4 , bnum4 ) ;
  537.    end
  538.    return 0 ;
  539. end
  540.  
  541. --%%%%%%%%%%%%%%%%%%%% Compound Functions %%%%%%%%%%%%%%%%%%%%--{{{1
  542.  
  543. --%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
  544. --
  545. --  Function: POW / EXP  
  546. --
  547. --
  548. --  Description:
  549. --     Computes a big number which represents the bnum2-th power of bnum1.
  550. --
  551. --  Parameters:
  552. --     bnum1 - base
  553. --     bnum2 - expoent
  554. --
  555. --  Returns:
  556. --     Returns a big number which represents the bnum2-th power of bnum1.
  557. --
  558. --  %%%%%%%% --
  559. --BigNum.exp{{{2
  560. function BigNum.pow( bnum1 , bnum2 )
  561.    local n = BigNum.new( bnum2 ) ;
  562.    local y = BigNum.new( 1 ) ;
  563.    local z = BigNum.new( bnum1 ) ;
  564.    local zero = BigNum.new( "0" ) ;
  565.    if bnum2 < zero then
  566.       error( "Function BigNum.exp: domain error" ) ;
  567.    elseif bnum2 == zero then
  568.       return y ;
  569.    end
  570.    while 1 do
  571.       if( n[0]% 2 ) == 0 then
  572.          n = n / 2 ;
  573.       else
  574.          n = n / 2 ;
  575.          y = z * y  ;
  576.          if n == zero then
  577.             return y ;
  578.          end
  579.       end
  580.       z = z * z ;
  581.    end
  582. end
  583. -- Portuguкs :
  584. BigNum.exp = BigNum.pow
  585.  
  586. --%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
  587. --
  588. --  Function: GCD / MMC
  589. --
  590. --
  591. --  Description:
  592. --     Computes the greatest commom divisor of bnum1 and bnum2.
  593. --
  594. --  Parameters:
  595. --     bnum1, bnum2 - positive numbers
  596. --
  597. --  Returns:
  598. --     Returns a big number witch represents the gcd between bnum1 and bnum2.
  599. --
  600. --  %%%%%%%% --
  601. --BigNum.gcd{{{2
  602. function BigNum.gcd( bnum1 , bnum2 )
  603.    local a = {} ;
  604.    local b = {} ;
  605.    local c = {} ;
  606.    local d = {} ;
  607.    local zero = {} ;
  608.    zero = BigNum.new( "0" ) ;
  609.    if bnum1 == zero or bnum2 == zero then
  610.       return BigNum.new( "1" ) ;
  611.    end
  612.    a = BigNum.new( bnum1 ) ;
  613.    b = BigNum.new( bnum2 ) ;
  614.    a.signal = '+' ;
  615.    b.signal = '+' ;
  616.    c = BigNum.new() ;
  617.    d = BigNum.new() ;
  618.    while b > zero do
  619.       BigNum.div( a , b , c , d ) ;
  620.       a , b , d = b , d , a ;
  621.    end
  622.    return a ;
  623. end
  624. -- Portuguкs:
  625. BigNum.mmc = BigNum.gcd
  626.  
  627. --%%%%%%%%%%%%%%%%%%%% Comparison Functions %%%%%%%%%%%%%%%%%%%%--{{{1
  628.  
  629. --%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
  630. --
  631. --  Function: EQ
  632. --
  633. --
  634. --  Description:
  635. --     Compares two Big Numbers.
  636. --
  637. --  Parameters:
  638. --     bnum1, bnum2 - numbers
  639. --
  640. --  Returns:
  641. --     Returns true if they are equal or false otherwise.
  642. --
  643. --  %%%%%%%% --
  644. --BigNum.eq{{{2
  645. function BigNum.eq( bnum1 , bnum2 )
  646.    if BigNum.compare( bnum1 , bnum2 ) == 0 then
  647.       return true ;
  648.    else
  649.       return false ;
  650.    end
  651. end
  652.  
  653. --%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
  654. --
  655. --  Function: LT
  656. --
  657. --
  658. --  Description:
  659. --     Verifies if bnum1 is lesser than bnum2.
  660. --
  661. --  Parameters:
  662. --     bnum1, bnum2 - numbers
  663. --
  664. --  Returns:
  665. --     Returns true if bnum1 is lesser than bnum2 or false otherwise.
  666. --
  667. --  %%%%%%%% --
  668. --BigNum.lt{{{2
  669. function BigNum.lt( bnum1 , bnum2 )
  670.    if BigNum.compare( bnum1 , bnum2 ) == 2 then
  671.       return true ;
  672.    else
  673.       return false ;
  674.    end
  675. end
  676.  
  677.  
  678. --%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
  679. --
  680. --  Function: LE
  681. --
  682. --
  683. --  Description:
  684. --     Verifies if bnum1 is lesser or equal than bnum2.
  685. --
  686. --  Parameters:
  687. --     bnum1, bnum2 - numbers
  688. --
  689. --  Returns:
  690. --     Returns true if bnum1 is lesser or equal than bnum2 or false otherwise.
  691. --
  692. --  %%%%%%%% --
  693. --BigNum.le{{{2
  694. function BigNum.le( bnum1 , bnum2 )
  695.    local temp = -1 ;
  696.    temp = BigNum.compare( bnum1 , bnum2 )
  697.    if temp == 0 or temp == 2 then
  698.       return true ;
  699.    else
  700.       return false ;
  701.    end
  702. end
  703.  
  704. --%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
  705. --
  706. --  Function: Compare Absolute Values
  707. --
  708. --
  709. --  Description:
  710. --     Compares absolute values of bnum1 and bnum2.
  711. --
  712. --  Parameters:
  713. --     bnum1, bnum2 - numbers
  714. --
  715. --  Returns:
  716. --     1 - |bnum1| > |bnum2|
  717. --     2 - |bnum1| < |bnum2|
  718. --     0 - |bnum1| = |bnum2|
  719. --
  720. --  %%%%%%%% --
  721. --BigNum.compareAbs{{{2
  722. function BigNum.compareAbs( bnum1 , bnum2 )
  723.    if bnum1 == nil or bnum2 == nil then
  724.       error("Function compare: parameter nil") ;
  725.    elseif bnum1.len > bnum2.len then
  726.       return 1 ;
  727.    elseif bnum1.len < bnum2.len then
  728.       return 2 ;
  729.    else
  730.       local i ;
  731.       for i = bnum1.len - 1 , 0 , -1 do
  732.          if bnum1[i] > bnum2[i] then
  733.             return 1 ;
  734.          elseif bnum1[i] < bnum2[i] then
  735.             return 2 ;
  736.          end
  737.       end
  738.    end
  739.    return 0 ;
  740. end
  741.  
  742.  
  743. --%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
  744. --
  745. --  Function: Compare
  746. --
  747. --
  748. --  Description:
  749. --     Compares values of bnum1 and bnum2.
  750. --
  751. --  Parameters:
  752. --     bnum1, bnum2 - numbers
  753. --
  754. --  Returns:
  755. --     1 - |bnum1| > |bnum2|
  756. --     2 - |bnum1| < |bnum2|
  757. --     0 - |bnum1| = |bnum2|
  758. --
  759. --  %%%%%%%% --
  760. --BigNum.compare{{{2
  761. function BigNum.compare( bnum1 , bnum2 )
  762.    local signal = 0 ;
  763.    
  764.    if bnum1 == nil or bnum2 == nil then
  765.       error("Funtion BigNum.compare: parameter nil") ;
  766.    elseif bnum1.signal == '+' and bnum2.signal == '-' then
  767.       return 1 ;
  768.    elseif bnum1.signal == '-' and bnum2.signal == '+' then
  769.       return 2 ;
  770.    elseif bnum1.signal == '-' and bnum2.signal == '-' then
  771.       signal = 1 ;
  772.    end
  773.    if bnum1.len > bnum2.len then
  774.       return 1 + signal ;
  775.    elseif bnum1.len < bnum2.len then
  776.       return 2 - signal ;
  777.    else
  778.       local i ;
  779.       for i = bnum1.len - 1 , 0 , -1 do
  780.          if bnum1[i] > bnum2[i] then
  781.             return 1 + signal ;
  782.      elseif bnum1[i] < bnum2[i] then
  783.         return 2 - signal ;
  784.      end
  785.       end
  786.    end
  787.    return 0 ;
  788. end        
  789.  
  790.  
  791. --%%%%%%%%%%%%%%%%%%%% Low level Functions %%%%%%%%%%%%%%%%%%%%--{{{1
  792. --BigNum.copy{{{2
  793. function BigNum.copy( bnum1 , bnum2 )
  794.    if bnum1 ~= nil and bnum2 ~= nil then
  795.       local i ;
  796.       for i = 0 , bnum1.len - 1 do
  797.          bnum2[i] = bnum1[i] ;
  798.       end
  799.       bnum2.len = bnum1.len ;
  800.    else
  801.       error("Function BigNum.copy: parameter nil") ;
  802.    end
  803. end
  804.  
  805.  
  806. --%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%{{{2
  807. --
  808. --  Function: Change
  809. --
  810. --  Description:
  811. --     Changes the value of a BigNum.
  812. --     This function is called by BigNum.new.
  813. --
  814. --  Parameters:
  815. --     bnum1, bnum2 - numbers
  816. --
  817. --  Returns:
  818. --     1 - |bnum1| > |bnum2|
  819. --     2 - |bnum1| < |bnum2|
  820. --     0 - |bnum1| = |bnum2|
  821. --
  822. --  %%%%%%%% --
  823. --BigNum.change{{{2
  824. function BigNum.change( bnum1 , num )
  825.    local j = 0 ;
  826.    local len = 0  ;
  827.    local num = num ;
  828.    local l ;
  829.    local oldLen = 0 ;
  830.    if bnum1 == nil then
  831.       error( "BigNum.change: parameter nil" ) ;
  832.    elseif type( bnum1 ) ~= "table" then
  833.       error( "BigNum.change: parameter error, type unexpected" ) ;
  834.    elseif num == nil then
  835.       bnum1.len = 1 ;
  836.       bnum1[0] = 0 ;
  837.       bnum1.signal = "+";
  838.    elseif type( num ) == "table" and num.len ~= nil then  --check if num is a big number
  839.       --copy given table to the new one
  840.       for i = 0 , num.len do
  841.          bnum1[i] = num[i] ;
  842.       end
  843.       if num.signal ~= '-' and num.signal ~= '+' then
  844.          bnum1.signal = '+' ;
  845.       else
  846.          bnum1.signal = num.signal ;
  847.       end
  848.       oldLen = bnum1.len ;
  849.       bnum1.len = num.len ;
  850.    elseif type( num ) == "string" or type( num ) == "number" then
  851.       if string.sub( num , 1 , 1 ) == '+' or string.sub( num , 1 , 1 ) == '-' then
  852.          bnum1.signal = string.sub( num , 1 , 1 ) ;
  853.          num = string.sub(num, 2) ;
  854.       else
  855.          bnum1.signal = '+' ;
  856.       end
  857.       num = string.gsub( num , " " , "" ) ;
  858.       local sf = string.find( num , "e" ) ;
  859.       --Handles if the number is in exp notation
  860.       if sf ~= nil then
  861.          num = string.gsub( num , "%." , "" ) ;
  862.          local e = string.sub( num , sf + 1 ) ;
  863.          e = tonumber(e) ;
  864.          if e ~= nil and e > 0 then
  865.             e = tonumber(e) ;
  866.          else
  867.             error( "Function BigNum.change: string is not a valid number" ) ;
  868.          end
  869.          num = string.sub( num , 1 , sf - 2 ) ;
  870.          for i = string.len( num ) , e do
  871.             num = num .. "0" ;
  872.          end
  873.       else
  874.          sf = string.find( num , "%." ) ;
  875.          if sf ~= nil then
  876.             num = string.sub( num , 1 , sf - 1 ) ;
  877.          end
  878.       end
  879.  
  880.       l = string.len( num ) ;
  881.       oldLen = bnum1.len ;
  882.       if (l > RADIX_LEN) then
  883.          local mod = l-( math.floor( l / RADIX_LEN ) * RADIX_LEN ) ;
  884.          for i = 1 , l-mod, RADIX_LEN do
  885.             bnum1[j] = tonumber( string.sub( num, -( i + RADIX_LEN - 1 ) , -i ) );
  886.             --Check if string dosn't represents a number
  887.             if bnum1[j] == nil then
  888.                error( "Function BigNum.change: string is not a valid number" ) ;
  889.                bnum1.len = 0 ;
  890.                return 1 ;
  891.             end
  892.             j = j + 1 ;
  893.             len = len + 1 ;
  894.          end
  895.          if (mod ~= 0) then
  896.             bnum1[j] = tonumber( string.sub( num , 1 , mod ) ) ;
  897.             bnum1.len = len + 1 ;
  898.          else
  899.             bnum1.len = len ;            
  900.          end
  901.          --Eliminate trailing zeros
  902.          for i = bnum1.len - 1 , 1 , -1 do
  903.             if bnum1[i] == 0 then
  904.                bnum1[i] = nil ;
  905.                bnum1.len = bnum1.len - 1 ;
  906.             else
  907.                break ;
  908.             end
  909.          end
  910.          
  911.       else    
  912.          -- string.len(num) <= RADIX_LEN
  913.          bnum1[j] = tonumber( num ) ;
  914.          bnum1.len = 1 ;
  915.       end
  916.    else
  917.       error( "Function BigNum.change: parameter error, type unexpected" ) ;
  918.    end
  919.  
  920.    --eliminates the deprecated higher order 'algarisms'
  921.    if oldLen ~= nil then
  922.       for i = bnum1.len , oldLen do
  923.          bnum1[i] = nil ;
  924.       end
  925.    end
  926.  
  927.    return 0 ;
  928. end
  929.  
  930. --BigNum.put{{{2
  931. --Places int in the position pos of bignum, fills before with zeroes and
  932. --after with nil.
  933. function BigNum.put( bnum , int , pos )
  934.    if bnum == nil then
  935.       error("Function BigNum.put: parameter nil") ;
  936.    end
  937.    local i = 0 ;
  938.    for i = 0 , pos - 1 do
  939.       bnum[i] = 0 ;
  940.    end
  941.    bnum[pos] = int ;
  942.    for i = pos + 1 , bnum.len do
  943.       bnum[i] = nil ;
  944.    end
  945.    bnum.len = pos ;
  946.    return 0 ;
  947. end
  948.  
  949. --printraw{{{2
  950. function printraw( bnum )
  951.    local i = 0 ;
  952.    if bnum == nil then
  953.       error( "Function printraw: parameter nil" ) ;
  954.    end
  955.    while 1 == 1 do
  956.       if bnum[i] == nil then
  957.          io.write( ' len '..bnum.len ) ;
  958.          if i ~= bnum.len then
  959.             io.write( ' ERRO!!!!!!!!' ) ;
  960.          end
  961.          io.write( "\n" ) ;
  962.          return 0 ;
  963.       end
  964.       io.write( 'r'..bnum[i] ) ;
  965.       i = i + 1 ;
  966.    end
  967. end
  968. --max{{{2
  969. function max( int1 , int2 )
  970.    if int1 > int2 then
  971.       return int1 ;
  972.    else
  973.       return int2 ;
  974.    end
  975. end
  976.  
  977. --decr{{{2
  978. function decr( bnum1 )
  979.    local temp = {} ;
  980.    temp = BigNum.new( "1" ) ;
  981.    BigNum.sub( bnum1 , temp , bnum1 ) ;
  982.    return 0 ;
  983. end
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement