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

下位関数群
[数論的関数]


関数

int ymp_odd_root (mp_ref_t root, mp_cref_t source, size_t pow)
 正の奇数に対し、完全奇数乗数かどうかを判定. より詳しく...

int ymp_nsqrt_mod2exp (mp_ref_t root, mp_cref_t source, size_t e_mod)
 奇数に対し平方根の逆数を2の冪を法として求める. より詳しく...

int ymp_odd_sqrt (mp_ref_t root, mp_cref_t source)
 奇数に対し平方根を求める. より詳しく...


関数の解説

int ymp_odd_root mp_ref_t    root,
mp_cref_t    source,
size_t    pow
[inline, static]
 

正の奇数に対し、完全奇数乗数かどうかを判定.

<soruce>が完全pow乗数かどうかを判定し、存在すれば冪根を求める。

引数:
root  もし存在すれば冪根を格納するstruct multiprecへのポインタ 根が不要ならNULLを指定する。
source  判定対象の奇数を表すstruct multiprecへのポインタ
pow  冪指数
事前条件:
sourceの表す数は正であること。そうでない場合結果は不定
sourceの表す数は奇数であること。そうでない場合、結果は不定
powは奇数であること。そうでない場合、結果は不定
覚え書き:
rootとsourceは一致しても良い
戻り値:
pow乗根となる自然数が存在したなら、その値が<root>に格納され、 非0が返る。存在しなければ0.
事後条件:
冪根が存在しなかった場合、<root>は変化しない

perfect_power.c34 行で定義されています。

参照 multiprec::len, mp_cref_t, multiprec::sign, ymp_abs_clog2, ymp_add, ymp_alloca_initialize, ymp_assign, ymp_assign_2exp, ymp_assign_digit, ymp_compare, ymp_mod_2exp, ymp_modmul_2exp, ymp_modpow_2exp_z, ymp_mul_digit, ymp_pow, と ymp_sub.

呼出 ymp_is_perfect_power, と ymp_proot.

00035 {
00036 /* 
00037  * 2-adic Newton iteration. `Modern computer algebra' p.264-268参照
00038  */
00039   size_t clog2, k, two_exp;
00040   struct multiprec g, s, tmp;
00041 
00042   /* clog2 := */
00043   clog2 = ymp_abs_clog2(source->digits, source->used);
00044   if (clog2 == 0)
00045     {
00046       if (root) ymp_assign_digit(root, 1);
00047       return 1;
00048     }
00049 
00050   /* k := 2**{n*k} > <digits> なる最小のk */
00051   k = clog2 / pow + (clog2 % pow != 0);
00052 
00053   ymp_alloca_initialize(&g, k * pow + 1);
00054   ymp_alloca_initialize(&s, source->len + 1);
00055   ymp_alloca_initialize(&tmp, k * pow + 1);
00056   ymp_assign_digit(&g, 1);
00057   ymp_assign_digit(&s, 1);
00058 
00059   for (two_exp=2; two_exp<k; two_exp<<=1)
00060     {
00061       /* tmp := f(g_i)s_i = (g_i**pow - source)) * s_i  (mod 2**two_exp) */
00062       ymp_modpow_2exp_z(&tmp, &g, two_exp, pow);
00063       ymp_sub(&tmp, &tmp, source); ymp_mod_2exp(&tmp, &tmp, two_exp);
00064       ymp_modmul_2exp(&tmp, &tmp, &s, two_exp);
00065 
00066       /* g_{i+1} := g_i - tmp */
00067       ymp_sub(&g, &g, &tmp); ymp_mod_2exp(&g, &g, two_exp);
00068 
00069       /* tmp := f'(g_{i+1})* s_i**2 
00070        *      = pow * g_{i+1}**(pow-1) * s_i**2 (mod 2**two_exp)
00071        */
00072       ymp_modpow_2exp_z(&tmp, &g, two_exp, pow-1);
00073       ymp_mul_digit(&tmp, &tmp, pow); ymp_mod_2exp(&tmp, &tmp, two_exp);
00074       ymp_modmul_2exp(&tmp, &tmp, &s, two_exp); 
00075       ymp_modmul_2exp(&tmp, &tmp, &s, two_exp);
00076 
00077       /* s_{i+1} := 2*s_i - tmp */
00078       ymp_add(&s, &s, &s); ymp_mod_2exp(&s, &s, two_exp);
00079       ymp_sub(&s, &s, &tmp); ymp_mod_2exp(&s, &s, two_exp);
00080     }
00081 
00082   /* g = g_i - f(g_i)s_i  ( mod 2**k )*/
00083   ymp_modpow_2exp_z(&tmp, &g, k, pow);
00084   ymp_sub(&tmp, &tmp, source); ymp_mod_2exp(&tmp, &tmp, k);
00085   ymp_modmul_2exp(&tmp, &tmp, &s, k);
00086   ymp_sub(&g, &g, &tmp); ymp_mod_2exp(&g, &g, k);
00087 
00088   /* if (g < 0) g += 2**k */
00089   if (g.sign)
00090     {
00091       ymp_assign_2exp(&tmp, k);
00092       ymp_add(&g, &g, &tmp);
00093     }
00094 
00095 
00096   ymp_pow(&tmp, &g, pow);
00097   if (ymp_compare(&tmp, source) == 0)
00098     {
00099       if (root) ymp_assign(root, &g);
00100       return 1;
00101     }
00102   else
00103     {
00104       return 0;
00105     }
00106 }

