1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* mpi-sub-ui.c - Subtract an unsigned integer from an MPI. 3 * 4 * Copyright 1991, 1993, 1994, 1996, 1999-2002, 2004, 2012, 2013, 2015 5 * Free Software Foundation, Inc. 6 * 7 * This file was based on the GNU MP Library source file: 8 * https://gmplib.org/repo/gmp-6.2/file/510b83519d1c/mpz/aors_ui.h 9 * 10 * The GNU MP Library is free software; you can redistribute it and/or modify 11 * it under the terms of either: 12 * 13 * * the GNU Lesser General Public License as published by the Free 14 * Software Foundation; either version 3 of the License, or (at your 15 * option) any later version. 16 * 17 * or 18 * 19 * * the GNU General Public License as published by the Free Software 20 * Foundation; either version 2 of the License, or (at your option) any 21 * later version. 22 * 23 * or both in parallel, as here. 24 * 25 * The GNU MP Library is distributed in the hope that it will be useful, but 26 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 27 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 28 * for more details. 29 * 30 * You should have received copies of the GNU General Public License and the 31 * GNU Lesser General Public License along with the GNU MP Library. If not, 32 * see https://www.gnu.org/licenses/. 33 */ 34 35 #include "mpi-internal.h" 36 37 int mpi_sub_ui(MPI w, MPI u, unsigned long vval) 38 { 39 if (u->nlimbs == 0) { 40 if (mpi_resize(w, 1) < 0) 41 return -ENOMEM; 42 w->d[0] = vval; 43 w->nlimbs = (vval != 0); 44 w->sign = (vval != 0); 45 return 0; 46 } 47 48 /* If not space for W (and possible carry), increase space. */ 49 if (mpi_resize(w, u->nlimbs + 1)) 50 return -ENOMEM; 51 52 if (u->sign) { 53 mpi_limb_t cy; 54 55 cy = mpihelp_add_1(w->d, u->d, u->nlimbs, (mpi_limb_t) vval); 56 w->d[u->nlimbs] = cy; 57 w->nlimbs = u->nlimbs + cy; 58 w->sign = 1; 59 } else { 60 /* The signs are different. Need exact comparison to determine 61 * which operand to subtract from which. 62 */ 63 if (u->nlimbs == 1 && u->d[0] < vval) { 64 w->d[0] = vval - u->d[0]; 65 w->nlimbs = 1; 66 w->sign = 1; 67 } else { 68 mpihelp_sub_1(w->d, u->d, u->nlimbs, (mpi_limb_t) vval); 69 /* Size can decrease with at most one limb. */ 70 w->nlimbs = (u->nlimbs - (w->d[u->nlimbs - 1] == 0)); 71 w->sign = 0; 72 } 73 } 74 75 mpi_normalize(w); 76 return 0; 77 } 78 EXPORT_SYMBOL_GPL(mpi_sub_ui); 79