-
+ 1D6A019FD026BF2712BE8E24EB9BAC995524336DF8EA4BF08878BDA3F95A943139E68381347974FEEA6DDAF3748ECD837FD698875324CB16C2AF13AF1E54BAA0
smg_comms/mpi/mpi-add.c
(0 . 0)(1 . 240)
3438 /* mpi-add.c - MPI functions
3439 * Modified by No Such Labs. (C) 2015. See README.
3440 *
3441 * This file was originally part of Gnu Privacy Guard (GPG), ver. 1.4.10,
3442 * SHA256(gnupg-1.4.10.tar.gz):
3443 * 0bfd74660a2f6cedcf7d8256db4a63c996ffebbcdc2cf54397bfb72878c5a85a
3444 * (C) 1994-2005 Free Software Foundation, Inc.
3445 *
3446 * This program is free software: you can redistribute it and/or modify
3447 * it under the terms of the GNU General Public License as published by
3448 * the Free Software Foundation, either version 3 of the License, or
3449 * (at your option) any later version.
3450 *
3451 * This program is distributed in the hope that it will be useful,
3452 * but WITHOUT ANY WARRANTY; without even the implied warranty of
3453 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3454 * GNU General Public License for more details.
3455 *
3456 * You should have received a copy of the GNU General Public License
3457 * along with this program. If not, see <http://www.gnu.org/licenses/>.
3458 */
3459
3460 #include <stdio.h>
3461 #include <stdlib.h>
3462
3463 #include "knobs.h"
3464 #include "mpi-internal.h"
3465
3466
3467 /****************
3468 * Add the unsigned integer V to the mpi-integer U and store the
3469 * result in W. U and V may be the same.
3470 */
3471 void
3472 mpi_add_ui(MPI w, MPI u, unsigned long v )
3473 {
3474 mpi_ptr_t wp, up;
3475 mpi_size_t usize, wsize;
3476 int usign, wsign;
3477
3478 usize = u->nlimbs;
3479 usign = u->sign;
3480 wsign = 0;
3481
3482 /* If not space for W (and possible carry), increase space. */
3483 wsize = usize + 1;
3484 if( w->alloced < wsize )
3485 mpi_resize(w, wsize);
3486
3487 /* These must be after realloc (U may be the same as W). */
3488 up = u->d;
3489 wp = w->d;
3490
3491 if( !usize ) { /* simple */
3492 wp[0] = v;
3493 wsize = v? 1:0;
3494 }
3495 else if( !usign ) { /* mpi is not negative */
3496 mpi_limb_t cy;
3497 cy = mpihelp_add_1(wp, up, usize, v);
3498 wp[usize] = cy;
3499 wsize = usize + cy;
3500 }
3501 else { /* The signs are different. Need exact comparison to determine
3502 * which operand to subtract from which. */
3503 if( usize == 1 && up[0] < v ) {
3504 wp[0] = v - up[0];
3505 wsize = 1;
3506 }
3507 else {
3508 mpihelp_sub_1(wp, up, usize, v);
3509 /* Size can decrease with at most one limb. */
3510 wsize = usize - (wp[usize-1]==0);
3511 wsign = 1;
3512 }
3513 }
3514
3515 w->nlimbs = wsize;
3516 w->sign = wsign;
3517 }
3518
3519
3520 void
3521 mpi_add(MPI w, MPI u, MPI v)
3522 {
3523 mpi_ptr_t wp, up, vp;
3524 mpi_size_t usize, vsize, wsize;
3525 int usign, vsign, wsign;
3526
3527 if( u->nlimbs < v->nlimbs ) { /* Swap U and V. */
3528 usize = v->nlimbs;
3529 usign = v->sign;
3530 vsize = u->nlimbs;
3531 vsign = u->sign;
3532 wsize = usize + 1;
3533 RESIZE_IF_NEEDED(w, wsize);
3534 /* These must be after realloc (u or v may be the same as w). */
3535 up = v->d;
3536 vp = u->d;
3537 }
3538 else {
3539 usize = u->nlimbs;
3540 usign = u->sign;
3541 vsize = v->nlimbs;
3542 vsign = v->sign;
3543 wsize = usize + 1;
3544 RESIZE_IF_NEEDED(w, wsize);
3545 /* These must be after realloc (u or v may be the same as w). */
3546 up = u->d;
3547 vp = v->d;
3548 }
3549 wp = w->d;
3550 wsign = 0;
3551
3552 if( !vsize ) { /* simple */
3553 MPN_COPY(wp, up, usize );
3554 wsize = usize;
3555 wsign = usign;
3556 }
3557 else if( usign != vsign ) { /* different sign */
3558 /* This test is right since USIZE >= VSIZE */
3559 if( usize != vsize ) {
3560 mpihelp_sub(wp, up, usize, vp, vsize);
3561 wsize = usize;
3562 MPN_NORMALIZE(wp, wsize);
3563 wsign = usign;
3564 }
3565 else if( mpihelp_cmp(up, vp, usize) < 0 ) {
3566 mpihelp_sub_n(wp, vp, up, usize);
3567 wsize = usize;
3568 MPN_NORMALIZE(wp, wsize);
3569 if( !usign )
3570 wsign = 1;
3571 }
3572 else {
3573 mpihelp_sub_n(wp, up, vp, usize);
3574 wsize = usize;
3575 MPN_NORMALIZE(wp, wsize);
3576 if( usign )
3577 wsign = 1;
3578 }
3579 }
3580 else { /* U and V have same sign. Add them. */
3581 mpi_limb_t cy = mpihelp_add(wp, up, usize, vp, vsize);
3582 wp[usize] = cy;
3583 wsize = usize + cy;
3584 if( usign )
3585 wsign = 1;
3586 }
3587
3588 w->nlimbs = wsize;
3589 w->sign = wsign;
3590 }
3591
3592
3593 /****************
3594 * Subtract the unsigned integer V from the mpi-integer U and store the
3595 * result in W.
3596 */
3597 void
3598 mpi_sub_ui(MPI w, MPI u, unsigned long v )
3599 {
3600 mpi_ptr_t wp, up;
3601 mpi_size_t usize, wsize;
3602 int usign, wsign;
3603
3604 usize = u->nlimbs;
3605 usign = u->sign;
3606 wsign = 0;
3607
3608 /* If not space for W (and possible carry), increase space. */
3609 wsize = usize + 1;
3610 if( w->alloced < wsize )
3611 mpi_resize(w, wsize);
3612
3613 /* These must be after realloc (U may be the same as W). */
3614 up = u->d;
3615 wp = w->d;
3616
3617 if( !usize ) { /* simple */
3618 wp[0] = v;
3619 wsize = v? 1:0;
3620 wsign = 1;
3621 }
3622 else if( usign ) { /* mpi and v are negative */
3623 mpi_limb_t cy;
3624 cy = mpihelp_add_1(wp, up, usize, v);
3625 wp[usize] = cy;
3626 wsize = usize + cy;
3627 }
3628 else { /* The signs are different. Need exact comparison to determine
3629 * which operand to subtract from which. */
3630 if( usize == 1 && up[0] < v ) {
3631 wp[0] = v - up[0];
3632 wsize = 1;
3633 wsign = 1;
3634 }
3635 else {
3636 mpihelp_sub_1(wp, up, usize, v);
3637 /* Size can decrease with at most one limb. */
3638 wsize = usize - (wp[usize-1]==0);
3639 }
3640 }
3641
3642 w->nlimbs = wsize;
3643 w->sign = wsign;
3644 }
3645
3646 void
3647 mpi_sub(MPI w, MPI u, MPI v)
3648 {
3649 if( w == v ) {
3650 MPI vv = mpi_copy(v);
3651 vv->sign = !vv->sign;
3652 mpi_add( w, u, vv );
3653 mpi_free(vv);
3654 }
3655 else {
3656 /* fixme: this is not thread-save (we temp. modify v) */
3657 v->sign = !v->sign;
3658 mpi_add( w, u, v );
3659 v->sign = !v->sign;
3660 }
3661 }
3662
3663
3664 void
3665 mpi_addm( MPI w, MPI u, MPI v, MPI m)
3666 {
3667 mpi_add(w, u, v);
3668 mpi_fdiv_r( w, w, m );
3669 }
3670
3671 void
3672 mpi_subm( MPI w, MPI u, MPI v, MPI m)
3673 {
3674 mpi_sub(w, u, v);
3675 mpi_fdiv_r( w, w, m );
3676 }
3677