// SPDX-License-Identifier: BSD-2-Clause /* * Copyright (c) 2014, STMicroelectronics International N.V. */ #include "mpa.h" /************************************************************* * * HELPERS * *************************************************************/ /* -------------------------------------------------------------------- * Function: __mpa_abs_cmp * * Returns 0 if |op1| == |op2| * >0 if |op1| > |op2| * <0 if |op1| < |op2| */ int __mpa_abs_cmp(const mpanum op1, const mpanum op2) { int wpos; char same; /* if they're really the same, return 0 */ if (op1 == op2) return 0; /* check the sizes */ if (__mpanum_size(op1) != __mpanum_size(op2)) return __mpanum_size(op1) - __mpanum_size(op2); if (__mpanum_is_zero(op1) && __mpanum_is_zero(op2)) return 0; /* Ok, so we have the same size and they're not zero. Check words */ wpos = __mpanum_size(op1) - 1; same = 1; while (same && (wpos >= 0)) { same = (op1->d[wpos] == op2->d[wpos]); wpos--; } if (same) return 0; wpos++; return (op1->d[wpos] > op2->d[wpos] ? 1 : -1); } /* -------------------------------------------------------------------- * Function: __mpa_abs_greater_than * * Returns 1 if |op1| > |op2| and otherwise returns 0. */ int __mpa_abs_greater_than(const mpanum op1, const mpanum op2) { return (__mpa_abs_cmp(op1, op2) > 0 ? 1 : 0); } /* -------------------------------------------------------------------- * Function: __mpa_abs_less_than * * Returns 1 if |op1| < |op2| and otherwise returns 0. */ int __mpa_abs_less_than(const mpanum op1, const mpanum op2) { return (__mpa_abs_cmp(op1, op2) < 0 ? 1 : 0); } /************************************************************* * * LIB FUNCTIONS * *************************************************************/ /* -------------------------------------------------------------------- * Function: mpa_cmp * * Returns 0 if op1 == op2 * >0 if op1 > op2 * <0 if op1 < op2 */ int32_t mpa_cmp(const mpanum op1, const mpanum op2) { int sign_1; int abscmp; /* if they have different signs, it's straight forward */ sign_1 = __mpanum_sign(op1); if (sign_1 != __mpanum_sign(op2)) return sign_1; /* handle the special case where op1->size = 0 */ if (__mpanum_size(op1) == 0) return __mpanum_size(op2) == 0 ? 0 : -__mpanum_sign(op2); /* so they have the same sign. compare the abs values and decide * based on sign_1. */ abscmp = __mpa_abs_cmp(op1, op2); if (sign_1 != MPA_POS_SIGN) return -abscmp; return abscmp; } /* -------------------------------------------------------------------- * Function: mpa_cmp_short * * Compares op1 to the word_t op2 and returns: * >0 if op1 > op2, * 0 if op1 == op2 * <0 if op1 < op2 */ int32_t mpa_cmp_short(const mpanum op1, int32_t op2) { #if (MPA_WORD_SIZE == 32) int sign_1; int sign_2; mpa_word_t op2abs; sign_1 = __mpanum_sign(op1); sign_2 = (op2 < 0) ? MPA_NEG_SIGN : MPA_POS_SIGN; /* handle the special case where op1->size = 0 */ if (op1->size == 0) return op2 == 0 ? 0 : -sign_2; /* check if op1 is larger than an int32_t */ if (__mpanum_size(op1) > 1) return sign_1; /* check if they have different signs */ if (sign_1 != sign_2) return sign_1; /* here they have the same sign and we can compare absolute values */ op2abs = ((op2 < 0) ? (mpa_word_t) -op2 : (mpa_word_t) op2); if (__mpanum_lsw(op1) == op2abs) return 0; return (__mpanum_lsw(op1) > op2abs) ? sign_1 : -sign_1; #else #error "Write code for digit size != 32" #endif }