LSSTApplications  19.0.0-14-gb0260a2+72efe9b372,20.0.0+7927753e06,20.0.0+8829bf0056,20.0.0+995114c5d2,20.0.0+b6f4b2abd1,20.0.0+bddc4f4cbe,20.0.0-1-g253301a+8829bf0056,20.0.0-1-g2b7511a+0d71a2d77f,20.0.0-1-g5b95a8c+7461dd0434,20.0.0-12-g321c96ea+23efe4bbff,20.0.0-16-gfab17e72e+fdf35455f6,20.0.0-2-g0070d88+ba3ffc8f0b,20.0.0-2-g4dae9ad+ee58a624b3,20.0.0-2-g61b8584+5d3db074ba,20.0.0-2-gb780d76+d529cf1a41,20.0.0-2-ged6426c+226a441f5f,20.0.0-2-gf072044+8829bf0056,20.0.0-2-gf1f7952+ee58a624b3,20.0.0-20-geae50cf+e37fec0aee,20.0.0-25-g3dcad98+544a109665,20.0.0-25-g5eafb0f+ee58a624b3,20.0.0-27-g64178ef+f1f297b00a,20.0.0-3-g4cc78c6+e0676b0dc8,20.0.0-3-g8f21e14+4fd2c12c9a,20.0.0-3-gbd60e8c+187b78b4b8,20.0.0-3-gbecbe05+48431fa087,20.0.0-38-ge4adf513+a12e1f8e37,20.0.0-4-g97dc21a+544a109665,20.0.0-4-gb4befbc+087873070b,20.0.0-4-gf910f65+5d3db074ba,20.0.0-5-gdfe0fee+199202a608,20.0.0-5-gfbfe500+d529cf1a41,20.0.0-6-g64f541c+d529cf1a41,20.0.0-6-g9a5b7a1+a1cd37312e,20.0.0-68-ga3f3dda+5fca18c6a4,20.0.0-9-g4aef684+e18322736b,w.2020.45
LSSTDataManagementBasePackage
BigInteger.cc
Go to the documentation of this file.
1 /*
2  * LSST Data Management System
3  * Copyright 2014-2015 AURA/LSST.
4  *
5  * This product includes software developed by the
6  * LSST Project (http://www.lsst.org/).
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the LSST License Statement and
19  * the GNU General Public License along with this program. If not,
20  * see <https://www.lsstcorp.org/LegalNotices/>.
21  */
22 
25 
27 
28 #include <algorithm>
29 
30 
31 namespace lsst {
32 namespace sphgeom {
33 
34 namespace {
35 
36 // `_add` computes the sum of the digits in m1 and m2 and stores the result in
37 // m, which may equal either m1 or m2. It returns the number of digits in the
38 // sum.
39 unsigned _add(uint32_t * const m,
40  uint32_t const * const m1,
41  uint32_t const * const m2,
42  unsigned const size1,
43  unsigned const size2)
44 {
45  uint64_t sum = 0;
46  unsigned i = 0;
47  unsigned const size = std::min(size1, size2);
48  for (; i < size; ++i) {
49  sum = static_cast<uint64_t>(m1[i]) + (sum >> 32) +
50  static_cast<uint64_t>(m2[i]);
51  m[i] = static_cast<uint32_t>(sum);
52  }
53  for (; i < size1; ++i) {
54  sum = static_cast<uint64_t>(m1[i]) + (sum >> 32);
55  m[i] = static_cast<uint32_t>(sum);
56  }
57  for (; i < size2; ++i) {
58  sum = static_cast<uint64_t>(m2[i]) + (sum >> 32);
59  m[i] = static_cast<uint32_t>(sum);
60  }
61  uint32_t carry = static_cast<uint32_t>(sum >> 32);
62  if (carry != 0) {
63  m[i] = carry;
64  ++i;
65  }
66  return i;
67 }
68 
69 // `_sub` computes the difference of the digits in m1 and m2 and stores the
70 // result in m, which may equal either m1 or m2. It assumes that the difference
71 // is non-negative, and returns the the number of digits in the difference.
72 unsigned _sub(uint32_t * const m,
73  uint32_t const * const m1,
74  uint32_t const * const m2,
75  unsigned const size1,
76  unsigned const size2)
77 {
78  int64_t diff = 0;
79  unsigned i = 0;
80  // Note that right shifting a negative integer is implementation defined
81  // (not undefined) behavior. Here we assume arithmetic right shifts for
82  // negative integers.
83  //
84  // TODO(smm): check for this at build time, and provide an alternate
85  // implementation when this assumption does not hold.
86  for (; i < size2; ++i) {
87  diff = static_cast<int64_t>(m1[i]) + (diff >> 32) -
88  static_cast<int64_t>(m2[i]);
89  m[i] = static_cast<uint32_t>(diff);
90  }
91  // Borrow from the remaining digits in m1 while necessary.
92  for (; diff < 0; ++i) {
93  diff = static_cast<int64_t>(m1[i]) - 1;
94  m[i] = static_cast<uint32_t>(diff);
95  }
96  // If we subtracted anything from the most significant digit in m1, strip
97  // any leading zeroes that may have been introduced.
98  if (i == size1) {
99  while (m1[i - 1] == 0) { --i; }
100  return i;
101  }
102  // Otherwise, copy the remaining digits from m1 to m.
103  for (; i < size1; ++i) {
104  m[i] = m1[i];
105  }
106  return i;
107 }
108 
109 // `_mul` computes the product of m1 and m2 and stores the result in m,
110 // which may equal either m1 or m2. It assumes that m1 has at least as many
111 // digits as m2, and returns the the number of digits in the product.
112 unsigned _mul(uint32_t * const m,
113  uint32_t const * const m1,
114  uint32_t const * const m2,
115  unsigned const size1,
116  unsigned const size2)
117 {
118  // The algorithm implemented is long multiplication, and is good for small
119  // digit counts. A requirement for anything fancier involves enough
120  // complexity that switching to GMP is definitely warranted.
121  //
122  // The only small subtlety here is that because m is allowed to alias m1
123  // or m2, we compute products of m2 from most to least significant digit of
124  // m1. This way no as yet unprocessed input digits are overwritten.
125  unsigned const size = size1 + size2;
126  for (unsigned i = size1; i < size; ++i) {
127  m[i] = 0;
128  }
129  for (unsigned i = size1; i > 0; --i) {
130  uint64_t digit = m1[i - 1];
131  uint64_t carry = static_cast<uint64_t>(m2[0]) * digit;
132  unsigned j = 1;
133  m[i - 1] = static_cast<uint32_t>(carry);
134  carry >>= 32;
135  for (; j < size2; ++j) {
136  carry = static_cast<uint64_t>(m2[j]) * digit +
137  static_cast<uint64_t>(m[i + j - 1]) +
138  carry;
139  m[i + j - 1] = static_cast<uint32_t>(carry);
140  carry >>= 32;
141  }
142  for (; carry != 0; ++j) {
143  carry += static_cast<uint64_t>(m[i + j - 1]);
144  m[i + j - 1] = static_cast<uint32_t>(carry);
145  carry >>= 32;
146  }
147  }
148  // The product of m1 and m2 contains size1 + size2 or size1 + size2 - 1
149  // digits.
150  return m[size - 1] == 0 ? size - 1 : size;
151 }
152 
153 } // unnamed namespace
154 
155 
157  if (b._sign == 0) {
158  return *this;
159  }
160  if (_sign == 0) {
161  *this = b;
162  return *this;
163  }
164  if (this == &b) {
165  return multiplyPow2(1);
166  }
167  // When adding two magnitudes, the maximum number of bits in the result is
168  // one greater than the number of bits B in the larger input. When
169  // subtracting them, the maximum result size is B.
170  _checkCapacity(std::max(_size, b._size) + 1);
171  if (_sign == b._sign) {
172  // If the signs of both integers match, add their magnitudes.
173  _size = _add(_digits, _digits, b._digits, _size, b._size);
174  return *this;
175  }
176  // Otherwise, subtract the smaller magnitude from the larger. The sign of
177  // the result is the sign of the input with the larger magnitude.
178  if (_size > b._size) {
179  _size = _sub(_digits, _digits, b._digits, _size, b._size);
180  } else if (_size < b._size) {
181  _size = _sub(_digits, b._digits, _digits, b._size, _size);
182  _sign = b._sign;
183  } else {
184  // Both magnitudes have the same number of digits. Compare and discard
185  // leading common digits until we find a digit position where the
186  // magnitudes differ, or we determine that they are identical.
187  int i = _size;
188  for (; i > 0 && _digits[i - 1] == b._digits[i - 1]; --i) {}
189  if (i == 0) {
190  setToZero();
191  } else if (_digits[i - 1] > b._digits[i - 1]) {
192  _size = _sub(_digits, _digits, b._digits, i, i);
193  } else {
194  _size = _sub(_digits, b._digits, _digits, i, i);
195  _sign = b._sign;
196  }
197  }
198  return *this;
199 }
200 
202  if (this != &b) {
203  // Avoid code duplication by computing a - b = -(-a + b).
204  // This only works if a and b are distinct.
205  negate();
206  add(b);
207  negate();
208  } else {
209  setToZero();
210  }
211  return *this;
212 }
213 
215  if (_sign == 0 || n == 0) {
216  return *this;
217  }
218  // Decompose n into (s, z), where s is a shift by less than 32 bits, and
219  // z is the number of trailing zero digits introduced by the shift.
220  unsigned const z = (n >> 5);
221  unsigned const s = (n & 0x1f);
222  unsigned const size = _size + z;
223  _checkCapacity(size + 1);
224  if (s == 0) {
225  // Right-shifting an unsigned 32 bit integer by 32 bits is undefined
226  // behavior. Avoid that using this special case code.
227  for (unsigned i = _size; i != 0; --i) {
228  _digits[i + z - 1] = _digits[i - 1];
229  }
230  for (unsigned i = z; i != 0; --i) {
231  _digits[i - 1] = 0;
232  }
233  _size = size;
234  } else {
235  uint32_t low, high = 0;
236  for (unsigned i = _size; i != 0; --i, high = low) {
237  low = _digits[i - 1];
238  _digits[i + z] = (high << s) | (low >> (32 - s));
239  }
240  _digits[z] = high << s;
241  for (unsigned i = z; i != 0; --i) {
242  _digits[i] = 0;
243  }
244  _size = (_digits[size] == 0) ? size: size + 1;
245  }
246  return *this;
247 }
248 
250  _sign *= b._sign;
251  if (_sign == 0) {
252  _size = 0;
253  return *this;
254  }
255  _checkCapacity(_size + b._size);
256  if (_size >= b._size) {
257  _size = _mul(_digits, _digits, b._digits, _size, b._size);
258  } else {
259  _size = _mul(_digits, b._digits, _digits, b._size, _size);
260  }
261  return *this;
262 }
263 
264 }} // namespace lsst::sphgeom
lsst::sphgeom::BigInteger::negate
void negate()
negate multiplies this integer by -1.
Definition: BigInteger.h:103
lsst::sphgeom::BigInteger::subtract
BigInteger & subtract(BigInteger const &b)
subtract subtracts b from this integer.
Definition: BigInteger.cc:201
lsst::sphgeom::BigInteger::multiplyPow2
BigInteger & multiplyPow2(unsigned n)
multiplyPow2 multiplies this integer by 2ⁿ.
Definition: BigInteger.cc:214
BigInteger.h
This file declares a class for arbitrary precision integers.
lsst::sphgeom::BigInteger::setToZero
void setToZero()
setToZero sets this integer to zero.
Definition: BigInteger.h:81
lsst::sphgeom::BigInteger::add
BigInteger & add(BigInteger const &b)
add adds b to this integer.
Definition: BigInteger.cc:156
z
double z
Definition: Match.cc:44
lsst::sphgeom::BigInteger
BigInteger is an arbitrary precision signed integer class.
Definition: BigInteger.h:45
b
table::Key< int > b
Definition: TransmissionCurve.cc:467
lsst
A base class for image defects.
Definition: imageAlgorithm.dox:1
std::min
T min(T... args)
std::max
T max(T... args)
m
int m
Definition: SpanSet.cc:49
lsst::sphgeom::BigInteger::multiply
BigInteger & multiply(BigInteger const &b)
multiply multiplies this integer by b.
Definition: BigInteger.cc:249