#include "function/arithmetic/negate.h"
#include "common/exception/overflow.h"
#include "common/type_utils.h"
#include "function/cast/functions/numeric_limits.h"
#include <format>
namespace lbug {
namespace function {
template<class SRC_TYPE>
static inline bool NegateInPlaceWithOverflowCheck(SRC_TYPE input, SRC_TYPE& result) {
if (input == NumericLimits<SRC_TYPE>::minimum()) {
return false;
}
result = -input;
return true;
}
struct NegateInPlace {
template<class T>
static inline bool operation(T& input, T& result);
};
template<>
bool inline NegateInPlace::operation(int8_t& input, int8_t& result) {
return NegateInPlaceWithOverflowCheck<int8_t>(input, result);
}
template<>
bool inline NegateInPlace::operation(int16_t& input, int16_t& result) {
return NegateInPlaceWithOverflowCheck<int16_t>(input, result);
}
template<>
bool inline NegateInPlace::operation(int32_t& input, int32_t& result) {
return NegateInPlaceWithOverflowCheck<int32_t>(input, result);
}
template<>
bool NegateInPlace::operation(int64_t& input, int64_t& result) {
return NegateInPlaceWithOverflowCheck<int64_t>(input, result);
}
template<>
void Negate::operation(int8_t& input, int8_t& result) {
if (!NegateInPlace::operation(input, result)) {
throw common::OverflowException{std::format("Value {} cannot be negated within INT8 range.",
common::TypeUtils::toString(input))};
}
}
template<>
void Negate::operation(int16_t& input, int16_t& result) {
if (!NegateInPlace::operation(input, result)) {
throw common::OverflowException{std::format(
"Value {} cannot be negated within INT16 range.", common::TypeUtils::toString(input))};
}
}
template<>
void Negate::operation(int32_t& input, int32_t& result) {
if (!NegateInPlace::operation(input, result)) {
throw common::OverflowException{std::format(
"Value {} cannot be negated within INT32 range.", common::TypeUtils::toString(input))};
}
}
template<>
void Negate::operation(int64_t& input, int64_t& result) {
if (!NegateInPlace::operation(input, result)) {
throw common::OverflowException{std::format(
"Value {} cannot be negated within INT64 range.", common::TypeUtils::toString(input))};
}
}
} }