#region Copyright and License
/*
* SharpAssembler
* Library for .NET that assembles a predetermined list of
* instructions into machine code.
*
* Copyright (C) 2011 Daniël Pelsmaeker
*
* This file is part of SharpAssembler.
*
* SharpAssembler is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* SharpAssembler is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with SharpAssembler. If not, see .
*/
#endregion
using System;
using System.Diagnostics.Contracts;
namespace SharpAssembler.Core
{
///
/// A 128-bit signed integer.
///
///
/// This implementation is based on the code described in
/// .
///
public struct Int128 : IFormattable, IConvertible,
IComparable, IComparable, IEquatable
{
#region Constants
///
/// The maximum value a can represent.
///
public static readonly Int128 MaxValue = new Int128(0xFFFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFFF);
///
/// The minimum value a can represent.
///
public static readonly Int128 MinValue = new Int128(0, unchecked((long)0x8000000000000000));
///
/// A value of -1.
///
public static readonly Int128 MinusOne = new Int128(0xFFFFFFFFFFFFFFFF, unchecked((long)0xFFFFFFFFFFFFFFFF));
///
/// A value of 0.
///
public static readonly Int128 Zero = new Int128(0, 0);
///
/// A value of 1.
///
public static readonly Int128 One = new Int128(1, 0);
#endregion
#region Constructors
///
/// Initializes a new instance of the struct.
///
/// The least significant 64-bits of the integer.
/// The most significant 64-bits of the integer.
public Int128(ulong low, long high)
{
this.low = low;
this.high = high;
}
#endregion
#region Properties
///
/// Gets whether the value of this is an even number.
///
/// when this value is an even number;
/// otherwise, .
///
/// Zero is also an even number.
///
public bool IsEven
{
get
{
return (low & 1) == 0;
}
}
///
/// Gets whether the value of this is zero.
///
/// when this value is zero;
/// otherwise, .
public bool IsZero
{
get { return high == 0 && low == 0; }
}
///
/// Gets whether the value of this is one.
///
/// when this value is one;
/// otherwise, .
public bool IsOne
{
get { return high == 0 && low == 1; }
}
///
/// Gets whether the value of this is a power of two.
///
/// when this value is a power of two;
/// otherwise, .
public bool IsPowerOfTwo
{
get { return !IsZero && (this & (this - 1)) == 0; }
}
///
/// Gets a number that indicates the sign (negative, positive, or zero) of the current .
///
/// A number that indicates the sign. The return value is 0 when the value is zero, 1 when the value
/// is positive or -1 when the value is negative.
public int Sign
{
get { return this.CompareTo(0); }
}
///
/// Gets the 64 least significant bits of the value.
///
/// The 64 least significant bits.
public ulong Low
{
get { return this.low; }
}
///
/// Gets the 64 most significant bits of the value.
///
/// The 64 most significant bits.
public long High
{
get { return this.high; }
}
#endregion
#region Equality
///
/// Indicates whether this instance and a specified object are equal.
///
/// Another object to compare to.
/// if and this instance are the same type and represent
/// the same value; otherwise, .
public override bool Equals(object obj)
{
if (Object.ReferenceEquals(obj, null) ||
!(obj is Int128))
return false;
return Equals((Int128)obj);
}
///
/// Indicates whether the current object is equal to another object of the same type.
///
/// An object to compare with this object.
/// if the current object is equal to the other parameter;
/// otherwise, .
public bool Equals(Int128 other)
{
return this.high == other.high && this.low == other.low;
}
///
/// Returns the hash code for this instance.
///
/// A 32-bit signed integer that is the hash code for this instance.
public override int GetHashCode()
{
unchecked
{
int hash = 17;
hash = hash * 23 + low.GetHashCode();
hash = hash * 23 + high.GetHashCode();
return hash;
}
}
///
/// Returns a value that indicates whether two objects have the same value.
///
/// The first value to compare.
/// The second value to compare.
/// if the and parameters have
/// the same value; otherwise, .
public static bool operator ==(Int128 left, Int128 right)
{
return left.Equals(right);
}
///
/// Returns a value that indicates whether two objects have different values.
///
/// The first value to compare.
/// The second value to compare.
/// if the and parameters have
/// different values; otherwise, .
public static bool operator !=(Int128 left, Int128 right)
{
return !left.Equals(right);
}
#endregion
#region Comparisons
///
/// Compares the current instance with another object of the same type.
///
/// An object to compare with this instance.
/// A value that indicates the relative order of the objects being compared.
public int CompareTo(object obj)
{
if (obj is Int128)
return CompareTo((Int128)obj);
else
throw new ArgumentException("The specified object is not the same type as this instance.", "obj");
}
///
/// Compares the current instance with another object of the same type.
///
/// An object to compare with this instance.
/// A value that indicates the relative order of the objects being compared.
public int CompareTo(Int128 other)
{
int result = this.high.CompareTo(other.high);
if (result == 0)
result = this.low.CompareTo(other.low);
return result;
}
///
/// Returns a value that indicates whether a value is greater than another
/// value.
///
/// The first value to compare.
/// The second value to compare.
/// if the value of is greater than the value of
/// ; otherwise, .
public static bool operator >(Int128 left, Int128 right)
{
return left.CompareTo(right) > 0;
}
///
/// Returns a value that indicates whether a value is less than another
/// value.
///
/// The first value to compare.
/// The second value to compare.
/// if the value of is less than the value of
/// ; otherwise, .
public static bool operator <(Int128 left, Int128 right)
{
return left.CompareTo(right) < 0;
}
///
/// Returns a value that indicates whether a value is greater than or equal to another
/// value.
///
/// The first value to compare.
/// The second value to compare.
/// if the value of is greater than or equal to the
/// value of ; otherwise, .
public static bool operator >=(Int128 left, Int128 right)
{
return left.CompareTo(right) >= 0;
}
///
/// Returns a value that indicates whether a value is less than or equal to another
/// value.
///
/// The first value to compare.
/// The second value to compare.
/// if the value of is less than or equal to the value
/// of ; otherwise, .
public static bool operator <=(Int128 left, Int128 right)
{
return left.CompareTo(right) <= 0;
}
#endregion
#region Conversions
///
/// Converts the specified unsigned 64-bit value to a signed 128-bit value.
///
/// The value to convert.
/// The resulting 128-bit value.
public static implicit operator Int128(ulong value)
{
return new Int128(value, 0);
}
///
/// Converts the specified signed 64-bit value to a signed 128-bit value.
///
/// The value to convert.
/// The resulting 128-bit value.
public static implicit operator Int128(long value)
{
return new Int128(unchecked((ulong)value), (value < 0 ? -1 : 0));
}
///
/// Converts the specified unsigned 32-bit value to a signed 128-bit value.
///
/// The value to convert.
/// The resulting 128-bit value.
public static implicit operator Int128(uint value)
{
return (Int128)(ulong)value;
}
///
/// Converts the specified signed 32-bit value to a signed 128-bit value.
///
/// The value to convert.
/// The resulting 128-bit value.
public static implicit operator Int128(int value)
{
return (Int128)(long)value;
}
///
/// Converts the specified unsigned 16-bit value to a signed 128-bit value.
///
/// The value to convert.
/// The resulting 128-bit value.
public static implicit operator Int128(ushort value)
{
return (Int128)(ulong)value;
}
///
/// Converts the specified signed 16-bit value to a signed 128-bit value.
///
/// The value to convert.
/// The resulting 128-bit value.
public static implicit operator Int128(short value)
{
return (Int128)(long)value;
}
///
/// Converts the specified unsigned 8-bit value to a signed 128-bit value.
///
/// The value to convert.
/// The resulting 128-bit value.
public static implicit operator Int128(byte value)
{
return (Int128)(ulong)value;
}
///
/// Converts the specified signed 8-bit value to a signed 128-bit value.
///
/// The value to convert.
/// The resulting 128-bit value.
public static implicit operator Int128(sbyte value)
{
return (Int128)(long)value;
}
///
/// Converts the specified signed 128-bit value to an unsigned 64-bit value.
///
/// The value to convert.
/// The resulting 64-bit value.
public static explicit operator ulong(Int128 value)
{
return (ulong)value.low;
}
///
/// Converts the specified signed 128-bit value to a signed 64-bit value.
///
/// The value to convert.
/// The resulting 64-bit value.
public static explicit operator long(Int128 value)
{
return (long)value.low;
}
///
/// Converts the specified signed 128-bit value to an unsigned 32-bit value.
///
/// The value to convert.
/// The resulting 32-bit value.
public static explicit operator uint(Int128 value)
{
return (uint)value.low;
}
///
/// Converts the specified signed 128-bit value to a signed 32-bit value.
///
/// The value to convert.
/// The resulting 32-bit value.
public static explicit operator int(Int128 value)
{
return (int)value.low;
}
///
/// Converts the specified signed 128-bit value to an unsigned 16-bit value.
///
/// The value to convert.
/// The resulting 16-bit value.
public static explicit operator ushort(Int128 value)
{
return (ushort)value.low;
}
///
/// Converts the specified signed 128-bit value to a signed 16-bit value.
///
/// The value to convert.
/// The resulting 16-bit value.
public static explicit operator short(Int128 value)
{
return (short)value.low;
}
///
/// Converts the specified signed 128-bit value to an unsigned 8-bit value.
///
/// The value to convert.
/// The resulting 8-bit value.
public static explicit operator byte(Int128 value)
{
return (byte)value.low;
}
///
/// Converts the specified signed 128-bit value to a signed 8-bit value.
///
/// The value to convert.
/// The resulting 8-bit value.
public static explicit operator sbyte(Int128 value)
{
return (sbyte)value.low;
}
///
/// Returns the for this instance.
///
/// The enumerated constant that is the of the class or value type that
/// implements this interface.
public TypeCode GetTypeCode()
{
return TypeCode.Object;
}
///
/// Converts the value of this instance to an of the specified that has
/// an equivalent value, using the specified culture-specific formatting information.
///
/// The to which the value of this instance is
/// converted.
/// An interface implementation that supplies
/// culture-specific formatting information.
/// An instance of type whose value is
/// equivalent to the value of this instance.
object IConvertible.ToType(Type conversionType, IFormatProvider provider)
{
IConvertible conv = (IConvertible)this;
if (conversionType == typeof(bool))
return conv.ToBoolean(provider);
if (conversionType == typeof(byte))
return conv.ToByte(provider);
if (conversionType == typeof(char))
return conv.ToChar(provider);
if (conversionType == typeof(DateTime))
return conv.ToDateTime(provider);
if (conversionType == typeof(Decimal))
return conv.ToDecimal(provider);
if (conversionType == typeof(Double))
return conv.ToDouble(provider);
if (conversionType == typeof(Int16))
return conv.ToInt16(provider);
if (conversionType == typeof(Int32))
return conv.ToInt32(provider);
if (conversionType == typeof(Int64))
return conv.ToInt64(provider);
if (conversionType == typeof(SByte))
return conv.ToSByte(provider);
if (conversionType == typeof(Single))
return conv.ToSingle(provider);
if (conversionType == typeof(String))
return conv.ToString(provider);
if (conversionType == typeof(UInt16))
return conv.ToUInt16(provider);
if (conversionType == typeof(UInt32))
return conv.ToUInt32(provider);
if (conversionType == typeof(UInt64))
return conv.ToUInt64(provider);
if (conversionType == typeof(Int128))
return this;
throw new InvalidCastException();
}
///
/// Converts the value of this instance to an equivalent boolean value using the specified
/// culture-specific formatting information.
///
/// An interface implementation that supplies
/// culture-specific formatting information.
/// A boolean value equivalent to the value of this instance.
bool IConvertible.ToBoolean(IFormatProvider provider)
{
return !(this.low == 0 && this.high == 0);
}
///
/// Converts the value of this instance to an equivalent Unicode character using the specified
/// culture-specific formatting information.
///
/// An interface implementation that supplies
/// culture-specific formatting information.
/// A Unicode character equivalent to the value of this instance.
Char IConvertible.ToChar(IFormatProvider provider)
{
if (this < Char.MinValue || this > Char.MaxValue)
throw new OverflowException();
return (Char)this;
}
///
/// Converts the value of this instance to an equivalent 8-bit unsigned integer using the specified
/// culture-specific formatting information.
///
/// An interface implementation that supplies
/// culture-specific formatting information.
/// A 8-bit unsigned integer equivalent to the value of this instance.
Byte IConvertible.ToByte(IFormatProvider provider)
{
if (this < Byte.MinValue || this > Byte.MaxValue)
throw new OverflowException();
return (Byte)this;
}
///
/// Converts the value of this instance to an equivalent 8-bit signed integer using the specified
/// culture-specific formatting information.
///
/// An interface implementation that supplies
/// culture-specific formatting information.
/// A 8-bit signed integer equivalent to the value of this instance.
SByte IConvertible.ToSByte(IFormatProvider provider)
{
if (this < SByte.MinValue || this > SByte.MaxValue)
throw new OverflowException();
return (SByte)this;
}
///
/// Converts the value of this instance to an equivalent 16-bit signed integer using the specified
/// culture-specific formatting information.
///
/// An interface implementation that supplies
/// culture-specific formatting information.
/// A 16-bit signed integer equivalent to the value of this instance.
Int16 IConvertible.ToInt16(IFormatProvider provider)
{
if (this < Int16.MinValue || this > Int16.MaxValue)
throw new OverflowException();
return (Int16)this;
}
///
/// Converts the value of this instance to an equivalent 32-bit signed integer using the specified
/// culture-specific formatting information.
///
/// An interface implementation that supplies
/// culture-specific formatting information.
/// A 32-bit signed integer equivalent to the value of this instance.
Int32 IConvertible.ToInt32(IFormatProvider provider)
{
if (this < Int32.MinValue || this > Int32.MaxValue)
throw new OverflowException();
return (Int32)this;
}
///
/// Converts the value of this instance to an equivalent 64-bit signed integer using the specified
/// culture-specific formatting information.
///
/// An interface implementation that supplies
/// culture-specific formatting information.
/// A 64-bit signed integer equivalent to the value of this instance.
Int64 IConvertible.ToInt64(IFormatProvider provider)
{
if (this < Int64.MinValue || this > Int64.MaxValue)
throw new OverflowException();
return (Int64)this;
}
///
/// Converts the value of this instance to an equivalent 16-bit unsigned integer using the specified
/// culture-specific formatting information.
///
/// An interface implementation that supplies
/// culture-specific formatting information.
/// A 16-bit unsigned integer equivalent to the value of this instance.
UInt16 IConvertible.ToUInt16(IFormatProvider provider)
{
if (this < UInt16.MinValue || this > UInt16.MaxValue)
throw new OverflowException();
return (UInt16)this;
}
///
/// Converts the value of this instance to an equivalent 32-bit unsigned integer using the specified
/// culture-specific formatting information.
///
/// An interface implementation that supplies
/// culture-specific formatting information.
/// A 32-bit unsigned integer equivalent to the value of this instance.
UInt32 IConvertible.ToUInt32(IFormatProvider provider)
{
if (this < UInt32.MinValue || this > UInt32.MaxValue)
throw new OverflowException();
return (UInt32)this;
}
///
/// Converts the value of this instance to an equivalent 64-bit unsigned integer using the specified
/// culture-specific formatting information.
///
/// An interface implementation that supplies
/// culture-specific formatting information.
/// A 64-bit unsigned integer equivalent to the value of this instance.
UInt64 IConvertible.ToUInt64(IFormatProvider provider)
{
if (this < UInt64.MinValue || this > UInt64.MaxValue)
throw new OverflowException();
return (UInt64)this;
}
///
/// Converts the value of this instance to an equivalent value using the specified
/// culture-specific formatting information.
///
/// An interface implementation that supplies
/// culture-specific formatting information.
/// A value equivalent to the value of this instance.
DateTime IConvertible.ToDateTime(IFormatProvider provider)
{
throw new InvalidCastException();
}
///
/// Converts the value of this instance to an equivalent decimal value using the specified
/// culture-specific formatting information.
///
/// An interface implementation that supplies
/// culture-specific formatting information.
/// A decimal value equivalent to the value of this instance.
decimal IConvertible.ToDecimal(IFormatProvider provider)
{
throw new InvalidCastException();
}
///
/// Converts the value of this instance to an equivalent floating-point value using the specified
/// culture-specific formatting information.
///
/// An interface implementation that supplies
/// culture-specific formatting information.
/// A floating-point value equivalent to the value of this instance.
double IConvertible.ToDouble(IFormatProvider provider)
{
throw new InvalidCastException();
}
///
/// Converts the value of this instance to an equivalent floating-point value using the specified
/// culture-specific formatting information.
///
/// An interface implementation that supplies
/// culture-specific formatting information.
/// A floating-point value equivalent to the value of this instance.
float IConvertible.ToSingle(IFormatProvider provider)
{
throw new InvalidCastException();
}
///
/// Converts the value of this instance to an equivalent string value using the specified
/// culture-specific formatting information.
///
/// An interface implementation that supplies
/// culture-specific formatting information.
/// A string value equivalent to the value of this instance.
string IConvertible.ToString(IFormatProvider provider)
{
throw new InvalidCastException();
}
#endregion
#region Arithmetic
#region Unary
///
/// Returns the value of the .
///
/// An integer value.
/// The value of the parameter.
public static Int128 operator +(Int128 value)
{
return value;
}
///
/// Negates a value.
///
/// The value to negate.
/// The result of the value parameter multiplied by negative one (-1).
public static Int128 operator -(Int128 value)
{
return Negate(value);
}
///
/// Negates an .
///
/// The value to negate.
/// The result of the value parameter multiplied by negative one (-1).
public static Int128 Negate(Int128 value)
{
value = ~value;
value++;
return value;
}
///
/// Returns the bitwise one's complement of an value.
///
/// An integer value.
/// The bitwise one's complement of .
public static Int128 operator ~(Int128 value)
{
return new Int128(~value.low, ~value.high);
}
///
/// Increments a value by 1.
///
/// The value to increment.
/// The value of the parameter incremented by 1.
public static Int128 operator ++(Int128 value)
{
value.low++;
if (value.low == 0)
value.high++;
return value;
}
///
/// Decrements a value by 1.
///
/// The value to decrement.
/// The value of the parameter decremented by 1.
public static Int128 operator --(Int128 value)
{
if (value.low == 0)
value.high--;
value.low--;
return value;
}
#endregion
#region Binary
///
/// Adds the values of two specified values.
///
/// The first value to add.
/// The second value to add.
/// The sum of and .
public static Int128 operator +(Int128 left, Int128 right)
{
return Add(left, right);
}
///
/// Adds two values and returns the result.
///
/// The first value to add.
/// The second value to add.
/// The sum of and .
public static Int128 Add(Int128 left, Int128 right)
{
var oldLow = left.low;
left.low += right.low;
left.high += right.high;
if (left.low < oldLow)
left.high++;
return left;
}
///
/// Subtracts an from another value.
///
/// The value to subtract from.
/// The value to subtract.
/// The result of subtracting from .
public static Int128 operator -(Int128 left, Int128 right)
{
return Subtract(left, right);
}
///
/// Subtracts one from another and returns the result.
///
/// The value to subtract from.
/// The value to subtract.
/// The result of subtracting from .
public static Int128 Subtract(Int128 left, Int128 right)
{
return left + (-right);
}
///
/// Performs a bitwise AND operation on two values.
///
/// The first value.
/// The second value.
/// The result of the bitwise AND operation.
public static Int128 operator &(Int128 left, Int128 right)
{
return new Int128(left.low & right.low, left.high & right.high);
}
///
/// Performs a bitwise OR operation on two values.
///
/// The first value.
/// The second value.
/// The result of the bitwise OR operation.
public static Int128 operator |(Int128 left, Int128 right)
{
return new Int128(left.low | right.low, left.high | right.high);
}
///
/// Performs a bitwise exclusive OR (XOR) operation on two values.
///
/// The first value.
/// The second value.
/// The result of the bitwise XOR operation.
public static Int128 operator ^(Int128 left, Int128 right)
{
return new Int128(left.low ^ right.low, left.high ^ right.high);
}
///
/// Shifts an value a specified number of bits to the left.
///
/// The value whose bits are to be shifted.
/// The number of bits to shift to the left.
/// A value that has been shifted to the left by the specified number of bits.
public static Int128 operator <<(Int128 value, int shift)
{
if (shift == 0)
return value;
if (shift < 0)
return value >> -shift;
// Shifting more than 127 bits would shift out any bits.
if (shift > 127)
return 0;
// Shifting more than 64 bits would shift all the low bits at least
// to the high bits.
if (shift > 63)
{
shift -= 64;
value.high = unchecked((long)value.low);
value.low = 0;
}
if (shift > 0)
{
long highbits = unchecked((long)(value.low >> (64 - shift)));
value.low <<= shift;
value.high <<= shift;
value.high |= highbits;
}
return value;
}
///
/// Shifts an value a specified number of bits to the right.
///
/// The value whose bits are to be shifted.
/// The number of bits to shift to the right.
/// A value that has been shifted to the right by the specified number of bits.
public static Int128 operator >>(Int128 value, int shift)
{
if (shift == 0)
return value;
if (shift < 0)
return value << -shift;
// Shifting more than 127 bits would shift out any bits.
if (shift > 127)
return 0;
// Shifting more than 64 bits would shift all the high bits at least
// to the low bits.
if (shift > 63)
{
shift -= 64;
value.low = unchecked((ulong)value.high);
value.high = 0;
}
if (shift > 0)
{
ulong lowbits = unchecked((ulong)(value.high << (64 - shift)));
value.low >>= shift;
value.high >>= shift;
value.low |= lowbits;
}
return value;
}
///
/// Multiplies two specified values.
///
/// The first value to multiply.
/// The second value to multiply.
/// The product of and .
public static Int128 operator *(Int128 left, Int128 right)
{
return Multiply(left, right);
}
///
/// Returns the product of two values.
///
/// The first number to multiply.
/// The second number to multiply.
/// The product of and .
public static Int128 Multiply(Int128 left, Int128 right)
{
uint left3 = (uint)(left.high >> 32);
uint left2 = (uint)left.high;
uint left1 = (uint)(left.low >> 32);
uint left0 = (uint)left.low;
ulong right3 = (uint)(right.high >> 32);
ulong right2 = (uint)right.high;
ulong right1 = (uint)(right.low >> 32);
ulong right0 = (uint)right.low;
Int128 value00 = (Int128)(left0 * right0);
Int128 value10 = (Int128)(left1 * right0) << 32;
Int128 value20 = new Int128(0, (long)(left2 * right0));
Int128 value30 = new Int128(0, (long)((left3 * right0) << 32));
Int128 value01 = (Int128)(left0 * right1) << 32;
Int128 value11 = new Int128(0, (long)(left1 * right1));
Int128 value21 = new Int128(0, (long)((left2 * right1) << 32));
Int128 value02 = new Int128(0, (long)(left0 * right2));
Int128 value12 = new Int128(0, (long)((left1 * right2) << 32));
Int128 value03 = new Int128(0, (long)((left0 * right3) << 32));
return value00 + value10 + value20 + value30
+ value01 + value11 + value21
+ value02 + value21
+ value03;
}
///
/// Divides a specified value by another specified value by using integer division.
///
/// The value to be divided.
/// The value to divide by.
/// The integral result of the division.
public static Int128 operator /(Int128 dividend, Int128 divisor)
{
#region Contract
Contract.Requires(divisor != 0);
#endregion
return Divide(dividend, divisor);
}
///
/// Divides one by another and returns the result.
///
/// The value to be divided.
/// The value to divide by.
/// The quotient of the division.
public static Int128 Divide(Int128 dividend, Int128 divisor)
{
#region Contract
Contract.Requires(divisor != 0);
#endregion
Int128 remainder;
return DivRem(dividend, divisor, out remainder);
}
///
/// Returns the remainder that results from division with two specified values.
///
/// The value to be divided.
/// The value to divide by.
/// The remainder that results from the division.
public static Int128 operator %(Int128 dividend, Int128 divisor)
{
#region Contract
Contract.Requires(divisor != 0);
#endregion
return Remainder(dividend, divisor);
}
///
/// Performs integer division on two values and returns the remainder.
///
/// The value to be divided.
/// The value to divide by.
/// The remainder after dividing by .
public static Int128 Remainder(Int128 dividend, Int128 divisor)
{
#region Contract
Contract.Requires(divisor != 0);
#endregion
Int128 remainder;
DivRem(dividend, divisor, out remainder);
return remainder;
}
#endregion
///
/// Gets the absolute value of an .
///
/// A value.
/// The absolute value of .
public static Int128 Abs(Int128 value)
{
Int128 result = value;
if (result < 0)
result = -result;
return result;
}
///
/// Divides one value by another, using signed integer division, and returns the result
/// and the remainder.
///
/// The value to be divided.
/// The value to divide by.
/// The remainder from the division.
/// The quotient of the division.
public static Int128 DivRem(Int128 dividend, Int128 divisor, out Int128 remainder)
{
Int128 quotient;
int remainderSign = 1;
if (dividend < 0)
{
dividend = -dividend;
remainderSign = -1;
}
int quotientSign = 1;
if (divisor < 0)
{
divisor = -divisor;
quotientSign = -1;
}
quotientSign *= remainderSign;
quotient = UnsignedDivRem(dividend, divisor, out remainder);
quotient *= quotientSign;
remainder *= remainderSign;
return quotient;
}
///
/// Divides one value by another, using unsigned integer division, and returns the result
/// and the remainder.
///
/// The value to be divided.
/// The value to divide by.
/// The remainder from the division.
/// The quotient of the division.
public static Int128 UnsignedDivRem(Int128 dividend, Int128 divisor, out Int128 remainder)
{
Int128 quotient = dividend;
remainder = 0;
for (int i = 0; i < 128; i++)
{
remainder <<= 1;
if (quotient < 0)
remainder.low |= 1;
quotient <<= 1;
if (remainder >= divisor)
{
remainder -= divisor;
quotient++;
}
}
return quotient;
}
///
/// Returns the larger of two values.
///
/// The first value to compare.
/// The second value to compare.
/// The or parameter, whichever is larger.
public static Int128 Max(Int128 left, Int128 right)
{
Int128 result = left;
if (right > left)
result = right;
return result;
}
///
/// Returns the smaller of two values.
///
/// The first value to compare.
/// The second value to compare.
/// The or parameter, whichever is smaller.
public static Int128 Min(Int128 left, Int128 right)
{
Int128 result = left;
if (right < left)
result = right;
return result;
}
///
/// Calculates the padding required to align the value to the next specified boundary.
///
/// The boundary to align to, which must be a power of two.
/// The number of padding bytes required to align the address to the specified boundary.
public Int128 GetPadding(int boundary)
{
return (boundary + ((this - 1) & ~(boundary - 1))) - this;
}
///
/// Aligns the value to the next specified boundary.
///
/// The boundary to align to, which must be a power of two.
/// The address aligned to the specified boundary.
public Int128 Align(int boundary)
{
return (boundary + ((this - 1) & ~(boundary - 1)));
}
#endregion
#region Strings
///
/// Formats the value of the current instance using the specified format.
///
/// The format to use.
/// -or-
/// to use the default format defined for the type of the
/// implementation.
/// The provider to use to format the value.
/// -or-
/// to obtain the numeric format information from the current locale setting of
/// the operating system.
/// The value of the current instance in the specified format.
public string ToString(string format, IFormatProvider formatProvider)
{
// TODO: Implement.
return ToString();
}
#endregion
#region Fields
///
/// The low part of the integer.
///
private ulong low;
///
/// The high part of the integer.
///
private long high;
#endregion
}
}