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.
 
 
 
 
 

197 lines
4.7 KiB

  1. #include "field.h"
  2. #include "test.h"
  3. #include <gmp.h>
  4. #include <string.h>
  5. #include <stdio.h>
  6. mpz_t mp_field;
  7. static mask_t mpz_to_field (
  8. struct field_t *out,
  9. const mpz_t in
  10. ) {
  11. uint8_t ser[FIELD_BYTES];
  12. mpz_t modded;
  13. memset(ser,0,sizeof(ser));
  14. mpz_init(modded);
  15. mpz_mod(modded, in, mp_field);
  16. mpz_export(ser, NULL, -1, 1, -1, 0, modded);
  17. mask_t succ = field_deserialize(out, ser);
  18. return succ;
  19. }
  20. static mask_t field_assert_eq_gmp(
  21. const char *descr,
  22. const struct field_t *x,
  23. const mpz_t y,
  24. float lowBound,
  25. float highBound
  26. ) {
  27. uint8_t xser[FIELD_BYTES], yser[FIELD_BYTES];
  28. mpz_t modded;
  29. memset(yser,0,sizeof(yser));
  30. field_serialize(xser, x);
  31. mpz_init(modded);
  32. mpz_mod(modded, y, mp_field);
  33. mpz_export(yser, NULL, -1, 1, -1, 0, modded);
  34. unsigned int i;
  35. for (i=0; i<sizeof(*x)/sizeof(x->limb[0]); i++) {
  36. int radix_bits = sizeof(x->limb[0]) * 448 / sizeof(*x);
  37. word_t yardstick = (i==sizeof(*x)/sizeof(x->limb[0])/2) ?
  38. (1ull<<radix_bits) - 2 : (1ull<<radix_bits) - 1; // FIELD_MAGIC
  39. if (x->limb[i] < yardstick * lowBound || x->limb[i] > yardstick * highBound) {
  40. youfail();
  41. printf(" Limb %d -> " PRIxWORDfull " is out of bounds (%0.2f, %0.2f) for test %s (yardstick = " PRIxWORDfull ")\n",
  42. i, x->limb[i], lowBound, highBound, descr, yardstick);
  43. break;
  44. }
  45. }
  46. if (memcmp(xser,yser,FIELD_BYTES)) {
  47. youfail();
  48. printf(" Failed arithmetic test %s\n", descr);
  49. field_print(" goldi", x);
  50. printf(" gmp = 0x");
  51. int j;
  52. for (j=FIELD_BYTES-1; j>=0; j--) {
  53. printf("%02x", yser[j]);
  54. }
  55. printf("\n");
  56. return MASK_FAILURE;
  57. }
  58. mpz_clear(modded);
  59. return MASK_SUCCESS;
  60. }
  61. static mask_t test_add_sub (
  62. const mpz_t x,
  63. const mpz_t y,
  64. word_t word
  65. ) {
  66. struct field_t xx,yy,tt;
  67. mpz_t t;
  68. mask_t succ = MASK_SUCCESS;
  69. succ = mpz_to_field(&xx,x);
  70. succ &= mpz_to_field(&yy,y);
  71. mpz_init(t);
  72. field_add(&tt,&xx,&yy);
  73. mpz_add(t,x,y);
  74. succ &= field_assert_eq_gmp("add",&tt,t,0,2.1);
  75. field_sub(&tt,&xx,&yy);
  76. field_bias(&tt,2);
  77. mpz_sub(t,x,y);
  78. succ &= field_assert_eq_gmp("sub",&tt,t,0,3.1);
  79. field_copy(&tt,&xx);
  80. field_addw(&tt,word);
  81. mpz_add_ui(t,x,word);
  82. succ &= field_assert_eq_gmp("addw",&tt,t,0,2.1);
  83. field_copy(&tt,&xx);
  84. field_subw(&tt,word);
  85. field_bias(&tt,1);
  86. mpz_sub_ui(t,x,word);
  87. succ &= field_assert_eq_gmp("subw",&tt,t,0,2.1);
  88. if (!succ) {
  89. field_print(" x", &xx);
  90. field_print(" y", &yy);
  91. }
  92. mpz_clear(t);
  93. return succ;
  94. }
  95. static mask_t test_mul_sqr (
  96. const mpz_t x,
  97. const mpz_t y,
  98. word_t word
  99. ) {
  100. struct field_t xx,yy,tt;
  101. mpz_t t;
  102. mask_t succ = MASK_SUCCESS;
  103. succ = mpz_to_field(&xx,x);
  104. succ &= mpz_to_field(&yy,y);
  105. mpz_init(t);
  106. field_mul(&tt,&xx,&yy);
  107. mpz_mul(t,x,y);
  108. succ &= field_assert_eq_gmp("mul",&tt,t,0,1.1);
  109. field_mulw(&tt,&xx,word);
  110. mpz_mul_ui(t,x,word);
  111. succ &= field_assert_eq_gmp("mulw",&tt,t,0,1.1);
  112. field_sqr(&tt,&xx);
  113. mpz_mul(t,x,x);
  114. succ &= field_assert_eq_gmp("sqrx",&tt,t,0,1.1);
  115. field_sqr(&tt,&yy);
  116. mpz_mul(t,y,y);
  117. succ &= field_assert_eq_gmp("sqy",&tt,t,0,1.1);
  118. if (!succ) {
  119. field_print(" x", &xx);
  120. field_print(" y", &yy);
  121. }
  122. mpz_clear(t);
  123. return succ;
  124. }
  125. int test_arithmetic (void) {
  126. int j, ntests = 100000;
  127. gmp_randstate_t state;
  128. gmp_randinit_mt(state);
  129. mpz_init(mp_field);
  130. mpz_import(mp_field, FIELD_BYTES, -1, 1, -1, 0, FIELD_MODULUS);
  131. mpz_t x,y;
  132. mpz_init(x);
  133. mpz_init(y);
  134. mask_t succ = MASK_SUCCESS;
  135. int radix_bits = sizeof(word_t) * FIELD_BITS / sizeof(field_t);
  136. for (j=0; j<ntests; j++) {
  137. if (j<256) {
  138. mpz_set_ui(x,0);
  139. mpz_set_ui(y,0);
  140. mpz_setbit(x,(j%16)*28); // FIELD_MAGIC
  141. mpz_setbit(y,(j/16)*28); // FIELD_MAGIC
  142. } else if (j&1) {
  143. mpz_rrandomb(x, state, FIELD_BITS);
  144. mpz_rrandomb(y, state, FIELD_BITS);
  145. } else {
  146. mpz_urandomb(x, state, FIELD_BITS);
  147. mpz_urandomb(y, state, FIELD_BITS);
  148. }
  149. word_t word = gmp_urandomm_ui (state, 1ull<<radix_bits);
  150. succ &= test_add_sub(x,y,word);
  151. succ &= test_mul_sqr(x,y,word);
  152. // TODO: test neg, cond_neg, set_ui, wrd, srd, inv, ...?
  153. }
  154. mpz_clear(x);
  155. mpz_clear(y);
  156. mpz_clear(mp_field);
  157. gmp_randclear(state);
  158. return succ ? 0 : 1;
  159. }