00001 #include "multiprec.h"
00002 #include <string.h>
00003
00033 size_t
00034 ymp_rshiftabs(digit_t *result, const digit_t *source, size_t len, size_t width)
00035 {
00036 register size_t i;
00037 size_t n_digits = width / DIGIT_BIT;
00038 size_t n_bits = width % DIGIT_BIT;
00039 digit_t prev;
00040
00041 if (len <= n_digits) return 0;
00042
00043 i=len; prev=0;
00044 while (i-- > n_digits)
00045 {
00046 double_digit_t tmp = LOW_DIGIT_TO_HIGH_DIGIT((double_digit_t)prev);
00047 prev = source[i];
00048 tmp += source[i];
00049 result[i-n_digits] = LOW_DIGIT(tmp >> n_bits);
00050 }
00051
00052
00053
00054 len -= n_digits;
00055 if (result[len-1]==0) --len;
00056
00057 return len;
00058 }
00059
00075 size_t
00076 ymp_lshiftabs(digit_t *result, const digit_t *source, size_t len, size_t width)
00077 {
00078 register size_t i;
00079 size_t n_digits = width / DIGIT_BIT;
00080 size_t n_bits = width % DIGIT_BIT;
00081 double_digit_t tmp;
00082
00083 if (len == 0) return 0;
00084
00085 i = len; tmp = source[--i];
00086 tmp <<= n_bits;
00087 if (HIGH_DIGIT(tmp)) result[len++ + n_digits] = HIGH_DIGIT(tmp);
00088
00089 tmp = source[i];
00090 while (i-- > 0)
00091 {
00092 tmp = LOW_DIGIT_TO_HIGH_DIGIT(tmp);
00093 tmp += source[i];
00094 result[i+n_digits+1] = HIGH_DIGIT(tmp << n_bits);
00095 tmp = source[i];
00096 }
00097 result[n_digits] = source[0] << n_bits;
00098
00099 i = n_digits;
00100 while (i-- > 0) result[i] = 0;
00101
00102 return len + n_digits;
00103 }
00104
00105
00119 size_t
00120 ymp_modabs_2exp(digit_t *result, const digit_t *self, size_t len, size_t pow)
00121 {
00122 size_t n_digits = pow / DIGIT_BIT;
00123 size_t n_bits = pow % DIGIT_BIT;
00124
00125 if (n_digits < len)
00126 {
00127 len = n_digits;
00128 if (n_bits)
00129 {
00130 result[n_digits] = self[n_digits] & ( (1u << n_bits) - 1u );
00131 ++n_digits;
00132 }
00133 }
00134 else if (n_digits > len)
00135 {
00136 n_digits = len;
00137 }
00138
00139 if (result != self) memcpy(result, self, len*sizeof(digit_t));
00140
00141 while (n_digits-- > 0)
00142 {
00143 if (self[n_digits] != 0) break;
00144 }
00145 return n_digits+1;
00146 }
00147
00169 void ymp_mul_2exp(mp_ref_t result, mp_cref_t self, size_t pow)
00170 {
00171 result->sign = self->sign;
00172 ymp_reserve(result, self->used+pow/DIGIT_BIT+1);
00173 result->used = ymp_lshiftabs(result->digits, self->digits, self->used, pow);
00174 }
00175
00176
00189 void ymp_div_2exp(mp_ref_t result, mp_cref_t self, size_t pow)
00190 {
00191 size_t n_shift_digits = pow/DIGIT_BIT;
00192
00193 if (self->used > n_shift_digits)
00194 {
00195 result->sign = self->sign;
00196 ymp_reserve(result, self->used - n_shift_digits);
00197 result->used
00198 = ymp_rshiftabs(result->digits, self->digits, self->used, pow);
00199 }
00200 else
00201 {
00202 result->used = 0;
00203 }
00204 }
00205
00206
00217 void ymp_mod_2exp(mp_ref_t result, mp_cref_t self, size_t pow)
00218 {
00219 size_t n_digits = pow / DIGIT_BIT;
00220 ymp_reserve(result, n_digits>self->used ? self->used : n_digits);
00221 result->sign = self->sign;
00222 result->used = ymp_modabs_2exp(result->digits, self->digits, self->used, pow);
00223 }
00224
00225