Boost.Real  1.0.0
Boost.Real numerical data type for real numbers representation using range arithmetic.
real_helpers.hpp
1 #ifndef BOOST_REAL_REAL_HELPERS_HPP
2 #define BOOST_REAL_REAL_HELPERS_HPP
3 
4 #include <list>
5 
6 #include <real/interval.hpp>
7 #include <real/boundary.hpp>
8 
9 namespace boost {
10  namespace real {
11  namespace helper {
12 
13  boundary abs(const boundary& b) {
14  boundary result = b;
15  result.positive = true;
16  return result;
17  }
18 
33  int add_vectors(const std::vector<int> &lhs,
34  int lhs_exponent,
35  const std::vector<int> &rhs,
36  int rhs_exponent,
37  std::vector<int> &result) {
38  int carry = 0;
39 
40  int fractional_length = std::max((int)lhs.size() - lhs_exponent, (int)rhs.size() - rhs_exponent);
41  int integral_length = std::max(lhs_exponent, rhs_exponent);
42 
43  // we walk the numbers from the lowest to the highest digit
44  for (int i = fractional_length - 1; i >= -integral_length; i--) {
45 
46  int lhs_digit = 0;
47  if (0 <= lhs_exponent + i && lhs_exponent + i < (int)lhs.size()) {
48  lhs_digit = lhs[lhs_exponent + i];
49  }
50 
51  int rhs_digit = 0;
52  if (0 <= rhs_exponent + i && rhs_exponent + i < (int)rhs.size()) {
53  rhs_digit = rhs[rhs_exponent + i];
54  }
55 
56  int digit = carry + lhs_digit + rhs_digit;
57 
58  if (digit > 9) {
59  carry = 1;
60  digit -= 10;
61  } else {
62  carry = 0;
63  }
64 
65  result.insert(result.begin(), digit);
66  }
67 
68  if (carry == 1) {
69  result.insert(result.begin(), 1);
70  integral_length++;
71  }
72 
73  return integral_length;
74  }
75 
92  int subtract_vectors(const std::vector<int> &lhs,
93  int lhs_exponent,
94  const std::vector<int> &rhs,
95  int rhs_exponent,
96  std::vector<int> &result) {
97 
98  int fractional_length = std::max((int)lhs.size() - lhs_exponent, (int)rhs.size() - rhs_exponent);
99  int integral_length = std::max(lhs_exponent, rhs_exponent);
100 
101  int borrow = 0;
102  // we walk the numbers from the lowest to the highest digit
103  for (int i = fractional_length - 1; i >= -integral_length; i--) {
104 
105  int lhs_digit = 0;
106  if (0 <= lhs_exponent + i && lhs_exponent + i < (int)lhs.size()) {
107  lhs_digit = lhs[lhs_exponent + i];
108  }
109 
110  int rhs_digit = 0;
111  if (0 <= rhs_exponent + i && rhs_exponent + i < (int)rhs.size()) {
112  rhs_digit = rhs[rhs_exponent + i];
113  }
114 
115  if (lhs_digit < borrow) {
116  lhs_digit += (10 - borrow);
117  } else {
118  lhs_digit -= borrow;
119  borrow = 0;
120  }
121 
122  if (lhs_digit < rhs_digit) {
123  lhs_digit += 10;
124  borrow++;
125  }
126 
127  result.insert(result.begin(), lhs_digit - rhs_digit);
128  }
129 
130  return lhs_exponent;
131  }
132 
147  int multiply_vectors(
148  const std::vector<int>& lhs,
149  int lhs_exponent,
150  const std::vector<int>& rhs,
151  int rhs_exponent,
152  std::vector<int>& result
153  ) {
154 
155  // will keep the result number in vector in reverse order
156  // Digits: .123 | Exponent: -3 | .000123 <--- Number size is the Digits size less the exponent
157  // Digits: .123 | Exponent: 2 | 12.3
158  size_t new_size = lhs.size() + rhs.size();
159  if (lhs_exponent < 0) new_size -= lhs_exponent; // <--- Less the exponent
160  if (rhs_exponent < 0) new_size -= rhs_exponent; // <--- Less the exponent
161 
162  if (!result.empty()) result.clear();
163  for (int i = 0; i < (int)new_size; i++) result.push_back(0);
164  // TODO: Check why the assign method crashes.
165  //result.assign(new_size, 0);
166 
167  // Below two indexes are used to find positions
168  // in result.
169  auto i_n1 = (int) result.size() - 1;
170 
171  // Go from right to left in lhs
172  for (int i = (int)lhs.size()-1; i>=0; i--) {
173  int carry = 0;
174 
175  // To shift position to left after every
176  // multiplication of a digit in rhs
177  int i_n2 = 0;
178 
179  // Go from right to left in rhs
180  for (int j = (int)rhs.size()-1; j>=0; j--) {
181 
182  // Multiply current digit of second number with current digit of first number
183  // and add result to previously stored result at current position.
184  int sum = lhs[i]*rhs[j] + result[i_n1 - i_n2] + carry;
185 
186  // Carry for next iteration
187  carry = sum / 10;
188 
189  // Store result
190  result[i_n1 - i_n2] = sum % 10;
191 
192  i_n2++;
193  }
194 
195  // store carry in next cell
196  if (carry > 0) {
197  result[i_n1 - i_n2] += carry;
198  }
199 
200  // To shift position to left after every
201  // multiplication of a digit in lhs.
202  i_n1--;
203  }
204 
205  int fractional_part = ((int)lhs.size() - lhs_exponent) + ((int)rhs.size() - rhs_exponent);
206  int result_exponent = (int)result.size() - fractional_part;
207 
208  return result_exponent;
209  }
210 
220  void add_boundaries(const boundary &lhs,
221  const boundary &rhs,
222  boundary &result) {
223  if (lhs.positive == rhs.positive) {
224  result.exponent = add_vectors(lhs.digits,
225  lhs.exponent,
226  rhs.digits,
227  rhs.exponent,
228  result.digits);
229  result.positive = lhs.positive;
230  } else if (abs(rhs) < abs(lhs)) {
231  result.exponent = subtract_vectors(lhs.digits,
232  lhs.exponent,
233  rhs.digits,
234  rhs.exponent,
235  result.digits);
236  result.positive = lhs.positive;
237  } else {
238  result.exponent = subtract_vectors(rhs.digits,
239  rhs.exponent,
240  lhs.digits,
241  lhs.exponent,
242  result.digits);
243  result.positive = rhs.positive;
244  }
245 
246  result.normalize();
247  }
248 
258  void subtract_boundaries(const boundary &lhs,
259  const boundary &rhs,
260  boundary &result) {
261  if (lhs.positive != rhs.positive) {
262  result.exponent = add_vectors(lhs.digits,
263  lhs.exponent,
264  rhs.digits,
265  rhs.exponent,
266  result.digits);
267  result.positive = lhs.positive;
268  } else {
269 
270  if (abs(rhs) < abs(lhs)) {
271  result.exponent = subtract_vectors(lhs.digits,
272  lhs.exponent,
273  rhs.digits,
274  rhs.exponent,
275  result.digits);
276  result.positive = lhs.positive;
277  } else {
278  result.exponent = subtract_vectors(rhs.digits,
279  rhs.exponent,
280  lhs.digits,
281  lhs.exponent,
282  result.digits);
283  result.positive = !lhs.positive;
284  }
285  }
286 
287  result.normalize();
288  }
289 
299  void multiply_boundaries(const boundary &lhs,
300  const boundary &rhs,
301  boundary &result) {
302 
303  result.positive = lhs.positive == rhs.positive;
304  result.exponent = multiply_vectors(lhs.digits,
305  lhs.exponent,
306  rhs.digits,
307  rhs.exponent,
308  result.digits);
309 
310  result.normalize();
311  }
312  }
313  }
314 }
315 
316 #endif //BOOST_REAL_REAL_HELPERS_HPP
Definition: boundary.hpp:7