メインページ   モジュール   データ構造   ファイル一覧   データフィールド   グローバル  

euclid.c

解説を見る。
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);          /* |r0| <= |self|        */
00120   ymp_alloca_initialize(&r1, modulus->used);       /* |r1| <= |modulus|     */
00121   ymp_alloca_initialize(&s0, modulus->used+len+1); /* |s0| <= |r0|*|q|+|s1| */
00122   ymp_alloca_initialize(&s1, modulus->used+len+1); /* |s1| <= |r1|*|q|+|s0| */
00123   ymp_alloca_initialize(&q, len);                  /* |q|  <= max(|r0|,|r1|)*/
00124   ymp_alloca_initialize(&tmp, modulus->used+len);  /* |tmp| <= |r_i|*|q|    */
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    * H. L. Garnerの高速解法
00171    * c_{0,1} := m_0^{-1} (mod m_1)
00172    *
00173    * v_0 := u_0 mod m_0
00174    * v_1 := (u_1 - u_0) * c_{0,1} mod m_1
00175    *
00176    * u = v_1 * m_0 + v_0
00177    */
00178 
00179   struct multiprec m_0_inv; /* m_0^{-1} (mod m_1) */
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 

YMPに対してTue Mar 16 19:23:51 2004に生成されました。 doxygen1.2.14 作者 Dimitri van Heesch, © 1997-2002