package fields
|
|
|
|
import (
|
|
"bytes"
|
|
"math/big"
|
|
)
|
|
|
|
// Fq6 is Field 6
|
|
type Fq6 struct {
|
|
F Fq2
|
|
NonResidue [2]*big.Int
|
|
}
|
|
|
|
// NewFq6 generates a new Fq6
|
|
func NewFq6(f Fq2, nonResidue [2]*big.Int) Fq6 {
|
|
fq6 := Fq6{
|
|
f,
|
|
nonResidue,
|
|
}
|
|
return fq6
|
|
}
|
|
|
|
// Zero returns a Zero value on the Fq6
|
|
func (fq6 Fq6) Zero() [3][2]*big.Int {
|
|
return [3][2]*big.Int{fq6.F.Zero(), fq6.F.Zero(), fq6.F.Zero()}
|
|
}
|
|
|
|
// One returns a One value on the Fq6
|
|
func (fq6 Fq6) One() [3][2]*big.Int {
|
|
return [3][2]*big.Int{fq6.F.One(), fq6.F.Zero(), fq6.F.Zero()}
|
|
}
|
|
|
|
func (fq6 Fq6) mulByNonResidue(a [2]*big.Int) [2]*big.Int {
|
|
return fq6.F.Mul(fq6.NonResidue, a)
|
|
}
|
|
|
|
// Add performs an addition on the Fq6
|
|
func (fq6 Fq6) Add(a, b [3][2]*big.Int) [3][2]*big.Int {
|
|
return [3][2]*big.Int{
|
|
fq6.F.Add(a[0], b[0]),
|
|
fq6.F.Add(a[1], b[1]),
|
|
fq6.F.Add(a[2], b[2]),
|
|
}
|
|
}
|
|
|
|
// Double is ...
|
|
func (fq6 Fq6) Double(a [3][2]*big.Int) [3][2]*big.Int {
|
|
return fq6.Add(a, a)
|
|
}
|
|
|
|
// Sub performs a subtraction on the Fq6
|
|
func (fq6 Fq6) Sub(a, b [3][2]*big.Int) [3][2]*big.Int {
|
|
return [3][2]*big.Int{
|
|
fq6.F.Sub(a[0], b[0]),
|
|
fq6.F.Sub(a[1], b[1]),
|
|
fq6.F.Sub(a[2], b[2]),
|
|
}
|
|
}
|
|
|
|
// Neg performs a negation on the Fq6
|
|
func (fq6 Fq6) Neg(a [3][2]*big.Int) [3][2]*big.Int {
|
|
return fq6.Sub(fq6.Zero(), a)
|
|
}
|
|
|
|
// Mul performs a multiplication on the Fq6
|
|
func (fq6 Fq6) Mul(a, b [3][2]*big.Int) [3][2]*big.Int {
|
|
v0 := fq6.F.Mul(a[0], b[0])
|
|
v1 := fq6.F.Mul(a[1], b[1])
|
|
v2 := fq6.F.Mul(a[2], b[2])
|
|
return [3][2]*big.Int{
|
|
fq6.F.Add(
|
|
v0,
|
|
fq6.mulByNonResidue(
|
|
fq6.F.Sub(
|
|
fq6.F.Mul(
|
|
fq6.F.Add(a[1], a[2]),
|
|
fq6.F.Add(b[1], b[2])),
|
|
fq6.F.Add(v1, v2)))),
|
|
|
|
fq6.F.Add(
|
|
fq6.F.Sub(
|
|
fq6.F.Mul(
|
|
fq6.F.Add(a[0], a[1]),
|
|
fq6.F.Add(b[0], b[1])),
|
|
fq6.F.Add(v0, v1)),
|
|
fq6.mulByNonResidue(v2)),
|
|
|
|
fq6.F.Add(
|
|
fq6.F.Sub(
|
|
fq6.F.Mul(
|
|
fq6.F.Add(a[0], a[2]),
|
|
fq6.F.Add(b[0], b[2])),
|
|
fq6.F.Add(v0, v2)),
|
|
v1),
|
|
}
|
|
}
|
|
|
|
// MulScalar is ...
|
|
func (fq6 Fq6) MulScalar(base [3][2]*big.Int, e *big.Int) [3][2]*big.Int {
|
|
// for more possible implementations see g2.go file, at the function g2.MulScalar()
|
|
|
|
res := fq6.Zero()
|
|
rem := e
|
|
exp := base
|
|
|
|
for !bytes.Equal(rem.Bytes(), big.NewInt(int64(0)).Bytes()) {
|
|
// if rem % 2 == 1
|
|
if bytes.Equal(new(big.Int).Rem(rem, big.NewInt(int64(2))).Bytes(), big.NewInt(int64(1)).Bytes()) {
|
|
res = fq6.Add(res, exp)
|
|
}
|
|
exp = fq6.Double(exp)
|
|
rem = rem.Rsh(rem, 1) // rem = rem >> 1
|
|
}
|
|
return res
|
|
}
|
|
|
|
// Inverse returns the inverse on the Fq6
|
|
func (fq6 Fq6) Inverse(a [3][2]*big.Int) [3][2]*big.Int {
|
|
t0 := fq6.F.Square(a[0])
|
|
t1 := fq6.F.Square(a[1])
|
|
t2 := fq6.F.Square(a[2])
|
|
t3 := fq6.F.Mul(a[0], a[1])
|
|
t4 := fq6.F.Mul(a[0], a[2])
|
|
t5 := fq6.F.Mul(a[1], a[2])
|
|
|
|
c0 := fq6.F.Sub(t0, fq6.mulByNonResidue(t5))
|
|
c1 := fq6.F.Sub(fq6.mulByNonResidue(t2), t3)
|
|
c2 := fq6.F.Sub(t1, t4)
|
|
|
|
t6 := fq6.F.Inverse(
|
|
fq6.F.Add(
|
|
fq6.F.Mul(a[0], c0),
|
|
fq6.mulByNonResidue(
|
|
fq6.F.Add(
|
|
fq6.F.Mul(a[2], c1),
|
|
fq6.F.Mul(a[1], c2)))))
|
|
return [3][2]*big.Int{
|
|
fq6.F.Mul(t6, c0),
|
|
fq6.F.Mul(t6, c1),
|
|
fq6.F.Mul(t6, c2),
|
|
}
|
|
}
|
|
|
|
// Div performs a division on the Fq6
|
|
func (fq6 Fq6) Div(a, b [3][2]*big.Int) [3][2]*big.Int {
|
|
return fq6.Mul(a, fq6.Inverse(b))
|
|
}
|
|
|
|
// Square performs a square operation on the Fq6
|
|
func (fq6 Fq6) Square(a [3][2]*big.Int) [3][2]*big.Int {
|
|
s0 := fq6.F.Square(a[0])
|
|
ab := fq6.F.Mul(a[0], a[1])
|
|
s1 := fq6.F.Add(ab, ab)
|
|
s2 := fq6.F.Square(
|
|
fq6.F.Add(
|
|
fq6.F.Sub(a[0], a[1]),
|
|
a[2]))
|
|
bc := fq6.F.Mul(a[1], a[2])
|
|
s3 := fq6.F.Add(bc, bc)
|
|
s4 := fq6.F.Square(a[2])
|
|
|
|
return [3][2]*big.Int{
|
|
fq6.F.Add(
|
|
s0,
|
|
fq6.mulByNonResidue(s3)),
|
|
fq6.F.Add(
|
|
s1,
|
|
fq6.mulByNonResidue(s4)),
|
|
fq6.F.Sub(
|
|
fq6.F.Add(
|
|
fq6.F.Add(s1, s2),
|
|
s3),
|
|
fq6.F.Add(s0, s4)),
|
|
}
|
|
}
|
|
|
|
// Affine is ...
|
|
func (fq6 Fq6) Affine(a [3][2]*big.Int) [3][2]*big.Int {
|
|
return [3][2]*big.Int{
|
|
fq6.F.Affine(a[0]),
|
|
fq6.F.Affine(a[1]),
|
|
fq6.F.Affine(a[2]),
|
|
}
|
|
}
|
|
|
|
// Equal is ...
|
|
func (fq6 Fq6) Equal(a, b [3][2]*big.Int) bool {
|
|
return fq6.F.Equal(a[0], b[0]) && fq6.F.Equal(a[1], b[1]) && fq6.F.Equal(a[2], b[2])
|
|
}
|
|
|
|
// Copy is ...
|
|
func (fq6 Fq6) Copy(a [3][2]*big.Int) [3][2]*big.Int {
|
|
return [3][2]*big.Int{
|
|
fq6.F.Copy(a[0]),
|
|
fq6.F.Copy(a[1]),
|
|
fq6.F.Copy(a[2]),
|
|
}
|
|
}
|