Skip to content

Commit

Permalink
some minor refactors
Browse files Browse the repository at this point in the history
  • Loading branch information
Laouen committed Aug 2, 2018
1 parent 23f5904 commit 7f129f3
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 59 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ In boost::real, a number has one of the next three representations:
Because of the third representation type, a number resulting from a complex calculus is a binary tree where each internal vertex is an operation and the vertex children are its operands. The tree leaves are those numbers represented by either (1) or (2) while the internal vertex are those numbers represented by (3). More information about the used number representation can be found in [3]

## The boost::real precision iterator.
The boost::real::const_precision_iterator is a forward iterator [4] that iterates through the number interval precisions. The iterator returns two numbers, a lower and an upper bound that represent the [m<sub>k</sub> - e<sub>k</sub>, m<sub>k</sub> + e<sub>k</sub>] limits of the number for a given precision. Each time the iterator is incremented, the interval range is decreased and a new interval with a better precision is obtained. Normally, there is no need to interact with the precision iterator and it is used by the boost::real operators <<, < and >.
The boost::real::const_precision_iterator is a forward iterator [4] that iterates through the number interval precisions. The iterator returns two numbers, a lower and an upper bound that represent the [m<sub>k</sub> - e<sub>k</sub>, m<sub>k</sub> + e<sub>k</sub>] limits of the number for a given precision. Each time the iterator is incremented, the interval approximation_interval is decreased and a new interval with a better precision is obtained. Normally, there is no need to interact with the precision iterator and it is used by the boost::real operators <<, < and >.

## Interface

Expand Down Expand Up @@ -189,5 +189,5 @@ h: 0.000001
## References
1. Computable calculus / Oliver Aberth, San Diego : Academic Press, c2001
2. Lambov, B. (2007). RealLib: An efficient implementation of exact real arithmetic. Mathematical Structures in Computer Science, 17(1), 81-98.
3. Aberth, O., & Schaefer, M. J. (1992). Precise computation using range arithmetic, via C++. ACM Transactions on Mathematical Software (TOMS), 18(4), 481-491.
3. Aberth, O., & Schaefer, M. J. (1992). Precise computation using approximation_interval arithmetic, via C++. ACM Transactions on Mathematical Software (TOMS), 18(4), 481-491.
4. https://en.cppreference.com/w/cpp/concept/ForwardIterator
8 changes: 4 additions & 4 deletions include/real/interval.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,14 @@ namespace boost {
}

bool positive() const {
// If the lower bound of a range is positive, then the upper bound is also positive
// and the range is fully contained in the positive number line
// If the lower bound of a approximation_interval is positive, then the upper bound is also positive
// and the approximation_interval is fully contained in the positive number line
return this->lower_bound.positive;
}

