using System; namespace ADOFAIRenderer.Util { internal static class RationalUtil { public static (int Numerator, int Denominator) Double2MaxPrecisionInt(double value, int maxDenominator = 100000000) { // 1. Edge case handling and sign detection if (value == 0.0) return (0, 1); var isNegative = value < 0; var target = Math.Abs(value); // 2. Stern-Brocot / continued fraction boundary initialization // Starts between (0/1, 1/0) and converges towards the target value. long m00 = 0, m01 = 1; long m10 = 1, m11 = 0; var x = target; // Iterate while preventing integer overflow while (true) { var ai = (long)Math.Floor(x); // Calculate next numerator and denominator (temporarily computed as long to prevent overflow) var nextNumerator = ai * m10 + m00; var nextDenominator = ai * m11 + m01; // If exceeding integer range or specified maximum denominator, return previous optimal value if (nextNumerator > int.MaxValue || nextDenominator > maxDenominator) { break; } // Update matrix m00 = m10; m01 = m11; m10 = nextNumerator; m11 = nextDenominator; // Terminate if error is negligible (precision limit reached) if (Math.Abs(x - ai) < 1e-15) break; // Prepare next continued fraction term x = 1.0 / (x - ai); } // 3. Final determined integer numerator and denominator var finalNumerator = (int)m10; var finalDenominator = (int)m11; // Restore sign if (isNegative) finalNumerator = -finalNumerator; return (finalNumerator, finalDenominator); } } }