73 lines
2.0 KiB
C++
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
|