Std

Mainly a port of Rust's std.
git clone https://git.philomathiclife.com/repos/Std
Log | Files | Refs | README

Cmp.cs (12395B)


      1 using Std.Clone;
      2 using Std.Convert;
      3 using Std.Hashing;
      4 using Std.Maybe;
      5 using Std.Ops;
      6 using Std.Result;
      7 using System;
      8 using System.Runtime.CompilerServices;
      9 using System.Runtime.InteropServices;
     10 #region Namespaces
     11 namespace Std.Cmp {
     12     #region Types
     13     // Types TSelf are allowed to implement IPartialEq<TSelf, T> so long as T implements IPartialEq<T, TSelf> in a consistent manner.
     14     // That is to say:
     15     // for all t1 in TSelf and t2 in T, t1 == t2 ⟺  t2 == t1.
     16     // For all t1 in TSelf and t2 in T, t1 == t2 ⟺  ¬(t1 != t2).
     17     public interface IPartialEq<TSelf, T> where TSelf: notnull, IPartialEq<TSelf, T> where T: notnull, IPartialEq<T, TSelf> {
     18 
     19         #region Type-level Constructors
     20         #endregion
     21 
     22         #region Instance Constructors
     23         #endregion
     24 
     25         #region Type-level Fields
     26         #endregion
     27 
     28         #region Instance Fields
     29         #endregion
     30 
     31         #region Type-level Properties
     32         #endregion
     33 
     34         #region Instance Properties
     35         #endregion
     36 
     37         #region Type-level Functions
     38         #endregion
     39 
     40         #region Instance Functions
     41         #endregion
     42 
     43         #region Operators
     44         [MethodImpl(MethodImplOptions.AggressiveInlining)]
     45         public static abstract bool operator ==(TSelf self, T other);
     46         [MethodImpl(MethodImplOptions.AggressiveInlining)]
     47         public static abstract bool operator !=(TSelf self, T other);
     48         #endregion
     49 
     50         #region Types
     51         #endregion
     52     }
     53     // Types TSelf are only allowed to implement IEq<TSelf>.
     54     // This interface represents an equivalence relation which means
     55     // that for all t1 in TSelf, t1 == t1 (reflexive).
     56     // For all t1, t2 in TSelf, t1 == t2 ⟺  t2 == t1 (symmetric).
     57     // For all t1, t2, t3 in TSelf, t1 == t2 ∧ t2 == t3 ⇒ t1 == t3 (transitive).
     58     // Types that additionally implement Std.Hash.IHashable MUST implement Hash such that equivalent values get hashed to the same thing.
     59     public interface IEq<TSelf>: IPartialEq<TSelf, TSelf> where TSelf: notnull, IEq<TSelf> {
     60 
     61         #region Type-level Constructors
     62         #endregion
     63 
     64         #region Instance Constructors
     65         #endregion
     66 
     67         #region Type-level Fields
     68         #endregion
     69 
     70         #region Instance Fields
     71         #endregion
     72 
     73         #region Type-level Properties
     74         #endregion
     75 
     76         #region Instance Properties
     77         #endregion
     78 
     79         #region Type-level Functions
     80         #endregion
     81 
     82         #region Instance Functions
     83         #endregion
     84 
     85         #region Operators
     86         #endregion
     87 
     88         #region Types
     89         #endregion
     90     }
     91     // This interface represents true equality which means
     92     // for all t1, t2 in TSelf, t1.Equals(in t2) implies that for all functions f, f(t1) has the same exact observable behavior (ignoring things like reflection and pointers)
     93     // as f(t2) (indistinguishable/equality).
     94     // For all t1, t2 in TSelf, t1.Equals(in t2) ⇒ t1 == t2.
     95     public interface IEquality<TSelf>: IEq<TSelf> where TSelf: notnull, IEquality<TSelf> {
     96 
     97         #region Type-level Constructors
     98         #endregion
     99 
    100         #region Instance Constructors
    101         #endregion
    102 
    103         #region Type-level Fields
    104         #endregion
    105 
    106         #region Instance Fields
    107         #endregion
    108 
    109         #region Type-level Properties
    110         #endregion
    111 
    112         #region Instance Properties
    113         #endregion
    114 
    115         #region Type-level Functions
    116         #endregion
    117 
    118         #region Instance Functions
    119         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    120         public abstract bool Equals(in TSelf other);
    121         #endregion
    122 
    123         #region Operators
    124         #endregion
    125 
    126         #region Types
    127         #endregion
    128     }
    129     [StructLayout(LayoutKind.Explicit, CharSet = CharSet.Unicode, Pack = 1, Size = 1)]
    130     public readonly struct Ordering: ISum<Ordering.Ord, Ordering.Ord, Ordering.Ord>, IClone<Ordering>, IEquality<Ordering>, IHashable, IInto<Ordering>, IInto<string>, IOrd<Ordering> {
    131 
    132         #region Type-level Constructors
    133         #endregion
    134 
    135         #region Instance Constructors
    136         public Ordering() => throw new InvalidOperationException("Parameterless constructor is not allowed to be called!");
    137         Ordering(Ord tag) => Var = tag;
    138         #endregion
    139 
    140         #region Type-level Fields
    141         public static readonly Ordering Less = new(Ord.Less);
    142         public static readonly Ordering Equivalent = new(Ord.Equivalent);
    143         public static readonly Ordering Greater = new(Ord.Greater);
    144         #endregion
    145 
    146         #region Instance Fields
    147         [FieldOffset(0)] public readonly Ord Var;
    148         #endregion
    149 
    150         #region Type-level Properties
    151         #endregion
    152 
    153         #region Instance Properties
    154         public readonly Var3 Variant => (Var3)Var;
    155         public readonly Ord Variant0 => Var == Ord.Less ? Var : throw new InvalidOperationException($"The Ordering variant, {Var.ToString()} is not Less!");
    156         public readonly Ord Variant1 => Var == Ord.Equivalent ? Var : throw new InvalidOperationException($"The Ordering variant, {Var.ToString()} is not Equivalent!");
    157         public readonly Ord Variant2 => Var == Ord.Greater ? Var : throw new InvalidOperationException($"The Ordering variant, {Var.ToString()} is not Greater!");
    158         #endregion
    159 
    160         #region Type-level Functions
    161         #endregion
    162 
    163         #region Instance Functions
    164         public readonly Ordering Clone() => this;
    165         public readonly Ordering Cmp(in Ordering other) => ((byte)Var).CompareTo((byte)other.Var) switch {
    166             < 0 => Less,
    167             0 => Equivalent,
    168             > 0 => Greater,
    169         };
    170         public readonly bool Equals(in Ordering other) => this == other;
    171         public override readonly bool Equals(object? _) => false;
    172         public override readonly int GetHashCode() => 0;
    173         public readonly Unit Hash<THasher>(ref THasher hasher) where THasher: notnull, IHasher => hasher.WriteUnsafe(this);
    174         public readonly Ordering Into() => this;
    175         public readonly string IntoString() => ToString();
    176         readonly string IInto<string>.Into() => IntoString();
    177         public readonly Maybe<Ordering> PartialCmp(in Ordering other) => new(Cmp(in other));
    178         public override readonly string ToString() => Var.ToString();
    179         readonly Result<Ordering, Bottom> ITryInto<Ordering, Bottom>.TryInto() => new(this);
    180         readonly Result<string, Bottom> ITryInto<string, Bottom>.TryInto() => new(ToString());
    181         #endregion
    182 
    183         #region Operators
    184         public static bool operator !=(Ordering val0, Ordering val1) => !(val0 == val1);
    185         public static bool operator <(Ordering val0, Ordering val1) => (byte)val0.Var < (byte)val1.Var;
    186         public static bool operator <=(Ordering val0, Ordering val1) => !(val0 > val1);
    187         public static bool operator ==(Ordering val0, Ordering val1) => val0.Var == val1.Var;
    188         public static bool operator >(Ordering val0, Ordering val1) => (byte)val0.Var > (byte)val1.Var;
    189         public static bool operator >=(Ordering val0, Ordering val1) => !(val0 < val1);
    190         #endregion
    191 
    192         #region Types
    193         public enum Ord: byte {
    194             Less = byte.MinValue,
    195             Equivalent = 1,
    196             Greater = 2,
    197         }
    198         #endregion
    199     }
    200     // Types TSelf are allowed to implement IPartialOrd<TSelf, T> so long as T implements IPartialOrd<T, TSelf> in a consistent manner. That is to say
    201     // for all t1 in TSelf and t2 in T, t1 > t2 ⟺  t2 < t1 ∧ t1 < t2 ⟺  t2 > t1.
    202     // For all t1 in TSelf and t2 in T, (t1 >= t2 ⟺  (t1 == t2 ∨ t1 > t2)) ∧ (t1 <= t2 ⟺  (t1 == t2 ∨ t1 < t2)).
    203     // Similarly for all t1 in TSelf and t2 in T, t1 > t2 ⟺  t1.PartialCmp(in t2).Unwrap().IsGreater ∧ t1 < t2 ⟺  t1.PartialCmp(in t2).Unwrap().IsLess ∧ t1 == t2 ⟺  t1.PartialCmp(in t2).Unwrap().IsEquivalent.
    204     public interface IPartialOrd<TSelf, T>: IPartialEq<TSelf, T> where TSelf: notnull, IPartialOrd<TSelf, T> where T: notnull, IPartialOrd<T, TSelf> {
    205 
    206         #region Type-level Constructors
    207         #endregion
    208 
    209         #region Instance Constructors
    210         #endregion
    211 
    212         #region Type-level Fields
    213         #endregion
    214 
    215         #region Instance Fields
    216         #endregion
    217 
    218         #region Type-level Properties
    219         #endregion
    220 
    221         #region Instance Properties
    222         #endregion
    223 
    224         #region Type-level Functions
    225         #endregion
    226 
    227         #region Instance Functions
    228         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    229         public abstract Maybe<Ordering> PartialCmp(in T other);
    230         #endregion
    231 
    232         #region Operators
    233         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    234         public static abstract bool operator >(TSelf self, T other);
    235         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    236         public static abstract bool operator >=(TSelf self, T other);
    237         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    238         public static abstract bool operator <(TSelf self, T other);
    239         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    240         public static abstract bool operator <=(TSelf self, T other);
    241         #endregion
    242 
    243         #region Types
    244         #endregion
    245     }
    246     // This interface represents a total ordering relation which means
    247     // a type TSelf that implements IOrd<TSelf> implements IEq<TSelf> and IPartialOrd<TSelf, TSelf>.
    248     // For all t1, t2 in TSelf, t1 < t2 ∨ t1 == t2 ∨ t1 > t2.
    249     // For all t1, t2 in TSelf, t1 < t2 ⟺  t1.Cmp(in t2).IsLess ∧ t1 == t2 ⟺  t1.Cmp(in t2).IsEquivalent ∧ t1 > t2 ⟺  t1.Cmp(in t2).IsGreater.
    250     public interface IOrd<TSelf>: IEq<TSelf>, IPartialOrd<TSelf, TSelf> where TSelf: notnull, IOrd<TSelf> {
    251 
    252         #region Type-level Constructors
    253         #endregion
    254 
    255         #region Instance Constructors
    256         #endregion
    257 
    258         #region Type-level Fields
    259         #endregion
    260 
    261         #region Instance Fields
    262         #endregion
    263 
    264         #region Type-level Properties
    265         #endregion
    266 
    267         #region Instance Properties
    268         #endregion
    269 
    270         #region Type-level Functions
    271         #endregion
    272 
    273         #region Instance Functions
    274         [MethodImpl(MethodImplOptions.AggressiveInlining)]
    275         public abstract Ordering Cmp(in TSelf other);
    276         #endregion
    277 
    278         #region Operators
    279         #endregion
    280 
    281         #region Types
    282         #endregion
    283     }
    284     public static class Functions {
    285 
    286         #region Type-level Constructors
    287         #endregion
    288 
    289         #region Instance Constructors
    290         #endregion
    291 
    292         #region Type-level Fields
    293         #endregion
    294 
    295         #region Instance Fields
    296         #endregion
    297 
    298         #region Type-level Properties
    299         #endregion
    300 
    301         #region Instance Properties
    302         #endregion
    303 
    304         #region Type-level Functions
    305         public static TSelf Clamp<TSelf>(this TSelf self, TSelf min, TSelf max) where TSelf: notnull, IOrd<TSelf> {
    306 
    307             System.Diagnostics.Trace.Assert(min.Cmp(in max).Var != Ordering.Ord.Greater);
    308             return self.Cmp(in min).Var switch {
    309                 Ordering.Ord.Less => min,
    310                 Ordering.Ord.Equivalent => self,
    311                 _ => self.Cmp(in max).Var == Ordering.Ord.Greater ? max : self,
    312             };
    313         }
    314         public static TSelf Max<TSelf>(this TSelf self, TSelf other) where TSelf: notnull, IOrd<TSelf> => self.Cmp(in other).Var == Ordering.Ord.Greater ? self : other;
    315         public static T MaxBy<T>(T v0, T v1, FnIn<T, T, Ordering> f) where T: notnull => f(in v0, in v1).Var == Ordering.Ord.Greater ? v0 : v1;
    316         public static T MaxByKey<T, TKey>(T v0, T v1, FnIn<T, TKey> f) where T: notnull where TKey: notnull, IOrd<TKey> => f(in v0).Cmp(f(in v1)).Var == Ordering.Ord.Greater ? v0 : v1;
    317         public static TSelf Min<TSelf>(this TSelf self, TSelf other) where TSelf: notnull, IOrd<TSelf> => self.Cmp(in other).Var == Ordering.Ord.Greater ? other : self;
    318         public static T MinBy<T>(T v0, T v1, FnIn<T, T, Ordering> f) where T: notnull => f(in v0, in v1).Var == Ordering.Ord.Greater ? v1 : v0;
    319         public static T MinByKey<T, TKey>(T v0, T v1, FnIn<T, TKey> f) where T: notnull where TKey: notnull, IOrd<TKey> => f(in v0).Cmp(f(in v1)).Var == Ordering.Ord.Greater ? v1 : v0;
    320         #endregion
    321 
    322         #region Instance Functions
    323         #endregion
    324 
    325         #region Operators
    326         #endregion
    327 
    328         #region Types
    329         #endregion
    330     }
    331     #endregion
    332 
    333     #region Namespaces
    334     #endregion
    335 }
    336 #endregion