Updated to 1.10.0!

Check changes.md for what was done
This commit is contained in:
2018-05-31 22:48:14 -04:00
parent 67499cc5ba
commit a07fe49880
31 changed files with 6386 additions and 2131 deletions
@@ -0,0 +1,683 @@
RADIX = 10^7 ;
RADIX_LEN = math.floor( math.log10 ( RADIX ) ) ;
BigNum = {} ;
BigNum.mt = {} ;
function BigNum.new( num ) --{{{2
local bignum = {} ;
setmetatable( bignum , BigNum.mt ) ;
BigNum.change( bignum , num ) ;
return bignum ;
end
function BigNum.mt.sub( num1 , num2 )
local temp = BigNum.new() ;
local bnum1 = BigNum.new( num1 ) ;
local bnum2 = BigNum.new( num2 ) ;
BigNum.sub( bnum1 , bnum2 , temp ) ;
return temp ;
end
function BigNum.mt.mod( num1 , num2 )
return BigNum.new(num1 - (num1/num2)*num2)
end
function BigNum.mt.add( num1 , num2 )
local temp = BigNum.new() ;
local bnum1 = BigNum.new( num1 ) ;
local bnum2 = BigNum.new( num2 ) ;
BigNum.add( bnum1 , bnum2 , temp ) ;
return temp ;
end
function BigNum.mt.mul( num1 , num2 )
local temp = BigNum.new() ;
local bnum1 = BigNum.new( num1 ) ;
local bnum2 = BigNum.new( num2 ) ;
BigNum.mul( bnum1 , bnum2 , temp ) ;
return temp ;
end
function BigNum.mt.div( num1 , num2 )
local bnum1 = {} ;
local bnum2 = {} ;
local bnum3 = BigNum.new() ;
local bnum4 = BigNum.new() ;
bnum1 = BigNum.new( num1 ) ;
bnum2 = BigNum.new( num2 ) ;
BigNum.div( bnum1 , bnum2 , bnum3 , bnum4 ) ;
return bnum3 , bnum4 ;
end
function BigNum.mt.tostring( bnum )
local i = 0 ;
local j = 0 ;
local str = "" ;
local temp = "" ;
if bnum == nil then
return "nil" ;
elseif bnum.len > 0 then
for i = bnum.len - 2 , 0 , -1 do
for j = 0 , RADIX_LEN - string.len( bnum[i] ) - 1 do
temp = temp .. '0' ;
end
temp = temp .. bnum[i] ;
end
if bnum[bnum.len - 1]==nil then
return "nil"
end
temp = bnum[bnum.len - 1] .. temp ;
if bnum.signal == '-' then
temp = bnum.signal .. temp ;
end
return temp ;
else
return "" ;
end
end
function BigNum.mt.pow( num1 , num2 )
local bnum1 = BigNum.new( num1 ) ;
local bnum2 = BigNum.new( num2 ) ;
return BigNum.pow( bnum1 , bnum2 ) ;
end
function BigNum.mt.eq( num1 , num2 )
local bnum1 = BigNum.new( num1 ) ;
local bnum2 = BigNum.new( num2 ) ;
return BigNum.eq( bnum1 , bnum2 ) ;
end
function BigNum.mt.lt( num1 , num2 )
local bnum1 = BigNum.new( num1 ) ;
local bnum2 = BigNum.new( num2 ) ;
return BigNum.lt( bnum1 , bnum2 ) ;
end
function BigNum.mt.le( num1 , num2 )
local bnum1 = BigNum.new( num1 ) ;
local bnum2 = BigNum.new( num2 ) ;
return BigNum.le( bnum1 , bnum2 ) ;
end
function BigNum.mt.unm( num )
local ret = BigNum.new( num )
if ret.signal == '+' then
ret.signal = '-'
else
ret.signal = '+'
end
return ret
end
BigNum.mt.__metatable = "hidden"
BigNum.mt.__tostring = BigNum.mt.tostring ;
BigNum.mt.__add = BigNum.mt.add ;
BigNum.mt.__sub = BigNum.mt.sub ;
BigNum.mt.__mul = BigNum.mt.mul ;
BigNum.mt.__div = BigNum.mt.div ;
BigNum.mt.__pow = BigNum.mt.pow ;
BigNum.mt.__unm = BigNum.mt.unm ;
BigNum.mt.__mod = BigNum.mt.mod ;
BigNum.mt.__eq = BigNum.mt.eq ;
BigNum.mt.__le = BigNum.mt.le ;
BigNum.mt.__lt = BigNum.mt.lt ;
setmetatable( BigNum.mt, { __index = "inexistent field", __newindex = "not available", __metatable="hidden" } ) ;
function BigNum.add( bnum1 , bnum2 , bnum3 )
local maxlen = 0 ;
local i = 0 ;
local carry = 0 ;
local signal = '+' ;
local old_len = 0 ;
--Handle the signals
if bnum1 == nil or bnum2 == nil or bnum3 == nil then
error("Function BigNum.add: parameter nil") ;
elseif bnum1.signal == '-' and bnum2.signal == '+' then
bnum1.signal = '+' ;
BigNum.sub( bnum2 , bnum1 , bnum3 ) ;
if not rawequal(bnum1, bnum3) then
bnum1.signal = '-' ;
end
return 0 ;
elseif bnum1.signal == '+' and bnum2.signal == '-' then
bnum2.signal = '+' ;
BigNum.sub( bnum1 , bnum2 , bnum3 ) ;
if not rawequal(bnum2, bnum3) then
bnum2.signal = '-' ;
end
return 0 ;
elseif bnum1.signal == '-' and bnum2.signal == '-' then
signal = '-' ;
end
--
old_len = bnum3.len ;
if bnum1.len > bnum2.len then
maxlen = bnum1.len ;
else
maxlen = bnum2.len ;
bnum1 , bnum2 = bnum2 , bnum1 ;
end
--School grade sum
for i = 0 , maxlen - 1 do
if bnum2[i] ~= nil then
bnum3[i] = bnum1[i] + bnum2[i] + carry ;
else
bnum3[i] = bnum1[i] + carry ;
end
if bnum3[i] >= RADIX then
bnum3[i] = bnum3[i] - RADIX ;
carry = 1 ;
else
carry = 0 ;
end
end
--Update the answer's size
if carry == 1 then
bnum3[maxlen] = 1 ;
end
bnum3.len = maxlen + carry ;
bnum3.signal = signal ;
for i = bnum3.len, old_len do
bnum3[i] = nil ;
end
return 0 ;
end
function BigNum.sub( bnum1 , bnum2 , bnum3 )
local maxlen = 0 ;
local i = 0 ;
local carry = 0 ;
local old_len = 0 ;
if bnum1 == nil or bnum2 == nil or bnum3 == nil then
error("Function BigNum.sub: parameter nil") ;
elseif bnum1.signal == '-' and bnum2.signal == '+' then
bnum1.signal = '+' ;
BigNum.add( bnum1 , bnum2 , bnum3 ) ;
bnum3.signal = '-' ;
if not rawequal(bnum1, bnum3) then
bnum1.signal = '-' ;
end
return 0 ;
elseif bnum1.signal == '-' and bnum2.signal == '-' then
bnum1.signal = '+' ;
bnum2.signal = '+' ;
BigNum.sub( bnum2, bnum1 , bnum3 ) ;
if not rawequal(bnum1, bnum3) then
bnum1.signal = '-' ;
end
if not rawequal(bnum2, bnum3) then
bnum2.signal = '-' ;
end
return 0 ;
elseif bnum1.signal == '+' and bnum2.signal == '-' then
bnum2.signal = '+' ;
BigNum.add( bnum1 , bnum2 , bnum3 ) ;
if not rawequal(bnum2, bnum3) then
bnum2.signal = '-' ;
end
return 0 ;
end
--Tests if bnum2 > bnum1
if BigNum.compareAbs( bnum1 , bnum2 ) == 2 then
BigNum.sub( bnum2 , bnum1 , bnum3 ) ;
bnum3.signal = '-' ;
return 0 ;
else
maxlen = bnum1.len ;
end
old_len = bnum3.len ;
bnum3.len = 0 ;
--School grade subtraction
for i = 0 , maxlen - 1 do
if bnum2[i] ~= nil then
bnum3[i] = bnum1[i] - bnum2[i] - carry ;
else
bnum3[i] = bnum1[i] - carry ;
end
if bnum3[i] < 0 then
bnum3[i] = RADIX + bnum3[i] ;
carry = 1 ;
else
carry = 0 ;
end
if bnum3[i] ~= 0 then
bnum3.len = i + 1 ;
end
end
bnum3.signal = '+' ;
--Check if answer's size if zero
if bnum3.len == 0 then
bnum3.len = 1 ;
bnum3[0] = 0 ;
end
if carry == 1 then
error( "Error in function sub" ) ;
end
for i = bnum3.len , max( old_len , maxlen - 1 ) do
bnum3[i] = nil ;
end
return 0 ;
end
function BigNum.mul( bnum1 , bnum2 , bnum3 )
local i = 0 ; j = 0 ;
local temp = BigNum.new( ) ;
local temp2 = 0 ;
local carry = 0 ;
local oldLen = bnum3.len ;
if bnum1 == nil or bnum2 == nil or bnum3 == nil then
error("Function BigNum.mul: parameter nil") ;
--Handle the signals
elseif bnum1.signal ~= bnum2.signal then
BigNum.mul( bnum1 , -bnum2 , bnum3 ) ;
bnum3.signal = '-' ;
return 0 ;
end
bnum3.len = ( bnum1.len ) + ( bnum2.len ) ;
--Fill with zeros
for i = 1 , bnum3.len do
bnum3[i - 1] = 0 ;
end
--Places nil where passes through this
for i = bnum3.len , oldLen do
bnum3[i] = nil ;
end
--School grade multiplication
for i = 0 , bnum1.len - 1 do
for j = 0 , bnum2.len - 1 do
carry = ( bnum1[i] * bnum2[j] + carry ) ;
carry = carry + bnum3[i + j] ;
bnum3[i + j] = ( carry % RADIX ) ;
temp2 = bnum3[i + j] ;
carry = math.floor ( carry / RADIX ) ;
end
if carry ~= 0 then
bnum3[i + bnum2.len] = carry ;
end
carry = 0 ;
end
--Update the answer's size
for i = bnum3.len - 1 , 1 , -1 do
if bnum3[i] ~= nil and bnum3[i] ~= 0 then
break ;
else
bnum3[i] = nil ;
end
bnum3.len = bnum3.len - 1 ;
end
return 0 ;
end
function BigNum.div( bnum1 , bnum2 , bnum3 , bnum4 )
local temp = BigNum.new() ;
local temp2 = BigNum.new() ;
local one = BigNum.new( "1" ) ;
local zero = BigNum.new( "0" ) ;
--Check division by zero
if BigNum.compareAbs( bnum2 , zero ) == 0 then
error( "Function BigNum.div: Division by zero" ) ;
end
--Handle the signals
if bnum1 == nil or bnum2 == nil or bnum3 == nil or bnum4 == nil then
error( "Function BigNum.div: parameter nil" ) ;
elseif bnum1.signal == "+" and bnum2.signal == "-" then
bnum2.signal = "+" ;
BigNum.div( bnum1 , bnum2 , bnum3 , bnum4 ) ;
bnum2.signal = "-" ;
bnum3.signal = "-" ;
return 0 ;
elseif bnum1.signal == "-" and bnum2.signal == "+" then
bnum1.signal = "+" ;
BigNum.div( bnum1 , bnum2 , bnum3 , bnum4 ) ;
bnum1.signal = "-" ;
if bnum4 < zero then --Check if remainder is negative
BigNum.add( bnum3 , one , bnum3 ) ;
BigNum.sub( bnum2 , bnum4 , bnum4 ) ;
end
bnum3.signal = "-" ;
return 0 ;
elseif bnum1.signal == "-" and bnum2.signal == "-" then
bnum1.signal = "+" ;
bnum2.signal = "+" ;
BigNum.div( bnum1 , bnum2 , bnum3 , bnum4 ) ;
bnum1.signal = "-" ;
if bnum4 < zero then --Check if remainder is negative
BigNum.add( bnum3 , one , bnum3 ) ;
BigNum.sub( bnum2 , bnum4 , bnum4 ) ;
end
bnum2.signal = "-" ;
return 0 ;
end
temp.len = bnum1.len - bnum2.len - 1 ;
--Reset variables
BigNum.change( bnum3 , "0" ) ;
BigNum.change( bnum4 , "0" ) ;
BigNum.copy( bnum1 , bnum4 ) ;
--Check if can continue dividing
while( BigNum.compareAbs( bnum4 , bnum2 ) ~= 2 ) do
if bnum4[bnum4.len - 1] >= bnum2[bnum2.len - 1] then
BigNum.put( temp , math.floor( bnum4[bnum4.len - 1] / bnum2[bnum2.len - 1] ) , bnum4.len - bnum2.len ) ;
temp.len = bnum4.len - bnum2.len + 1 ;
else
BigNum.put( temp , math.floor( ( bnum4[bnum4.len - 1] * RADIX + bnum4[bnum4.len - 2] ) / bnum2[bnum2.len -1] ) , bnum4.len - bnum2.len - 1 ) ;
temp.len = bnum4.len - bnum2.len ;
end
if bnum4.signal ~= bnum2.signal then
temp.signal = "-";
else
temp.signal = "+";
end
BigNum.add( temp , bnum3 , bnum3 ) ;
temp = temp * bnum2 ;
BigNum.sub( bnum4 , temp , bnum4 ) ;
end
--Update if the remainder is negative
if bnum4.signal == '-' then
decr( bnum3 ) ;
BigNum.add( bnum2 , bnum4 , bnum4 ) ;
end
return 0 ;
end
function BigNum.pow( bnum1 , bnum2 )
local n = BigNum.new( bnum2 ) ;
local y = BigNum.new( 1 ) ;
local z = BigNum.new( bnum1 ) ;
local zero = BigNum.new( "0" ) ;
if bnum2 < zero then
error( "Function BigNum.exp: domain error" ) ;
elseif bnum2 == zero then
return y ;
end
while 1 do
if ( n[0] % 2 ) == 0 then
n = n / 2 ;
else
n = n / 2 ;
y = z * y ;
if n == zero then
return y ;
end
end
z = z * z ;
end
end
-- Português :
BigNum.exp = BigNum.pow
function BigNum.gcd( bnum1 , bnum2 )
local a = {} ;
local b = {} ;
local c = {} ;
local d = {} ;
local zero = {} ;
zero = BigNum.new( "0" ) ;
if bnum1 == zero or bnum2 == zero then
return BigNum.new( "1" ) ;
end
a = BigNum.new( bnum1 ) ;
b = BigNum.new( bnum2 ) ;
a.signal = '+' ;
b.signal = '+' ;
c = BigNum.new() ;
d = BigNum.new() ;
while b > zero do
BigNum.div( a , b , c , d ) ;
a , b , d = b , d , a ;
end
return a ;
end
-- Português:
BigNum.mmc = BigNum.gcd
function BigNum.eq( bnum1 , bnum2 )
if BigNum.compare( bnum1 , bnum2 ) == 0 then
return true ;
else
return false ;
end
end
function BigNum.lt( bnum1 , bnum2 )
if BigNum.compare( bnum1 , bnum2 ) == 2 then
return true ;
else
return false ;
end
end
function BigNum.le( bnum1 , bnum2 )
local temp = -1 ;
temp = BigNum.compare( bnum1 , bnum2 )
if temp == 0 or temp == 2 then
return true ;
else
return false ;
end
end
function BigNum.compareAbs( bnum1 , bnum2 )
if bnum1 == nil or bnum2 == nil then
error("Function compare: parameter nil") ;
elseif bnum1.len > bnum2.len then
return 1 ;
elseif bnum1.len < bnum2.len then
return 2 ;
else
local i ;
for i = bnum1.len - 1 , 0 , -1 do
if bnum1[i] > bnum2[i] then
return 1 ;
elseif bnum1[i] < bnum2[i] then
return 2 ;
end
end
end
return 0 ;
end
function BigNum.compare( bnum1 , bnum2 )
local signal = 0 ;
if bnum1 == nil or bnum2 == nil then
error("Funtion BigNum.compare: parameter nil") ;
elseif bnum1.signal == '+' and bnum2.signal == '-' then
return 1 ;
elseif bnum1.signal == '-' and bnum2.signal == '+' then
return 2 ;
elseif bnum1.signal == '-' and bnum2.signal == '-' then
signal = 1 ;
end
if bnum1.len > bnum2.len then
return 1 + signal ;
elseif bnum1.len < bnum2.len then
return 2 - signal ;
else
local i ;
for i = bnum1.len - 1 , 0 , -1 do
if bnum1[i] > bnum2[i] then
return 1 + signal ;
elseif bnum1[i] < bnum2[i] then
return 2 - signal ;
end
end
end
return 0 ;
end
function BigNum.copy( bnum1 , bnum2 )
if bnum1 ~= nil and bnum2 ~= nil then
local i ;
for i = 0 , bnum1.len - 1 do
bnum2[i] = bnum1[i] ;
end
bnum2.len = bnum1.len ;
else
error("Function BigNum.copy: parameter nil") ;
end
end
function BigNum.change( bnum1 , num )
local j = 0 ;
local len = 0 ;
local num = num ;
local l ;
local oldLen = 0 ;
if bnum1 == nil then
error( "BigNum.change: parameter nil" ) ;
elseif type( bnum1 ) ~= "table" then
error( "BigNum.change: parameter error, type unexpected" ) ;
elseif num == nil then
bnum1.len = 1 ;
bnum1[0] = 0 ;
bnum1.signal = "+";
elseif type( num ) == "table" and num.len ~= nil then --check if num is a big number
--copy given table to the new one
for i = 0 , num.len do
bnum1[i] = num[i] ;
end
if num.signal ~= '-' and num.signal ~= '+' then
bnum1.signal = '+' ;
else
bnum1.signal = num.signal ;
end
oldLen = bnum1.len ;
bnum1.len = num.len ;
elseif type( num ) == "string" or type( num ) == "number" then
if string.sub( num , 1 , 1 ) == '+' or string.sub( num , 1 , 1 ) == '-' then
bnum1.signal = string.sub( num , 1 , 1 ) ;
num = string.sub(num, 2) ;
else
bnum1.signal = '+' ;
end
num = string.gsub( num , " " , "" ) ;
local sf = string.find( num , "e" ) ;
--Handles if the number is in exp notation
if sf ~= nil then
num = string.gsub( num , "%." , "" ) ;
local e = string.sub( num , sf + 1 ) ;
e = tonumber(e) ;
if e ~= nil and e > 0 then
e = tonumber(e) ;
else
error( "Function BigNum.change: string is not a valid number" ) ;
end
num = string.sub( num , 1 , sf - 2 ) ;
for i = string.len( num ) , e do
num = num .. "0" ;
end
else
sf = string.find( num , "%." ) ;
if sf ~= nil then
num = string.sub( num , 1 , sf - 1 ) ;
end
end
l = string.len( num ) ;
oldLen = bnum1.len ;
if (l > RADIX_LEN) then
local mod = l-( math.floor( l / RADIX_LEN ) * RADIX_LEN ) ;
for i = 1 , l-mod, RADIX_LEN do
bnum1[j] = tonumber( string.sub( num, -( i + RADIX_LEN - 1 ) , -i ) );
--Check if string dosn't represents a number
if bnum1[j] == nil then
error( "Function BigNum.change: string is not a valid number" ) ;
bnum1.len = 0 ;
return 1 ;
end
j = j + 1 ;
len = len + 1 ;
end
if (mod ~= 0) then
bnum1[j] = tonumber( string.sub( num , 1 , mod ) ) ;
bnum1.len = len + 1 ;
else
bnum1.len = len ;
end
--Eliminate trailing zeros
for i = bnum1.len - 1 , 1 , -1 do
if bnum1[i] == 0 then
bnum1[i] = nil ;
bnum1.len = bnum1.len - 1 ;
else
break ;
end
end
else
-- string.len(num) <= RADIX_LEN
bnum1[j] = tonumber( num ) ;
bnum1.len = 1 ;
end
else
error( "Function BigNum.change: parameter error, type unexpected" ) ;
end
--eliminates the deprecated higher order 'algarisms'
if oldLen ~= nil then
for i = bnum1.len , oldLen do
bnum1[i] = nil ;
end
end
return 0 ;
end
function BigNum.put( bnum , int , pos )
if bnum == nil then
error("Function BigNum.put: parameter nil") ;
end
local i = 0 ;
for i = 0 , pos - 1 do
bnum[i] = 0 ;
end
bnum[pos] = int ;
for i = pos + 1 , bnum.len do
bnum[i] = nil ;
end
bnum.len = pos ;
return 0 ;
end
--printraw{{{2
function printraw( bnum )
local i = 0 ;
if bnum == nil then
error( "Function printraw: parameter nil" ) ;
end
while 1 == 1 do
if bnum[i] == nil then
io.write( ' len '..bnum.len ) ;
if i ~= bnum.len then
io.write( ' ERRO!!!!!!!!' ) ;
end
io.write( "\n" ) ;
return 0 ;
end
io.write( 'r'..bnum[i] ) ;
i = i + 1 ;
end
end
--max{{{2
function max( int1 , int2 )
if int1 > int2 then
return int1 ;
else
return int2 ;
end
end
--decr{{{2
function decr( bnum1 )
local temp = {} ;
temp = BigNum.new( "1" ) ;
BigNum.sub( bnum1 , temp , bnum1 ) ;
return 0 ;
end
@@ -0,0 +1,227 @@
require( "bin.numbers.BigNum" ) ;
BigRat = {} ;
BigRat.mt = {} ;
function BigRat.new( num1 , num2 ) --{{{2
local bigrat = {} ;
local f ;
setmetatable(bigrat, BigRat.mt) ;
if type( num1 ) == "table" then
if num1.num ~= nil and num1.den ~= nil then
bigrat.num = BigNum.new( num1.num ) ;
bigrat.den = BigNum.new( num1.den ) ;
else
bigrat.num = BigNum.new( num1 ) ;
bigrat.den = BigNum.new( "1" ) ;
end
elseif num1 ~= nil then
if num2 == nil then
bigrat.den = BigNum.new( "1" ) ;
else
bigrat.den = BigNum.new( num2 ) ;
end
bigrat.num = BigNum.new( num1 ) ;
else
bigrat.den = BigNum.new( ) ;
bigrat.num = BigNum.new( ) ;
end
--Update the signals
if bigrat.den.signal == "-" then
if bigrat.num.signal == "-" then
bigrat.num.signal = "+" ;
else
bigrat.num.signal = "-" ;
end
bigrat.den.signal = "+" ;
end
return bigrat ;
end
function BigRat.mt.sub( num1 , num2 )
local temp = BigRat.new() ;
local brat1 = BigRat.new( num1 ) ;
local brat2 = BigRat.new( num2 ) ;
BigRat.sub( brat1 , brat2 , temp ) ;
return temp ;
end
function BigRat.mt.add( num1 , num2 )
local temp = BigRat.new() ;
local brat1 = BigRat.new( num1 ) ;
local brat2 = BigRat.new( num2 ) ;
BigRat.add( brat1 , brat2 , temp ) ;
return temp ;
end
function BigRat.mt.mul( num1 , num2 )
local temp = BigRat.new() ;
local brat1 = BigRat.new( num1 ) ;
local brat2 = BigRat.new( num2 ) ;
BigRat.mul( brat1 , brat2 , temp ) ;
return temp ;
end
function BigRat.mt.div( num1 , num2 )
local brat1 = BigRat.new( num1 ) ;
local brat2 = BigRat.new( num2 ) ;
local brat3 = BigRat.new() ;
local brat4 = BigRat.new() ;
BigRat.div( brat1 , brat2 , brat3 , brat4 ) ;
return brat3 , brat4 ;
end
function BigRat.mt.tostring( brat )
BigRat.simplify( brat ) ;
return BigNum.mt.tostring( brat.num ) .. " / " .. BigNum.mt.tostring( brat.den ) ;
end
function BigRat.mt.pow ( num1 , num2 )
local brat1 = BigRat.new( num1 ) ;
local brat2 = BigRat.new( num2 ) ;
return BigRat.pow( brat1 , brat2 )
end
function BigRat.mt.eq ( num1 , num2 )
return BigRat.eq( num1 , num2 )
end
function BigRat.mt.lt ( num1 , num2 )
return BigRat.lt( num1 , num2 )
end
function BigRat.mt.le ( num1 , num2 )
return BigRat.le( num1 , num2 )
end
function BigRat.mt.unm ( num )
local ret = BigRat.new( num )
if ret.num.signal == '-' then
ret.num.signal = '+'
else
ret.num.signal = '-'
end
return ret
end
BigRat.mt.__metatable = "hidden"
BigRat.mt.__tostring = BigRat.mt.tostring
BigRat.mt.__add = BigRat.mt.add
BigRat.mt.__sub = BigRat.mt.sub
BigRat.mt.__mul = BigRat.mt.mul
BigRat.mt.__div = BigRat.mt.div
BigRat.mt.__pow = BigRat.mt.pow
BigRat.mt.__unm = BigRat.mt.unm
BigRat.mt.__eq = BigRat.mt.eq
BigRat.mt.__le = BigRat.mt.le
BigRat.mt.__lt = BigRat.mt.lt
setmetatable( BigRat.mt, { __index = "inexistent field", __newindex = "not available", __metatable="hidden" } ) ;
function BigRat.add( brat1 , brat2 , brat3 )
brat3.den = brat1.den * brat2.den ;
brat3.num = ( brat1.num * brat2.den ) + ( brat2.num * brat1.den ) ;
return brat3 ;
end
function BigRat.sub( brat1 , brat2 , brat3 )
brat3.den = brat1.den * brat2.den ;
brat3.num = ( brat1.num * brat2.den ) - ( brat2.num * brat1.den ) ;
return brat3 ;
end
function BigRat.mul( brat1 , brat2 , brat3 )
brat3.num = brat1.num * brat2.num ;
brat3.den = brat1.den * brat2.den ;
return 0 ;
end
function BigRat.div( brat1 , brat2 , brat3 )
brat3.num = brat1.num * brat2.den ;
brat3.den = brat1.den * brat2.num ;
return brat3 ;
end
function BigRat.pow( bnum1 , bnum2 )
if bnum1 == nil or bnum2 == nil then
error( "Function BigRat.pow: parameter nil" ) ;
end
local x = BigRat.new( "8" ) ;
local n = BigRat.new( bnum2.den ) ;
local n2 ;
local y = BigRat.new( ) ;
local i ;
local temp = BigRat.new( ) ;
BigRat.simplify( bnum2 ) ;
temp.num = BigNum.exp( bnum1.num , bnum2.num ) ;
temp.den = BigNum.exp( bnum1.den , bnum2.num ) ;
n2 = n - 1 ;
for i = 0 , 4 do
y.num = x.num ^ n2.num ;
y.den = x.den ^ n2.num ;
x = (( temp / y ) + ( n2 * x )) / n ;
end
return x ;
end
function BigRat.simplify( brat )
if brat == nil then
error( "Function BigRat.simplify: parameter nil" ) ;
end
local gcd = BigNum.new( ) ;
local temp = BigRat.new( brat ) ;
local devnull = BigNum.new( ) ;
local zero = BigNum.new( "0" ) ;
--Check if numerator is zero
if BigNum.compareAbs( brat.num , zero ) == 0 then
brat.den = BigNum.new( "1" ) ;
return 0 ;
end
gcd = BigNum.gcd( brat.num , brat.den ) ;
BigNum.div( temp.num , gcd , brat.num , devnull ) ;
BigNum.div( temp.den , gcd , brat.den , devnull ) ;
--Update the signal
if brat.num.signal == '-' and brat.den.signal == '-' then
brat.num.signal = '+' ;
brat.den.signal = '+' ;
end
return 0 ;
end
function BigRat.eq( brat1 , brat2 )
if BigRat.compare( brat1 , brat2 ) == 0 then
return true ;
else
return false ;
end
end
function BigRat.lt( brat1 , brat2 )
if BigRat.compare( brat1 , brat2 ) == 2 then
return true ;
else
return false ;
end
end
function BigRat.le( brat1 , brat2 )
local temp = -1 ;
temp = BigRat.compare( brat1 , brat2 )
if temp == 0 or temp == 2 then
return true ;
else
return false ;
end
end
function BigRat.compare( bnum1 , bnum2 )
local temp ;
temp = bnum1 - bnum2 ;
if temp.num[0] == 0 and temp.num.len == 1 then --Check if is zero
return 0 ;
elseif temp.num.signal == "-" then
return 2 ;
else
return 1 ;
end
end
@@ -0,0 +1,191 @@
local bits={}
bits.data=''
bits.t='bits'
bits.Type='bits'
bits.__index = bits
bits.__tostring=function(self) return self.data end
bits.__len=function(self) return (#self.data)/8 end
local floor,insert = math.floor, table.insert
function bits.newBitBuffer(n)
--
end
function bits.newConverter(bitsIn,bitsOut)
local c={}
--
end
function basen(n,b)
if not b or b == 10 then return tostring(n) end
local digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
local t = {}
local sign = ""
if n < 0 then
sign = "-"
n = -n
end
repeat
local d = n % b + 1
n = n / b
insert(t, 1, digits:sub(d,d))
until n == 0
return sign .. table.concat(t,"")
end
bits.ref={}
function bits.newByte(d)
local c={}
if type(d)=="string" then
if #d>1 or #d<1 then
error("A byte must be one character!")
else
c.data=string.byte(d)
end
elseif type(d)=="number" then
if d>255 or d<0 then
error("A byte must be between 0 and 255!")
else
c.data=d
end
else
error("cannot use type "..type(d).." as an argument! Takes only strings or numbers!")
end
c.__index=function(self,k)
if k>=0 and k<9 then
if self.data==0 then
return 0
elseif self.data==255 then
return 1
else
return bits.ref[self.data][k]
end
end
end
c.__tostring=function(self)
return bits.ref[tostring(self.data)]
end
setmetatable(c,c)
return c
end
function bits.newByteArray(s)
local c={}
if type(s)~="string" then
error("Must be a string type or bin/buffer type")
elseif type(s)=="table" then
if s.t=="sink" or s.t=="buffer" or s.t=="bin" then
local data=s:getData()
for i=1,#data do
c[#c+1]=bits.newByte(data:sub(i,i))
end
else
error("Must be a string type or bin/buffer type")
end
else
for i=1,#s do
c[#c+1]=bits.newByte(s:sub(i,i))
end
end
return c
end
function bits.new(n,binary)
local temp={}
temp.t="bits"
temp.Type="bits"
if type(n)=="string" then
if binary then
temp.data=n:match("[10]+")
else
local t={}
for i=#n,1,-1 do
table.insert(t,bits:conv(string.byte(n,i)))
end
temp.data=table.concat(t)
end
elseif type(n)=="number" or type(n)=="table" then
temp.data=basen(n,2)
end
if #temp.data%8~=0 then
temp.data=string.rep('0',8-#temp.data%8)..temp.data
end
setmetatable(temp, bits)
return temp
end
for i=0,255 do
local d=bits.new(i).data
bits.ref[i]={d:match("(%d)(%d)(%d)(%d)(%d)(%d)(%d)(%d)")}
bits.ref[tostring(i)]=d
bits.ref[d]=i
bits.ref["\255"..string.char(i)]=d
end
function bits.numToBytes(n,fit,func)
local num=string.reverse(bits.new(n):toSbytes())
local ref={["num"]=num,["fit"]=fit}
if fit then
if fit<#num then
if func then
print("Warning: attempting to store a number that takes up more space than allotted! Using provided method!")
func(ref)
else
print("Warning: attempting to store a number that takes up more space than allotted!")
end
return ref.num:sub(1,ref.fit)
elseif fit==#num then
return string.reverse(num)
else
return string.reverse(string.rep("\0",fit-#num)..num)
end
else
return string.reverse(num)
end
end
function bits:conv(n)
local tab={}
while n>=1 do
table.insert(tab,n%2)
n=math.floor(n/2)
end
local str=string.reverse(table.concat(tab))
if #str%8~=0 or #str==0 then
str=string.rep('0',8-#str%8)..str
end
return str
end
function bits:tonumber(s,e)
if s==0 then
return tonumber(self.data,2)
end
s=s or 1
return tonumber(string.sub(self.data,(8*(s-1))+1,8*s),2) or error('Bounds!')
end
function bits:isover()
return #self.data>8
end
function bits:flipbits()
tab={}
for i=1,#self.data do
if string.sub(self.data,i,i)=='1' then
table.insert(tab,'0')
else
table.insert(tab,'1')
end
end
self.data=table.concat(tab)
end
function bits:tobytes()
local tab={}
for i=self:getbytes(),1,-1 do
table.insert(tab,string.char(self:tonumber(i)))
end
return bin.new(table.concat(tab))
end
function bits:toSbytes()
local tab={}
for i=self:getbytes(),1,-1 do
table.insert(tab,string.char(self:tonumber(i)))
end
return table.concat(tab)
end
function bits:getBin()
return self.data
end
function bits:getbytes()
return #self.data/8
end
return bits
@@ -0,0 +1,244 @@
local binNum=require("bin.numbers.BigNum")
local infinabits={}
infinabits.data=''
infinabits.t='infinabits'
infinabits.Type='infinabits'
infinabits.__index = infinabits
infinabits.__tostring=function(self) return self.data end
infinabits.__len=function(self) return (#self.data)/8 end
local floor,insert = math.floor, table.insert
function basen(n,b)
n=BigNum.new(n)
if not b or b == 10 then return tostring(n) end
local digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
local t = {}
local sign = ""
if n < BigNum.new(0) then
sign = "-"
n = -n
end
repeat
local d = tonumber(tostring(n % b)) + 1
n = n / b
insert(t, 1, digits:sub(d,d))
until n == BigNum.new(0)
return sign .. table.concat(t,"")
end
function base2to10(num)
local n=BigNum.new(0)
for i = #num-1,0,-1 do
nn=BigNum.new(num:sub(i+1,i+1))*(BigNum.new(2)^((#num-i)-1))
n=n+nn
end
return n
end
function infinabits.newBitBuffer(n)
-- WIP
end
function infinabits.newConverter(bitsIn,bitsOut)
local c={}
-- WIP
end
infinabits.ref={}
function infinabits.newByte(d)-- WIP
local c={}
if type(d)=="string" then
if #d>1 or #d<1 then
error("A byte must be one character!")
else
c.data=string.byte(d)
end
elseif type(d)=="number" then
if d>255 or d<0 then
error("A byte must be between 0 and 255!")
else
c.data=d
end
else
error("cannot use type "..type(d).." as an argument! Takes only strings or numbers!")
end
c.__index=function(self,k)
if k>=0 and k<9 then
if self.data==0 then
return 0
elseif self.data==255 then
return 1
else
return infinabits.ref[self.data][k]
end
end
end
c.__tostring=function(self)
return infinabits.ref[tostring(self.data)]
end
setmetatable(c,c)
return c
end
function infinabits.newByteArray(s)-- WIP
local c={}
if type(s)~="string" then
error("Must be a string type or bin/buffer type")
elseif type(s)=="table" then
if s.t=="sink" or s.t=="buffer" or s.t=="bin" then
local data=s:getData()
for i=1,#data do
c[#c+1]=infinabits.newByte(data:sub(i,i))
end
else
error("Must be a string type or bin/buffer type")
end
else
for i=1,#s do
c[#c+1]=infinabits.newByte(s:sub(i,i))
end
end
return c
end
function infinabits.new(n,binary)
local temp={}
temp.t="infinabits"
temp.Type="infinabits"
if type(n)=="string" then
if binary then
temp.data=n:match("[10]+")
else
local t={}
for i=#n,1,-1 do
table.insert(t,infinabits:conv(string.byte(n,i)))
end
temp.data=table.concat(t)
end
elseif type(n)=="number" or type(n)=="table" then
temp.data=basen(tostring(n),2)
end
if #temp.data%8~=0 then
temp.data=string.rep('0',8-#temp.data%8)..temp.data
end
setmetatable(temp, infinabits)
return temp
end
for i=0,255 do
local d=infinabits.new(i).data
infinabits.ref[i]={d:match("(%d)(%d)(%d)(%d)(%d)(%d)(%d)(%d)")}
infinabits.ref[tostring(i)]=d
infinabits.ref[d]=i
infinabits.ref["\255"..string.char(i)]=d
end
function infinabits.numToBytes(n,fit,func)
local num=string.reverse(infinabits.new(BigNum.new(n)):toSbytes())
local ref={["num"]=num,["fit"]=fit}
if fit then
if fit<#num then
if func then
print("Warning: attempting to store a number that takes up more space than allotted! Using provided method!")
func(ref)
else
print("Warning: attempting to store a number that takes up more space than allotted!")
end
return ref.num:sub(1,ref.fit)
elseif fit==#num then
return string.reverse(num)
else
return string.reverse(string.rep("\0",fit-#num)..num)
end
else
return string.reverse(num)
end
end
function infinabits.numToBytes(n,fit,fmt,func)
if fmt=="%e" then
local num=string.reverse(infinabits.new(BigNum.new(n)):toSbytes())
local ref={["num"]=num,["fit"]=fit}
if fit then
if fit<#num then
if func then
print("Warning: attempting to store a number that takes up more space than allotted! Using provided method!")
func(ref)
else
print("Warning: attempting to store a number that takes up more space than allotted!")
end
return ref.num:sub(1,ref.fit)
elseif fit==#num then
return num
else
return string.rep("\0",fit-#num)..num
end
else
return num
end
else
local num=string.reverse(infinabits.new(BigNum.new(n)):toSbytes())
local ref={["num"]=num,["fit"]=fit}
if fit then
if fit<#num then
if func then
print("Warning: attempting to store a number that takes up more space than allotted! Using provided method!")
func(ref)
else
print("Warning: attempting to store a number that takes up more space than allotted!")
end
return ref.num:sub(1,ref.fit)
elseif fit==#num then
return string.reverse(num)
else
return string.reverse(string.rep("\0",fit-#num)..num)
end
else
return string.reverse(num)
end
end
end
function infinabits:conv(n)
local tab={}
local one=BigNum.new(1)
local n=BigNum.new(n)
while n>=one do
table.insert(tab,tonumber(tostring(n%2)))
n=n/2
end
local str=string.reverse(table.concat(tab))
if #str%8~=0 or #str==0 then
str=string.rep('0',8-#str%8)..str
end
return str
end
function infinabits:tonumber(s)
if s==0 then
return tonumber(self.data,2)
end
s=s or 1
return tonumber(tostring(base2to10(string.sub(self.data,(8*(s-1))+1,8*s)))) or error('Bounds!')
end
function infinabits:isover()
return #self.data>8
end
function infinabits:flipbits()
tab={}
local s=self.data
s=s:gsub("1","_")
s=s:gsub("0","1")
s=s:gsub("_","0")
self.data=s
end
function infinabits:tobytes()
local tab={}
for i=self:getbytes(),1,-1 do
table.insert(tab,string.char(self:tonumber(i)))
end
return bin.new(table.concat(tab))
end
function infinabits:toSbytes()
local tab={}
for i=self:getbytes(),1,-1 do
table.insert(tab,string.char(self:tonumber(i)))
end
return table.concat(tab)
end
function infinabits:getBin()
return self.data
end
function infinabits:getbytes()
return #self.data/8
end
return infinabits
@@ -0,0 +1,333 @@
--[[
LICENSE
(c) 2008-2011 David Manura. Licensed under the same terms as Lua (MIT).
--]]
local M = {_TYPE='module', _NAME='bit.numberlua', _VERSION='0.3.1.20120131'}
local floor = math.floor
local MOD = 2^32
local MODM = MOD-1
local function memoize(f)
local mt = {}
local t = setmetatable({}, mt)
function mt:__index(k)
local v = f(k); t[k] = v
return v
end
return t
end
local function make_bitop_uncached(t, m)
local function bitop(a, b)
local res,p = 0,1
while a ~= 0 and b ~= 0 do
local am, bm = a%m, b%m
res = res + t[am][bm]*p
a = (a - am) / m
b = (b - bm) / m
p = p*m
end
res = res + (a+b)*p
return res
end
return bitop
end
local function make_bitop(t)
local op1 = make_bitop_uncached(t,2^1)
local op2 = memoize(function(a)
return memoize(function(b)
return op1(a, b)
end)
end)
return make_bitop_uncached(op2, 2^(t.n or 1))
end
-- ok? probably not if running on a 32-bit int Lua number type platform
function M.tobit(x)
return x % 2^32
end
M.bxor = make_bitop {[0]={[0]=0,[1]=1},[1]={[0]=1,[1]=0}, n=4}
local bxor = M.bxor
function M.bnot(a) return MODM - a end
local bnot = M.bnot
function M.band(a,b) return ((a+b) - bxor(a,b))/2 end
local band = M.band
function M.bor(a,b) return MODM - band(MODM - a, MODM - b) end
local bor = M.bor
local lshift, rshift -- forward declare
function M.rshift(a,disp) -- Lua5.2 insipred
if disp < 0 then return lshift(a,-disp) end
return floor(a % 2^32 / 2^disp)
end
rshift = M.rshift
function M.lshift(a,disp) -- Lua5.2 inspired
if disp < 0 then return rshift(a,-disp) end
return (a * 2^disp) % 2^32
end
lshift = M.lshift
function M.tohex(x, n) -- BitOp style
n = n or 8
local up
if n <= 0 then
if n == 0 then return '' end
up = true
n = - n
end
x = band(x, 16^n-1)
return ('%0'..n..(up and 'X' or 'x')):format(x)
end
local tohex = M.tohex
function M.extract(n, field, width) -- Lua5.2 inspired
width = width or 1
return band(rshift(n, field), 2^width-1)
end
local extract = M.extract
function M.replace(n, v, field, width) -- Lua5.2 inspired
width = width or 1
local mask1 = 2^width-1
v = band(v, mask1) -- required by spec?
local mask = bnot(lshift(mask1, field))
return band(n, mask) + lshift(v, field)
end
local replace = M.replace
function M.bswap(x) -- BitOp style
local a = band(x, 0xff); x = rshift(x, 8)
local b = band(x, 0xff); x = rshift(x, 8)
local c = band(x, 0xff); x = rshift(x, 8)
local d = band(x, 0xff)
return lshift(lshift(lshift(a, 8) + b, 8) + c, 8) + d
end
local bswap = M.bswap
function M.rrotate(x, disp) -- Lua5.2 inspired
disp = disp % 32
local low = band(x, 2^disp-1)
return rshift(x, disp) + lshift(low, 32-disp)
end
local rrotate = M.rrotate
function M.lrotate(x, disp) -- Lua5.2 inspired
return rrotate(x, -disp)
end
local lrotate = M.lrotate
M.rol = M.lrotate -- LuaOp inspired
M.ror = M.rrotate -- LuaOp insipred
function M.arshift(x, disp) -- Lua5.2 inspired
local z = rshift(x, disp)
if x >= 0x80000000 then z = z + lshift(2^disp-1, 32-disp) end
return z
end
local arshift = M.arshift
function M.btest(x, y) -- Lua5.2 inspired
return band(x, y) ~= 0
end
M.bit32 = {} -- Lua 5.2 'bit32' compatibility
local function bit32_bnot(x)
return (-1 - x) % MOD
end
M.bit32.bnot = bit32_bnot
local function bit32_bxor(a, b, c, ...)
local z
if b then
a = a % MOD
b = b % MOD
z = bxor(a, b)
if c then
z = bit32_bxor(z, c, ...)
end
return z
elseif a then
return a % MOD
else
return 0
end
end
M.bit32.bxor = bit32_bxor
local function bit32_band(a, b, c, ...)
local z
if b then
a = a % MOD
b = b % MOD
z = ((a+b) - bxor(a,b)) / 2
if c then
z = bit32_band(z, c, ...)
end
return z
elseif a then
return a % MOD
else
return MODM
end
end
M.bit32.band = bit32_band
local function bit32_bor(a, b, c, ...)
local z
if b then
a = a % MOD
b = b % MOD
z = MODM - band(MODM - a, MODM - b)
if c then
z = bit32_bor(z, c, ...)
end
return z
elseif a then
return a % MOD
else
return 0
end
end
M.bit32.bor = bit32_bor
function M.bit32.btest(...)
return bit32_band(...) ~= 0
end
function M.bit32.lrotate(x, disp)
return lrotate(x % MOD, disp)
end
function M.bit32.rrotate(x, disp)
return rrotate(x % MOD, disp)
end
function M.bit32.lshift(x,disp)
if disp > 31 or disp < -31 then return 0 end
return lshift(x % MOD, disp)
end
function M.bit32.rshift(x,disp)
if disp > 31 or disp < -31 then return 0 end
return rshift(x % MOD, disp)
end
function M.bit32.arshift(x,disp)
x = x % MOD
if disp >= 0 then
if disp > 31 then
return (x >= 0x80000000) and MODM or 0
else
local z = rshift(x, disp)
if x >= 0x80000000 then z = z + lshift(2^disp-1, 32-disp) end
return z
end
else
return lshift(x, -disp)
end
end
function M.bit32.extract(x, field, ...)
local width = ... or 1
if field < 0 or field > 31 or width < 0 or field+width > 32 then error 'out of range' end
x = x % MOD
return extract(x, field, ...)
end
function M.bit32.replace(x, v, field, ...)
local width = ... or 1
if field < 0 or field > 31 or width < 0 or field+width > 32 then error 'out of range' end
x = x % MOD
v = v % MOD
return replace(x, v, field, ...)
end
M.bit = {} -- LuaBitOp "bit" compatibility
function M.bit.tobit(x)
x = x % MOD
if x >= 0x80000000 then x = x - MOD end
return x
end
local bit_tobit = M.bit.tobit
function M.bit.tohex(x, ...)
return tohex(x % MOD, ...)
end
function M.bit.bnot(x)
return bit_tobit(bnot(x % MOD))
end
local function bit_bor(a, b, c, ...)
if c then
return bit_bor(bit_bor(a, b), c, ...)
elseif b then
return bit_tobit(bor(a % MOD, b % MOD))
else
return bit_tobit(a)
end
end
M.bit.bor = bit_bor
local function bit_band(a, b, c, ...)
if c then
return bit_band(bit_band(a, b), c, ...)
elseif b then
return bit_tobit(band(a % MOD, b % MOD))
else
return bit_tobit(a)
end
end
M.bit.band = bit_band
local function bit_bxor(a, b, c, ...)
if c then
return bit_bxor(bit_bxor(a, b), c, ...)
elseif b then
return bit_tobit(bxor(a % MOD, b % MOD))
else
return bit_tobit(a)
end
end
M.bit.bxor = bit_bxor
function M.bit.lshift(x, n)
return bit_tobit(lshift(x % MOD, n % 32))
end
function M.bit.rshift(x, n)
return bit_tobit(rshift(x % MOD, n % 32))
end
function M.bit.arshift(x, n)
return bit_tobit(arshift(x % MOD, n % 32))
end
function M.bit.rol(x, n)
return bit_tobit(lrotate(x % MOD, n % 32))
end
function M.bit.ror(x, n)
return bit_tobit(rrotate(x % MOD, n % 32))
end
function M.bit.bswap(x)
return bit_tobit(bswap(x % MOD))
end
return M
@@ -0,0 +1,232 @@
--[[----------------------------------------
Random
Not all of this is mine
------------------------------------------]]
--[[------------------------------------
RandomLua v0.3.1
Pure Lua Pseudo-Random Numbers Generator
Under the MIT license.
copyright(c) 2011 linux-man
--]]------------------------------------
local math_floor = math.floor
local function normalize(n)
return n % 0x80000000
end
local function bit_and(a, b)
local r = 0
local m = 0
for m = 0, 31 do
if (a % 2 == 1) and (b % 2 == 1) then r = r + 2^m end
if a % 2 ~= 0 then a = a - 1 end
if b % 2 ~= 0 then b = b - 1 end
a = a / 2 b = b / 2
end
return normalize(r)
end
local function bit_or(a, b)
local r = 0
local m = 0
for m = 0, 31 do
if (a % 2 == 1) or (b % 2 == 1) then r = r + 2^m end
if a % 2 ~= 0 then a = a - 1 end
if b % 2 ~= 0 then b = b - 1 end
a = a / 2 b = b / 2
end
return normalize(r)
end
local function bit_xor(a, b)
local r = 0
local m = 0
for m = 0, 31 do
if a % 2 ~= b % 2 then r = r + 2^m end
if a % 2 ~= 0 then a = a - 1 end
if b % 2 ~= 0 then b = b - 1 end
a = a / 2 b = b / 2
end
return normalize(r)
end
local function seed()
return normalize(os.time())
end
--Mersenne twister
local mersenne_twister = {}
mersenne_twister.__index = mersenne_twister
function mersenne_twister:randomseed(s)
if not s then s = seed() end
self.mt[0] = normalize(s)
for i = 1, 623 do
self.mt[i] = normalize(0x6c078965 * bit_xor(self.mt[i-1], math_floor(self.mt[i-1] / 0x40000000)) + i)
end
end
function mersenne_twister:random(a, b)
local y
if self.index == 0 then
for i = 0, 623 do
y = self.mt[(i + 1) % 624] % 0x80000000
self.mt[i] = bit_xor(self.mt[(i + 397) % 624], math_floor(y / 2))
if y % 2 ~= 0 then self.mt[i] = bit_xor(self.mt[i], 0x9908b0df) end
end
end
y = self.mt[self.index]
y = bit_xor(y, math_floor(y / 0x800))
y = bit_xor(y, bit_and(normalize(y * 0x80), 0x9d2c5680))
y = bit_xor(y, bit_and(normalize(y * 0x8000), 0xefc60000))
y = bit_xor(y, math_floor(y / 0x40000))
self.index = (self.index + 1) % 624
if not a then return y / 0x80000000
elseif not b then
if a == 0 then return y
else return 1 + (y % a)
end
else
return a + (y % (b - a + 1))
end
end
local function twister(s)
local temp = {}
setmetatable(temp, mersenne_twister)
temp.mt = {}
temp.index = 0
temp:randomseed(s)
return temp
end
--Linear Congruential Generator
local linear_congruential_generator = {}
linear_congruential_generator.__index = linear_congruential_generator
function linear_congruential_generator:random(a, b)
local y = (self.a * self.x + self.c) % self.m
self.x = y
if not a then return y / 0x10000
elseif not b then
if a == 0 then return y
else return 1 + (y % a) end
else
return a + (y % (b - a + 1))
end
end
function linear_congruential_generator:randomseed(s)
if not s then s = seed() end
self.x = normalize(s)
end
local function lcg(s, r)
local temp = {}
setmetatable(temp, linear_congruential_generator)
temp.a, temp.c, temp.m = 1103515245, 12345, 0x10000 --from Ansi C
if r then
if r == 'nr' then temp.a, temp.c, temp.m = 1664525, 1013904223, 0x10000 --from Numerical Recipes.
elseif r == 'mvc' then temp.a, temp.c, temp.m = 214013, 2531011, 0x10000 end--from MVC
end
temp:randomseed(s)
return temp
end
-- Multiply-with-carry
local multiply_with_carry = {}
multiply_with_carry.__index = multiply_with_carry
function multiply_with_carry:random(a, b)
local m = self.m
local t = self.a * self.x + self.c
local y = t % m
self.x = y
self.c = math_floor(t / m)
if not a then return y / 0x10000
elseif not b then
if a == 0 then return y
else return 1 + (y % a) end
else
return a + (y % (b - a + 1))
end
end
function multiply_with_carry:randomseed(s)
if not s then s = seed() end
self.c = self.ic
self.x = normalize(s)
end
local function mwc(s, r)
local temp = {}
setmetatable(temp, multiply_with_carry)
temp.a, temp.c, temp.m = 1103515245, 12345, 0x10000 --from Ansi C
if r then
if r == 'nr' then temp.a, temp.c, temp.m = 1664525, 1013904223, 0x10000 --from Numerical Recipes.
elseif r == 'mvc' then temp.a, temp.c, temp.m = 214013, 2531011, 0x10000 end--from MVC
end
temp.ic = temp.c
temp:randomseed(s)
return temp
end
-- Little bind for the methods: My code starts
local randomGen={}
randomGen.__index=randomGen
function randomGen:new(s)
local temp={}
setmetatable(temp,randomGen)
temp[1]=twister()
temp[2]=lcg()
temp[3]=mwc()
temp.pos=1
for i=1,3 do
temp[i]:randomseed(s)
end
return temp
end
function randomGen:randomseed(s)
self.pos=1
self[1]:randomseed(s)
self[2]:randomseed(s)
self[3]:randomseed(s)
end
function randomGen:randomInt(a,b)
local t=self[self.pos]:random(a,b)
self.pos=self.pos+1
if self.pos>3 then
self.pos=1
end
return t
end
function randomGen:newND(a,b,s)
if not(a) or not(b) then error('You must include a range!') end
local temp=randomGen:new(s)
temp.a=a
temp.b=b
temp.range=b-a+1
temp.dups={no=0}
function temp:nextInt()
local t=self:randomInt(self.a,self.b)
if self.dups[t]==nil then
self.dups[t]=true
self.dups.no=self.dups.no+1
else
return self:nextInt()
end
if self.dups.no==self.range then
function self:nextInt()
return 1,true
end
return t
else
return t
end
end
function temp:nextIInt()
return function() return self:nextInt() end
end
return temp
end
return randomGen