-
+ FFCEA4F2389EB4919DF50FC60423606D2835E4BE6A853FA885754CF04C397FE96D4A688ECCD591C60BC687846AE1E230304D3554B3E504E2E53662270342C591
mpi/mpi-add.c
(0 . 0)(1 . 246)
5986 /* mpi-add.c - MPI functions
5987 * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
5988 * Copyright (C) 1994, 1996 Free Software Foundation, Inc.
5989 *
5990 * This file is part of GnuPG.
5991 *
5992 * GnuPG is free software; you can redistribute it and/or modify
5993 * it under the terms of the GNU General Public License as published by
5994 * the Free Software Foundation; either version 3 of the License, or
5995 * (at your option) any later version.
5996 *
5997 * GnuPG is distributed in the hope that it will be useful,
5998 * but WITHOUT ANY WARRANTY; without even the implied warranty of
5999 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6000 * GNU General Public License for more details.
6001 *
6002 * You should have received a copy of the GNU General Public License
6003 * along with this program; if not, see <http://www.gnu.org/licenses/>.
6004 *
6005 * Note: This code is heavily based on the GNU MP Library.
6006 * Actually it's the same code with only minor changes in the
6007 * way the data is stored; this is to support the abstraction
6008 * of an optional secure memory allocation which may be used
6009 * to avoid revealing of sensitive data due to paging etc.
6010 * The GNU MP Library itself is published under the LGPL;
6011 * however I decided to publish this code under the plain GPL.
6012 */
6013
6014 #include <config.h>
6015 #include <stdio.h>
6016 #include <stdlib.h>
6017
6018 #include "mpi-internal.h"
6019
6020
6021 /****************
6022 * Add the unsigned integer V to the mpi-integer U and store the
6023 * result in W. U and V may be the same.
6024 */
6025 void
6026 mpi_add_ui(MPI w, MPI u, unsigned long v )
6027 {
6028 mpi_ptr_t wp, up;
6029 mpi_size_t usize, wsize;
6030 int usign, wsign;
6031
6032 usize = u->nlimbs;
6033 usign = u->sign;
6034 wsign = 0;
6035
6036 /* If not space for W (and possible carry), increase space. */
6037 wsize = usize + 1;
6038 if( w->alloced < wsize )
6039 mpi_resize(w, wsize);
6040
6041 /* These must be after realloc (U may be the same as W). */
6042 up = u->d;
6043 wp = w->d;
6044
6045 if( !usize ) { /* simple */
6046 wp[0] = v;
6047 wsize = v? 1:0;
6048 }
6049 else if( !usign ) { /* mpi is not negative */
6050 mpi_limb_t cy;
6051 cy = mpihelp_add_1(wp, up, usize, v);
6052 wp[usize] = cy;
6053 wsize = usize + cy;
6054 }
6055 else { /* The signs are different. Need exact comparison to determine
6056 * which operand to subtract from which. */
6057 if( usize == 1 && up[0] < v ) {
6058 wp[0] = v - up[0];
6059 wsize = 1;
6060 }
6061 else {
6062 mpihelp_sub_1(wp, up, usize, v);
6063 /* Size can decrease with at most one limb. */
6064 wsize = usize - (wp[usize-1]==0);
6065 wsign = 1;
6066 }
6067 }
6068
6069 w->nlimbs = wsize;
6070 w->sign = wsign;
6071 }
6072
6073
6074 void
6075 mpi_add(MPI w, MPI u, MPI v)
6076 {
6077 mpi_ptr_t wp, up, vp;
6078 mpi_size_t usize, vsize, wsize;
6079 int usign, vsign, wsign;
6080
6081 if( u->nlimbs < v->nlimbs ) { /* Swap U and V. */
6082 usize = v->nlimbs;
6083 usign = v->sign;
6084 vsize = u->nlimbs;
6085 vsign = u->sign;
6086 wsize = usize + 1;
6087 RESIZE_IF_NEEDED(w, wsize);
6088 /* These must be after realloc (u or v may be the same as w). */
6089 up = v->d;
6090 vp = u->d;
6091 }
6092 else {
6093 usize = u->nlimbs;
6094 usign = u->sign;
6095 vsize = v->nlimbs;
6096 vsign = v->sign;
6097 wsize = usize + 1;
6098 RESIZE_IF_NEEDED(w, wsize);
6099 /* These must be after realloc (u or v may be the same as w). */
6100 up = u->d;
6101 vp = v->d;
6102 }
6103 wp = w->d;
6104 wsign = 0;
6105
6106 if( !vsize ) { /* simple */
6107 MPN_COPY(wp, up, usize );
6108 wsize = usize;
6109 wsign = usign;
6110 }
6111 else if( usign != vsign ) { /* different sign */
6112 /* This test is right since USIZE >= VSIZE */
6113 if( usize != vsize ) {
6114 mpihelp_sub(wp, up, usize, vp, vsize);
6115 wsize = usize;
6116 MPN_NORMALIZE(wp, wsize);
6117 wsign = usign;
6118 }
6119 else if( mpihelp_cmp(up, vp, usize) < 0 ) {
6120 mpihelp_sub_n(wp, vp, up, usize);
6121 wsize = usize;
6122 MPN_NORMALIZE(wp, wsize);
6123 if( !usign )
6124 wsign = 1;
6125 }
6126 else {
6127 mpihelp_sub_n(wp, up, vp, usize);
6128 wsize = usize;
6129 MPN_NORMALIZE(wp, wsize);
6130 if( usign )
6131 wsign = 1;
6132 }
6133 }
6134 else { /* U and V have same sign. Add them. */
6135 mpi_limb_t cy = mpihelp_add(wp, up, usize, vp, vsize);
6136 wp[usize] = cy;
6137 wsize = usize + cy;
6138 if( usign )
6139 wsign = 1;
6140 }
6141
6142 w->nlimbs = wsize;
6143 w->sign = wsign;
6144 }
6145
6146
6147 /****************
6148 * Subtract the unsigned integer V from the mpi-integer U and store the
6149 * result in W.
6150 */
6151 void
6152 mpi_sub_ui(MPI w, MPI u, unsigned long v )
6153 {
6154 mpi_ptr_t wp, up;
6155 mpi_size_t usize, wsize;
6156 int usign, wsign;
6157
6158 usize = u->nlimbs;
6159 usign = u->sign;
6160 wsign = 0;
6161
6162 /* If not space for W (and possible carry), increase space. */
6163 wsize = usize + 1;
6164 if( w->alloced < wsize )
6165 mpi_resize(w, wsize);
6166
6167 /* These must be after realloc (U may be the same as W). */
6168 up = u->d;
6169 wp = w->d;
6170
6171 if( !usize ) { /* simple */
6172 wp[0] = v;
6173 wsize = v? 1:0;
6174 wsign = 1;
6175 }
6176 else if( usign ) { /* mpi and v are negative */
6177 mpi_limb_t cy;
6178 cy = mpihelp_add_1(wp, up, usize, v);
6179 wp[usize] = cy;
6180 wsize = usize + cy;
6181 }
6182 else { /* The signs are different. Need exact comparison to determine
6183 * which operand to subtract from which. */
6184 if( usize == 1 && up[0] < v ) {
6185 wp[0] = v - up[0];
6186 wsize = 1;
6187 wsign = 1;
6188 }
6189 else {
6190 mpihelp_sub_1(wp, up, usize, v);
6191 /* Size can decrease with at most one limb. */
6192 wsize = usize - (wp[usize-1]==0);
6193 }
6194 }
6195
6196 w->nlimbs = wsize;
6197 w->sign = wsign;
6198 }
6199
6200 void
6201 mpi_sub(MPI w, MPI u, MPI v)
6202 {
6203 if( w == v ) {
6204 MPI vv = mpi_copy(v);
6205 vv->sign = !vv->sign;
6206 mpi_add( w, u, vv );
6207 mpi_free(vv);
6208 }
6209 else {
6210 /* fixme: this is not thread-save (we temp. modify v) */
6211 v->sign = !v->sign;
6212 mpi_add( w, u, v );
6213 v->sign = !v->sign;
6214 }
6215 }
6216
6217
6218 void
6219 mpi_addm( MPI w, MPI u, MPI v, MPI m)
6220 {
6221 mpi_add(w, u, v);
6222 mpi_fdiv_r( w, w, m );
6223 }
6224
6225 void
6226 mpi_subm( MPI w, MPI u, MPI v, MPI m)
6227 {
6228 mpi_sub(w, u, v);
6229 mpi_fdiv_r( w, w, m );
6230 }
6231