int ymp_nsqrt_mod2exp mp_ref_t    root,
mp_cref_t    source,
size_t    e_mod
[inline, static]
 

奇数に対し平方根の逆数を2の冪を法として求める.

もし存在すれば<source> * i**2 = 1 (mod 2**(e_mod+1)) なる自然数iを求める

引数:
root  もし存在すればiを格納する、struct multiprecへのポインタ
source  判定対象の奇数を表すstruct multiprecへのポインタ
e_mod  法の冪指数
事前条件:
<source>の表す数は正であること。そうでない場合結果は不定
<source>の表す数は奇数であること。そうでない場合、結果は不定
覚え書き:
rootとsourceは一致しても良い
戻り値:
解となる自然数が存在したならその値が<root>に格納され、非0が返る。 存在しなければ0が返る.
事後条件:
冪根が存在しなかった場合、<root>は変化しない

perfect_power.c125 行で定義されています。

参照 DIGIT_BIT, mp_cref_t, ymp_alloca_initialize, ymp_assign_digit, ymp_div_2exp, ymp_modmul_2exp, ymp_neg, と ymp_sub_digit.

呼出 ymp_odd_sqrt.

00126 {
00127   /*
00128    * MATHEMATICS OF COMPUTATION Volume 67, Number 223, 
00129    * July 1998, Pages 1253-1283
00130    *
00131    * Daniel J. Bernstein
00132    * "DETECTING PERFECT POWERS IN ESSENTIALLY LINEAR TIME": Section 21
00133    *
00134    * Algorithm S2 and Lemma 21.4
00135    */
00136   
00137   size_t n_digits;
00138   size_t e;
00139   struct multiprec tmp, r;
00140 
00141   if ((source->digits[0] & 0x03) != 1) return 0;
00142   if (e_mod == 1) { ymp_assign_digit(root, 1); return 1;}
00143   if ((source->digits[0] & 0x07) != 1) return 0;
00144   if (e_mod == 2) { ymp_assign_digit(root, 1); return 1;}
00145 
00146   n_digits = e_mod / DIGIT_BIT + (e_mod % DIGIT_BIT != 0);
00147   ymp_alloca_initialize(&r, n_digits+2);
00148   ymp_alloca_initialize(&tmp, n_digits+2);
00149 
00150   ymp_assign_digit(&r, 1);
00151   for (e = 3; e < e_mod; e = 2*e-1)
00152     {
00153       /* tmp := (3r - source*r**3) mod 2**(e+1) */
00154       ymp_modmul_2exp(&tmp, source, &r, e+1);
00155       ymp_modmul_2exp(&tmp, &tmp, &r, e+1);
00156       ymp_sub_digit(&tmp, &tmp, 3);
00157       ymp_neg(&tmp, &tmp);
00158       ymp_modmul_2exp(&tmp, &tmp, &r, e+1);
00159 
00160       /* r := tmp/2 mod 2**e */
00161       ymp_div_2exp(&r, &tmp, 1);
00162     }
00163 
00164   /* tmp := (3r - source*r**3) mod 2**(e_mod+1) */
00165   ymp_modmul_2exp(&tmp, source, &r, e_mod+1);
00166   ymp_modmul_2exp(&tmp, &tmp, &r, e_mod+1);
00167   ymp_sub_digit(&tmp, &tmp, 3);
00168   ymp_neg(&tmp, &tmp);
00169   ymp_modmul_2exp(&tmp, &tmp, &r, e_mod+1);
00170 
00171   /* r := tmp/2 mod 2**e */
00172   ymp_div_2exp(root, &tmp, 1);
00173   return 1;
00174 }

