// Copyright (C) 2026 Kiyotsugu Arai // SPDX-License-Identifier: LGPL-3.0-or-later // RationalTraits.hpp // Trait specializations for the Rational type #ifndef SANGI_RATIONAL_TRAITS_HPP #define SANGI_RATIONAL_TRAITS_HPP #include namespace sangi { // Forward declarations struct real_tag; template struct numeric_traits; template struct numeric_state_traits; // numeric_traits specialization for Rational template<> struct numeric_traits { using value_type = Rational; using category = real_tag; static constexpr bool is_supported = true; static constexpr bool is_complex = false; static constexpr bool is_integer = false; static constexpr bool is_floating_point = false; static Rational zero() { return Rational(); } static Rational one() { return Rational(1); } static Rational epsilon() { return Rational(); } // The rationals are dense: no smallest unit → 0 static Rational abs(const Rational& value) { return sangi::abs(value); } /// Pivot selection: a smaller height (max(|numerator|, |denominator|)) is a better pivot. /// Helps suppress coefficient blow-up. static bool pivotBetter(const Rational& a, const Rational& b) { return height(a) < height(b); } static Rational conj(const Rational& value) { return value; // The conjugate of a real number is itself } static Rational norm(const Rational& value) { return abs(value); } static bool isNaN(const Rational& value) { return value.isNaN(); } static bool isInfinite(const Rational& /*value*/) { return false; // Rational has no infinities } static bool isFinite(const Rational& value) { return !value.isNaN(); } static int getSign(const Rational& value) { if (value.isNaN()) return 0; if (value.isZero()) return 0; return value.isNegative() ? -1 : 1; } }; // numeric_state_traits specialization for Rational template<> struct numeric_state_traits { static bool isNormal(const Rational& value) { return !value.isNaN() && !value.isZero(); } static bool isNaN(const Rational& value) { return value.isNaN(); } static bool isInfinite(const Rational& /*value*/) { return false; } static bool isDivergent(const Rational& /*value*/) { return false; } static bool isOverflow(const Rational& /*value*/) { return false; } static NumericState getState(const Rational& value) { if (value.isNaN()) return NumericState::NaN; return NumericState::Normal; } static NumericError getError(const Rational& value) { if (value.isNaN()) return NumericError::ExplicitNaN; return NumericError::None; } static int getSign(const Rational& value) { if (value.isNaN()) return 0; if (value.isZero()) return 0; return value.isNegative() ? -1 : 1; } }; } // namespace sangi #endif // SANGI_RATIONAL_TRAITS_HPP