-
+ 4C816E02A36ADBCAE224E0F6ECBEF7D46811A2ADD9D33B677165936BEE0D5E8B4900490904C25E0EAE3E8616CC3BD7F7DF13269EA4ADDE641814BE563F820667
eucrypt/mpi/mpi-div.c
(0 . 0)(1 . 316)
3290 /* mpi-div.c - MPI functions
3291 * Modified by No Such Labs. (C) 2015. See README.
3292 *
3293 * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10,
3294 * SHA256(gnupg-1.4.10.tar.gz):
3295 * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a
3296 * (C) 1994-2005 Free Software Foundation, Inc.
3297 *
3298 * This program is free software: you can redistribute it and/or modify
3299 * it under the terms of the GNU General Public License as published by
3300 * the Free Software Foundation, either version 3 of the License, or
3301 * (at your option) any later version.
3302 *
3303 * This program is distributed in the hope that it will be useful,
3304 * but WITHOUT ANY WARRANTY; without even the implied warranty of
3305 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3306 * GNU General Public License for more details.
3307 *
3308 * You should have received a copy of the GNU General Public License
3309 * along with this program. If not, see <http://www.gnu.org/licenses/>.
3310 */
3311
3312 #include <stdio.h>
3313 #include <stdlib.h>
3314
3315 #include "knobs.h"
3316 #include "mpi-internal.h"
3317 #include "longlong.h"
3318
3319
3320
3321 void
3322 mpi_fdiv_r( MPI rem, MPI dividend, MPI divisor )
3323 {
3324 int divisor_sign = divisor->sign;
3325 MPI temp_divisor = NULL;
3326
3327 /* We need the original value of the divisor after the remainder has been
3328 * preliminary calculated. We have to copy it to temporary space if it's
3329 * the same variable as REM. */
3330 if( rem == divisor ) {
3331 temp_divisor = mpi_copy( divisor );
3332 divisor = temp_divisor;
3333 }
3334
3335 mpi_tdiv_r( rem, dividend, divisor );
3336
3337 if( ((divisor_sign?1:0) ^ (dividend->sign?1:0)) && rem->nlimbs )
3338 mpi_add( rem, rem, divisor);
3339
3340 if( temp_divisor )
3341 mpi_free(temp_divisor);
3342 }
3343
3344
3345
3346 /****************
3347 * Division rounding the quotient towards -infinity.
3348 * The remainder gets the same sign as the denominator.
3349 * rem is optional
3350 */
3351
3352 ulong
3353 mpi_fdiv_r_ui( MPI rem, MPI dividend, ulong divisor )
3354 {
3355 mpi_limb_t rlimb;
3356
3357 rlimb = mpihelp_mod_1( dividend->d, dividend->nlimbs, divisor );
3358 if( rlimb && dividend->sign )
3359 rlimb = divisor - rlimb;
3360
3361 if( rem ) {
3362 rem->d[0] = rlimb;
3363 rem->nlimbs = rlimb? 1:0;
3364 }
3365 return rlimb;
3366 }
3367
3368
3369 void
3370 mpi_fdiv_q( MPI quot, MPI dividend, MPI divisor )
3371 {
3372 MPI tmp = mpi_alloc( mpi_get_nlimbs(quot) );
3373 mpi_fdiv_qr( quot, tmp, dividend, divisor);
3374 mpi_free(tmp);
3375 }
3376
3377 void
3378 mpi_fdiv_qr( MPI quot, MPI rem, MPI dividend, MPI divisor )
3379 {
3380 int divisor_sign = divisor->sign;
3381 MPI temp_divisor = NULL;
3382
3383 if( quot == divisor || rem == divisor ) {
3384 temp_divisor = mpi_copy( divisor );
3385 divisor = temp_divisor;
3386 }
3387
3388 mpi_tdiv_qr( quot, rem, dividend, divisor );
3389
3390 if( (divisor_sign ^ dividend->sign) && rem->nlimbs ) {
3391 mpi_sub_ui( quot, quot, 1 );
3392 mpi_add( rem, rem, divisor);
3393 }
3394
3395 if( temp_divisor )
3396 mpi_free(temp_divisor);
3397 }
3398
3399
3400 /* If den == quot, den needs temporary storage.
3401 * If den == rem, den needs temporary storage.
3402 * If num == quot, num needs temporary storage.
3403 * If den has temporary storage, it can be normalized while being copied,
3404 * i.e no extra storage should be allocated.
3405 */
3406
3407 void
3408 mpi_tdiv_r( MPI rem, MPI num, MPI den)
3409 {
3410 mpi_tdiv_qr(NULL, rem, num, den );
3411 }
3412
3413 void
3414 mpi_tdiv_qr( MPI quot, MPI rem, MPI num, MPI den)
3415 {
3416 mpi_ptr_t np, dp;
3417 mpi_ptr_t qp, rp;
3418 mpi_size_t nsize = num->nlimbs;
3419 mpi_size_t dsize = den->nlimbs;
3420 mpi_size_t qsize, rsize;
3421 mpi_size_t sign_remainder = num->sign;
3422 mpi_size_t sign_quotient = num->sign ^ den->sign;
3423 unsigned normalization_steps;
3424 mpi_limb_t q_limb;
3425 mpi_ptr_t marker[5];
3426 int markidx=0;
3427
3428 /* Ensure space is enough for quotient and remainder.
3429 * We need space for an extra limb in the remainder, because it's
3430 * up-shifted (normalized) below. */
3431 rsize = nsize + 1;
3432 mpi_resize( rem, rsize);
3433
3434 qsize = rsize - dsize; /* qsize cannot be bigger than this. */
3435 if( qsize <= 0 ) {
3436 if( num != rem ) {
3437 rem->nlimbs = num->nlimbs;
3438 rem->sign = num->sign;
3439 MPN_COPY(rem->d, num->d, nsize);
3440 }
3441 if( quot ) {
3442 /* This needs to follow the assignment to rem, in case the
3443 * numerator and quotient are the same. */
3444 quot->nlimbs = 0;
3445 quot->sign = 0;
3446 }
3447 return;
3448 }
3449
3450 if( quot )
3451 mpi_resize( quot, qsize);
3452
3453 /* Read pointers here, when reallocation is finished. */
3454 np = num->d;
3455 dp = den->d;
3456 rp = rem->d;
3457
3458 /* Optimize division by a single-limb divisor. */
3459 if( dsize == 1 ) {
3460 mpi_limb_t rlimb;
3461 if( quot ) {
3462 qp = quot->d;
3463 rlimb = mpihelp_divmod_1( qp, np, nsize, dp[0] );
3464 qsize -= qp[qsize - 1] == 0;
3465 quot->nlimbs = qsize;
3466 quot->sign = sign_quotient;
3467 }
3468 else
3469 rlimb = mpihelp_mod_1( np, nsize, dp[0] );
3470 rp[0] = rlimb;
3471 rsize = rlimb != 0?1:0;
3472 rem->nlimbs = rsize;
3473 rem->sign = sign_remainder;
3474 return;
3475 }
3476
3477
3478 if( quot ) {
3479 qp = quot->d;
3480 /* Make sure QP and NP point to different objects. Otherwise the
3481 * numerator would be gradually overwritten by the quotient limbs. */
3482 if(qp == np) { /* Copy NP object to temporary space. */
3483 np = marker[markidx++] = mpi_alloc_limb_space(nsize,
3484 mpi_is_secure(quot));
3485 MPN_COPY(np, qp, nsize);
3486 }
3487 }
3488 else /* Put quotient at top of remainder. */
3489 qp = rp + dsize;
3490
3491 count_leading_zeros( normalization_steps, dp[dsize - 1] );
3492
3493 /* Normalize the denominator, i.e. make its most significant bit set by
3494 * shifting it NORMALIZATION_STEPS bits to the left. Also shift the
3495 * numerator the same number of steps (to keep the quotient the same!).
3496 */
3497 if( normalization_steps ) {
3498 mpi_ptr_t tp;
3499 mpi_limb_t nlimb;
3500
3501 /* Shift up the denominator setting the most significant bit of
3502 * the most significant word. Use temporary storage not to clobber
3503 * the original contents of the denominator. */
3504 tp = marker[markidx++] = mpi_alloc_limb_space(dsize,mpi_is_secure(den));
3505 mpihelp_lshift( tp, dp, dsize, normalization_steps );
3506 dp = tp;
3507
3508 /* Shift up the numerator, possibly introducing a new most
3509 * significant word. Move the shifted numerator in the remainder
3510 * meanwhile. */
3511 nlimb = mpihelp_lshift(rp, np, nsize, normalization_steps);
3512 if( nlimb ) {
3513 rp[nsize] = nlimb;
3514 rsize = nsize + 1;
3515 }
3516 else
3517 rsize = nsize;
3518 }
3519 else {
3520 /* The denominator is already normalized, as required. Copy it to
3521 * temporary space if it overlaps with the quotient or remainder. */
3522 if( dp == rp || (quot && (dp == qp))) {
3523 mpi_ptr_t tp;
3524
3525 tp = marker[markidx++] = mpi_alloc_limb_space(dsize, mpi_is_secure(den));
3526 MPN_COPY( tp, dp, dsize );
3527 dp = tp;
3528 }
3529
3530 /* Move the numerator to the remainder. */
3531 if( rp != np )
3532 MPN_COPY(rp, np, nsize);
3533
3534 rsize = nsize;
3535 }
3536
3537 q_limb = mpihelp_divrem( qp, 0, rp, rsize, dp, dsize );
3538
3539 if( quot ) {
3540 qsize = rsize - dsize;
3541 if(q_limb) {
3542 qp[qsize] = q_limb;
3543 qsize += 1;
3544 }
3545
3546 quot->nlimbs = qsize;
3547 quot->sign = sign_quotient;
3548 }
3549
3550 rsize = dsize;
3551 MPN_NORMALIZE (rp, rsize);
3552
3553 if( normalization_steps && rsize ) {
3554 mpihelp_rshift(rp, rp, rsize, normalization_steps);
3555 rsize -= rp[rsize - 1] == 0?1:0;
3556 }
3557
3558 rem->nlimbs = rsize;
3559 rem->sign = sign_remainder;
3560 while( markidx )
3561 mpi_free_limb_space(marker[--markidx]);
3562 }
3563
3564 void
3565 mpi_tdiv_q_2exp( MPI w, MPI u, unsigned count )
3566 {
3567 mpi_size_t usize, wsize;
3568 mpi_size_t limb_cnt;
3569
3570 usize = u->nlimbs;
3571 limb_cnt = count / BITS_PER_MPI_LIMB;
3572 wsize = usize - limb_cnt;
3573 if( limb_cnt >= usize )
3574 w->nlimbs = 0;
3575 else {
3576 mpi_ptr_t wp;
3577 mpi_ptr_t up;
3578
3579 RESIZE_IF_NEEDED( w, wsize );
3580 wp = w->d;
3581 up = u->d;
3582
3583 count %= BITS_PER_MPI_LIMB;
3584 if( count ) {
3585 mpihelp_rshift( wp, up + limb_cnt, wsize, count );
3586 wsize -= !wp[wsize - 1];
3587 }
3588 else {
3589 MPN_COPY_INCR( wp, up + limb_cnt, wsize);
3590 }
3591
3592 w->nlimbs = wsize;
3593 }
3594 }
3595
3596 /****************
3597 * Check whether dividend is divisible by divisor
3598 * (note: divisor must fit into a limb)
3599 */
3600 int
3601 mpi_divisible_ui(MPI dividend, ulong divisor )
3602 {
3603 return !mpihelp_mod_1( dividend->d, dividend->nlimbs, divisor );
3604 }
3605