4
\$\begingroup\$

I have created Int128 which is based off of BigInteger with operator overloading to handle larger math requirements. Here is a look at my Int128 implementation.

/// <summary>
/// Creates a new <see cref="Int128"/>
/// </summary> 
public readonly struct Int128(long high, ulong low) : 
IComparable, IComparable<Int128>, IEquatable<Int128>
{ 
 private readonly BigInteger Value = ((BigInteger)high << 64) | low;
 /// <summary>
 /// Used for our ++ and -- operators
 /// </summary>
 private static readonly Int128 Increment_Deincrement = new(1);
 /// <summary>
 /// Creates a new <see cref="Int128"/> with
 /// only <paramref name="low"/> bits set
 /// </summary>
 /// <param name="low"></param>
 public Int128(ulong low) : this(0, low) 
 { 
 } 
 
 /// <summary>
 /// Used only for our <see cref="operator"/> overloads.
 /// Low and high bits don't matter here as it most 
 /// likely will exceed what can they can represent. 
 /// </summary> 
 private Int128(BigInteger value) : this(0, 0)
 { 
 Value = value;
 } 
 public static Int128 operator ++(Int128 value)
 => value + Increment_Deincrement;
 public static Int128 operator --(Int128 value)
 => value - Increment_Deincrement;
 public static Int128 operator +(Int128 left, Int128 right) 
 => new((BigInteger)(left.Value + right.Value));
 public static Int128 operator -(Int128 left, Int128 right) 
 => new((BigInteger)(left.Value - right.Value));
 public static Int128 operator *(Int128 left, Int128 right) 
 => new((BigInteger)(left.Value * right.Value));
 public static Int128 operator /(Int128 left, Int128 right)
 {
 return right.Value == 0 ? default : new((BigInteger)(left.Value / right.Value));
 } 
 public static Int128 operator %(Int128 left, Int128 right) 
 => new((BigInteger)(left.Value % right.Value));
 public static bool operator ==(Int128 left, Int128 right) 
 => left.Value == right.Value;
 public static bool operator !=(Int128 left, Int128 right) 
 => !(left == right);
 public static bool operator <(Int128 left, Int128 right) 
 => left.Value < right.Value;
 public static bool operator <=(Int128 left, Int128 right) 
 => left.Value <= right.Value;
 public static bool operator >(Int128 left, Int128 right) 
 => left.Value > right.Value;
 public static bool operator >=(Int128 left, Int128 right) 
 => left.Value >= right.Value;
 public override bool Equals(object? obj)
 => obj != null && obj is Int128 other && Equals(other);
 public bool Equals(Int128 other) 
 => Value.Equals(other.Value);
 public override int GetHashCode() 
 => Value.GetHashCode();
 public int CompareTo(object? obj) 
 => obj != null && obj is Int128 other ? CompareTo(other) : 1;
 public int CompareTo(Int128 other) => Value.CompareTo(other.Value);
 public override string ToString() => Value.ToString();
 public string ToString(string format) => Value.ToString(format);
}
toolic
14.4k5 gold badges29 silver badges200 bronze badges
asked Feb 8 at 18:53
\$\endgroup\$
5
  • 3
    \$\begingroup\$ Since .NET 7, there has been an Int128 struct. Why is this insufficient for you? What does your implementation do to justify its existence? \$\endgroup\$ Commented Feb 9 at 18:03
  • \$\begingroup\$ From source.dot.net : source.dot.net/#System.Private.CoreLib/src/libraries/… \$\endgroup\$ Commented Feb 9 at 18:04
  • \$\begingroup\$ @RickDavin you're correct, I have an Int128 on my windows rig, my Linux rig on the other hand does not. This is the reason for developing this struct as I can add System.Numerics NuGet package to make use of BigInteger to create the Int128. This should probably be explained in the question. \$\endgroup\$ Commented Feb 10 at 14:50
  • \$\begingroup\$ As User555045 recommended I am currently creating a clamp function to keep it within range of Int128 \$\endgroup\$ Commented Feb 10 at 14:51
  • \$\begingroup\$ linux: depending on compiler and libraries there are - not well matured - uint128 and int128 types available as GNU extension. gcc.gnu.org/onlinedocs/gcc/_005f_005fint128.html \$\endgroup\$ Commented Feb 12 at 2:05

1 Answer 1

5
\$\begingroup\$
/// <summary>
/// Used only for our <see cref="operator"/> overloads.
/// Low and high bits don't matter here as it most 
/// likely will exceed what can they can represent. 
/// </summary> 
private Int128(BigInteger value) : this(0, 0)
{ 
 Value = value;
}

If the value passed in is outside the range of an Int128, then this constructor constructs an instance of this struct in an invalid state. The comment even acknowledges that.
Since this is a private constructor, that may be OK as long as every use of it is careful to pass an in-range value. But the arithmetic operators do not restrict the range, so you can very easily leave the range that an Int128 would have without the expected "wrapping" behaviour.

In effect, that makes this struct a BigInteger again, there's no "Int128-like behaviour" except offering a constructor that takes two 64-bit chunks to build the value out of. In almost every way this struct acts like a BigInteger.

However, it's a version of BigInteger that allows division by zero (but not remainder by zero), and it supports fewer operations.

Casts

Casting a BigInteger to a BigInteger is not useful. Many of the arithmetic operators do that.

Short Int
6242 silver badges14 bronze badges
answered Feb 8 at 20:05
\$\endgroup\$
4
  • \$\begingroup\$ There is no upper bound for BigInteger, it grows as much as your system memory allows. The larger the number the slower it is \$\endgroup\$ Commented Feb 8 at 20:39
  • 2
    \$\begingroup\$ @CharlesHenington well yes, I know what a BigInteger is \$\endgroup\$ Commented Feb 8 at 20:41
  • \$\begingroup\$ The comment you mention, that the BigInteger will exceed what the high and low can represent but not what the BigInteger represents. If I'm misunderstanding you please let me know, thanks. \$\endgroup\$ Commented Feb 8 at 21:26
  • 2
    \$\begingroup\$ @CharlesHenington that's right but my point is it makes this Int128 struct just act like it is a BigInteger again, which is not how an Int128 would behave \$\endgroup\$ Commented Feb 8 at 21:30

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.