From ac99f43c840792b19bb8232846ab6f8c1b36d9b2 Mon Sep 17 00:00:00 2001 From: Rohan Nagar Date: Mon, 16 Jul 2018 19:53:35 -0700 Subject: [PATCH] Move Fractions library inside project (#194) * Move Fractions library inside project * Add README and license --- .../Fractions/Extensions/MathExt.cs | 128 +++++++ .../DefaultFractionFormatProvider.cs | 19 ++ .../Formatter/DefaultFractionFormatter.cs | 95 ++++++ .../Fractions/Fraction.CompareTo.cs | 61 ++++ .../Fractions/Fraction.Constructors.cs | 123 +++++++ .../Fractions/Fraction.ConvertFrom.cs | 314 ++++++++++++++++++ .../Fractions/Fraction.ConvertTo.cs | 96 ++++++ .../Fractions/Fraction.Equality.cs | 63 ++++ .../Fractions/Fraction.Math.cs | 192 +++++++++++ .../Fractions/Fraction.Operators.cs | 111 +++++++ .../Fractions/Fraction.ToString.cs | 55 +++ src/KubernetesClient/Fractions/Fraction.cs | 81 +++++ .../Fractions/FractionState.cs | 17 + .../Fractions/InvalidNumberException.cs | 14 + src/KubernetesClient/Fractions/README.md | 6 + .../TypeConverters/FractionTypeConverter.cs | 96 ++++++ src/KubernetesClient/Fractions/license.txt | 22 ++ src/KubernetesClient/KubernetesClient.csproj | 1 - 18 files changed, 1493 insertions(+), 1 deletion(-) create mode 100644 src/KubernetesClient/Fractions/Extensions/MathExt.cs create mode 100644 src/KubernetesClient/Fractions/Formatter/DefaultFractionFormatProvider.cs create mode 100644 src/KubernetesClient/Fractions/Formatter/DefaultFractionFormatter.cs create mode 100644 src/KubernetesClient/Fractions/Fraction.CompareTo.cs create mode 100644 src/KubernetesClient/Fractions/Fraction.Constructors.cs create mode 100644 src/KubernetesClient/Fractions/Fraction.ConvertFrom.cs create mode 100644 src/KubernetesClient/Fractions/Fraction.ConvertTo.cs create mode 100644 src/KubernetesClient/Fractions/Fraction.Equality.cs create mode 100644 src/KubernetesClient/Fractions/Fraction.Math.cs create mode 100644 src/KubernetesClient/Fractions/Fraction.Operators.cs create mode 100644 src/KubernetesClient/Fractions/Fraction.ToString.cs create mode 100644 src/KubernetesClient/Fractions/Fraction.cs create mode 100644 src/KubernetesClient/Fractions/FractionState.cs create mode 100644 src/KubernetesClient/Fractions/InvalidNumberException.cs create mode 100644 src/KubernetesClient/Fractions/README.md create mode 100644 src/KubernetesClient/Fractions/TypeConverters/FractionTypeConverter.cs create mode 100644 src/KubernetesClient/Fractions/license.txt diff --git a/src/KubernetesClient/Fractions/Extensions/MathExt.cs b/src/KubernetesClient/Fractions/Extensions/MathExt.cs new file mode 100644 index 0000000..e13aecd --- /dev/null +++ b/src/KubernetesClient/Fractions/Extensions/MathExt.cs @@ -0,0 +1,128 @@ +using System; + +namespace Fractions.Extensions { + internal static class MathExt { + /// + /// Checks for an even number. + /// + /// + /// true if the number is even. + public static bool IsEven(this long number) { + return (number & 1) == 0; + } + + /// + /// Checks for an odd number. + /// + /// + /// true if the number is odd. + public static bool IsOdd(this long number) { + return (number & 1) != 0; + } + + /// + /// Get the greatest common divisor (GCD) of and . + /// + /// First number. + /// Second number. + /// The largest positive integer that divides and without a remainder. + public static long GreatestCommonDivisor(long a, long b) { + a = Math.Abs(a); + b = Math.Abs(b); + + if (a == 0) { + // ggT(0, b) = b + // Denn alles teilt durch 0. + return b; + } + + if (b == 0) { + // ggT(a, 0) = a + return a; + } + + if (a == 1 || b == 1) { + // trivial + return 1; + } + + return a == b + ? a // Beide Zahlen sind identisch, wir haben bereits den ggT gefunden. + : BinaryGreatestCommonDivisorAlgorithm(a, b); + } + + private static long BinaryGreatestCommonDivisorAlgorithm(long a, long b) { + + // Solange 'a' und 'b' beide gerade Zahlen sind, teile die Zahlen durch 2 + // und merke wie oft dies möglich war in 'k'. + int k; + for (k = 0; (a | b).IsEven(); ++k) { + a >>= 1; // a = (a / 2); + b >>= 1; // b = (b / 2); + } + + // Teile 'a' solange durch 2 bis die Zahl ungerade ist. + while (a.IsEven()) { + a >>= 1; // a = (a / 2); + } + + // Ab hier ist 'a' definitiv ungerade. Für 'b' muss dies allerdings noch nicht gelten! + do { + // Teile 'b' solange durch 2 bis die Zahl ungerade ist. + while (b.IsEven()) { + b >>= 1; // b = (b / 2); + } + + // 'a' und 'b' sind hier beide ungerade. Falls 'a' >= 'b' + // muss der Inhalt beider Variablen geswappt werden, + // damit die notwendige Subtraktion durchgeführt werden + // kann. + if (a > b) { + var temp = b; + b = a; + a = temp; + } + + b = b - a; + + } while (b != 0); + + return a << k; // a * 2^k + } + + /// + /// Get the least common multiple (LCM) of and . + /// + /// The first number. + /// The second number. + /// The smallest positive integer that is divisible by both and or 0 if either or is 0 + /// If and are 0 + public static long LeastCommonMultiple(long a, long b) { + if (a == 0 && b == 0) { + throw new ArgumentException("The least common multiple is not defined if both numbers are zero."); + } + + a = Math.Abs(a); + b = Math.Abs(b); + + if (a == b) { + return a; + } + + // Es gilt LCM(a,b) = (|a*b|) / GCD(a,b) + + var gcd = GreatestCommonDivisor(a, b); + return a / gcd * b; + } + + /// + /// Returns true if there are remaining digits after the decimal point. + /// + /// A value with possible remaining digits + /// true if has digits after the decimal point + + public static bool RemainingDigitsAfterTheDecimalPoint(double remainingDigits) { + return Math.Abs(remainingDigits - Math.Floor(remainingDigits)) > double.Epsilon; + } + } +} diff --git a/src/KubernetesClient/Fractions/Formatter/DefaultFractionFormatProvider.cs b/src/KubernetesClient/Fractions/Formatter/DefaultFractionFormatProvider.cs new file mode 100644 index 0000000..f59ed25 --- /dev/null +++ b/src/KubernetesClient/Fractions/Formatter/DefaultFractionFormatProvider.cs @@ -0,0 +1,19 @@ +using System; + +namespace Fractions.Formatter { + /// + /// Default formatter. + /// + public class DefaultFractionFormatProvider : IFormatProvider { + /// + /// Singleton instance + /// + public static readonly IFormatProvider Instance = new DefaultFractionFormatProvider(); + + object IFormatProvider.GetFormat(Type formatType) { + return formatType == typeof (Fraction) + ? DefaultFractionFormatter.Instance + : null; + } + } +} \ No newline at end of file diff --git a/src/KubernetesClient/Fractions/Formatter/DefaultFractionFormatter.cs b/src/KubernetesClient/Fractions/Formatter/DefaultFractionFormatter.cs new file mode 100644 index 0000000..cb5a6e2 --- /dev/null +++ b/src/KubernetesClient/Fractions/Formatter/DefaultFractionFormatter.cs @@ -0,0 +1,95 @@ +using System; +using System.Globalization; +using System.Numerics; +using System.Text; + +namespace Fractions.Formatter { + internal class DefaultFractionFormatter : ICustomFormatter { + public static readonly ICustomFormatter Instance = new DefaultFractionFormatter(); + + public string Format(string format, object arg, IFormatProvider formatProvider) { + if (arg == null) { + return string.Empty; + } + + if (!(arg is Fraction)) { + throw new FormatException(string.Format("The type {0} is not supported.", arg.GetType())); + } + + var fraction = (Fraction)arg; + + if (string.IsNullOrEmpty(format) || format == "G") { + return FormatGeneral(fraction); + } + + var sb = new StringBuilder(32); + foreach (var character in format) { + switch (character) { + case 'G': + sb.Append(FormatGeneral(fraction)); + break; + case 'n': + sb.Append(fraction.Numerator.ToString(CultureInfo.InvariantCulture)); + break; + case 'd': + sb.Append(fraction.Denominator.ToString(CultureInfo.InvariantCulture)); + break; + case 'z': + sb.Append(FormatInteger(fraction)); + break; + case 'r': + sb.Append(FormatRemainder(fraction)); + break; + case 'm': + sb.Append(FormatMixed(fraction)); + break; + default: + sb.Append(character); + break; + } + } + return sb.ToString(); + } + + private static string FormatMixed(Fraction fraction) { + if (BigInteger.Abs(fraction.Numerator) < BigInteger.Abs(fraction.Denominator)) { + return FormatGeneral(fraction); + } + + var integer = fraction.Numerator / fraction.Denominator; + var remainder = Fraction.Abs(fraction - integer); + + return remainder.IsZero + ? integer.ToString(CultureInfo.InvariantCulture) + : string.Concat( + integer.ToString(CultureInfo.InvariantCulture), + " ", + FormatGeneral(remainder)); + } + + private static string FormatInteger(Fraction fraction) { + return (fraction.Numerator / fraction.Denominator) + .ToString(CultureInfo.InvariantCulture); + } + + private static string FormatRemainder(Fraction fraction) { + if (BigInteger.Abs(fraction.Numerator) < BigInteger.Abs(fraction.Denominator)) { + return FormatGeneral(fraction); + } + var integer = fraction.Numerator / fraction.Denominator; + var remainder = fraction - integer; + return FormatGeneral(remainder); + } + + private static string FormatGeneral(Fraction fraction) { + if (fraction.Denominator == BigInteger.One) { + return fraction.Numerator.ToString(CultureInfo.InvariantCulture); + + } + return string.Concat( + fraction.Numerator.ToString(CultureInfo.InvariantCulture), + "/", + fraction.Denominator.ToString(CultureInfo.InvariantCulture)); + } + } +} diff --git a/src/KubernetesClient/Fractions/Fraction.CompareTo.cs b/src/KubernetesClient/Fractions/Fraction.CompareTo.cs new file mode 100644 index 0000000..28dd6c7 --- /dev/null +++ b/src/KubernetesClient/Fractions/Fraction.CompareTo.cs @@ -0,0 +1,61 @@ +using System; +using System.Numerics; + +namespace Fractions { + public partial struct Fraction + { + /// + /// Compares the calculated value with the supplied . + /// + /// Fraction that shall be compared with. + /// + /// Less than 0 if is greater. + /// Zero (0) if both calculated values are equal. + /// Greater then zero (0) if less. + /// If is not of type . + public int CompareTo(object other) { + if (other == null) { + return 1; + } + + if (other.GetType() != typeof(Fraction)) { + throw new ArgumentException( + string.Format("The comparing instance must be of type {0}. The supplied argument is of type {1}", GetType(), other.GetType()), nameof(other)); + } + + return CompareTo((Fraction)other); + } + + /// + /// Compares the calculated value with the supplied . + /// + /// Fraction that shall be compared with. + /// + /// Less than 0 if is greater. + /// Zero (0) if both calculated values are equal. + /// Greater then zero (0) if less. + + public int CompareTo(Fraction other) { + if (_denominator == other._denominator) { + return _numerator.CompareTo(other._numerator); + } + + if (IsZero != other.IsZero) { + if (IsZero) { + return other.IsPositive ? -1 : 1; + } + return IsPositive ? 1 : -1; + } + + var gcd = BigInteger.GreatestCommonDivisor(_denominator, other._denominator); + + var thisMultiplier = BigInteger.Divide(_denominator, gcd); + var otherMultiplier = BigInteger.Divide(other._denominator, gcd); + + var a = BigInteger.Multiply(_numerator, otherMultiplier); + var b = BigInteger.Multiply(other._numerator, thisMultiplier); + + return a.CompareTo(b); + } + } +} diff --git a/src/KubernetesClient/Fractions/Fraction.Constructors.cs b/src/KubernetesClient/Fractions/Fraction.Constructors.cs new file mode 100644 index 0000000..0d04610 --- /dev/null +++ b/src/KubernetesClient/Fractions/Fraction.Constructors.cs @@ -0,0 +1,123 @@ +using System; +using System.Numerics; + +namespace Fractions { + public partial struct Fraction + { + /// + /// Create a fraction with , and the fraction' . + /// Warning: if you use unreduced values combined with a state of + /// you will get wrong results when working with the fraction value. + /// + /// + /// + /// + private Fraction(BigInteger numerator, BigInteger denominator, FractionState state) { + _numerator = numerator; + _denominator = denominator; + _state = state; + } + + /// + /// Creates a normalized (reduced/simplified) fraction using and . + /// + /// Numerator + /// Denominator + public Fraction(BigInteger numerator, BigInteger denominator) + : this(numerator, denominator, true) { } + + /// + /// Creates a normalized (reduced/simplified) or unnormalized fraction using and . + /// + /// Numerator + /// Denominator + /// If true the fraction will be created as reduced/simplified fraction. + /// This is recommended, especially if your applications requires that the results of the equality methods + /// and are always the same. (1/2 != 2/4) + public Fraction(BigInteger numerator, BigInteger denominator, bool normalize) { + if (normalize) { + this = GetReducedFraction(numerator, denominator); + return; + } + + _state = numerator.IsZero && denominator.IsZero + ? FractionState.IsNormalized + : FractionState.Unknown; + + _numerator = numerator; + _denominator = denominator; + } + + /// + /// Creates a normalized fraction using a signed 32bit integer. + /// + /// integer value that will be used for the numerator. The denominator will be 1. + public Fraction(int numerator) { + _numerator = new BigInteger(numerator); + _denominator = numerator != 0 ? BigInteger.One : BigInteger.Zero; + _state = FractionState.IsNormalized; + } + + /// + /// Creates a normalized fraction using a signed 64bit integer. + /// + /// integer value that will be used for the numerator. The denominator will be 1. + public Fraction(long numerator) { + _numerator = new BigInteger(numerator); + _denominator = numerator != 0 ? BigInteger.One : BigInteger.Zero; + _state = FractionState.IsNormalized; + } + + /// + /// Creates a normalized fraction using a unsigned 32bit integer. + /// + /// integer value that will be used for the numerator. The denominator will be 1. + public Fraction(uint numerator) { + _numerator = new BigInteger(numerator); + _denominator = numerator != 0 ? BigInteger.One : BigInteger.Zero; + _state = FractionState.IsNormalized; + } + + + /// + /// Creates a normalized fraction using a unsigned 64bit integer. + /// + /// integer value that will be used for the numerator. The denominator will be 1. + public Fraction(ulong numerator) { + _numerator = new BigInteger(numerator); + _denominator = numerator != 0 ? BigInteger.One : BigInteger.Zero; + _state = FractionState.IsNormalized; + } + + /// + /// Creates a normalized fraction using a big integer. + /// + /// big integer value that will be used for the numerator. The denominator will be 1. + public Fraction(BigInteger numerator) { + _numerator = numerator; + _denominator = numerator.IsZero ? BigInteger.Zero : BigInteger.One; + _state = FractionState.IsNormalized; + } + + + /// + /// Creates a normalized fraction using a 64bit floating point value (double). + /// The value will not be rounded therefore you will probably get huge numbers as numerator und denominator. + /// values are not able to store simple rational numbers like 0.2 or 0.3 - so please + /// don't be worried if the fraction looks weird. For more information visit + /// http://en.wikipedia.org/wiki/Floating_point + /// + /// Floating point value. + public Fraction(double value) { + this = FromDouble(value); + } + + /// + /// Creates a normalized fraction using a 128bit decimal value (decimal). + /// + /// Floating point value. + public Fraction(decimal value) { + this = FromDecimal(value); + } + } +} \ No newline at end of file diff --git a/src/KubernetesClient/Fractions/Fraction.ConvertFrom.cs b/src/KubernetesClient/Fractions/Fraction.ConvertFrom.cs new file mode 100644 index 0000000..a69653c --- /dev/null +++ b/src/KubernetesClient/Fractions/Fraction.ConvertFrom.cs @@ -0,0 +1,314 @@ +using System; +using System.Globalization; +using System.Numerics; +using Fractions.Extensions; + +namespace Fractions { + public partial struct Fraction { + /// + /// Converts a string to a fraction. Example: "3/4" or "4.5" (the decimal separator character is depending on the system culture). + /// If the number contains a decimal separator it will be parsed as . + /// + /// A fraction or a (decimal) number. The numerator and denominator must be separated with a '/' (slash) character. + /// A normalized + public static Fraction FromString(string fractionString) { + return FromString(fractionString, NumberStyles.Number, null); + } + + /// + /// Converts a string to a fraction. Example: "3/4" or "4.5" (the decimal separator character depends on ). + /// If the number contains a decimal separator it will be parsed as . + /// + /// A fraction or a (decimal) number. The numerator and denominator must be separated with a '/' (slash) character. + /// Provides culture specific information that will be used to parse the . + /// A normalized + public static Fraction FromString(string fractionString, IFormatProvider formatProvider) { + return FromString(fractionString, NumberStyles.Number, formatProvider); + } + + /// + /// Converts a string to a fraction. Example: "3/4" or "4.5" (the decimal separator character depends on ). + /// If the number contains a decimal separator it will be parsed as . + /// + /// A fraction or a (decimal) number. The numerator and denominator must be separated with a '/' (slash) character. + /// A bitwise combination of number styles that are allowed in . + /// Provides culture specific information that will be used to parse the . + /// A normalized + public static Fraction FromString(string fractionString, NumberStyles numberStyles, IFormatProvider formatProvider) { + if (fractionString == null) { + throw new ArgumentNullException(nameof(fractionString)); + } + + if (!TryParse(fractionString, numberStyles, formatProvider, true, out Fraction fraction)) { + throw new FormatException(string.Format("The string '{0}' cannot be converted to fraction.", fractionString)); + } + + return fraction; + } + + /// + /// Try to convert a string to a fraction. Example: "3/4" or "4.5" (the decimal separator character depends on the system's culture). + /// If the number contains a decimal separator it will be parsed as . + /// + /// A fraction or a (decimal) number. The numerator and denominator must be separated with a '/' (slash) character. + /// A normalized if the method returns with true. Otherwise the value is invalid. + /// + /// true if was well formed. The parsing result will be written to . + /// false if was invalid. + public static bool TryParse(string fractionString, out Fraction fraction) { + return TryParse(fractionString, NumberStyles.Number, null, true, out fraction); + } + + /// + /// Try to convert a string to a fraction. Example: "3/4" or "4.5" (the decimal separator character depends on ). + /// If the number contains a decimal separator it will be parsed as . + /// + /// A fraction or a (decimal) number. The numerator and denominator must be separated with a '/' (slash) character. + /// A bitwise combination of number styles that are allowed in . + /// Provides culture specific information that will be used to parse the . + /// A normalized if the method returns with true. Otherwise the value is invalid. + /// + /// true if was well formed. The parsing result will be written to . + /// false if was invalid. + /// + public static bool TryParse(string fractionString, NumberStyles numberStyles, IFormatProvider formatProvider, out Fraction fraction) { + return TryParse(fractionString, numberStyles, formatProvider, true, out fraction); + } + + /// + /// Try to convert a string to a fraction. Example: "3/4" or "4.5" (the decimal separator character depends on ). + /// If the number contains a decimal separator it will be parsed as . + /// + /// A fraction or a (decimal) number. The numerator and denominator must be separated with a '/' (slash) character. + /// A bitwise combination of number styles that are allowed in . + /// Provides culture specific information that will be used to parse the . + /// If true the parsed fraction will be reduced. + /// A if the method returns with true. Otherwise the value is invalid. + /// + /// true if was well formed. The parsing result will be written to . + /// false if was invalid. + /// + public static bool TryParse(string fractionString, NumberStyles numberStyles, IFormatProvider formatProvider, bool normalize, out Fraction fraction) { + if (fractionString == null) { + return CannotParse(out fraction); + } + + var components = fractionString.Split('/'); + if (components.Length == 1) { + return TryParseSingleNumber(components[0], numberStyles, formatProvider, out fraction); + } + + if (components.Length >= 2) { + var numeratorString = components[0]; + var denominatorString = components[1]; + + var withoutDecimalpoint = numberStyles & ~NumberStyles.AllowDecimalPoint; + if (!BigInteger.TryParse( + value: numeratorString, + style: withoutDecimalpoint, + provider: formatProvider, + result: out BigInteger numerator) + || !BigInteger.TryParse( + value: denominatorString, + style: withoutDecimalpoint, + provider: formatProvider, + result: out BigInteger denominator)) { + return CannotParse(out fraction); + } + fraction = new Fraction(numerator, denominator, normalize); + return true; + } + + // Technically it should not be possible to reach this line of code.. + return CannotParse(out fraction); + } + + /// + /// Try to convert a single number to a fraction. Example 34 or 4.5 (depending on the supplied culture used in ) + /// If the number contains a decimal separator it will be parsed as . + /// + /// A (decimal) number + /// A bitwise combination of number styles that are allowed in . + /// Provides culture specific information that will be used to parse the . + /// A if the method returns with true. Otherwise the value is invalid. + /// + /// true if was well formed. The parsing result will be written to . + /// false if was invalid. + /// + private static bool TryParseSingleNumber(string number, NumberStyles numberStyles, IFormatProvider formatProvider, out Fraction fraction) { + var numberFormatInfo = NumberFormatInfo.GetInstance(formatProvider); + + if (number.Contains(numberFormatInfo.NumberDecimalSeparator)) { + if (!decimal.TryParse(number, numberStyles, formatProvider, out decimal decimalNumber)) { + return CannotParse(out fraction); + } + fraction = FromDecimal(decimalNumber); + return true; + } + + var withoutDecimalpoint = numberStyles & ~NumberStyles.AllowDecimalPoint; + if (!BigInteger.TryParse(number, withoutDecimalpoint, formatProvider, out BigInteger numerator)) { + return CannotParse(out fraction); + } + fraction = new Fraction(numerator); + return true; + } + + /// + /// Returns false. contains an invalid value. + /// + /// Returns default() of + /// false + private static bool CannotParse(out Fraction fraction) { + fraction = default(Fraction); + return false; + } + + /// + /// Converts a floating point value to a fraction. The value will not be rounded therefore you will probably + /// get huge numbers as numerator und denominator. values are not able to store simple rational + /// numbers like 0.2 or 0.3 - so please don't be worried if the fraction looks weird. For more information visit + /// http://en.wikipedia.org/wiki/Floating_point + /// + /// A floating point value. + /// A fraction + /// If is NaN (not a number) or infinite. + public static Fraction FromDouble(double value) { + if (double.IsNaN(value) || double.IsInfinity(value)) { + throw new InvalidNumberException(); + } + + // No rounding here! It will convert the actual number that is stored as double! + // See http://www.mpdvc.de/artikel/FloatingPoint.htm + + const ulong SIGN_BIT = 0x8000000000000000; + const ulong EXPONENT_BITS = 0x7FF0000000000000; + const ulong MANTISSA = 0x000FFFFFFFFFFFFF; + const ulong MANTISSA_DIVISOR = 0x0010000000000000; + const ulong K = 1023; + var one = BigInteger.One; + + // value = (-1 * sign) * (1 + 2^(-1) + 2^(-2) .. + 2^(-52)) * 2^(exponent-K) + var valueBits = unchecked((ulong) BitConverter.DoubleToInt64Bits(value)); + + if (valueBits == 0) { + // See IEEE 754 + return Zero; + } + + var isNegative = (valueBits & SIGN_BIT) == SIGN_BIT; + var mantissaBits = valueBits & MANTISSA; + + // (exponent-K) + var exponent = (int) (((valueBits & EXPONENT_BITS) >> 52) - K); + + // (1 + 2^(-1) + 2^(-2) .. + 2^(-52)) + var mantissa = new Fraction(mantissaBits + MANTISSA_DIVISOR, MANTISSA_DIVISOR); + + // 2^exponent + var factor = exponent < 0 + ? new Fraction(one, one << Math.Abs(exponent)) + : new Fraction(one << exponent); + + var result = mantissa * factor; + + return isNegative + ? result.Invert() + : result; + } + + /// + /// Converts a floating point value to a fraction. The value will be rounded if possible. + /// + /// A floating point value. + /// A fraction + /// If is NaN (not a number) or infinite. + public static Fraction FromDoubleRounded(double value) { + if (double.IsNaN(value) || double.IsInfinity(value)) { + throw new InvalidNumberException(); + } + + // Null? + if (Math.Abs(value - 0.0) < double.Epsilon) { + return Zero; + } + + // Inspired from Syed Mehroz Alam http://www.geocities.ws/smehrozalam/source/fractioncs.txt + // .. who got it from http://ebookbrowse.com/confrac-pdf-d13212190 + // or ftp://89.25.159.69/knm/ksiazki/reszta/homepage.smc.edu.kennedy_john/CONFRAC.pdf + var sign = Math.Sign(value); + var absoluteValue = Math.Abs(value); + + var numerator = new BigInteger(absoluteValue); + var denominator = 1.0; + var remainingDigits = absoluteValue; + var previousDenominator = 0.0; + var breakCounter = 0; + + while (MathExt.RemainingDigitsAfterTheDecimalPoint(remainingDigits) + && Math.Abs(absoluteValue - (double) numerator / denominator) > double.Epsilon) { + + remainingDigits = 1.0 / (remainingDigits - Math.Floor(remainingDigits)); + + var tmp = denominator; + + denominator = Math.Floor(remainingDigits) * denominator + previousDenominator; + numerator = new BigInteger(absoluteValue * denominator + 0.5); + + previousDenominator = tmp; + + // See http://www.ozgrid.com/forum/archive/index.php/t-22530.html + if (++breakCounter > 594) { + break; + } + } + + return new Fraction( + sign < 0 ? BigInteger.Negate(numerator) : numerator, + new BigInteger(denominator), + true); + } + + /// + /// Converts a decimal value in a fraction. The value will not be rounded. + /// + /// A decimal value. + /// A fraction. + public static Fraction FromDecimal(decimal value) { + if (value == decimal.Zero) { + return _zero; + } + + if (value == decimal.One) { + return _one; + } + + if (value == decimal.MinusOne) { + return _minus_one; + } + + var bits = decimal.GetBits(value); + var low = BitConverter.GetBytes(bits[0]); + var middle = BitConverter.GetBytes(bits[1]); + var high = BitConverter.GetBytes(bits[2]); + var scale = BitConverter.GetBytes(bits[3]); + + + var exp = scale[2]; + bool positiveSign = (scale[3] & 0x80) == 0; + + // value = 0x00,high,middle,low / 10^exp + var numerator = new BigInteger(new byte[] { + low[0], low[1], low[2], low[3], + middle[0], middle[1], middle[2], middle[3], + high[0], high[1], high[2], high[3], + 0x00 + }); + var denominator = BigInteger.Pow(10, exp); + + return positiveSign + ? new Fraction(numerator, denominator, true) + : new Fraction(BigInteger.Negate(numerator), denominator, true); + } + } +} diff --git a/src/KubernetesClient/Fractions/Fraction.ConvertTo.cs b/src/KubernetesClient/Fractions/Fraction.ConvertTo.cs new file mode 100644 index 0000000..f4217c2 --- /dev/null +++ b/src/KubernetesClient/Fractions/Fraction.ConvertTo.cs @@ -0,0 +1,96 @@ +using System; +using System.Numerics; + +namespace Fractions { + public partial struct Fraction { + /// + /// Returns the fraction as signed 32bit integer. + /// + /// 32bit signed integer + public int ToInt32() { + if (IsZero) { + return 0; + } + return (int) (Numerator / Denominator); + } + + /// + /// Returns the fraction as signed 64bit integer. + /// + /// 64bit signed integer + public long ToInt64() { + if (IsZero) { + return 0; + } + return (long) (Numerator / Denominator); + } + + /// + /// Returns the fraction as unsigned 32bit integer. + /// + /// 32bit unsigned integer + public uint ToUInt32() { + if (IsZero) { + return 0; + } + return (uint) (Numerator / Denominator); + } + + /// + /// Returns the fraction as unsigned 64bit integer. + /// + /// 64-Bit unsigned integer + public ulong ToUInt64() { + if (IsZero) { + return 0; + } + return (ulong) (Numerator / Denominator); + } + + /// + /// Returns the fraction as BigInteger. + /// + /// BigInteger + public BigInteger ToBigInteger() { + if (IsZero) { + return BigInteger.Zero; + } + return Numerator / Denominator; + } + + /// + /// Returns the fraction as (rounded!) decimal value. + /// + /// Decimal value + public decimal ToDecimal() { + if (IsZero) { + return decimal.Zero; + } + + if (_numerator >= MIN_DECIMAL && _numerator <= MAX_DECIMAL && _denominator >= MIN_DECIMAL && _denominator <= MAX_DECIMAL) { + return (decimal) _numerator / (decimal) _denominator; + } + + // numerator or denominator is too big. Lets try to split the calculation.. + // Possible OverFlowException! + var withoutDecimalPlaces = (decimal) (_numerator / _denominator); + + var remainder = _numerator % _denominator; + var lowpart = remainder * BigInteger.Pow(10, 28) / _denominator; + var decimalPlaces = (decimal) lowpart / (decimal) Math.Pow(10, 28); + + return withoutDecimalPlaces + decimalPlaces; + } + + /// + /// Returns the fraction as (rounded!) floating point value. + /// + /// A floating point value + public double ToDouble() { + if (IsZero) { + return 0; + } + return (double) Numerator / (double) Denominator; + } + } +} \ No newline at end of file diff --git a/src/KubernetesClient/Fractions/Fraction.Equality.cs b/src/KubernetesClient/Fractions/Fraction.Equality.cs new file mode 100644 index 0000000..d8e5f0a --- /dev/null +++ b/src/KubernetesClient/Fractions/Fraction.Equality.cs @@ -0,0 +1,63 @@ + +namespace Fractions { + public partial struct Fraction + { + /// + /// Tests if the calculated value of this fraction equals to the calculated value of . + /// It does not matter if either of them is not normalized. Both values will be reduced (normalized) before performing + /// the test. + /// + /// The fraction to compare with. + /// true if both values are equivalent. (e.g. 2/4 is equivalent to 1/2. But 2/4 is not equivalent to -1/2) + + public bool IsEquivalentTo(Fraction other) { + var a = Reduce(); + var b = other.Reduce(); + + return a.Equals(b); + } + + /// + /// Performs an exact comparison with using numerator and denominator. + /// Warning: 1/2 is NOT equal to 2/4! -1/2 is NOT equal to 1/-2! + /// If you want to test the calculated values for equality use or + /// + /// + /// The fraction to compare with. + /// true if numerator and denominator of both fractions are equal. + + public bool Equals(Fraction other) { + return other._denominator.Equals(_denominator) && other._numerator.Equals(_numerator); + } + + /// + /// Performs an exact comparison with using numerator and denominator. + /// Warning: 1/2 is NOT equal to 2/4! -1/2 is NOT equal to 1/-2! + /// If you want to test the calculated values for equality use or + /// + /// + /// The fraction to compare with. + /// true if is type of and numerator and denominator of both are equal. + + public override bool Equals(object other) { + if (ReferenceEquals(null, other)) { + return false; + } + return other is Fraction && Equals((Fraction)other); + } + + /// + /// Returns the hash code. + /// + /// + /// A 32bit integer with sign. It has been constructed using the and the . + /// + /// 2 + + public override int GetHashCode() { + unchecked { + return (_denominator.GetHashCode() * 397) ^ _numerator.GetHashCode(); + } + } + } +} \ No newline at end of file diff --git a/src/KubernetesClient/Fractions/Fraction.Math.cs b/src/KubernetesClient/Fractions/Fraction.Math.cs new file mode 100644 index 0000000..7e944ec --- /dev/null +++ b/src/KubernetesClient/Fractions/Fraction.Math.cs @@ -0,0 +1,192 @@ +using System; +using System.Numerics; + +namespace Fractions { + public partial struct Fraction { + /// + /// Calculates the remainder of the division with the fraction's value and the supplied (% operator). + /// + /// Divisor + /// The remainder (left over) + public Fraction Remainder(Fraction divisor) { + if (divisor.IsZero) { + throw new DivideByZeroException(); + } + if (IsZero) { + return _zero; + } + + var gcd = BigInteger.GreatestCommonDivisor(_denominator, divisor.Denominator); + + var thisMultiplier = BigInteger.Divide(_denominator, gcd); + var otherMultiplier = BigInteger.Divide(divisor.Denominator, gcd); + + var leastCommonMultiple = BigInteger.Multiply(thisMultiplier, divisor.Denominator); + + var a = BigInteger.Multiply(_numerator, otherMultiplier); + var b = BigInteger.Multiply(divisor.Numerator, thisMultiplier); + + var remainder = BigInteger.Remainder(a, b); + + return new Fraction(remainder, leastCommonMultiple); + } + + /// + /// Adds the fraction's value with . + /// + /// Summand + /// The result as summation. + + public Fraction Add(Fraction summand) { + if (_denominator == summand.Denominator) { + return new Fraction(BigInteger.Add(_numerator, summand.Numerator), _denominator, true); + } + + if (IsZero) { + // 0 + b = b + return summand; + } + + if (summand.IsZero) { + // a + 0 = a + return this; + } + + var gcd = BigInteger.GreatestCommonDivisor(_denominator, summand.Denominator); + + var thisMultiplier = BigInteger.Divide(_denominator, gcd); + var otherMultiplier = BigInteger.Divide(summand.Denominator, gcd); + + var leastCommonMultiple = BigInteger.Multiply(thisMultiplier, summand.Denominator); + + var calculatedNumerator = BigInteger.Add( + BigInteger.Multiply(_numerator, otherMultiplier), + BigInteger.Multiply(summand.Numerator, thisMultiplier) + ); + + return new Fraction(calculatedNumerator, leastCommonMultiple, true); + } + + /// + /// Subtracts the fraction's value (minuend) with . + /// + /// Subtrahend. + /// The result as difference. + + public Fraction Subtract(Fraction subtrahend) { + return Add(subtrahend.Invert()); + } + + /// + /// Inverts the fraction. Has the same result as multiplying it by -1. + /// + /// The inverted fraction. + + public Fraction Invert() { + if (IsZero) { + return _zero; + } + return new Fraction(BigInteger.Negate(_numerator), _denominator, _state); + } + + /// + /// Multiply the fraction's value by . + /// + /// Factor + /// The result as product. + + public Fraction Multiply(Fraction factor) { + return new Fraction( + _numerator * factor._numerator, + _denominator * factor._denominator, + true); + } + + /// + /// Divides the fraction's value by . + /// + /// Divisor + /// The result as quotient. + + public Fraction Divide(Fraction divisor) { + if (divisor.IsZero) { + throw new DivideByZeroException(string.Format("{0} shall be divided by zero.", this)); + } + + return new Fraction( + numerator: _numerator * divisor._denominator, + denominator: _denominator * divisor._numerator, + normalize: true); + } + + /// + /// Returns this as reduced/simplified fraction. The fraction's sign will be normalized. + /// + /// A reduced and normalized fraction. + + public Fraction Reduce() { + return _state == FractionState.IsNormalized + ? this + : GetReducedFraction(_numerator, _denominator); + } + + /// + /// Gets the absolute value of a object. + /// + /// The absolute value. + + public Fraction Abs() { + return Abs(this); + } + + /// + /// Gets the absolute value of a object. + /// + /// The fraction. + /// The absolute value. + + public static Fraction Abs(Fraction fraction) { + return new Fraction(BigInteger.Abs(fraction.Numerator), BigInteger.Abs(fraction.Denominator), fraction.State); + } + + /// + /// Returns a reduced and normalized fraction. + /// + /// Numerator + /// Denominator + /// A reduced and normalized fraction + + public static Fraction GetReducedFraction(BigInteger numerator, BigInteger denominator) { + if (numerator.IsZero || denominator.IsZero) { + return Zero; + } + + if (denominator.Sign == -1) { + // Denominator must not be negative after normalization + numerator = BigInteger.Negate(numerator); + denominator = BigInteger.Negate(denominator); + } + + var gcd = BigInteger.GreatestCommonDivisor(numerator, denominator); + if (!gcd.IsOne && !gcd.IsZero) { + return new Fraction(BigInteger.Divide(numerator, gcd), BigInteger.Divide(denominator, gcd), + FractionState.IsNormalized); + } + + return new Fraction(numerator, denominator, FractionState.IsNormalized); + } + + /// + /// Returns a fraction raised to the specified power. + /// + /// base to be raised to a power + /// A number that specifies a power (exponent) + /// The fraction raised to the power . + + public static Fraction Pow(Fraction @base, int exponent) { + return exponent < 0 + ? Pow(new Fraction(@base._denominator, @base._numerator), -exponent) + : new Fraction(BigInteger.Pow(@base._numerator, exponent), BigInteger.Pow(@base._denominator, exponent)); + } + } +} diff --git a/src/KubernetesClient/Fractions/Fraction.Operators.cs b/src/KubernetesClient/Fractions/Fraction.Operators.cs new file mode 100644 index 0000000..c481d1b --- /dev/null +++ b/src/KubernetesClient/Fractions/Fraction.Operators.cs @@ -0,0 +1,111 @@ +using System.Numerics; + +namespace Fractions { + public partial struct Fraction { +#pragma warning disable 1591 + public static bool operator ==(Fraction left, Fraction right) { + return left.Equals(right); + } + + public static bool operator !=(Fraction left, Fraction right) { + return !left.Equals(right); + } + + public static Fraction operator +(Fraction a, Fraction b) { + return a.Add(b); + } + + public static Fraction operator -(Fraction a, Fraction b) { + return a.Subtract(b); + } + + public static Fraction operator *(Fraction a, Fraction b) { + return a.Multiply(b); + } + + public static Fraction operator /(Fraction a, Fraction b) { + return a.Divide(b); + } + + public static Fraction operator %(Fraction a, Fraction b) { + return a.Remainder(b); + } + + public static bool operator <(Fraction a, Fraction b) { + return a.CompareTo(b) < 0; + } + + public static bool operator >(Fraction a, Fraction b) { + return a.CompareTo(b) > 0; + } + + public static bool operator <=(Fraction a, Fraction b) { + return a.CompareTo(b) <= 0; + } + + public static bool operator >=(Fraction a, Fraction b) { + return a.CompareTo(b) >= 0; + } + + public static implicit operator Fraction(int value) { + return new Fraction(value); + } + + public static implicit operator Fraction(long value) { + return new Fraction(value); + } + + public static implicit operator Fraction(uint value) { + return new Fraction(value); + } + + public static implicit operator Fraction(ulong value) { + return new Fraction(value); + } + + public static implicit operator Fraction(BigInteger value) { + return new Fraction(value); + } + + public static explicit operator Fraction(double value) { + return new Fraction(value); + } + + public static explicit operator Fraction(decimal value) { + return new Fraction(value); + } + + public static explicit operator Fraction(string value) { + return FromString(value); + } + + public static explicit operator int(Fraction fraction) { + return fraction.ToInt32(); + } + + public static explicit operator long(Fraction fraction) { + return fraction.ToInt64(); + } + + public static explicit operator uint(Fraction fraction) { + return fraction.ToUInt32(); + } + + public static explicit operator ulong(Fraction fraction) { + return fraction.ToUInt64(); + } + + public static explicit operator decimal(Fraction fraction) { + return fraction.ToDecimal(); + } + + public static explicit operator double(Fraction fraction) { + return fraction.ToDouble(); + } + + public static explicit operator BigInteger(Fraction fraction) { + return fraction.ToBigInteger(); + } +#pragma warning restore 1591 + } +} \ No newline at end of file diff --git a/src/KubernetesClient/Fractions/Fraction.ToString.cs b/src/KubernetesClient/Fractions/Fraction.ToString.cs new file mode 100644 index 0000000..a1afb09 --- /dev/null +++ b/src/KubernetesClient/Fractions/Fraction.ToString.cs @@ -0,0 +1,55 @@ +using System; +using System.Globalization; +using Fractions.Formatter; + +namespace Fractions { + public partial struct Fraction { + /// + /// Returns the fraction as "numerator/denominator" or just "numerator" if the denominator has a value of 1. + /// The returning value is culture invariant (). + /// + /// "numerator/denominator" or just "numerator" + + public override string ToString() { + return ToString("G", DefaultFractionFormatProvider.Instance); + } + + /// + /// Formats the value of the current instance using the specified format. + /// The returning value is culture invariant (). + /// See for all formatting options. + /// + /// "numerator/denominator" or just "numerator" + + public string ToString(string format) { + return ToString(format, DefaultFractionFormatProvider.Instance); + } + + /// + /// Formats the value of the current instance using the specified format. The numbers are however culture invariant. + /// + /// + /// The value of the current instance in the specified format. + /// + /// The format to use. + /// + /// symboldescription + /// GGeneral format: numerator/denominator + /// nNumerator + /// dDenominator + /// zThe fraction as integer + /// rThe positive remainder of all digits after the decimal point using the format: numerator/denominator or if the fraction is a valid integer without digits after the decimal point. + /// mThe fraction as mixed number e.g. "2 1/3" instead of "7/3" + /// + /// -or- A null reference (Nothing in Visual Basic) to use the default format defined for the type of the implementation. + /// The provider to use to format the value. -or- A null reference (Nothing in Visual Basic) to obtain the numeric format information from the current locale setting of the operating system. + /// 2 + public string ToString(string format, IFormatProvider formatProvider) { + var formatter = formatProvider?.GetFormat(GetType()) as ICustomFormatter; + + return formatter != null + ? formatter.Format(format, this, formatProvider) + : DefaultFractionFormatter.Instance.Format(format, this, formatProvider); + } + } +} \ No newline at end of file diff --git a/src/KubernetesClient/Fractions/Fraction.cs b/src/KubernetesClient/Fractions/Fraction.cs new file mode 100644 index 0000000..c6ef9cc --- /dev/null +++ b/src/KubernetesClient/Fractions/Fraction.cs @@ -0,0 +1,81 @@ +using System; +using System.ComponentModel; +using System.Numerics; +using System.Runtime.InteropServices; +using Fractions.TypeConverters; + +namespace Fractions { + /// + /// A mathematical fraction. A rational number written as a/b (a is the numerator and b the denominator). + /// The data type is not capable to store NaN (not a number) or infinite. + /// + [TypeConverter(typeof (FractionTypeConverter))] + [StructLayout(LayoutKind.Sequential)] + public partial struct Fraction : IEquatable, IComparable, IComparable, IFormattable { + private static readonly BigInteger MIN_DECIMAL = new BigInteger(decimal.MinValue); + private static readonly BigInteger MAX_DECIMAL = new BigInteger(decimal.MaxValue); + private static readonly Fraction _zero = new Fraction(BigInteger.Zero, BigInteger.Zero, FractionState.IsNormalized); + private static readonly Fraction _one = new Fraction(BigInteger.One, BigInteger.One, FractionState.IsNormalized); + private static readonly Fraction _minus_one = new Fraction(BigInteger.MinusOne, BigInteger.One, FractionState.IsNormalized); + + private readonly BigInteger _denominator; + private readonly BigInteger _numerator; + private readonly FractionState _state; + + /// + /// The numerator. + /// + + public BigInteger Numerator => _numerator; + + /// + /// The denominator + /// + + public BigInteger Denominator => _denominator; + + /// + /// true if the value is positive (greater than or equal to 0). + /// + + public bool IsPositive => _numerator.Sign == 1 && _denominator.Sign == 1 || + _numerator.Sign == -1 && _denominator.Sign == -1; + + /// + /// true if the value is negative (lesser than 0). + /// + + public bool IsNegative => _numerator.Sign == -1 && _denominator.Sign == 1 || + _numerator.Sign == 1 && _denominator.Sign == -1; + + /// + /// true if the fraction has a real (calculated) value of 0. + /// + + public bool IsZero => _numerator.IsZero || _denominator.IsZero; + + /// + /// The fraction's state. + /// + + public FractionState State => _state; + + /// + /// A fraction with the reduced/simplified value of 0. + /// + + public static Fraction Zero => _zero; + + /// + /// A fraction with the reduced/simplified value of 1. + /// + + public static Fraction One => _one; + + /// + /// A fraction with the reduced/simplified value of -1. + /// + + public static Fraction MinusOne => _minus_one; + } +} \ No newline at end of file diff --git a/src/KubernetesClient/Fractions/FractionState.cs b/src/KubernetesClient/Fractions/FractionState.cs new file mode 100644 index 0000000..f3a480e --- /dev/null +++ b/src/KubernetesClient/Fractions/FractionState.cs @@ -0,0 +1,17 @@ +namespace Fractions { + /// + /// The fraction's state. + /// + public enum FractionState + { + /// + /// Unknown state. + /// + Unknown, + + /// + /// A reduced/simplified fraction. + /// + IsNormalized + } +} \ No newline at end of file diff --git a/src/KubernetesClient/Fractions/InvalidNumberException.cs b/src/KubernetesClient/Fractions/InvalidNumberException.cs new file mode 100644 index 0000000..a0b68a8 --- /dev/null +++ b/src/KubernetesClient/Fractions/InvalidNumberException.cs @@ -0,0 +1,14 @@ +using System; + +namespace Fractions { + /// + /// Exception that will be thrown if an argument contains not a number (NaN) or is infinite. + /// + public class InvalidNumberException : ArithmeticException { +#pragma warning disable 1591 + public InvalidNumberException() {} + public InvalidNumberException(string message) : base(message) {} + public InvalidNumberException(string message, Exception innerException) : base(message, innerException) {} +#pragma warning restore 1591 + } +} \ No newline at end of file diff --git a/src/KubernetesClient/Fractions/README.md b/src/KubernetesClient/Fractions/README.md new file mode 100644 index 0000000..860b1bd --- /dev/null +++ b/src/KubernetesClient/Fractions/README.md @@ -0,0 +1,6 @@ +This is a copy of the Fractions library. +Original source code is [here](https://github.com/danm-de/Fractions), licensed under the BSD license. + +The source has been vendored into this project in order to produce a fully strongly-named assembly. +As of the time that this file was created, no strongly-named assembly for the Fractions library existed. +By including the source code in this project, we can produce a strongly-named assembly for the KubernetesClient. diff --git a/src/KubernetesClient/Fractions/TypeConverters/FractionTypeConverter.cs b/src/KubernetesClient/Fractions/TypeConverters/FractionTypeConverter.cs new file mode 100644 index 0000000..d748c23 --- /dev/null +++ b/src/KubernetesClient/Fractions/TypeConverters/FractionTypeConverter.cs @@ -0,0 +1,96 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Globalization; +using System.Numerics; + +namespace Fractions.TypeConverters { + /// + /// Converts the from / to various data types. + /// + public sealed class FractionTypeConverter : TypeConverter { + private static readonly HashSet SUPPORTED_TYPES = new HashSet { + typeof (string), + typeof (int), + typeof (long), + typeof (decimal), + typeof (double), + typeof (Fraction), + typeof (BigInteger) + }; + + private static readonly Dictionary> CONVERT_TO_DICTIONARY = + new Dictionary> { + {typeof (string), (o, info) => ((Fraction) o).ToString()}, + {typeof (int), (o, info) => ((Fraction) o).ToInt32()}, + {typeof (long), (o, info) => ((Fraction) o).ToInt64()}, + {typeof (decimal), (o, info) => ((Fraction) o).ToDecimal()}, + {typeof (double), (o, info) => ((Fraction) o).ToDouble()}, + {typeof (Fraction), (o, info) => (Fraction) o}, + {typeof (BigInteger), (o, info) => ((Fraction) o).ToBigInteger()} + }; + + private static readonly Dictionary> CONVERT_FROM_DICTIONARY = + new Dictionary> { + {typeof (string), (o, info) => Fraction.FromString((string) o, info)}, + {typeof (int), (o, info) => new Fraction((int) o)}, + {typeof (long), (o, info) => new Fraction((long) o)}, + {typeof (decimal), (o, info) => Fraction.FromDecimal((decimal) o)}, + {typeof (double), (o, info) => Fraction.FromDouble((double) o)}, + {typeof (Fraction), (o, info) => (Fraction) o}, + {typeof (BigInteger), (o, info) => new Fraction((BigInteger) o)} + }; + + /// + /// Returns whether the type converter can convert an object to the specified type. + /// + /// An object that provides a format context. + /// The type you want to convert to. + /// true if this converter can perform the conversion; otherwise, false. + public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType) { + return SUPPORTED_TYPES.Contains(destinationType); + } + + /// + /// Returns whether this converter can convert an object of the given type to the type of this converter, using the specified context. + /// + /// An that provides a format context. + /// A that represents the type you want to convert from. + /// trueif this converter can perform the conversion; otherwise, false. + public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType) { + return SUPPORTED_TYPES.Contains(sourceType); + } + + /// + /// Converts the given value object to the specified type, using the specified context and culture information. + /// + /// An that provides a format context. + /// A CultureInfo. If null is passed, the current culture is assumed. + /// The to convert. + /// The to convert the value parameter to. + /// An that represents the converted value. + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, + Type destinationType) { + return !ReferenceEquals(value, null) && CONVERT_TO_DICTIONARY.TryGetValue(destinationType, out Func func) + ? func(value, culture) + : base.ConvertTo(context, culture, value, destinationType); + } + + /// + /// Converts the given object to the type of this converter, using the specified context and culture information. + /// + /// An that provides a format context. + /// The to use as the current culture. + /// The to convert. + /// An that represents the converted value. + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) { + if (ReferenceEquals(value, null)) { + return Fraction.Zero; + } + + return CONVERT_FROM_DICTIONARY.TryGetValue(value.GetType(), out Func func) + ? func(value, culture) + : base.ConvertFrom(context, culture, value); + } + } +} \ No newline at end of file diff --git a/src/KubernetesClient/Fractions/license.txt b/src/KubernetesClient/Fractions/license.txt new file mode 100644 index 0000000..b1237d0 --- /dev/null +++ b/src/KubernetesClient/Fractions/license.txt @@ -0,0 +1,22 @@ +Copyright (c) 2013-2017, Daniel Mueller +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. \ No newline at end of file diff --git a/src/KubernetesClient/KubernetesClient.csproj b/src/KubernetesClient/KubernetesClient.csproj index 0d1117f..ae2127e 100644 --- a/src/KubernetesClient/KubernetesClient.csproj +++ b/src/KubernetesClient/KubernetesClient.csproj @@ -22,7 +22,6 @@ -