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