1 1.1 mrg /* mpz_cmp_d -- compare absolute values of mpz and double. 2 1.1 mrg 3 1.1.1.3 mrg Copyright 2001-2003 Free Software Foundation, Inc. 4 1.1 mrg 5 1.1 mrg This file is part of the GNU MP Library. 6 1.1 mrg 7 1.1 mrg The GNU MP Library is free software; you can redistribute it and/or modify 8 1.1.1.3 mrg it under the terms of either: 9 1.1.1.3 mrg 10 1.1.1.3 mrg * the GNU Lesser General Public License as published by the Free 11 1.1.1.3 mrg Software Foundation; either version 3 of the License, or (at your 12 1.1.1.3 mrg option) any later version. 13 1.1.1.3 mrg 14 1.1.1.3 mrg or 15 1.1.1.3 mrg 16 1.1.1.3 mrg * the GNU General Public License as published by the Free Software 17 1.1.1.3 mrg Foundation; either version 2 of the License, or (at your option) any 18 1.1.1.3 mrg later version. 19 1.1.1.3 mrg 20 1.1.1.3 mrg or both in parallel, as here. 21 1.1 mrg 22 1.1 mrg The GNU MP Library is distributed in the hope that it will be useful, but 23 1.1 mrg WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 24 1.1.1.3 mrg or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 25 1.1.1.3 mrg for more details. 26 1.1 mrg 27 1.1.1.3 mrg You should have received copies of the GNU General Public License and the 28 1.1.1.3 mrg GNU Lesser General Public License along with the GNU MP Library. If not, 29 1.1.1.3 mrg see https://www.gnu.org/licenses/. */ 30 1.1 mrg 31 1.1 mrg #include "config.h" 32 1.1 mrg 33 1.1 mrg #if HAVE_FLOAT_H 34 1.1 mrg #include <float.h> /* for DBL_MAX */ 35 1.1 mrg #endif 36 1.1 mrg 37 1.1 mrg #include "gmp-impl.h" 38 1.1 mrg 39 1.1 mrg 40 1.1 mrg #define RETURN_CMP(zl, dl) \ 41 1.1 mrg do { \ 42 1.1 mrg zlimb = (zl); \ 43 1.1 mrg dlimb = (dl); \ 44 1.1 mrg if (zlimb != dlimb) \ 45 1.1 mrg return (zlimb >= dlimb ? ret : -ret); \ 46 1.1 mrg } while (0) 47 1.1 mrg 48 1.1 mrg #define RETURN_NONZERO(ptr, size, val) \ 49 1.1 mrg do { \ 50 1.1 mrg mp_size_t __i; \ 51 1.1 mrg for (__i = (size)-1; __i >= 0; __i--) \ 52 1.1 mrg if ((ptr)[__i] != 0) \ 53 1.1 mrg return val; \ 54 1.1 mrg return 0; \ 55 1.1 mrg } while (0) 56 1.1 mrg 57 1.1 mrg 58 1.1 mrg int 59 1.1 mrg mpz_cmp_d (mpz_srcptr z, double d) 60 1.1 mrg { 61 1.1 mrg mp_limb_t darray[LIMBS_PER_DOUBLE], zlimb, dlimb; 62 1.1 mrg mp_srcptr zp; 63 1.1 mrg mp_size_t zsize; 64 1.1 mrg int dexp, ret; 65 1.1 mrg 66 1.1 mrg /* d=NaN is an invalid operation, there's no sensible return value. 67 1.1 mrg d=Inf or -Inf is always bigger than z. */ 68 1.1 mrg DOUBLE_NAN_INF_ACTION (d, __gmp_invalid_operation (), goto z_zero); 69 1.1 mrg 70 1.1 mrg /* 1. Either operand zero. */ 71 1.1 mrg zsize = SIZ(z); 72 1.1 mrg if (d == 0.0) 73 1.1 mrg return zsize; 74 1.1 mrg if (zsize == 0) 75 1.1 mrg { 76 1.1 mrg z_zero: 77 1.1 mrg return (d < 0.0 ? 1 : -1); 78 1.1 mrg } 79 1.1 mrg 80 1.1 mrg /* 2. Opposite signs. */ 81 1.1 mrg if (zsize >= 0) 82 1.1 mrg { 83 1.1 mrg if (d < 0.0) 84 1.1.1.2 mrg return 1; /* >=0 cmp <0 */ 85 1.1 mrg ret = 1; 86 1.1 mrg } 87 1.1 mrg else 88 1.1 mrg { 89 1.1 mrg if (d >= 0.0) 90 1.1.1.2 mrg return -1; /* <0 cmp >=0 */ 91 1.1 mrg ret = -1; 92 1.1 mrg d = -d; 93 1.1 mrg zsize = -zsize; 94 1.1 mrg } 95 1.1 mrg 96 1.1 mrg /* 3. Small d, knowing abs(z) >= 1. */ 97 1.1 mrg if (d < 1.0) 98 1.1 mrg return ret; 99 1.1 mrg 100 1.1 mrg dexp = __gmp_extract_double (darray, d); 101 1.1 mrg ASSERT (dexp >= 1); 102 1.1 mrg 103 1.1 mrg /* 4. Check for different high limb positions. */ 104 1.1 mrg if (zsize != dexp) 105 1.1 mrg return (zsize >= dexp ? ret : -ret); 106 1.1 mrg 107 1.1 mrg /* 5. Limb data. */ 108 1.1 mrg zp = PTR(z); 109 1.1 mrg 110 1.1 mrg #if LIMBS_PER_DOUBLE == 2 111 1.1 mrg RETURN_CMP (zp[zsize-1], darray[1]); 112 1.1 mrg if (zsize == 1) 113 1.1 mrg return (darray[0] != 0 ? -ret : 0); 114 1.1 mrg 115 1.1 mrg RETURN_CMP (zp[zsize-2], darray[0]); 116 1.1 mrg RETURN_NONZERO (zp, zsize-2, ret); 117 1.1 mrg #endif 118 1.1 mrg 119 1.1 mrg #if LIMBS_PER_DOUBLE == 3 120 1.1 mrg RETURN_CMP (zp[zsize-1], darray[2]); 121 1.1 mrg if (zsize == 1) 122 1.1 mrg return ((darray[0] | darray[1]) != 0 ? -ret : 0); 123 1.1 mrg 124 1.1 mrg RETURN_CMP (zp[zsize-2], darray[1]); 125 1.1 mrg if (zsize == 2) 126 1.1 mrg return (darray[0] != 0 ? -ret : 0); 127 1.1 mrg 128 1.1 mrg RETURN_CMP (zp[zsize-3], darray[0]); 129 1.1 mrg RETURN_NONZERO (zp, zsize-3, ret); 130 1.1 mrg #endif 131 1.1 mrg 132 1.1 mrg #if LIMBS_PER_DOUBLE >= 4 133 1.1 mrg { 134 1.1 mrg int i; 135 1.1 mrg for (i = 1; i <= LIMBS_PER_DOUBLE; i++) 136 1.1 mrg { 137 1.1 mrg RETURN_CMP (zp[zsize-i], darray[LIMBS_PER_DOUBLE-i]); 138 1.1 mrg if (i >= zsize) 139 1.1 mrg RETURN_NONZERO (darray, LIMBS_PER_DOUBLE-i, -ret); 140 1.1 mrg } 141 1.1 mrg RETURN_NONZERO (zp, zsize-LIMBS_PER_DOUBLE, ret); 142 1.1 mrg } 143 1.1 mrg #endif 144 1.1 mrg } 145