I would like to write a family of functions for different integers types INT whose signature is
INT safe_product(INT a, INT b, bool& error);
which takes two integers a and b and returns a * b if a * b does not overflow and returns 0 and sets error to true if a * b does overflow. I also want this function to be efficient and I want it to run on 32-bit and 64-bit platforms.
I am thinking of overloading safe_product using std::int32_t
, std::uint32_t
, std::int64_t
, std::uint64_t
, etc. I believe that std::int64_t
is not always defined with a 32-bit compiler. Is there a way to know at compile time if it is defined?
Moreover, if we are on a 64-bit plateform, the best way to implement a safe product in between 2 32-bit integers is the following:
std::int32_t safe_product(std::int32_t a, std::int32_t b,
bool& error) {
const std::int64_t a_64 = a;
const std::int64_t b_64 = b;
const std::int64_t ab_64 = a_64 * b_64;
if (ab_64 > std::numeric_limits<std::int32_t>::max() ||
ab_64 < std::numeric_limits<std::int32_t>::min()) {
error = true;
return 0;
} else {
error = false;
return static_cast<std::int32_t>(ab_64);
}
}
but if we are a 32-bit platform, the fastest algorithm might imply computing some integer division.
So I have 2 questions:
How do I declare my
safe_product
so it is defined for all integers types available on my platform (and obviously not for the ones that don't exist)?How do I make it efficient on both 32-bit and 64-bit using the algorithms I know?