<p>Is there any feasible way of using generics to create a Math library that does not depend on the base type chosen to store data?</p>

<p>In other words, let's assume I want to write a Fraction class. The fraction can be represented by two ints or two doubles or whatnot. The important thing is that the basic four arithmetic operations are well defined. So, I would like to be able to write <code>Fraction&lt;int&gt; frac = new Fraction&lt;int&gt;(1,2)</code> and/or <code>Fraction&lt;double&gt; frac = new Fraction&lt;double&gt;(0.1, 1.0)</code>.</p>

<p>Unfortunately there is no interface representing the four basic operations (+,-,*,/). Has anybody found a workable, feasible way of implementing this?</p>

[{'answer_id': 63858, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 2, 'selected': False, 'text': '<p>First, your class should limit the generic parameter to primitives ( public class Fraction where T : struct, new() ).</p>\n\n<p>Second, you\'ll probably need to create <a href="http://msdn.microsoft.com/en-us/library/z5z9kes2(VS.71).aspx" rel="nofollow noreferrer">implicit cast overloads</a> so you can handle casting from one type to another without the compiler crying.  </p>\n\n<p>Third, you can overload the four basic operators as well to make the interface more flexible when combining fractions of different types.</p>\n\n<p>Lastly, you have to consider how you are handling arithmetic over and underflows.  A good library is going to be extremely explicit in how it handles overflows; otherwise you cannot trust the outcome of operations of different fraction types.</p>\n'}, {'answer_id': 63889, 'author': 'Community', 'author_id': -1, 'author_profile': 'https://Stackoverflow.com/users/-1', 'pm_score': 3, 'selected': False, 'text': '<p>I believe this answers your question:</p>\n<p><a href="http://www.codeproject.com/KB/cs/genericnumerics.aspx" rel="noreferrer">http://www.codeproject.com/KB/cs/genericnumerics.aspx</a></p>\n'}, {'answer_id': 64142, 'author': 'fryguybob', 'author_id': 4592, 'author_profile': 'https://Stackoverflow.com/users/4592', 'pm_score': 6, 'selected': True, 'text': '<p>Here is a way to abstract out the operators that is relatively painless.</p>\n\n<pre><code>    abstract class MathProvider&lt;T&gt;\n    {\n        public abstract T Divide(T a, T b);\n        public abstract T Multiply(T a, T b);\n        public abstract T Add(T a, T b);\n        public abstract T Negate(T a);\n        public virtual T Subtract(T a, T b)\n        {\n            return Add(a, Negate(b));\n        }\n    }\n\n    class DoubleMathProvider : MathProvider&lt;double&gt;\n    {\n        public override double Divide(double a, double b)\n        {\n            return a / b;\n        }\n\n        public override double Multiply(double a, double b)\n        {\n            return a * b;\n        }\n\n        public override double Add(double a, double b)\n        {\n            return a + b;\n        }\n\n        public override double Negate(double a)\n        {\n            return -a;\n        }\n    }\n\n    class IntMathProvider : MathProvider&lt;int&gt;\n    {\n        public override int Divide(int a, int b)\n        {\n            return a / b;\n        }\n\n        public override int Multiply(int a, int b)\n        {\n            return a * b;\n        }\n\n        public override int Add(int a, int b)\n        {\n            return a + b;\n        }\n\n        public override int Negate(int a)\n        {\n            return -a;\n        }\n    }\n\n    class Fraction&lt;T&gt;\n    {\n        static MathProvider&lt;T&gt; _math;\n        // Notice this is a type constructor.  It gets run the first time a\n        // variable of a specific type is declared for use.\n        // Having _math static reduces overhead.\n        static Fraction()\n        {\n            // This part of the code might be cleaner by once\n            // using reflection and finding all the implementors of\n            // MathProvider and assigning the instance by the one that\n            // matches T.\n            if (typeof(T) == typeof(double))\n                _math = new DoubleMathProvider() as MathProvider&lt;T&gt;;\n            else if (typeof(T) == typeof(int))\n                _math = new IntMathProvider() as MathProvider&lt;T&gt;;\n            // ... assign other options here.\n\n            if (_math == null)\n                throw new InvalidOperationException(\n                    "Type " + typeof(T).ToString() + " is not supported by Fraction.");\n        }\n\n        // Immutable impementations are better.\n        public T Numerator { get; private set; }\n        public T Denominator { get; private set; }\n\n        public Fraction(T numerator, T denominator)\n        {\n            // We would want this to be reduced to simpilest terms.\n            // For that we would need GCD, abs, and remainder operations\n            // defined for each math provider.\n            Numerator = numerator;\n            Denominator = denominator;\n        }\n\n        public static Fraction&lt;T&gt; operator +(Fraction&lt;T&gt; a, Fraction&lt;T&gt; b)\n        {\n            return new Fraction&lt;T&gt;(\n                _math.Add(\n                  _math.Multiply(a.Numerator, b.Denominator),\n                  _math.Multiply(b.Numerator, a.Denominator)),\n                _math.Multiply(a.Denominator, b.Denominator));\n        }\n\n        public static Fraction&lt;T&gt; operator -(Fraction&lt;T&gt; a, Fraction&lt;T&gt; b)\n        {\n            return new Fraction&lt;T&gt;(\n                _math.Subtract(\n                  _math.Multiply(a.Numerator, b.Denominator),\n                  _math.Multiply(b.Numerator, a.Denominator)),\n                _math.Multiply(a.Denominator, b.Denominator));\n        }\n\n        public static Fraction&lt;T&gt; operator /(Fraction&lt;T&gt; a, Fraction&lt;T&gt; b)\n        {\n            return new Fraction&lt;T&gt;(\n                _math.Multiply(a.Numerator, b.Denominator),\n                _math.Multiply(a.Denominator, b.Numerator));\n        }\n\n        // ... other operators would follow.\n    }\n</code></pre>\n\n<p>If you fail to implement a type that you use, you will get a failure at runtime instead of at compile time (that is bad).  The definition of the <code>MathProvider&lt;T&gt;</code> implementations is always going to be the same (also bad).  I would suggest that you just avoid doing this in C# and use F# or some other language better suited to this level of abstraction.</p>\n\n<p><strong>Edit:</strong> Fixed definitions of add and subtract for <code>Fraction&lt;T&gt;</code>.\nAnother interesting and simple thing to do is implement a MathProvider that operates on an abstract syntax tree.  This idea immediately points to doing things like automatic differentiation: <a href="http://conal.net/papers/beautiful-differentiation/" rel="noreferrer">http://conal.net/papers/beautiful-differentiation/</a></p>\n'}, {'answer_id': 4399400, 'author': 'John D. Cook', 'author_id': 25188, 'author_profile': 'https://Stackoverflow.com/users/25188', 'pm_score': 2, 'selected': False, 'text': "<p>Here's a subtle problem that comes with generic types.  Suppose an algorithm involves division, say Gaussian elimination to solve a system of equations.  If you pass in integers, you'll get a wrong answer because you'll carry out <em>integer</em> division.  But if you pass in double arguments that happen have integer values, you'll get the right answer.  </p>\n\n<p>The same thing happens with square roots, as in Cholesky factorization.  Factoring an integer matrix will go wrong, whereas factoring a matrix of doubles that happen to have integer values will be fine.</p>\n"}, {'answer_id': 65107700, 'author': 'Mike Marynowski', 'author_id': 612510, 'author_profile': 'https://Stackoverflow.com/users/612510', 'pm_score': 1, 'selected': False, 'text': '<p>The other approaches here will work, but they have a high performance impact over raw operators. I figured I would post this here for someone who needs the fastest, not the prettiest approach.</p>\n<p>If you want to do generic math without paying a performance penalty, then this is, unfortunately, the way to do it:</p>\n<pre class="lang-cs prettyprint-override"><code>[MethodImpl(MethodImplOptions.AggressiveInlining)]\npublic static T IncrementToMax(T value)\n{\n    if (typeof(T) == typeof(char))\n        return (char)(object)value! &lt; char.MaxValue ? (T)(object)(char)((char)(object)value + 1) : value;\n \n    if (typeof(T) == typeof(byte))\n        return (byte)(object)value! &lt; byte.MaxValue ? (T)(object)(byte)((byte)(object)value + 1) : value;\n\n    // ...rest of the types\n}\n</code></pre>\n<p>It looks horrific, I know, but using this method will produce code that runs as fast as possible. The JIT will optimize out all the casts and conditional branches.</p>\n<p>You can read the explanation and some additional important details here: <a href="http://www.singulink.com/codeindex/post/generic-math-at-raw-operator-speed" rel="nofollow noreferrer">http://www.singulink.com/codeindex/post/generic-math-at-raw-operator-speed</a></p>\n'}, {'answer_id': 74468046, 'author': 'Guru Stron', 'author_id': 2501279, 'author_profile': 'https://Stackoverflow.com/users/2501279', 'pm_score': 0, 'selected': False, 'text': '<p>.NET 7 introduces a new feature - generic math (read more <a href="https://devblogs.microsoft.com/dotnet/dotnet-7-generic-math/" rel="nofollow noreferrer">here</a> and <a href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/csharp-11#generic-math-support" rel="nofollow noreferrer">here</a>) which is based on addition of <a href="https://learn.microsoft.com/en-us/dotnet/csharp/whats-new/tutorials/static-virtual-interface-members#static-abstract-interface-methods" rel="nofollow noreferrer"><code>static abstract</code> interface methods</a>. This feature introduces a lot of interfaces which allow to generically abstract over number types and/or math operations:</p>\n<pre class="lang-cs prettyprint-override"><code>class Fraction&lt;T&gt; :\n    IAdditionOperators&lt;Fraction&lt;T&gt;, Fraction&lt;T&gt;, Fraction&lt;T&gt;&gt;,\n    ISubtractionOperators&lt;Fraction&lt;T&gt;, Fraction&lt;T&gt;, Fraction&lt;T&gt;&gt;,\n    IDivisionOperators&lt;Fraction&lt;T&gt;, Fraction&lt;T&gt;, Fraction&lt;T&gt;&gt;\n    where T : INumber&lt;T&gt;\n{\n    public T Numerator { get; }\n    public T Denominator { get; }\n\n    public Fraction(T numerator, T denominator)\n    {\n        Numerator = numerator;\n        Denominator = denominator;\n    }\n\n    public static Fraction&lt;T&gt; operator +(Fraction&lt;T&gt; left, Fraction&lt;T&gt; right) =&gt;\n        new(left.Numerator * right.Denominator + right.Numerator * left.Denominator,\n            left.Denominator * right.Denominator);\n\n    public static Fraction&lt;T&gt; operator -(Fraction&lt;T&gt; left, Fraction&lt;T&gt; right) =&gt;\n        new(left.Numerator * right.Denominator - right.Numerator * left.Denominator,\n            left.Denominator * right.Denominator);\n\n    public static Fraction&lt;T&gt; operator /(Fraction&lt;T&gt; left, Fraction&lt;T&gt; right) =&gt;\n        new(left.Numerator * right.Denominator, left.Denominator * right.Numerator);\n}\n</code></pre>\n'}]
['https://Stackoverflow.com/questions/63694', 'https://Stackoverflow.com', 'https://Stackoverflow.com/users/7028/']