int ymp_odd_sqrt mp_ref_t    root,
mp_cref_t    source
[inline, static]
 

奇数に対し平方根を求める.

もし存在すれば<source> = i**2 なる自然数iを求める

引数:
root  もし存在すればiを格納する、struct multiprecへのポインタ 根が不要ならNULLを指定する
source  判定対象の奇数を表すstruct multiprecへのポインタ
事前条件:
<source>の表す数は正であること。そうでない場合結果は不定
<source>の表す数は奇数であること。そうでない場合、結果は不定
覚え書き:
rootとsourceは一致しても良い
戻り値:
平方根となる自然数が存在したなら、 その値が<root>に格納され、非0が返る。存在しなければ0が返る.
事後条件:
冪根が存在しなかった場合、<root>は変化しない

perfect_power.c194 行で定義されています。

参照 DIGIT_BIT, MAX, mp_cref_t, multiprec::sign, multiprec::used, ymp_abs_clog2, ymp_add, ymp_alloca_initialize, ymp_assign, ymp_assign_2exp, ymp_compare, ymp_modmul_2exp, ymp_mul, ymp_nsqrt_mod2exp, と ymp_sub.

呼出 ymp_is_perfect_power, と ymp_proot.

00195 {
00196   size_t n_digits, n_bits;
00197   size_t clog2, b;
00198   struct multiprec r, tmp;
00199 
00200   clog2 = ymp_abs_clog2(source->digits, source->used);
00201   b = clog2/2 + clog2%2;
00202 
00203   n_digits = b / DIGIT_BIT; n_bits = b % DIGIT_BIT;
00204   ymp_alloca_initialize(&r, n_digits + 1);
00205 
00206   if (!ymp_nsqrt_mod2exp(&r, source, b)) return 0;
00207 
00208   ymp_modmul_2exp(&r, &r, source, b);
00209   
00210   ymp_alloca_initialize(&tmp, MAX(2*(n_digits+1), 2*(r.used+1)));
00211 
00212   if (r.sign)
00213     {
00214       ymp_assign_2exp(&tmp, b);
00215       ymp_add(&r, &tmp, &r);
00216     }
00217   
00218   ymp_mul(&tmp, &r, &r);
00219   if (ymp_compare(source, &tmp) == 0)
00220     {
00221       if (root) ymp_assign(root, &r);
00222       return 1;
00223     }
00224 
00225   ymp_assign_2exp(&tmp, b);
00226   ymp_sub(&tmp, &tmp, &r);
00227   ymp_mul(&tmp, &tmp, &tmp);
00228   if (ymp_compare(source, &tmp) == 0)
00229     {
00230       if (root) ymp_assign(root, &r);
00231       return 1;
00232     }
00233 
00234   return 0;
00235 }


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