1/* mpfr_eq -- Compare two floats up to a specified bit #. 2 3Copyright 1999, 2001, 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. 4Contributed by the AriC and Caramel projects, INRIA. 5 6This file is part of the GNU MPFR Library. 7 8The GNU MPFR Library is free software; you can redistribute it and/or modify 9it under the terms of the GNU Lesser General Public License as published by 10the Free Software Foundation; either version 3 of the License, or (at your 11option) any later version. 12 13The GNU MPFR Library is distributed in the hope that it will be useful, but 14WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 15or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 16License for more details. 17 18You should have received a copy of the GNU Lesser General Public License 19along with the GNU MPFR Library; see the file COPYING.LESSER. If not, see 20http://www.gnu.org/licenses/ or write to the Free Software Foundation, Inc., 2151 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. */ 22 23 24#include "mpfr-impl.h" 25 26/* return non-zero if the first n_bits bits of u, v are equal, 27 0 otherwise */ 28int 29mpfr_eq (mpfr_srcptr u, mpfr_srcptr v, unsigned long int n_bits) 30{ 31 mpfr_limb_srcptr up, vp; 32 mp_size_t usize, vsize, size, i; 33 mpfr_exp_t uexp, vexp; 34 int k; 35 36 if (MPFR_ARE_SINGULAR(u, v)) 37 { 38 if (MPFR_IS_NAN(u) || MPFR_IS_NAN(v)) 39 return 0; /* non equal */ 40 else if (MPFR_IS_INF(u) && MPFR_IS_INF(v)) 41 return (MPFR_SIGN(u) == MPFR_SIGN(v)); 42 else if (MPFR_IS_ZERO(u) && MPFR_IS_ZERO(v)) 43 return 1; 44 else 45 return 0; 46 } 47 48 /* 1. Are the signs different? */ 49 if (MPFR_SIGN(u) != MPFR_SIGN(v)) 50 return 0; 51 52 uexp = MPFR_GET_EXP (u); 53 vexp = MPFR_GET_EXP (v); 54 55 /* 2. Are the exponents different? */ 56 if (uexp != vexp) 57 return 0; /* no bit agree */ 58 59 usize = MPFR_LIMB_SIZE (u); 60 vsize = MPFR_LIMB_SIZE (v); 61 62 if (vsize > usize) /* exchange u and v */ 63 { 64 up = MPFR_MANT(v); 65 vp = MPFR_MANT(u); 66 size = vsize; 67 vsize = usize; 68 usize = size; 69 } 70 else 71 { 72 up = MPFR_MANT(u); 73 vp = MPFR_MANT(v); 74 } 75 76 /* now usize >= vsize */ 77 MPFR_ASSERTD(usize >= vsize); 78 79 if (usize > vsize) 80 { 81 if ((unsigned long) vsize * GMP_NUMB_BITS < n_bits) 82 { 83 /* check if low min(PREC(u), n_bits) - (vsize * GMP_NUMB_BITS) 84 bits from u are non-zero */ 85 unsigned long remains = n_bits - (vsize * GMP_NUMB_BITS); 86 k = usize - vsize - 1; 87 while (k >= 0 && remains >= GMP_NUMB_BITS && !up[k]) 88 { 89 k--; 90 remains -= GMP_NUMB_BITS; 91 } 92 /* now either k < 0: all low bits from u are zero 93 or remains < GMP_NUMB_BITS: check high bits from up[k] 94 or up[k] <> 0: different */ 95 if (k >= 0 && (((remains < GMP_NUMB_BITS) && 96 (up[k] >> (GMP_NUMB_BITS - remains))) || 97 (remains >= GMP_NUMB_BITS && up[k]))) 98 return 0; /* surely too different */ 99 } 100 size = vsize; 101 } 102 else 103 { 104 size = usize; 105 } 106 107 /* now size = min (usize, vsize) */ 108 109 /* If size is too large wrt n_bits, reduce it to look only at the 110 high n_bits bits. 111 Otherwise, if n_bits > size * GMP_NUMB_BITS, reduce n_bits to 112 size * GMP_NUMB_BITS, since the extra low bits of one of the 113 operands have already been check above. */ 114 if ((unsigned long) size > 1 + (n_bits - 1) / GMP_NUMB_BITS) 115 size = 1 + (n_bits - 1) / GMP_NUMB_BITS; 116 else if (n_bits > (unsigned long) size * GMP_NUMB_BITS) 117 n_bits = size * GMP_NUMB_BITS; 118 119 up += usize - size; 120 vp += vsize - size; 121 122 for (i = size - 1; i > 0 && n_bits >= GMP_NUMB_BITS; i--) 123 { 124 if (up[i] != vp[i]) 125 return 0; 126 n_bits -= GMP_NUMB_BITS; 127 } 128 129 /* now either i=0 or n_bits<GMP_NUMB_BITS */ 130 131 /* since n_bits <= size * GMP_NUMB_BITS before the above for-loop, 132 we have the invariant n_bits <= (i+1) * GMP_NUMB_BITS, thus 133 we always have n_bits <= GMP_NUMB_BITS here */ 134 MPFR_ASSERTD(n_bits <= GMP_NUMB_BITS); 135 136 if (n_bits & (GMP_NUMB_BITS - 1)) 137 return (up[i] >> (GMP_NUMB_BITS - (n_bits & (GMP_NUMB_BITS - 1))) == 138 vp[i] >> (GMP_NUMB_BITS - (n_bits & (GMP_NUMB_BITS - 1)))); 139 else 140 return (up[i] == vp[i]); 141} 142