github.com/consensys/gnark-crypto@v0.14.0/field/generator/internal/templates/element/tests.go (about) 1 package element 2 3 const Test = ` 4 5 6 import ( 7 "crypto/rand" 8 "encoding/json" 9 "math/big" 10 "math/bits" 11 "fmt" 12 {{if .UsingP20Inverse}} 13 mrand "math/rand" 14 {{end}} 15 "testing" 16 17 "github.com/leanovate/gopter" 18 "github.com/leanovate/gopter/prop" 19 ggen "github.com/leanovate/gopter/gen" 20 21 "github.com/stretchr/testify/require" 22 ) 23 24 25 // ------------------------------------------------------------------------------------------------- 26 // benchmarks 27 // most benchmarks are rudimentary and should sample a large number of random inputs 28 // or be run multiple times to ensure it didn't measure the fastest path of the function 29 30 var benchRes{{.ElementName}} {{.ElementName}} 31 32 func Benchmark{{toTitle .ElementName}}Select(b *testing.B) { 33 var x, y {{.ElementName}} 34 x.SetRandom() 35 y.SetRandom() 36 37 b.ResetTimer() 38 for i := 0; i < b.N; i++ { 39 benchRes{{.ElementName}}.Select(i%3, &x, &y) 40 } 41 } 42 43 func Benchmark{{toTitle .ElementName}}SetRandom(b *testing.B) { 44 var x {{.ElementName}} 45 x.SetRandom() 46 47 b.ResetTimer() 48 for i := 0; i < b.N; i++ { 49 _, _ = x.SetRandom() 50 } 51 } 52 53 func Benchmark{{toTitle .ElementName}}SetBytes(b *testing.B) { 54 var x {{.ElementName}} 55 x.SetRandom() 56 bb := x.Bytes() 57 b.ResetTimer() 58 59 for i := 0; i < b.N; i++ { 60 benchRes{{.ElementName}}.SetBytes(bb[:]) 61 } 62 63 } 64 65 func Benchmark{{toTitle .ElementName}}MulByConstants(b *testing.B) { 66 b.Run("mulBy3", func(b *testing.B){ 67 benchRes{{.ElementName}}.SetRandom() 68 b.ResetTimer() 69 for i := 0; i < b.N; i++ { 70 MulBy3(&benchRes{{.ElementName}}) 71 } 72 }) 73 b.Run("mulBy5", func(b *testing.B){ 74 benchRes{{.ElementName}}.SetRandom() 75 b.ResetTimer() 76 for i := 0; i < b.N; i++ { 77 MulBy5(&benchRes{{.ElementName}}) 78 } 79 }) 80 b.Run("mulBy13", func(b *testing.B){ 81 benchRes{{.ElementName}}.SetRandom() 82 b.ResetTimer() 83 for i := 0; i < b.N; i++ { 84 MulBy13(&benchRes{{.ElementName}}) 85 } 86 }) 87 } 88 89 func Benchmark{{toTitle .ElementName}}Inverse(b *testing.B) { 90 var x {{.ElementName}} 91 x.SetRandom() 92 benchRes{{.ElementName}}.SetRandom() 93 b.ResetTimer() 94 95 for i := 0; i < b.N; i++ { 96 benchRes{{.ElementName}}.Inverse(&x) 97 } 98 99 } 100 101 func Benchmark{{toTitle .ElementName}}Butterfly(b *testing.B) { 102 var x {{.ElementName}} 103 x.SetRandom() 104 benchRes{{.ElementName}}.SetRandom() 105 b.ResetTimer() 106 for i := 0; i < b.N; i++ { 107 Butterfly(&x, &benchRes{{.ElementName}}) 108 } 109 } 110 111 112 func Benchmark{{toTitle .ElementName}}Exp(b *testing.B) { 113 var x {{.ElementName}} 114 x.SetRandom() 115 benchRes{{.ElementName}}.SetRandom() 116 b1, _ := rand.Int(rand.Reader, Modulus()) 117 b.ResetTimer() 118 for i := 0; i < b.N; i++ { 119 benchRes{{.ElementName}}.Exp(x, b1) 120 } 121 } 122 123 124 func Benchmark{{toTitle .ElementName}}Double(b *testing.B) { 125 benchRes{{.ElementName}}.SetRandom() 126 b.ResetTimer() 127 for i := 0; i < b.N; i++ { 128 benchRes{{.ElementName}}.Double(&benchRes{{.ElementName}}) 129 } 130 } 131 132 133 func Benchmark{{toTitle .ElementName}}Add(b *testing.B) { 134 var x {{.ElementName}} 135 x.SetRandom() 136 benchRes{{.ElementName}}.SetRandom() 137 b.ResetTimer() 138 for i := 0; i < b.N; i++ { 139 benchRes{{.ElementName}}.Add(&x, &benchRes{{.ElementName}}) 140 } 141 } 142 143 func Benchmark{{toTitle .ElementName}}Sub(b *testing.B) { 144 var x {{.ElementName}} 145 x.SetRandom() 146 benchRes{{.ElementName}}.SetRandom() 147 b.ResetTimer() 148 for i := 0; i < b.N; i++ { 149 benchRes{{.ElementName}}.Sub(&x, &benchRes{{.ElementName}}) 150 } 151 } 152 153 func Benchmark{{toTitle .ElementName}}Neg(b *testing.B) { 154 benchRes{{.ElementName}}.SetRandom() 155 b.ResetTimer() 156 for i := 0; i < b.N; i++ { 157 benchRes{{.ElementName}}.Neg(&benchRes{{.ElementName}}) 158 } 159 } 160 161 func Benchmark{{toTitle .ElementName}}Div(b *testing.B) { 162 var x {{.ElementName}} 163 x.SetRandom() 164 benchRes{{.ElementName}}.SetRandom() 165 b.ResetTimer() 166 for i := 0; i < b.N; i++ { 167 benchRes{{.ElementName}}.Div(&x, &benchRes{{.ElementName}}) 168 } 169 } 170 171 172 func Benchmark{{toTitle .ElementName}}FromMont(b *testing.B) { 173 benchRes{{.ElementName}}.SetRandom() 174 b.ResetTimer() 175 for i := 0; i < b.N; i++ { 176 benchRes{{.ElementName}}.fromMont() 177 } 178 } 179 180 func Benchmark{{toTitle .ElementName}}Square(b *testing.B) { 181 benchRes{{.ElementName}}.SetRandom() 182 b.ResetTimer() 183 for i := 0; i < b.N; i++ { 184 benchRes{{.ElementName}}.Square(&benchRes{{.ElementName}}) 185 } 186 } 187 188 func Benchmark{{toTitle .ElementName}}Sqrt(b *testing.B) { 189 var a {{.ElementName}} 190 a.SetUint64(4) 191 a.Neg(&a) 192 b.ResetTimer() 193 for i := 0; i < b.N; i++ { 194 benchRes{{.ElementName}}.Sqrt(&a) 195 } 196 } 197 198 func Benchmark{{toTitle .ElementName}}Mul(b *testing.B) { 199 x := {{.ElementName}}{ 200 {{- range $i := .RSquare}} 201 {{$i}},{{end}} 202 } 203 benchRes{{.ElementName}}.SetOne() 204 b.ResetTimer() 205 for i := 0; i < b.N; i++ { 206 benchRes{{.ElementName}}.Mul(&benchRes{{.ElementName}}, &x) 207 } 208 } 209 210 func Benchmark{{toTitle .ElementName}}Cmp(b *testing.B) { 211 x := {{.ElementName}}{ 212 {{- range $i := .RSquare}} 213 {{$i}},{{end}} 214 } 215 benchRes{{.ElementName}} = x 216 benchRes{{.ElementName}}[0] = 0 217 b.ResetTimer() 218 for i := 0; i < b.N; i++ { 219 benchRes{{.ElementName}}.Cmp(&x) 220 } 221 } 222 223 func Test{{toTitle .ElementName}}Cmp(t *testing.T) { 224 var x, y {{.ElementName}} 225 226 if x.Cmp(&y) != 0 { 227 t.Fatal("x == y") 228 } 229 230 one := One() 231 y.Sub(&y, &one) 232 233 if x.Cmp(&y) != -1 { 234 t.Fatal("x < y") 235 } 236 if y.Cmp(&x) != 1 { 237 t.Fatal("x < y") 238 } 239 240 x = y 241 if x.Cmp(&y) != 0 { 242 t.Fatal("x == y") 243 } 244 245 x.Sub(&x, &one) 246 if x.Cmp(&y) != -1 { 247 t.Fatal("x < y") 248 } 249 if y.Cmp(&x) != 1 { 250 t.Fatal("x < y") 251 } 252 } 253 254 {{- if gt .NbWords 1}} 255 func Test{{toTitle .ElementName}}IsRandom(t *testing.T) { 256 for i := 0; i < 50; i++ { 257 var x, y {{.ElementName}} 258 x.SetRandom() 259 y.SetRandom() 260 if x.Equal(&y) { 261 t.Fatal("2 random numbers are unlikely to be equal") 262 } 263 } 264 } 265 266 func Test{{toTitle .ElementName}}IsUint64(t *testing.T) { 267 t.Parallel() 268 parameters := gopter.DefaultTestParameters() 269 if testing.Short() { 270 parameters.MinSuccessfulTests = nbFuzzShort 271 } else { 272 parameters.MinSuccessfulTests = nbFuzz 273 } 274 275 properties := gopter.NewProperties(parameters) 276 277 278 properties.Property("reduce should output a result smaller than modulus", prop.ForAll( 279 func(v uint64) bool { 280 var e {{.ElementName}} 281 e.SetUint64(v) 282 283 if !e.IsUint64() { 284 return false 285 } 286 287 return e.Uint64() == v 288 }, 289 ggen.UInt64(), 290 )) 291 292 properties.TestingRun(t, gopter.ConsoleReporter(false)) 293 } 294 295 {{- end}} 296 297 func Test{{toTitle .ElementName}}NegZero(t *testing.T) { 298 var a, b {{.ElementName}} 299 b.SetZero() 300 for a.IsZero() { 301 a.SetRandom() 302 } 303 a.Neg(&b) 304 if !a.IsZero() { 305 t.Fatal("neg(0) != 0") 306 } 307 } 308 309 // ------------------------------------------------------------------------------------------------- 310 // Gopter tests 311 // most of them are generated with a template 312 313 {{ if gt .NbWords 6}} 314 const ( 315 nbFuzzShort = 20 316 nbFuzz = 100 317 ) 318 {{else}} 319 const ( 320 nbFuzzShort = 200 321 nbFuzz = 1000 322 ) 323 {{end}} 324 325 // special values to be used in tests 326 var staticTestValues []{{.ElementName}} 327 328 func init() { 329 staticTestValues = append(staticTestValues, {{.ElementName}}{}) // zero 330 staticTestValues = append(staticTestValues, One()) // one 331 staticTestValues = append(staticTestValues, rSquare) // r² 332 var e, one {{.ElementName}} 333 one.SetOne() 334 e.Sub(&q{{.ElementName}}, &one) 335 staticTestValues = append(staticTestValues, e) // q - 1 336 e.Double(&one) 337 staticTestValues = append(staticTestValues, e) // 2 338 339 340 { 341 a := q{{.ElementName}} 342 a[0]-- 343 staticTestValues = append(staticTestValues, a) 344 } 345 346 {{- $qi := index $.Q $.NbWordsLastIndex}} 347 {{- range $i := iterate 0 3}} 348 staticTestValues = append(staticTestValues, {{$.ElementName}}{ {{$i}} }) 349 {{- if gt $.NbWords 1}} 350 {{- if le $i $qi}} 351 staticTestValues = append(staticTestValues, {{$.ElementName}}{0, {{$i}} }) 352 {{- end}} 353 {{- end}} 354 {{- end}} 355 356 { 357 a := q{{.ElementName}} 358 a[{{.NbWordsLastIndex}}]-- 359 staticTestValues = append(staticTestValues, a) 360 } 361 362 {{- if ne .NbWords 1}} 363 { 364 a := q{{.ElementName}} 365 a[{{.NbWordsLastIndex}}]-- 366 a[0]++ 367 staticTestValues = append(staticTestValues, a) 368 } 369 {{- end}} 370 371 { 372 a := q{{.ElementName}} 373 a[{{.NbWordsLastIndex}}] = 0 374 staticTestValues = append(staticTestValues, a) 375 } 376 377 } 378 379 func Test{{toTitle .ElementName}}Reduce(t *testing.T) { 380 testValues := make([]{{.ElementName}}, len(staticTestValues)) 381 copy(testValues, staticTestValues) 382 383 for i := range testValues { 384 s := testValues[i] 385 expected := s 386 reduce(&s) 387 _reduceGeneric(&expected) 388 if !s.Equal(&expected) { 389 t.Fatal("reduce failed: asm and generic impl don't match") 390 } 391 } 392 393 394 t.Parallel() 395 parameters := gopter.DefaultTestParameters() 396 if testing.Short() { 397 parameters.MinSuccessfulTests = nbFuzzShort 398 } else { 399 parameters.MinSuccessfulTests = nbFuzz 400 } 401 402 properties := gopter.NewProperties(parameters) 403 404 genA := genFull() 405 406 properties.Property("reduce should output a result smaller than modulus", prop.ForAll( 407 func(a {{.ElementName}}) bool { 408 b := a 409 reduce(&a) 410 _reduceGeneric(&b) 411 return a.smallerThanModulus() && a.Equal(&b) 412 }, 413 genA, 414 )) 415 416 properties.TestingRun(t, gopter.ConsoleReporter(false)) 417 418 419 } 420 421 func Test{{toTitle .ElementName}}Equal(t *testing.T) { 422 t.Parallel() 423 parameters := gopter.DefaultTestParameters() 424 if testing.Short() { 425 parameters.MinSuccessfulTests = nbFuzzShort 426 } else { 427 parameters.MinSuccessfulTests = nbFuzz 428 } 429 430 properties := gopter.NewProperties(parameters) 431 432 genA := gen() 433 genB := gen() 434 435 properties.Property("x.Equal(&y) iff x == y; likely false for random pairs", prop.ForAll( 436 func(a testPair{{.ElementName}}, b testPair{{.ElementName}}) bool { 437 return a.element.Equal(&b.element) == (a.element == b.element) 438 }, 439 genA, 440 genB, 441 )) 442 443 properties.Property("x.Equal(&y) if x == y", prop.ForAll( 444 func(a testPair{{.ElementName}}) bool { 445 b := a.element 446 return a.element.Equal(&b) 447 }, 448 genA, 449 )) 450 451 properties.TestingRun(t, gopter.ConsoleReporter(false)) 452 } 453 454 func Test{{toTitle .ElementName}}Bytes(t *testing.T) { 455 t.Parallel() 456 parameters := gopter.DefaultTestParameters() 457 if testing.Short() { 458 parameters.MinSuccessfulTests = nbFuzzShort 459 } else { 460 parameters.MinSuccessfulTests = nbFuzz 461 } 462 463 properties := gopter.NewProperties(parameters) 464 465 genA := gen() 466 467 properties.Property("SetBytes(Bytes()) should stay constant", prop.ForAll( 468 func(a testPair{{.ElementName}}) bool { 469 var b {{.ElementName}} 470 bytes := a.element.Bytes() 471 b.SetBytes(bytes[:]) 472 return a.element.Equal(&b) 473 }, 474 genA, 475 )) 476 477 properties.TestingRun(t, gopter.ConsoleReporter(false)) 478 } 479 480 func Test{{toTitle .ElementName}}InverseExp(t *testing.T) { 481 // inverse must be equal to exp^-2 482 exp := Modulus() 483 exp.Sub(exp, new(big.Int).SetUint64(2)) 484 485 invMatchExp := func(a testPair{{.ElementName}}) bool { 486 var b {{.ElementName}} 487 b.Set(&a.element) 488 a.element.Inverse(&a.element) 489 b.Exp(b, exp) 490 491 return a.element.Equal(&b) 492 } 493 494 t.Parallel() 495 parameters := gopter.DefaultTestParameters() 496 if testing.Short() { 497 parameters.MinSuccessfulTests = nbFuzzShort 498 } else { 499 parameters.MinSuccessfulTests = nbFuzz 500 } 501 properties := gopter.NewProperties(parameters) 502 genA := gen() 503 properties.Property("inv == exp^-2", prop.ForAll(invMatchExp, genA)) 504 properties.TestingRun(t, gopter.ConsoleReporter(false)) 505 506 parameters.MinSuccessfulTests = 1 507 properties = gopter.NewProperties(parameters) 508 properties.Property("inv(0) == 0", prop.ForAll(invMatchExp, ggen.OneConstOf(testPair{{.ElementName}}{}))) 509 properties.TestingRun(t, gopter.ConsoleReporter(false)) 510 511 512 } 513 514 515 func mulByConstant(z *{{.ElementName}}, c uint8) { 516 var y {{.ElementName}} 517 y.SetUint64(uint64(c)) 518 z.Mul(z, &y) 519 } 520 521 522 func Test{{toTitle .ElementName}}MulByConstants(t *testing.T) { 523 524 t.Parallel() 525 parameters := gopter.DefaultTestParameters() 526 if testing.Short() { 527 parameters.MinSuccessfulTests = nbFuzzShort 528 } else { 529 parameters.MinSuccessfulTests = nbFuzz 530 } 531 532 properties := gopter.NewProperties(parameters) 533 534 genA := gen() 535 536 implemented := []uint8{0,1,2,3,5,13} 537 properties.Property("mulByConstant", prop.ForAll( 538 func(a testPair{{.ElementName}}) bool { 539 for _, c := range implemented { 540 var constant {{.ElementName}} 541 constant.SetUint64(uint64(c)) 542 543 b := a.element 544 b.Mul(&b, &constant) 545 546 aa := a.element 547 mulByConstant(&aa, c) 548 549 if !aa.Equal(&b) { 550 return false 551 } 552 } 553 554 return true 555 }, 556 genA, 557 )) 558 559 560 properties.Property("MulBy3(x) == Mul(x, 3)", prop.ForAll( 561 func(a testPair{{.ElementName}}) bool { 562 var constant {{.ElementName}} 563 constant.SetUint64(3) 564 565 b := a.element 566 b.Mul(&b, &constant) 567 568 MulBy3(&a.element) 569 570 return a.element.Equal(&b) 571 }, 572 genA, 573 )) 574 575 properties.Property("MulBy5(x) == Mul(x, 5)", prop.ForAll( 576 func(a testPair{{.ElementName}}) bool { 577 var constant {{.ElementName}} 578 constant.SetUint64(5) 579 580 b := a.element 581 b.Mul(&b, &constant) 582 583 MulBy5(&a.element) 584 585 return a.element.Equal(&b) 586 }, 587 genA, 588 )) 589 590 properties.Property("MulBy13(x) == Mul(x, 13)", prop.ForAll( 591 func(a testPair{{.ElementName}}) bool { 592 var constant {{.ElementName}} 593 constant.SetUint64(13) 594 595 b := a.element 596 b.Mul(&b, &constant) 597 598 MulBy13(&a.element) 599 600 return a.element.Equal(&b) 601 }, 602 genA, 603 )) 604 605 properties.TestingRun(t, gopter.ConsoleReporter(false)) 606 607 608 } 609 610 func Test{{toTitle .ElementName}}Legendre(t *testing.T) { 611 t.Parallel() 612 parameters := gopter.DefaultTestParameters() 613 if testing.Short() { 614 parameters.MinSuccessfulTests = nbFuzzShort 615 } else { 616 parameters.MinSuccessfulTests = nbFuzz 617 } 618 619 properties := gopter.NewProperties(parameters) 620 621 genA := gen() 622 623 properties.Property("legendre should output same result than big.Int.Jacobi", prop.ForAll( 624 func(a testPair{{.ElementName}}) bool { 625 return a.element.Legendre() == big.Jacobi(&a.bigint, Modulus()) 626 }, 627 genA, 628 )) 629 630 properties.TestingRun(t, gopter.ConsoleReporter(false)) 631 632 633 } 634 635 func Test{{toTitle .ElementName}}BitLen(t *testing.T) { 636 t.Parallel() 637 parameters := gopter.DefaultTestParameters() 638 if testing.Short() { 639 parameters.MinSuccessfulTests = nbFuzzShort 640 } else { 641 parameters.MinSuccessfulTests = nbFuzz 642 } 643 644 properties := gopter.NewProperties(parameters) 645 646 genA := gen() 647 648 properties.Property("BitLen should output same result than big.Int.BitLen", prop.ForAll( 649 func(a testPair{{.ElementName}}) bool { 650 return a.element.fromMont().BitLen() == a.bigint.BitLen() 651 }, 652 genA, 653 )) 654 655 properties.TestingRun(t, gopter.ConsoleReporter(false)) 656 657 658 } 659 660 661 662 func Test{{toTitle .ElementName}}Butterflies(t *testing.T) { 663 664 t.Parallel() 665 parameters := gopter.DefaultTestParameters() 666 if testing.Short() { 667 parameters.MinSuccessfulTests = nbFuzzShort 668 } else { 669 parameters.MinSuccessfulTests = nbFuzz 670 } 671 672 properties := gopter.NewProperties(parameters) 673 674 genA := gen() 675 676 properties.Property("butterfly0 == a -b; a +b", prop.ForAll( 677 func(a,b testPair{{.ElementName}}) bool { 678 a0, b0 := a.element, b.element 679 680 _butterflyGeneric(&a.element, &b.element) 681 Butterfly(&a0, &b0) 682 683 return a.element.Equal(&a0) && b.element.Equal(&b0) 684 }, 685 genA, 686 genA, 687 )) 688 689 properties.TestingRun(t, gopter.ConsoleReporter(false)) 690 691 692 } 693 694 func Test{{toTitle .ElementName}}LexicographicallyLargest(t *testing.T) { 695 t.Parallel() 696 parameters := gopter.DefaultTestParameters() 697 if testing.Short() { 698 parameters.MinSuccessfulTests = nbFuzzShort 699 } else { 700 parameters.MinSuccessfulTests = nbFuzz 701 } 702 703 properties := gopter.NewProperties(parameters) 704 705 genA := gen() 706 707 properties.Property("element.Cmp should match LexicographicallyLargest output", prop.ForAll( 708 func(a testPair{{.ElementName}}) bool { 709 var negA {{.ElementName}} 710 negA.Neg(&a.element) 711 712 cmpResult := a.element.Cmp(&negA) 713 lResult := a.element.LexicographicallyLargest() 714 715 if lResult && cmpResult == 1 { 716 return true 717 } 718 if !lResult && cmpResult !=1 { 719 return true 720 } 721 return false 722 }, 723 genA, 724 )) 725 726 properties.TestingRun(t, gopter.ConsoleReporter(false)) 727 728 729 } 730 731 732 {{template "testBinaryOp" dict "all" . "Op" "Add"}} 733 {{template "testBinaryOp" dict "all" . "Op" "Sub"}} 734 {{template "testBinaryOp" dict "all" . "Op" "Mul" "GenericOp" "_mulGeneric"}} 735 {{template "testBinaryOp" dict "all" . "Op" "Div"}} 736 {{template "testBinaryOp" dict "all" . "Op" "Exp"}} 737 738 {{template "testUnaryOp" dict "all" . "Op" "Square" }} 739 {{template "testUnaryOp" dict "all" . "Op" "Inverse"}} 740 {{template "testUnaryOp" dict "all" . "Op" "Sqrt"}} 741 {{template "testUnaryOp" dict "all" . "Op" "Double"}} 742 {{template "testUnaryOp" dict "all" . "Op" "Neg" }} 743 744 {{ define "testBinaryOp" }} 745 746 func Test{{toTitle .all.ElementName}}{{.Op}}(t *testing.T) { 747 t.Parallel() 748 parameters := gopter.DefaultTestParameters() 749 if testing.Short() { 750 parameters.MinSuccessfulTests = nbFuzzShort 751 } else { 752 parameters.MinSuccessfulTests = nbFuzz 753 } 754 755 756 properties := gopter.NewProperties(parameters) 757 758 genA := gen() 759 genB := gen() 760 761 properties.Property("{{.Op}}: having the receiver as operand should output the same result", prop.ForAll( 762 func(a, b testPair{{.all.ElementName}}) bool { 763 var c, d {{.all.ElementName}} 764 d.Set(&a.element) 765 {{if eq .Op "Exp"}} 766 c.{{.Op}}(a.element, &b.bigint) 767 a.element.{{.Op}}(a.element, &b.bigint) 768 b.element.{{.Op}}(d, &b.bigint) 769 {{else}} 770 c.{{.Op}}(&a.element, &b.element) 771 a.element.{{.Op}}(&a.element, &b.element) 772 b.element.{{.Op}}(&d, &b.element) 773 {{end}} 774 return a.element.Equal(&b.element) && a.element.Equal(&c) && b.element.Equal(&c) 775 }, 776 genA, 777 genB, 778 )) 779 780 properties.Property("{{.Op}}: operation result must match big.Int result", prop.ForAll( 781 func(a, b testPair{{.all.ElementName}}) bool { 782 { 783 var c {{.all.ElementName}} 784 {{if eq .Op "Exp"}} 785 c.{{.Op}}(a.element, &b.bigint) 786 {{else}} 787 c.{{.Op}}(&a.element, &b.element) 788 {{end}} 789 var d, e big.Int 790 {{- if eq .Op "Div"}} 791 d.ModInverse(&b.bigint, Modulus()) 792 d.Mul(&d, &a.bigint).Mod(&d, Modulus()) 793 {{- else if eq .Op "Exp"}} 794 d.Exp(&a.bigint, &b.bigint, Modulus()) 795 {{- else}} 796 d.{{.Op}}(&a.bigint, &b.bigint).Mod(&d, Modulus()) 797 {{- end }} 798 799 800 if c.BigInt(&e).Cmp(&d) != 0 { 801 return false 802 } 803 } 804 805 // fixed elements 806 // a is random 807 // r takes special values 808 testValues := make([]{{.all.ElementName}}, len(staticTestValues)) 809 copy(testValues, staticTestValues) 810 811 for i := range testValues { 812 r := testValues[i] 813 var d, e, rb big.Int 814 r.BigInt(&rb) 815 816 var c {{.all.ElementName}} 817 {{- if eq .Op "Div"}} 818 c.{{.Op}}(&a.element, &r) 819 d.ModInverse(&rb, Modulus()) 820 d.Mul(&d, &a.bigint).Mod(&d, Modulus()) 821 {{- else if eq .Op "Exp"}} 822 c.{{.Op}}(a.element, &rb) 823 d.Exp(&a.bigint, &rb, Modulus()) 824 {{- else}} 825 c.{{.Op}}(&a.element, &r) 826 d.{{.Op}}(&a.bigint, &rb).Mod(&d, Modulus()) 827 {{- end }} 828 829 {{if .GenericOp}} 830 // checking generic impl against asm path 831 var cGeneric {{.all.ElementName}} 832 {{.GenericOp}}(&cGeneric, &a.element, &r) 833 if !cGeneric.Equal(&c) { 834 // need to give context to failing error. 835 return false 836 } 837 {{end}} 838 839 if c.BigInt(&e).Cmp(&d) != 0 { 840 return false 841 } 842 } 843 return true 844 }, 845 genA, 846 genB, 847 )) 848 849 properties.Property("{{.Op}}: operation result must be smaller than modulus", prop.ForAll( 850 func(a, b testPair{{.all.ElementName}}) bool { 851 var c {{.all.ElementName}} 852 {{if eq .Op "Exp"}} 853 c.{{.Op}}(a.element, &b.bigint) 854 {{else}} 855 c.{{.Op}}(&a.element, &b.element) 856 {{end}} 857 return c.smallerThanModulus() 858 }, 859 genA, 860 genB, 861 )) 862 863 {{if .GenericOp}} 864 properties.Property("{{.Op}}: assembly implementation must be consistent with generic one", prop.ForAll( 865 func(a, b testPair{{.all.ElementName}}) bool { 866 var c,d {{.all.ElementName}} 867 c.{{.Op}}(&a.element, &b.element) 868 {{.GenericOp}}(&d, &a.element, &b.element) 869 return c.Equal(&d) 870 }, 871 genA, 872 genB, 873 )) 874 875 {{end}} 876 877 878 specialValueTest := func() { 879 // test special values against special values 880 testValues := make([]{{.all.ElementName}}, len(staticTestValues)) 881 copy(testValues, staticTestValues) 882 883 for i := range testValues { 884 a := testValues[i] 885 var aBig big.Int 886 a.BigInt(&aBig) 887 for j := range testValues { 888 b := testValues[j] 889 var bBig, d, e big.Int 890 b.BigInt(&bBig) 891 892 var c {{.all.ElementName}} 893 894 895 896 {{- if eq .Op "Div"}} 897 c.{{.Op}}(&a, &b) 898 d.ModInverse(&bBig, Modulus()) 899 d.Mul(&d, &aBig).Mod(&d, Modulus()) 900 {{- else if eq .Op "Exp"}} 901 c.{{.Op}}(a, &bBig) 902 d.Exp(&aBig, &bBig, Modulus()) 903 {{- else}} 904 c.{{.Op}}(&a, &b) 905 d.{{.Op}}(&aBig, &bBig).Mod(&d, Modulus()) 906 {{- end }} 907 908 {{if .GenericOp}} 909 // checking asm against generic impl 910 var cGeneric {{.all.ElementName}} 911 {{.GenericOp}}(&cGeneric, &a, &b) 912 if !cGeneric.Equal(&c) { 913 t.Fatal("{{.Op}} failed special test values: asm and generic impl don't match") 914 } 915 {{end}} 916 917 918 if c.BigInt(&e).Cmp(&d) != 0 { 919 t.Fatal("{{.Op}} failed special test values") 920 } 921 } 922 } 923 } 924 925 926 properties.TestingRun(t, gopter.ConsoleReporter(false)) 927 specialValueTest() 928 929 } 930 931 {{ end }} 932 933 934 {{ define "testUnaryOp" }} 935 936 func Test{{toTitle .all.ElementName}}{{.Op}}(t *testing.T) { 937 t.Parallel() 938 parameters := gopter.DefaultTestParameters() 939 if testing.Short() { 940 parameters.MinSuccessfulTests = nbFuzzShort 941 } else { 942 parameters.MinSuccessfulTests = nbFuzz 943 } 944 945 properties := gopter.NewProperties(parameters) 946 947 genA := gen() 948 949 properties.Property("{{.Op}}: having the receiver as operand should output the same result", prop.ForAll( 950 func(a testPair{{.all.ElementName}}) bool { 951 {{if eq .Op "Sqrt"}} 952 b := a.element 953 {{else}} 954 var b {{.all.ElementName}} 955 {{end}} 956 b.{{.Op}}(&a.element) 957 a.element.{{.Op}}(&a.element) 958 return a.element.Equal(&b) 959 }, 960 genA, 961 )) 962 963 properties.Property("{{.Op}}: operation result must match big.Int result", prop.ForAll( 964 func(a testPair{{.all.ElementName}}) bool { 965 var c {{.all.ElementName}} 966 c.{{.Op}}(&a.element) 967 968 var d, e big.Int 969 {{- if eq .Op "Square"}} 970 d.Mul(&a.bigint, &a.bigint).Mod(&d, Modulus()) 971 {{- else if eq .Op "Inverse"}} 972 d.ModInverse(&a.bigint, Modulus()) 973 {{- else if eq .Op "Sqrt"}} 974 d.ModSqrt(&a.bigint, Modulus()) 975 {{- else if eq .Op "Double"}} 976 d.Lsh(&a.bigint, 1).Mod(&d, Modulus()) 977 {{- else if eq .Op "Neg"}} 978 d.Neg(&a.bigint).Mod(&d, Modulus()) 979 {{- end }} 980 981 982 return c.BigInt(&e).Cmp(&d) == 0 983 }, 984 genA, 985 )) 986 987 properties.Property("{{.Op}}: operation result must be smaller than modulus", prop.ForAll( 988 func(a testPair{{.all.ElementName}}) bool { 989 var c {{.all.ElementName}} 990 c.{{.Op}}(&a.element) 991 return c.smallerThanModulus() 992 }, 993 genA, 994 )) 995 996 {{if .GenericOp}} 997 properties.Property("{{.Op}}: assembly implementation must be consistent with generic one", prop.ForAll( 998 func(a testPair{{.all.ElementName}}) bool { 999 var c,d {{.all.ElementName}} 1000 c.{{.Op}}(&a.element) 1001 {{.GenericOp}}(&d, &a.element) 1002 return c.Equal(&d) 1003 }, 1004 genA, 1005 )) 1006 1007 {{end}} 1008 1009 1010 specialValueTest := func() { 1011 // test special values 1012 testValues := make([]{{.all.ElementName}}, len(staticTestValues)) 1013 copy(testValues, staticTestValues) 1014 1015 for i := range testValues { 1016 a := testValues[i] 1017 var aBig big.Int 1018 a.BigInt(&aBig) 1019 var c {{.all.ElementName}} 1020 c.{{.Op}}(&a) 1021 1022 var d, e big.Int 1023 {{- if eq .Op "Square"}} 1024 d.Mul(&aBig, &aBig).Mod(&d, Modulus()) 1025 {{- else if eq .Op "Inverse"}} 1026 d.ModInverse(&aBig, Modulus()) 1027 {{- else if eq .Op "Sqrt"}} 1028 d.ModSqrt(&aBig, Modulus()) 1029 {{- else if eq .Op "Double"}} 1030 d.Lsh(&aBig, 1).Mod(&d, Modulus()) 1031 {{- else if eq .Op "Neg"}} 1032 d.Neg(&aBig).Mod(&d, Modulus()) 1033 {{- end }} 1034 1035 {{if .GenericOp}} 1036 // checking asm against generic impl 1037 var cGeneric {{.all.ElementName}} 1038 {{.GenericOp}}(&cGeneric, &a) 1039 if !cGeneric.Equal(&c) { 1040 t.Fatal("{{.Op}} failed special test values: asm and generic impl don't match") 1041 } 1042 {{end}} 1043 1044 1045 if c.BigInt(&e).Cmp(&d) != 0 { 1046 t.Fatal("{{.Op}} failed special test values") 1047 } 1048 } 1049 } 1050 1051 1052 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1053 specialValueTest() 1054 1055 } 1056 1057 {{ end }} 1058 1059 {{ if .UseAddChain}} 1060 func Test{{toTitle .ElementName}}FixedExp(t *testing.T) { 1061 1062 t.Parallel() 1063 parameters := gopter.DefaultTestParameters() 1064 if testing.Short() { 1065 parameters.MinSuccessfulTests = nbFuzzShort 1066 } else { 1067 parameters.MinSuccessfulTests = nbFuzz 1068 } 1069 1070 properties := gopter.NewProperties(parameters) 1071 1072 var ( 1073 _bLegendreExponent{{.ElementName}} *big.Int 1074 _bSqrtExponent{{.ElementName}} *big.Int 1075 ) 1076 1077 _bLegendreExponent{{.ElementName}}, _ = new(big.Int).SetString("{{.LegendreExponent}}", 16) 1078 {{- if .SqrtQ3Mod4}} 1079 const sqrtExponent{{.ElementName}} = "{{.SqrtQ3Mod4Exponent}}" 1080 {{- else if .SqrtAtkin}} 1081 const sqrtExponent{{.ElementName}} = "{{.SqrtAtkinExponent}}" 1082 {{- else if .SqrtTonelliShanks}} 1083 const sqrtExponent{{.ElementName}} = "{{.SqrtSMinusOneOver2}}" 1084 {{- end }} 1085 _bSqrtExponent{{.ElementName}}, _ = new(big.Int).SetString(sqrtExponent{{.ElementName}}, 16) 1086 1087 genA := gen() 1088 1089 properties.Property(fmt.Sprintf("expBySqrtExp must match Exp(%s)", sqrtExponent{{.ElementName}}), prop.ForAll( 1090 func(a testPair{{.ElementName}}) bool { 1091 c := a.element 1092 d := a.element 1093 c.expBySqrtExp(c) 1094 d.Exp(d, _bSqrtExponent{{.ElementName}}) 1095 return c.Equal(&d) 1096 }, 1097 genA, 1098 )) 1099 1100 properties.Property("expByLegendreExp must match Exp({{.LegendreExponent}})", prop.ForAll( 1101 func(a testPair{{.ElementName}}) bool { 1102 c := a.element 1103 d := a.element 1104 c.expByLegendreExp(c) 1105 d.Exp(d, _bLegendreExponent{{.ElementName}}) 1106 return c.Equal(&d) 1107 }, 1108 genA, 1109 )) 1110 1111 1112 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1113 } 1114 1115 {{ end }} 1116 1117 1118 1119 1120 1121 func Test{{toTitle .ElementName}}Halve(t *testing.T) { 1122 1123 t.Parallel() 1124 parameters := gopter.DefaultTestParameters() 1125 if testing.Short() { 1126 parameters.MinSuccessfulTests = nbFuzzShort 1127 } else { 1128 parameters.MinSuccessfulTests = nbFuzz 1129 } 1130 1131 properties := gopter.NewProperties(parameters) 1132 1133 genA := gen() 1134 var twoInv {{.ElementName}} 1135 twoInv.SetUint64(2) 1136 twoInv.Inverse(&twoInv) 1137 1138 properties.Property("z.Halve must match z / 2", prop.ForAll( 1139 func(a testPair{{.ElementName}}) bool { 1140 c := a.element 1141 d := a.element 1142 c.Halve() 1143 d.Mul(&d, &twoInv) 1144 return c.Equal(&d) 1145 }, 1146 genA, 1147 )) 1148 1149 1150 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1151 } 1152 1153 func combineSelectionArguments(c int64, z int8) int { 1154 if z%3 == 0 { 1155 return 0 1156 } 1157 return int(c) 1158 } 1159 1160 func Test{{toTitle .ElementName}}Select(t *testing.T) { 1161 t.Parallel() 1162 parameters := gopter.DefaultTestParameters() 1163 if testing.Short() { 1164 parameters.MinSuccessfulTests = nbFuzzShort 1165 } else { 1166 parameters.MinSuccessfulTests = nbFuzz 1167 } 1168 1169 properties := gopter.NewProperties(parameters) 1170 1171 genA := genFull() 1172 genB := genFull() 1173 genC := ggen.Int64() //the condition 1174 genZ := ggen.Int8() //to make zeros artificially more likely 1175 1176 properties.Property("Select: must select correctly", prop.ForAll( 1177 func(a, b {{.ElementName}}, cond int64, z int8) bool { 1178 condC := combineSelectionArguments(cond, z) 1179 1180 var c {{.ElementName}} 1181 c.Select(condC, &a, &b) 1182 1183 if condC == 0 { 1184 return c.Equal(&a) 1185 } 1186 return c.Equal(&b) 1187 }, 1188 genA, 1189 genB, 1190 genC, 1191 genZ, 1192 )) 1193 1194 properties.Property("Select: having the receiver as operand should output the same result", prop.ForAll( 1195 func(a, b {{.ElementName}}, cond int64, z int8) bool { 1196 condC := combineSelectionArguments(cond, z) 1197 1198 var c, d {{.ElementName}} 1199 d.Set(&a) 1200 c.Select(condC, &a, &b) 1201 a.Select(condC, &a, &b) 1202 b.Select(condC, &d, &b) 1203 return a.Equal(&b) && a.Equal(&c) && b.Equal(&c) 1204 }, 1205 genA, 1206 genB, 1207 genC, 1208 genZ, 1209 )) 1210 1211 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1212 } 1213 1214 func Test{{toTitle .ElementName}}SetInt64(t *testing.T) { 1215 1216 t.Parallel() 1217 parameters := gopter.DefaultTestParameters() 1218 if testing.Short() { 1219 parameters.MinSuccessfulTests = nbFuzzShort 1220 } else { 1221 parameters.MinSuccessfulTests = nbFuzz 1222 } 1223 1224 properties := gopter.NewProperties(parameters) 1225 1226 genA := gen() 1227 1228 properties.Property("z.SetInt64 must match z.SetString", prop.ForAll( 1229 func(a testPair{{.ElementName}}, v int64) bool { 1230 c := a.element 1231 d := a.element 1232 1233 c.SetInt64(v) 1234 d.SetString(fmt.Sprintf("%v",v)) 1235 1236 return c.Equal(&d) 1237 }, 1238 genA, ggen.Int64(), 1239 )) 1240 1241 1242 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1243 } 1244 1245 1246 func Test{{toTitle .ElementName}}SetInterface(t *testing.T) { 1247 1248 t.Parallel() 1249 parameters := gopter.DefaultTestParameters() 1250 if testing.Short() { 1251 parameters.MinSuccessfulTests = nbFuzzShort 1252 } else { 1253 parameters.MinSuccessfulTests = nbFuzz 1254 } 1255 1256 properties := gopter.NewProperties(parameters) 1257 1258 genA := gen() 1259 genInt := ggen.Int 1260 genInt8 := ggen.Int8 1261 genInt16 := ggen.Int16 1262 genInt32 := ggen.Int32 1263 genInt64 := ggen.Int64 1264 1265 genUint := ggen.UInt 1266 genUint8 := ggen.UInt8 1267 genUint16 := ggen.UInt16 1268 genUint32 := ggen.UInt32 1269 genUint64 := ggen.UInt64 1270 1271 {{setInterface .ElementName "int8"}} 1272 {{setInterface .ElementName "int16"}} 1273 {{setInterface .ElementName "int32"}} 1274 {{setInterface .ElementName "int64"}} 1275 {{setInterface .ElementName "int"}} 1276 1277 {{setInterface .ElementName "uint8"}} 1278 {{setInterface .ElementName "uint16"}} 1279 {{setInterface .ElementName "uint32"}} 1280 {{setInterface .ElementName "uint64"}} 1281 {{setInterface .ElementName "uint"}} 1282 1283 1284 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1285 1286 { 1287 assert := require.New(t) 1288 var e {{.ElementName}} 1289 r, err := e.SetInterface(nil) 1290 assert.Nil(r) 1291 assert.Error(err) 1292 1293 var ptE *{{.ElementName}} 1294 var ptB *big.Int 1295 1296 r, err = e.SetInterface(ptE) 1297 assert.Nil(r) 1298 assert.Error(err) 1299 ptE = new({{.ElementName}}).SetOne() 1300 r, err = e.SetInterface(ptE) 1301 assert.NoError(err) 1302 assert.True(r.IsOne()) 1303 1304 r, err = e.SetInterface(ptB) 1305 assert.Nil(r) 1306 assert.Error(err) 1307 1308 } 1309 } 1310 1311 1312 {{define "setInterface eName tName"}} 1313 1314 properties.Property("z.SetInterface must match z.SetString with {{.tName}}", prop.ForAll( 1315 func(a testPair{{.eName}}, v {{.tName}}) bool { 1316 c := a.element 1317 d := a.element 1318 1319 c.SetInterface(v) 1320 d.SetString(fmt.Sprintf("%v",v)) 1321 1322 return c.Equal(&d) 1323 }, 1324 genA, gen{{toTitle .tName}}(), 1325 )) 1326 1327 {{end}} 1328 1329 func Test{{toTitle .ElementName}}NegativeExp(t *testing.T) { 1330 t.Parallel() 1331 1332 parameters := gopter.DefaultTestParameters() 1333 if testing.Short() { 1334 parameters.MinSuccessfulTests = nbFuzzShort 1335 } else { 1336 parameters.MinSuccessfulTests = nbFuzz 1337 } 1338 1339 properties := gopter.NewProperties(parameters) 1340 1341 genA := gen() 1342 1343 properties.Property("x⁻ᵏ == 1/xᵏ", prop.ForAll( 1344 func(a,b testPair{{.ElementName}}) bool { 1345 1346 var nb, d, e big.Int 1347 nb.Neg(&b.bigint) 1348 1349 var c {{.ElementName}} 1350 c.Exp(a.element, &nb) 1351 1352 d.Exp(&a.bigint, &nb, Modulus()) 1353 1354 return c.BigInt(&e).Cmp(&d) == 0 1355 }, 1356 genA, genA, 1357 )) 1358 1359 1360 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1361 } 1362 1363 func Test{{toTitle .ElementName}}New{{.ElementName}}(t *testing.T) { 1364 assert := require.New(t) 1365 1366 t.Parallel() 1367 1368 e := New{{.ElementName}}(1) 1369 assert.True(e.IsOne()) 1370 1371 e = New{{.ElementName}}(0) 1372 assert.True(e.IsZero()) 1373 } 1374 1375 1376 func Test{{toTitle .ElementName}}BatchInvert(t *testing.T) { 1377 assert := require.New(t) 1378 1379 t.Parallel() 1380 1381 // ensure batchInvert([x]) == invert(x) 1382 for i:=int64(-1); i <=2; i++ { 1383 var e, eInv {{.ElementName}} 1384 e.SetInt64(i) 1385 eInv.Inverse(&e) 1386 1387 a := []{{.ElementName}}{e} 1388 aInv := BatchInvert(a) 1389 1390 assert.True(aInv[0].Equal(&eInv), "batchInvert != invert") 1391 1392 } 1393 1394 // test x * x⁻¹ == 1 1395 tData := [][]int64 { 1396 []int64{-1,1,2,3}, 1397 []int64{0, -1,1,2,3, 0}, 1398 []int64{0, -1,1,0, 2,3, 0}, 1399 []int64{-1,1,0, 2,3}, 1400 []int64{0,0,1}, 1401 []int64{1,0,0}, 1402 []int64{0,0,0}, 1403 } 1404 1405 for _, t := range tData { 1406 a := make([]{{.ElementName}}, len(t)) 1407 for i:=0; i <len(a);i++ { 1408 a[i].SetInt64(t[i]) 1409 } 1410 1411 aInv := BatchInvert(a) 1412 1413 assert.True(len(aInv) == len(a)) 1414 1415 for i:=0; i <len(a);i++ { 1416 if a[i].IsZero() { 1417 assert.True(aInv[i].IsZero(), "0⁻¹ != 0") 1418 } else { 1419 assert.True(a[i].Mul(&a[i], &aInv[i]).IsOne(), "x * x⁻¹ != 1") 1420 } 1421 } 1422 } 1423 1424 1425 parameters := gopter.DefaultTestParameters() 1426 if testing.Short() { 1427 parameters.MinSuccessfulTests = nbFuzzShort 1428 } else { 1429 parameters.MinSuccessfulTests = nbFuzz 1430 } 1431 1432 properties := gopter.NewProperties(parameters) 1433 1434 genA := gen() 1435 1436 properties.Property("batchInvert --> x * x⁻¹ == 1", prop.ForAll( 1437 func(tp testPair{{.ElementName}}, r uint8) bool { 1438 1439 a := make([]{{.ElementName}}, r) 1440 if r != 0 { 1441 a[0] = tp.element 1442 1443 } 1444 one := One() 1445 for i:=1; i <len(a);i++ { 1446 a[i].Add(&a[i-1], &one) 1447 } 1448 1449 aInv := BatchInvert(a) 1450 1451 assert.True(len(aInv) == len(a)) 1452 1453 for i:=0; i <len(a);i++ { 1454 if a[i].IsZero() { 1455 if !aInv[i].IsZero() { 1456 return false 1457 } 1458 } else { 1459 if !a[i].Mul(&a[i], &aInv[i]).IsOne() { 1460 return false 1461 } 1462 } 1463 } 1464 return true 1465 }, 1466 genA,ggen.UInt8(), 1467 )) 1468 1469 1470 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1471 } 1472 1473 func Test{{toTitle .ElementName}}FromMont(t *testing.T) { 1474 1475 t.Parallel() 1476 parameters := gopter.DefaultTestParameters() 1477 if testing.Short() { 1478 parameters.MinSuccessfulTests = nbFuzzShort 1479 } else { 1480 parameters.MinSuccessfulTests = nbFuzz 1481 } 1482 1483 properties := gopter.NewProperties(parameters) 1484 1485 genA := gen() 1486 1487 properties.Property("Assembly implementation must be consistent with generic one", prop.ForAll( 1488 func(a testPair{{.ElementName}}) bool { 1489 c := a.element 1490 d := a.element 1491 c.fromMont() 1492 _fromMontGeneric(&d) 1493 return c.Equal(&d) 1494 }, 1495 genA, 1496 )) 1497 1498 properties.Property("x.fromMont().toMont() == x", prop.ForAll( 1499 func(a testPair{{.ElementName}}) bool { 1500 c := a.element 1501 c.fromMont().toMont() 1502 return c.Equal(&a.element) 1503 }, 1504 genA, 1505 )) 1506 1507 1508 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1509 } 1510 1511 1512 1513 func Test{{toTitle .ElementName}}JSON(t *testing.T) { 1514 assert := require.New(t) 1515 1516 type S struct { 1517 A {{.ElementName}} 1518 B [3]{{.ElementName}} 1519 C *{{.ElementName}} 1520 D *{{.ElementName}} 1521 } 1522 1523 // encode to JSON 1524 var s S 1525 s.A.SetString("-1") 1526 s.B[2].SetUint64(42) 1527 s.D = new({{.ElementName}}).SetUint64(8000) 1528 1529 encoded, err := json.Marshal(&s) 1530 assert.NoError(err) 1531 {{- $noNeg := and (eq $.NbWords 1) (ltu64 (index $.Q 0) 1000000)}} 1532 // we may need to adjust "42" and "8000" values for some moduli; see Text() method for more details. 1533 formatValue := func(v int64) string { 1534 var a big.Int 1535 a.SetInt64(v) 1536 a.Mod(&a, Modulus()) 1537 {{- if not $noNeg}} 1538 const maxUint16 = 65535 1539 var aNeg big.Int 1540 aNeg.Neg(&a).Mod(&aNeg, Modulus()) 1541 if aNeg.Uint64() != 0 && aNeg.Uint64() <= maxUint16 { 1542 return "-"+aNeg.Text(10) 1543 } 1544 {{- end}} 1545 return a.Text(10) 1546 } 1547 expected := fmt.Sprintf("{\"A\":%s,\"B\":[0,0,%s],\"C\":null,\"D\":%s}", formatValue(-1), formatValue(42), formatValue(8000)) 1548 assert.Equal(expected, string(encoded)) 1549 1550 // decode valid 1551 var decoded S 1552 err = json.Unmarshal([]byte(expected), &decoded) 1553 assert.NoError(err) 1554 1555 assert.Equal(s, decoded, "element -> json -> element round trip failed") 1556 1557 // decode hex and string values 1558 withHexValues := "{\"A\":\"-1\",\"B\":[0,\"0x00000\",\"0x2A\"],\"C\":null,\"D\":\"8000\"}" 1559 1560 var decodedS S 1561 err = json.Unmarshal([]byte(withHexValues), &decodedS) 1562 assert.NoError(err) 1563 1564 assert.Equal(s, decodedS, " json with strings -> element failed") 1565 1566 } 1567 1568 type testPair{{.ElementName}} struct { 1569 element {{.ElementName}} 1570 bigint big.Int 1571 } 1572 1573 1574 func gen() gopter.Gen { 1575 return func(genParams *gopter.GenParameters) *gopter.GenResult { 1576 var g testPair{{.ElementName}} 1577 1578 g.element = {{.ElementName}}{ 1579 {{- range $i := .NbWordsIndexesFull}} 1580 genParams.NextUint64(),{{end}} 1581 } 1582 if q{{.ElementName}}[{{.NbWordsLastIndex}}] != ^uint64(0) { 1583 g.element[{{.NbWordsLastIndex}}] %= (q{{.ElementName}}[{{.NbWordsLastIndex}}] +1 ) 1584 } 1585 1586 1587 for !g.element.smallerThanModulus() { 1588 g.element = {{.ElementName}}{ 1589 {{- range $i := .NbWordsIndexesFull}} 1590 genParams.NextUint64(),{{end}} 1591 } 1592 if q{{.ElementName}}[{{.NbWordsLastIndex}}] != ^uint64(0) { 1593 g.element[{{.NbWordsLastIndex}}] %= (q{{.ElementName}}[{{.NbWordsLastIndex}}] +1 ) 1594 } 1595 } 1596 1597 g.element.BigInt(&g.bigint) 1598 genResult := gopter.NewGenResult(g, gopter.NoShrinker) 1599 return genResult 1600 } 1601 } 1602 1603 1604 func genFull() gopter.Gen { 1605 return func(genParams *gopter.GenParameters) *gopter.GenResult { 1606 1607 genRandomFq := func() {{.ElementName}} { 1608 var g {{.ElementName}} 1609 1610 g = {{.ElementName}}{ 1611 {{- range $i := .NbWordsIndexesFull}} 1612 genParams.NextUint64(),{{end}} 1613 } 1614 1615 if q{{.ElementName}}[{{.NbWordsLastIndex}}] != ^uint64(0) { 1616 g[{{.NbWordsLastIndex}}] %= (q{{.ElementName}}[{{.NbWordsLastIndex}}] +1 ) 1617 } 1618 1619 for !g.smallerThanModulus() { 1620 g = {{.ElementName}}{ 1621 {{- range $i := .NbWordsIndexesFull}} 1622 genParams.NextUint64(),{{end}} 1623 } 1624 if q{{.ElementName}}[{{.NbWordsLastIndex}}] != ^uint64(0) { 1625 g[{{.NbWordsLastIndex}}] %= (q{{.ElementName}}[{{.NbWordsLastIndex}}] +1 ) 1626 } 1627 } 1628 1629 return g 1630 } 1631 a := genRandomFq() 1632 1633 var carry uint64 1634 {{- range $i := .NbWordsIndexesFull}} 1635 {{- if eq $i $.NbWordsLastIndex}} 1636 a[{{$i}}], _ = bits.Add64(a[{{$i}}], q{{$.ElementName}}[{{$i}}], carry) 1637 {{- else}} 1638 a[{{$i}}], carry = bits.Add64(a[{{$i}}], q{{$.ElementName}}[{{$i}}], carry) 1639 {{- end}} 1640 {{- end}} 1641 1642 genResult := gopter.NewGenResult(a, gopter.NoShrinker) 1643 return genResult 1644 } 1645 } 1646 {{if $.UsingP20Inverse}} 1647 func (z *{{.ElementName}}) matchVeryBigInt(aHi uint64, aInt *big.Int) error { 1648 var modulus big.Int 1649 var aIntMod big.Int 1650 modulus.SetInt64(1) 1651 modulus.Lsh(&modulus, (Limbs+1)*64) 1652 aIntMod.Mod(aInt, &modulus) 1653 1654 slice := append(z[:], aHi) 1655 1656 return bigIntMatchUint64Slice(&aIntMod, slice) 1657 } 1658 1659 //TODO: Phase out in favor of property based testing 1660 func (z *{{.ElementName}}) assertMatchVeryBigInt(t *testing.T, aHi uint64, aInt *big.Int) { 1661 1662 if err := z.matchVeryBigInt(aHi, aInt); err != nil { 1663 t.Error(err) 1664 } 1665 } 1666 1667 1668 // bigIntMatchUint64Slice is a test helper to match big.Int words against a uint64 slice 1669 func bigIntMatchUint64Slice(aInt *big.Int, a []uint64) error { 1670 1671 words := aInt.Bits() 1672 1673 const steps = 64 / bits.UintSize 1674 const filter uint64 = 0xFFFFFFFFFFFFFFFF >> (64 - bits.UintSize) 1675 for i := 0; i < len(a)*steps; i++ { 1676 1677 var wI big.Word 1678 1679 if i < len(words) { 1680 wI = words[i] 1681 } 1682 1683 aI := a[i/steps] >> ((i * bits.UintSize) % 64) 1684 aI &= filter 1685 1686 if uint64(wI) != aI { 1687 return fmt.Errorf("bignum mismatch: disagreement on word %d: %x ≠ %x; %d ≠ %d", i, uint64(wI), aI, uint64(wI), aI) 1688 } 1689 } 1690 1691 return nil 1692 } 1693 {{- end}} 1694 1695 1696 1697 `