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 }