cpp_mp/mp_math.hpp
2025-09-27 15:56:12 +02:00

73 lines
2.0 KiB
C++

#pragma once
#include <algorithm>
#include <cstddef>
#include <cstdint>
#include <stdexcept>
namespace mp
{
struct Addition
{
template <class TR, class TLhs, class TRhs> static void Op(TR& r, const TLhs& lhs, const TRhs& rhs)
{
static_assert(std::is_same_v<typename TR::ElementType, typename TLhs::ElementType>);
static_assert(std::is_same_v<typename TR::ElementType, typename TRhs::ElementType>);
using ElementType = TR::ElementType;
ElementType carry = 0;
size_t end = std::max(lhs.GetNumElements(), rhs.GetNumElements());
for (size_t i = 0; i < end; ++i)
{
ElementType a = lhs.GetElement(i);
ElementType b = rhs.GetElement(i);
ElementType c = carry + a;
carry = (c < a) ? 1 : 0;
c += b;
carry |= (c < b) ? 1 : 0;
r.SetElement(i, c);
// carry = (((a + carry) > (ELEMENT_MAX - b)) || (a > (ELEMENT_MAX - carry))) ? 1 : 0;
}
r.SetElement(end, carry);
}
};
struct Subtraction
{
template <class TR, class TLhs, class TRhs> static void Op(TR& r, const TLhs& lhs, const TRhs& rhs)
{
static_assert(std::is_same_v<typename TR::ElementType, typename TLhs::ElementType>);
static_assert(std::is_same_v<typename TR::ElementType, typename TRhs::ElementType>);
using ElementType = TR::ElementType;
ElementType borrow = 0;
size_t end = std::max(lhs.GetNumElements(), rhs.GetNumElements());
for (size_t i = 0; i < end; ++i)
{
ElementType a = lhs.GetElement(i);
ElementType b = rhs.GetElement(i);
ElementType c = a - b - borrow;
borrow = (a < b || (a - b) < borrow) ? 1 : 0;
r.SetElement(i, c);
}
if (borrow > 0)
{
throw std::runtime_error("Subtraction result negative");
}
// r.SetElement(end, borrow);
}
};
} // namespace mp