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

addsub.c

解説を見る。
00001 #include "multiprec.h"
00002 #include <string.h>
00003 
00036 inline size_t
00037 ymp_addabs(digit_t *result, const digit_t *lhs, const digit_t *rhs,
00038            size_t lhs_len, size_t rhs_len)
00039 {
00040   double_digit_t tmp = 0;
00041   size_t i;
00042 
00043   for ( i = 0; i < rhs_len; ++i)
00044     {
00045       tmp += lhs[i];
00046       tmp += rhs[i];
00047       result[i] = LOW_DIGIT(tmp);
00048       tmp = HIGH_DIGIT(tmp);
00049     }
00050   for ( ; i < lhs_len; ++i)
00051     {
00052       tmp += lhs[i];
00053       result[i] = LOW_DIGIT(tmp);
00054       tmp = HIGH_DIGIT(tmp);
00055     }
00056   if (LOW_DIGIT(tmp))
00057     {
00058       result[i++] = LOW_DIGIT(tmp);
00059     }
00060   return i;
00061 }
00062 
00063 
00064 
00080 inline size_t
00081 ymp_subabs(digit_t *result, const digit_t *lhs, const digit_t *rhs,
00082            size_t lhs_len, size_t rhs_len)
00083 {
00084   double_digit_t tmp = 1;
00085   size_t i;
00086 
00087   for ( i = 0; i < rhs_len; ++i)
00088     {
00089       tmp += MULTIPREC_RADIX - 1;
00090       tmp += lhs[i];
00091       tmp -= rhs[i];
00092       result[i] = LOW_DIGIT(tmp);
00093       tmp = HIGH_DIGIT(tmp);
00094     }
00095   for ( ; i < lhs_len; ++i)
00096     {
00097       tmp += MULTIPREC_RADIX - 1;
00098       tmp += lhs[i];
00099       result[i] = LOW_DIGIT(tmp);
00100       tmp = HIGH_DIGIT(tmp);
00101     }
00102   while (i-- > 0)
00103     {
00104       if (result[i]) break;
00105     }
00106   return ++i;
00107 }
00108 
00126 inline static void
00127 ymp_do_add(mp_ref_t result, mp_cref_t self, mp_cref_t other, int is_add)
00128 {
00129   if (self->used > other->used)
00130     {
00131       if (is_add)
00132         {
00133           ymp_reserve(result, self->used+1);
00134           result->used
00135             = ymp_addabs(result->digits, self->digits, other->digits,
00136                          self->used, other->used);
00137           result->sign = self->sign;
00138         }
00139       else
00140         {
00141           ymp_reserve(result, self->used);
00142           result->used
00143             = ymp_subabs(result->digits, self->digits, other->digits,
00144                          self->used, other->used);
00145           result->sign = self->sign;
00146         }
00147       return;
00148     }
00149   else if (self->used < other->used)
00150     {
00151       if (is_add)
00152         {
00153           ymp_reserve(result, other->used+1);
00154           result->used
00155             = ymp_addabs(result->digits, other->digits, self->digits,
00156                          other->used, self->used);
00157           result->sign = self->sign;
00158         }
00159       else
00160         {
00161           ymp_reserve(result, other->used);
00162           result->used
00163             = ymp_subabs(result->digits, other->digits, self->digits,
00164                          other->used, self->used);
00165           result->sign = !self->sign;
00166         }
00167       return;
00168     }
00169 
00170 
00171 
00172   /* self->used == other->used */
00173 
00174   if (is_add)
00175     {
00176       ymp_reserve(result, self->used+1);
00177       result->used
00178         = ymp_addabs(result->digits, self->digits, other->digits,
00179                      self->used, other->used);
00180       result->sign = self->sign;
00181     }
00182   else 
00183     {
00184       size_t i = self->used;
00185       while (i-- > 0)
00186         {
00187           if ( self->digits[i] > other->digits[i])
00188             {
00189               ymp_reserve(result, ++i);
00190               result->used
00191                 = ymp_subabs(result->digits, self->digits, other->digits,
00192                              i, i);
00193               result->sign = self->sign;
00194               return;
00195             }
00196           else if (self->digits[i] < other->digits[i])
00197             {
00198               ymp_reserve(result, ++i);
00199               result->used
00200                 = ymp_subabs(result->digits, other->digits, self->digits,
00201                              i, i);
00202               result->sign = !self->sign;
00203               return;
00204             }
00205         }
00206       result->sign = positive_sign;
00207       result->used = 0;
00208     }
00209 }
00210 
00211 
00212 
00227 inline static void
00228 ymp_do_add_digit(mp_ref_t result, mp_cref_t self, digit_t other, int is_add)
00229 {
00230   switch (self->used)
00231     {
00232     case 0:
00233       ymp_reserve(result, 1);
00234       result->sign = self->sign;
00235       result->used = 1;
00236       result->digits[0] = other;
00237       return;
00238 
00239     case 1:
00240       if (is_add)
00241         {
00242           double_digit_t tmp;
00243 
00244           ymp_reserve(result, 2);
00245           result->sign = self->sign;
00246           result->used = 1;
00247 
00248           tmp = other;
00249           tmp += self->digits[0];
00250 
00251           result->digits[0] = LOW_DIGIT(tmp);
00252           if ( (tmp = HIGH_DIGIT(tmp)) )
00253             {
00254               self->digits[1] = LOW_DIGIT(tmp);
00255               ++result->used;
00256             }
00257           return;
00258         }
00259       else
00260         {
00261           ymp_reserve(result, 1);
00262           result->used = 1;
00263           if (self->digits[0] > other)
00264             {
00265               result->sign = self->sign;
00266               result->digits[0] = self->digits[0] - other;
00267             }
00268           else
00269             {
00270               result->sign = !self->sign;
00271               self->digits[0] = other - self->digits[0];
00272             }
00273           return;
00274         }
00275     default:
00276       if (is_add)
00277         {
00278           ymp_reserve(result, self->used+1);
00279           result->used 
00280             = ymp_addabs(result->digits, self->digits, &other, self->used, 1);
00281           result->sign = self->sign;
00282           return;
00283         }
00284       else
00285         {
00286           ymp_reserve(result, self->used+1);
00287           result->used
00288             = ymp_subabs(result->digits, self->digits, &other, self->used, 1);
00289           result->sign = self->sign;
00290           return;
00291         }
00292     }
00293 }
00294 
00295 
00296 
00297 
00298 
00309 void ymp_add(mp_ref_t result, mp_cref_t self, mp_cref_t other)
00310 {
00311   ymp_do_add(result, self, other, self->sign==other->sign);
00312 }
00313 
00324 void ymp_sub(mp_ref_t result, mp_cref_t self, mp_cref_t other)
00325 {
00326   ymp_do_add(result, self, other, self->sign!=other->sign);
00327 }
00328 
00329 
00330 
00338 void
00339 ymp_add_digit(mp_ref_t result, mp_cref_t self, digit_t val)
00340 {
00341   ymp_do_add_digit(result, self, val, self->sign==positive_sign);
00342 }
00343 
00351 void 
00352 ymp_sub_digit(mp_ref_t result, mp_cref_t self, digit_t val)
00353 {
00354   ymp_do_add_digit(result, self, val, self->sign!=positive_sign);
00355 }
00356 
00357 
00366 void ymp_neg(mp_ref_t result, mp_cref_t orig)
00367 {
00368   result->sign = !orig->sign;
00369   if (result != orig)
00370     {
00371       ymp_reserve(result, orig->used);
00372       result->used = orig->used;
00373       memcpy(result->digits, orig->digits, sizeof(digit_t)*orig->used);
00374     }
00375 }
00376 

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