github.com/consensys/gnark-crypto@v0.14.0/field/goldilocks/element_test.go (about) 1 // Copyright 2020 ConsenSys Software Inc. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Code generated by consensys/gnark-crypto DO NOT EDIT 16 17 package goldilocks 18 19 import ( 20 "crypto/rand" 21 "encoding/json" 22 "fmt" 23 "math/big" 24 "math/bits" 25 26 "testing" 27 28 "github.com/leanovate/gopter" 29 ggen "github.com/leanovate/gopter/gen" 30 "github.com/leanovate/gopter/prop" 31 32 "github.com/stretchr/testify/require" 33 ) 34 35 // ------------------------------------------------------------------------------------------------- 36 // benchmarks 37 // most benchmarks are rudimentary and should sample a large number of random inputs 38 // or be run multiple times to ensure it didn't measure the fastest path of the function 39 40 var benchResElement Element 41 42 func BenchmarkElementSelect(b *testing.B) { 43 var x, y Element 44 x.SetRandom() 45 y.SetRandom() 46 47 b.ResetTimer() 48 for i := 0; i < b.N; i++ { 49 benchResElement.Select(i%3, &x, &y) 50 } 51 } 52 53 func BenchmarkElementSetRandom(b *testing.B) { 54 var x Element 55 x.SetRandom() 56 57 b.ResetTimer() 58 for i := 0; i < b.N; i++ { 59 _, _ = x.SetRandom() 60 } 61 } 62 63 func BenchmarkElementSetBytes(b *testing.B) { 64 var x Element 65 x.SetRandom() 66 bb := x.Bytes() 67 b.ResetTimer() 68 69 for i := 0; i < b.N; i++ { 70 benchResElement.SetBytes(bb[:]) 71 } 72 73 } 74 75 func BenchmarkElementMulByConstants(b *testing.B) { 76 b.Run("mulBy3", func(b *testing.B) { 77 benchResElement.SetRandom() 78 b.ResetTimer() 79 for i := 0; i < b.N; i++ { 80 MulBy3(&benchResElement) 81 } 82 }) 83 b.Run("mulBy5", func(b *testing.B) { 84 benchResElement.SetRandom() 85 b.ResetTimer() 86 for i := 0; i < b.N; i++ { 87 MulBy5(&benchResElement) 88 } 89 }) 90 b.Run("mulBy13", func(b *testing.B) { 91 benchResElement.SetRandom() 92 b.ResetTimer() 93 for i := 0; i < b.N; i++ { 94 MulBy13(&benchResElement) 95 } 96 }) 97 } 98 99 func BenchmarkElementInverse(b *testing.B) { 100 var x Element 101 x.SetRandom() 102 benchResElement.SetRandom() 103 b.ResetTimer() 104 105 for i := 0; i < b.N; i++ { 106 benchResElement.Inverse(&x) 107 } 108 109 } 110 111 func BenchmarkElementButterfly(b *testing.B) { 112 var x Element 113 x.SetRandom() 114 benchResElement.SetRandom() 115 b.ResetTimer() 116 for i := 0; i < b.N; i++ { 117 Butterfly(&x, &benchResElement) 118 } 119 } 120 121 func BenchmarkElementExp(b *testing.B) { 122 var x Element 123 x.SetRandom() 124 benchResElement.SetRandom() 125 b1, _ := rand.Int(rand.Reader, Modulus()) 126 b.ResetTimer() 127 for i := 0; i < b.N; i++ { 128 benchResElement.Exp(x, b1) 129 } 130 } 131 132 func BenchmarkElementDouble(b *testing.B) { 133 benchResElement.SetRandom() 134 b.ResetTimer() 135 for i := 0; i < b.N; i++ { 136 benchResElement.Double(&benchResElement) 137 } 138 } 139 140 func BenchmarkElementAdd(b *testing.B) { 141 var x Element 142 x.SetRandom() 143 benchResElement.SetRandom() 144 b.ResetTimer() 145 for i := 0; i < b.N; i++ { 146 benchResElement.Add(&x, &benchResElement) 147 } 148 } 149 150 func BenchmarkElementSub(b *testing.B) { 151 var x Element 152 x.SetRandom() 153 benchResElement.SetRandom() 154 b.ResetTimer() 155 for i := 0; i < b.N; i++ { 156 benchResElement.Sub(&x, &benchResElement) 157 } 158 } 159 160 func BenchmarkElementNeg(b *testing.B) { 161 benchResElement.SetRandom() 162 b.ResetTimer() 163 for i := 0; i < b.N; i++ { 164 benchResElement.Neg(&benchResElement) 165 } 166 } 167 168 func BenchmarkElementDiv(b *testing.B) { 169 var x Element 170 x.SetRandom() 171 benchResElement.SetRandom() 172 b.ResetTimer() 173 for i := 0; i < b.N; i++ { 174 benchResElement.Div(&x, &benchResElement) 175 } 176 } 177 178 func BenchmarkElementFromMont(b *testing.B) { 179 benchResElement.SetRandom() 180 b.ResetTimer() 181 for i := 0; i < b.N; i++ { 182 benchResElement.fromMont() 183 } 184 } 185 186 func BenchmarkElementSquare(b *testing.B) { 187 benchResElement.SetRandom() 188 b.ResetTimer() 189 for i := 0; i < b.N; i++ { 190 benchResElement.Square(&benchResElement) 191 } 192 } 193 194 func BenchmarkElementSqrt(b *testing.B) { 195 var a Element 196 a.SetUint64(4) 197 a.Neg(&a) 198 b.ResetTimer() 199 for i := 0; i < b.N; i++ { 200 benchResElement.Sqrt(&a) 201 } 202 } 203 204 func BenchmarkElementMul(b *testing.B) { 205 x := Element{ 206 18446744065119617025, 207 } 208 benchResElement.SetOne() 209 b.ResetTimer() 210 for i := 0; i < b.N; i++ { 211 benchResElement.Mul(&benchResElement, &x) 212 } 213 } 214 215 func BenchmarkElementCmp(b *testing.B) { 216 x := Element{ 217 18446744065119617025, 218 } 219 benchResElement = x 220 benchResElement[0] = 0 221 b.ResetTimer() 222 for i := 0; i < b.N; i++ { 223 benchResElement.Cmp(&x) 224 } 225 } 226 227 func TestElementCmp(t *testing.T) { 228 var x, y Element 229 230 if x.Cmp(&y) != 0 { 231 t.Fatal("x == y") 232 } 233 234 one := One() 235 y.Sub(&y, &one) 236 237 if x.Cmp(&y) != -1 { 238 t.Fatal("x < y") 239 } 240 if y.Cmp(&x) != 1 { 241 t.Fatal("x < y") 242 } 243 244 x = y 245 if x.Cmp(&y) != 0 { 246 t.Fatal("x == y") 247 } 248 249 x.Sub(&x, &one) 250 if x.Cmp(&y) != -1 { 251 t.Fatal("x < y") 252 } 253 if y.Cmp(&x) != 1 { 254 t.Fatal("x < y") 255 } 256 } 257 258 func TestElementNegZero(t *testing.T) { 259 var a, b Element 260 b.SetZero() 261 for a.IsZero() { 262 a.SetRandom() 263 } 264 a.Neg(&b) 265 if !a.IsZero() { 266 t.Fatal("neg(0) != 0") 267 } 268 } 269 270 // ------------------------------------------------------------------------------------------------- 271 // Gopter tests 272 // most of them are generated with a template 273 274 const ( 275 nbFuzzShort = 200 276 nbFuzz = 1000 277 ) 278 279 // special values to be used in tests 280 var staticTestValues []Element 281 282 func init() { 283 staticTestValues = append(staticTestValues, Element{}) // zero 284 staticTestValues = append(staticTestValues, One()) // one 285 staticTestValues = append(staticTestValues, rSquare) // r² 286 var e, one Element 287 one.SetOne() 288 e.Sub(&qElement, &one) 289 staticTestValues = append(staticTestValues, e) // q - 1 290 e.Double(&one) 291 staticTestValues = append(staticTestValues, e) // 2 292 293 { 294 a := qElement 295 a[0]-- 296 staticTestValues = append(staticTestValues, a) 297 } 298 staticTestValues = append(staticTestValues, Element{0}) 299 staticTestValues = append(staticTestValues, Element{1}) 300 staticTestValues = append(staticTestValues, Element{2}) 301 302 { 303 a := qElement 304 a[0]-- 305 staticTestValues = append(staticTestValues, a) 306 } 307 308 { 309 a := qElement 310 a[0] = 0 311 staticTestValues = append(staticTestValues, a) 312 } 313 314 } 315 316 func TestElementReduce(t *testing.T) { 317 testValues := make([]Element, len(staticTestValues)) 318 copy(testValues, staticTestValues) 319 320 for i := range testValues { 321 s := testValues[i] 322 expected := s 323 reduce(&s) 324 _reduceGeneric(&expected) 325 if !s.Equal(&expected) { 326 t.Fatal("reduce failed: asm and generic impl don't match") 327 } 328 } 329 330 t.Parallel() 331 parameters := gopter.DefaultTestParameters() 332 if testing.Short() { 333 parameters.MinSuccessfulTests = nbFuzzShort 334 } else { 335 parameters.MinSuccessfulTests = nbFuzz 336 } 337 338 properties := gopter.NewProperties(parameters) 339 340 genA := genFull() 341 342 properties.Property("reduce should output a result smaller than modulus", prop.ForAll( 343 func(a Element) bool { 344 b := a 345 reduce(&a) 346 _reduceGeneric(&b) 347 return a.smallerThanModulus() && a.Equal(&b) 348 }, 349 genA, 350 )) 351 352 properties.TestingRun(t, gopter.ConsoleReporter(false)) 353 354 } 355 356 func TestElementEqual(t *testing.T) { 357 t.Parallel() 358 parameters := gopter.DefaultTestParameters() 359 if testing.Short() { 360 parameters.MinSuccessfulTests = nbFuzzShort 361 } else { 362 parameters.MinSuccessfulTests = nbFuzz 363 } 364 365 properties := gopter.NewProperties(parameters) 366 367 genA := gen() 368 genB := gen() 369 370 properties.Property("x.Equal(&y) iff x == y; likely false for random pairs", prop.ForAll( 371 func(a testPairElement, b testPairElement) bool { 372 return a.element.Equal(&b.element) == (a.element == b.element) 373 }, 374 genA, 375 genB, 376 )) 377 378 properties.Property("x.Equal(&y) if x == y", prop.ForAll( 379 func(a testPairElement) bool { 380 b := a.element 381 return a.element.Equal(&b) 382 }, 383 genA, 384 )) 385 386 properties.TestingRun(t, gopter.ConsoleReporter(false)) 387 } 388 389 func TestElementBytes(t *testing.T) { 390 t.Parallel() 391 parameters := gopter.DefaultTestParameters() 392 if testing.Short() { 393 parameters.MinSuccessfulTests = nbFuzzShort 394 } else { 395 parameters.MinSuccessfulTests = nbFuzz 396 } 397 398 properties := gopter.NewProperties(parameters) 399 400 genA := gen() 401 402 properties.Property("SetBytes(Bytes()) should stay constant", prop.ForAll( 403 func(a testPairElement) bool { 404 var b Element 405 bytes := a.element.Bytes() 406 b.SetBytes(bytes[:]) 407 return a.element.Equal(&b) 408 }, 409 genA, 410 )) 411 412 properties.TestingRun(t, gopter.ConsoleReporter(false)) 413 } 414 415 func TestElementInverseExp(t *testing.T) { 416 // inverse must be equal to exp^-2 417 exp := Modulus() 418 exp.Sub(exp, new(big.Int).SetUint64(2)) 419 420 invMatchExp := func(a testPairElement) bool { 421 var b Element 422 b.Set(&a.element) 423 a.element.Inverse(&a.element) 424 b.Exp(b, exp) 425 426 return a.element.Equal(&b) 427 } 428 429 t.Parallel() 430 parameters := gopter.DefaultTestParameters() 431 if testing.Short() { 432 parameters.MinSuccessfulTests = nbFuzzShort 433 } else { 434 parameters.MinSuccessfulTests = nbFuzz 435 } 436 properties := gopter.NewProperties(parameters) 437 genA := gen() 438 properties.Property("inv == exp^-2", prop.ForAll(invMatchExp, genA)) 439 properties.TestingRun(t, gopter.ConsoleReporter(false)) 440 441 parameters.MinSuccessfulTests = 1 442 properties = gopter.NewProperties(parameters) 443 properties.Property("inv(0) == 0", prop.ForAll(invMatchExp, ggen.OneConstOf(testPairElement{}))) 444 properties.TestingRun(t, gopter.ConsoleReporter(false)) 445 446 } 447 448 func mulByConstant(z *Element, c uint8) { 449 var y Element 450 y.SetUint64(uint64(c)) 451 z.Mul(z, &y) 452 } 453 454 func TestElementMulByConstants(t *testing.T) { 455 456 t.Parallel() 457 parameters := gopter.DefaultTestParameters() 458 if testing.Short() { 459 parameters.MinSuccessfulTests = nbFuzzShort 460 } else { 461 parameters.MinSuccessfulTests = nbFuzz 462 } 463 464 properties := gopter.NewProperties(parameters) 465 466 genA := gen() 467 468 implemented := []uint8{0, 1, 2, 3, 5, 13} 469 properties.Property("mulByConstant", prop.ForAll( 470 func(a testPairElement) bool { 471 for _, c := range implemented { 472 var constant Element 473 constant.SetUint64(uint64(c)) 474 475 b := a.element 476 b.Mul(&b, &constant) 477 478 aa := a.element 479 mulByConstant(&aa, c) 480 481 if !aa.Equal(&b) { 482 return false 483 } 484 } 485 486 return true 487 }, 488 genA, 489 )) 490 491 properties.Property("MulBy3(x) == Mul(x, 3)", prop.ForAll( 492 func(a testPairElement) bool { 493 var constant Element 494 constant.SetUint64(3) 495 496 b := a.element 497 b.Mul(&b, &constant) 498 499 MulBy3(&a.element) 500 501 return a.element.Equal(&b) 502 }, 503 genA, 504 )) 505 506 properties.Property("MulBy5(x) == Mul(x, 5)", prop.ForAll( 507 func(a testPairElement) bool { 508 var constant Element 509 constant.SetUint64(5) 510 511 b := a.element 512 b.Mul(&b, &constant) 513 514 MulBy5(&a.element) 515 516 return a.element.Equal(&b) 517 }, 518 genA, 519 )) 520 521 properties.Property("MulBy13(x) == Mul(x, 13)", prop.ForAll( 522 func(a testPairElement) bool { 523 var constant Element 524 constant.SetUint64(13) 525 526 b := a.element 527 b.Mul(&b, &constant) 528 529 MulBy13(&a.element) 530 531 return a.element.Equal(&b) 532 }, 533 genA, 534 )) 535 536 properties.TestingRun(t, gopter.ConsoleReporter(false)) 537 538 } 539 540 func TestElementLegendre(t *testing.T) { 541 t.Parallel() 542 parameters := gopter.DefaultTestParameters() 543 if testing.Short() { 544 parameters.MinSuccessfulTests = nbFuzzShort 545 } else { 546 parameters.MinSuccessfulTests = nbFuzz 547 } 548 549 properties := gopter.NewProperties(parameters) 550 551 genA := gen() 552 553 properties.Property("legendre should output same result than big.Int.Jacobi", prop.ForAll( 554 func(a testPairElement) bool { 555 return a.element.Legendre() == big.Jacobi(&a.bigint, Modulus()) 556 }, 557 genA, 558 )) 559 560 properties.TestingRun(t, gopter.ConsoleReporter(false)) 561 562 } 563 564 func TestElementBitLen(t *testing.T) { 565 t.Parallel() 566 parameters := gopter.DefaultTestParameters() 567 if testing.Short() { 568 parameters.MinSuccessfulTests = nbFuzzShort 569 } else { 570 parameters.MinSuccessfulTests = nbFuzz 571 } 572 573 properties := gopter.NewProperties(parameters) 574 575 genA := gen() 576 577 properties.Property("BitLen should output same result than big.Int.BitLen", prop.ForAll( 578 func(a testPairElement) bool { 579 return a.element.fromMont().BitLen() == a.bigint.BitLen() 580 }, 581 genA, 582 )) 583 584 properties.TestingRun(t, gopter.ConsoleReporter(false)) 585 586 } 587 588 func TestElementButterflies(t *testing.T) { 589 590 t.Parallel() 591 parameters := gopter.DefaultTestParameters() 592 if testing.Short() { 593 parameters.MinSuccessfulTests = nbFuzzShort 594 } else { 595 parameters.MinSuccessfulTests = nbFuzz 596 } 597 598 properties := gopter.NewProperties(parameters) 599 600 genA := gen() 601 602 properties.Property("butterfly0 == a -b; a +b", prop.ForAll( 603 func(a, b testPairElement) bool { 604 a0, b0 := a.element, b.element 605 606 _butterflyGeneric(&a.element, &b.element) 607 Butterfly(&a0, &b0) 608 609 return a.element.Equal(&a0) && b.element.Equal(&b0) 610 }, 611 genA, 612 genA, 613 )) 614 615 properties.TestingRun(t, gopter.ConsoleReporter(false)) 616 617 } 618 619 func TestElementLexicographicallyLargest(t *testing.T) { 620 t.Parallel() 621 parameters := gopter.DefaultTestParameters() 622 if testing.Short() { 623 parameters.MinSuccessfulTests = nbFuzzShort 624 } else { 625 parameters.MinSuccessfulTests = nbFuzz 626 } 627 628 properties := gopter.NewProperties(parameters) 629 630 genA := gen() 631 632 properties.Property("element.Cmp should match LexicographicallyLargest output", prop.ForAll( 633 func(a testPairElement) bool { 634 var negA Element 635 negA.Neg(&a.element) 636 637 cmpResult := a.element.Cmp(&negA) 638 lResult := a.element.LexicographicallyLargest() 639 640 if lResult && cmpResult == 1 { 641 return true 642 } 643 if !lResult && cmpResult != 1 { 644 return true 645 } 646 return false 647 }, 648 genA, 649 )) 650 651 properties.TestingRun(t, gopter.ConsoleReporter(false)) 652 653 } 654 655 func TestElementAdd(t *testing.T) { 656 t.Parallel() 657 parameters := gopter.DefaultTestParameters() 658 if testing.Short() { 659 parameters.MinSuccessfulTests = nbFuzzShort 660 } else { 661 parameters.MinSuccessfulTests = nbFuzz 662 } 663 664 properties := gopter.NewProperties(parameters) 665 666 genA := gen() 667 genB := gen() 668 669 properties.Property("Add: having the receiver as operand should output the same result", prop.ForAll( 670 func(a, b testPairElement) bool { 671 var c, d Element 672 d.Set(&a.element) 673 674 c.Add(&a.element, &b.element) 675 a.element.Add(&a.element, &b.element) 676 b.element.Add(&d, &b.element) 677 678 return a.element.Equal(&b.element) && a.element.Equal(&c) && b.element.Equal(&c) 679 }, 680 genA, 681 genB, 682 )) 683 684 properties.Property("Add: operation result must match big.Int result", prop.ForAll( 685 func(a, b testPairElement) bool { 686 { 687 var c Element 688 689 c.Add(&a.element, &b.element) 690 691 var d, e big.Int 692 d.Add(&a.bigint, &b.bigint).Mod(&d, Modulus()) 693 694 if c.BigInt(&e).Cmp(&d) != 0 { 695 return false 696 } 697 } 698 699 // fixed elements 700 // a is random 701 // r takes special values 702 testValues := make([]Element, len(staticTestValues)) 703 copy(testValues, staticTestValues) 704 705 for i := range testValues { 706 r := testValues[i] 707 var d, e, rb big.Int 708 r.BigInt(&rb) 709 710 var c Element 711 c.Add(&a.element, &r) 712 d.Add(&a.bigint, &rb).Mod(&d, Modulus()) 713 714 if c.BigInt(&e).Cmp(&d) != 0 { 715 return false 716 } 717 } 718 return true 719 }, 720 genA, 721 genB, 722 )) 723 724 properties.Property("Add: operation result must be smaller than modulus", prop.ForAll( 725 func(a, b testPairElement) bool { 726 var c Element 727 728 c.Add(&a.element, &b.element) 729 730 return c.smallerThanModulus() 731 }, 732 genA, 733 genB, 734 )) 735 736 specialValueTest := func() { 737 // test special values against special values 738 testValues := make([]Element, len(staticTestValues)) 739 copy(testValues, staticTestValues) 740 741 for i := range testValues { 742 a := testValues[i] 743 var aBig big.Int 744 a.BigInt(&aBig) 745 for j := range testValues { 746 b := testValues[j] 747 var bBig, d, e big.Int 748 b.BigInt(&bBig) 749 750 var c Element 751 c.Add(&a, &b) 752 d.Add(&aBig, &bBig).Mod(&d, Modulus()) 753 754 if c.BigInt(&e).Cmp(&d) != 0 { 755 t.Fatal("Add failed special test values") 756 } 757 } 758 } 759 } 760 761 properties.TestingRun(t, gopter.ConsoleReporter(false)) 762 specialValueTest() 763 764 } 765 766 func TestElementSub(t *testing.T) { 767 t.Parallel() 768 parameters := gopter.DefaultTestParameters() 769 if testing.Short() { 770 parameters.MinSuccessfulTests = nbFuzzShort 771 } else { 772 parameters.MinSuccessfulTests = nbFuzz 773 } 774 775 properties := gopter.NewProperties(parameters) 776 777 genA := gen() 778 genB := gen() 779 780 properties.Property("Sub: having the receiver as operand should output the same result", prop.ForAll( 781 func(a, b testPairElement) bool { 782 var c, d Element 783 d.Set(&a.element) 784 785 c.Sub(&a.element, &b.element) 786 a.element.Sub(&a.element, &b.element) 787 b.element.Sub(&d, &b.element) 788 789 return a.element.Equal(&b.element) && a.element.Equal(&c) && b.element.Equal(&c) 790 }, 791 genA, 792 genB, 793 )) 794 795 properties.Property("Sub: operation result must match big.Int result", prop.ForAll( 796 func(a, b testPairElement) bool { 797 { 798 var c Element 799 800 c.Sub(&a.element, &b.element) 801 802 var d, e big.Int 803 d.Sub(&a.bigint, &b.bigint).Mod(&d, Modulus()) 804 805 if c.BigInt(&e).Cmp(&d) != 0 { 806 return false 807 } 808 } 809 810 // fixed elements 811 // a is random 812 // r takes special values 813 testValues := make([]Element, len(staticTestValues)) 814 copy(testValues, staticTestValues) 815 816 for i := range testValues { 817 r := testValues[i] 818 var d, e, rb big.Int 819 r.BigInt(&rb) 820 821 var c Element 822 c.Sub(&a.element, &r) 823 d.Sub(&a.bigint, &rb).Mod(&d, Modulus()) 824 825 if c.BigInt(&e).Cmp(&d) != 0 { 826 return false 827 } 828 } 829 return true 830 }, 831 genA, 832 genB, 833 )) 834 835 properties.Property("Sub: operation result must be smaller than modulus", prop.ForAll( 836 func(a, b testPairElement) bool { 837 var c Element 838 839 c.Sub(&a.element, &b.element) 840 841 return c.smallerThanModulus() 842 }, 843 genA, 844 genB, 845 )) 846 847 specialValueTest := func() { 848 // test special values against special values 849 testValues := make([]Element, len(staticTestValues)) 850 copy(testValues, staticTestValues) 851 852 for i := range testValues { 853 a := testValues[i] 854 var aBig big.Int 855 a.BigInt(&aBig) 856 for j := range testValues { 857 b := testValues[j] 858 var bBig, d, e big.Int 859 b.BigInt(&bBig) 860 861 var c Element 862 c.Sub(&a, &b) 863 d.Sub(&aBig, &bBig).Mod(&d, Modulus()) 864 865 if c.BigInt(&e).Cmp(&d) != 0 { 866 t.Fatal("Sub failed special test values") 867 } 868 } 869 } 870 } 871 872 properties.TestingRun(t, gopter.ConsoleReporter(false)) 873 specialValueTest() 874 875 } 876 877 func TestElementMul(t *testing.T) { 878 t.Parallel() 879 parameters := gopter.DefaultTestParameters() 880 if testing.Short() { 881 parameters.MinSuccessfulTests = nbFuzzShort 882 } else { 883 parameters.MinSuccessfulTests = nbFuzz 884 } 885 886 properties := gopter.NewProperties(parameters) 887 888 genA := gen() 889 genB := gen() 890 891 properties.Property("Mul: having the receiver as operand should output the same result", prop.ForAll( 892 func(a, b testPairElement) bool { 893 var c, d Element 894 d.Set(&a.element) 895 896 c.Mul(&a.element, &b.element) 897 a.element.Mul(&a.element, &b.element) 898 b.element.Mul(&d, &b.element) 899 900 return a.element.Equal(&b.element) && a.element.Equal(&c) && b.element.Equal(&c) 901 }, 902 genA, 903 genB, 904 )) 905 906 properties.Property("Mul: operation result must match big.Int result", prop.ForAll( 907 func(a, b testPairElement) bool { 908 { 909 var c Element 910 911 c.Mul(&a.element, &b.element) 912 913 var d, e big.Int 914 d.Mul(&a.bigint, &b.bigint).Mod(&d, Modulus()) 915 916 if c.BigInt(&e).Cmp(&d) != 0 { 917 return false 918 } 919 } 920 921 // fixed elements 922 // a is random 923 // r takes special values 924 testValues := make([]Element, len(staticTestValues)) 925 copy(testValues, staticTestValues) 926 927 for i := range testValues { 928 r := testValues[i] 929 var d, e, rb big.Int 930 r.BigInt(&rb) 931 932 var c Element 933 c.Mul(&a.element, &r) 934 d.Mul(&a.bigint, &rb).Mod(&d, Modulus()) 935 936 // checking generic impl against asm path 937 var cGeneric Element 938 _mulGeneric(&cGeneric, &a.element, &r) 939 if !cGeneric.Equal(&c) { 940 // need to give context to failing error. 941 return false 942 } 943 944 if c.BigInt(&e).Cmp(&d) != 0 { 945 return false 946 } 947 } 948 return true 949 }, 950 genA, 951 genB, 952 )) 953 954 properties.Property("Mul: operation result must be smaller than modulus", prop.ForAll( 955 func(a, b testPairElement) bool { 956 var c Element 957 958 c.Mul(&a.element, &b.element) 959 960 return c.smallerThanModulus() 961 }, 962 genA, 963 genB, 964 )) 965 966 properties.Property("Mul: assembly implementation must be consistent with generic one", prop.ForAll( 967 func(a, b testPairElement) bool { 968 var c, d Element 969 c.Mul(&a.element, &b.element) 970 _mulGeneric(&d, &a.element, &b.element) 971 return c.Equal(&d) 972 }, 973 genA, 974 genB, 975 )) 976 977 specialValueTest := func() { 978 // test special values against special values 979 testValues := make([]Element, len(staticTestValues)) 980 copy(testValues, staticTestValues) 981 982 for i := range testValues { 983 a := testValues[i] 984 var aBig big.Int 985 a.BigInt(&aBig) 986 for j := range testValues { 987 b := testValues[j] 988 var bBig, d, e big.Int 989 b.BigInt(&bBig) 990 991 var c Element 992 c.Mul(&a, &b) 993 d.Mul(&aBig, &bBig).Mod(&d, Modulus()) 994 995 // checking asm against generic impl 996 var cGeneric Element 997 _mulGeneric(&cGeneric, &a, &b) 998 if !cGeneric.Equal(&c) { 999 t.Fatal("Mul failed special test values: asm and generic impl don't match") 1000 } 1001 1002 if c.BigInt(&e).Cmp(&d) != 0 { 1003 t.Fatal("Mul failed special test values") 1004 } 1005 } 1006 } 1007 } 1008 1009 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1010 specialValueTest() 1011 1012 } 1013 1014 func TestElementDiv(t *testing.T) { 1015 t.Parallel() 1016 parameters := gopter.DefaultTestParameters() 1017 if testing.Short() { 1018 parameters.MinSuccessfulTests = nbFuzzShort 1019 } else { 1020 parameters.MinSuccessfulTests = nbFuzz 1021 } 1022 1023 properties := gopter.NewProperties(parameters) 1024 1025 genA := gen() 1026 genB := gen() 1027 1028 properties.Property("Div: having the receiver as operand should output the same result", prop.ForAll( 1029 func(a, b testPairElement) bool { 1030 var c, d Element 1031 d.Set(&a.element) 1032 1033 c.Div(&a.element, &b.element) 1034 a.element.Div(&a.element, &b.element) 1035 b.element.Div(&d, &b.element) 1036 1037 return a.element.Equal(&b.element) && a.element.Equal(&c) && b.element.Equal(&c) 1038 }, 1039 genA, 1040 genB, 1041 )) 1042 1043 properties.Property("Div: operation result must match big.Int result", prop.ForAll( 1044 func(a, b testPairElement) bool { 1045 { 1046 var c Element 1047 1048 c.Div(&a.element, &b.element) 1049 1050 var d, e big.Int 1051 d.ModInverse(&b.bigint, Modulus()) 1052 d.Mul(&d, &a.bigint).Mod(&d, Modulus()) 1053 1054 if c.BigInt(&e).Cmp(&d) != 0 { 1055 return false 1056 } 1057 } 1058 1059 // fixed elements 1060 // a is random 1061 // r takes special values 1062 testValues := make([]Element, len(staticTestValues)) 1063 copy(testValues, staticTestValues) 1064 1065 for i := range testValues { 1066 r := testValues[i] 1067 var d, e, rb big.Int 1068 r.BigInt(&rb) 1069 1070 var c Element 1071 c.Div(&a.element, &r) 1072 d.ModInverse(&rb, Modulus()) 1073 d.Mul(&d, &a.bigint).Mod(&d, Modulus()) 1074 1075 if c.BigInt(&e).Cmp(&d) != 0 { 1076 return false 1077 } 1078 } 1079 return true 1080 }, 1081 genA, 1082 genB, 1083 )) 1084 1085 properties.Property("Div: operation result must be smaller than modulus", prop.ForAll( 1086 func(a, b testPairElement) bool { 1087 var c Element 1088 1089 c.Div(&a.element, &b.element) 1090 1091 return c.smallerThanModulus() 1092 }, 1093 genA, 1094 genB, 1095 )) 1096 1097 specialValueTest := func() { 1098 // test special values against special values 1099 testValues := make([]Element, len(staticTestValues)) 1100 copy(testValues, staticTestValues) 1101 1102 for i := range testValues { 1103 a := testValues[i] 1104 var aBig big.Int 1105 a.BigInt(&aBig) 1106 for j := range testValues { 1107 b := testValues[j] 1108 var bBig, d, e big.Int 1109 b.BigInt(&bBig) 1110 1111 var c Element 1112 c.Div(&a, &b) 1113 d.ModInverse(&bBig, Modulus()) 1114 d.Mul(&d, &aBig).Mod(&d, Modulus()) 1115 1116 if c.BigInt(&e).Cmp(&d) != 0 { 1117 t.Fatal("Div failed special test values") 1118 } 1119 } 1120 } 1121 } 1122 1123 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1124 specialValueTest() 1125 1126 } 1127 1128 func TestElementExp(t *testing.T) { 1129 t.Parallel() 1130 parameters := gopter.DefaultTestParameters() 1131 if testing.Short() { 1132 parameters.MinSuccessfulTests = nbFuzzShort 1133 } else { 1134 parameters.MinSuccessfulTests = nbFuzz 1135 } 1136 1137 properties := gopter.NewProperties(parameters) 1138 1139 genA := gen() 1140 genB := gen() 1141 1142 properties.Property("Exp: having the receiver as operand should output the same result", prop.ForAll( 1143 func(a, b testPairElement) bool { 1144 var c, d Element 1145 d.Set(&a.element) 1146 1147 c.Exp(a.element, &b.bigint) 1148 a.element.Exp(a.element, &b.bigint) 1149 b.element.Exp(d, &b.bigint) 1150 1151 return a.element.Equal(&b.element) && a.element.Equal(&c) && b.element.Equal(&c) 1152 }, 1153 genA, 1154 genB, 1155 )) 1156 1157 properties.Property("Exp: operation result must match big.Int result", prop.ForAll( 1158 func(a, b testPairElement) bool { 1159 { 1160 var c Element 1161 1162 c.Exp(a.element, &b.bigint) 1163 1164 var d, e big.Int 1165 d.Exp(&a.bigint, &b.bigint, Modulus()) 1166 1167 if c.BigInt(&e).Cmp(&d) != 0 { 1168 return false 1169 } 1170 } 1171 1172 // fixed elements 1173 // a is random 1174 // r takes special values 1175 testValues := make([]Element, len(staticTestValues)) 1176 copy(testValues, staticTestValues) 1177 1178 for i := range testValues { 1179 r := testValues[i] 1180 var d, e, rb big.Int 1181 r.BigInt(&rb) 1182 1183 var c Element 1184 c.Exp(a.element, &rb) 1185 d.Exp(&a.bigint, &rb, Modulus()) 1186 1187 if c.BigInt(&e).Cmp(&d) != 0 { 1188 return false 1189 } 1190 } 1191 return true 1192 }, 1193 genA, 1194 genB, 1195 )) 1196 1197 properties.Property("Exp: operation result must be smaller than modulus", prop.ForAll( 1198 func(a, b testPairElement) bool { 1199 var c Element 1200 1201 c.Exp(a.element, &b.bigint) 1202 1203 return c.smallerThanModulus() 1204 }, 1205 genA, 1206 genB, 1207 )) 1208 1209 specialValueTest := func() { 1210 // test special values against special values 1211 testValues := make([]Element, len(staticTestValues)) 1212 copy(testValues, staticTestValues) 1213 1214 for i := range testValues { 1215 a := testValues[i] 1216 var aBig big.Int 1217 a.BigInt(&aBig) 1218 for j := range testValues { 1219 b := testValues[j] 1220 var bBig, d, e big.Int 1221 b.BigInt(&bBig) 1222 1223 var c Element 1224 c.Exp(a, &bBig) 1225 d.Exp(&aBig, &bBig, Modulus()) 1226 1227 if c.BigInt(&e).Cmp(&d) != 0 { 1228 t.Fatal("Exp failed special test values") 1229 } 1230 } 1231 } 1232 } 1233 1234 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1235 specialValueTest() 1236 1237 } 1238 1239 func TestElementSquare(t *testing.T) { 1240 t.Parallel() 1241 parameters := gopter.DefaultTestParameters() 1242 if testing.Short() { 1243 parameters.MinSuccessfulTests = nbFuzzShort 1244 } else { 1245 parameters.MinSuccessfulTests = nbFuzz 1246 } 1247 1248 properties := gopter.NewProperties(parameters) 1249 1250 genA := gen() 1251 1252 properties.Property("Square: having the receiver as operand should output the same result", prop.ForAll( 1253 func(a testPairElement) bool { 1254 1255 var b Element 1256 1257 b.Square(&a.element) 1258 a.element.Square(&a.element) 1259 return a.element.Equal(&b) 1260 }, 1261 genA, 1262 )) 1263 1264 properties.Property("Square: operation result must match big.Int result", prop.ForAll( 1265 func(a testPairElement) bool { 1266 var c Element 1267 c.Square(&a.element) 1268 1269 var d, e big.Int 1270 d.Mul(&a.bigint, &a.bigint).Mod(&d, Modulus()) 1271 1272 return c.BigInt(&e).Cmp(&d) == 0 1273 }, 1274 genA, 1275 )) 1276 1277 properties.Property("Square: operation result must be smaller than modulus", prop.ForAll( 1278 func(a testPairElement) bool { 1279 var c Element 1280 c.Square(&a.element) 1281 return c.smallerThanModulus() 1282 }, 1283 genA, 1284 )) 1285 1286 specialValueTest := func() { 1287 // test special values 1288 testValues := make([]Element, len(staticTestValues)) 1289 copy(testValues, staticTestValues) 1290 1291 for i := range testValues { 1292 a := testValues[i] 1293 var aBig big.Int 1294 a.BigInt(&aBig) 1295 var c Element 1296 c.Square(&a) 1297 1298 var d, e big.Int 1299 d.Mul(&aBig, &aBig).Mod(&d, Modulus()) 1300 1301 if c.BigInt(&e).Cmp(&d) != 0 { 1302 t.Fatal("Square failed special test values") 1303 } 1304 } 1305 } 1306 1307 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1308 specialValueTest() 1309 1310 } 1311 1312 func TestElementInverse(t *testing.T) { 1313 t.Parallel() 1314 parameters := gopter.DefaultTestParameters() 1315 if testing.Short() { 1316 parameters.MinSuccessfulTests = nbFuzzShort 1317 } else { 1318 parameters.MinSuccessfulTests = nbFuzz 1319 } 1320 1321 properties := gopter.NewProperties(parameters) 1322 1323 genA := gen() 1324 1325 properties.Property("Inverse: having the receiver as operand should output the same result", prop.ForAll( 1326 func(a testPairElement) bool { 1327 1328 var b Element 1329 1330 b.Inverse(&a.element) 1331 a.element.Inverse(&a.element) 1332 return a.element.Equal(&b) 1333 }, 1334 genA, 1335 )) 1336 1337 properties.Property("Inverse: operation result must match big.Int result", prop.ForAll( 1338 func(a testPairElement) bool { 1339 var c Element 1340 c.Inverse(&a.element) 1341 1342 var d, e big.Int 1343 d.ModInverse(&a.bigint, Modulus()) 1344 1345 return c.BigInt(&e).Cmp(&d) == 0 1346 }, 1347 genA, 1348 )) 1349 1350 properties.Property("Inverse: operation result must be smaller than modulus", prop.ForAll( 1351 func(a testPairElement) bool { 1352 var c Element 1353 c.Inverse(&a.element) 1354 return c.smallerThanModulus() 1355 }, 1356 genA, 1357 )) 1358 1359 specialValueTest := func() { 1360 // test special values 1361 testValues := make([]Element, len(staticTestValues)) 1362 copy(testValues, staticTestValues) 1363 1364 for i := range testValues { 1365 a := testValues[i] 1366 var aBig big.Int 1367 a.BigInt(&aBig) 1368 var c Element 1369 c.Inverse(&a) 1370 1371 var d, e big.Int 1372 d.ModInverse(&aBig, Modulus()) 1373 1374 if c.BigInt(&e).Cmp(&d) != 0 { 1375 t.Fatal("Inverse failed special test values") 1376 } 1377 } 1378 } 1379 1380 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1381 specialValueTest() 1382 1383 } 1384 1385 func TestElementSqrt(t *testing.T) { 1386 t.Parallel() 1387 parameters := gopter.DefaultTestParameters() 1388 if testing.Short() { 1389 parameters.MinSuccessfulTests = nbFuzzShort 1390 } else { 1391 parameters.MinSuccessfulTests = nbFuzz 1392 } 1393 1394 properties := gopter.NewProperties(parameters) 1395 1396 genA := gen() 1397 1398 properties.Property("Sqrt: having the receiver as operand should output the same result", prop.ForAll( 1399 func(a testPairElement) bool { 1400 1401 b := a.element 1402 1403 b.Sqrt(&a.element) 1404 a.element.Sqrt(&a.element) 1405 return a.element.Equal(&b) 1406 }, 1407 genA, 1408 )) 1409 1410 properties.Property("Sqrt: operation result must match big.Int result", prop.ForAll( 1411 func(a testPairElement) bool { 1412 var c Element 1413 c.Sqrt(&a.element) 1414 1415 var d, e big.Int 1416 d.ModSqrt(&a.bigint, Modulus()) 1417 1418 return c.BigInt(&e).Cmp(&d) == 0 1419 }, 1420 genA, 1421 )) 1422 1423 properties.Property("Sqrt: operation result must be smaller than modulus", prop.ForAll( 1424 func(a testPairElement) bool { 1425 var c Element 1426 c.Sqrt(&a.element) 1427 return c.smallerThanModulus() 1428 }, 1429 genA, 1430 )) 1431 1432 specialValueTest := func() { 1433 // test special values 1434 testValues := make([]Element, len(staticTestValues)) 1435 copy(testValues, staticTestValues) 1436 1437 for i := range testValues { 1438 a := testValues[i] 1439 var aBig big.Int 1440 a.BigInt(&aBig) 1441 var c Element 1442 c.Sqrt(&a) 1443 1444 var d, e big.Int 1445 d.ModSqrt(&aBig, Modulus()) 1446 1447 if c.BigInt(&e).Cmp(&d) != 0 { 1448 t.Fatal("Sqrt failed special test values") 1449 } 1450 } 1451 } 1452 1453 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1454 specialValueTest() 1455 1456 } 1457 1458 func TestElementDouble(t *testing.T) { 1459 t.Parallel() 1460 parameters := gopter.DefaultTestParameters() 1461 if testing.Short() { 1462 parameters.MinSuccessfulTests = nbFuzzShort 1463 } else { 1464 parameters.MinSuccessfulTests = nbFuzz 1465 } 1466 1467 properties := gopter.NewProperties(parameters) 1468 1469 genA := gen() 1470 1471 properties.Property("Double: having the receiver as operand should output the same result", prop.ForAll( 1472 func(a testPairElement) bool { 1473 1474 var b Element 1475 1476 b.Double(&a.element) 1477 a.element.Double(&a.element) 1478 return a.element.Equal(&b) 1479 }, 1480 genA, 1481 )) 1482 1483 properties.Property("Double: operation result must match big.Int result", prop.ForAll( 1484 func(a testPairElement) bool { 1485 var c Element 1486 c.Double(&a.element) 1487 1488 var d, e big.Int 1489 d.Lsh(&a.bigint, 1).Mod(&d, Modulus()) 1490 1491 return c.BigInt(&e).Cmp(&d) == 0 1492 }, 1493 genA, 1494 )) 1495 1496 properties.Property("Double: operation result must be smaller than modulus", prop.ForAll( 1497 func(a testPairElement) bool { 1498 var c Element 1499 c.Double(&a.element) 1500 return c.smallerThanModulus() 1501 }, 1502 genA, 1503 )) 1504 1505 specialValueTest := func() { 1506 // test special values 1507 testValues := make([]Element, len(staticTestValues)) 1508 copy(testValues, staticTestValues) 1509 1510 for i := range testValues { 1511 a := testValues[i] 1512 var aBig big.Int 1513 a.BigInt(&aBig) 1514 var c Element 1515 c.Double(&a) 1516 1517 var d, e big.Int 1518 d.Lsh(&aBig, 1).Mod(&d, Modulus()) 1519 1520 if c.BigInt(&e).Cmp(&d) != 0 { 1521 t.Fatal("Double failed special test values") 1522 } 1523 } 1524 } 1525 1526 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1527 specialValueTest() 1528 1529 } 1530 1531 func TestElementNeg(t *testing.T) { 1532 t.Parallel() 1533 parameters := gopter.DefaultTestParameters() 1534 if testing.Short() { 1535 parameters.MinSuccessfulTests = nbFuzzShort 1536 } else { 1537 parameters.MinSuccessfulTests = nbFuzz 1538 } 1539 1540 properties := gopter.NewProperties(parameters) 1541 1542 genA := gen() 1543 1544 properties.Property("Neg: having the receiver as operand should output the same result", prop.ForAll( 1545 func(a testPairElement) bool { 1546 1547 var b Element 1548 1549 b.Neg(&a.element) 1550 a.element.Neg(&a.element) 1551 return a.element.Equal(&b) 1552 }, 1553 genA, 1554 )) 1555 1556 properties.Property("Neg: operation result must match big.Int result", prop.ForAll( 1557 func(a testPairElement) bool { 1558 var c Element 1559 c.Neg(&a.element) 1560 1561 var d, e big.Int 1562 d.Neg(&a.bigint).Mod(&d, Modulus()) 1563 1564 return c.BigInt(&e).Cmp(&d) == 0 1565 }, 1566 genA, 1567 )) 1568 1569 properties.Property("Neg: operation result must be smaller than modulus", prop.ForAll( 1570 func(a testPairElement) bool { 1571 var c Element 1572 c.Neg(&a.element) 1573 return c.smallerThanModulus() 1574 }, 1575 genA, 1576 )) 1577 1578 specialValueTest := func() { 1579 // test special values 1580 testValues := make([]Element, len(staticTestValues)) 1581 copy(testValues, staticTestValues) 1582 1583 for i := range testValues { 1584 a := testValues[i] 1585 var aBig big.Int 1586 a.BigInt(&aBig) 1587 var c Element 1588 c.Neg(&a) 1589 1590 var d, e big.Int 1591 d.Neg(&aBig).Mod(&d, Modulus()) 1592 1593 if c.BigInt(&e).Cmp(&d) != 0 { 1594 t.Fatal("Neg failed special test values") 1595 } 1596 } 1597 } 1598 1599 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1600 specialValueTest() 1601 1602 } 1603 1604 func TestElementFixedExp(t *testing.T) { 1605 1606 t.Parallel() 1607 parameters := gopter.DefaultTestParameters() 1608 if testing.Short() { 1609 parameters.MinSuccessfulTests = nbFuzzShort 1610 } else { 1611 parameters.MinSuccessfulTests = nbFuzz 1612 } 1613 1614 properties := gopter.NewProperties(parameters) 1615 1616 var ( 1617 _bLegendreExponentElement *big.Int 1618 _bSqrtExponentElement *big.Int 1619 ) 1620 1621 _bLegendreExponentElement, _ = new(big.Int).SetString("7fffffff80000000", 16) 1622 const sqrtExponentElement = "7fffffff" 1623 _bSqrtExponentElement, _ = new(big.Int).SetString(sqrtExponentElement, 16) 1624 1625 genA := gen() 1626 1627 properties.Property(fmt.Sprintf("expBySqrtExp must match Exp(%s)", sqrtExponentElement), prop.ForAll( 1628 func(a testPairElement) bool { 1629 c := a.element 1630 d := a.element 1631 c.expBySqrtExp(c) 1632 d.Exp(d, _bSqrtExponentElement) 1633 return c.Equal(&d) 1634 }, 1635 genA, 1636 )) 1637 1638 properties.Property("expByLegendreExp must match Exp(7fffffff80000000)", prop.ForAll( 1639 func(a testPairElement) bool { 1640 c := a.element 1641 d := a.element 1642 c.expByLegendreExp(c) 1643 d.Exp(d, _bLegendreExponentElement) 1644 return c.Equal(&d) 1645 }, 1646 genA, 1647 )) 1648 1649 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1650 } 1651 1652 func TestElementHalve(t *testing.T) { 1653 1654 t.Parallel() 1655 parameters := gopter.DefaultTestParameters() 1656 if testing.Short() { 1657 parameters.MinSuccessfulTests = nbFuzzShort 1658 } else { 1659 parameters.MinSuccessfulTests = nbFuzz 1660 } 1661 1662 properties := gopter.NewProperties(parameters) 1663 1664 genA := gen() 1665 var twoInv Element 1666 twoInv.SetUint64(2) 1667 twoInv.Inverse(&twoInv) 1668 1669 properties.Property("z.Halve must match z / 2", prop.ForAll( 1670 func(a testPairElement) bool { 1671 c := a.element 1672 d := a.element 1673 c.Halve() 1674 d.Mul(&d, &twoInv) 1675 return c.Equal(&d) 1676 }, 1677 genA, 1678 )) 1679 1680 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1681 } 1682 1683 func combineSelectionArguments(c int64, z int8) int { 1684 if z%3 == 0 { 1685 return 0 1686 } 1687 return int(c) 1688 } 1689 1690 func TestElementSelect(t *testing.T) { 1691 t.Parallel() 1692 parameters := gopter.DefaultTestParameters() 1693 if testing.Short() { 1694 parameters.MinSuccessfulTests = nbFuzzShort 1695 } else { 1696 parameters.MinSuccessfulTests = nbFuzz 1697 } 1698 1699 properties := gopter.NewProperties(parameters) 1700 1701 genA := genFull() 1702 genB := genFull() 1703 genC := ggen.Int64() //the condition 1704 genZ := ggen.Int8() //to make zeros artificially more likely 1705 1706 properties.Property("Select: must select correctly", prop.ForAll( 1707 func(a, b Element, cond int64, z int8) bool { 1708 condC := combineSelectionArguments(cond, z) 1709 1710 var c Element 1711 c.Select(condC, &a, &b) 1712 1713 if condC == 0 { 1714 return c.Equal(&a) 1715 } 1716 return c.Equal(&b) 1717 }, 1718 genA, 1719 genB, 1720 genC, 1721 genZ, 1722 )) 1723 1724 properties.Property("Select: having the receiver as operand should output the same result", prop.ForAll( 1725 func(a, b Element, cond int64, z int8) bool { 1726 condC := combineSelectionArguments(cond, z) 1727 1728 var c, d Element 1729 d.Set(&a) 1730 c.Select(condC, &a, &b) 1731 a.Select(condC, &a, &b) 1732 b.Select(condC, &d, &b) 1733 return a.Equal(&b) && a.Equal(&c) && b.Equal(&c) 1734 }, 1735 genA, 1736 genB, 1737 genC, 1738 genZ, 1739 )) 1740 1741 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1742 } 1743 1744 func TestElementSetInt64(t *testing.T) { 1745 1746 t.Parallel() 1747 parameters := gopter.DefaultTestParameters() 1748 if testing.Short() { 1749 parameters.MinSuccessfulTests = nbFuzzShort 1750 } else { 1751 parameters.MinSuccessfulTests = nbFuzz 1752 } 1753 1754 properties := gopter.NewProperties(parameters) 1755 1756 genA := gen() 1757 1758 properties.Property("z.SetInt64 must match z.SetString", prop.ForAll( 1759 func(a testPairElement, v int64) bool { 1760 c := a.element 1761 d := a.element 1762 1763 c.SetInt64(v) 1764 d.SetString(fmt.Sprintf("%v", v)) 1765 1766 return c.Equal(&d) 1767 }, 1768 genA, ggen.Int64(), 1769 )) 1770 1771 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1772 } 1773 1774 func TestElementSetInterface(t *testing.T) { 1775 1776 t.Parallel() 1777 parameters := gopter.DefaultTestParameters() 1778 if testing.Short() { 1779 parameters.MinSuccessfulTests = nbFuzzShort 1780 } else { 1781 parameters.MinSuccessfulTests = nbFuzz 1782 } 1783 1784 properties := gopter.NewProperties(parameters) 1785 1786 genA := gen() 1787 genInt := ggen.Int 1788 genInt8 := ggen.Int8 1789 genInt16 := ggen.Int16 1790 genInt32 := ggen.Int32 1791 genInt64 := ggen.Int64 1792 1793 genUint := ggen.UInt 1794 genUint8 := ggen.UInt8 1795 genUint16 := ggen.UInt16 1796 genUint32 := ggen.UInt32 1797 genUint64 := ggen.UInt64 1798 1799 properties.Property("z.SetInterface must match z.SetString with int8", prop.ForAll( 1800 func(a testPairElement, v int8) bool { 1801 c := a.element 1802 d := a.element 1803 1804 c.SetInterface(v) 1805 d.SetString(fmt.Sprintf("%v", v)) 1806 1807 return c.Equal(&d) 1808 }, 1809 genA, genInt8(), 1810 )) 1811 1812 properties.Property("z.SetInterface must match z.SetString with int16", prop.ForAll( 1813 func(a testPairElement, v int16) bool { 1814 c := a.element 1815 d := a.element 1816 1817 c.SetInterface(v) 1818 d.SetString(fmt.Sprintf("%v", v)) 1819 1820 return c.Equal(&d) 1821 }, 1822 genA, genInt16(), 1823 )) 1824 1825 properties.Property("z.SetInterface must match z.SetString with int32", prop.ForAll( 1826 func(a testPairElement, v int32) bool { 1827 c := a.element 1828 d := a.element 1829 1830 c.SetInterface(v) 1831 d.SetString(fmt.Sprintf("%v", v)) 1832 1833 return c.Equal(&d) 1834 }, 1835 genA, genInt32(), 1836 )) 1837 1838 properties.Property("z.SetInterface must match z.SetString with int64", prop.ForAll( 1839 func(a testPairElement, v int64) bool { 1840 c := a.element 1841 d := a.element 1842 1843 c.SetInterface(v) 1844 d.SetString(fmt.Sprintf("%v", v)) 1845 1846 return c.Equal(&d) 1847 }, 1848 genA, genInt64(), 1849 )) 1850 1851 properties.Property("z.SetInterface must match z.SetString with int", prop.ForAll( 1852 func(a testPairElement, v int) bool { 1853 c := a.element 1854 d := a.element 1855 1856 c.SetInterface(v) 1857 d.SetString(fmt.Sprintf("%v", v)) 1858 1859 return c.Equal(&d) 1860 }, 1861 genA, genInt(), 1862 )) 1863 1864 properties.Property("z.SetInterface must match z.SetString with uint8", prop.ForAll( 1865 func(a testPairElement, v uint8) bool { 1866 c := a.element 1867 d := a.element 1868 1869 c.SetInterface(v) 1870 d.SetString(fmt.Sprintf("%v", v)) 1871 1872 return c.Equal(&d) 1873 }, 1874 genA, genUint8(), 1875 )) 1876 1877 properties.Property("z.SetInterface must match z.SetString with uint16", prop.ForAll( 1878 func(a testPairElement, v uint16) bool { 1879 c := a.element 1880 d := a.element 1881 1882 c.SetInterface(v) 1883 d.SetString(fmt.Sprintf("%v", v)) 1884 1885 return c.Equal(&d) 1886 }, 1887 genA, genUint16(), 1888 )) 1889 1890 properties.Property("z.SetInterface must match z.SetString with uint32", prop.ForAll( 1891 func(a testPairElement, v uint32) bool { 1892 c := a.element 1893 d := a.element 1894 1895 c.SetInterface(v) 1896 d.SetString(fmt.Sprintf("%v", v)) 1897 1898 return c.Equal(&d) 1899 }, 1900 genA, genUint32(), 1901 )) 1902 1903 properties.Property("z.SetInterface must match z.SetString with uint64", prop.ForAll( 1904 func(a testPairElement, v uint64) bool { 1905 c := a.element 1906 d := a.element 1907 1908 c.SetInterface(v) 1909 d.SetString(fmt.Sprintf("%v", v)) 1910 1911 return c.Equal(&d) 1912 }, 1913 genA, genUint64(), 1914 )) 1915 1916 properties.Property("z.SetInterface must match z.SetString with uint", prop.ForAll( 1917 func(a testPairElement, v uint) bool { 1918 c := a.element 1919 d := a.element 1920 1921 c.SetInterface(v) 1922 d.SetString(fmt.Sprintf("%v", v)) 1923 1924 return c.Equal(&d) 1925 }, 1926 genA, genUint(), 1927 )) 1928 1929 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1930 1931 { 1932 assert := require.New(t) 1933 var e Element 1934 r, err := e.SetInterface(nil) 1935 assert.Nil(r) 1936 assert.Error(err) 1937 1938 var ptE *Element 1939 var ptB *big.Int 1940 1941 r, err = e.SetInterface(ptE) 1942 assert.Nil(r) 1943 assert.Error(err) 1944 ptE = new(Element).SetOne() 1945 r, err = e.SetInterface(ptE) 1946 assert.NoError(err) 1947 assert.True(r.IsOne()) 1948 1949 r, err = e.SetInterface(ptB) 1950 assert.Nil(r) 1951 assert.Error(err) 1952 1953 } 1954 } 1955 1956 func TestElementNegativeExp(t *testing.T) { 1957 t.Parallel() 1958 1959 parameters := gopter.DefaultTestParameters() 1960 if testing.Short() { 1961 parameters.MinSuccessfulTests = nbFuzzShort 1962 } else { 1963 parameters.MinSuccessfulTests = nbFuzz 1964 } 1965 1966 properties := gopter.NewProperties(parameters) 1967 1968 genA := gen() 1969 1970 properties.Property("x⁻ᵏ == 1/xᵏ", prop.ForAll( 1971 func(a, b testPairElement) bool { 1972 1973 var nb, d, e big.Int 1974 nb.Neg(&b.bigint) 1975 1976 var c Element 1977 c.Exp(a.element, &nb) 1978 1979 d.Exp(&a.bigint, &nb, Modulus()) 1980 1981 return c.BigInt(&e).Cmp(&d) == 0 1982 }, 1983 genA, genA, 1984 )) 1985 1986 properties.TestingRun(t, gopter.ConsoleReporter(false)) 1987 } 1988 1989 func TestElementNewElement(t *testing.T) { 1990 assert := require.New(t) 1991 1992 t.Parallel() 1993 1994 e := NewElement(1) 1995 assert.True(e.IsOne()) 1996 1997 e = NewElement(0) 1998 assert.True(e.IsZero()) 1999 } 2000 2001 func TestElementBatchInvert(t *testing.T) { 2002 assert := require.New(t) 2003 2004 t.Parallel() 2005 2006 // ensure batchInvert([x]) == invert(x) 2007 for i := int64(-1); i <= 2; i++ { 2008 var e, eInv Element 2009 e.SetInt64(i) 2010 eInv.Inverse(&e) 2011 2012 a := []Element{e} 2013 aInv := BatchInvert(a) 2014 2015 assert.True(aInv[0].Equal(&eInv), "batchInvert != invert") 2016 2017 } 2018 2019 // test x * x⁻¹ == 1 2020 tData := [][]int64{ 2021 {-1, 1, 2, 3}, 2022 {0, -1, 1, 2, 3, 0}, 2023 {0, -1, 1, 0, 2, 3, 0}, 2024 {-1, 1, 0, 2, 3}, 2025 {0, 0, 1}, 2026 {1, 0, 0}, 2027 {0, 0, 0}, 2028 } 2029 2030 for _, t := range tData { 2031 a := make([]Element, len(t)) 2032 for i := 0; i < len(a); i++ { 2033 a[i].SetInt64(t[i]) 2034 } 2035 2036 aInv := BatchInvert(a) 2037 2038 assert.True(len(aInv) == len(a)) 2039 2040 for i := 0; i < len(a); i++ { 2041 if a[i].IsZero() { 2042 assert.True(aInv[i].IsZero(), "0⁻¹ != 0") 2043 } else { 2044 assert.True(a[i].Mul(&a[i], &aInv[i]).IsOne(), "x * x⁻¹ != 1") 2045 } 2046 } 2047 } 2048 2049 parameters := gopter.DefaultTestParameters() 2050 if testing.Short() { 2051 parameters.MinSuccessfulTests = nbFuzzShort 2052 } else { 2053 parameters.MinSuccessfulTests = nbFuzz 2054 } 2055 2056 properties := gopter.NewProperties(parameters) 2057 2058 genA := gen() 2059 2060 properties.Property("batchInvert --> x * x⁻¹ == 1", prop.ForAll( 2061 func(tp testPairElement, r uint8) bool { 2062 2063 a := make([]Element, r) 2064 if r != 0 { 2065 a[0] = tp.element 2066 2067 } 2068 one := One() 2069 for i := 1; i < len(a); i++ { 2070 a[i].Add(&a[i-1], &one) 2071 } 2072 2073 aInv := BatchInvert(a) 2074 2075 assert.True(len(aInv) == len(a)) 2076 2077 for i := 0; i < len(a); i++ { 2078 if a[i].IsZero() { 2079 if !aInv[i].IsZero() { 2080 return false 2081 } 2082 } else { 2083 if !a[i].Mul(&a[i], &aInv[i]).IsOne() { 2084 return false 2085 } 2086 } 2087 } 2088 return true 2089 }, 2090 genA, ggen.UInt8(), 2091 )) 2092 2093 properties.TestingRun(t, gopter.ConsoleReporter(false)) 2094 } 2095 2096 func TestElementFromMont(t *testing.T) { 2097 2098 t.Parallel() 2099 parameters := gopter.DefaultTestParameters() 2100 if testing.Short() { 2101 parameters.MinSuccessfulTests = nbFuzzShort 2102 } else { 2103 parameters.MinSuccessfulTests = nbFuzz 2104 } 2105 2106 properties := gopter.NewProperties(parameters) 2107 2108 genA := gen() 2109 2110 properties.Property("Assembly implementation must be consistent with generic one", prop.ForAll( 2111 func(a testPairElement) bool { 2112 c := a.element 2113 d := a.element 2114 c.fromMont() 2115 _fromMontGeneric(&d) 2116 return c.Equal(&d) 2117 }, 2118 genA, 2119 )) 2120 2121 properties.Property("x.fromMont().toMont() == x", prop.ForAll( 2122 func(a testPairElement) bool { 2123 c := a.element 2124 c.fromMont().toMont() 2125 return c.Equal(&a.element) 2126 }, 2127 genA, 2128 )) 2129 2130 properties.TestingRun(t, gopter.ConsoleReporter(false)) 2131 } 2132 2133 func TestElementJSON(t *testing.T) { 2134 assert := require.New(t) 2135 2136 type S struct { 2137 A Element 2138 B [3]Element 2139 C *Element 2140 D *Element 2141 } 2142 2143 // encode to JSON 2144 var s S 2145 s.A.SetString("-1") 2146 s.B[2].SetUint64(42) 2147 s.D = new(Element).SetUint64(8000) 2148 2149 encoded, err := json.Marshal(&s) 2150 assert.NoError(err) 2151 // we may need to adjust "42" and "8000" values for some moduli; see Text() method for more details. 2152 formatValue := func(v int64) string { 2153 var a big.Int 2154 a.SetInt64(v) 2155 a.Mod(&a, Modulus()) 2156 const maxUint16 = 65535 2157 var aNeg big.Int 2158 aNeg.Neg(&a).Mod(&aNeg, Modulus()) 2159 if aNeg.Uint64() != 0 && aNeg.Uint64() <= maxUint16 { 2160 return "-" + aNeg.Text(10) 2161 } 2162 return a.Text(10) 2163 } 2164 expected := fmt.Sprintf("{\"A\":%s,\"B\":[0,0,%s],\"C\":null,\"D\":%s}", formatValue(-1), formatValue(42), formatValue(8000)) 2165 assert.Equal(expected, string(encoded)) 2166 2167 // decode valid 2168 var decoded S 2169 err = json.Unmarshal([]byte(expected), &decoded) 2170 assert.NoError(err) 2171 2172 assert.Equal(s, decoded, "element -> json -> element round trip failed") 2173 2174 // decode hex and string values 2175 withHexValues := "{\"A\":\"-1\",\"B\":[0,\"0x00000\",\"0x2A\"],\"C\":null,\"D\":\"8000\"}" 2176 2177 var decodedS S 2178 err = json.Unmarshal([]byte(withHexValues), &decodedS) 2179 assert.NoError(err) 2180 2181 assert.Equal(s, decodedS, " json with strings -> element failed") 2182 2183 } 2184 2185 type testPairElement struct { 2186 element Element 2187 bigint big.Int 2188 } 2189 2190 func gen() gopter.Gen { 2191 return func(genParams *gopter.GenParameters) *gopter.GenResult { 2192 var g testPairElement 2193 2194 g.element = Element{ 2195 genParams.NextUint64(), 2196 } 2197 if qElement[0] != ^uint64(0) { 2198 g.element[0] %= (qElement[0] + 1) 2199 } 2200 2201 for !g.element.smallerThanModulus() { 2202 g.element = Element{ 2203 genParams.NextUint64(), 2204 } 2205 if qElement[0] != ^uint64(0) { 2206 g.element[0] %= (qElement[0] + 1) 2207 } 2208 } 2209 2210 g.element.BigInt(&g.bigint) 2211 genResult := gopter.NewGenResult(g, gopter.NoShrinker) 2212 return genResult 2213 } 2214 } 2215 2216 func genFull() gopter.Gen { 2217 return func(genParams *gopter.GenParameters) *gopter.GenResult { 2218 2219 genRandomFq := func() Element { 2220 var g Element 2221 2222 g = Element{ 2223 genParams.NextUint64(), 2224 } 2225 2226 if qElement[0] != ^uint64(0) { 2227 g[0] %= (qElement[0] + 1) 2228 } 2229 2230 for !g.smallerThanModulus() { 2231 g = Element{ 2232 genParams.NextUint64(), 2233 } 2234 if qElement[0] != ^uint64(0) { 2235 g[0] %= (qElement[0] + 1) 2236 } 2237 } 2238 2239 return g 2240 } 2241 a := genRandomFq() 2242 2243 var carry uint64 2244 a[0], _ = bits.Add64(a[0], qElement[0], carry) 2245 2246 genResult := gopter.NewGenResult(a, gopter.NoShrinker) 2247 return genResult 2248 } 2249 }