#pragma once #include #include #include #include namespace mp { struct Addition { template static void Op(TR& r, const TLhs& lhs, const TRhs& rhs) { static_assert(std::is_same_v); static_assert(std::is_same_v); 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 static void Op(TR& r, const TLhs& lhs, const TRhs& rhs) { static_assert(std::is_same_v); static_assert(std::is_same_v); 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