bn_mp_is_square.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. #include <tommath.h>
  2. #ifdef BN_MP_IS_SQUARE_C
  3. /* LibTomMath, multiple-precision integer library -- Tom St Denis
  4. *
  5. * LibTomMath is a library that provides multiple-precision
  6. * integer arithmetic as well as number theoretic functionality.
  7. *
  8. * The library was designed directly after the MPI library by
  9. * Michael Fromberger but has been written from scratch with
  10. * additional optimizations in place.
  11. *
  12. * The library is free for all purposes without any express
  13. * guarantee it works.
  14. *
  15. * Tom St Denis, tomstdenis@gmail.com, http://math.libtomcrypt.com
  16. */
  17. /* Check if remainders are possible squares - fast exclude non-squares */
  18. static const char rem_128[128] = {
  19. 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
  20. 0, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
  21. 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
  22. 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
  23. 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
  24. 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
  25. 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1,
  26. 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1
  27. };
  28. static const char rem_105[105] = {
  29. 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1,
  30. 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1,
  31. 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1,
  32. 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
  33. 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1,
  34. 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1,
  35. 1, 0, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1
  36. };
  37. /* Store non-zero to ret if arg is square, and zero if not */
  38. int mp_is_square(mp_int *arg,int *ret)
  39. {
  40. int res;
  41. mp_digit c;
  42. mp_int t;
  43. unsigned long r;
  44. /* Default to Non-square :) */
  45. *ret = MP_NO;
  46. if (arg->sign == MP_NEG) {
  47. return MP_VAL;
  48. }
  49. /* digits used? (TSD) */
  50. if (arg->used == 0) {
  51. return MP_OKAY;
  52. }
  53. /* First check mod 128 (suppose that DIGIT_BIT is at least 7) */
  54. if (rem_128[127 & DIGIT(arg,0)] == 1) {
  55. return MP_OKAY;
  56. }
  57. /* Next check mod 105 (3*5*7) */
  58. if ((res = mp_mod_d(arg,105,&c)) != MP_OKAY) {
  59. return res;
  60. }
  61. if (rem_105[c] == 1) {
  62. return MP_OKAY;
  63. }
  64. if ((res = mp_init_set_int(&t,11L*13L*17L*19L*23L*29L*31L)) != MP_OKAY) {
  65. return res;
  66. }
  67. if ((res = mp_mod(arg,&t,&t)) != MP_OKAY) {
  68. goto ERR;
  69. }
  70. r = mp_get_int(&t);
  71. /* Check for other prime modules, note it's not an ERROR but we must
  72. * free "t" so the easiest way is to goto ERR. We know that res
  73. * is already equal to MP_OKAY from the mp_mod call
  74. */
  75. if ( (1L<<(r%11)) & 0x5C4L ) goto ERR;
  76. if ( (1L<<(r%13)) & 0x9E4L ) goto ERR;
  77. if ( (1L<<(r%17)) & 0x5CE8L ) goto ERR;
  78. if ( (1L<<(r%19)) & 0x4F50CL ) goto ERR;
  79. if ( (1L<<(r%23)) & 0x7ACCA0L ) goto ERR;
  80. if ( (1L<<(r%29)) & 0xC2EDD0CL ) goto ERR;
  81. if ( (1L<<(r%31)) & 0x6DE2B848L ) goto ERR;
  82. /* Final check - is sqr(sqrt(arg)) == arg ? */
  83. if ((res = mp_sqrt(arg,&t)) != MP_OKAY) {
  84. goto ERR;
  85. }
  86. if ((res = mp_sqr(&t,&t)) != MP_OKAY) {
  87. goto ERR;
  88. }
  89. *ret = (mp_cmp_mag(&t,arg) == MP_EQ) ? MP_YES : MP_NO;
  90. ERR:mp_clear(&t);
  91. return res;
  92. }
  93. #endif
  94. /* $Source: /cvs/libtom/libtommath/bn_mp_is_square.c,v $ */
  95. /* $Revision: 1.3 $ */
  96. /* $Date: 2006/03/31 14:18:44 $ */