qarith.c 1.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. #include <openssl/bn.h>
  2. #include "qa/questions/qarith.h"
  3. /**
  4. * \brief Square Root for bignums.
  5. *
  6. * An implementation of Dijkstra's Square Root Algorithm.
  7. * A Discipline of Programming, page 61 - Fifth Exercise.
  8. *
  9. * \return true if rem is equal to zero, false otherwise.
  10. */
  11. int BN_sqrtmod(BIGNUM* dv, BIGNUM* rem, BIGNUM* a, BN_CTX* ctx)
  12. {
  13. BIGNUM *shift;
  14. BIGNUM *adj;
  15. shift = BN_new();
  16. adj = BN_new();
  17. BN_zero(dv);
  18. BN_copy(rem, a);
  19. /* hacking into internal sequence to skip some cycles. */
  20. /* for (BN_one(shift); original */
  21. for (bn_wexpand(shift, a->top+1), shift->top=a->top, shift->d[shift->top-1] = 1;
  22. BN_ucmp(shift, rem) != 1;
  23. /* BN_rshift(shift, shift, 2); */
  24. BN_lshift1(shift, shift), BN_lshift1(shift, shift));
  25. while (!BN_is_one(shift)) {
  26. /* BN_rshift(shift, shift, 2); */
  27. BN_rshift1(shift, shift);
  28. BN_rshift1(shift, shift);
  29. BN_uadd(adj, dv, shift);
  30. BN_rshift1(dv, dv);
  31. if (BN_ucmp(rem, adj) != -1) {
  32. BN_uadd(dv, dv, shift);
  33. BN_usub(rem, rem, adj);
  34. }
  35. }
  36. BN_free(shift);
  37. BN_free(adj);
  38. return BN_is_zero(rem);
  39. }