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 <linux/export.h> 36 37 #include "mpi-internal.h" 38 39 int mpi_sub_ui(MPI w, MPI u, unsigned long vval) 40 { 41 if (u->nlimbs == 0) { 42 if (mpi_resize(w, 1) < 0) 43 return -ENOMEM; 44 w->d[0] = vval; 45 w->nlimbs = (vval != 0); 46 w->sign = (vval != 0); 47 return 0; 48 } 49 50 /* If not space for W (and possible carry), increase space. */ 51 if (mpi_resize(w, u->nlimbs + 1)) 52 return -ENOMEM; 53 54 if (u->sign) { 55 mpi_limb_t cy; 56 57 cy = mpihelp_add_1(w->d, u->d, u->nlimbs, (mpi_limb_t) vval); 58 w->d[u->nlimbs] = cy; 59 w->nlimbs = u->nlimbs + cy; 60 w->sign = 1; 61 } else { 62 /* The signs are different. Need exact comparison to determine 63 * which operand to subtract from which. 64 */ 65 if (u->nlimbs == 1 && u->d[0] < vval) { 66 w->d[0] = vval - u->d[0]; 67 w->nlimbs = 1; 68 w->sign = 1; 69 } else { 70 mpihelp_sub_1(w->d, u->d, u->nlimbs, (mpi_limb_t) vval); 71 /* Size can decrease with at most one limb. */ 72 w->nlimbs = (u->nlimbs - (w->d[u->nlimbs - 1] == 0)); 73 w->sign = 0; 74 } 75 } 76 77 mpi_normalize(w); 78 return 0; 79 } 80 EXPORT_SYMBOL_GPL(mpi_sub_ui); 81