Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /* mpi-sub-ui.c - Subtract an unsigned integer from an MPI.
0003  *
0004  * Copyright 1991, 1993, 1994, 1996, 1999-2002, 2004, 2012, 2013, 2015
0005  * Free Software Foundation, Inc.
0006  *
0007  * This file was based on the GNU MP Library source file:
0008  * https://gmplib.org/repo/gmp-6.2/file/510b83519d1c/mpz/aors_ui.h
0009  *
0010  * The GNU MP Library is free software; you can redistribute it and/or modify
0011  * it under the terms of either:
0012  *
0013  *   * the GNU Lesser General Public License as published by the Free
0014  *     Software Foundation; either version 3 of the License, or (at your
0015  *     option) any later version.
0016  *
0017  * or
0018  *
0019  *   * the GNU General Public License as published by the Free Software
0020  *     Foundation; either version 2 of the License, or (at your option) any
0021  *     later version.
0022  *
0023  * or both in parallel, as here.
0024  *
0025  * The GNU MP Library is distributed in the hope that it will be useful, but
0026  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
0027  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
0028  * for more details.
0029  *
0030  * You should have received copies of the GNU General Public License and the
0031  * GNU Lesser General Public License along with the GNU MP Library.  If not,
0032  * see https://www.gnu.org/licenses/.
0033  */
0034 
0035 #include "mpi-internal.h"
0036 
0037 int mpi_sub_ui(MPI w, MPI u, unsigned long vval)
0038 {
0039     if (u->nlimbs == 0) {
0040         if (mpi_resize(w, 1) < 0)
0041             return -ENOMEM;
0042         w->d[0] = vval;
0043         w->nlimbs = (vval != 0);
0044         w->sign = (vval != 0);
0045         return 0;
0046     }
0047 
0048     /* If not space for W (and possible carry), increase space. */
0049     if (mpi_resize(w, u->nlimbs + 1))
0050         return -ENOMEM;
0051 
0052     if (u->sign) {
0053         mpi_limb_t cy;
0054 
0055         cy = mpihelp_add_1(w->d, u->d, u->nlimbs, (mpi_limb_t) vval);
0056         w->d[u->nlimbs] = cy;
0057         w->nlimbs = u->nlimbs + cy;
0058         w->sign = 1;
0059     } else {
0060         /* The signs are different.  Need exact comparison to determine
0061          * which operand to subtract from which.
0062          */
0063         if (u->nlimbs == 1 && u->d[0] < vval) {
0064             w->d[0] = vval - u->d[0];
0065             w->nlimbs = 1;
0066             w->sign = 1;
0067         } else {
0068             mpihelp_sub_1(w->d, u->d, u->nlimbs, (mpi_limb_t) vval);
0069             /* Size can decrease with at most one limb. */
0070             w->nlimbs = (u->nlimbs - (w->d[u->nlimbs - 1] == 0));
0071             w->sign = 0;
0072         }
0073     }
0074 
0075     mpi_normalize(w);
0076     return 0;
0077 }
0078 EXPORT_SYMBOL_GPL(mpi_sub_ui);