github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/hyperledger/fabric-amcl/amcl/FP256BN/FP12.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  /* MiotCL Fp^12 functions */
    21  /* FP12 elements are of the form a+i.b+i^2.c */
    22  
    23  package FP256BN
    24  
    25  
    26  
    27  type FP12 struct {
    28  	a *FP4
    29  	b *FP4
    30  	c *FP4
    31  }
    32  
    33  /* Constructors */
    34  func NewFP12fp4(d *FP4) *FP12 {
    35  	F:=new(FP12)
    36  	F.a=NewFP4copy(d)
    37  	F.b=NewFP4int(0)
    38  	F.c=NewFP4int(0)
    39  	return F
    40  }
    41  
    42  func NewFP12int(d int) *FP12 {
    43  	F:=new(FP12)
    44  	F.a=NewFP4int(d)
    45  	F.b=NewFP4int(0)
    46  	F.c=NewFP4int(0)
    47  	return F
    48  }
    49  
    50  func NewFP12fp4s(d *FP4,e *FP4,f *FP4) *FP12 {
    51  	F:=new(FP12)
    52  	F.a=NewFP4copy(d)
    53  	F.b=NewFP4copy(e)
    54  	F.c=NewFP4copy(f)
    55  	return F
    56  }
    57  
    58  func NewFP12copy(x *FP12) *FP12 {
    59  	F:=new(FP12)
    60  	F.a=NewFP4copy(x.a)
    61  	F.b=NewFP4copy(x.b)
    62  	F.c=NewFP4copy(x.c)
    63  	return F
    64  }
    65  
    66  /* reduce all components of this mod Modulus */
    67  func (F *FP12) reduce() {
    68  	F.a.reduce()
    69  	F.b.reduce()
    70  	F.c.reduce()
    71  }
    72  /* normalise all components of this */
    73  func (F *FP12) norm() {
    74  	F.a.norm()
    75  	F.b.norm()
    76  	F.c.norm()
    77  }
    78  /* test x==0 ? */
    79  func (F *FP12) iszilch() bool {
    80  	//F.reduce()
    81  	return (F.a.iszilch() && F.b.iszilch() && F.c.iszilch())
    82  }
    83  
    84  /* Conditional move */
    85  func (F *FP12) cmove(g *FP12,d int) {
    86  	F.a.cmove(g.a,d)
    87  	F.b.cmove(g.b,d)
    88  	F.c.cmove(g.c,d)
    89  }
    90  
    91  /* Constant time select from pre-computed table */
    92  func (F *FP12) selector(g []*FP12,b int32) {
    93  
    94  	m:=b>>31
    95  	babs:=(b^m)-m
    96  
    97  	babs=(babs-1)/2
    98  
    99  	F.cmove(g[0],teq(babs,0))  // conditional move
   100  	F.cmove(g[1],teq(babs,1))
   101  	F.cmove(g[2],teq(babs,2))
   102  	F.cmove(g[3],teq(babs,3))
   103  	F.cmove(g[4],teq(babs,4))
   104  	F.cmove(g[5],teq(babs,5))
   105  	F.cmove(g[6],teq(babs,6))
   106  	F.cmove(g[7],teq(babs,7))
   107   
   108   	invF:=NewFP12copy(F) 
   109  	invF.conj()
   110  	F.cmove(invF,int(m&1))
   111  }
   112  
   113  /* test x==1 ? */
   114  func (F *FP12) Isunity() bool {
   115  	one:=NewFP4int(1)
   116  	return (F.a.Equals(one) && F.b.iszilch() && F.c.iszilch())
   117  }
   118  /* return 1 if x==y, else 0 */
   119  func (F *FP12) Equals(x *FP12) bool {
   120  	return (F.a.Equals(x.a) && F.b.Equals(x.b) && F.c.Equals(x.c))
   121  }
   122  
   123  /* extract a from this */
   124  func (F *FP12) geta() *FP4 {
   125  	return F.a
   126  }
   127  /* extract b */
   128  func (F *FP12) getb() *FP4 {
   129  	return F.b
   130  }
   131  /* extract c */
   132  func (F *FP12) getc() *FP4 {
   133  	return F.c
   134  }
   135  /* copy this=x */
   136  func (F *FP12) Copy(x *FP12) {
   137  	F.a.copy(x.a)
   138  	F.b.copy(x.b)
   139  	F.c.copy(x.c)
   140  }
   141  /* set this=1 */
   142  func (F *FP12) one() {
   143  	F.a.one()
   144  	F.b.zero()
   145  	F.c.zero()
   146  }
   147  /* this=conj(this) */
   148  func (F *FP12) conj() {
   149  	F.a.conj()
   150  	F.b.nconj()
   151  	F.c.conj()
   152  }
   153  
   154  /* Granger-Scott Unitary Squaring */
   155  func (F *FP12) usqr() {
   156  	A:=NewFP4copy(F.a)
   157  	B:=NewFP4copy(F.c)
   158  	C:=NewFP4copy(F.b)
   159  	D:=NewFP4int(0)
   160  
   161  	F.a.sqr()
   162  	D.copy(F.a); D.add(F.a)
   163  	F.a.add(D)
   164  
   165  	F.a.norm();
   166  	A.nconj()
   167  
   168  	A.add(A)
   169  	F.a.add(A)
   170  	B.sqr()
   171  	B.times_i()
   172  
   173  	D.copy(B); D.add(B)
   174  	B.add(D)
   175  	B.norm();
   176  
   177  	C.sqr()
   178  	D.copy(C); D.add(C)
   179  	C.add(D)
   180  	C.norm();
   181  
   182  	F.b.conj()
   183  	F.b.add(F.b)
   184  	F.c.nconj()
   185  
   186  	F.c.add(F.c)
   187  	F.b.add(B)
   188  	F.c.add(C)
   189  	F.reduce()
   190  
   191  }
   192  
   193  /* Chung-Hasan SQR2 method from http://cacr.uwaterloo.ca/techreports/2006/cacr2006-24.pdf */
   194  func (F *FP12)  sqr() {
   195  	A:=NewFP4copy(F.a)
   196  	B:=NewFP4copy(F.b)
   197  	C:=NewFP4copy(F.c)
   198  	D:=NewFP4copy(F.a)
   199  
   200  	A.sqr()
   201  	B.mul(F.c)
   202  	B.add(B); B.norm()
   203  	C.sqr()
   204  	D.mul(F.b)
   205  	D.add(D)
   206  
   207  	F.c.add(F.a)
   208  	F.c.add(F.b); F.c.norm()
   209  	F.c.sqr()
   210  
   211  	F.a.copy(A)
   212  
   213  	A.add(B)
   214  	A.norm();
   215  	A.add(C)
   216  	A.add(D)
   217  	A.norm();
   218  
   219  	A.neg()
   220  	B.times_i();
   221  	C.times_i()
   222  
   223  	F.a.add(B)
   224  
   225  	F.b.copy(C); F.b.add(D)
   226  	F.c.add(A)
   227  	F.norm()
   228  }
   229  
   230  /* FP12 full multiplication this=this*y */
   231  func (F *FP12) Mul(y *FP12) {
   232  	z0:=NewFP4copy(F.a)
   233  	z1:=NewFP4int(0)
   234  	z2:=NewFP4copy(F.b)
   235  	z3:=NewFP4int(0)
   236  	t0:=NewFP4copy(F.a)
   237  	t1:=NewFP4copy(y.a)
   238  
   239  	z0.mul(y.a)
   240  	z2.mul(y.b)
   241  
   242  	t0.add(F.b); t0.norm()
   243  	t1.add(y.b); t1.norm() 
   244  
   245  	z1.copy(t0); z1.mul(t1)
   246  	t0.copy(F.b); t0.add(F.c); t0.norm()
   247  
   248  	t1.copy(y.b); t1.add(y.c); t1.norm()
   249  	z3.copy(t0); z3.mul(t1)
   250  
   251  	t0.copy(z0); t0.neg()
   252  	t1.copy(z2); t1.neg()
   253  
   254  	z1.add(t0)
   255  	//z1.norm();
   256  	F.b.copy(z1); F.b.add(t1)
   257  
   258  	z3.add(t1)
   259  	z2.add(t0)
   260  
   261  	t0.copy(F.a); t0.add(F.c); t0.norm()
   262  	t1.copy(y.a); t1.add(y.c); t1.norm()
   263  	t0.mul(t1)
   264  	z2.add(t0)
   265  
   266  	t0.copy(F.c); t0.mul(y.c)
   267  	t1.copy(t0); t1.neg()
   268  
   269  	F.c.copy(z2); F.c.add(t1)
   270  	z3.add(t1)
   271  	t0.times_i()
   272  	F.b.add(t0)
   273  	z3.norm()
   274  	z3.times_i()
   275  	F.a.copy(z0); F.a.add(z3)
   276  	F.norm()
   277  }
   278  
   279  /* Special case of multiplication arises from special form of ATE pairing line function */
   280  func (F *FP12) smul(y *FP12,twist int ) {
   281  	if twist==D_TYPE {
   282  		z0:=NewFP4copy(F.a)
   283  		z2:=NewFP4copy(F.b)
   284  		z3:=NewFP4copy(F.b)
   285  		t0:=NewFP4int(0)
   286  		t1:=NewFP4copy(y.a)
   287  		
   288  		z0.mul(y.a)
   289  		z2.pmul(y.b.real());
   290  		F.b.add(F.a)
   291  		t1.real().add(y.b.real())
   292  
   293  		t1.norm(); F.b.norm()
   294  		F.b.mul(t1)
   295  		z3.add(F.c); z3.norm()
   296  		z3.pmul(y.b.real())
   297  
   298  		t0.copy(z0); t0.neg()
   299  		t1.copy(z2); t1.neg()
   300  
   301  		F.b.add(t0)
   302  	//F.b.norm();
   303  
   304  		F.b.add(t1)
   305  		z3.add(t1); z3.norm()
   306  		z2.add(t0)
   307  
   308  		t0.copy(F.a); t0.add(F.c); t0.norm()
   309  		t0.mul(y.a)
   310  		F.c.copy(z2); F.c.add(t0)
   311  
   312  		z3.times_i()
   313  		F.a.copy(z0); F.a.add(z3)
   314  	}
   315  	if twist==M_TYPE {
   316  		z0:=NewFP4copy(F.a)
   317  		z1:=NewFP4int(0)
   318  		z2:=NewFP4int(0)
   319  		z3:=NewFP4int(0)
   320  		t0:=NewFP4copy(F.a)
   321  		t1:=NewFP4int(0)
   322  		
   323  		z0.mul(y.a)
   324  		t0.add(F.b)
   325  		t0.norm()
   326  
   327  		z1.copy(t0); z1.mul(y.a)
   328  		t0.copy(F.b); t0.add(F.c)
   329  		t0.norm()
   330  
   331  		z3.copy(t0) //z3.mul(y.c);
   332  		z3.pmul(y.c.getb())
   333  		z3.times_i()
   334  
   335  		t0.copy(z0); t0.neg()
   336  
   337  		z1.add(t0)
   338  		F.b.copy(z1) 
   339  		z2.copy(t0)
   340  
   341  		t0.copy(F.a); t0.add(F.c)
   342  		t1.copy(y.a); t1.add(y.c)
   343  
   344  		t0.norm()
   345  		t1.norm()
   346  	
   347  		t0.mul(t1)
   348  		z2.add(t0)
   349  
   350  		t0.copy(F.c)
   351  			
   352  		t0.pmul(y.c.getb())
   353  		t0.times_i()
   354  
   355  		t1.copy(t0); t1.neg()
   356  
   357  		F.c.copy(z2); F.c.add(t1)
   358  		z3.add(t1)
   359  		t0.times_i()
   360  		F.b.add(t0)
   361  		z3.norm()
   362  		z3.times_i()
   363  		F.a.copy(z0); F.a.add(z3)
   364  	}
   365  	F.norm()
   366  }
   367  
   368  /* this=1/this */
   369  func (F *FP12) Inverse() {
   370  	f0:=NewFP4copy(F.a)
   371  	f1:=NewFP4copy(F.b)
   372  	f2:=NewFP4copy(F.a)
   373  	f3:=NewFP4int(0)
   374  
   375  	F.norm()
   376  	f0.sqr()
   377  	f1.mul(F.c)
   378  	f1.times_i()
   379  	f0.sub(f1); f0.norm()
   380  
   381  	f1.copy(F.c); f1.sqr()
   382  	f1.times_i()
   383  	f2.mul(F.b)
   384  	f1.sub(f2); f1.norm()
   385  
   386  	f2.copy(F.b); f2.sqr()
   387  	f3.copy(F.a); f3.mul(F.c)
   388  	f2.sub(f3); f2.norm()
   389  
   390  	f3.copy(F.b); f3.mul(f2)
   391  	f3.times_i()
   392  	F.a.mul(f0)
   393  	f3.add(F.a)
   394  	F.c.mul(f1)
   395  	F.c.times_i()
   396  
   397  	f3.add(F.c); f3.norm()
   398  	f3.inverse()
   399  	F.a.copy(f0); F.a.mul(f3)
   400  	F.b.copy(f1); F.b.mul(f3)
   401  	F.c.copy(f2); F.c.mul(f3)
   402  }
   403  
   404  /* this=this^p using Frobenius */
   405  func (F *FP12) frob(f *FP2) {
   406  	f2:=NewFP2copy(f)
   407  	f3:=NewFP2copy(f)
   408  
   409  	f2.sqr()
   410  	f3.mul(f2)
   411  
   412  	F.a.frob(f3);
   413  	F.b.frob(f3);
   414  	F.c.frob(f3);
   415  
   416  	F.b.pmul(f);
   417  	F.c.pmul(f2);
   418  }
   419  
   420  /* trace function */
   421  func (F *FP12) trace() *FP4 {
   422  	t:=NewFP4int(0)
   423  	t.copy(F.a)
   424  	t.imul(3)
   425  	t.reduce()
   426  	return t;
   427  }
   428  
   429  /* convert from byte array to FP12 */
   430  func FP12_fromBytes(w []byte) *FP12 {
   431  	var t [int(MODBYTES)]byte
   432  	MB:=int(MODBYTES)
   433  
   434  	for i:=0;i<MB;i++ {t[i]=w[i]}
   435  	a:=FromBytes(t[:])
   436  	for i:=0;i<MB;i++ {t[i]=w[i+MB]}
   437  	b:=FromBytes(t[:])
   438  	c:=NewFP2bigs(a,b)
   439  
   440  	for i:=0;i<MB;i++ {t[i]=w[i+2*MB]}
   441  	a=FromBytes(t[:])
   442  	for i:=0;i<MB;i++ {t[i]=w[i+3*MB]}
   443  	b=FromBytes(t[:])
   444  	d:=NewFP2bigs(a,b)
   445  
   446  	e:=NewFP4fp2s(c,d)
   447  
   448  
   449  	for i:=0;i<MB;i++ {t[i]=w[i+4*MB]}
   450  	a=FromBytes(t[:])
   451  	for i:=0;i<MB;i++ {t[i]=w[i+5*MB]}
   452  	b=FromBytes(t[:])
   453  	c=NewFP2bigs(a,b)
   454  
   455  	for i:=0;i<MB;i++ {t[i]=w[i+6*MB]}
   456  	a=FromBytes(t[:])
   457  	for i:=0;i<MB;i++ {t[i]=w[i+7*MB]}
   458  	b=FromBytes(t[:])
   459  	d=NewFP2bigs(a,b)
   460  
   461  	f:=NewFP4fp2s(c,d)
   462  
   463  
   464  	for i:=0;i<MB;i++ {t[i]=w[i+8*MB]}
   465  	a=FromBytes(t[:])
   466  	for i:=0;i<MB;i++ {t[i]=w[i+9*MB]}
   467  	b=FromBytes(t[:]);
   468  		
   469  	c=NewFP2bigs(a,b)
   470  
   471  	for i:=0;i<MB;i++ {t[i]=w[i+10*MB]}
   472  	a=FromBytes(t[:])
   473  	for i:=0;i<MB;i++ {t[i]=w[i+11*MB]}
   474  	b=FromBytes(t[:])
   475  	d=NewFP2bigs(a,b)
   476  
   477  	g:=NewFP4fp2s(c,d)
   478  
   479  	return NewFP12fp4s(e,f,g)
   480  }
   481  
   482  /* convert this to byte array */
   483  func (F *FP12) ToBytes(w []byte) {
   484  	var t [int(MODBYTES)]byte
   485  	MB:=int(MODBYTES)
   486  	F.a.geta().GetA().ToBytes(t[:])
   487  	for i:=0;i<MB;i++ {w[i]=t[i]}
   488  	F.a.geta().GetB().ToBytes(t[:])
   489  	for i:=0;i<MB;i++ {w[i+MB]=t[i]}
   490  	F.a.getb().GetA().ToBytes(t[:])
   491  	for i:=0;i<MB;i++ {w[i+2*MB]=t[i]}
   492  	F.a.getb().GetB().ToBytes(t[:])
   493  	for i:=0;i<MB;i++ {w[i+3*MB]=t[i]}
   494  
   495  	F.b.geta().GetA().ToBytes(t[:])
   496  	for i:=0;i<MB;i++ {w[i+4*MB]=t[i]}
   497  	F.b.geta().GetB().ToBytes(t[:])
   498  	for i:=0;i<MB;i++ {w[i+5*MB]=t[i]}
   499  	F.b.getb().GetA().ToBytes(t[:])
   500  	for i:=0;i<MB;i++ {w[i+6*MB]=t[i]}
   501  	F.b.getb().GetB().ToBytes(t[:])
   502  	for i:=0;i<MB;i++ {w[i+7*MB]=t[i]}
   503  
   504  	F.c.geta().GetA().ToBytes(t[:])
   505  	for i:=0;i<MB;i++ {w[i+8*MB]=t[i]}
   506  	F.c.geta().GetB().ToBytes(t[:])
   507  	for i:=0;i<MB;i++ {w[i+9*MB]=t[i]}
   508  	F.c.getb().GetA().ToBytes(t[:])
   509  	for i:=0;i<MB;i++ {w[i+10*MB]=t[i]}
   510  	F.c.getb().GetB().ToBytes(t[:])
   511  	for i:=0;i<MB;i++ {w[i+11*MB]=t[i]}
   512  }
   513  
   514  /* convert to hex string */
   515  func (F *FP12) toString() string {
   516  	return ("["+F.a.toString()+","+F.b.toString()+","+F.c.toString()+"]")
   517  }
   518  
   519  /* this=this^e */ 
   520  func (F *FP12) Pow(e *BIG) *FP12 {
   521  	F.norm()
   522  	e.norm()
   523  	e3:=NewBIGcopy(e)
   524  	e3.pmul(3)
   525  	e3.norm()
   526  
   527  	w:=NewFP12copy(F)
   528  	//z:=NewBIGcopy(e)
   529  	//r:=NewFP12int(1)
   530  
   531  	nb:=e3.nbits()
   532  	for i:=nb-2;i>=1;i-- {
   533  		w.usqr()
   534  		bt:=e3.bit(i)-e.bit(i)
   535  		if bt==1 {
   536  			w.Mul(F)
   537  		}
   538  		if bt==-1 {
   539  			F.conj()
   540  			w.Mul(F)
   541  			F.conj()	
   542  		}
   543  	}
   544  	w.reduce()
   545  	return w
   546  /*
   547  	for true {
   548  		bt:=z.parity()
   549  		z.fshr(1)
   550  		if bt==1 {r.Mul(w)}
   551  		if z.iszilch() {break}
   552  		w.usqr()
   553  	}
   554  	r.reduce();
   555  	return r; */
   556  }
   557  
   558  /* constant time powering by small integer of max length bts */
   559  func (F *FP12) pinpow(e int,bts int) {
   560  	var R []*FP12
   561  	R=append(R,NewFP12int(1))
   562  	R=append(R,NewFP12copy(F))
   563  
   564  	for i:=bts-1;i>=0;i-- {
   565  		b:=(e>>uint(i))&1
   566  		R[1-b].Mul(R[b])
   567  		R[b].usqr()
   568  	}
   569  	F.Copy(R[0])
   570  }
   571  
   572  /* Fast compressed FP4 power of unitary FP12 */
   573  func (F *FP12) Compow(e *BIG,r *BIG) *FP4 {
   574  	q:=NewBIGints(Modulus)
   575  	//r:=NewBIGints(CURVE_Order)
   576  	f:=NewFP2bigs(NewBIGints(Fra),NewBIGints(Frb))
   577  
   578  	m:=NewBIGcopy(q)
   579  	m.Mod(r)
   580  
   581  	a:=NewBIGcopy(e)
   582  	a.Mod(m)
   583  
   584  	b:=NewBIGcopy(e)
   585  	b.div(m)
   586  
   587  	g1:=NewFP12copy(F);
   588  	c:=g1.trace()
   589  
   590  	if b.iszilch() {
   591  		c=c.xtr_pow(e)
   592  		return c
   593  	}
   594  
   595  	g2:=NewFP12copy(F)
   596  	g2.frob(f)
   597  	cp:=g2.trace()
   598  
   599  	g1.conj()
   600  	g2.Mul(g1)
   601  	cpm1:=g2.trace()
   602  	g2.Mul(g1)
   603  	cpm2:=g2.trace()
   604  
   605  	c=c.xtr_pow2(cp,cpm1,cpm2,a,b)
   606  	return c
   607  }
   608  
   609  /* p=q0^u0.q1^u1.q2^u2.q3^u3 */
   610  // Bos & Costello https://eprint.iacr.org/2013/458.pdf
   611  // Faz-Hernandez & Longa & Sanchez  https://eprint.iacr.org/2013/158.pdf
   612  // Side channel attack secure 
   613  
   614  func pow4(q []*FP12,u []*BIG) *FP12 {
   615  	var g []*FP12
   616  	var w [NLEN*int(BASEBITS)+1]int8
   617  	var s [NLEN*int(BASEBITS)+1]int8
   618  	var t []*BIG
   619  	r:=NewFP12int(0)
   620  	p:=NewFP12int(0)
   621  	mt:=NewBIGint(0)
   622  
   623  	for i:=0;i<4;i++ {
   624  		t=append(t,NewBIGcopy(u[i]))
   625  	}
   626  
   627  	g=append(g,NewFP12copy(q[0]))	// q[0]
   628  	g=append(g,NewFP12copy(g[0])); g[1].Mul(q[1])	// q[0].q[1]
   629  	g=append(g,NewFP12copy(g[0])); g[2].Mul(q[2])	// q[0].q[2]
   630  	g=append(g,NewFP12copy(g[1])); g[3].Mul(q[2])	// q[0].q[1].q[2]
   631  	g=append(g,NewFP12copy(g[0])); g[4].Mul(q[3])	// q[0].q[3]
   632  	g=append(g,NewFP12copy(g[1])); g[5].Mul(q[3])	// q[0].q[1].q[3]
   633  	g=append(g,NewFP12copy(g[2])); g[6].Mul(q[3])	// q[0].q[2].q[3]
   634  	g=append(g,NewFP12copy(g[3])); g[7].Mul(q[3])	// q[0].q[1].q[2].q[3]
   635  
   636  // Make it odd
   637  	pb:=1-t[0].parity()
   638  	t[0].inc(pb)
   639  //	t[0].norm();
   640  
   641  // Number of bits
   642  	mt.zero()
   643  	for i:=0;i<4;i++ {
   644  		t[i].norm()
   645  		mt.or(t[i])
   646  	}
   647  
   648  	nb:=1+mt.nbits();
   649  
   650  // Sign pivot 
   651  	s[nb-1]=1
   652  	for i:=0;i<nb-1;i++ {
   653  		t[0].fshr(1)
   654  		s[i]=2*int8(t[0].parity())-1
   655  	}
   656  
   657  // Recoded exponent
   658  	for i:=0; i<nb; i++ {
   659  		w[i]=0
   660  		k:=1
   661  		for j:=1; j<4; j++ {
   662  			bt:=s[i]*int8(t[j].parity())
   663  			t[j].fshr(1)
   664  			t[j].dec(int(bt)>>1)
   665  			t[j].norm()
   666  			w[i]+=bt*int8(k)
   667  			k*=2
   668  		}
   669  	}
   670  
   671  // Main loop
   672  	p.selector(g,int32(2*w[nb-1]+1))  
   673  	for i:=nb-2;i>=0;i-- {
   674  		p.usqr()
   675  		r.selector(g,int32(2*w[i]+s[i]))
   676  		p.Mul(r)
   677  	}
   678  
   679  // apply correction
   680  	r.Copy(q[0]); r.conj()   
   681  	r.Mul(p)
   682  	p.cmove(r,pb)
   683  
   684  	p.reduce()
   685  	return p;
   686  }
   687  
   688  /*
   689  func pow4(q []*FP12,u []*BIG) *FP12 {
   690  	var a [4]int8
   691  	var g []*FP12
   692  	var s []*FP12
   693  	c:=NewFP12int(1)
   694  	p:=NewFP12int(0)
   695  	var w [NLEN*int(BASEBITS)+1]int8
   696  	var t []*BIG
   697  	mt:=NewBIGint(0)
   698  
   699  	for i:=0;i<4;i++ {
   700  		t=append(t,NewBIGcopy(u[i]))
   701  	}
   702  
   703  	s=append(s,NewFP12int(0))
   704  	s=append(s,NewFP12int(0))
   705  
   706  	g=append(g,NewFP12copy(q[0])); s[0].Copy(q[1]); s[0].conj(); g[0].Mul(s[0])
   707  	g=append(g,NewFP12copy(g[0]))
   708  	g=append(g,NewFP12copy(g[0]))
   709  	g=append(g,NewFP12copy(g[0]))
   710  	g=append(g,NewFP12copy(q[0])); g[4].Mul(q[1])
   711  	g=append(g,NewFP12copy(g[4]))
   712  	g=append(g,NewFP12copy(g[4]))
   713  	g=append(g,NewFP12copy(g[4]))
   714  
   715  	s[1].Copy(q[2]); s[0].Copy(q[3]); s[0].conj(); s[1].Mul(s[0])
   716  	s[0].Copy(s[1]); s[0].conj(); g[1].Mul(s[0])
   717  	g[2].Mul(s[1])
   718  	g[5].Mul(s[0])
   719  	g[6].Mul(s[1])
   720  	s[1].Copy(q[2]); s[1].Mul(q[3])
   721  	s[0].Copy(s[1]); s[0].conj(); g[0].Mul(s[0])
   722  	g[3].Mul(s[1])
   723  	g[4].Mul(s[0])
   724  	g[7].Mul(s[1])
   725  
   726  // if power is even add 1 to power, and add q to correction 
   727  
   728  	for i:=0;i<4;i++ {
   729  		if t[i].parity()==0 {
   730  			t[i].inc(1); t[i].norm()
   731  			c.Mul(q[i])
   732  		}
   733  		mt.add(t[i]); mt.norm()
   734  	}
   735  	c.conj()
   736  	nb:=1+mt.nbits()
   737  
   738  // convert exponent to signed 1-bit window 
   739  	for j:=0;j<nb;j++ {
   740  		for i:=0;i<4;i++ {
   741  			a[i]=int8(t[i].lastbits(2)-2)
   742  			t[i].dec(int(a[i])); t[i].norm();
   743  			t[i].fshr(1)
   744  		}
   745  		w[j]=(8*a[0]+4*a[1]+2*a[2]+a[3])
   746  	}
   747  	w[nb]=int8(8*t[0].lastbits(2)+4*t[1].lastbits(2)+2*t[2].lastbits(2)+t[3].lastbits(2))
   748  	p.Copy(g[(w[nb]-1)/2])
   749  
   750  	for i:=nb-1;i>=0;i-- {
   751  		m:=w[i]>>7
   752  		j:=(w[i]^m)-m  // j=abs(w[i]) 
   753  		j=(j-1)/2
   754  		s[0].Copy(g[j]); s[1].Copy(g[j]); s[1].conj()
   755  		p.usqr()
   756  		p.Mul(s[m&1]);
   757  	}
   758  	p.Mul(c)  // apply correction 
   759  	p.reduce()
   760  	return p;
   761  }
   762  */
   763