@ -13,35 +13,35 @@ func arrayOfZeroes(n int) []*big.Int {
return r
return r
}
}
func F Add( a , b * big . Int ) * big . Int {
func f Add( a , b * big . Int ) * big . Int {
ab := new ( big . Int ) . Add ( a , b )
ab := new ( big . Int ) . Add ( a , b )
return new ( big . Int ) . Mod ( ab , R )
return new ( big . Int ) . Mod ( ab , R )
}
}
func F Sub( a , b * big . Int ) * big . Int {
func f Sub( a , b * big . Int ) * big . Int {
ab := new ( big . Int ) . Sub ( a , b )
ab := new ( big . Int ) . Sub ( a , b )
return new ( big . Int ) . Mod ( ab , R )
return new ( big . Int ) . Mod ( ab , R )
}
}
func F Mul( a , b * big . Int ) * big . Int {
func f Mul( a , b * big . Int ) * big . Int {
ab := new ( big . Int ) . Mul ( a , b )
ab := new ( big . Int ) . Mul ( a , b )
return new ( big . Int ) . Mod ( ab , R )
return new ( big . Int ) . Mod ( ab , R )
}
}
func F Div( a , b * big . Int ) * big . Int {
func f Div( a , b * big . Int ) * big . Int {
ab := new ( big . Int ) . Mul ( a , new ( big . Int ) . ModInverse ( b , R ) )
ab := new ( big . Int ) . Mul ( a , new ( big . Int ) . ModInverse ( b , R ) )
return new ( big . Int ) . Mod ( ab , R )
return new ( big . Int ) . Mod ( ab , R )
}
}
func F Neg( a * big . Int ) * big . Int {
func f Neg( a * big . Int ) * big . Int {
return new ( big . Int ) . Mod ( new ( big . Int ) . Neg ( a ) , R )
return new ( big . Int ) . Mod ( new ( big . Int ) . Neg ( a ) , R )
}
}
func F Inv( a * big . Int ) * big . Int {
func f Inv( a * big . Int ) * big . Int {
return new ( big . Int ) . ModInverse ( a , R )
return new ( big . Int ) . ModInverse ( a , R )
}
}
func F Exp( base * big . Int , e * big . Int ) * big . Int {
func f Exp( base * big . Int , e * big . Int ) * big . Int {
res := big . NewInt ( 1 )
res := big . NewInt ( 1 )
rem := new ( big . Int ) . Set ( e )
rem := new ( big . Int ) . Set ( e )
exp := base
exp := base
@ -49,9 +49,9 @@ func FExp(base *big.Int, e *big.Int) *big.Int {
for ! bytes . Equal ( rem . Bytes ( ) , big . NewInt ( int64 ( 0 ) ) . Bytes ( ) ) {
for ! bytes . Equal ( rem . Bytes ( ) , big . NewInt ( int64 ( 0 ) ) . Bytes ( ) ) {
// if BigIsOdd(rem) {
// if BigIsOdd(rem) {
if rem . Bit ( 0 ) == 1 { // .Bit(0) returns 1 when is odd
if rem . Bit ( 0 ) == 1 { // .Bit(0) returns 1 when is odd
res = F Mul( res , exp )
res = f Mul( res , exp )
}
}
exp = F Mul( exp , exp )
exp = f Mul( exp , exp )
rem = new ( big . Int ) . Rsh ( rem , 1 )
rem = new ( big . Int ) . Rsh ( rem , 1 )
}
}
return res
return res
@ -64,38 +64,38 @@ func max(a, b int) int {
return b
return b
}
}
func P olynomialSub( a , b [ ] * big . Int ) [ ] * big . Int {
func p olynomialSub( a , b [ ] * big . Int ) [ ] * big . Int {
r := arrayOfZeroes ( max ( len ( a ) , len ( b ) ) )
r := arrayOfZeroes ( max ( len ( a ) , len ( b ) ) )
for i := 0 ; i < len ( a ) ; i ++ {
for i := 0 ; i < len ( a ) ; i ++ {
r [ i ] = F Add( r [ i ] , a [ i ] )
r [ i ] = f Add( r [ i ] , a [ i ] )
}
}
for i := 0 ; i < len ( b ) ; i ++ {
for i := 0 ; i < len ( b ) ; i ++ {
r [ i ] = F Sub( r [ i ] , b [ i ] )
r [ i ] = f Sub( r [ i ] , b [ i ] )
}
}
return r
return r
}
}
func P olynomialMul( a , b [ ] * big . Int ) [ ] * big . Int {
func p olynomialMul( a , b [ ] * big . Int ) [ ] * big . Int {
r := arrayOfZeroes ( len ( a ) + len ( b ) - 1 )
r := arrayOfZeroes ( len ( a ) + len ( b ) - 1 )
for i := 0 ; i < len ( a ) ; i ++ {
for i := 0 ; i < len ( a ) ; i ++ {
for j := 0 ; j < len ( b ) ; j ++ {
for j := 0 ; j < len ( b ) ; j ++ {
r [ i + j ] = F Add( r [ i + j ] , F Mul( a [ i ] , b [ j ] ) )
r [ i + j ] = f Add( r [ i + j ] , f Mul( a [ i ] , b [ j ] ) )
}
}
}
}
return r
return r
}
}
func P olynomialDiv( a , b [ ] * big . Int ) ( [ ] * big . Int , [ ] * big . Int ) {
func p olynomialDiv( a , b [ ] * big . Int ) ( [ ] * big . Int , [ ] * big . Int ) {
// https://en.wikipedia.org/wiki/Division_algorithm
// https://en.wikipedia.org/wiki/Division_algorithm
r := arrayOfZeroes ( len ( a ) - len ( b ) + 1 )
r := arrayOfZeroes ( len ( a ) - len ( b ) + 1 )
rem := a
rem := a
for len ( rem ) >= len ( b ) {
for len ( rem ) >= len ( b ) {
l := F Div( rem [ len ( rem ) - 1 ] , b [ len ( b ) - 1 ] )
l := f Div( rem [ len ( rem ) - 1 ] , b [ len ( b ) - 1 ] )
pos := len ( rem ) - len ( b )
pos := len ( rem ) - len ( b )
r [ pos ] = l
r [ pos ] = l
aux := arrayOfZeroes ( pos )
aux := arrayOfZeroes ( pos )
aux1 := append ( aux , l )
aux1 := append ( aux , l )
aux2 := P olynomialSub( rem , P olynomialMul( b , aux1 ) )
aux2 := p olynomialSub( rem , p olynomialMul( b , aux1 ) )
rem = aux2 [ : len ( aux2 ) - 1 ]
rem = aux2 [ : len ( aux2 ) - 1 ]
}
}
return r , rem
return r , rem