init: v1.0.0
This commit is contained in:
+125
@@ -0,0 +1,125 @@
|
||||
package fpe
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/big"
|
||||
"math/bits"
|
||||
)
|
||||
|
||||
type Radix struct {
|
||||
r int
|
||||
|
||||
e int // the maximum number such that r^e is a uint64
|
||||
|
||||
rBig *big.Int // radix as big
|
||||
|
||||
reBig *big.Int // radix^e as big.Int, the same as rPowers[-1]
|
||||
|
||||
rPowers []big.Int // [r, r^2, ..., r^e]
|
||||
}
|
||||
|
||||
func NewRadix(r int) *Radix {
|
||||
radix := &Radix{}
|
||||
radix.Set(r)
|
||||
return radix
|
||||
}
|
||||
|
||||
func (r *Radix) Set(v int) {
|
||||
if v < 2 || v >= math.MaxUint16 {
|
||||
panic("radix overflow")
|
||||
}
|
||||
r.r = v
|
||||
r.e = 64 / bits.Len32(uint32(v))
|
||||
r.rPowers = make([]big.Int, r.e)
|
||||
r.rPowers[0].SetUint64(uint64(v))
|
||||
for i, vi := 1, uint64(v); i < r.e; i++ {
|
||||
vi *= uint64(v)
|
||||
r.rPowers[i].SetUint64(vi)
|
||||
}
|
||||
r.rBig = &r.rPowers[0]
|
||||
r.reBig = &r.rPowers[r.e-1]
|
||||
}
|
||||
|
||||
func (r *Radix) Radix() int {
|
||||
return r.r
|
||||
}
|
||||
|
||||
func (r *Radix) Num(X []Char) *big.Int {
|
||||
if false {
|
||||
radix := big.NewInt(int64(r.r))
|
||||
n := new(big.Int)
|
||||
for _, d := range X {
|
||||
n.Mul(n, radix)
|
||||
n.Add(n, big.NewInt(int64(d)))
|
||||
}
|
||||
return n
|
||||
} else {
|
||||
radix := uint64(r.r)
|
||||
l := len(X) % r.e
|
||||
|
||||
tail := uint64(0)
|
||||
for i := 0; i < l; i++ {
|
||||
tail *= uint64(radix)
|
||||
tail += uint64(X[i])
|
||||
}
|
||||
|
||||
n := new(big.Int).SetUint64(tail)
|
||||
for i := l; i < len(X); i += r.e {
|
||||
d := uint64(0)
|
||||
for j := 0; j < r.e; j++ {
|
||||
d = d*uint64(radix) + uint64(X[i+j])
|
||||
}
|
||||
|
||||
n.Mul(n, r.reBig)
|
||||
n.Add(n, new(big.Int).SetUint64(d))
|
||||
}
|
||||
return n
|
||||
}
|
||||
}
|
||||
|
||||
// x should < radix^(lenX)
|
||||
func (r *Radix) Str(X []Numeral, x *big.Int) {
|
||||
if false {
|
||||
n := len(X)
|
||||
radix := big.NewInt(int64(r.r))
|
||||
d := new(big.Int)
|
||||
xx := new(big.Int).Set(x) // make a copy
|
||||
for i := 0; i < n; i++ {
|
||||
xx, d = xx.DivMod(xx, radix, d)
|
||||
X[n-i-1] = Numeral(d.Int64())
|
||||
}
|
||||
// if xx is not zero, then the input x must too big
|
||||
if xx.Sign() != 0 {
|
||||
panic("x should less then radix^m")
|
||||
}
|
||||
} else {
|
||||
xx := new(big.Int).Set(x) // make a copy
|
||||
lx := len(X)
|
||||
radix := uint64(r.r)
|
||||
d := new(big.Int)
|
||||
|
||||
// the tail part
|
||||
m := lx % r.e
|
||||
if m > 0 {
|
||||
xx, d = xx.DivMod(xx, &r.rPowers[m-1], d)
|
||||
n := d.Uint64()
|
||||
for i := lx - 1; i >= lx-m; i-- {
|
||||
X[i] = Numeral(n % radix)
|
||||
n /= radix
|
||||
}
|
||||
}
|
||||
|
||||
for i := lx - m; i > 0; i -= r.e {
|
||||
xx, d = xx.DivMod(xx, r.reBig, d)
|
||||
n := d.Uint64()
|
||||
for j := i - 1; j >= i-r.e; j-- {
|
||||
X[j] = uint16(n % radix)
|
||||
n /= radix
|
||||
}
|
||||
}
|
||||
// if xx is not zero, then the input x must too big
|
||||
if xx.Sign() != 0 {
|
||||
panic("x should less then radix^m")
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user