00001 #include "multiprec.h"
00002 #include <string.h>
00003
00021 void
00022 ymp_euclid(mp_ref_t g, mp_cref_t a, mp_cref_t b)
00023 {
00024 struct {
00025 size_t used;
00026 digit_t *digits;
00027 } r0, r1;
00028
00029 r0.used = a->used; r1.used = b->used;
00030 YMP_TEMP_ALLOCATE(r0.digits, digit_t, r0.used);
00031 YMP_TEMP_ALLOCATE(r1.digits, digit_t, r1.used);
00032 memcpy(r0.digits, a->digits, r0.used*sizeof(digit_t));
00033 memcpy(r1.digits, b->digits, r1.used*sizeof(digit_t));
00034
00035 while (r1.used !=0 && (r1.used != 1 || r1.digits[0] != 0))
00036 {
00037 register size_t tmp_used;
00038 register digit_t *tmp_digits;
00039 if (r0.used >= r1.used)
00040 {
00041 r0.used = ymp_divmodabs(NULL, r0.digits,
00042 r0.digits, r1.digits, r0.used, r1.used);
00043 }
00044 tmp_used = r0.used; r0.used = r1.used; r1.used = tmp_used;
00045 tmp_digits = r0.digits; r0.digits = r1.digits; r1.digits = tmp_digits;
00046 }
00047 ymp_assign_array(g, r0.used, r0.digits);
00048 }
00049
00050
00067 void
00068 ymp_euclid_ex(mp_ref_t g, mp_ref_t s, mp_ref_t t, mp_cref_t a, mp_cref_t b)
00069 {
00070 struct multiprec r0, r1, s0, s1, t0, t1, q, tmp;
00071
00072 ymp_alloca_initialize(&r0, a->used);
00073 ymp_alloca_initialize(&r1, b->used);
00074 ymp_alloca_initialize(&q, MAX(a->used, b->used));
00075 ymp_assign(&r0, a); ymp_assign(&r1, b);
00076
00077 ymp_initialize_by_digit(&s0, 1); ymp_initialize_by_digit(&s1, 0);
00078 ymp_initialize_by_digit(&t0, 0); ymp_initialize_by_digit(&t1, 1);
00079 ymp_initialize(&tmp);
00080
00081 while (!ymp_is_zero(&r1))
00082 {
00083 ymp_divmod(&q, &r0, &r0, &r1);
00084 ymp_mul(&tmp, &q, &s1);
00085 ymp_sub(&s0, &s0, &tmp);
00086 ymp_mul(&tmp, &q, &t1);
00087 ymp_sub(&t0, &t0, &tmp);
00088
00089 ymp_swap(&r0, &r1);
00090 ymp_swap(&s0, &s1);
00091 ymp_swap(&t0, &t1);
00092 }
00093
00094 if (g) ymp_assign(g, &r0);
00095 if (s) ymp_assign(s, &s0);
00096 if (t) ymp_assign(t, &t0);
00097 ymp_destroy(&s0); ymp_destroy(&s1);
00098 ymp_destroy(&t0); ymp_destroy(&t1);
00099 ymp_destroy(&tmp);
00100 }
00101
00102
00113 int
00114 ymp_modinv(mp_ref_t result, mp_cref_t self, mp_cref_t modulus)
00115 {
00116 struct multiprec r0, r1, s0, s1, q, tmp;
00117 register size_t len = MAX(self->used, modulus->used);
00118
00119 ymp_alloca_initialize(&r0, self->used);
00120 ymp_alloca_initialize(&r1, modulus->used);
00121 ymp_alloca_initialize(&s0, modulus->used+len+1);
00122 ymp_alloca_initialize(&s1, modulus->used+len+1);
00123 ymp_alloca_initialize(&q, len);
00124 ymp_alloca_initialize(&tmp, modulus->used+len);
00125
00126 ymp_assign(&r0, self); ymp_assign(&r1, modulus);
00127 ymp_assign_digit(&s0, 1); ymp_assign_digit(&s1, 0);
00128
00129 while (!ymp_is_zero(&r1))
00130 {
00131 ymp_divmod(&q, &r0, &r0, &r1);
00132 ymp_mul(&tmp, &s1, &q);
00133 ymp_sub(&s0, &s0, &tmp);
00134 ymp_mod(&s0, &s0, modulus);
00135
00136 ymp_swap(&r0, &r1);
00137 ymp_swap(&s0, &s1);
00138 }
00139
00140 if (r0.used == 1 && r0.digits[0] == 1)
00141 {
00142 ymp_assign(result, &s0);
00143 if (r0.sign) result->sign = !result->sign;
00144 return 0;
00145 }
00146 else
00147 {
00148 return 1;
00149 }
00150 }
00151
00152
00165 int
00166 ymp_binary_sunzi(mp_ref_t result,
00167 const mp_cref_t remainders[2], const mp_cref_t moduli[2])
00168 {
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179 struct multiprec m_0_inv;
00180 struct multiprec v[2];
00181 register size_t len;
00182
00183 ymp_alloca_initialize(&m_0_inv, moduli[1]->used);
00184 if (ymp_modinv(&m_0_inv, moduli[0], moduli[1])) return 1;
00185
00186 ymp_alloca_initialize(&v[0], moduli[0]->used);
00187 ymp_mod(&v[0], remainders[0], moduli[0]);
00188
00189 len = MAX(remainders[1]->used, moduli[0]->used + moduli[1]->used);
00190 ymp_alloca_initialize(&v[1], len);
00191
00192 ymp_sub(&v[1], remainders[1], &v[0]);
00193 ymp_modmul(&v[1], &v[1], &m_0_inv, moduli[1]);
00194 ymp_mul(&v[1], &v[1], moduli[0]);
00195
00196 ymp_add(result, &v[1], &v[0]);
00197 return 0;
00198 }
00199