-
+ 4C816E02A36ADBCAE224E0F6ECBEF7D46811A2ADD9D33B677165936BEE0D5E8B4900490904C25E0EAE3E8616CC3BD7F7DF13269EA4ADDE641814BE563F820667
smg_comms/mpi/mpi-div.c
(0 . 0)(1 . 316)
4029 /* mpi-div.c - MPI functions
4030 * Modified by No Such Labs. (C) 2015. See README.
4031 *
4032 * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10,
4033 * SHA256(gnupg-1.4.10.tar.gz):
4034 * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a
4035 * (C) 1994-2005 Free Software Foundation, Inc.
4036 *
4037 * This program is free software: you can redistribute it and/or modify
4038 * it under the terms of the GNU General Public License as published by
4039 * the Free Software Foundation, either version 3 of the License, or
4040 * (at your option) any later version.
4041 *
4042 * This program is distributed in the hope that it will be useful,
4043 * but WITHOUT ANY WARRANTY; without even the implied warranty of
4044 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4045 * GNU General Public License for more details.
4046 *
4047 * You should have received a copy of the GNU General Public License
4048 * along with this program. If not, see <http://www.gnu.org/licenses/>.
4049 */
4050
4051 #include <stdio.h>
4052 #include <stdlib.h>
4053
4054 #include "knobs.h"
4055 #include "mpi-internal.h"
4056 #include "longlong.h"
4057
4058
4059
4060 void
4061 mpi_fdiv_r( MPI rem, MPI dividend, MPI divisor )
4062 {
4063 int divisor_sign = divisor->sign;
4064 MPI temp_divisor = NULL;
4065
4066 /* We need the original value of the divisor after the remainder has been
4067 * preliminary calculated. We have to copy it to temporary space if it's
4068 * the same variable as REM. */
4069 if( rem == divisor ) {
4070 temp_divisor = mpi_copy( divisor );
4071 divisor = temp_divisor;
4072 }
4073
4074 mpi_tdiv_r( rem, dividend, divisor );
4075
4076 if( ((divisor_sign?1:0) ^ (dividend->sign?1:0)) && rem->nlimbs )
4077 mpi_add( rem, rem, divisor);
4078
4079 if( temp_divisor )
4080 mpi_free(temp_divisor);
4081 }
4082
4083
4084
4085 /****************
4086 * Division rounding the quotient towards -infinity.
4087 * The remainder gets the same sign as the denominator.
4088 * rem is optional
4089 */
4090
4091 ulong
4092 mpi_fdiv_r_ui( MPI rem, MPI dividend, ulong divisor )
4093 {
4094 mpi_limb_t rlimb;
4095
4096 rlimb = mpihelp_mod_1( dividend->d, dividend->nlimbs, divisor );
4097 if( rlimb && dividend->sign )
4098 rlimb = divisor - rlimb;
4099
4100 if( rem ) {
4101 rem->d[0] = rlimb;
4102 rem->nlimbs = rlimb? 1:0;
4103 }
4104 return rlimb;
4105 }
4106
4107
4108 void
4109 mpi_fdiv_q( MPI quot, MPI dividend, MPI divisor )
4110 {
4111 MPI tmp = mpi_alloc( mpi_get_nlimbs(quot) );
4112 mpi_fdiv_qr( quot, tmp, dividend, divisor);
4113 mpi_free(tmp);
4114 }
4115
4116 void
4117 mpi_fdiv_qr( MPI quot, MPI rem, MPI dividend, MPI divisor )
4118 {
4119 int divisor_sign = divisor->sign;
4120 MPI temp_divisor = NULL;
4121
4122 if( quot == divisor || rem == divisor ) {
4123 temp_divisor = mpi_copy( divisor );
4124 divisor = temp_divisor;
4125 }
4126
4127 mpi_tdiv_qr( quot, rem, dividend, divisor );
4128
4129 if( (divisor_sign ^ dividend->sign) && rem->nlimbs ) {
4130 mpi_sub_ui( quot, quot, 1 );
4131 mpi_add( rem, rem, divisor);
4132 }
4133
4134 if( temp_divisor )
4135 mpi_free(temp_divisor);
4136 }
4137
4138
4139 /* If den == quot, den needs temporary storage.
4140 * If den == rem, den needs temporary storage.
4141 * If num == quot, num needs temporary storage.
4142 * If den has temporary storage, it can be normalized while being copied,
4143 * i.e no extra storage should be allocated.
4144 */
4145
4146 void
4147 mpi_tdiv_r( MPI rem, MPI num, MPI den)
4148 {
4149 mpi_tdiv_qr(NULL, rem, num, den );
4150 }
4151
4152 void
4153 mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den)
4154 {
4155 mpi_ptr_t np, dp;
4156 mpi_ptr_t qp, rp;
4157 mpi_size_t nsize = num->nlimbs;
4158 mpi_size_t dsize = den->nlimbs;
4159 mpi_size_t qsize, rsize;
4160 mpi_size_t sign_remainder = num->sign;
4161 mpi_size_t sign_quotient = num->sign ^ den->sign;
4162 unsigned normalization_steps;
4163 mpi_limb_t q_limb;
4164 mpi_ptr_t marker[5];
4165 int markidx=0;
4166
4167 /* Ensure space is enough for quotient and remainder.
4168 * We need space for an extra limb in the remainder, because it's
4169 * up-shifted (normalized) below. */
4170 rsize = nsize + 1;
4171 mpi_resize( rem, rsize);
4172
4173 qsize = rsize - dsize; /* qsize cannot be bigger than this. */
4174 if( qsize <= 0 ) {
4175 if( num != rem ) {
4176 rem->nlimbs = num->nlimbs;
4177 rem->sign = num->sign;
4178 MPN_COPY(rem->d, num->d, nsize);
4179 }
4180 if( quot ) {
4181 /* This needs to follow the assignment to rem, in case the
4182 * numerator and quotient are the same. */
4183 quot->nlimbs = 0;
4184 quot->sign = 0;
4185 }
4186 return;
4187 }
4188
4189 if( quot )
4190 mpi_resize( quot, qsize);
4191
4192 /* Read pointers here, when reallocation is finished. */
4193 np = num->d;
4194 dp = den->d;
4195 rp = rem->d;
4196
4197 /* Optimize division by a single-limb divisor. */
4198 if( dsize == 1 ) {
4199 mpi_limb_t rlimb;
4200 if( quot ) {
4201 qp = quot->d;
4202 rlimb = mpihelp_divmod_1( qp, np, nsize, dp[0] );
4203 qsize -= qp[qsize - 1] == 0;
4204 quot->nlimbs = qsize;
4205 quot->sign = sign_quotient;
4206 }
4207 else
4208 rlimb = mpihelp_mod_1( np, nsize, dp[0] );
4209 rp[0] = rlimb;
4210 rsize = rlimb != 0?1:0;
4211 rem->nlimbs = rsize;
4212 rem->sign = sign_remainder;
4213 return;
4214 }
4215
4216
4217 if( quot ) {
4218 qp = quot->d;
4219 /* Make sure QP and NP point to different objects. Otherwise the
4220 * numerator would be gradually overwritten by the quotient limbs. */
4221 if(qp == np) { /* Copy NP object to temporary space. */
4222 np = marker[markidx++] = mpi_alloc_limb_space(nsize,
4223 mpi_is_secure(quot));
4224 MPN_COPY(np, qp, nsize);
4225 }
4226 }
4227 else /* Put quotient at top of remainder. */
4228 qp = rp + dsize;
4229
4230 count_leading_zeros( normalization_steps, dp[dsize - 1] );
4231
4232 /* Normalize the denominator, i.e. make its most significant bit set by
4233 * shifting it NORMALIZATION_STEPS bits to the left. Also shift the
4234 * numerator the same number of steps (to keep the quotient the same!).
4235 */
4236 if( normalization_steps ) {
4237 mpi_ptr_t tp;
4238 mpi_limb_t nlimb;
4239
4240 /* Shift up the denominator setting the most significant bit of
4241 * the most significant word. Use temporary storage not to clobber
4242 * the original contents of the denominator. */
4243 tp = marker[markidx++] = mpi_alloc_limb_space(dsize,mpi_is_secure(den));
4244 mpihelp_lshift( tp, dp, dsize, normalization_steps );
4245 dp = tp;
4246
4247 /* Shift up the numerator, possibly introducing a new most
4248 * significant word. Move the shifted numerator in the remainder
4249 * meanwhile. */
4250 nlimb = mpihelp_lshift(rp, np, nsize, normalization_steps);
4251 if( nlimb ) {
4252 rp[nsize] = nlimb;
4253 rsize = nsize + 1;
4254 }
4255 else
4256 rsize = nsize;
4257 }
4258 else {
4259 /* The denominator is already normalized, as required. Copy it to
4260 * temporary space if it overlaps with the quotient or remainder. */
4261 if( dp == rp || (quot && (dp == qp))) {
4262 mpi_ptr_t tp;
4263
4264 tp = marker[markidx++] = mpi_alloc_limb_space(dsize, mpi_is_secure(den));
4265 MPN_COPY( tp, dp, dsize );
4266 dp = tp;
4267 }
4268
4269 /* Move the numerator to the remainder. */
4270 if( rp != np )
4271 MPN_COPY(rp, np, nsize);
4272
4273 rsize = nsize;
4274 }
4275
4276 q_limb = mpihelp_divrem( qp, 0, rp, rsize, dp, dsize );
4277
4278 if( quot ) {
4279 qsize = rsize - dsize;
4280 if(q_limb) {
4281 qp[qsize] = q_limb;
4282 qsize += 1;
4283 }
4284
4285 quot->nlimbs = qsize;
4286 quot->sign = sign_quotient;
4287 }
4288
4289 rsize = dsize;
4290 MPN_NORMALIZE (rp, rsize);
4291
4292 if( normalization_steps && rsize ) {
4293 mpihelp_rshift(rp, rp, rsize, normalization_steps);
4294 rsize -= rp[rsize - 1] == 0?1:0;
4295 }
4296
4297 rem->nlimbs = rsize;
4298 rem->sign = sign_remainder;
4299 while( markidx )
4300 mpi_free_limb_space(marker[--markidx]);
4301 }
4302
4303 void
4304 mpi_tdiv_q_2exp( MPI w, MPI u, unsigned count )
4305 {
4306 mpi_size_t usize, wsize;
4307 mpi_size_t limb_cnt;
4308
4309 usize = u->nlimbs;
4310 limb_cnt = count / BITS_PER_MPI_LIMB;
4311 wsize = usize - limb_cnt;
4312 if( limb_cnt >= usize )
4313 w->nlimbs = 0;
4314 else {
4315 mpi_ptr_t wp;
4316 mpi_ptr_t up;
4317
4318 RESIZE_IF_NEEDED( w, wsize );
4319 wp = w->d;
4320 up = u->d;
4321
4322 count %= BITS_PER_MPI_LIMB;
4323 if( count ) {
4324 mpihelp_rshift( wp, up + limb_cnt, wsize, count );
4325 wsize -= !wp[wsize - 1];
4326 }
4327 else {
4328 MPN_COPY_INCR( wp, up + limb_cnt, wsize);
4329 }
4330
4331 w->nlimbs = wsize;
4332 }
4333 }
4334
4335 /****************
4336 * Check whether dividend is divisible by divisor
4337 * (note: divisor must fit into a limb)
4338 */
4339 int
4340 mpi_divisible_ui(MPI dividend, ulong divisor )
4341 {
4342 return !mpihelp_mod_1( dividend->d, dividend->nlimbs, divisor );
4343 }
4344