Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 128 additions & 0 deletions src/KubernetesClient/Fractions/Extensions/MathExt.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
using System;

namespace Fractions.Extensions {
internal static class MathExt {
/// <summary>
/// Checks for an even number.
/// </summary>
/// <param name="number"></param>
/// <returns><c>true</c> if the number is even.</returns>
public static bool IsEven(this long number) {
return (number & 1) == 0;
}

/// <summary>
/// Checks for an odd number.
/// </summary>
/// <param name="number"></param>
/// <returns><c>true</c> if the number is odd.</returns>
public static bool IsOdd(this long number) {
return (number & 1) != 0;
}

/// <summary>
/// Get the greatest common divisor (GCD) of <paramref name="a"/> and <paramref name="b"/>.
/// </summary>
/// <param name="a">First number.</param>
/// <param name="b">Second number.</param>
/// <returns>The largest positive integer that divides <paramref name="a"/> and <paramref name="b"/> without a remainder.</returns>
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
}

/// <summary>
/// Get the least common multiple (LCM) of <paramref name="a"/> and <paramref name="b"/>.
/// </summary>
/// <param name="a">The first number.</param>
/// <param name="b">The second number.</param>
/// <returns>The smallest positive integer that is divisible by both <paramref name="a"/> and <paramref name="b"/> or 0 if either <paramref name="a"/> or <paramref name="b"/> is 0</returns>
/// <exception cref="ArgumentException">If <paramref name="a"/> and <paramref name="b"/> are 0</exception>
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;
}

/// <summary>
/// Returns <c>true</c> if there are remaining digits after the decimal point.
/// </summary>
/// <param name="remainingDigits">A <see cref="double"/> value with possible remaining digits</param>
/// <returns><c>true</c> if <paramref name="remainingDigits"/> has digits after the decimal point</returns>

public static bool RemainingDigitsAfterTheDecimalPoint(double remainingDigits) {
return Math.Abs(remainingDigits - Math.Floor(remainingDigits)) > double.Epsilon;
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using System;

namespace Fractions.Formatter {
/// <summary>
/// Default <see cref="Fraction.ToString()"/> formatter.
/// </summary>
public class DefaultFractionFormatProvider : IFormatProvider {
/// <summary>
/// Singleton instance
/// </summary>
public static readonly IFormatProvider Instance = new DefaultFractionFormatProvider();

object IFormatProvider.GetFormat(Type formatType) {
return formatType == typeof (Fraction)
? DefaultFractionFormatter.Instance
: null;
}
}
}
Original file line number Diff line number Diff line change
@@ -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));
}
}
}
61 changes: 61 additions & 0 deletions src/KubernetesClient/Fractions/Fraction.CompareTo.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
using System;
using System.Numerics;

namespace Fractions {
public partial struct Fraction
{
/// <summary>
/// Compares the calculated value with the supplied <paramref name="other"/>.
/// </summary>
/// <param name="other">Fraction that shall be compared with.</param>
/// <returns>
/// Less than 0 if <paramref name="other"/> is greater.
/// Zero (0) if both calculated values are equal.
/// Greater then zero (0) if <paramref name="other"/> less.</returns>
/// <exception cref="ArgumentException">If <paramref name="other"/> is not of type <see cref="Fraction"/>.</exception>
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);
}

/// <summary>
/// Compares the calculated value with the supplied <paramref name="other"/>.
/// </summary>
/// <param name="other">Fraction that shall be compared with.</param>
/// <returns>
/// Less than 0 if <paramref name="other"/> is greater.
/// Zero (0) if both calculated values are equal.
/// Greater then zero (0) if <paramref name="other"/> less.</returns>

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);
}
}
}
Loading