Skip to content

Commit

Permalink
complete implementation of all required procedures in exact_arithmeti…
Browse files Browse the repository at this point in the history
…c<> class
  • Loading branch information
sinandredemption committed Jul 30, 2021
1 parent 29a1ac3 commit 38f02d9
Show file tree
Hide file tree
Showing 2 changed files with 70 additions and 0 deletions.
69 changes: 69 additions & 0 deletions include/boost/multiprecision/cpp_double_float.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,18 @@ struct exact_arithmetic
return out;
}

static void sum(float_pair& p, float_type& e)
{
using std::tie;

float_pair t;
float_type t_;

t = sum(p.first, p.second);
tie(p.first, t_) = sum(e, t.first);
tie(p.second, e) = sum(t.second, t_);
}

static float_pair difference(const float_type& a, const float_type& b)
{
// Exact subtraction of two floating point numbers
Expand Down Expand Up @@ -294,6 +306,63 @@ struct exact_arithmetic

t = s;
}

static void normalize(float_tuple& t, float_type e)
{
using std::tie;
using std::get;

float_tuple s(0, 0, 0, 0);

tie(get<0>(s), e) = fast_sum(get<3>(t), e);
tie(get<0>(s), get<3>(t)) = fast_sum(get<2>(t), get<0>(s));
tie(get<0>(s), get<2>(t)) = fast_sum(get<1>(t), get<0>(s));
tie(get<0>(t), get<1>(t)) = fast_sum(get<0>(t), get<0>(s));

tie(get<0>(s), get<1>(s)) = std::make_tuple(get<0>(t), get<1>(t));

if (get<1>(s) != 0)
{
tie(get<1>(s), get<2>(s)) = fast_sum(get<1>(s), get<2>(t));
if (get<2>(s) != 0)
{
tie(get<2>(s), get<3>(s)) = fast_sum(get<2>(s), get<3>(t));
if (get<3>(s) != 0)
get<3>(s) += e;
else tie(get<2>(s), get<3>(s)) = fast_sum(get<2>(s), e);
}
else
{
tie(get<1>(s), get<2>(s)) = fast_sum(get<1>(s), get<3>(t));
if (get<2>(s) != 0)
tie(get<2>(s), get<3>(s)) = fast_sum(get<2>(s), e);
else
tie(get<1>(s), get<2>(s)) = fast_sum(get<1>(s), e);
}
}
else
{
tie(get<0>(s), get<1>(s)) = fast_sum(get<0>(s), get<2>(t));
if (get<1>(s) != 0)
{
tie(get<1>(s), get<2>(s)) = fast_sum(get<1>(s), get<3>(t));
if (get<2>(s) != 0)
tie(get<2>(s), get<3>(s)) = fast_sum(get<2>(s), e);
else
tie(get<1>(s), get<2>(s)) = fast_sum(get<1>(s), e);
}
else
{
tie(get<0>(s), get<1>(s)) = fast_sum(get<0>(s), get<3>(t));
if (get<1>(s) != 0)
tie(get<1>(s), get<2>(s)) = fast_sum(get<1>(s), e);
else
tie(get<0>(s), get<1>(s)) = fast_sum(get<0>(s), e);
}
}

t = s;
}
};

} // namespace detail
Expand Down
1 change: 1 addition & 0 deletions include/boost/multiprecision/cpp_quad_float.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,7 @@ class cpp_quad_float
public:
using float_type = FloatingPointType;
using rep_type = std::tuple<float_type, float_type, float_type, float_type>;
using arithmetic = detail::exact_arithmetic<float_type>;

using signed_types = std::tuple<signed char, signed short, signed int, signed long, signed long long, std::intmax_t>;
using unsigned_types = std::tuple<unsigned char, unsigned short, unsigned int, unsigned long, unsigned long long, std::uintmax_t>;
Expand Down

4 comments on commit 38f02d9

@ckormanyos
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @sinandredemption this looks like exciting, clean work Fahad. It'll bee cool to start fashioning the cpp_quad_float class and in a while see how it plays.

Nice!

@sinandredemption
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, glad that you like it @ckormanyos :)

Please tell me if you have any suggestions on the exact_arithmetic class, and if you think this should be moved to a separate file of its own.

@ckormanyos
Copy link
Member

@ckormanyos ckormanyos commented on 38f02d9 Aug 1, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tell me if you have any suggestions on the exact_arithmetic

Sure. I have several thoughts.

I think the location within the cpp_double_float.hpp header is a good choice. I am rather sure that cpp_quad_float.hpp will also include cpp_double_float.hpp. So each class wil lhave access to these mathematical primitives.

Why am I so sure that quad-float might include double-float? Although I do want to keep these classes as separate as possible, there will be some situations, such as eval_log() where it is highly convenient to first compute the exp() function at half precision and use one iterative step to obtain full precision. This is convenient and we might use it for the pairs eval_exp()/eval_log(), eval_sin()/eval_asin(), etc.

exact_arithmetic is something that could potentially help when constexpr-ifying parts of cpp_double_float and cpp_quad_float. So you might want to look at some of the subroutines and asses them regarding how you could maybe make them C++11 constexpr correct. It seems like the function split() might be a central part of that. This is something we can do later.

Another question I have is if the use of std::tie is invisible regarding runtime overhead or not? It might make sense to actually check if using these functions incure overhead, or if they disappear when compiling with optimization on. I do not have that much experience with tie, so I'm not sure. I know that STL container and algorithm stuff is mostly invisible, but some artifacts (rare indeed, but often used) are, in fact, significantly slower from the Library.

The first step in all this is to first get the mathematics numerically correct. We usually say, get it working, then optimize it. I also find the process of full constexpr-ification to actually be better suited for a class when it is running deep within a test system. Then successively make parts of it constexpr while running the tests with each and every change along the way. So in summary, get it working, then optimize and constexpr-ify.

Along the lines of getting stuff working, I will continue to bind cpp_double_float into more rigorous Boost-style testing with the JAM file and needed code changes in the test files. So when you are getting finished with cpp_quad_float we can readily go through the same testing or a very similar procedure for it.

@sinandredemption and @cosurgi

@cosurgi
Copy link
Collaborator

@cosurgi cosurgi commented on 38f02d9 Aug 3, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if the use of std::tie is invisible regarding runtime overhead or not?

Interesting point to check later. I would expect it to become invisible in newer compilers, namely those that support structured binding.

Please sign in to comment.