bool negative() const {
// If the upper bound of a range is negative, then the lower bound is also negative
// and the range is fully contained in the negative number line
// If the upper bound of a approximation_interval is negative, then the lower bound is also negative
// and the approximation_interval is fully contained in the negative number line
return !this->upper_bound.positive;
}
};
Expand Down
11 changes: 6 additions & 5 deletions include/real/real.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ namespace boost {
const_precision_iterator* _lhs_it_ptr = nullptr;
const_precision_iterator* _rhs_it_ptr = nullptr;

// TODO: rename bounds to boundaries
void calculate_operation_bounds() {

switch (this->_real_ptr->_operation) {
Expand Down Expand Up @@ -223,7 +224,7 @@ namespace boost {

public:

// Number range boundaries
// Number approximation_interval boundaries
boost::real::interval range;

const_precision_iterator() = default;
Expand All @@ -236,12 +237,12 @@ namespace boost {

case KIND::EXPLICIT:
this->_explicit_it = this->_real_ptr->_explicit_number.cbegin();
this->range = this->_explicit_it.range;
this->range = this->_explicit_it.approximation_interval;
break;

case KIND::ALGORITHM:
this->_algorithmic_it = this->_real_ptr->_algorithmic_number.cbegin();
this->range = this->_algorithmic_it.range;
this->range = this->_algorithmic_it.approximation_interval;
break;

case KIND::OPERATION:
Expand All @@ -258,12 +259,12 @@ namespace boost {

case KIND::EXPLICIT:
++this->_explicit_it;
this->range = this->_explicit_it.range;
this->range = this->_explicit_it.approximation_interval;
break;

case KIND::ALGORITHM:
++this->_algorithmic_it;
this->range = this->_algorithmic_it.range;
this->range = this->_algorithmic_it.approximation_interval;
break;

case KIND::OPERATION:
Expand Down
42 changes: 21 additions & 21 deletions include/real/real_algorithm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,14 +30,14 @@ namespace boost {

void check_and_swap_bounds() {
if (!this->_real_ptr->_positive) {
this->range.swap_bounds();
this->approximation_interval.swap_bounds();
}
}

public:

// Number range boundaries
boost::real::interval range;
// Number approximation_interval boundaries
boost::real::interval approximation_interval;

const_precision_iterator() = default;

Expand All @@ -46,15 +46,15 @@ namespace boost {
explicit const_precision_iterator(real_algorithm const* ptr) : _real_ptr(ptr) {

for (int i = 0; i < this->_real_ptr->_exponent; i++) {
this->range.lower_bound.push_back((*this->_real_ptr)[i]);
this->range.upper_bound.push_back((*this->_real_ptr)[i]);
this->approximation_interval.lower_bound.push_back((*this->_real_ptr)[i]);
this->approximation_interval.upper_bound.push_back((*this->_real_ptr)[i]);
}

this->range.upper_bound.digits.at((uint)this->_real_ptr->_exponent - 1)++;
this->range.lower_bound.exponent = this->_real_ptr->_exponent;
this->range.upper_bound.exponent = this->_real_ptr->_exponent;
this->range.lower_bound.positive = this->_real_ptr->_positive;
this->range.upper_bound.positive = this->_real_ptr->_positive;
this->approximation_interval.upper_bound.digits.at((uint)this->_real_ptr->_exponent - 1)++;
this->approximation_interval.lower_bound.exponent = this->_real_ptr->_exponent;
this->approximation_interval.upper_bound.exponent = this->_real_ptr->_exponent;
this->approximation_interval.lower_bound.positive = this->_real_ptr->_positive;
this->approximation_interval.upper_bound.positive = this->_real_ptr->_positive;
this->_n = this->_real_ptr->_exponent;
this->check_and_swap_bounds();
}
Expand All @@ -66,25 +66,25 @@ namespace boost {
// bounds are swapped to come back to the negative representation.
this->check_and_swap_bounds();

this->range.lower_bound.push_back((*this->_real_ptr)[this->_n]);
this->approximation_interval.lower_bound.push_back((*this->_real_ptr)[this->_n]);

this->range.upper_bound.clear();
this->range.upper_bound.digits.resize(this->range.lower_bound.size());
this->approximation_interval.upper_bound.clear();
this->approximation_interval.upper_bound.digits.resize(this->approximation_interval.lower_bound.size());
int carry = 1;
for (int i = (int)this->range.lower_bound.size() - 1; i >= 0; --i) {
if (this->range.lower_bound[i] + carry == 10) {
this->range.upper_bound[i] = 0;
for (int i = (int)this->approximation_interval.lower_bound.size() - 1; i >= 0; --i) {
if (this->approximation_interval.lower_bound[i] + carry == 10) {
this->approximation_interval.upper_bound[i] = 0;
} else {
this->range.upper_bound[i] = this->range.lower_bound[i] + carry;
this->approximation_interval.upper_bound[i] = this->approximation_interval.lower_bound[i] + carry;
carry = 0;
}
}

if (carry > 0) {
this->range.upper_bound.push_front(carry);
this->range.upper_bound.exponent = this->range.lower_bound.exponent + 1;
this->approximation_interval.upper_bound.push_front(carry);
this->approximation_interval.upper_bound.exponent = this->approximation_interval.lower_bound.exponent + 1;
} else {
this->range.upper_bound.exponent = this->range.lower_bound.exponent;
this->approximation_interval.upper_bound.exponent = this->approximation_interval.lower_bound.exponent;
}

this->check_and_swap_bounds();
Expand Down Expand Up @@ -135,7 +135,7 @@ std::ostream& operator<<(std::ostream& os, const boost::real::real_algorithm& r)
for (int i = 0; i <= r.max_precision(); i++) {
++it;
}
os << it.range;
os << it.approximation_interval;
return os;
}

Expand Down
55 changes: 28 additions & 27 deletions include/real/real_explicit.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,27 +33,27 @@ namespace boost {
// Internal number to iterate
real_explicit const* _real_ptr = nullptr;

void check_and_swap_bounds() {
void check_and_swap_boundaries() {
if (!this->_real_ptr->_positive) {
this->range.swap_bounds();
this->approximation_interval.swap_bounds();
}
}

public:

// Number range boundaries
boost::real::interval range;
// Number approximation_interval boundaries
boost::real::interval approximation_interval;

const_precision_iterator() = default;

const_precision_iterator(const const_precision_iterator& other) = default;

explicit const_precision_iterator(real_explicit const* ptr) : _real_ptr(ptr) {
// Lower bound and upper bounds of the number integer part
this->range.lower_bound.exponent = this->_real_ptr->_exponent;
this->range.upper_bound.exponent = this->_real_ptr->_exponent;
this->range.lower_bound.positive = this->_real_ptr->_positive;
this->range.upper_bound.positive = this->_real_ptr->_positive;
this->approximation_interval.lower_bound.exponent = this->_real_ptr->_exponent;
this->approximation_interval.upper_bound.exponent = this->_real_ptr->_exponent;
this->approximation_interval.lower_bound.positive = this->_real_ptr->_positive;
this->approximation_interval.upper_bound.positive = this->_real_ptr->_positive;

for(int i = 0; i < this->_real_ptr->_exponent; i++) {
++(*this);
Expand All @@ -73,53 +73,54 @@ namespace boost {
// If the explicit number full precision has been already reached,
// then just add zeros at the boundaries ends
if (this->_n >= (int)this->_real_ptr->_digits.size()) {
this->range.lower_bound.push_back(0);
this->range.upper_bound.push_back(0);
// TODO: no need to add zeros at the end
this->approximation_interval.lower_bound.push_back(0);
this->approximation_interval.upper_bound.push_back(0);
this->_n++;
return;
}

// If the number is negative, boundaries are interpreted as mirrored:
// First, the operation is made as positive, and after bound calculation
// bounds are swapped to come back to the negative representation.
this->check_and_swap_bounds();
// First, the operation is made as positive, and after boundary calculation
// boundaries are swapped to come back to the negative representation.
this->check_and_swap_boundaries();

// If the explicit number just reaches the full precision
// then set both boundaries equals
if (this->_n == (int)this->_real_ptr->_digits.size() - 1) {

this->range.lower_bound.push_back(this->_real_ptr->_digits[this->_n]);
this->range.upper_bound = this->range.lower_bound;
this->approximation_interval.lower_bound.push_back(this->_real_ptr->_digits[this->_n]);
this->approximation_interval.upper_bound = this->approximation_interval.lower_bound;


} else {

// If the explicit number didn't reaches the full precision
// then the number interval is defined by truncation.
this->range.lower_bound.push_back(this->_real_ptr->_digits[this->_n]);
this->approximation_interval.lower_bound.push_back(this->_real_ptr->_digits[this->_n]);

this->range.upper_bound.clear();
this->range.upper_bound.digits.resize(this->range.lower_bound.size());
this->approximation_interval.upper_bound.clear();
this->approximation_interval.upper_bound.digits.resize(this->approximation_interval.lower_bound.size());

int carry = 1;
for (int i = (int)this->range.lower_bound.size() - 1; i >= 0; --i) {
if (this->range.lower_bound[i] + carry == 10) {
this->range.upper_bound[i] = 0;
for (int i = (int)this->approximation_interval.lower_bound.size() - 1; i >= 0; --i) {
if (this->approximation_interval.lower_bound[i] + carry == 10) {
this->approximation_interval.upper_bound[i] = 0;
} else {
this->range.upper_bound[i] = this->range.lower_bound[i] + carry;
this->approximation_interval.upper_bound[i] = this->approximation_interval.lower_bound[i] + carry;
carry = 0;
}
}

if (carry > 0) {
this->range.upper_bound.push_front(carry);
this->range.upper_bound.exponent = this->range.lower_bound.exponent + 1;
this->approximation_interval.upper_bound.push_front(carry);
this->approximation_interval.upper_bound.exponent = this->approximation_interval.lower_bound.exponent + 1;
} else {
this->range.upper_bound.exponent = this->range.lower_bound.exponent;
this->approximation_interval.upper_bound.exponent = this->approximation_interval.lower_bound.exponent;
}
}

this->check_and_swap_bounds();
this->check_and_swap_boundaries();
this->_n++;
}
};
Expand Down Expand Up @@ -167,7 +168,7 @@ std::ostream& operator<<(std::ostream& os, const boost::real::real_explicit& r)
for (int i = 0; i <= r.max_precision(); i++) {
++it;
}
os << it.range;
os << it.approximation_interval;
return os;
}

Expand Down

0 comments on commit 7f129f3

Please sign in to comment.