You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1874 lines
40 KiB

  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. // Code generated by consensys/gnark-crypto DO NOT EDIT
  15. package ff
  16. import (
  17. "crypto/rand"
  18. "math/big"
  19. "math/bits"
  20. "testing"
  21. "github.com/leanovate/gopter"
  22. "github.com/leanovate/gopter/prop"
  23. )
  24. // -------------------------------------------------------------------------------------------------
  25. // benchmarks
  26. // most benchmarks are rudimentary and should sample a large number of random inputs
  27. // or be run multiple times to ensure it didn't measure the fastest path of the function
  28. var benchResElement Element
  29. func BenchmarkElementSetBytes(b *testing.B) {
  30. var x Element
  31. x.SetRandom()
  32. bb := x.Bytes()
  33. b.ResetTimer()
  34. for i := 0; i < b.N; i++ {
  35. benchResElement.SetBytes(bb[:])
  36. }
  37. }
  38. func BenchmarkElementMulByConstants(b *testing.B) {
  39. b.Run("mulBy3", func(b *testing.B) {
  40. benchResElement.SetRandom()
  41. b.ResetTimer()
  42. for i := 0; i < b.N; i++ {
  43. MulBy3(&benchResElement)
  44. }
  45. })
  46. b.Run("mulBy5", func(b *testing.B) {
  47. benchResElement.SetRandom()
  48. b.ResetTimer()
  49. for i := 0; i < b.N; i++ {
  50. MulBy5(&benchResElement)
  51. }
  52. })
  53. b.Run("mulBy13", func(b *testing.B) {
  54. benchResElement.SetRandom()
  55. b.ResetTimer()
  56. for i := 0; i < b.N; i++ {
  57. MulBy13(&benchResElement)
  58. }
  59. })
  60. }
  61. func BenchmarkElementInverse(b *testing.B) {
  62. var x Element
  63. x.SetRandom()
  64. benchResElement.SetRandom()
  65. b.ResetTimer()
  66. for i := 0; i < b.N; i++ {
  67. benchResElement.Inverse(&x)
  68. }
  69. }
  70. func BenchmarkElementButterfly(b *testing.B) {
  71. var x Element
  72. x.SetRandom()
  73. benchResElement.SetRandom()
  74. b.ResetTimer()
  75. for i := 0; i < b.N; i++ {
  76. Butterfly(&x, &benchResElement)
  77. }
  78. }
  79. func BenchmarkElementExp(b *testing.B) {
  80. var x Element
  81. x.SetRandom()
  82. benchResElement.SetRandom()
  83. b1, _ := rand.Int(rand.Reader, Modulus())
  84. b.ResetTimer()
  85. for i := 0; i < b.N; i++ {
  86. benchResElement.Exp(x, b1)
  87. }
  88. }
  89. func BenchmarkElementDouble(b *testing.B) {
  90. benchResElement.SetRandom()
  91. b.ResetTimer()
  92. for i := 0; i < b.N; i++ {
  93. benchResElement.Double(&benchResElement)
  94. }
  95. }
  96. func BenchmarkElementAdd(b *testing.B) {
  97. var x Element
  98. x.SetRandom()
  99. benchResElement.SetRandom()
  100. b.ResetTimer()
  101. for i := 0; i < b.N; i++ {
  102. benchResElement.Add(&x, &benchResElement)
  103. }
  104. }
  105. func BenchmarkElementSub(b *testing.B) {
  106. var x Element
  107. x.SetRandom()
  108. benchResElement.SetRandom()
  109. b.ResetTimer()
  110. for i := 0; i < b.N; i++ {
  111. benchResElement.Sub(&x, &benchResElement)
  112. }
  113. }
  114. func BenchmarkElementNeg(b *testing.B) {
  115. benchResElement.SetRandom()
  116. b.ResetTimer()
  117. for i := 0; i < b.N; i++ {
  118. benchResElement.Neg(&benchResElement)
  119. }
  120. }
  121. func BenchmarkElementDiv(b *testing.B) {
  122. var x Element
  123. x.SetRandom()
  124. benchResElement.SetRandom()
  125. b.ResetTimer()
  126. for i := 0; i < b.N; i++ {
  127. benchResElement.Div(&x, &benchResElement)
  128. }
  129. }
  130. func BenchmarkElementFromMont(b *testing.B) {
  131. benchResElement.SetRandom()
  132. b.ResetTimer()
  133. for i := 0; i < b.N; i++ {
  134. benchResElement.FromMont()
  135. }
  136. }
  137. func BenchmarkElementToMont(b *testing.B) {
  138. benchResElement.SetRandom()
  139. b.ResetTimer()
  140. for i := 0; i < b.N; i++ {
  141. benchResElement.ToMont()
  142. }
  143. }
  144. func BenchmarkElementSquare(b *testing.B) {
  145. benchResElement.SetRandom()
  146. b.ResetTimer()
  147. for i := 0; i < b.N; i++ {
  148. benchResElement.Square(&benchResElement)
  149. }
  150. }
  151. func BenchmarkElementSqrt(b *testing.B) {
  152. var a Element
  153. a.SetUint64(4)
  154. a.Neg(&a)
  155. b.ResetTimer()
  156. for i := 0; i < b.N; i++ {
  157. benchResElement.Sqrt(&a)
  158. }
  159. }
  160. func BenchmarkElementMul(b *testing.B) {
  161. x := Element{
  162. 1997599621687373223,
  163. 6052339484930628067,
  164. 10108755138030829701,
  165. 150537098327114917,
  166. }
  167. benchResElement.SetOne()
  168. b.ResetTimer()
  169. for i := 0; i < b.N; i++ {
  170. benchResElement.Mul(&benchResElement, &x)
  171. }
  172. }
  173. func BenchmarkElementCmp(b *testing.B) {
  174. x := Element{
  175. 1997599621687373223,
  176. 6052339484930628067,
  177. 10108755138030829701,
  178. 150537098327114917,
  179. }
  180. benchResElement = x
  181. benchResElement[0] = 0
  182. b.ResetTimer()
  183. for i := 0; i < b.N; i++ {
  184. benchResElement.Cmp(&x)
  185. }
  186. }
  187. func TestElementCmp(t *testing.T) {
  188. var x, y Element
  189. if x.Cmp(&y) != 0 {
  190. t.Fatal("x == y")
  191. }
  192. one := One()
  193. y.Sub(&y, &one)
  194. if x.Cmp(&y) != -1 {
  195. t.Fatal("x < y")
  196. }
  197. if y.Cmp(&x) != 1 {
  198. t.Fatal("x < y")
  199. }
  200. x = y
  201. if x.Cmp(&y) != 0 {
  202. t.Fatal("x == y")
  203. }
  204. x.Sub(&x, &one)
  205. if x.Cmp(&y) != -1 {
  206. t.Fatal("x < y")
  207. }
  208. if y.Cmp(&x) != 1 {
  209. t.Fatal("x < y")
  210. }
  211. }
  212. func TestElementIsRandom(t *testing.T) {
  213. for i := 0; i < 50; i++ {
  214. var x, y Element
  215. x.SetRandom()
  216. y.SetRandom()
  217. if x.Equal(&y) {
  218. t.Fatal("2 random numbers are unlikely to be equal")
  219. }
  220. }
  221. }
  222. // -------------------------------------------------------------------------------------------------
  223. // Gopter tests
  224. // most of them are generated with a template
  225. const (
  226. nbFuzzShort = 200
  227. nbFuzz = 1000
  228. )
  229. // special values to be used in tests
  230. var staticTestValues []Element
  231. func init() {
  232. staticTestValues = append(staticTestValues, Element{}) // zero
  233. staticTestValues = append(staticTestValues, One()) // one
  234. staticTestValues = append(staticTestValues, rSquare) // r^2
  235. var e, one Element
  236. one.SetOne()
  237. e.Sub(&qElement, &one)
  238. staticTestValues = append(staticTestValues, e) // q - 1
  239. e.Double(&one)
  240. staticTestValues = append(staticTestValues, e) // 2
  241. {
  242. a := qElement
  243. a[3]--
  244. staticTestValues = append(staticTestValues, a)
  245. }
  246. {
  247. a := qElement
  248. a[0]--
  249. staticTestValues = append(staticTestValues, a)
  250. }
  251. for i := 0; i <= 3; i++ {
  252. staticTestValues = append(staticTestValues, Element{uint64(i)})
  253. staticTestValues = append(staticTestValues, Element{0, uint64(i)})
  254. }
  255. {
  256. a := qElement
  257. a[3]--
  258. a[0]++
  259. staticTestValues = append(staticTestValues, a)
  260. }
  261. }
  262. func TestElementNegZero(t *testing.T) {
  263. var a, b Element
  264. b.SetZero()
  265. for a.IsZero() {
  266. a.SetRandom()
  267. }
  268. a.Neg(&b)
  269. if !a.IsZero() {
  270. t.Fatal("neg(0) != 0")
  271. }
  272. }
  273. func TestElementReduce(t *testing.T) {
  274. testValues := make([]Element, len(staticTestValues))
  275. copy(testValues, staticTestValues)
  276. for _, s := range testValues {
  277. expected := s
  278. reduce(&s)
  279. _reduceGeneric(&expected)
  280. if !s.Equal(&expected) {
  281. t.Fatal("reduce failed: asm and generic impl don't match")
  282. }
  283. }
  284. parameters := gopter.DefaultTestParameters()
  285. if testing.Short() {
  286. parameters.MinSuccessfulTests = nbFuzzShort
  287. } else {
  288. parameters.MinSuccessfulTests = nbFuzz
  289. }
  290. properties := gopter.NewProperties(parameters)
  291. genA := genFull()
  292. properties.Property("reduce should output a result smaller than modulus", prop.ForAll(
  293. func(a Element) bool {
  294. b := a
  295. reduce(&a)
  296. _reduceGeneric(&b)
  297. return !a.biggerOrEqualModulus() && a.Equal(&b)
  298. },
  299. genA,
  300. ))
  301. properties.TestingRun(t, gopter.ConsoleReporter(false))
  302. // if we have ADX instruction enabled, test both path in assembly
  303. if supportAdx {
  304. t.Log("disabling ADX")
  305. supportAdx = false
  306. properties.TestingRun(t, gopter.ConsoleReporter(false))
  307. supportAdx = true
  308. }
  309. }
  310. func TestElementBytes(t *testing.T) {
  311. parameters := gopter.DefaultTestParameters()
  312. if testing.Short() {
  313. parameters.MinSuccessfulTests = nbFuzzShort
  314. } else {
  315. parameters.MinSuccessfulTests = nbFuzz
  316. }
  317. properties := gopter.NewProperties(parameters)
  318. genA := gen()
  319. properties.Property("SetBytes(Bytes()) should stayt constant", prop.ForAll(
  320. func(a testPairElement) bool {
  321. var b Element
  322. bytes := a.element.Bytes()
  323. b.SetBytes(bytes[:])
  324. return a.element.Equal(&b)
  325. },
  326. genA,
  327. ))
  328. properties.TestingRun(t, gopter.ConsoleReporter(false))
  329. }
  330. func TestElementInverseExp(t *testing.T) {
  331. // inverse must be equal to exp^-2
  332. exp := Modulus()
  333. exp.Sub(exp, new(big.Int).SetUint64(2))
  334. parameters := gopter.DefaultTestParameters()
  335. if testing.Short() {
  336. parameters.MinSuccessfulTests = nbFuzzShort
  337. } else {
  338. parameters.MinSuccessfulTests = nbFuzz
  339. }
  340. properties := gopter.NewProperties(parameters)
  341. genA := gen()
  342. properties.Property("inv == exp^-2", prop.ForAll(
  343. func(a testPairElement) bool {
  344. var b Element
  345. b.Set(&a.element)
  346. a.element.Inverse(&a.element)
  347. b.Exp(b, exp)
  348. return a.element.Equal(&b)
  349. },
  350. genA,
  351. ))
  352. properties.TestingRun(t, gopter.ConsoleReporter(false))
  353. // if we have ADX instruction enabled, test both path in assembly
  354. if supportAdx {
  355. t.Log("disabling ADX")
  356. supportAdx = false
  357. properties.TestingRun(t, gopter.ConsoleReporter(false))
  358. supportAdx = true
  359. }
  360. }
  361. func TestElementMulByConstants(t *testing.T) {
  362. parameters := gopter.DefaultTestParameters()
  363. if testing.Short() {
  364. parameters.MinSuccessfulTests = nbFuzzShort
  365. } else {
  366. parameters.MinSuccessfulTests = nbFuzz
  367. }
  368. properties := gopter.NewProperties(parameters)
  369. genA := gen()
  370. implemented := []uint8{0, 1, 2, 3, 5, 13}
  371. properties.Property("mulByConstant", prop.ForAll(
  372. func(a testPairElement) bool {
  373. for _, c := range implemented {
  374. var constant Element
  375. constant.SetUint64(uint64(c))
  376. b := a.element
  377. b.Mul(&b, &constant)
  378. aa := a.element
  379. mulByConstant(&aa, c)
  380. if !aa.Equal(&b) {
  381. return false
  382. }
  383. }
  384. return true
  385. },
  386. genA,
  387. ))
  388. properties.Property("MulBy3(x) == Mul(x, 3)", prop.ForAll(
  389. func(a testPairElement) bool {
  390. var constant Element
  391. constant.SetUint64(3)
  392. b := a.element
  393. b.Mul(&b, &constant)
  394. MulBy3(&a.element)
  395. return a.element.Equal(&b)
  396. },
  397. genA,
  398. ))
  399. properties.Property("MulBy5(x) == Mul(x, 5)", prop.ForAll(
  400. func(a testPairElement) bool {
  401. var constant Element
  402. constant.SetUint64(5)
  403. b := a.element
  404. b.Mul(&b, &constant)
  405. MulBy5(&a.element)
  406. return a.element.Equal(&b)
  407. },
  408. genA,
  409. ))
  410. properties.Property("MulBy13(x) == Mul(x, 13)", prop.ForAll(
  411. func(a testPairElement) bool {
  412. var constant Element
  413. constant.SetUint64(13)
  414. b := a.element
  415. b.Mul(&b, &constant)
  416. MulBy13(&a.element)
  417. return a.element.Equal(&b)
  418. },
  419. genA,
  420. ))
  421. properties.TestingRun(t, gopter.ConsoleReporter(false))
  422. // if we have ADX instruction enabled, test both path in assembly
  423. if supportAdx {
  424. t.Log("disabling ADX")
  425. supportAdx = false
  426. properties.TestingRun(t, gopter.ConsoleReporter(false))
  427. supportAdx = true
  428. }
  429. }
  430. func TestElementLegendre(t *testing.T) {
  431. parameters := gopter.DefaultTestParameters()
  432. if testing.Short() {
  433. parameters.MinSuccessfulTests = nbFuzzShort
  434. } else {
  435. parameters.MinSuccessfulTests = nbFuzz
  436. }
  437. properties := gopter.NewProperties(parameters)
  438. genA := gen()
  439. properties.Property("legendre should output same result than big.Int.Jacobi", prop.ForAll(
  440. func(a testPairElement) bool {
  441. return a.element.Legendre() == big.Jacobi(&a.bigint, Modulus())
  442. },
  443. genA,
  444. ))
  445. properties.TestingRun(t, gopter.ConsoleReporter(false))
  446. // if we have ADX instruction enabled, test both path in assembly
  447. if supportAdx {
  448. t.Log("disabling ADX")
  449. supportAdx = false
  450. properties.TestingRun(t, gopter.ConsoleReporter(false))
  451. supportAdx = true
  452. }
  453. }
  454. func TestElementButterflies(t *testing.T) {
  455. parameters := gopter.DefaultTestParameters()
  456. if testing.Short() {
  457. parameters.MinSuccessfulTests = nbFuzzShort
  458. } else {
  459. parameters.MinSuccessfulTests = nbFuzz
  460. }
  461. properties := gopter.NewProperties(parameters)
  462. genA := gen()
  463. properties.Property("butterfly0 == a -b; a +b", prop.ForAll(
  464. func(a, b testPairElement) bool {
  465. a0, b0 := a.element, b.element
  466. _butterflyGeneric(&a.element, &b.element)
  467. Butterfly(&a0, &b0)
  468. return a.element.Equal(&a0) && b.element.Equal(&b0)
  469. },
  470. genA,
  471. genA,
  472. ))
  473. properties.TestingRun(t, gopter.ConsoleReporter(false))
  474. // if we have ADX instruction enabled, test both path in assembly
  475. if supportAdx {
  476. t.Log("disabling ADX")
  477. supportAdx = false
  478. properties.TestingRun(t, gopter.ConsoleReporter(false))
  479. supportAdx = true
  480. }
  481. }
  482. func TestElementLexicographicallyLargest(t *testing.T) {
  483. parameters := gopter.DefaultTestParameters()
  484. if testing.Short() {
  485. parameters.MinSuccessfulTests = nbFuzzShort
  486. } else {
  487. parameters.MinSuccessfulTests = nbFuzz
  488. }
  489. properties := gopter.NewProperties(parameters)
  490. genA := gen()
  491. properties.Property("element.Cmp should match LexicographicallyLargest output", prop.ForAll(
  492. func(a testPairElement) bool {
  493. var negA Element
  494. negA.Neg(&a.element)
  495. cmpResult := a.element.Cmp(&negA)
  496. lResult := a.element.LexicographicallyLargest()
  497. if lResult && cmpResult == 1 {
  498. return true
  499. }
  500. if !lResult && cmpResult != 1 {
  501. return true
  502. }
  503. return false
  504. },
  505. genA,
  506. ))
  507. properties.TestingRun(t, gopter.ConsoleReporter(false))
  508. // if we have ADX instruction enabled, test both path in assembly
  509. if supportAdx {
  510. t.Log("disabling ADX")
  511. supportAdx = false
  512. properties.TestingRun(t, gopter.ConsoleReporter(false))
  513. supportAdx = true
  514. }
  515. }
  516. func TestElementAdd(t *testing.T) {
  517. parameters := gopter.DefaultTestParameters()
  518. if testing.Short() {
  519. parameters.MinSuccessfulTests = nbFuzzShort
  520. } else {
  521. parameters.MinSuccessfulTests = nbFuzz
  522. }
  523. properties := gopter.NewProperties(parameters)
  524. genA := gen()
  525. genB := gen()
  526. properties.Property("Add: having the receiver as operand should output the same result", prop.ForAll(
  527. func(a, b testPairElement) bool {
  528. var c, d Element
  529. d.Set(&a.element)
  530. c.Add(&a.element, &b.element)
  531. a.element.Add(&a.element, &b.element)
  532. b.element.Add(&d, &b.element)
  533. return a.element.Equal(&b.element) && a.element.Equal(&c) && b.element.Equal(&c)
  534. },
  535. genA,
  536. genB,
  537. ))
  538. properties.Property("Add: operation result must match big.Int result", prop.ForAll(
  539. func(a, b testPairElement) bool {
  540. {
  541. var c Element
  542. c.Add(&a.element, &b.element)
  543. var d, e big.Int
  544. d.Add(&a.bigint, &b.bigint).Mod(&d, Modulus())
  545. if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
  546. return false
  547. }
  548. }
  549. // fixed elements
  550. // a is random
  551. // r takes special values
  552. testValues := make([]Element, len(staticTestValues))
  553. copy(testValues, staticTestValues)
  554. for _, r := range testValues {
  555. var d, e, rb big.Int
  556. r.ToBigIntRegular(&rb)
  557. var c Element
  558. c.Add(&a.element, &r)
  559. d.Add(&a.bigint, &rb).Mod(&d, Modulus())
  560. // checking generic impl against asm path
  561. var cGeneric Element
  562. _addGeneric(&cGeneric, &a.element, &r)
  563. if !cGeneric.Equal(&c) {
  564. // need to give context to failing error.
  565. return false
  566. }
  567. if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
  568. return false
  569. }
  570. }
  571. return true
  572. },
  573. genA,
  574. genB,
  575. ))
  576. properties.Property("Add: operation result must be smaller than modulus", prop.ForAll(
  577. func(a, b testPairElement) bool {
  578. var c Element
  579. c.Add(&a.element, &b.element)
  580. return !c.biggerOrEqualModulus()
  581. },
  582. genA,
  583. genB,
  584. ))
  585. properties.Property("Add: assembly implementation must be consistent with generic one", prop.ForAll(
  586. func(a, b testPairElement) bool {
  587. var c, d Element
  588. c.Add(&a.element, &b.element)
  589. _addGeneric(&d, &a.element, &b.element)
  590. return c.Equal(&d)
  591. },
  592. genA,
  593. genB,
  594. ))
  595. specialValueTest := func() {
  596. // test special values against special values
  597. testValues := make([]Element, len(staticTestValues))
  598. copy(testValues, staticTestValues)
  599. for _, a := range testValues {
  600. var aBig big.Int
  601. a.ToBigIntRegular(&aBig)
  602. for _, b := range testValues {
  603. var bBig, d, e big.Int
  604. b.ToBigIntRegular(&bBig)
  605. var c Element
  606. c.Add(&a, &b)
  607. d.Add(&aBig, &bBig).Mod(&d, Modulus())
  608. // checking asm against generic impl
  609. var cGeneric Element
  610. _addGeneric(&cGeneric, &a, &b)
  611. if !cGeneric.Equal(&c) {
  612. t.Fatal("Add failed special test values: asm and generic impl don't match")
  613. }
  614. if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
  615. t.Fatal("Add failed special test values")
  616. }
  617. }
  618. }
  619. }
  620. properties.TestingRun(t, gopter.ConsoleReporter(false))
  621. specialValueTest()
  622. // if we have ADX instruction enabled, test both path in assembly
  623. if supportAdx {
  624. t.Log("disabling ADX")
  625. supportAdx = false
  626. properties.TestingRun(t, gopter.ConsoleReporter(false))
  627. specialValueTest()
  628. supportAdx = true
  629. }
  630. }
  631. func TestElementSub(t *testing.T) {
  632. parameters := gopter.DefaultTestParameters()
  633. if testing.Short() {
  634. parameters.MinSuccessfulTests = nbFuzzShort
  635. } else {
  636. parameters.MinSuccessfulTests = nbFuzz
  637. }
  638. properties := gopter.NewProperties(parameters)
  639. genA := gen()
  640. genB := gen()
  641. properties.Property("Sub: having the receiver as operand should output the same result", prop.ForAll(
  642. func(a, b testPairElement) bool {
  643. var c, d Element
  644. d.Set(&a.element)
  645. c.Sub(&a.element, &b.element)
  646. a.element.Sub(&a.element, &b.element)
  647. b.element.Sub(&d, &b.element)
  648. return a.element.Equal(&b.element) && a.element.Equal(&c) && b.element.Equal(&c)
  649. },
  650. genA,
  651. genB,
  652. ))
  653. properties.Property("Sub: operation result must match big.Int result", prop.ForAll(
  654. func(a, b testPairElement) bool {
  655. {
  656. var c Element
  657. c.Sub(&a.element, &b.element)
  658. var d, e big.Int
  659. d.Sub(&a.bigint, &b.bigint).Mod(&d, Modulus())
  660. if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
  661. return false
  662. }
  663. }
  664. // fixed elements
  665. // a is random
  666. // r takes special values
  667. testValues := make([]Element, len(staticTestValues))
  668. copy(testValues, staticTestValues)
  669. for _, r := range testValues {
  670. var d, e, rb big.Int
  671. r.ToBigIntRegular(&rb)
  672. var c Element
  673. c.Sub(&a.element, &r)
  674. d.Sub(&a.bigint, &rb).Mod(&d, Modulus())
  675. // checking generic impl against asm path
  676. var cGeneric Element
  677. _subGeneric(&cGeneric, &a.element, &r)
  678. if !cGeneric.Equal(&c) {
  679. // need to give context to failing error.
  680. return false
  681. }
  682. if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
  683. return false
  684. }
  685. }
  686. return true
  687. },
  688. genA,
  689. genB,
  690. ))
  691. properties.Property("Sub: operation result must be smaller than modulus", prop.ForAll(
  692. func(a, b testPairElement) bool {
  693. var c Element
  694. c.Sub(&a.element, &b.element)
  695. return !c.biggerOrEqualModulus()
  696. },
  697. genA,
  698. genB,
  699. ))
  700. properties.Property("Sub: assembly implementation must be consistent with generic one", prop.ForAll(
  701. func(a, b testPairElement) bool {
  702. var c, d Element
  703. c.Sub(&a.element, &b.element)
  704. _subGeneric(&d, &a.element, &b.element)
  705. return c.Equal(&d)
  706. },
  707. genA,
  708. genB,
  709. ))
  710. specialValueTest := func() {
  711. // test special values against special values
  712. testValues := make([]Element, len(staticTestValues))
  713. copy(testValues, staticTestValues)
  714. for _, a := range testValues {
  715. var aBig big.Int
  716. a.ToBigIntRegular(&aBig)
  717. for _, b := range testValues {
  718. var bBig, d, e big.Int
  719. b.ToBigIntRegular(&bBig)
  720. var c Element
  721. c.Sub(&a, &b)
  722. d.Sub(&aBig, &bBig).Mod(&d, Modulus())
  723. // checking asm against generic impl
  724. var cGeneric Element
  725. _subGeneric(&cGeneric, &a, &b)
  726. if !cGeneric.Equal(&c) {
  727. t.Fatal("Sub failed special test values: asm and generic impl don't match")
  728. }
  729. if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
  730. t.Fatal("Sub failed special test values")
  731. }
  732. }
  733. }
  734. }
  735. properties.TestingRun(t, gopter.ConsoleReporter(false))
  736. specialValueTest()
  737. // if we have ADX instruction enabled, test both path in assembly
  738. if supportAdx {
  739. t.Log("disabling ADX")
  740. supportAdx = false
  741. properties.TestingRun(t, gopter.ConsoleReporter(false))
  742. specialValueTest()
  743. supportAdx = true
  744. }
  745. }
  746. func TestElementMul(t *testing.T) {
  747. parameters := gopter.DefaultTestParameters()
  748. if testing.Short() {
  749. parameters.MinSuccessfulTests = nbFuzzShort
  750. } else {
  751. parameters.MinSuccessfulTests = nbFuzz
  752. }
  753. properties := gopter.NewProperties(parameters)
  754. genA := gen()
  755. genB := gen()
  756. properties.Property("Mul: having the receiver as operand should output the same result", prop.ForAll(
  757. func(a, b testPairElement) bool {
  758. var c, d Element
  759. d.Set(&a.element)
  760. c.Mul(&a.element, &b.element)
  761. a.element.Mul(&a.element, &b.element)
  762. b.element.Mul(&d, &b.element)
  763. return a.element.Equal(&b.element) && a.element.Equal(&c) && b.element.Equal(&c)
  764. },
  765. genA,
  766. genB,
  767. ))
  768. properties.Property("Mul: operation result must match big.Int result", prop.ForAll(
  769. func(a, b testPairElement) bool {
  770. {
  771. var c Element
  772. c.Mul(&a.element, &b.element)
  773. var d, e big.Int
  774. d.Mul(&a.bigint, &b.bigint).Mod(&d, Modulus())
  775. if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
  776. return false
  777. }
  778. }
  779. // fixed elements
  780. // a is random
  781. // r takes special values
  782. testValues := make([]Element, len(staticTestValues))
  783. copy(testValues, staticTestValues)
  784. for _, r := range testValues {
  785. var d, e, rb big.Int
  786. r.ToBigIntRegular(&rb)
  787. var c Element
  788. c.Mul(&a.element, &r)
  789. d.Mul(&a.bigint, &rb).Mod(&d, Modulus())
  790. // checking generic impl against asm path
  791. var cGeneric Element
  792. _mulGeneric(&cGeneric, &a.element, &r)
  793. if !cGeneric.Equal(&c) {
  794. // need to give context to failing error.
  795. return false
  796. }
  797. if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
  798. return false
  799. }
  800. }
  801. return true
  802. },
  803. genA,
  804. genB,
  805. ))
  806. properties.Property("Mul: operation result must be smaller than modulus", prop.ForAll(
  807. func(a, b testPairElement) bool {
  808. var c Element
  809. c.Mul(&a.element, &b.element)
  810. return !c.biggerOrEqualModulus()
  811. },
  812. genA,
  813. genB,
  814. ))
  815. properties.Property("Mul: assembly implementation must be consistent with generic one", prop.ForAll(
  816. func(a, b testPairElement) bool {
  817. var c, d Element
  818. c.Mul(&a.element, &b.element)
  819. _mulGeneric(&d, &a.element, &b.element)
  820. return c.Equal(&d)
  821. },
  822. genA,
  823. genB,
  824. ))
  825. specialValueTest := func() {
  826. // test special values against special values
  827. testValues := make([]Element, len(staticTestValues))
  828. copy(testValues, staticTestValues)
  829. for _, a := range testValues {
  830. var aBig big.Int
  831. a.ToBigIntRegular(&aBig)
  832. for _, b := range testValues {
  833. var bBig, d, e big.Int
  834. b.ToBigIntRegular(&bBig)
  835. var c Element
  836. c.Mul(&a, &b)
  837. d.Mul(&aBig, &bBig).Mod(&d, Modulus())
  838. // checking asm against generic impl
  839. var cGeneric Element
  840. _mulGeneric(&cGeneric, &a, &b)
  841. if !cGeneric.Equal(&c) {
  842. t.Fatal("Mul failed special test values: asm and generic impl don't match")
  843. }
  844. if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
  845. t.Fatal("Mul failed special test values")
  846. }
  847. }
  848. }
  849. }
  850. properties.TestingRun(t, gopter.ConsoleReporter(false))
  851. specialValueTest()
  852. // if we have ADX instruction enabled, test both path in assembly
  853. if supportAdx {
  854. t.Log("disabling ADX")
  855. supportAdx = false
  856. properties.TestingRun(t, gopter.ConsoleReporter(false))
  857. specialValueTest()
  858. supportAdx = true
  859. }
  860. }
  861. func TestElementDiv(t *testing.T) {
  862. parameters := gopter.DefaultTestParameters()
  863. if testing.Short() {
  864. parameters.MinSuccessfulTests = nbFuzzShort
  865. } else {
  866. parameters.MinSuccessfulTests = nbFuzz
  867. }
  868. properties := gopter.NewProperties(parameters)
  869. genA := gen()
  870. genB := gen()
  871. properties.Property("Div: having the receiver as operand should output the same result", prop.ForAll(
  872. func(a, b testPairElement) bool {
  873. var c, d Element
  874. d.Set(&a.element)
  875. c.Div(&a.element, &b.element)
  876. a.element.Div(&a.element, &b.element)
  877. b.element.Div(&d, &b.element)
  878. return a.element.Equal(&b.element) && a.element.Equal(&c) && b.element.Equal(&c)
  879. },
  880. genA,
  881. genB,
  882. ))
  883. properties.Property("Div: operation result must match big.Int result", prop.ForAll(
  884. func(a, b testPairElement) bool {
  885. {
  886. var c Element
  887. c.Div(&a.element, &b.element)
  888. var d, e big.Int
  889. d.ModInverse(&b.bigint, Modulus())
  890. d.Mul(&d, &a.bigint).Mod(&d, Modulus())
  891. if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
  892. return false
  893. }
  894. }
  895. // fixed elements
  896. // a is random
  897. // r takes special values
  898. testValues := make([]Element, len(staticTestValues))
  899. copy(testValues, staticTestValues)
  900. for _, r := range testValues {
  901. var d, e, rb big.Int
  902. r.ToBigIntRegular(&rb)
  903. var c Element
  904. c.Div(&a.element, &r)
  905. d.ModInverse(&rb, Modulus())
  906. d.Mul(&d, &a.bigint).Mod(&d, Modulus())
  907. if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
  908. return false
  909. }
  910. }
  911. return true
  912. },
  913. genA,
  914. genB,
  915. ))
  916. properties.Property("Div: operation result must be smaller than modulus", prop.ForAll(
  917. func(a, b testPairElement) bool {
  918. var c Element
  919. c.Div(&a.element, &b.element)
  920. return !c.biggerOrEqualModulus()
  921. },
  922. genA,
  923. genB,
  924. ))
  925. specialValueTest := func() {
  926. // test special values against special values
  927. testValues := make([]Element, len(staticTestValues))
  928. copy(testValues, staticTestValues)
  929. for _, a := range testValues {
  930. var aBig big.Int
  931. a.ToBigIntRegular(&aBig)
  932. for _, b := range testValues {
  933. var bBig, d, e big.Int
  934. b.ToBigIntRegular(&bBig)
  935. var c Element
  936. c.Div(&a, &b)
  937. d.ModInverse(&bBig, Modulus())
  938. d.Mul(&d, &aBig).Mod(&d, Modulus())
  939. if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
  940. t.Fatal("Div failed special test values")
  941. }
  942. }
  943. }
  944. }
  945. properties.TestingRun(t, gopter.ConsoleReporter(false))
  946. specialValueTest()
  947. // if we have ADX instruction enabled, test both path in assembly
  948. if supportAdx {
  949. t.Log("disabling ADX")
  950. supportAdx = false
  951. properties.TestingRun(t, gopter.ConsoleReporter(false))
  952. specialValueTest()
  953. supportAdx = true
  954. }
  955. }
  956. func TestElementExp(t *testing.T) {
  957. parameters := gopter.DefaultTestParameters()
  958. if testing.Short() {
  959. parameters.MinSuccessfulTests = nbFuzzShort
  960. } else {
  961. parameters.MinSuccessfulTests = nbFuzz
  962. }
  963. properties := gopter.NewProperties(parameters)
  964. genA := gen()
  965. genB := gen()
  966. properties.Property("Exp: having the receiver as operand should output the same result", prop.ForAll(
  967. func(a, b testPairElement) bool {
  968. var c, d Element
  969. d.Set(&a.element)
  970. c.Exp(a.element, &b.bigint)
  971. a.element.Exp(a.element, &b.bigint)
  972. b.element.Exp(d, &b.bigint)
  973. return a.element.Equal(&b.element) && a.element.Equal(&c) && b.element.Equal(&c)
  974. },
  975. genA,
  976. genB,
  977. ))
  978. properties.Property("Exp: operation result must match big.Int result", prop.ForAll(
  979. func(a, b testPairElement) bool {
  980. {
  981. var c Element
  982. c.Exp(a.element, &b.bigint)
  983. var d, e big.Int
  984. d.Exp(&a.bigint, &b.bigint, Modulus())
  985. if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
  986. return false
  987. }
  988. }
  989. // fixed elements
  990. // a is random
  991. // r takes special values
  992. testValues := make([]Element, len(staticTestValues))
  993. copy(testValues, staticTestValues)
  994. for _, r := range testValues {
  995. var d, e, rb big.Int
  996. r.ToBigIntRegular(&rb)
  997. var c Element
  998. c.Exp(a.element, &rb)
  999. d.Exp(&a.bigint, &rb, Modulus())
  1000. if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
  1001. return false
  1002. }
  1003. }
  1004. return true
  1005. },
  1006. genA,
  1007. genB,
  1008. ))
  1009. properties.Property("Exp: operation result must be smaller than modulus", prop.ForAll(
  1010. func(a, b testPairElement) bool {
  1011. var c Element
  1012. c.Exp(a.element, &b.bigint)
  1013. return !c.biggerOrEqualModulus()
  1014. },
  1015. genA,
  1016. genB,
  1017. ))
  1018. specialValueTest := func() {
  1019. // test special values against special values
  1020. testValues := make([]Element, len(staticTestValues))
  1021. copy(testValues, staticTestValues)
  1022. for _, a := range testValues {
  1023. var aBig big.Int
  1024. a.ToBigIntRegular(&aBig)
  1025. for _, b := range testValues {
  1026. var bBig, d, e big.Int
  1027. b.ToBigIntRegular(&bBig)
  1028. var c Element
  1029. c.Exp(a, &bBig)
  1030. d.Exp(&aBig, &bBig, Modulus())
  1031. if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
  1032. t.Fatal("Exp failed special test values")
  1033. }
  1034. }
  1035. }
  1036. }
  1037. properties.TestingRun(t, gopter.ConsoleReporter(false))
  1038. specialValueTest()
  1039. // if we have ADX instruction enabled, test both path in assembly
  1040. if supportAdx {
  1041. t.Log("disabling ADX")
  1042. supportAdx = false
  1043. properties.TestingRun(t, gopter.ConsoleReporter(false))
  1044. specialValueTest()
  1045. supportAdx = true
  1046. }
  1047. }
  1048. func TestElementSquare(t *testing.T) {
  1049. parameters := gopter.DefaultTestParameters()
  1050. if testing.Short() {
  1051. parameters.MinSuccessfulTests = nbFuzzShort
  1052. } else {
  1053. parameters.MinSuccessfulTests = nbFuzz
  1054. }
  1055. properties := gopter.NewProperties(parameters)
  1056. genA := gen()
  1057. properties.Property("Square: having the receiver as operand should output the same result", prop.ForAll(
  1058. func(a testPairElement) bool {
  1059. var b Element
  1060. b.Square(&a.element)
  1061. a.element.Square(&a.element)
  1062. return a.element.Equal(&b)
  1063. },
  1064. genA,
  1065. ))
  1066. properties.Property("Square: operation result must match big.Int result", prop.ForAll(
  1067. func(a testPairElement) bool {
  1068. var c Element
  1069. c.Square(&a.element)
  1070. var d, e big.Int
  1071. d.Mul(&a.bigint, &a.bigint).Mod(&d, Modulus())
  1072. return c.FromMont().ToBigInt(&e).Cmp(&d) == 0
  1073. },
  1074. genA,
  1075. ))
  1076. properties.Property("Square: operation result must be smaller than modulus", prop.ForAll(
  1077. func(a testPairElement) bool {
  1078. var c Element
  1079. c.Square(&a.element)
  1080. return !c.biggerOrEqualModulus()
  1081. },
  1082. genA,
  1083. ))
  1084. specialValueTest := func() {
  1085. // test special values
  1086. testValues := make([]Element, len(staticTestValues))
  1087. copy(testValues, staticTestValues)
  1088. for _, a := range testValues {
  1089. var aBig big.Int
  1090. a.ToBigIntRegular(&aBig)
  1091. var c Element
  1092. c.Square(&a)
  1093. var d, e big.Int
  1094. d.Mul(&aBig, &aBig).Mod(&d, Modulus())
  1095. if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
  1096. t.Fatal("Square failed special test values")
  1097. }
  1098. }
  1099. }
  1100. properties.TestingRun(t, gopter.ConsoleReporter(false))
  1101. specialValueTest()
  1102. // if we have ADX instruction enabled, test both path in assembly
  1103. if supportAdx {
  1104. supportAdx = false
  1105. t.Log("disabling ADX")
  1106. properties.TestingRun(t, gopter.ConsoleReporter(false))
  1107. specialValueTest()
  1108. supportAdx = true
  1109. }
  1110. }
  1111. func TestElementInverse(t *testing.T) {
  1112. parameters := gopter.DefaultTestParameters()
  1113. if testing.Short() {
  1114. parameters.MinSuccessfulTests = nbFuzzShort
  1115. } else {
  1116. parameters.MinSuccessfulTests = nbFuzz
  1117. }
  1118. properties := gopter.NewProperties(parameters)
  1119. genA := gen()
  1120. properties.Property("Inverse: having the receiver as operand should output the same result", prop.ForAll(
  1121. func(a testPairElement) bool {
  1122. var b Element
  1123. b.Inverse(&a.element)
  1124. a.element.Inverse(&a.element)
  1125. return a.element.Equal(&b)
  1126. },
  1127. genA,
  1128. ))
  1129. properties.Property("Inverse: operation result must match big.Int result", prop.ForAll(
  1130. func(a testPairElement) bool {
  1131. var c Element
  1132. c.Inverse(&a.element)
  1133. var d, e big.Int
  1134. d.ModInverse(&a.bigint, Modulus())
  1135. return c.FromMont().ToBigInt(&e).Cmp(&d) == 0
  1136. },
  1137. genA,
  1138. ))
  1139. properties.Property("Inverse: operation result must be smaller than modulus", prop.ForAll(
  1140. func(a testPairElement) bool {
  1141. var c Element
  1142. c.Inverse(&a.element)
  1143. return !c.biggerOrEqualModulus()
  1144. },
  1145. genA,
  1146. ))
  1147. specialValueTest := func() {
  1148. // test special values
  1149. testValues := make([]Element, len(staticTestValues))
  1150. copy(testValues, staticTestValues)
  1151. for _, a := range testValues {
  1152. var aBig big.Int
  1153. a.ToBigIntRegular(&aBig)
  1154. var c Element
  1155. c.Inverse(&a)
  1156. var d, e big.Int
  1157. d.ModInverse(&aBig, Modulus())
  1158. if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
  1159. t.Fatal("Inverse failed special test values")
  1160. }
  1161. }
  1162. }
  1163. properties.TestingRun(t, gopter.ConsoleReporter(false))
  1164. specialValueTest()
  1165. // if we have ADX instruction enabled, test both path in assembly
  1166. if supportAdx {
  1167. supportAdx = false
  1168. t.Log("disabling ADX")
  1169. properties.TestingRun(t, gopter.ConsoleReporter(false))
  1170. specialValueTest()
  1171. supportAdx = true
  1172. }
  1173. }
  1174. func TestElementSqrt(t *testing.T) {
  1175. parameters := gopter.DefaultTestParameters()
  1176. if testing.Short() {
  1177. parameters.MinSuccessfulTests = nbFuzzShort
  1178. } else {
  1179. parameters.MinSuccessfulTests = nbFuzz
  1180. }
  1181. properties := gopter.NewProperties(parameters)
  1182. genA := gen()
  1183. properties.Property("Sqrt: having the receiver as operand should output the same result", prop.ForAll(
  1184. func(a testPairElement) bool {
  1185. b := a.element
  1186. b.Sqrt(&a.element)
  1187. a.element.Sqrt(&a.element)
  1188. return a.element.Equal(&b)
  1189. },
  1190. genA,
  1191. ))
  1192. properties.Property("Sqrt: operation result must match big.Int result", prop.ForAll(
  1193. func(a testPairElement) bool {
  1194. var c Element
  1195. c.Sqrt(&a.element)
  1196. var d, e big.Int
  1197. d.ModSqrt(&a.bigint, Modulus())
  1198. return c.FromMont().ToBigInt(&e).Cmp(&d) == 0
  1199. },
  1200. genA,
  1201. ))
  1202. properties.Property("Sqrt: operation result must be smaller than modulus", prop.ForAll(
  1203. func(a testPairElement) bool {
  1204. var c Element
  1205. c.Sqrt(&a.element)
  1206. return !c.biggerOrEqualModulus()
  1207. },
  1208. genA,
  1209. ))
  1210. specialValueTest := func() {
  1211. // test special values
  1212. testValues := make([]Element, len(staticTestValues))
  1213. copy(testValues, staticTestValues)
  1214. for _, a := range testValues {
  1215. var aBig big.Int
  1216. a.ToBigIntRegular(&aBig)
  1217. var c Element
  1218. c.Sqrt(&a)
  1219. var d, e big.Int
  1220. d.ModSqrt(&aBig, Modulus())
  1221. if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
  1222. t.Fatal("Sqrt failed special test values")
  1223. }
  1224. }
  1225. }
  1226. properties.TestingRun(t, gopter.ConsoleReporter(false))
  1227. specialValueTest()
  1228. // if we have ADX instruction enabled, test both path in assembly
  1229. if supportAdx {
  1230. supportAdx = false
  1231. t.Log("disabling ADX")
  1232. properties.TestingRun(t, gopter.ConsoleReporter(false))
  1233. specialValueTest()
  1234. supportAdx = true
  1235. }
  1236. }
  1237. func TestElementDouble(t *testing.T) {
  1238. parameters := gopter.DefaultTestParameters()
  1239. if testing.Short() {
  1240. parameters.MinSuccessfulTests = nbFuzzShort
  1241. } else {
  1242. parameters.MinSuccessfulTests = nbFuzz
  1243. }
  1244. properties := gopter.NewProperties(parameters)
  1245. genA := gen()
  1246. properties.Property("Double: having the receiver as operand should output the same result", prop.ForAll(
  1247. func(a testPairElement) bool {
  1248. var b Element
  1249. b.Double(&a.element)
  1250. a.element.Double(&a.element)
  1251. return a.element.Equal(&b)
  1252. },
  1253. genA,
  1254. ))
  1255. properties.Property("Double: operation result must match big.Int result", prop.ForAll(
  1256. func(a testPairElement) bool {
  1257. var c Element
  1258. c.Double(&a.element)
  1259. var d, e big.Int
  1260. d.Lsh(&a.bigint, 1).Mod(&d, Modulus())
  1261. return c.FromMont().ToBigInt(&e).Cmp(&d) == 0
  1262. },
  1263. genA,
  1264. ))
  1265. properties.Property("Double: operation result must be smaller than modulus", prop.ForAll(
  1266. func(a testPairElement) bool {
  1267. var c Element
  1268. c.Double(&a.element)
  1269. return !c.biggerOrEqualModulus()
  1270. },
  1271. genA,
  1272. ))
  1273. properties.Property("Double: assembly implementation must be consistent with generic one", prop.ForAll(
  1274. func(a testPairElement) bool {
  1275. var c, d Element
  1276. c.Double(&a.element)
  1277. _doubleGeneric(&d, &a.element)
  1278. return c.Equal(&d)
  1279. },
  1280. genA,
  1281. ))
  1282. specialValueTest := func() {
  1283. // test special values
  1284. testValues := make([]Element, len(staticTestValues))
  1285. copy(testValues, staticTestValues)
  1286. for _, a := range testValues {
  1287. var aBig big.Int
  1288. a.ToBigIntRegular(&aBig)
  1289. var c Element
  1290. c.Double(&a)
  1291. var d, e big.Int
  1292. d.Lsh(&aBig, 1).Mod(&d, Modulus())
  1293. // checking asm against generic impl
  1294. var cGeneric Element
  1295. _doubleGeneric(&cGeneric, &a)
  1296. if !cGeneric.Equal(&c) {
  1297. t.Fatal("Double failed special test values: asm and generic impl don't match")
  1298. }
  1299. if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
  1300. t.Fatal("Double failed special test values")
  1301. }
  1302. }
  1303. }
  1304. properties.TestingRun(t, gopter.ConsoleReporter(false))
  1305. specialValueTest()
  1306. // if we have ADX instruction enabled, test both path in assembly
  1307. if supportAdx {
  1308. supportAdx = false
  1309. t.Log("disabling ADX")
  1310. properties.TestingRun(t, gopter.ConsoleReporter(false))
  1311. specialValueTest()
  1312. supportAdx = true
  1313. }
  1314. }
  1315. func TestElementNeg(t *testing.T) {
  1316. parameters := gopter.DefaultTestParameters()
  1317. if testing.Short() {
  1318. parameters.MinSuccessfulTests = nbFuzzShort
  1319. } else {
  1320. parameters.MinSuccessfulTests = nbFuzz
  1321. }
  1322. properties := gopter.NewProperties(parameters)
  1323. genA := gen()
  1324. properties.Property("Neg: having the receiver as operand should output the same result", prop.ForAll(
  1325. func(a testPairElement) bool {
  1326. var b Element
  1327. b.Neg(&a.element)
  1328. a.element.Neg(&a.element)
  1329. return a.element.Equal(&b)
  1330. },
  1331. genA,
  1332. ))
  1333. properties.Property("Neg: operation result must match big.Int result", prop.ForAll(
  1334. func(a testPairElement) bool {
  1335. var c Element
  1336. c.Neg(&a.element)
  1337. var d, e big.Int
  1338. d.Neg(&a.bigint).Mod(&d, Modulus())
  1339. return c.FromMont().ToBigInt(&e).Cmp(&d) == 0
  1340. },
  1341. genA,
  1342. ))
  1343. properties.Property("Neg: operation result must be smaller than modulus", prop.ForAll(
  1344. func(a testPairElement) bool {
  1345. var c Element
  1346. c.Neg(&a.element)
  1347. return !c.biggerOrEqualModulus()
  1348. },
  1349. genA,
  1350. ))
  1351. properties.Property("Neg: assembly implementation must be consistent with generic one", prop.ForAll(
  1352. func(a testPairElement) bool {
  1353. var c, d Element
  1354. c.Neg(&a.element)
  1355. _negGeneric(&d, &a.element)
  1356. return c.Equal(&d)
  1357. },
  1358. genA,
  1359. ))
  1360. specialValueTest := func() {
  1361. // test special values
  1362. testValues := make([]Element, len(staticTestValues))
  1363. copy(testValues, staticTestValues)
  1364. for _, a := range testValues {
  1365. var aBig big.Int
  1366. a.ToBigIntRegular(&aBig)
  1367. var c Element
  1368. c.Neg(&a)
  1369. var d, e big.Int
  1370. d.Neg(&aBig).Mod(&d, Modulus())
  1371. // checking asm against generic impl
  1372. var cGeneric Element
  1373. _negGeneric(&cGeneric, &a)
  1374. if !cGeneric.Equal(&c) {
  1375. t.Fatal("Neg failed special test values: asm and generic impl don't match")
  1376. }
  1377. if c.FromMont().ToBigInt(&e).Cmp(&d) != 0 {
  1378. t.Fatal("Neg failed special test values")
  1379. }
  1380. }
  1381. }
  1382. properties.TestingRun(t, gopter.ConsoleReporter(false))
  1383. specialValueTest()
  1384. // if we have ADX instruction enabled, test both path in assembly
  1385. if supportAdx {
  1386. supportAdx = false
  1387. t.Log("disabling ADX")
  1388. properties.TestingRun(t, gopter.ConsoleReporter(false))
  1389. specialValueTest()
  1390. supportAdx = true
  1391. }
  1392. }
  1393. func TestElementHalve(t *testing.T) {
  1394. parameters := gopter.DefaultTestParameters()
  1395. if testing.Short() {
  1396. parameters.MinSuccessfulTests = nbFuzzShort
  1397. } else {
  1398. parameters.MinSuccessfulTests = nbFuzz
  1399. }
  1400. properties := gopter.NewProperties(parameters)
  1401. genA := gen()
  1402. var twoInv Element
  1403. twoInv.SetUint64(2)
  1404. twoInv.Inverse(&twoInv)
  1405. properties.Property("z.Halve must match z / 2", prop.ForAll(
  1406. func(a testPairElement) bool {
  1407. c := a.element
  1408. d := a.element
  1409. c.Halve()
  1410. d.Mul(&d, &twoInv)
  1411. return c.Equal(&d)
  1412. },
  1413. genA,
  1414. ))
  1415. properties.TestingRun(t, gopter.ConsoleReporter(false))
  1416. }
  1417. func TestElementFromMont(t *testing.T) {
  1418. parameters := gopter.DefaultTestParameters()
  1419. if testing.Short() {
  1420. parameters.MinSuccessfulTests = nbFuzzShort
  1421. } else {
  1422. parameters.MinSuccessfulTests = nbFuzz
  1423. }
  1424. properties := gopter.NewProperties(parameters)
  1425. genA := gen()
  1426. properties.Property("Assembly implementation must be consistent with generic one", prop.ForAll(
  1427. func(a testPairElement) bool {
  1428. c := a.element
  1429. d := a.element
  1430. c.FromMont()
  1431. _fromMontGeneric(&d)
  1432. return c.Equal(&d)
  1433. },
  1434. genA,
  1435. ))
  1436. properties.Property("x.FromMont().ToMont() == x", prop.ForAll(
  1437. func(a testPairElement) bool {
  1438. c := a.element
  1439. c.FromMont().ToMont()
  1440. return c.Equal(&a.element)
  1441. },
  1442. genA,
  1443. ))
  1444. properties.TestingRun(t, gopter.ConsoleReporter(false))
  1445. }
  1446. type testPairElement struct {
  1447. element Element
  1448. bigint big.Int
  1449. }
  1450. func (z *Element) biggerOrEqualModulus() bool {
  1451. if z[3] > qElement[3] {
  1452. return true
  1453. }
  1454. if z[3] < qElement[3] {
  1455. return false
  1456. }
  1457. if z[2] > qElement[2] {
  1458. return true
  1459. }
  1460. if z[2] < qElement[2] {
  1461. return false
  1462. }
  1463. if z[1] > qElement[1] {
  1464. return true
  1465. }
  1466. if z[1] < qElement[1] {
  1467. return false
  1468. }
  1469. return z[0] >= qElement[0]
  1470. }
  1471. func gen() gopter.Gen {
  1472. return func(genParams *gopter.GenParameters) *gopter.GenResult {
  1473. var g testPairElement
  1474. g.element = Element{
  1475. genParams.NextUint64(),
  1476. genParams.NextUint64(),
  1477. genParams.NextUint64(),
  1478. genParams.NextUint64(),
  1479. }
  1480. if qElement[3] != ^uint64(0) {
  1481. g.element[3] %= (qElement[3] + 1)
  1482. }
  1483. for g.element.biggerOrEqualModulus() {
  1484. g.element = Element{
  1485. genParams.NextUint64(),
  1486. genParams.NextUint64(),
  1487. genParams.NextUint64(),
  1488. genParams.NextUint64(),
  1489. }
  1490. if qElement[3] != ^uint64(0) {
  1491. g.element[3] %= (qElement[3] + 1)
  1492. }
  1493. }
  1494. g.element.ToBigIntRegular(&g.bigint)
  1495. genResult := gopter.NewGenResult(g, gopter.NoShrinker)
  1496. return genResult
  1497. }
  1498. }
  1499. func genFull() gopter.Gen {
  1500. return func(genParams *gopter.GenParameters) *gopter.GenResult {
  1501. genRandomFq := func() Element {
  1502. var g Element
  1503. g = Element{
  1504. genParams.NextUint64(),
  1505. genParams.NextUint64(),
  1506. genParams.NextUint64(),
  1507. genParams.NextUint64(),
  1508. }
  1509. if qElement[3] != ^uint64(0) {
  1510. g[3] %= (qElement[3] + 1)
  1511. }
  1512. for g.biggerOrEqualModulus() {
  1513. g = Element{
  1514. genParams.NextUint64(),
  1515. genParams.NextUint64(),
  1516. genParams.NextUint64(),
  1517. genParams.NextUint64(),
  1518. }
  1519. if qElement[3] != ^uint64(0) {
  1520. g[3] %= (qElement[3] + 1)
  1521. }
  1522. }
  1523. return g
  1524. }
  1525. a := genRandomFq()
  1526. var carry uint64
  1527. a[0], carry = bits.Add64(a[0], qElement[0], carry)
  1528. a[1], carry = bits.Add64(a[1], qElement[1], carry)
  1529. a[2], carry = bits.Add64(a[2], qElement[2], carry)
  1530. a[3], _ = bits.Add64(a[3], qElement[3], carry)
  1531. genResult := gopter.NewGenResult(a, gopter.NoShrinker)
  1532. return genResult
  1533. }
  1534. }