1/* mpf_eq -- Compare two floats up to a specified bit #.
2
3Copyright 1993, 1995, 1996, 2001, 2002, 2008, 2009 Free Software Foundation,
4Inc.
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 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 MP 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 MP Library.  If not, see http://www.gnu.org/licenses/.  */
20
21#include "gmp.h"
22#include "gmp-impl.h"
23#include "longlong.h"
24
25int
26mpf_eq (mpf_srcptr u, mpf_srcptr v, mp_bitcnt_t n_bits)
27{
28  mp_srcptr up, vp, p;
29  mp_size_t usize, vsize, minsize, maxsize, n_limbs, i, size;
30  mp_exp_t uexp, vexp;
31  mp_limb_t diff;
32  int cnt;
33
34  uexp = u->_mp_exp;
35  vexp = v->_mp_exp;
36
37  usize = u->_mp_size;
38  vsize = v->_mp_size;
39
40  /* 1. Are the signs different?  */
41  if ((usize ^ vsize) >= 0)
42    {
43      /* U and V are both non-negative or both negative.  */
44      if (usize == 0)
45	return vsize == 0;
46      if (vsize == 0)
47	return 0;
48
49      /* Fall out.  */
50    }
51  else
52    {
53      /* Either U or V is negative, but not both.  */
54      return 0;
55    }
56
57  /* U and V have the same sign and are both non-zero.  */
58
59  /* 2. Are the exponents different?  */
60  if (uexp != vexp)
61    return 0;
62
63  usize = ABS (usize);
64  vsize = ABS (vsize);
65
66  up = u->_mp_d;
67  vp = v->_mp_d;
68
69  up += usize;			/* point just above most significant limb */
70  vp += vsize;			/* point just above most significant limb */
71
72  count_leading_zeros (cnt, up[-1]);
73  if ((vp[-1] >> (GMP_LIMB_BITS - 1 - cnt)) != 1)
74    return 0;			/* msb positions different */
75
76  n_bits += cnt - GMP_NAIL_BITS;
77  n_limbs = (n_bits + GMP_NUMB_BITS - 1) / GMP_NUMB_BITS;
78
79  usize = MIN (usize, n_limbs);
80  vsize = MIN (vsize, n_limbs);
81
82#if 0
83  /* Ignore zeros at the low end of U and V.  */
84  while (up[0] == 0)
85    up++, usize--;
86  while (vp[0] == 0)
87    vp++, vsize--;
88#endif
89
90  minsize = MIN (usize, vsize);
91  maxsize = usize + vsize - minsize;
92
93  up -= minsize;		/* point at most significant common limb */
94  vp -= minsize;		/* point at most significant common limb */
95
96  /* Compare the most significant part which has explicit limbs for U and V. */
97  for (i = minsize - 1; i > 0; i--)
98    {
99      if (up[i] != vp[i])
100	return 0;
101    }
102
103  n_bits -= (maxsize - 1) * GMP_NUMB_BITS;
104
105  size = maxsize - minsize;
106  if (size != 0)
107    {
108      if (up[0] != vp[0])
109	return 0;
110
111      /* Now either U or V has its limbs consumed, i.e, continues with an
112	 infinite number of implicit zero limbs.  Check that the other operand
113	 has just zeros in the corresponding, relevant part.  */
114
115      if (usize > vsize)
116	p = up - size;
117      else
118	p = vp - size;
119
120      for (i = size - 1; i > 0; i--)
121	{
122	  if (p[i] != 0)
123	    return 0;
124	}
125
126      diff = p[0];
127    }
128  else
129    {
130      /* Both U or V has its limbs consumed.  */
131
132      diff = up[0] ^ vp[0];
133    }
134
135  if (n_bits < GMP_NUMB_BITS)
136    diff >>= GMP_NUMB_BITS - n_bits;
137
138  return diff == 0;
139}
140