#include #include #include #include #include #include "prx/libc/include/General.hpp" namespace { using Int128 = __int128; using Uint128 = unsigned __int128; constexpr std::uint32_t DefaultMxcsr = 0x1f80; template struct FloatFormat; template<> struct FloatFormat { using Rep = std::uint32_t; static constexpr int SignificandBits = 23; static constexpr int Bias = 127; static constexpr int MaxBiased = 0xff; }; template<> struct FloatFormat { using Rep = std::uint64_t; static constexpr int SignificandBits = 52; static constexpr int Bias = 1023; static constexpr int MaxBiased = 0x7ff; }; template struct Decomposed { bool negative; int exponent; typename FloatFormat::Rep significand; }; template Decomposed Decompose(TFloat value) { using Format = FloatFormat; using Rep = typename Format::Rep; const Rep bits = std::bit_cast(value); const Rep implicitBit = static_cast(1) << Format::SignificandBits; const int biased = static_cast((bits >> Format::SignificandBits) & Format::MaxBiased); return {(bits >> (sizeof(Rep) * 8 - 1)) != 0, biased - Format::Bias, (bits & (implicitBit - 1)) | implicitBit}; } struct ExtendedBits { std::uint64_t mantissa; bool negative; int exponent; }; ExtendedBits DecomposeExtended(long double value) { unsigned char bytes[sizeof(long double)]; std::memcpy(bytes, &value, sizeof(bytes)); std::uint64_t mantissa; std::uint16_t signExponent; std::memcpy(&mantissa, bytes, sizeof(mantissa)); std::memcpy(&signExponent, bytes + 8, sizeof(signExponent)); return {mantissa, (signExponent & 0x8000u) != 0, static_cast(signExponent & 0x7fffu) - 16383}; } long double ComposeExtended(bool negative, int biased, std::uint64_t mantissa) { unsigned char bytes[sizeof(long double)] = {}; const std::uint16_t signExponent = static_cast((negative ? 0x8000u : 0u) | static_cast(biased)); std::memcpy(bytes, &mantissa, sizeof(mantissa)); std::memcpy(bytes + 8, &signExponent, sizeof(signExponent)); long double value; std::memcpy(&value, bytes, sizeof(value)); return value; } template constexpr int ShiftMask = static_cast(sizeof(TShift) * 8 - 1); template TShift ShiftSignificand(const Decomposed& parts) { constexpr int significandBits = FloatFormat::SignificandBits; const TShift significand = parts.significand; if (parts.exponent < significandBits) return significand >> (significandBits - parts.exponent); return significand << ((parts.exponent - significandBits) & ShiftMask); } template TResult FixSigned(TFloat value) { const Decomposed parts = Decompose(value); if (parts.exponent < 0) return 0; const TShift magnitude = ShiftSignificand(parts); return static_cast(parts.negative ? static_cast(0) - magnitude : magnitude); } template TResult FixUnsigned(TFloat value) { const Decomposed parts = Decompose(value); if (parts.negative || parts.exponent < 0) return 0; return ShiftSignificand(parts); } template TResult FixExtendedSigned(long double value) { const ExtendedBits parts = DecomposeExtended(value); if (parts.exponent < 0) return 0; TResult magnitude; if constexpr (sizeof(TResult) == 16) { const Uint128 mantissa = parts.mantissa; magnitude = static_cast(parts.exponent < 64 ? mantissa >> (63 - parts.exponent) : mantissa << ((parts.exponent - 63) & 127)); } else { magnitude = static_cast(parts.mantissa >> ((63 - parts.exponent) & 63)); } using TUnsigned = std::conditional_t; const TUnsigned bits = static_cast(magnitude); return static_cast(parts.negative ? static_cast(0) - bits : bits); } template TResult FixExtendedUnsigned(long double value) { const ExtendedBits parts = DecomposeExtended(value); if (parts.negative || parts.exponent < 0) return 0; if constexpr (sizeof(TResult) == 16) { const Uint128 mantissa = parts.mantissa; return parts.exponent < 64 ? mantissa >> (63 - parts.exponent) : mantissa << ((parts.exponent - 63) & 127); } else if constexpr (sizeof(TResult) == 8) { return parts.mantissa >> ((63 - parts.exponent) & 63); } else { return static_cast(parts.mantissa >> 32) >> ((31 - parts.exponent) & 31); } } int HighestBit(Uint128 value) { const std::uint64_t high = static_cast(value >> 64); return high != 0 ? 127 - std::countl_zero(high) : 63 - std::countl_zero(static_cast(value)); } template TFloat RoundToFloat(bool negative, Uint128 magnitude) { using Format = FloatFormat; using Rep = typename Format::Rep; const Rep sign = negative ? static_cast(1) << (sizeof(Rep) * 8 - 1) : 0; if (magnitude == 0) return std::bit_cast(sign); int exponent = HighestBit(magnitude); Uint128 significand; if (exponent <= Format::SignificandBits) { significand = magnitude << (Format::SignificandBits - exponent); } else { const int shift = exponent - Format::SignificandBits; significand = magnitude >> shift; const Uint128 rest = magnitude & ((static_cast(1) << shift) - 1); const Uint128 half = static_cast(1) << (shift - 1); if (rest > half || (rest == half && (significand & 1) != 0)) ++significand; if (significand >> (Format::SignificandBits + 1) != 0) { significand >>= 1; ++exponent; } } const int biased = exponent + Format::Bias; if (biased >= Format::MaxBiased) return std::bit_cast(static_cast(sign | (static_cast(Format::MaxBiased) << Format::SignificandBits))); const Rep fraction = static_cast(significand) & ((static_cast(1) << Format::SignificandBits) - 1); return std::bit_cast(static_cast(sign | (static_cast(biased) << Format::SignificandBits) | fraction)); } long double RoundToExtended(bool negative, Uint128 magnitude) { if (magnitude == 0) return ComposeExtended(negative, 0, 0); int exponent = HighestBit(magnitude); Uint128 significand; if (exponent <= 63) { significand = magnitude << (63 - exponent); } else { const int shift = exponent - 63; significand = magnitude >> shift; const Uint128 rest = magnitude & ((static_cast(1) << shift) - 1); const Uint128 half = static_cast(1) << (shift - 1); if (rest > half || (rest == half && (significand & 1) != 0)) ++significand; if (significand >> 64 != 0) { significand >>= 1; ++exponent; } } return ComposeExtended(negative, exponent + 16383, static_cast(significand)); } Uint128 Magnitude(Int128 value) { return value < 0 ? static_cast(0) - static_cast(value) : static_cast(value); } template bool IsNan(TFloat value) { using Format = FloatFormat; using Rep = typename Format::Rep; const Rep magnitude = std::bit_cast(value) & (~static_cast(0) >> 1); return magnitude > (static_cast(Format::MaxBiased) << Format::SignificandBits); } template TFloat QuietNan() { using Format = FloatFormat; using Rep = typename Format::Rep; return std::bit_cast(static_cast((static_cast(Format::MaxBiased) << Format::SignificandBits) | (static_cast(1) << (Format::SignificandBits - 1)))); } template TFloat Negate(TFloat value) { using Rep = typename FloatFormat::Rep; return std::bit_cast(static_cast(std::bit_cast(value) ^ (static_cast(1) << (sizeof(Rep) * 8 - 1)))); } template TFloat GeneratedNan(TFloat result, TFloat a, TFloat b) { return IsNan(result) && !IsNan(a) && !IsNan(b) ? QuietNan() : result; } double AddDouble(double a, double b) { std::uint32_t saved = 0; asm volatile("stmxcsr %[saved]\n\tldmxcsr %[standard]\n\taddsd %[b], %[a]\n\tldmxcsr %[saved]" : [a] "+x"(a), [saved] "+m"(saved) : [b] "x"(b), [standard] "m"(DefaultMxcsr)); return a; } double MultiplyDouble(double a, double b) { std::uint32_t saved = 0; asm volatile("stmxcsr %[saved]\n\tldmxcsr %[standard]\n\tmulsd %[b], %[a]\n\tldmxcsr %[saved]" : [a] "+x"(a), [saved] "+m"(saved) : [b] "x"(b), [standard] "m"(DefaultMxcsr)); return a; } double DivideDouble(double a, double b) { std::uint32_t saved = 0; asm volatile("stmxcsr %[saved]\n\tldmxcsr %[standard]\n\tdivsd %[b], %[a]\n\tldmxcsr %[saved]" : [a] "+x"(a), [saved] "+m"(saved) : [b] "x"(b), [standard] "m"(DefaultMxcsr)); return a; } float AddFloat(float a, float b) { std::uint32_t saved = 0; asm volatile("stmxcsr %[saved]\n\tldmxcsr %[standard]\n\taddss %[b], %[a]\n\tldmxcsr %[saved]" : [a] "+x"(a), [saved] "+m"(saved) : [b] "x"(b), [standard] "m"(DefaultMxcsr)); return a; } float MultiplyFloat(float a, float b) { std::uint32_t saved = 0; asm volatile("stmxcsr %[saved]\n\tldmxcsr %[standard]\n\tmulss %[b], %[a]\n\tldmxcsr %[saved]" : [a] "+x"(a), [saved] "+m"(saved) : [b] "x"(b), [standard] "m"(DefaultMxcsr)); return a; } float DivideFloat(float a, float b) { std::uint32_t saved = 0; asm volatile("stmxcsr %[saved]\n\tldmxcsr %[standard]\n\tdivss %[b], %[a]\n\tldmxcsr %[saved]" : [a] "+x"(a), [saved] "+m"(saved) : [b] "x"(b), [standard] "m"(DefaultMxcsr)); return a; } constexpr std::uint32_t TowardZeroMxcsr = DefaultMxcsr | 0x6000; double DivideDoubleTowardZero(double a, double b) { std::uint32_t saved = 0; asm volatile("stmxcsr %[saved]\n\tldmxcsr %[standard]\n\tdivsd %[b], %[a]\n\tldmxcsr %[saved]" : [a] "+x"(a), [saved] "+m"(saved) : [b] "x"(b), [standard] "m"(TowardZeroMxcsr)); return a; } float DivideFloatTowardZero(float a, float b) { std::uint32_t saved = 0; asm volatile("stmxcsr %[saved]\n\tldmxcsr %[standard]\n\tdivss %[b], %[a]\n\tldmxcsr %[saved]" : [a] "+x"(a), [saved] "+m"(saved) : [b] "x"(b), [standard] "m"(TowardZeroMxcsr)); return a; } template TFloat FlushSubnormalQuotient(TFloat quotient, TFloat truncated) { using Format = FloatFormat; using Rep = typename Format::Rep; const Rep signBit = static_cast(1) << (sizeof(Rep) * 8 - 1); const Rep magnitude = std::bit_cast(truncated) & ~signBit; if (magnitude >= (static_cast(1) << Format::SignificandBits)) return quotient; return std::bit_cast(static_cast(std::bit_cast(truncated) & signBit)); } float TruncateDouble(double value) { std::uint32_t saved = 0; float result; asm volatile("stmxcsr %[saved]\n\tldmxcsr %[standard]\n\tcvtsd2ss %[value], %[result]\n\tldmxcsr %[saved]" : [result] "=x"(result), [saved] "+m"(saved) : [value] "x"(value), [standard] "m"(DefaultMxcsr)); return result; } double ExtendFloat(float value) { const std::uint32_t bits = std::bit_cast(value); const std::uint64_t sign = static_cast(bits >> 31) << 63; const std::uint32_t magnitude = bits & 0x7fffffffu; if (magnitude >= 0x7f800000u) return std::bit_cast(sign | 0x7ff0000000000000ull | (static_cast(magnitude & 0x400000u) << 29) | (magnitude & 0x3fffffu)); if (magnitude >= 0x00800000u) return std::bit_cast(sign | ((static_cast(magnitude) << 29) + (static_cast(1023 - 127) << 52))); if (magnitude == 0) return std::bit_cast(sign); const int shift = std::countl_zero(magnitude) - 8; const std::uint64_t fraction = static_cast(magnitude << shift) & 0x7fffffu; const std::uint64_t biased = static_cast(1023 - 126 - shift); return std::bit_cast(sign | (biased << 52) | (fraction << 29)); } template int LessEqual(TFloat a, TFloat b, int unordered) { using Rep = typename FloatFormat::Rep; using Signed = std::make_signed_t; if (IsNan(a) || IsNan(b)) return unordered; const Rep aBits = std::bit_cast(a), bBits = std::bit_cast(b); const Rep magnitudeMask = ~static_cast(0) >> 1; if (((aBits | bBits) & magnitudeMask) == 0) return 0; const Signed aInt = static_cast(aBits), bInt = static_cast(bBits); if ((aInt & bInt) >= 0) { if (aInt < bInt) return -1; return aInt == bInt ? 0 : 1; } if (aInt > bInt) return -1; return aInt == bInt ? 0 : 1; } template bool IsInfinite(TFloat value) { return std::isinf(value); } template TFloat Box(TFloat value) { return std::copysign(std::isinf(value) ? TFloat(1) : TFloat(0), value); } template TFloat ZeroIfNan(TFloat value) { return std::isnan(value) ? std::copysign(TFloat(0), value) : value; } template TFloat MultiplyAdd(TFloat a, TFloat b, TFloat product) { if constexpr (Fused) return std::fma(a, b, product); else return a * b + product; } template TFloat MultiplySubtract(TFloat a, TFloat b, TFloat product) { return MultiplyAdd(a, b, std::isnan(product) ? product : -product); } template void MultiplyComplex(TFloat a, TFloat b, TFloat c, TFloat d, TFloat& real, TFloat& imaginary) { const TFloat ac = a * c, bd = b * d, ad = a * d, bc = b * c; real = ac - bd; imaginary = bc + ad; if (!std::isnan(real) || !std::isnan(imaginary)) return; bool recalculate = false; if (IsInfinite(a) || IsInfinite(b)) { a = Box(a); b = Box(b); c = ZeroIfNan(c); d = ZeroIfNan(d); recalculate = true; } if (IsInfinite(c) || IsInfinite(d)) { c = Box(c); d = Box(d); a = ZeroIfNan(a); b = ZeroIfNan(b); recalculate = true; } if (!recalculate && (IsInfinite(ac) || IsInfinite(bd) || IsInfinite(ad) || IsInfinite(bc))) { a = ZeroIfNan(a); b = ZeroIfNan(b); c = ZeroIfNan(c); d = ZeroIfNan(d); recalculate = true; } if (recalculate) { real = MultiplySubtract(a, c, b * d) * static_cast(INFINITY); imaginary = MultiplyAdd(a, d, b * c) * static_cast(INFINITY); } } template TFloat Scale(TFloat value, int exponent) { return static_cast(std::scalbn(static_cast(value), exponent)); } template TFloat LargerMagnitude(TFloat c, TFloat d) { const TFloat magnitudeC = std::fabs(c), magnitudeD = std::fabs(d); if (std::isnan(magnitudeC)) return magnitudeD; if (std::isnan(magnitudeD)) return magnitudeC; return magnitudeC < magnitudeD ? magnitudeD : magnitudeC; } template void DivideComplex(TFloat a, TFloat b, TFloat c, TFloat d, TFloat& real, TFloat& imaginary) { int scale = 0; const TFloat logScale = std::logb(LargerMagnitude(c, d)); if (std::isfinite(logScale)) { scale = static_cast(logScale); c = Scale(c, -scale); d = Scale(d, -scale); } const TFloat denominator = MultiplyAdd(c, c, d * d); real = Scale(MultiplyAdd(c, a, d * b) / denominator, -scale); imaginary = Scale(MultiplySubtract(c, b, d * a) / denominator, -scale); if (!std::isnan(real) || !std::isnan(imaginary)) return; if (denominator == TFloat(0) && (!std::isnan(a) || !std::isnan(b))) { real = std::copysign(static_cast(INFINITY), c) * a; imaginary = std::copysign(static_cast(INFINITY), c) * b; } else if ((IsInfinite(a) || IsInfinite(b)) && std::isfinite(c) && std::isfinite(d)) { a = Box(a); b = Box(b); real = MultiplyAdd(a, c, b * d) * static_cast(INFINITY); imaginary = MultiplySubtract(b, c, d * a) * static_cast(INFINITY); } else if (IsInfinite(logScale) && logScale > TFloat(0) && std::isfinite(a) && std::isfinite(b)) { c = Box(c); d = Box(d); real = MultiplyAdd(a, c, d * b) * TFloat(0); imaginary = MultiplySubtract(b, c, d * a) * TFloat(0); } } using ComplexFloat = __complex__ float; using ComplexDouble = __complex__ double; using ComplexExtended = __complex__ long double; ComplexFloat MakeComplex(float real, float imaginary) { ComplexFloat result; __real__ result = real; __imag__ result = imaginary; return result; } ComplexDouble MakeComplex(double real, double imaginary) { ComplexDouble result; __real__ result = real; __imag__ result = imaginary; return result; } ComplexExtended MakeComplex(long double real, long double imaginary) { ComplexExtended result; __real__ result = real; __imag__ result = imaginary; return result; } } extern "C" { double APS5_VABI __adddf3_nid_postfix(double a, double b) { return GeneratedNan(AddDouble(a, b), a, b); } float APS5_VABI __addsf3_nid_postfix(float a, float b) { return GeneratedNan(AddFloat(a, b), a, b); } double APS5_VABI __subdf3_nid_postfix(double a, double b) { const double negated = Negate(b); return GeneratedNan(AddDouble(a, negated), a, negated); } float APS5_VABI __subsf3_nid_postfix(float a, float b) { const float negated = Negate(b); return GeneratedNan(AddFloat(a, negated), a, negated); } double APS5_VABI __muldf3_nid_postfix(double a, double b) { return GeneratedNan(MultiplyDouble(a, b), a, b); } float APS5_VABI __mulsf3_nid_postfix(float a, float b) { return GeneratedNan(MultiplyFloat(a, b), a, b); } double APS5_VABI __divdf3_nid_postfix(double a, double b) { if (IsNan(a) || IsNan(b)) return GeneratedNan(DivideDouble(a, b), a, b); return GeneratedNan(FlushSubnormalQuotient(DivideDouble(a, b), DivideDoubleTowardZero(a, b)), a, b); } float APS5_VABI __divsf3_nid_postfix(float a, float b) { if (IsNan(a) || IsNan(b)) return GeneratedNan(DivideFloat(a, b), a, b); return GeneratedNan(FlushSubnormalQuotient(DivideFloat(a, b), DivideFloatTowardZero(a, b)), a, b); } double APS5_VABI __negdf2_nid_postfix(double a) { return Negate(a); } float APS5_VABI __negsf2_nid_postfix(float a) { return Negate(a); } int APS5_VABI __eqdf2_nid_postfix(double a, double b) { return LessEqual(a, b, 1); } int APS5_VABI __nedf2_nid_postfix(double a, double b) { return LessEqual(a, b, 1); } int APS5_VABI __ltdf2_nid_postfix(double a, double b) { return LessEqual(a, b, 1); } int APS5_VABI __ledf2_nid_postfix(double a, double b) { return LessEqual(a, b, 1); } int APS5_VABI __gtdf2_nid_postfix(double a, double b) { return LessEqual(a, b, -1); } int APS5_VABI __gedf2_nid_postfix(double a, double b) { return LessEqual(a, b, -1); } int APS5_VABI __unorddf2_nid_postfix(double a, double b) { return IsNan(a) || IsNan(b) ? 1 : 0; } int APS5_VABI __eqsf2_nid_postfix(float a, float b) { return LessEqual(a, b, 1); } int APS5_VABI __nesf2_nid_postfix(float a, float b) { return LessEqual(a, b, 1); } int APS5_VABI __ltsf2_nid_postfix(float a, float b) { return LessEqual(a, b, 1); } int APS5_VABI __lesf2_nid_postfix(float a, float b) { return LessEqual(a, b, 1); } int APS5_VABI __gtsf2_nid_postfix(float a, float b) { return LessEqual(a, b, -1); } int APS5_VABI __gesf2_nid_postfix(float a, float b) { return LessEqual(a, b, -1); } int APS5_VABI __unordsf2_nid_postfix(float a, float b) { return IsNan(a) || IsNan(b) ? 1 : 0; } double APS5_VABI __extendsfdf2_nid_postfix(float a) { return ExtendFloat(a); } float APS5_VABI __truncdfsf2_nid_postfix(double a) { if (!IsNan(a)) return TruncateDouble(a); const std::uint64_t bits = std::bit_cast(a); return std::bit_cast(static_cast(((bits >> 32) & 0x80000000u) | 0x7fc00000u | (bits & 0x3fffffu))); } std::int32_t APS5_VABI __fixsfsi_nid_postfix(float a) { return FixSigned(a); } std::int64_t APS5_VABI __fixsfdi_nid_postfix(float a) { return FixSigned(a); } Int128 APS5_VABI __fixsfti_nid_postfix(float a) { return FixSigned(a); } std::int32_t APS5_VABI __fixdfsi_nid_postfix(double a) { return FixSigned(a); } std::int64_t APS5_VABI __fixdfdi_nid_postfix(double a) { return FixSigned(a); } Int128 APS5_VABI __fixdfti_nid_postfix(double a) { return FixSigned(a); } std::uint32_t APS5_VABI __fixunssfsi_nid_postfix(float a) { return FixUnsigned(a); } std::uint64_t APS5_VABI __fixunssfdi_nid_postfix(float a) { return FixUnsigned(a); } Uint128 APS5_VABI __fixunssfti_nid_postfix(float a) { return FixUnsigned(a); } std::uint32_t APS5_VABI __fixunsdfsi_nid_postfix(double a) { const Decomposed parts = Decompose(a); if (parts.negative || parts.exponent < 0) return 0; return static_cast(parts.significand >> 21) >> ((31 - parts.exponent) & 31); } std::uint64_t APS5_VABI __fixunsdfdi_nid_postfix(double a) { return FixUnsigned(a); } Uint128 APS5_VABI __fixunsdfti_nid_postfix(double a) { return FixUnsigned(a); } std::int64_t APS5_VABI __fixxfdi_nid_postfix(long double a) { return FixExtendedSigned(a); } Int128 APS5_VABI __fixxfti_nid_postfix(long double a) { return FixExtendedSigned(a); } std::uint32_t APS5_VABI __fixunsxfsi_nid_postfix(long double a) { return FixExtendedUnsigned(a); } std::uint64_t APS5_VABI __fixunsxfdi_nid_postfix(long double a) { return FixExtendedUnsigned(a); } Uint128 APS5_VABI __fixunsxfti_nid_postfix(long double a) { return FixExtendedUnsigned(a); } double APS5_VABI __floatsidf_nid_postfix(std::int32_t a) { return static_cast(a); } double APS5_VABI __floatunsidf_nid_postfix(std::uint32_t a) { return static_cast(a); } float APS5_VABI __floatsisf_nid_postfix(std::int32_t a) { return RoundToFloat(a < 0, Magnitude(a)); } float APS5_VABI __floatunsisf_nid_postfix(std::uint32_t a) { return RoundToFloat(false, a); } double APS5_VABI __floatdidf_nid_postfix(std::int64_t a) { return static_cast(a); } float APS5_VABI __floatdisf_nid_postfix(std::int64_t a) { return static_cast(a); } long double APS5_VABI __floatdixf_nid_postfix(std::int64_t a) { return static_cast(a); } double APS5_VABI __floatundidf_nid_postfix(std::uint64_t a) { return static_cast(a); } float APS5_VABI __floatundisf_nid_postfix(std::uint64_t a) { return static_cast(a); } long double APS5_VABI __floatundixf_nid_postfix(std::uint64_t a) { return static_cast(a); } double APS5_VABI __floattidf_nid_postfix(Int128 a) { return RoundToFloat(a < 0, Magnitude(a)); } float APS5_VABI __floattisf_nid_postfix(Int128 a) { return RoundToFloat(a < 0, Magnitude(a)); } long double APS5_VABI __floattixf_nid_postfix(Int128 a) { return RoundToExtended(a < 0, Magnitude(a)); } double APS5_VABI __floatuntidf_nid_postfix(Uint128 a) { return RoundToFloat(false, a); } float APS5_VABI __floatuntisf_nid_postfix(Uint128 a) { return RoundToFloat(false, a); } long double APS5_VABI __floatuntixf_nid_postfix(Uint128 a) { return RoundToExtended(false, a); } __complex__ float APS5_VABI __mulsc3_nid_postfix(float a, float b, float c, float d) { float real, imaginary; MultiplyComplex(a, b, c, d, real, imaginary); return MakeComplex(real, imaginary); } __complex__ double APS5_VABI __muldc3_nid_postfix(double a, double b, double c, double d) { double real, imaginary; MultiplyComplex(a, b, c, d, real, imaginary); return MakeComplex(real, imaginary); } __complex__ long double APS5_VABI __mulxc3_nid_postfix(long double a, long double b, long double c, long double d) { long double real, imaginary; MultiplyComplex(a, b, c, d, real, imaginary); return MakeComplex(real, imaginary); } __complex__ float APS5_VABI __divsc3_nid_postfix(float a, float b, float c, float d) { float real, imaginary; DivideComplex(a, b, c, d, real, imaginary); return MakeComplex(real, imaginary); } __complex__ double APS5_VABI __divdc3_nid_postfix(double a, double b, double c, double d) { double real, imaginary; DivideComplex(a, b, c, d, real, imaginary); return MakeComplex(real, imaginary); } __complex__ long double APS5_VABI __divxc3_nid_postfix(long double a, long double b, long double c, long double d) { long double real, imaginary; DivideComplex(a, b, c, d, real, imaginary); return MakeComplex(real, imaginary); } long double APS5_VABI __powixf2_nid_postfix(long double base, int exponent) { const bool reciprocal = exponent < 0; long double result = (exponent & 1) != 0 ? base : 1.0L; for (exponent /= 2; exponent != 0; exponent /= 2) { base *= base; if (exponent & 1) result *= base; } return reciprocal ? 1 / result : result; } }