1/* mpf_eq -- Compare two floats up to a specified bit #. 2 3Copyright 1993, 1995, 1996, 2001, 2002, 2008, 2009, 2012 Free Software 4Foundation, Inc. 5 6This file is part of the GNU MP Library. 7 8The GNU MP Library is free software; you can redistribute it and/or modify 9it under the terms of either: 10 11 * the GNU Lesser General Public License as published by the Free 12 Software Foundation; either version 3 of the License, or (at your 13 option) any later version. 14 15or 16 17 * the GNU General Public License as published by the Free Software 18 Foundation; either version 2 of the License, or (at your option) any 19 later version. 20 21or both in parallel, as here. 22 23The GNU MP Library is distributed in the hope that it will be useful, but 24WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 25or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 26for more details. 27 28You should have received copies of the GNU General Public License and the 29GNU Lesser General Public License along with the GNU MP Library. If not, 30see https://www.gnu.org/licenses/. */ 31 32#include "gmp-impl.h" 33#include "longlong.h" 34 35int 36mpf_eq (mpf_srcptr u, mpf_srcptr v, mp_bitcnt_t n_bits) 37{ 38 mp_srcptr up, vp, p; 39 mp_size_t usize, vsize, minsize, maxsize, n_limbs, i, size; 40 mp_exp_t uexp, vexp; 41 mp_limb_t diff; 42 int cnt; 43 44 uexp = u->_mp_exp; 45 vexp = v->_mp_exp; 46 47 usize = u->_mp_size; 48 vsize = v->_mp_size; 49 50 /* 1. Are the signs different? */ 51 if ((usize ^ vsize) >= 0) 52 { 53 /* U and V are both non-negative or both negative. */ 54 if (usize == 0) 55 return vsize == 0; 56 if (vsize == 0) 57 return 0; 58 59 /* Fall out. */ 60 } 61 else 62 { 63 /* Either U or V is negative, but not both. */ 64 return 0; 65 } 66 67 /* U and V have the same sign and are both non-zero. */ 68 69 /* 2. Are the exponents different? */ 70 if (uexp != vexp) 71 return 0; 72 73 usize = ABS (usize); 74 vsize = ABS (vsize); 75 76 up = u->_mp_d; 77 vp = v->_mp_d; 78 79 up += usize; /* point just above most significant limb */ 80 vp += vsize; /* point just above most significant limb */ 81 82 count_leading_zeros (cnt, up[-1]); 83 if ((vp[-1] >> (GMP_LIMB_BITS - 1 - cnt)) != 1) 84 return 0; /* msb positions different */ 85 86 n_bits += cnt - GMP_NAIL_BITS; 87 n_limbs = (n_bits + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS; 88 89 usize = MIN (usize, n_limbs); 90 vsize = MIN (vsize, n_limbs); 91 92#if 0 93 /* Ignore zeros at the low end of U and V. */ 94 while (up[0] == 0) 95 up++, usize--; 96 while (vp[0] == 0) 97 vp++, vsize--; 98#endif 99 100 minsize = MIN (usize, vsize); 101 maxsize = usize + vsize - minsize; 102 103 up -= minsize; /* point at most significant common limb */ 104 vp -= minsize; /* point at most significant common limb */ 105 106 /* Compare the most significant part which has explicit limbs for U and V. */ 107 for (i = minsize - 1; i > 0; i--) 108 { 109 if (up[i] != vp[i]) 110 return 0; 111 } 112 113 n_bits -= (maxsize - 1) * GMP_NUMB_BITS; 114 115 size = maxsize - minsize; 116 if (size != 0) 117 { 118 if (up[0] != vp[0]) 119 return 0; 120 121 /* Now either U or V has its limbs consumed, i.e, continues with an 122 infinite number of implicit zero limbs. Check that the other operand 123 has just zeros in the corresponding, relevant part. */ 124 125 if (usize > vsize) 126 p = up - size; 127 else 128 p = vp - size; 129 130 for (i = size - 1; i > 0; i--) 131 { 132 if (p[i] != 0) 133 return 0; 134 } 135 136 diff = p[0]; 137 } 138 else 139 { 140 /* Both U or V has its limbs consumed. */ 141 142 diff = up[0] ^ vp[0]; 143 } 144 145 if (n_bits < GMP_NUMB_BITS) 146 diff >>= GMP_NUMB_BITS - n_bits; 147 148 return diff == 0; 149} 150