github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/hyperledger/fabric-amcl/amcl/FP256BN/FP.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 */
    21  /* CLINT mod p functions */
    22  
    23  package FP256BN
    24  
    25  
    26  
    27  const NOT_SPECIAL int=0
    28  const PSEUDO_MERSENNE int=1
    29  const MONTGOMERY_FRIENDLY int=2
    30  const GENERALISED_MERSENNE int=3
    31  
    32  const MODBITS uint=256 /* Number of bits in Modulus */
    33  const MOD8 uint=3  /* Modulus mod 8 */
    34  const MODTYPE int=NOT_SPECIAL //NOT_SPECIAL
    35  
    36  const FEXCESS int32=(int32(1)<<24)
    37  const OMASK Chunk= ((Chunk(-1))<<(MODBITS%BASEBITS))
    38  const TBITS uint=MODBITS%BASEBITS // Number of active bits in top word 
    39  const TMASK Chunk=(Chunk(1)<<TBITS)-1
    40  
    41  
    42  type FP struct {
    43  	x *BIG
    44  	XES int32
    45  }
    46  
    47  /* Constructors */
    48  func NewFPint(a int) *FP {
    49  	F:=new(FP)
    50  	F.x=NewBIGint(a)
    51  	F.nres()
    52  	return F
    53  }
    54  
    55  func NewFPbig(a *BIG) *FP {
    56  	F:=new(FP)
    57  	F.x=NewBIGcopy(a)
    58  	F.nres()
    59  	return F
    60  }
    61  
    62  func NewFPcopy(a *FP) *FP {
    63  	F:=new(FP)
    64  	F.x=NewBIGcopy(a.x)
    65  	F.XES=a.XES
    66  	return F
    67  }
    68  
    69  func (F *FP) toString() string {
    70  	F.reduce()
    71  	return F.redc().toString()
    72  }
    73  
    74  /* convert to Montgomery n-residue form */
    75  func (F *FP) nres() {
    76  	if MODTYPE!=PSEUDO_MERSENNE && MODTYPE!=GENERALISED_MERSENNE {
    77  		r:=NewBIGints(R2modp)
    78  		d:=mul(F.x,r)
    79  		F.x.copy(mod(d))
    80  		F.XES=2
    81  	} else {
    82  		F.XES=1
    83  	}
    84  }
    85  
    86  /* convert back to regular form */
    87  func (F *FP) redc() *BIG {
    88  	if MODTYPE!=PSEUDO_MERSENNE && MODTYPE!=GENERALISED_MERSENNE {
    89  		d:=NewDBIGscopy(F.x)
    90  		return mod(d)
    91  	} else {
    92  		r:=NewBIGcopy(F.x)
    93  		return r
    94  	}
    95  }
    96  
    97  /* reduce a DBIG to a BIG using the appropriate form of the modulus */
    98  
    99  func mod(d *DBIG) *BIG {
   100  	if MODTYPE==PSEUDO_MERSENNE {
   101  		t:=d.split(MODBITS)
   102  		b:=NewBIGdcopy(d)
   103  
   104  		v:=t.pmul(int(MConst))
   105  
   106  		t.add(b)
   107  		t.norm()
   108  
   109  		tw:=t.w[NLEN-1]
   110  		t.w[NLEN-1]&=TMASK
   111  		t.w[0]+=(MConst*((tw>>TBITS)+(v<<(BASEBITS-TBITS))))
   112  
   113  		t.norm()
   114  		return t
   115  	//	b.add(t)
   116  	//	b.norm()
   117  	//	return b		
   118  	}
   119  	if MODTYPE==MONTGOMERY_FRIENDLY {
   120  		for i:=0;i<NLEN;i++ {
   121  			top,bot:=muladd(d.w[i],MConst-1,d.w[i],d.w[NLEN+i-1])
   122  			d.w[NLEN+i-1]=bot
   123  			d.w[NLEN+i]+=top
   124  		}
   125  		b:=NewBIG()
   126  
   127  		for i:=0;i<NLEN;i++ {
   128  			b.w[i]=d.w[NLEN+i]
   129  		}
   130  		b.norm()
   131  		return b		
   132  	}
   133  
   134  	if MODTYPE==GENERALISED_MERSENNE { // GoldiLocks only
   135  		t:=d.split(MODBITS)
   136  		b:=NewBIGdcopy(d)
   137  		b.add(t);
   138  		dd:=NewDBIGscopy(t)
   139  		dd.shl(MODBITS/2)
   140  
   141  		tt:=dd.split(MODBITS)
   142  		lo:=NewBIGdcopy(dd)
   143  		b.add(tt)
   144  		b.add(lo)
   145  		b.norm()
   146  		tt.shl(MODBITS/2)
   147  		b.add(tt)
   148  
   149  		carry:=b.w[NLEN-1]>>TBITS
   150  		b.w[NLEN-1]&=TMASK
   151  		b.w[0]+=carry
   152  			
   153  		b.w[224/BASEBITS]+=carry<<(224%BASEBITS);
   154  		b.norm()
   155  		return b		
   156  	}
   157  
   158  	if MODTYPE==NOT_SPECIAL {
   159  		md:=NewBIGints(Modulus)
   160  		return monty(md,MConst,d) 
   161  	}
   162  	return NewBIG()
   163  }
   164  
   165  
   166  /* reduce this mod Modulus */
   167  func (F *FP) reduce() {
   168  	p:=NewBIGints(Modulus)
   169  	F.x.Mod(p)
   170  	F.XES=1
   171  }
   172  
   173  /* test this=0? */
   174  func (F *FP) iszilch() bool {
   175  	W:=NewFPcopy(F)
   176  	W.reduce()
   177  	return W.x.iszilch()
   178  }
   179  
   180  /* copy from FP b */
   181  func (F *FP) copy(b *FP ) {
   182  	F.x.copy(b.x)
   183  	F.XES=b.XES
   184  }
   185  
   186  /* set this=0 */
   187  func (F *FP) zero() {
   188  	F.x.zero()
   189  	F.XES=1
   190  }
   191  	
   192  /* set this=1 */
   193  func (F *FP) one() {
   194  	F.x.one(); F.nres()
   195  }
   196  
   197  /* normalise this */
   198  func (F *FP) norm() {
   199  	F.x.norm()
   200  }
   201  
   202  /* swap FPs depending on d */
   203  func (F *FP) cswap(b *FP,d int) {
   204  	c:=int32(d)
   205  	c=^(c-1)
   206  	t:=c&(F.XES^b.XES)
   207  	F.XES^=t
   208  	b.XES^=t
   209  	F.x.cswap(b.x,d)
   210  }
   211  
   212  /* copy FPs depending on d */
   213  func (F *FP) cmove(b *FP,d int) {
   214  	F.x.cmove(b.x,d)
   215  	c:=int32(-d)
   216  	F.XES^=(F.XES^b.XES)&c
   217  }
   218  
   219  /* this*=b mod Modulus */
   220  func (F *FP) mul(b *FP) {
   221  
   222  	if int64(F.XES)*int64(b.XES)>int64(FEXCESS) {F.reduce()}
   223  
   224  	d:=mul(F.x,b.x)
   225  	F.x.copy(mod(d))
   226  	F.XES=2
   227  }
   228  
   229  /* this = -this mod Modulus */
   230  func (F *FP) neg() {
   231  	m:=NewBIGints(Modulus)
   232  	sb:=logb2(uint32(F.XES-1))
   233  
   234  	m.fshl(sb)
   235  	F.x.rsub(m)		
   236  
   237  	F.XES=(1<<sb)
   238  	if F.XES>FEXCESS {F.reduce()}
   239  }
   240  
   241  
   242  /* this*=c mod Modulus, where c is a small int */
   243  func (F *FP) imul(c int) {
   244  //	F.norm()
   245  	s:=false
   246  	if (c<0) {
   247  		c=-c
   248  		s=true
   249  	}
   250  
   251  	if MODTYPE==PSEUDO_MERSENNE || MODTYPE==GENERALISED_MERSENNE {
   252  		d:=F.x.pxmul(c)
   253  		F.x.copy(mod(d))
   254  		F.XES=2
   255  	} else {
   256  		if F.XES*int32(c)<=FEXCESS {
   257  			F.x.pmul(c)
   258  			F.XES*=int32(c)
   259  		} else {
   260  			n:=NewFPint(c)
   261  			F.mul(n)
   262  		}
   263  	}
   264  	if s {F.neg(); F.norm()}
   265  }
   266  
   267  /* this*=this mod Modulus */
   268  func (F *FP) sqr() {
   269  	if int64(F.XES)*int64(F.XES)>int64(FEXCESS) {F.reduce()}	
   270  	d:=sqr(F.x)	
   271  	F.x.copy(mod(d))
   272  	F.XES=2
   273  }
   274  
   275  /* this+=b */
   276  func (F *FP) add(b *FP) {
   277  	F.x.add(b.x)
   278  	F.XES+=b.XES
   279  	if (F.XES>FEXCESS) {F.reduce()}
   280  }
   281  
   282  /* this-=b */
   283  func (F *FP) sub(b *FP) {
   284  	n:=NewFPcopy(b)
   285  	n.neg()
   286  	F.add(n)
   287  }
   288  
   289  func (F *FP) rsub(b *FP) {
   290  	F.neg()
   291  	F.add(b)
   292  }
   293  
   294  /* this/=2 mod Modulus */
   295  func (F *FP) div2() {
   296  //	F.x.norm()
   297  	if (F.x.parity()==0) {
   298  		F.x.fshr(1)
   299  	} else {
   300  		p:=NewBIGints(Modulus);
   301  		F.x.add(p)
   302  		F.x.norm()
   303  		F.x.fshr(1)
   304  	}
   305  }
   306  
   307  /* this=1/this mod Modulus */
   308  func (F *FP) inverse() {
   309  /*
   310  	p:=NewBIGints(Modulus);
   311  	r:=F.redc()
   312  	r.Invmodp(p)
   313  	F.x.copy(r)
   314  	F.nres()
   315  */
   316  
   317  	m2:=NewBIGints(Modulus);
   318  	m2.dec(2); m2.norm()
   319  	F.copy(F.pow(m2))
   320  
   321  }
   322  
   323  /* return TRUE if this==a */
   324  func (F *FP) Equals(a *FP) bool {
   325  	f:=NewFPcopy(F)
   326  	s:=NewFPcopy(a);
   327  
   328  	s.reduce()
   329  	f.reduce()
   330  	if (comp(s.x,f.x)==0) {return true}
   331  	return false
   332  }
   333  
   334  /* return this^e mod Modulus */
   335  /*
   336  func (F *FP) pow(e *BIG) *FP {
   337  	r:=NewFPint(1)
   338  	e.norm()
   339  	F.norm()
   340  	m:=NewFPcopy(F)
   341  	for true {
   342  		bt:=e.parity()
   343  		e.fshr(1)
   344  		if bt==1 {r.mul(m)}
   345  		if e.iszilch() {break}
   346  		m.sqr()
   347  	}
   348  	r.reduce()
   349  	return r
   350  }
   351  */
   352  
   353  
   354  func (F *FP) pow(e *BIG) *FP {
   355  	var tb []*FP
   356  	var w [1+(NLEN*int(BASEBITS)+3)/4]int8	
   357  	F.norm()
   358  	t:=NewBIGcopy(e)
   359  	t.norm()
   360  	nb:=1+(t.nbits()+3)/4
   361  
   362  	for i:=0;i<nb;i++ {
   363  		lsbs:=t.lastbits(4)
   364  		t.dec(lsbs)
   365  		t.norm()
   366  		w[i]=int8(lsbs)
   367  		t.fshr(4);
   368  	}
   369  	tb=append(tb,NewFPint(1))
   370  	tb=append(tb,NewFPcopy(F))
   371  	for i:=2;i<16;i++ {
   372  		tb=append(tb,NewFPcopy(tb[i-1]))
   373  		tb[i].mul(F);
   374  	}
   375  	r:=NewFPcopy(tb[w[nb-1]])
   376  	for i:=nb-2;i>=0;i-- {
   377  		r.sqr()
   378  		r.sqr()
   379  		r.sqr()
   380  		r.sqr()
   381  		r.mul(tb[w[i]])
   382  	}
   383  	r.reduce()
   384  	return r
   385  }
   386  
   387  
   388  /* return sqrt(this) mod Modulus */
   389  func (F *FP) sqrt() *FP {
   390  	F.reduce();
   391  	p:=NewBIGints(Modulus);
   392  	b:=NewBIGcopy(p)
   393  	if MOD8==5 {
   394  		b.dec(5); b.norm(); b.shr(3)
   395  		i:=NewFPcopy(F); i.x.shl(1)
   396  		v:=i.pow(b)
   397  		i.mul(v); i.mul(v)
   398  		i.x.dec(1)
   399  		r:=NewFPcopy(F)
   400  		r.mul(v); r.mul(i) 
   401  		r.reduce()
   402  		return r
   403  	} else {
   404  		b.inc(1); b.norm(); b.shr(2)
   405  		return F.pow(b);
   406  	}
   407  }
   408  
   409  /* return jacobi symbol (this/Modulus) */
   410  func (F *FP) jacobi() int {
   411  	w:=F.redc();
   412  	p:=NewBIGints(Modulus);
   413  	return w.Jacobi(p)
   414  }