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.
 
 
 
 
 

263 lines
6.0 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. field_a_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 inline int BRANCH_ON_CONSTANT(int x) {
  21. __asm__ ("" : "+r"(x));
  22. return x;
  23. }
  24. static mask_t field_assert_eq_gmp(
  25. const char *descr,
  26. const field_a_t a,
  27. const field_a_t b,
  28. const field_a_t x,
  29. const mpz_t y,
  30. float lowBound,
  31. float highBound
  32. ) {
  33. uint8_t xser[FIELD_BYTES], yser[FIELD_BYTES];
  34. mpz_t modded;
  35. memset(yser,0,sizeof(yser));
  36. field_serialize(xser, x);
  37. mpz_init(modded);
  38. mpz_mod(modded, y, mp_field);
  39. mpz_export(yser, NULL, -1, 1, -1, 0, modded);
  40. unsigned int i;
  41. for (i=0; i<sizeof(*x)/sizeof(x->limb[0]); i++) {
  42. int radix_bits = 1 + (sizeof(x->limb[0]) * FIELD_BITS - 1) / sizeof(*x);
  43. word_t yardstick;
  44. if (BRANCH_ON_CONSTANT(FIELD_BITS == 521) && BRANCH_ON_CONSTANT(sizeof(*x)==12*8)) {
  45. radix_bits = 58;
  46. }
  47. yardstick = (1ull<<radix_bits) - 1;
  48. if (x->limb[i] < yardstick * lowBound || x->limb[i] > yardstick * highBound) {
  49. youfail();
  50. printf(" Limb %d -> " PRIxWORDfull " is out of bounds (%0.2f, %0.2f) for test %s (yardstick = " PRIxWORDfull ")\n",
  51. i, x->limb[i], lowBound, highBound, descr, yardstick);
  52. break;
  53. }
  54. }
  55. if (memcmp(xser,yser,FIELD_BYTES)) {
  56. youfail();
  57. printf(" Failed arithmetic test %s\n", descr);
  58. field_print(" a", a);
  59. field_print(" b", b);
  60. field_print(" goldi", x);
  61. printf(" gmp = 0x");
  62. int j;
  63. for (j=FIELD_BYTES-1; j>=0; j--) {
  64. printf("%02x", yser[j]);
  65. }
  66. printf("\n");
  67. return MASK_FAILURE;
  68. }
  69. mpz_clear(modded);
  70. return MASK_SUCCESS;
  71. }
  72. static mask_t test_add_sub_RAW (
  73. const mpz_t x,
  74. const mpz_t y,
  75. word_t word
  76. ) {
  77. field_a_t xx,yy,tt;
  78. mpz_t t;
  79. mask_t succ = MASK_SUCCESS;
  80. succ = mpz_to_field(xx,x);
  81. succ &= mpz_to_field(yy,y);
  82. mpz_init(t);
  83. field_add_RAW(tt,xx,yy);
  84. mpz_add(t,x,y);
  85. succ &= field_assert_eq_gmp("add",xx,yy,tt,t,0,2.1);
  86. field_sub_RAW(tt,xx,yy);
  87. field_bias(tt,2);
  88. mpz_sub(t,x,y);
  89. succ &= field_assert_eq_gmp("sub",xx,yy,tt,t,0,3.1);
  90. field_copy(tt,xx);
  91. field_addw(tt,word);
  92. mpz_add_ui(t,x,word);
  93. succ &= field_assert_eq_gmp("addw",xx,yy,tt,t,0,2.1);
  94. field_copy(tt,xx);
  95. field_subw(tt,word);
  96. field_bias(tt,1);
  97. mpz_sub_ui(t,x,word);
  98. succ &= field_assert_eq_gmp("subw",xx,yy,tt,t,0,2.1);
  99. /*
  100. if (!succ) {
  101. field_print(" x", &xx);
  102. field_print(" y", &yy);
  103. }
  104. */
  105. mpz_clear(t);
  106. return succ;
  107. }
  108. static mask_t test_mul_sqr (
  109. const mpz_t x,
  110. const mpz_t y,
  111. word_t word
  112. ) {
  113. ANALYZE_THIS_ROUTINE_CAREFULLY;
  114. field_a_t xx,yy,tt,zz;
  115. mpz_t t, z;
  116. mask_t succ = MASK_SUCCESS;
  117. succ = mpz_to_field(xx,x);
  118. succ &= mpz_to_field(yy,y);
  119. mpz_init(t);
  120. mpz_init(z);
  121. field_mul(tt,xx,yy);
  122. mpz_mul(t,x,y);
  123. succ &= field_assert_eq_gmp("mul",xx,yy,tt,t,0,1.1);
  124. field_mulw(tt,xx,word);
  125. mpz_mul_ui(t,x,word);
  126. succ &= field_assert_eq_gmp("mulw",xx,yy,tt,t,0,1.1);
  127. field_sqr(tt,xx);
  128. mpz_mul(t,x,x);
  129. succ &= field_assert_eq_gmp("sqrx",xx,yy,tt,t,0,1.1);
  130. field_sqr(tt,yy);
  131. mpz_mul(t,y,y);
  132. succ &= field_assert_eq_gmp("sqy",xx,yy,tt,t,0,1.1);
  133. field_add_nr(zz,xx,xx);
  134. mpz_add(z,x,x);
  135. mpz_mul(t,z,z);
  136. field_mul(tt,zz,zz);
  137. succ &= field_assert_eq_gmp("msr4",xx,yy,tt,t,0,1.1);
  138. field_sqr(tt,zz);
  139. succ &= field_assert_eq_gmp("sqr4",xx,yy,tt,t,0,1.1);
  140. if (!succ) {
  141. field_print(" x", xx);
  142. field_print(" y", yy);
  143. }
  144. mpz_clear(t);
  145. mpz_clear(z);
  146. return succ;
  147. }
  148. static mask_t test_isr (
  149. const mpz_t x
  150. ) {
  151. field_a_t xx,yy,ss,tt;
  152. mask_t succ = 0;
  153. succ = mpz_to_field(xx,x);
  154. field_isr(ss,xx);
  155. field_sqr(tt,ss);
  156. field_mul(yy,xx,tt);
  157. field_addw(tt,1);
  158. succ |= field_is_zero(tt);
  159. field_subw(tt,2);
  160. field_bias(tt,1);
  161. succ |= field_is_zero(tt);
  162. field_addw(tt,1);
  163. if (~succ) {
  164. youfail();
  165. printf("ISR failure.\n");
  166. field_print(" x", xx);
  167. field_print(" s", ss);
  168. field_print(" t", tt);
  169. }
  170. return succ;
  171. }
  172. void dbg_gmp_printf(const mpz_t x);
  173. void dbg_gmp_printf(const mpz_t x) {
  174. gmp_printf("DEBUG: 0x%Zx\n", x);
  175. }
  176. int test_arithmetic (void) {
  177. int j, ntests = 100000;
  178. gmp_randstate_t state;
  179. gmp_randinit_mt(state);
  180. mpz_init(mp_field);
  181. mpz_import(mp_field, FIELD_BYTES, -1, 1, -1, 0, FIELD_MODULUS);
  182. mpz_t x,y;
  183. mpz_init(x);
  184. mpz_init(y);
  185. mask_t succ = MASK_SUCCESS;
  186. int radix_bits = sizeof(word_t) * FIELD_BITS / sizeof(field_a_t);
  187. for (j=0; j<ntests; j++) {
  188. if (j<256) {
  189. mpz_set_ui(x,0);
  190. mpz_set_ui(y,0);
  191. mpz_setbit(x,(j%16)*28);
  192. mpz_setbit(y,(j/16)*28);
  193. } else if (j&1) {
  194. mpz_rrandomb(x, state, FIELD_BITS);
  195. mpz_rrandomb(y, state, FIELD_BITS);
  196. } else {
  197. mpz_urandomb(x, state, FIELD_BITS);
  198. mpz_urandomb(y, state, FIELD_BITS);
  199. }
  200. word_t word = gmp_urandomm_ui (state, 1ull<<radix_bits);
  201. succ &= test_add_sub_RAW(x,y,word);
  202. succ &= test_mul_sqr(x,y,word);
  203. if (j < 1000)
  204. succ &= test_isr(x);
  205. // TODO: test neg, cond_neg_RAW, set_ui, wrd, srd, inv, ...?
  206. }
  207. mpz_clear(x);
  208. mpz_clear(y);
  209. mpz_clear(mp_field);
  210. gmp_randclear(state);
  211. return succ ? 0 : 1;
  212. }