github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/hyperledger/fabric-amcl/amcl/FP256BN/FP2.go (about)

     1  /*
     2  Licensed to the Apache Software Foundation (ASF) under one
     3  or more contributor license agreements.  See the NOTICE file
     4  distributed with this work for additional information
     5  regarding copyright ownership.  The ASF licenses this file
     6  to you under the Apache License, Version 2.0 (the
     7  "License"); you may not use this file except in compliance
     8  with the License.  You may obtain a copy of the License at
     9  
    10    http://www.apache.org/licenses/LICENSE-2.0
    11  
    12  Unless required by applicable law or agreed to in writing,
    13  software distributed under the License is distributed on an
    14  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    15  KIND, either express or implied.  See the License for the
    16  specific language governing permissions and limitations
    17  under the License.
    18  */
    19  
    20  /* Finite Field arithmetic  Fp^2 functions */
    21  
    22  /* FP2 elements are of the form a+ib, where i is sqrt(-1) */
    23  
    24  package FP256BN
    25  
    26  
    27  
    28  type FP2 struct {
    29  	a *FP
    30  	b *FP
    31  }
    32  
    33  /* Constructors */
    34  func NewFP2int(a int) *FP2 {
    35  	F:=new(FP2)
    36  	F.a=NewFPint(a)
    37  	F.b=NewFPint(0)
    38  	return F
    39  }
    40  
    41  func NewFP2copy(x *FP2) *FP2 {
    42  	F:=new(FP2)
    43  	F.a=NewFPcopy(x.a)
    44  	F.b=NewFPcopy(x.b)
    45  	return F
    46  }
    47  
    48  func NewFP2fps(c *FP,d *FP) *FP2 {
    49  	F:=new(FP2)
    50  	F.a=NewFPcopy(c)
    51  	F.b=NewFPcopy(d)
    52  	return F
    53  }
    54  
    55  func NewFP2bigs(c *BIG,d *BIG) *FP2 {
    56  	F:=new(FP2)
    57  	F.a=NewFPbig(c)
    58  	F.b=NewFPbig(d)
    59  	return F
    60  }
    61  
    62  func NewFP2fp(c *FP) *FP2 {
    63  	F:=new(FP2)
    64  	F.a=NewFPcopy(c)
    65  	F.b=NewFPint(0)
    66  	return F
    67  }
    68  
    69  func NewFP2big(c *BIG) *FP2 {
    70  	F:=new(FP2)
    71  	F.a=NewFPbig(c)
    72  	F.b=NewFPint(0)
    73  	return F
    74  }
    75  
    76  /* reduce components mod Modulus */
    77  func (F *FP2) reduce() {
    78  	F.a.reduce()
    79  	F.b.reduce()
    80  }
    81  
    82  /* normalise components of w */
    83  func (F *FP2) norm() {
    84  	F.a.norm()
    85  	F.b.norm()
    86  }
    87  
    88  /* test this=0 ? */
    89  func (F *FP2) iszilch() bool {
    90  	//F.reduce()
    91  	return (F.a.iszilch() && F.b.iszilch())
    92  }
    93  
    94  func (F *FP2) cmove(g *FP2,d int) {
    95  	F.a.cmove(g.a,d)
    96  	F.b.cmove(g.b,d)
    97  }
    98  
    99  /* test this=1 ? */
   100  func (F *FP2)  isunity() bool {
   101  	one:=NewFPint(1)
   102  	return (F.a.Equals(one) && F.b.iszilch())
   103  }
   104  
   105  /* test this=x */
   106  func (F *FP2) Equals(x *FP2) bool {
   107  	return (F.a.Equals(x.a) && F.b.Equals(x.b))
   108  }
   109  
   110  /* extract a */
   111  func (F *FP2) GetA() *BIG { 
   112  	return F.a.redc()
   113  }
   114  
   115  /* extract b */
   116  func (F *FP2) GetB() *BIG {
   117  	return F.b.redc()
   118  }
   119  
   120  /* copy this=x */
   121  func (F *FP2) copy(x *FP2) {
   122  	F.a.copy(x.a)
   123  	F.b.copy(x.b)
   124  }
   125  
   126  /* set this=0 */
   127  func (F *FP2) zero() {
   128  	F.a.zero()
   129  	F.b.zero()
   130  }
   131  
   132  /* set this=1 */
   133  func (F *FP2) one() {
   134  	F.a.one()
   135  	F.b.zero()
   136  }
   137  
   138  /* negate this mod Modulus */
   139  func (F *FP2) neg() {
   140  //	F.norm()
   141  	m:=NewFPcopy(F.a)
   142  	t:= NewFPint(0)
   143  
   144  	m.add(F.b)
   145  	m.neg()
   146  //	m.norm()
   147  	t.copy(m); t.add(F.b)
   148  	F.b.copy(m)
   149  	F.b.add(F.a)
   150  	F.a.copy(t)
   151  }
   152  
   153  /* set to a-ib */
   154  func (F *FP2) conj() {
   155  	F.b.neg(); F.b.norm()
   156  }
   157  
   158  /* this+=a */
   159  func (F *FP2) add(x *FP2) {
   160  	F.a.add(x.a)
   161  	F.b.add(x.b)
   162  }
   163  
   164  /* this-=a */
   165  func (F *FP2) sub(x *FP2) {
   166  	m:=NewFP2copy(x)
   167  	m.neg()
   168  	F.add(m)
   169  }
   170  
   171  /* this-=a */
   172  func (F *FP2) rsub(x *FP2) {
   173  	F.neg()
   174  	F.add(x)
   175  }
   176  
   177  /* this*=s, where s is an FP */
   178  func (F *FP2) pmul(s *FP) {
   179  	F.a.mul(s)
   180  	F.b.mul(s)
   181  }
   182  
   183  /* this*=i, where i is an int */
   184  func (F *FP2) imul(c int) {
   185  	F.a.imul(c)
   186  	F.b.imul(c)
   187  }
   188  
   189  /* this*=this */
   190  func (F *FP2) sqr() {
   191  	w1:=NewFPcopy(F.a)
   192  	w3:=NewFPcopy(F.a)
   193  	mb:=NewFPcopy(F.b)
   194  
   195  //	w3.mul(F.b)
   196  	w1.add(F.b)
   197  
   198  w3.add(F.a);
   199  w3.norm();
   200  F.b.mul(w3);
   201  
   202  	mb.neg()
   203  	F.a.add(mb)
   204  
   205  	w1.norm()
   206  	F.a.norm()
   207  
   208  	F.a.mul(w1)
   209  //	F.b.copy(w3); F.b.add(w3)
   210  
   211  //	F.b.norm()
   212  }
   213  
   214  /* this*=y */
   215  /* Now using Lazy reduction */
   216  func (F *FP2) mul(y *FP2) {
   217  
   218  	if int64(F.a.XES+F.b.XES)*int64(y.a.XES+y.b.XES)>int64(FEXCESS) {
   219  		if F.a.XES>1 {F.a.reduce()}
   220  		if F.b.XES>1 {F.b.reduce()}		
   221  	}
   222  
   223  	pR:=NewDBIG()
   224  	C:=NewBIGcopy(F.a.x)
   225  	D:=NewBIGcopy(y.a.x)
   226  	p:=NewBIGints(Modulus)
   227  
   228  	pR.ucopy(p)
   229  
   230  	A:=mul(F.a.x,y.a.x)
   231  	B:=mul(F.b.x,y.b.x)
   232  
   233  	C.add(F.b.x); C.norm()
   234  	D.add(y.b.x); D.norm()
   235  
   236  	E:=mul(C,D)
   237  	FF:=NewDBIGcopy(A); FF.add(B)
   238  	B.rsub(pR)
   239  
   240  	A.add(B); A.norm()
   241  	E.sub(FF); E.norm()
   242  
   243  	F.a.x.copy(mod(A)); F.a.XES=3
   244  	F.b.x.copy(mod(E)); F.b.XES=2
   245  
   246  }
   247  
   248  /* sqrt(a+ib) = sqrt(a+sqrt(a*a-n*b*b)/2)+ib/(2*sqrt(a+sqrt(a*a-n*b*b)/2)) */
   249  /* returns true if this is QR */
   250  func (F *FP2) sqrt() bool {
   251  	if F.iszilch() {return true}
   252  	w1:=NewFPcopy(F.b)
   253  	w2:=NewFPcopy(F.a)
   254  	w1.sqr(); w2.sqr(); w1.add(w2)
   255  	if w1.jacobi()!=1 { F.zero(); return false }
   256  	w1=w1.sqrt()
   257  	w2.copy(F.a); w2.add(w1); w2.norm(); w2.div2()
   258  	if w2.jacobi()!=1 {
   259  		w2.copy(F.a); w2.sub(w1); w2.norm(); w2.div2()
   260  		if w2.jacobi()!=1 { F.zero(); return false }
   261  	}
   262  	w2=w2.sqrt()
   263  	F.a.copy(w2)
   264  	w2.add(w2)
   265  	w2.inverse()
   266  	F.b.mul(w2)
   267  	return true
   268  }
   269  
   270  /* output to hex string */
   271  func (F *FP2) toString() string {
   272  	return ("["+F.a.toString()+","+F.b.toString()+"]")
   273  }
   274  
   275  /* this=1/this */
   276  func (F *FP2) inverse() {
   277  	F.norm()
   278  	w1:=NewFPcopy(F.a)
   279  	w2:=NewFPcopy(F.b)
   280  
   281  	w1.sqr()
   282  	w2.sqr()
   283  	w1.add(w2)
   284  	w1.inverse()
   285  	F.a.mul(w1)
   286  	w1.neg(); w1.norm();
   287  	F.b.mul(w1)
   288  }
   289  
   290  /* this/=2 */
   291  func (F *FP2) div2() {
   292  	F.a.div2()
   293  	F.b.div2()
   294  }
   295  
   296  /* this*=sqrt(-1) */
   297  func (F *FP2) times_i() {
   298  	//	a.norm();
   299  	z:=NewFPcopy(F.a)
   300  	F.a.copy(F.b); F.a.neg()
   301  	F.b.copy(z)
   302  }
   303  
   304  /* w*=(1+sqrt(-1)) */
   305  /* where X*2-(1+sqrt(-1)) is irreducible for FP4, assumes p=3 mod 8 */
   306  func (F *FP2) mul_ip() {
   307  //	F.norm()
   308  	t:=NewFP2copy(F)
   309  	z:=NewFPcopy(F.a)
   310  	F.a.copy(F.b)
   311  	F.a.neg()
   312  	F.b.copy(z)
   313  	F.add(t)
   314  //	F.norm()
   315  }
   316  
   317  func (F *FP2) div_ip2() {
   318  	t:=NewFP2int(0)
   319  	F.norm()
   320  	t.a.copy(F.a); t.a.add(F.b)
   321  	t.b.copy(F.b); t.b.sub(F.a);
   322  	F.copy(t); F.norm()
   323  }
   324  
   325  /* w/=(1+sqrt(-1)) */
   326  func (F *FP2) div_ip() {
   327  	t:=NewFP2int(0)
   328  	F.norm()
   329  	t.a.copy(F.a); t.a.add(F.b)
   330  	t.b.copy(F.b); t.b.sub(F.a);
   331  	F.copy(t); F.norm()
   332  	F.div2()
   333  }