in AWSCognitoIdentityProvider/Internal/JKBigInteger/LibTomMath/tommath.c [730:832]
int aws_mp_n_root(aws_mp_int *a, aws_mp_digit b, aws_mp_int *c)
{
aws_mp_int t1, t2, t3;
int res, neg;
/* input must be positive if b is even */
if ((b & 1) == 0 && a->sign == AWS_MP_NEG) {
return AWS_MP_VAL;
}
if ((res = aws_mp_init(&t1)) != AWS_MP_OKAY) {
return res;
}
if ((res = aws_mp_init(&t2)) != AWS_MP_OKAY) {
goto LBL_T1;
}
if ((res = aws_mp_init(&t3)) != AWS_MP_OKAY) {
goto LBL_T2;
}
/* if a is negative fudge the sign but keep track */
neg = a->sign;
a->sign = AWS_MP_ZPOS;
/* t2 = 2 */
aws_mp_set(&t2, 2);
do {
/* t1 = t2 */
if ((res = aws_mp_copy(&t2, &t1)) != AWS_MP_OKAY) {
goto LBL_T3;
}
/* t2 = t1 - ((t1**b - a) / (b * t1**(b-1))) */
/* t3 = t1**(b-1) */
if ((res = aws_mp_expt_d(&t1, b - 1, &t3)) != AWS_MP_OKAY) {
goto LBL_T3;
}
/* numerator */
/* t2 = t1**b */
if ((res = aws_mp_mul(&t3, &t1, &t2)) != AWS_MP_OKAY) {
goto LBL_T3;
}
/* t2 = t1**b - a */
if ((res = aws_mp_sub(&t2, a, &t2)) != AWS_MP_OKAY) {
goto LBL_T3;
}
/* denominator */
/* t3 = t1**(b-1) * b */
if ((res = aws_mp_mul_d(&t3, b, &t3)) != AWS_MP_OKAY) {
goto LBL_T3;
}
/* t3 = (t1**b - a)/(b * t1**(b-1)) */
if ((res = aws_mp_div(&t2, &t3, &t3, NULL)) != AWS_MP_OKAY) {
goto LBL_T3;
}
if ((res = aws_mp_sub(&t1, &t3, &t2)) != AWS_MP_OKAY) {
goto LBL_T3;
}
} while (aws_mp_cmp(&t1, &t2) != AWS_MP_EQ);
/* result can be off by a few so check */
for (;;) {
if ((res = aws_mp_expt_d(&t1, b, &t2)) != AWS_MP_OKAY) {
goto LBL_T3;
}
if (aws_mp_cmp(&t2, a) == AWS_MP_GT) {
if ((res = aws_mp_sub_d(&t1, 1, &t1)) != AWS_MP_OKAY) {
goto LBL_T3;
}
} else {
break;
}
}
/* reset the sign of a first */
a->sign = neg;
/* set the result */
aws_mp_exch(&t1, c);
/* set the sign of the result */
c->sign = neg;
res = AWS_MP_OKAY;
LBL_T3:
aws_mp_clear(&t3);
LBL_T2:
aws_mp_clear(&t2);
LBL_T1:
aws_mp_clear(&t1);
return res;
}