Skip to content

Add generic Math methods for numeric types #18244

@Daniel-Svensson

Description

@Daniel-Svensson

Overview

With the addition of System.Numerics.Vector it suddenly became possible to write some generic algorithms that worked for most primitive numeric datatypes. However as soon as you need to work with single elements you are out of luck.

I propose a new generic API for scalar datatypes based upon the ideas behind System.Numerics.Vector.

Just as for vectors many of the genereic methods could be generated using .tt files such as in https://github.com/dotnet/corefx/blob/master/src/System.Numerics.Vectors/src/System/Numerics/Vector.tt

API

This is an example of how the API could look like.
All methods below are taken from the Vector class (https://msdn.microsoft.com/en-us/library/system.numerics.vector(v=vs.111).aspx).

Additional methods such as those found in System.Math (https://msdn.microsoft.com/en-us/library/system.math.aspx) would be interesting as well.
It could also be interesting to add non-generic methods such as float Round(float x, int digits); as well

All functionlity could be provided in a new nuget package in order to allow out of band releases without conflicts with the current Math type.

public static class Scalar
{
    public static T Abs<T>(T left, T right) where T : struct
    public static T Add<T>(T left, T right) where T : struct
    public static T AndNot<T>(T left, T right) where T : struct
    public static T BitwiseAnd<T>(T left, T right) where T : struct
    public static T BitwiseOr<T>(T left, T right) where T : struct
    public static T Divide<T>(T left, T right) where T : struct
    public static T Max<T>(T left, T right) where T : struct
    public static T Min<T>(T left, T right) where T : struct
    public static T Multiply<T>(T left, T right) where T : struct
    public static T Negate<T>(T left, T right) where T : struct
    public static T OnesComplement<T>(T left, T right) where T : struct
    public static T SquareRoot<T>(T left, T right) where T : struct
    public static T Subtract<T>(T left, T right) where T : struct
    public static T Xor<T>(T left, T right) where T : struct

    // Useful methods part of Vector<T>
    public static T Zero<T>()  where T : struct
    public static T One<T>()  where T : struct
}

The generic requirements for some methods might be changed a bit to allow additional types, such as using providing extra overload such as those suggested in https://github.com/dotnet/corefx/issues/1583.

Comparison and equality checking was not included since IComparable<> and IEquatable<> are implemented for the types already, but if it is considered a good idea to be as similar as possible to Vector then the following methods should also be considered

    public static bool GreaterThan<T>(T left, T right) where T : struct
    public static bool GreaterThanOrEqual<T>(T left, T right) where T : struct
    public static bool LessThan<T>(T left, T right) where T : struct
    public static bool LessThanOrEqual<T>(T left, T right) where T : struct

Types to support

I propose that all the primitive numeric types including decimal are supported (the same types as Vector<> support but with the addition of decimal). Invoking any method with any other type should result in an NotSupportedException()

  • Byte
  • SByte
  • UInt16
  • Int16
  • UInt32
  • Int32
  • UInt64
  • Int64
  • Single
  • Double
  • Decimal (The only difference from Vector)

Related issues:

I found a few issues regarding similar ideas

Metadata

Metadata

Assignees

No one assigned

    Labels

    api-needs-workAPI needs work before it is approved, it is NOT ready for implementationarea-System.Numerics

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions