Line data Source code
1 : #include "tommath_private.h" 2 : #ifdef BN_MP_SQRT_C 3 : /* LibTomMath, multiple-precision integer library -- Tom St Denis */ 4 : /* SPDX-License-Identifier: Unlicense */ 5 : 6 : /* this function is less generic than mp_n_root, simpler and faster */ 7 0 : mp_err mp_sqrt(const mp_int *arg, mp_int *ret) 8 : { 9 0 : mp_err err; 10 0 : mp_int t1, t2; 11 : 12 : /* must be positive */ 13 0 : if (arg->sign == MP_NEG) { 14 0 : return MP_VAL; 15 : } 16 : 17 : /* easy out */ 18 0 : if (MP_IS_ZERO(arg)) { 19 0 : mp_zero(ret); 20 0 : return MP_OKAY; 21 : } 22 : 23 0 : if ((err = mp_init_copy(&t1, arg)) != MP_OKAY) { 24 0 : return err; 25 : } 26 : 27 0 : if ((err = mp_init(&t2)) != MP_OKAY) { 28 0 : goto E2; 29 : } 30 : 31 : /* First approx. (not very bad for large arg) */ 32 0 : mp_rshd(&t1, t1.used/2); 33 : 34 : /* t1 > 0 */ 35 0 : if ((err = mp_div(arg, &t1, &t2, NULL)) != MP_OKAY) { 36 0 : goto E1; 37 : } 38 0 : if ((err = mp_add(&t1, &t2, &t1)) != MP_OKAY) { 39 0 : goto E1; 40 : } 41 0 : if ((err = mp_div_2(&t1, &t1)) != MP_OKAY) { 42 0 : goto E1; 43 : } 44 : /* And now t1 > sqrt(arg) */ 45 0 : do { 46 0 : if ((err = mp_div(arg, &t1, &t2, NULL)) != MP_OKAY) { 47 0 : goto E1; 48 : } 49 0 : if ((err = mp_add(&t1, &t2, &t1)) != MP_OKAY) { 50 0 : goto E1; 51 : } 52 0 : if ((err = mp_div_2(&t1, &t1)) != MP_OKAY) { 53 0 : goto E1; 54 : } 55 : /* t1 >= sqrt(arg) >= t2 at this point */ 56 0 : } while (mp_cmp_mag(&t1, &t2) == MP_GT); 57 : 58 0 : mp_exch(&t1, ret); 59 : 60 0 : E1: 61 0 : mp_clear(&t2); 62 0 : E2: 63 0 : mp_clear(&t1); 64 0 : return err; 65 : } 66 : 67 : #endif