-
+ FFCEA4F2389EB4919DF50FC60423606D2835E4BE6A853FA885754CF04C397FE96D4A688ECCD591C60BC687846AE1E230304D3554B3E504E2E53662270342C591
mpi/mpi-add.c
(0 . 0)(1 . 246)
6061 /* mpi-add.c - MPI functions
6062 * Copyright (C) 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
6063 * Copyright (C) 1994, 1996 Free Software Foundation, Inc.
6064 *
6065 * This file is part of GnuPG.
6066 *
6067 * GnuPG is free software; you can redistribute it and/or modify
6068 * it under the terms of the GNU General Public License as published by
6069 * the Free Software Foundation; either version 3 of the License, or
6070 * (at your option) any later version.
6071 *
6072 * GnuPG is distributed in the hope that it will be useful,
6073 * but WITHOUT ANY WARRANTY; without even the implied warranty of
6074 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6075 * GNU General Public License for more details.
6076 *
6077 * You should have received a copy of the GNU General Public License
6078 * along with this program; if not, see <http://www.gnu.org/licenses/>.
6079 *
6080 * Note: This code is heavily based on the GNU MP Library.
6081 * Actually it's the same code with only minor changes in the
6082 * way the data is stored; this is to support the abstraction
6083 * of an optional secure memory allocation which may be used
6084 * to avoid revealing of sensitive data due to paging etc.
6085 * The GNU MP Library itself is published under the LGPL;
6086 * however I decided to publish this code under the plain GPL.
6087 */
6088
6089 #include <config.h>
6090 #include <stdio.h>
6091 #include <stdlib.h>
6092
6093 #include "mpi-internal.h"
6094
6095
6096 /****************
6097 * Add the unsigned integer V to the mpi-integer U and store the
6098 * result in W. U and V may be the same.
6099 */
6100 void
6101 mpi_add_ui(MPI w, MPI u, unsigned long v )
6102 {
6103 mpi_ptr_t wp, up;
6104 mpi_size_t usize, wsize;
6105 int usign, wsign;
6106
6107 usize = u->nlimbs;
6108 usign = u->sign;
6109 wsign = 0;
6110
6111 /* If not space for W (and possible carry), increase space. */
6112 wsize = usize + 1;
6113 if( w->alloced < wsize )
6114 mpi_resize(w, wsize);
6115
6116 /* These must be after realloc (U may be the same as W). */
6117 up = u->d;
6118 wp = w->d;
6119
6120 if( !usize ) { /* simple */
6121 wp[0] = v;
6122 wsize = v? 1:0;
6123 }
6124 else if( !usign ) { /* mpi is not negative */
6125 mpi_limb_t cy;
6126 cy = mpihelp_add_1(wp, up, usize, v);
6127 wp[usize] = cy;
6128 wsize = usize + cy;
6129 }
6130 else { /* The signs are different. Need exact comparison to determine
6131 * which operand to subtract from which. */
6132 if( usize == 1 && up[0] < v ) {
6133 wp[0] = v - up[0];
6134 wsize = 1;
6135 }
6136 else {
6137 mpihelp_sub_1(wp, up, usize, v);
6138 /* Size can decrease with at most one limb. */
6139 wsize = usize - (wp[usize-1]==0);
6140 wsign = 1;
6141 }
6142 }
6143
6144 w->nlimbs = wsize;
6145 w->sign = wsign;
6146 }
6147
6148
6149 void
6150 mpi_add(MPI w, MPI u, MPI v)
6151 {
6152 mpi_ptr_t wp, up, vp;
6153 mpi_size_t usize, vsize, wsize;
6154 int usign, vsign, wsign;
6155
6156 if( u->nlimbs < v->nlimbs ) { /* Swap U and V. */
6157 usize = v->nlimbs;
6158 usign = v->sign;
6159 vsize = u->nlimbs;
6160 vsign = u->sign;
6161 wsize = usize + 1;
6162 RESIZE_IF_NEEDED(w, wsize);
6163 /* These must be after realloc (u or v may be the same as w). */
6164 up = v->d;
6165 vp = u->d;
6166 }
6167 else {
6168 usize = u->nlimbs;
6169 usign = u->sign;
6170 vsize = v->nlimbs;
6171 vsign = v->sign;
6172 wsize = usize + 1;
6173 RESIZE_IF_NEEDED(w, wsize);
6174 /* These must be after realloc (u or v may be the same as w). */
6175 up = u->d;
6176 vp = v->d;
6177 }
6178 wp = w->d;
6179 wsign = 0;
6180
6181 if( !vsize ) { /* simple */
6182 MPN_COPY(wp, up, usize );
6183 wsize = usize;
6184 wsign = usign;
6185 }
6186 else if( usign != vsign ) { /* different sign */
6187 /* This test is right since USIZE >= VSIZE */
6188 if( usize != vsize ) {
6189 mpihelp_sub(wp, up, usize, vp, vsize);
6190 wsize = usize;
6191 MPN_NORMALIZE(wp, wsize);
6192 wsign = usign;
6193 }
6194 else if( mpihelp_cmp(up, vp, usize) < 0 ) {
6195 mpihelp_sub_n(wp, vp, up, usize);
6196 wsize = usize;
6197 MPN_NORMALIZE(wp, wsize);
6198 if( !usign )
6199 wsign = 1;
6200 }
6201 else {
6202 mpihelp_sub_n(wp, up, vp, usize);
6203 wsize = usize;
6204 MPN_NORMALIZE(wp, wsize);
6205 if( usign )
6206 wsign = 1;
6207 }
6208 }
6209 else { /* U and V have same sign. Add them. */
6210 mpi_limb_t cy = mpihelp_add(wp, up, usize, vp, vsize);
6211 wp[usize] = cy;
6212 wsize = usize + cy;
6213 if( usign )
6214 wsign = 1;
6215 }
6216
6217 w->nlimbs = wsize;
6218 w->sign = wsign;
6219 }
6220
6221
6222 /****************
6223 * Subtract the unsigned integer V from the mpi-integer U and store the
6224 * result in W.
6225 */
6226 void
6227 mpi_sub_ui(MPI w, MPI u, unsigned long v )
6228 {
6229 mpi_ptr_t wp, up;
6230 mpi_size_t usize, wsize;
6231 int usign, wsign;
6232
6233 usize = u->nlimbs;
6234 usign = u->sign;
6235 wsign = 0;
6236
6237 /* If not space for W (and possible carry), increase space. */
6238 wsize = usize + 1;
6239 if( w->alloced < wsize )
6240 mpi_resize(w, wsize);
6241
6242 /* These must be after realloc (U may be the same as W). */
6243 up = u->d;
6244 wp = w->d;
6245
6246 if( !usize ) { /* simple */
6247 wp[0] = v;
6248 wsize = v? 1:0;
6249 wsign = 1;
6250 }
6251 else if( usign ) { /* mpi and v are negative */
6252 mpi_limb_t cy;
6253 cy = mpihelp_add_1(wp, up, usize, v);
6254 wp[usize] = cy;
6255 wsize = usize + cy;
6256 }
6257 else { /* The signs are different. Need exact comparison to determine
6258 * which operand to subtract from which. */
6259 if( usize == 1 && up[0] < v ) {
6260 wp[0] = v - up[0];
6261 wsize = 1;
6262 wsign = 1;
6263 }
6264 else {
6265 mpihelp_sub_1(wp, up, usize, v);
6266 /* Size can decrease with at most one limb. */
6267 wsize = usize - (wp[usize-1]==0);
6268 }
6269 }
6270
6271 w->nlimbs = wsize;
6272 w->sign = wsign;
6273 }
6274
6275 void
6276 mpi_sub(MPI w, MPI u, MPI v)
6277 {
6278 if( w == v ) {
6279 MPI vv = mpi_copy(v);
6280 vv->sign = !vv->sign;
6281 mpi_add( w, u, vv );
6282 mpi_free(vv);
6283 }
6284 else {
6285 /* fixme: this is not thread-save (we temp. modify v) */
6286 v->sign = !v->sign;
6287 mpi_add( w, u, v );
6288 v->sign = !v->sign;
6289 }
6290 }
6291
6292
6293 void
6294 mpi_addm( MPI w, MPI u, MPI v, MPI m)
6295 {
6296 mpi_add(w, u, v);
6297 mpi_fdiv_r( w, w, m );
6298 }
6299
6300 void
6301 mpi_subm( MPI w, MPI u, MPI v, MPI m)
6302 {
6303 mpi_sub(w, u, v);
6304 mpi_fdiv_r( w, w, m );
6305 }
6306