1 #include "tommath_private.h"
3 /* LibTomMath, multiple-precision integer library -- Tom St Denis */
4 /* SPDX-License-Identifier: Unlicense */
6 /* Greatest Common Divisor using the binary method */
7 mp_err
mp_gcd(const mp_int
*a
, const mp_int
*b
, mp_int
*c
)
13 /* either zero than gcd is the largest */
21 /* get copies of a and b we can modify */
22 if ((err
= mp_init_copy(&u
, a
)) != MP_OKAY
) {
26 if ((err
= mp_init_copy(&v
, b
)) != MP_OKAY
) {
30 /* must be positive for the remainder of the algorithm */
31 u
.sign
= v
.sign
= MP_ZPOS
;
33 /* B1. Find the common power of two for u and v */
34 u_lsb
= mp_cnt_lsb(&u
);
35 v_lsb
= mp_cnt_lsb(&v
);
36 k
= MP_MIN(u_lsb
, v_lsb
);
39 /* divide the power of two out */
40 if ((err
= mp_div_2d(&u
, k
, &u
, NULL
)) != MP_OKAY
) {
44 if ((err
= mp_div_2d(&v
, k
, &v
, NULL
)) != MP_OKAY
) {
49 /* divide any remaining factors of two out */
51 if ((err
= mp_div_2d(&u
, u_lsb
- k
, &u
, NULL
)) != MP_OKAY
) {
57 if ((err
= mp_div_2d(&v
, v_lsb
- k
, &v
, NULL
)) != MP_OKAY
) {
62 while (!mp_iszero(&v
)) {
63 /* make sure v is the largest */
64 if (mp_cmp_mag(&u
, &v
) == MP_GT
) {
65 /* swap u and v to make sure v is >= u */
69 /* subtract smallest from largest */
70 if ((err
= s_mp_sub(&v
, &u
, &v
)) != MP_OKAY
) {
74 /* Divide out all factors of two */
75 if ((err
= mp_div_2d(&v
, mp_cnt_lsb(&v
), &v
, NULL
)) != MP_OKAY
) {
80 /* multiply by 2**k which we divided out at the beginning */
81 if ((err
= mp_mul_2d(&u
, k
, c
)) != MP_OKAY
) {