/// <summary> /// Performs so-called downcasting, an attempt to narrow a number's affiliation to a number set /// It attempts to cast ComplexNumber to RealNumber, RealNumber to RationalNumber, RationalNumber to IntegerNumber /// </summary> /// <param name="a"> /// Number to downcast /// </param> /// <returns> /// Downcasted or kept Number /// </returns> public static Number Downcast(Number a) { if (!MathS.Settings.DowncastingEnabled) { return(a); } var res = SuperSwitch( num => (Result: num[0], Continue: false), (num) => { if (!(a as RealNumber).IsDefinite()) { return(Result: a, Continue: false); } var ratnum = num[0]; var gcd = Utils.GCD(ratnum.Denominator.Value, ratnum.Numerator.Value); ratnum = new RationalNumber( new IntegerNumber(ratnum.Numerator.Value / gcd), new IntegerNumber(ratnum.Denominator.Value / gcd) ); if (EDecimalWrapper.IsEqual(ratnum.Denominator.Value, 1)) { return(Result: ratnum.Numerator, Continue: false); } else { return(Result: ratnum, Continue: false); } }, (num) => { if (!(a as RealNumber).IsDefinite()) { return(Result: a, Continue: false); } var realnum = num[0]; if (TryCastToInt(realnum.Value, out var intres)) { return(Result: new IntegerNumber(intres), Continue: false); } var attempt = FindRational(realnum.Value, MathS.Settings.FloatToRationalIterCount); if (attempt is null || Number.Abs(attempt.Numerator) > MathS.Settings.MaxAbsNumeratorOrDenominatorValue || Number.Abs(attempt.Denominator) > MathS.Settings.MaxAbsNumeratorOrDenominatorValue) { return(Result: realnum, Continue: false); }