Advertisement
incinirate

BigNumber Lua

Jun 26th, 2016
203
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Lua 30.41 KB | None | 0 0
  1. --[[ BonaLuna bignumber library
  2.  
  3. Copyright (C) 2010-2016 Christophe Delord
  4. http://cdsoft.fr/bl/bonaluna.html
  5.  
  6. BonaLuna is based on Lua 5.3
  7. Copyright (C) 1994-2015 Lua.org, PUC-Rio
  8.  
  9. Freely available under the terms of the MIT license.
  10.  
  11. --]]
  12.  
  13. -- Inspired by BigNum (http://oss.digirati.com.br/luabignum/)
  14.  
  15. local bn = {}
  16.  
  17. do
  18.  
  19. -- Low level integer routines {{{
  20.     local int, int_copy, int_trim, int_tostring, int_tonumber
  21.     local int_abscmp, int_cmp, int_iszero, int_isone
  22.     local int_neg, int_abs
  23.     local int_add, int_sub, int_mul, int_divmod
  24.     local int_pow
  25.     local int_zero, int_one, int_two
  26.     local int_gcd
  27.  
  28.     local RADIX = 10000000
  29.     local RADIX_LEN = math.floor(math.log10(RADIX))
  30.  
  31.     local _sep = nil
  32.  
  33.     assert(RADIX^2 < 2^53, "RADIX^2 shall be storable on a lua number")
  34.  
  35.     function bn.sep(s)
  36.         if s == "_" or s == " " or s == "" or not s then
  37.             if s == "" then s = nil end
  38.             _sep = s
  39.         else
  40.             error("bn separator shall be \"_\", \" \" or nil")
  41.         end
  42.     end
  43.  
  44.     int_trim = function(a)
  45.         for i = #a, 1, -1 do
  46.             if a[i] and a[i] ~= 0 then break end
  47.             table.remove(a)
  48.         end
  49.         if #a == 0 then a.sign = 1 end
  50.     end
  51.  
  52.     int = function(n)
  53.         n = n or 0
  54.         if type(n) == "table" then return n end
  55.         if type(n) == "number" then n = string.format("%.0f", math.floor(n)) end
  56.         assert(type(n) == "string")
  57.         n = string.gsub(n, "[ _]", "")
  58.         local sign = 1
  59.         local d = 1 -- current digit index
  60.         if string.sub(n, d, d) == '+' then d = d+1
  61.         elseif string.sub(n, d, d) == '-' then sign = -1; d = d+1
  62.         end
  63.         local base = 10
  64.         if string.lower(string.sub(n, d, d+1)) == "0x" then
  65.             d = d+2
  66.             base = 16
  67.         elseif string.lower(string.sub(n, d, d+1)) == "0o" then
  68.             d = d+2
  69.             base = 8
  70.         elseif string.lower(string.sub(n, d, d+1)) == "0b" then
  71.             d = d+2
  72.             base = 2
  73.         end
  74.         local self = {sign=1}
  75.         if base == 10 then
  76.             for i = #n, d, -RADIX_LEN do
  77.                 local digit = string.sub(n, math.max(d, i-RADIX_LEN+1), i)
  78.                 self[#self+1] = tonumber(digit)
  79.             end
  80.         else
  81.             local bn_base = {sign=1; base}
  82.             local bn_shift = {sign=1; 1}
  83.             local bn_digit = {sign=1; 0}
  84.             for i = #n, d, -1 do
  85.                 bn_digit[1] = tonumber(string.sub(n, i, i), base)
  86.                 self = int_add(self, int_mul(bn_digit, bn_shift))
  87.                 bn_shift = int_mul(bn_shift, bn_base)
  88.             end
  89.         end
  90.         self.sign = sign
  91.         int_trim(self)
  92.         return self
  93.     end
  94.  
  95.     int_zero = int(0)
  96.     int_one = int(1)
  97.     int_two = int(2)
  98.  
  99.     int_copy = function(n)
  100.         local c = {sign=n.sign}
  101.         for i = 1, #n do
  102.             c[i] = n[i]
  103.         end
  104.         return c
  105.     end
  106.  
  107.     local base_prefix = {[2]="0b", [8]="0o", [16]="0x"}
  108.     local base_group = {[2]=4, [10]=3, [16]=4}
  109.  
  110.     local function groupby(s, n)
  111.         if n and _sep then
  112.             s = s:reverse()
  113.             s = s..(("0"):rep((n-1) - (s:len()-1)%n)) -- padding
  114.             s = s:gsub("("..("."):rep(n)..")", "%1".._sep) -- group by n digits
  115.             s = s:reverse()
  116.             s = s:gsub("^".._sep, "")
  117.         end
  118.         return s
  119.     end
  120.  
  121.     int_tostring = function(n, base, bits)
  122.         base = base or 10
  123.         local s = ""
  124.         local sign = n.sign
  125.         if base == 10 and not bits then
  126.             local fmt = string.format("%%0%dd", RADIX_LEN)
  127.             for i = 1, #n do
  128.                 s = string.format(fmt, n[i]) .. s
  129.             end
  130.             s = groupby(s, base_group[base])
  131.             s = string.gsub(s, "^[_0]+", "")
  132.             if s == "" then s = "0" end
  133.         else
  134.             local prefix = base_prefix[base]
  135.             local bitsperdigits = math.log2(base)
  136.             local bn_base = int(base)
  137.             if bits then
  138.                 _, n = int_divmod(n, int_pow(int_two, int(bits)))
  139.                 for i = 1, bits, bitsperdigits do
  140.                     local d
  141.                     n, d = int_divmod(n, bn_base)
  142.                     d = int_tonumber(d)
  143.                     s = string.sub("0123456789ABCDEF", d+1, d+1) .. s
  144.                 end
  145.                 s = groupby(s, base_group[base])
  146.             else
  147.                 local absn = int_abs(n)
  148.                 while #absn > 0 do
  149.                     local d
  150.                     absn, d = int_divmod(absn, bn_base)
  151.                     d = int_tonumber(d)
  152.                     s = string.sub("0123456789ABCDEF", d+1, d+1) .. s
  153.                 end
  154.                 s = groupby(s, base_group[base])
  155.                 s = string.gsub(s, "^0+", "")
  156.                 if s == "" then s = "0" end
  157.             end
  158.             if prefix then s = prefix .. (_sep or "") .. s end
  159.         end
  160.         if sign < 0 and not bits then s = "-" .. s end
  161.         return s
  162.     end
  163.  
  164.     int_tonumber = function(n)
  165.         local s = n.sign < 0 and "-0" or "0"
  166.         local fmt = string.format("%%0%dd", RADIX_LEN)
  167.         for i = #n, 1, -1 do
  168.             s = s..string.format(fmt, n[i])
  169.         end
  170.         return tonumber(s..".")
  171.     end
  172.  
  173.     int_iszero = function(a)
  174.         return #a == 0
  175.     end
  176.  
  177.     int_isone = function(a)
  178.         return #a == 1 and a[1] == 1 and a.sign == 1
  179.     end
  180.  
  181.     int_cmp = function(a, b)
  182.         if #a == 0 and #b == 0 then return 0 end -- 0 == -0
  183.         if a.sign > b.sign then return 1 end
  184.         if a.sign < b.sign then return -1 end
  185.         if #a > #b then return a.sign end
  186.         if #a < #b then return -a.sign end
  187.         for i = #a, 1, -1 do
  188.             if a[i] > b[i] then return a.sign end
  189.             if a[i] < b[i] then return -a.sign end
  190.         end
  191.         return 0
  192.     end
  193.  
  194.     int_abscmp = function(a, b)
  195.         if #a > #b then return 1 end
  196.         if #a < #b then return -1 end
  197.         for i = #a, 1, -1 do
  198.             if a[i] > b[i] then return 1 end
  199.             if a[i] < b[i] then return -1 end
  200.         end
  201.         return 0
  202.     end
  203.  
  204.     int_neg = function(a)
  205.         local b = int_copy(a)
  206.         b.sign = -a.sign
  207.         return b
  208.     end
  209.  
  210.     int_add = function(a, b)
  211.         if a.sign == b.sign then            -- a+b = a+b, (-a)+(-b) = -(a+b)
  212.             local c = int()
  213.             c.sign = a.sign
  214.             local carry = 0
  215.             for i = 1, math.max(#a, #b) + 1 do -- +1 for the last carry
  216.                 c[i] = carry + (a[i] or 0) + (b[i] or 0)
  217.                 if c[i] >= RADIX then
  218.                     c[i] = c[i] - RADIX
  219.                     carry = 1
  220.                 else
  221.                     carry = 0
  222.                 end
  223.             end
  224.             int_trim(c)
  225.             return c
  226.         else
  227.             return int_sub(a, int_neg(b))
  228.         end
  229.     end
  230.  
  231.     int_sub = function(a, b)
  232.         if a.sign == b.sign then
  233.             local A, B
  234.             local cmp = int_abscmp(a, b)
  235.             if cmp >= 0 then A = a; B = b; else A = b; B = a; end
  236.             local c = int()
  237.             local carry = 0
  238.             for i = 1, #A do
  239.                 c[i] = A[i] - (B[i] or 0) - carry
  240.                 if c[i] < 0 then
  241.                     c[i] = c[i] + RADIX
  242.                     carry = 1
  243.                 else
  244.                     carry = 0
  245.                 end
  246.             end
  247.             assert(carry == 0) -- should be true if |A| >= |B|
  248.             c.sign = (cmp >= 0) and a.sign or -a.sign
  249.             int_trim(c)
  250.             return c
  251.         else
  252.             local c = int_add(a, int_neg(b))
  253.             c.sign = a.sign
  254.             return c
  255.         end
  256.     end
  257.  
  258.     int_mul = function(a, b)
  259.         local c = int()
  260.         for i = 1, #a do
  261.             local carry = 0
  262.             for j = 1, #b do
  263.                 carry = (c[i+j-1] or 0) + a[i]*b[j] + carry
  264.                 c[i+j-1] = carry % RADIX
  265.                 carry = math.floor(carry / RADIX)
  266.             end
  267.             if carry ~= 0 then
  268.                 c[i + #b] = carry
  269.             end
  270.         end
  271.         for i = #c, 1, -1 do
  272.             if c[i] and c[i] ~= 0 then break end
  273.             table.remove(c, i)
  274.         end            
  275.         c.sign = a.sign * b.sign
  276.         int_trim(c)
  277.         return c
  278.     end
  279.  
  280.     local function int_absdiv2(a)
  281.         local c = int()
  282.         local carry = 0
  283.         for i = 1, #a do
  284.             c[i] = 0
  285.         end
  286.         for i = #a, 1, -1 do
  287.             c[i] = math.floor(carry + a[i] / 2)
  288.             if a[i] % 2 ~= 0 then
  289.                 carry = RADIX // 2
  290.             else
  291.                 carry = 0
  292.             end
  293.         end
  294.         c.sign = a.sign
  295.         int_trim(c)
  296.         return c, (a[1] or 0) % 2
  297.     end
  298.  
  299.     int_divmod = function(a, b)
  300.         -- euclidian division using dichotomie
  301.         -- searching q and r such that a = q*b + r and |r| < |b|
  302.         assert(not int_iszero(b), "Division by zero")
  303.         if int_iszero(a) then return int_zero, int_zero end
  304.         if b.sign < 0 then a = int_neg(a); b = int_neg(b) end
  305.         local qmin = int_neg(a)
  306.         local qmax = a
  307.         if int_cmp(qmax, qmin) < 0 then qmin, qmax = qmax, qmin end
  308.         local rmin = int_sub(a, int_mul(qmin, b))
  309.         if rmin.sign > 0 and int_cmp(rmin, b) < 0 then return qmin, rmin end
  310.         local rmax = int_sub(a, int_mul(qmax, b))
  311.         if rmax.sign > 0 and int_cmp(rmax, b) < 0 then return qmax, rmax end
  312.         assert(rmin.sign ~= rmax.sign)
  313.         local q = int_absdiv2(int_add(qmin, qmax))
  314.         local r = int_sub(a, int_mul(q, b))
  315.         while r.sign < 0 or int_cmp(r, b) >= 0 do
  316.             if r.sign == rmin.sign then
  317.                 qmin, qmax = q, qmax
  318.                 rmin, rmax = r, rmax
  319.             else
  320.                 qmin, qmax = qmin, q
  321.                 rmin, rmax = rmin, r
  322.             end
  323.             q = int_absdiv2(int_add(qmin, qmax))
  324.             r = int_sub(a, int_mul(q, b))
  325.         end
  326.         return q, r
  327.     end
  328.  
  329.     int_pow = function(a, b)
  330.         assert(b.sign > 0)
  331.         if #b == 0 then return int_one end
  332.         if #b == 1 and b[1] == 1 then return a end
  333.         if #b == 1 and b[1] == 2 then return int_mul(a, a) end
  334.         local c
  335.         local q, r = int_absdiv2(b)
  336.         c = int_pow(a, q)
  337.         c = int_mul(c, c)
  338.         if r == 1 then c = int_mul(c, a) end
  339.         return c
  340.     end
  341.  
  342.     int_abs = function(a)
  343.         local b = int_copy(a)
  344.         b.sign = 1
  345.         return b
  346.     end
  347.  
  348.     int_gcd = function(a, b)
  349.         a = int_abs(a)
  350.         b = int_abs(b)
  351.         while true do
  352.             local q
  353.             local order = int_cmp(a, b)
  354.             if order == 0 then return a end
  355.             if order > 0 then
  356.                 q, a = int_divmod(a, b)
  357.                 if int_iszero(a) then return b end
  358.             else
  359.                 q, b = int_divmod(b, a)
  360.                 if int_iszero(b) then return a end
  361.             end
  362.         end
  363.     end
  364.  
  365. -- }}}
  366.  
  367. -- bn {{{
  368.  
  369.     function bn.tostring(n, base, bits)
  370.         if n.isInt then return int_tostring(n, base, bits) end
  371.         if n.isRat then return string.format("%s / %s", n.num, n.den) end
  372.         return tostring(n.n)
  373.     end
  374.  
  375.     function bn.tonumber(n)
  376.         if n.isInt then return int_tonumber(n) end
  377.         if n.isRat then return int_tonumber(n.num) / int_tonumber(n.den) end
  378.         return n.n
  379.     end
  380.  
  381.     function bn.divmod(a, b)
  382.         if a.isInt and b.isInt then
  383.             local q, r = int_divmod(a, b)
  384.             return bn.Int(q), bn.Int(r)
  385.         elseif a.isInt and b.isRat then
  386.             local q, r = int_divmod(a*b.den, b.num)
  387.             return bn.Int(q), bn.Rat(r, b.den)
  388.         elseif a.isRat and b.isInt then
  389.             local q, r = int_divmod(a.num*b, b*a.den)
  390.             return bn.Int(q), bn.Rat(r, a.den)
  391.         elseif a.isRat and b.isRat then
  392.             local q, r = int_divmod(a.num*b.den, b.num*a.den)
  393.             return bn.Int(q), bn.Rat(r, a.den*b.den)
  394.         else
  395.             a = a:tonumber()
  396.             b = b:tonumber()
  397.             return bn.Int(math.floor(a/b)), bn.Float(math.fmod(a, b))
  398.         end
  399.     end
  400.  
  401.     function bn.powmod(a, b, m)
  402.         assert(a.isInt and b.isInt and b.sign >= 0 and m.isInt)
  403.         local result = bn.one
  404.         local r
  405.         a = a % m
  406.         while not b:iszero() do
  407.             b, r = bn.divmod(b, bn.two)
  408.             if r:isone() then
  409.                 result = (result*a) % m
  410.             end
  411.             a = (a*a) % m
  412.         end
  413.         return result
  414.     end
  415.  
  416. -- }}}
  417.  
  418. -- metatable {{{
  419.  
  420.     local mt = {}
  421.     mt.__index = mt
  422.  
  423.     function mt.tostring(n, base, bits) return bn.tostring(n, base, bits) end
  424.     function mt.__tostring(n, base, bits) return bn.tostring(n, base, bits) end
  425.  
  426.     function mt.tonumber(n) return bn.tonumber(n) end
  427.     function mt.__tonumber(n) return bn.tonumber(n) end
  428.  
  429.     function mt.toInt(n)
  430.         if n.isInt then return n end
  431.         if n.isRat then local q, r = int_divmod(n.num, n.den) return bn.Int(q) end
  432.         if n.isFloat then return bn.Int(n.n) end
  433.     end
  434.  
  435.     function mt.toRat(n, eps)
  436.         if n.isInt then return n end
  437.         if n.isRat then return n end
  438.         if n.isFloat then
  439.             local num = 1
  440.             local den = 1
  441.             eps = eps or 1e-6
  442.             local absn = math.abs(n.n)
  443.             local r = num / den
  444.             --while r ~= n do
  445.             while math.abs(absn - r) > eps do
  446.                 if r < absn then
  447.                     num = num + 1
  448.                 else
  449.                     den = den + 1
  450.                     num = math.floor(absn * den)
  451.                 end
  452.                 r = num / den
  453.             end
  454.             r = bn.Rat(num, den)
  455.             if n.n < 0 then r = -r end
  456.             return r
  457.         end
  458.     end
  459.  
  460.     function mt.toFloat(n)
  461.         return bn.Float(n:tonumber())
  462.     end
  463.  
  464.     function mt.iszero(n)
  465.         return n:tonumber() == 0
  466.     end
  467.  
  468.     function mt.isone(n)
  469.         return n:tonumber() == 1
  470.     end
  471.  
  472.     function mt.__unm(a)
  473.         if a.isInt then return bn.Int(int_neg(a)) end
  474.         if a.isRat then return bn.Rat(-a.num, a.den) end
  475.         return bn.Float(-a:tonumber())
  476.     end
  477.  
  478.     function mt.__add(a, b)
  479.         if a.isInt then
  480.             if b.isInt then return bn.Int(int_add(a, b)) end
  481.             if b.isRat then return bn.Rat(a*b.den + b.num, b.den) end
  482.         elseif a.isRat then
  483.             if b.isInt then return bn.Rat(a.num + b*a.den, a.den) end
  484.             if b.isRat then return bn.Rat(a.num*b.den + b.num*a.den, a.den*b.den) end
  485.         end
  486.         return bn.Float(a:tonumber() + b:tonumber())
  487.     end
  488.  
  489.     function mt.__sub(a, b)
  490.         if a.isInt then
  491.             if b.isInt then return bn.Int(int_sub(a, b)) end
  492.             if b.isRat then return bn.Rat(a*b.den - b.num, b.den) end
  493.         elseif a.isRat then
  494.             if b.isInt then return bn.Rat(a.num - b*a.den, a.den) end
  495.             if b.isRat then return bn.Rat(a.num*b.den - b.num*a.den, a.den*b.den) end
  496.         end
  497.         return bn.Float(a:tonumber() - b:tonumber())
  498.     end
  499.  
  500.     function mt.__mul(a, b)
  501.         if a.isInt then
  502.             if b.isInt then return bn.Int(int_mul(a, b)) end
  503.             if b.isRat then return bn.Rat(a*b.num, b.den) end
  504.         elseif a.isRat then
  505.             if b.isInt then return bn.Rat(a.num*b, a.den) end
  506.             if b.isRat then return bn.Rat(a.num*b.num, a.den*b.den) end
  507.         end
  508.         return bn.Float(a:tonumber() * b:tonumber())
  509.     end
  510.  
  511.     function mt.__div(a, b)
  512.         if a.isInt then
  513.             if b.isInt then return bn.Rat(a, b) end
  514.             if b.isRat then return bn.Rat(a*b.den, b.num) end
  515.         elseif a.isRat then
  516.             if b.isInt then return bn.Rat(a.num, a.den*b) end
  517.             if b.isRat then return bn.Rat(a.num*b.den, a.den*b.num) end
  518.         end
  519.         return bn.Float(a:tonumber() / b:tonumber())
  520.     end
  521.  
  522.     function mt.__idiv(a, b)
  523.         local q, r = bn.divmod(a, b)
  524.         return q
  525.     end
  526.  
  527.     function mt.__mod(a, b)
  528.         local q, r = bn.divmod(a, b)
  529.         return r
  530.     end
  531.  
  532.     function mt.__pow(a, b)
  533.         if a.isInt then
  534.             if b.isInt then
  535.                 if b.sign > 0 then
  536.                     return bn.Int(int_pow(a, b))
  537.                 else
  538.                     return bn.Rat(bn.one, bn.Int(int_pow(a, int_neg(b))))
  539.                 end
  540.             end
  541.         elseif a.isRat then
  542.             if b.isInt then return (a.num^b) / (a.den^b) end
  543.         end
  544.         return bn.Float(a:tonumber() ^ b:tonumber())
  545.     end
  546.  
  547.     function mt.__eq(a, b)
  548.         if a.isInt then
  549.             if b.isInt then return int_cmp(a, b) == 0 end
  550.             if b.isRat then return int_cmp(a*b.den, b.num) == 0 end
  551.         elseif a.isRat then
  552.             if b.isInt then return int_cmp(a.num, b*a.den) == 0 end
  553.             if b.isRat then return int_cmp(a.num*b.den, b.num*a.den) == 0 end
  554.         end
  555.         return a:tonumber() == b:tonumber()
  556.     end
  557.  
  558.     function mt.__lt(a, b)
  559.         if a.isInt then
  560.             if b.isInt then return int_cmp(a, b) < 0 end
  561.             if b.isRat then return int_cmp(a*b.den, b.num) * b.den.sign < 0 end
  562.         elseif a.isRat then
  563.             if b.isInt then return int_cmp(a.num, b*a.den) * a.den.sign < 0 end
  564.             if b.isRat then return int_cmp(a.num*b.den, b.num*a.den) * a.den.sign*b.den.sign < 0 end
  565.         end
  566.         return a:tonumber() < b:tonumber()
  567.     end
  568.  
  569.     function mt.__le(a, b)
  570.         if a.isInt then
  571.             if b.isInt then return int_cmp(a, b) <= 0 end
  572.             if b.isRat then return int_cmp(a*b.den, b.num) * b.den.sign <= 0 end
  573.         elseif a.isRat then
  574.             if b.isInt then return int_cmp(a.num, b*a.den) * a.den.sign <= 0 end
  575.             if b.isRat then return int_cmp(a.num*b.den, b.num*a.den) * a.den.sign*b.den.sign <= 0 end
  576.         end
  577.         return a:tonumber() <= b:tonumber()
  578.     end
  579.  
  580.     function mt.__band(a, b) return bn.band(a, b) end
  581.     function mt.__bor(a, b) return bn.bor(a, b) end
  582.     function mt.__bxor(a, b) return bn.bxor(a, b) end
  583.     function mt.__bnot(a) return bn.bnot(a) end
  584.     function mt.__shl(a, b) return bn.lshift(a, b) end
  585.     function mt.__shr(a, b) return bn.rshift(a, b) end
  586.  
  587. -- }}}
  588.  
  589. -- bn.Int {{{
  590.  
  591.     function bn.Int(n)
  592.         if type(n) == "table" then
  593.             if n.toInt then return n:toInt() end
  594.             local self = int_copy(n)
  595.             self.isInt = true
  596.             return setmetatable(self, mt)
  597.         else
  598.             local self = int(n)
  599.             self.isInt = true
  600.             return setmetatable(self, mt)
  601.         end
  602.     end
  603.  
  604.     bn.zero = bn.Int(0)
  605.     bn.one = bn.Int(1)
  606.     bn.two = bn.Int(2)
  607.  
  608.  
  609. -- }}}
  610.  
  611. -- bn.Rat {{{
  612.  
  613.     local rat_simpl
  614.  
  615.     function bn.Rat(num, den)
  616.         if not den then
  617.             if type(num) == "table" then
  618.                 if num.toRat then return num:toRat() end
  619.                 return bn.Int(num)
  620.             else
  621.                 return bn.Float(num):toRat()
  622.             end
  623.         else
  624.             local self = {num=bn.Int(num), den=bn.Int(den)}
  625.             assert(not int_iszero(self.den), "Division by zero")
  626.             if int_iszero(self.num) then return bn.zero end
  627.             if self.den.sign < 0 then
  628.                 self.num = -self.num
  629.                 self.den = -self.den
  630.             end
  631.             if int_isone(self.den) then return self.num end
  632.             rat_simpl(self)
  633.             if int_isone(self.den) then return self.num end
  634.             self.isRat = true
  635.             return setmetatable(self, mt)
  636.         end
  637.     end
  638.  
  639.     rat_simpl = function(a)
  640.         local num = a.num
  641.         local den = a.den
  642.         local gcd = bn.Int(int_gcd(num, den))
  643.         a.num = bn.Int(int_divmod(a.num, gcd))
  644.         a.den = bn.Int(int_divmod(a.den, gcd))
  645.     end
  646.  
  647. -- }}}
  648.  
  649. -- bn.Float {{{
  650.  
  651.     function bn.Float(n)
  652.         if type(n) == "table" then
  653.             if n.toFloat then return n:toFloat() end
  654.             error(string.format("Can not convert %s to Float", n))
  655.         else
  656.             if type(n) == "string" then
  657.                 n = string.gsub(n, "[ _]", "")
  658.             end
  659.             local self = {n=1.0*tonumber(n)}
  660.             self.isFloat = true
  661.             return setmetatable(self, mt)
  662.         end
  663.     end
  664.  
  665. -- }}}
  666.  
  667. -- math/mathx fonctions {{{
  668.  
  669.     bn.huge = bn.Float(math.huge)
  670.     bn.inf = bn.Float(math.inf)
  671.     bn.nan = bn.Float(math.nan)
  672.     bn.pi = bn.Float(math.pi)
  673.     bn.e = bn.Float(math.exp(1))
  674.  
  675.     function bn.abs(x)
  676.         if x.isInt then return bn.Int(int_abs(x)) end
  677.         if x.isRat then return bn.Rat(int_abs(x.num), int_abs(x.den)) end
  678.         return bn.Float(math.abs(x:tonumber()))
  679.     end
  680.     function bn.acos(x) return bn.Float(math.acos(x:tonumber())) end
  681.     function bn.acosh(x) return bn.Float(math.acosh(x:tonumber())) end
  682.     function bn.asin(x) return bn.Float(math.asin(x:tonumber())) end
  683.     function bn.asinh(x) return bn.Float(math.asinh(x:tonumber())) end
  684.     function bn.atan(x, y) return bn.Float(math.atan(x:tonumber(), y and y:tonumber())) end
  685.     function bn.atan2(y, x) return bn.Float(math.atan2(y:tonumber(), x:tonumber())) end
  686.     function bn.atanh(x) return bn.Float(math.atanh(x:tonumber())) end
  687.     function bn.ceil(x)
  688.         if x.isInt then return x end
  689.         if x.isRat then
  690.             local q, r = int_divmod(x.num, x.den)
  691.             if not int_iszero(r) then q = int_add(q, bn.one) end
  692.             return bn.Int(q)
  693.         end
  694.         return bn.Int(math.ceil(x:tonumber()))
  695.     end
  696.     function bn.copysign(x, y) --return bn.Float(math.copysign(x:tonumber(), y:tonumber())) end
  697.         if y >= bn.zero then return x else return -x end
  698.     end
  699.     function bn.cos(x) return bn.Float(math.cos(x:tonumber())) end
  700.     function bn.cosh(x) return bn.Float(math.cosh(x:tonumber())) end
  701.     function bn.deg(x) return bn.Float(math.deg(x:tonumber())) end
  702.     function bn.erf(x) return bn.Float(math.erf(x:tonumber())) end
  703.     function bn.erfc(x) return bn.Float(math.erfc(x:tonumber())) end
  704.     function bn.exp(x) return bn.Float(math.exp(x:tonumber())) end
  705.     function bn.exp2(x) return bn.Float(math.exp2(x:tonumber())) end
  706.     function bn.expm1(x) return bn.Float(math.expm1(x:tonumber())) end
  707.     function bn.fdim(x, y)
  708.         if x > y then return x-y end
  709.         return bn.zero
  710.     end
  711.     function bn.floor(x)
  712.         if x.isInt then return x end
  713.         if x.isRat then
  714.             local q, r = int_divmod(x.num, x.den)
  715.             return bn.Int(q)
  716.         end
  717.         return bn.Int(math.floor(x:tonumber()))
  718.     end
  719.     function bn.fma(x, y, z)
  720.         if x.isFloat or y.isFloat or z.isFloat then return bn.Float(math.fma(x:tonumber(), y:tonumber(), z:tonumber())) end
  721.         return x*y + z
  722.     end
  723.     function bn.fmax(x, y)
  724.         if x.isFloat or y.isFloat then return bn.Float(math.fmax(x:tonumber(), y:tonumber())) end
  725.         return bn.max(x, y)
  726.     end
  727.     function bn.fmin(x, y)
  728.         if x.isFloat or y.isFloat then return bn.Float(math.fmin(x:tonumber(), y:tonumber())) end
  729.         return bn.min(x, y)
  730.     end
  731.     function bn.fmod(x, y) return bn.Float(math.fmod(x:tonumber(), y:tonumber())) end
  732.     function bn.frexp(y) local mant, exp = math.frexp(y:tonumber()) return bn.Float(mant), bn.Int(exp) end
  733.     function bn.gamma(x) return bn.Float(math.gamma(x:tonumber())) end
  734.     function bn.hypot(x, y) return bn.Float(math.hypot(x:tonumber(), y:tonumber())) end
  735.     function bn.isfinite(x) if x.isFloat then return math.isfinite(x:tonumber()) else return true end end
  736.     function bn.isinf(x) if x.isFloat then return math.isinf(x:tonumber()) else return false end end
  737.     function bn.isnan(x) if x.isFloat then return math.isnan(x:tonumber()) else return false end end
  738.     function bn.isnormal(x) if x.isFloat then return math.isnormal(x:tonumber()) else return x ~= bn.zero end end
  739.     function bn.j0(x) return bn.Float(math.j0(x:tonumber())) end
  740.     function bn.j1(x) return bn.Float(math.j1(x:tonumber())) end
  741.     function bn.jn(x, y) return bn.Float(math.jn(x:tonumber(), y:tonumber())) end
  742.     function bn.ldexp(m, e)
  743.         if m.isFloat or e.isFloat then return bn.Float(math.ldexp(m:tonumber(), e:tonumber())) end
  744.         return m * bn.two^e
  745.     end
  746.     function bn.lgamma(x) return bn.Float(math.lgamma(x:tonumber())) end
  747.     function bn.log(x, base)
  748.         if base then return bn.Float(math.log(x:tonumber())/math.log(base)) end
  749.         return bn.Float(math.log(x:tonumber()))
  750.     end
  751.     function bn.log10(x) return bn.Float(math.log10(x:tonumber())) end
  752.     function bn.log1p(x) return bn.Float(math.log1p(x:tonumber())) end
  753.     function bn.log2(x) return bn.Float(math.log2(x:tonumber())) end
  754.     function bn.logb(x) return bn.Float(math.logb(x:tonumber())) end
  755.     function bn.max(x, ...)
  756.         for i, y in ipairs({...}) do
  757.             if y > x then
  758.                 x = y
  759.             end
  760.         end
  761.         return x
  762.     end
  763.     function bn.min(x, ...)
  764.         for i, y in ipairs({...}) do
  765.             if y < x then
  766.                 x = y
  767.             end
  768.         end
  769.         return x
  770.     end
  771.     function bn.modf(x)
  772.         if x.isInt then
  773.             return x, bn.zero
  774.         elseif x.isRat then
  775.             local q, r = int_divmod(x.num, x.den)
  776.             return bn.Int(q), bn.Rat(r, x.den)
  777.         else
  778.             local i, f = math.modf(x:tonumber())
  779.             return bn.Int(i), bn.Float(f)
  780.         end
  781.     end
  782.     function bn.nearbyint(x) return bn.Int(math.nearbyint(x:tonumber())) end
  783.     function bn.nextafter(x, y) return bn.Float(math.nextafter(x:tonumber(), y:tonumber())) end
  784.     function bn.pow(x, y) return x ^ y end
  785.     function bn.rad(x) return bn.Float(math.rad(x:tonumber())) end
  786.     function bn.remainder(x, y) return bn.Float(math.remainder(x:tonumber(), y:tonumber())) end
  787.     function bn.round(x) return bn.Float(math.round(x:tonumber())) end
  788.     function bn.scalbn(x, y) return bn.Float(math.scalbn(x:tonumber(), y:tonumber())) end
  789.     function bn.random(m, n)
  790.         if not m then return bn.Float(math.random()) end
  791.         if not n then return bn.Int(math.random(m:tonumber())) end
  792.         return bn.Int(math.random(m:tonumber(), n:tonumber()))
  793.     end
  794.     function bn.randomseed(x) math.randomseed(x:tonumber()) end
  795.     function bn.sin(x) return bn.Float(math.sin(x:tonumber())) end
  796.     function bn.sinh(x) return bn.Float(math.sinh(x:tonumber())) end
  797.     function bn.sqrt(x) return bn.Float(math.sqrt(x:tonumber())) end
  798.     function bn.cbrt(x) return bn.Float(math.cbrt(x:tonumber())) end
  799.     function bn.tan(x) return bn.Float(math.tan(x:tonumber())) end
  800.     function bn.tanh(x) return bn.Float(math.tanh(x:tonumber())) end
  801.     function bn.trunc(x) return bn.Float(math.trunc(x:tonumber())) end
  802.     function bn.y0(x) return bn.Float(math.y0(x:tonumber())) end
  803.     function bn.y1(x) return bn.Float(math.y1(x:tonumber())) end
  804.     function bn.yn(x, y) return bn.Float(math.yn(x:tonumber(), y:tonumber())) end
  805.  
  806.     function bn.hex(x, bits) return int_tostring(x, 16, bits) end
  807.     function bn.dec(x, bits) return int_tostring(x, 10, bits) end
  808.     function bn.oct(x, bits) return int_tostring(x, 8, bits) end
  809.     function bn.bin(x, bits) return int_tostring(x, 2, bits) end
  810.  
  811.     function bn.type(x)
  812.         if x.isInt then return "Integer" end
  813.         if x.isRat then return "Rational" end
  814.         return "Float"
  815.     end
  816.  
  817. -- }}}
  818.  
  819. -- bitwise operations {{{
  820.  
  821.     local bn_two_pow_32 = bn.Int(2^32)
  822.  
  823.     function bn.bnot(x, bits)
  824.         assert(x.isInt)
  825.         if bits == nil then
  826.             return -x-bn.one
  827.         else
  828.             local b = bn.two ^ bn.Int(bits)
  829.             x = x % b
  830.             return (b-bn.one-x) % b
  831.         end
  832.     end
  833.  
  834.     function bn.band(x, y, bits)
  835.         assert(x.isInt)
  836.         assert(y.isInt)
  837.         local z = bn.zero
  838.         local i = 0
  839.         local b = bn_two_pow_32
  840.         local nb_32bit = (bits ~= nil) and bits/32 or 1e308
  841.         while not x:iszero() and not y:iszero() and (i <= nb_32bit) do
  842.             local xd, yd
  843.             x, xd = bn.divmod(x, b)
  844.             y, yd = bn.divmod(y, b)
  845.             z = z + bn.Int(xd:tonumber() & yd:tonumber())*(b^bn.Int(i))
  846.             i = i + 1
  847.         end
  848.         if bits ~= nil then
  849.             z = z % (bn.two ^ bn.Int(bits))
  850.         end
  851.         return z
  852.     end
  853.  
  854.     function bn.bor(x, y, bits)
  855.         assert(x.isInt)
  856.         assert(y.isInt)
  857.         local z = bn.zero
  858.         local i = 0
  859.         local b = bn_two_pow_32
  860.         local nb_32bit = (bits ~= nil) and bits/32 or 1e308
  861.         while not x:iszero() or not y:iszero() and (i <= nb_32bit) do
  862.             local xd, yd
  863.             x, xd = bn.divmod(x, b)
  864.             y, yd = bn.divmod(y, b)
  865.             z = z + bn.Int(xd:tonumber() | yd:tonumber())*(b^bn.Int(i))
  866.             i = i + 1
  867.         end
  868.         if bits ~= nil then
  869.             z = z % (bn.two ^ bn.Int(bits))
  870.         end
  871.         return z
  872.     end
  873.  
  874.     function bn.bxor(x, y, bits)
  875.         assert(x.isInt)
  876.         assert(y.isInt)
  877.         local z = bn.zero
  878.         local i = 0
  879.         local b = bn_two_pow_32
  880.         local nb_32bit = (bits ~= nil) and bits/32 or 1e308
  881.         while not x:iszero() or not y:iszero() and (i <= nb_32bit) do
  882.             local xd, yd
  883.             x, xd = bn.divmod(x, b)
  884.             y, yd = bn.divmod(y, b)
  885.             z = z + bn.Int(xd:tonumber() ~ yd:tonumber())*(b^bn.Int(i))
  886.             i = i + 1
  887.         end
  888.         if bits ~= nil then
  889.             z = z % (bn.two ^ bn.Int(bits))
  890.         end
  891.         return z
  892.     end
  893.  
  894.     function bn.btest(x, y, bits)
  895.         return not bn.band(x, y, bits):iszero()
  896.     end
  897.  
  898.     function bn.extract(x, field, width)
  899.         assert(x.isInt)
  900.         if width == nil then width = 1 end
  901.         local shift = bn.two ^ bn.Int(field)
  902.         local mask = bn.two ^ bn.Int(width)
  903.         return bn.Int(x / shift) % mask
  904.     end
  905.  
  906.     function bn.replace(x, v, field, width)
  907.         assert(x.isInt)
  908.         assert(v.isInt)
  909.         if width == nil then width = 1 end
  910.         local shift = bn.two ^ bn.Int(field)
  911.         local mask = bn.two ^ bn.Int(width)
  912.         return x + (v - (bn.Int(x / shift) % mask)) * shift;
  913.     end
  914.  
  915.     function bn.lshift(x, disp)
  916.         assert(x.isInt)
  917.         if disp < 0 then return bn.rshift(x, -disp) end
  918.         return x * bn.two^bn.Int(disp)
  919.     end
  920.  
  921.     function bn.rshift(x, disp)
  922.         assert(x.isInt)
  923.         if disp < 0 then return bn.lshift(x, -disp) end
  924.         return bn.Int(x / bn.two^bn.Int(disp))
  925.     end
  926.  
  927.  
  928. -- }}}
  929.  
  930. end
  931.  
  932. return bn
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement