I128.cs (14670B)
1 using Std.Clone; 2 using Std.Cmp; 3 using Std.Convert; 4 using Std.Hashing; 5 using Std.Maybe; 6 using static Std.Maybe.Maybe<Std.Cmp.Ordering>; 7 using static Std.Maybe.Maybe<uint>; 8 using Std.Result; 9 using static Std.Result.Result<Std.Num.I128, Std.Bottom>; 10 using static Std.Result.Result<string, Std.Bottom>; 11 using System; 12 using System.Runtime.CompilerServices; 13 using System.Runtime.InteropServices; 14 #region Namespaces 15 namespace Std.Num { 16 #region Types 17 [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 8, Size = 16)] 18 public readonly struct I128: IClone<I128>, IEquality<I128>, IHashable, IInto<I128>, IInto<string>, IOrd<I128>, ITryInto<U128, TryIntoIntError>, ITryInto<NonZeroI128, TryIntoIntError>, ITryInto<byte, TryIntoIntError>, ITryInto<int, TryIntoIntError>, ITryInto<long, TryIntoIntError>, ITryInto<sbyte, TryIntoIntError>, ITryInto<short, TryIntoIntError>, ITryInto<uint, TryIntoIntError>, ITryInto<ulong, TryIntoIntError>, ITryInto<ushort, TryIntoIntError>, IFrom<I128, bool>, IFrom<I128, sbyte>, IFrom<I128, byte>, IFrom<I128, short>, IFrom<I128, ushort>, IFrom<I128, int>, IFrom<I128, uint>, IFrom<I128, long>, IFrom<I128, ulong> { 19 20 #region Type-level Constructors 21 #endregion 22 23 #region Instance Constructors 24 [MethodImpl(MethodImplOptions.AggressiveInlining)] 25 public I128() => Value = U128.MinValue; 26 [MethodImpl(MethodImplOptions.AggressiveInlining)] 27 internal I128(U128 val) => Value = val; 28 [MethodImpl(MethodImplOptions.AggressiveInlining)] 29 public I128(long low) => Value = low < 0L ? new((ulong)low, ulong.MaxValue) : new((ulong)low); 30 [MethodImpl(MethodImplOptions.AggressiveInlining)] 31 public I128(long low, long high) => Value = new((ulong)low, (ulong)high); 32 #endregion 33 34 #region Type-level Fields 35 public static readonly I128 Zero = new(); 36 public static readonly I128 MaxValue = new(-1L, long.MaxValue); 37 public static readonly I128 MinValue = new(0L, long.MinValue); 38 #endregion 39 40 #region Instance Fields 41 [FieldOffset(0)] public readonly U128 Value; 42 #endregion 43 44 #region Type-level Properties 45 #endregion 46 47 #region Instance Properties 48 #endregion 49 50 #region Type-level Functions 51 public static U128 Abs(I128 val) => val >= Zero ? val.Value : (MinValue - (val - MinValue)).Value; 52 public static Prod<I128, I128> DivRem(I128 dividend, I128 divisor) { 53 54 var val = U128.DivRem(Abs(dividend), Abs(divisor)); 55 return dividend < Zero ? divisor < Zero ? new(new I128(val.Item0), -new I128(val.Item1)) : new(-new I128(val.Item0), -new I128(val.Item1)) : divisor < Zero ? new(-new I128(val.Item0), new I128(val.Item1)) : new(new I128(val.Item0), new I128(val.Item1)); 56 } 57 public static Prod<I128, I128> DivRem(I128 dividend, NonZeroI128 divisor) { 58 var val = U128.DivRem(Abs(dividend), new NonZeroU128(Abs(divisor.Value))); 59 return dividend < Zero ? divisor.Value < Zero ? new(new I128(val.Item0), -new I128(val.Item1)) : new(-new I128(val.Item0), -new I128(val.Item1)) : divisor.Value < Zero ? new(-new I128(val.Item0), new I128(val.Item1)) : new(new I128(val.Item0), new I128(val.Item1)); 60 } 61 public static I128 FromBEBytes(ReadOnlySpan<byte> val) => new(U128.FromBEBytes(val)); 62 public static I128 FromLEBytes(ReadOnlySpan<byte> val) => new(U128.FromLEBytes(val)); 63 public static Result<I128, ParseIntError> TryFrom(ReadOnlySpan<char> val) => val.Length is 0 or > 40 ? (new(ParseIntError.InvalidLength)) : val[0] == '-' ? val.Length == 1 ? (new(ParseIntError.InvalidDigit)) : U128.TryFrom(val[1..]).AndThen((v) => v.TryIntoI128().MapErr((_) => ParseIntError.OverflowOrUnderflow)).Map((v) => -v) : U128.TryFrom(val).AndThen((v) => v.TryIntoI128().MapErr((_) => ParseIntError.OverflowOrUnderflow)); 64 public static Result<I128, ParseIntError> TryFromAllowLeading0s(ReadOnlySpan<char> val) => val.Length == 0 ? (new(ParseIntError.InvalidLength)) : val[0] == '-' ? val.Length == 1 ? (new(ParseIntError.InvalidDigit)) : U128.TryFromAllowLeading0s(val[1..]).AndThen((v) => v.TryIntoI128().MapErr((_) => ParseIntError.OverflowOrUnderflow)).Map((v) => -v) : U128.TryFromAllowLeading0s(val).AndThen((v) => v.TryIntoI128().MapErr((_) => ParseIntError.OverflowOrUnderflow)); 65 public static I128 New(long low) => new(low); 66 public static I128 New(long low, long high) => new(low, high); 67 public static I128 From(bool val) => new(U128.From(val)); 68 public static I128 From(byte val) => new(val); 69 public static I128 From(int val) => new(val); 70 public static I128 From(long val) => new(val); 71 public static I128 From(sbyte val) => new(val); 72 public static I128 From(short val) => new(val); 73 public static I128 From(uint val) => new(val); 74 public static I128 From(ulong val) => new(new U128(val)); 75 public static I128 From(ushort val) => new(val); 76 static Result<I128, Bottom> ITryFrom<I128, bool, Bottom>.TryFrom(bool val) => new(From(val)); 77 static Result<I128, Bottom> ITryFrom<I128, byte, Bottom>.TryFrom(byte val) => new(From(val)); 78 static Result<I128, Bottom> ITryFrom<I128, int, Bottom>.TryFrom(int val) => new(From(val)); 79 static Result<I128, Bottom> ITryFrom<I128, long, Bottom>.TryFrom(long val) => new(From(val)); 80 static Result<I128, Bottom> ITryFrom<I128, sbyte, Bottom>.TryFrom(sbyte val) => new(From(val)); 81 static Result<I128, Bottom> ITryFrom<I128, short, Bottom>.TryFrom(short val) => new(From(val)); 82 public static Result<I128, ParseIntError> TryFrom(string val) => TryFrom(val.AsSpan()); 83 static Result<I128, Bottom> ITryFrom<I128, uint, Bottom>.TryFrom(uint val) => new(From(val)); 84 static Result<I128, Bottom> ITryFrom<I128, ulong, Bottom>.TryFrom(ulong val) => new(From(val)); 85 static Result<I128, Bottom> ITryFrom<I128, ushort, Bottom>.TryFrom(ushort val) => new(From(val)); 86 #endregion 87 88 #region Instance Functions 89 public readonly I128 Clone() => this; 90 public readonly Ordering Cmp(in I128 other) => (this - MinValue).Value.Cmp((other - MinValue).Value); 91 public readonly bool Equals(in I128 other) => this == other; 92 public override readonly bool Equals(object? _) => false; 93 public override readonly int GetHashCode() => 0; 94 public readonly Unit Hash<THasher>(ref THasher hasher) where THasher: notnull, IHasher => hasher.WriteUnsafe(this); 95 public readonly I128 Into() => this; 96 public readonly byte[] IntoBEBytes() => Value.IntoBEBytes(); 97 public readonly Unit IntoBEBytes(Span<byte> bytes) => Value.IntoBEBytes(bytes); 98 public readonly byte[] IntoLEBytes() => Value.IntoLEBytes(); 99 public readonly Unit IntoLEBytes(Span<byte> bytes) => Value.IntoLEBytes(bytes); 100 public readonly string IntoString() => ToString(); 101 readonly string IInto<string>.Into() => IntoString(); 102 public readonly Maybe<Ordering> PartialCmp(in I128 other) => Some(Cmp(in other)); 103 public override readonly string ToString() => this < Zero ? $"-{Abs(this).ToString()}" : $"{Value.ToString()}"; 104 readonly Result<I128, Bottom> ITryInto<I128, Bottom>.TryInto() => OK(this); 105 readonly Result<string, Bottom> ITryInto<string, Bottom>.TryInto() => new(ToString()); 106 readonly Result<U128, TryIntoIntError> ITryInto<U128, TryIntoIntError>.TryInto() => TryIntoU128(); 107 readonly Result<NonZeroI128, TryIntoIntError> ITryInto<NonZeroI128, TryIntoIntError>.TryInto() => TryIntoNonZeroI128(); 108 readonly Result<byte, TryIntoIntError> ITryInto<byte, TryIntoIntError>.TryInto() => TryIntoByte(); 109 readonly Result<int, TryIntoIntError> ITryInto<int, TryIntoIntError>.TryInto() => TryIntoInt(); 110 readonly Result<long, TryIntoIntError> ITryInto<long, TryIntoIntError>.TryInto() => TryIntoLong(); 111 readonly Result<sbyte, TryIntoIntError> ITryInto<sbyte, TryIntoIntError>.TryInto() => TryIntoSbyte(); 112 readonly Result<short, TryIntoIntError> ITryInto<short, TryIntoIntError>.TryInto() => TryIntoShort(); 113 readonly Result<uint, TryIntoIntError> ITryInto<uint, TryIntoIntError>.TryInto() => TryIntoUint(); 114 readonly Result<ulong, TryIntoIntError> ITryInto<ulong, TryIntoIntError>.TryInto() => TryIntoUlong(); 115 readonly Result<ushort, TryIntoIntError> ITryInto<ushort, TryIntoIntError>.TryInto() => TryIntoUshort(); 116 public readonly Result<U128, TryIntoIntError> TryIntoU128() => this < Zero ? new(TryIntoIntError.Overflow) : new((U128)this); 117 public readonly Result<NonZeroI128, TryIntoIntError> TryIntoNonZeroI128() => NonZeroI128.New(this).OKOr(TryIntoIntError.Overflow); 118 public readonly Result<byte, TryIntoIntError> TryIntoByte() => this > (I128)byte.MaxValue ? new(TryIntoIntError.Overflow) : new((byte)this); 119 public readonly Result<int, TryIntoIntError> TryIntoInt() => this > (I128)int.MaxValue ? new(TryIntoIntError.Overflow) : new((int)this); 120 public readonly Result<long, TryIntoIntError> TryIntoLong() => this > (I128)long.MaxValue ? new(TryIntoIntError.Overflow) : new((long)this); 121 public readonly Result<sbyte, TryIntoIntError> TryIntoSbyte() => this > (I128)sbyte.MaxValue ? new(TryIntoIntError.Overflow) : new((sbyte)this); 122 public readonly Result<short, TryIntoIntError> TryIntoShort() => this > (I128)short.MaxValue ? new(TryIntoIntError.Overflow) : new((short)this); 123 public readonly Result<uint, TryIntoIntError> TryIntoUint() => this > (I128)uint.MaxValue ? new(TryIntoIntError.Overflow) : new((uint)this); 124 public readonly Result<ulong, TryIntoIntError> TryIntoUlong() => this > (I128)ulong.MaxValue ? new(TryIntoIntError.Overflow) : new((ulong)this); 125 public readonly Result<ushort, TryIntoIntError> TryIntoUshort() => this > (I128)ushort.MaxValue ? new(TryIntoIntError.Overflow) : new((ushort)this); 126 #endregion 127 128 #region Operators 129 public static bool operator !=(I128 val0, I128 val1) => !(val0 == val1); 130 public static I128 operator %(I128 dividend, I128 divisor) => DivRem(dividend, divisor).Item1; 131 public static I128 operator %(I128 dividend, NonZeroI128 divisor) => DivRem(dividend, divisor).Item1; 132 public static I128 operator &(I128 val0, I128 val1) => new(val0.Value & val1.Value); 133 public static I128 operator *(I128 val0, I128 val1) => new(val0.Value * val1.Value); 134 public static I128 operator +(I128 val) => val; 135 public static I128 operator +(I128 val0, I128 val1) => new(val0.Value + val1.Value); 136 public static I128 operator ++(I128 val) => val + new I128(1L); 137 public static I128 operator -(I128 val) => new(-val.Value); 138 public static I128 operator -(I128 val0, I128 val1) => new(val0.Value - val1.Value); 139 public static I128 operator --(I128 val) => val - new I128(1L); 140 public static I128 operator /(I128 dividend, I128 divisor) => DivRem(dividend, divisor).Item0; 141 public static I128 operator /(I128 dividend, NonZeroI128 divisor) => DivRem(dividend, divisor).Item0; 142 public static bool operator <(I128 val0, I128 val1) => (val0 - MinValue).Value < (val1 - MinValue).Value; 143 public static I128 operator <<(I128 val, int shift) => new(val.Value << shift); 144 public static bool operator <=(I128 val0, I128 val1) => !(val0 > val1); 145 public static bool operator ==(I128 val0, I128 val1) => val0.Value == val1.Value; 146 public static bool operator >(I128 val0, I128 val1) => (val0 - MinValue).Value > (val1 - MinValue).Value; 147 public static bool operator >=(I128 val0, I128 val1) => !(val0 < val1); 148 public static I128 operator >>(I128 val, int shift) { 149 150 shift &= 127; 151 return val >= Zero ? new(val.Value >> shift) : shift == 0 ? val : new((val.Value >> shift) | (U128.MaxValue << (128 - shift))); 152 } 153 public static I128 operator ^(I128 val0, I128 val1) => new(val0.Value ^ val1.Value); 154 public static I128 operator |(I128 val0, I128 val1) => new(val0.Value | val1.Value); 155 public static I128 operator |(I128 val0, NonZeroI128 val1) => val0 | val1.Value; 156 public static I128 operator ~(I128 val) => new(~val.Value); 157 public static explicit operator I128(byte val) => new((U128)val); 158 public static explicit operator I128(decimal val) { 159 160 var u128 = (U128)Math.Abs(val); 161 return val < decimal.Zero ? u128 >= MinValue.Value ? MinValue : -new I128(u128) : u128 >= MaxValue.Value ? MaxValue : new I128(u128); 162 } 163 public static explicit operator I128(double val) { 164 165 var u128 = (U128)Math.Abs(val); 166 return val < 0d ? u128 >= MinValue.Value ? MinValue : -new I128(u128) : u128 >= MaxValue.Value ? MaxValue : new I128(u128); 167 } 168 public static explicit operator I128(float val) => (I128)(double)val; 169 public static explicit operator I128(U128 val) => new(val); 170 public static explicit operator I128(int val) => new((U128)val); 171 public static explicit operator I128(long val) => new((U128)val); 172 public static explicit operator I128(sbyte val) => new((U128)val); 173 public static explicit operator byte(I128 val) => (byte)val.Value; 174 public static explicit operator decimal(I128 val) => val < Zero ? -(decimal)Abs(val) : (decimal)Abs(val); 175 public static explicit operator double(I128 val) => val < Zero ? -(double)Abs(val) : (double)Abs(val); 176 public static explicit operator float(I128 val) => (float)(double)val; 177 public static explicit operator U128(I128 val) => val.Value; 178 public static explicit operator int(I128 val) => (int)val.Value; 179 public static explicit operator long(I128 val) => (long)val.Value; 180 public static explicit operator sbyte(I128 val) => (sbyte)val.Value; 181 public static explicit operator short(I128 val) => (short)val.Value; 182 public static explicit operator uint(I128 val) => (uint)val.Value; 183 public static explicit operator ulong(I128 val) => (ulong)val.Value; 184 public static explicit operator ushort(I128 val) => (ushort)val.Value; 185 public static explicit operator I128(uint val) => new((U128)val); 186 public static explicit operator I128(ulong val) => new((U128)val); 187 public static explicit operator I128(ushort val) => new((U128)val); 188 #endregion 189 190 #region Types 191 #endregion 192 } 193 #endregion 194 195 #region Namespaces 196 #endregion 197 } 198 #endregion