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