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.

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