Skip to content

[API Proposal]: MultiplyAddEstimate #98053

Closed
@tannergooding

Description

@tannergooding

Summary

Today users have access to the direct operators (x * y) + z and the fused named method FusedMultiplyAdd(x, y, z). On some hardware using one over the other can provide significant perf advantages, however not all hardware provides acceleration for fma and further due to the difference in result (which may be 1 ULP difference for any standalone operation), it is not something that the runtime can freely optimize to use.

As such, it is proposed we provide an explicit Estimate function (matching the convention we've used for other operation where the result can differ across machines but the operation is not itself unsafe) that will implicitly pick the "best" of the two operations. Users who want a specific behavior can still get it by using the direct functions and users who want to opt-in can.

API Proposal

namespace System
{
    public partial struct Double
    {
        public static double MultiplyAddEstimate(double x, double y, double addend);
    }

    public partial struct Half
    {
        public static Half MultiplyAddEstimate(Half x, Half y, Half addend);
    }

    public partial struct Single
    {
        public static float MultiplyAddEstimate(float x, float y, float addend);
    }
}

namespace System.Numerics
{
    public partial interface IFloatingPointIeee754<TSelf>
    {
        static virtual TSelf MultiplyAddEstimate(TSelf x, TSelf y, TSelf addend);
    }

    public partial class Vector
    {
        static Vector<double> MultiplyAddEstimate(Vector<double> x, Vector<double> y, Vector<double> addend);
        static Vector<float> MultiplyAddEstimate(Vector<float> x, Vector<float> y, Vector<float> addend);
    }
}

namespace System.Numerics.Tensors
{
    public partial class TensorPrimitives
    {
        public static void MultiplyAddEstimate<T>(ReadOnlySpan<T> x, ReadOnlySpan<T> y, ReadOnlySpan<T> addend, Span<T> destination) where T : IFloatingPointIeee754<T>;
    }
}

namespace System.Runtime.InteropServices
{
    public partial struct NFloat
    {
        public static NFloat MultiplyAddEstimate(NFloat x, NFloat y, NFloat addend);
    }
}

namespace System.Runtime.Intrinsics
{
    public partial class Vector64
    {
        static Vector64<double> MultiplyAddEstimate(Vector64<double> x, Vector64<double> y, Vector64<double> addend);
        static Vector64<float> MultiplyAddEstimate(Vector64<float> x, Vector64<float> y, Vector64<float> addend);
    }

    public partial class Vector128
    {
        static Vector128<double> MultiplyAddEstimate(Vector128<double> x, Vector128<double> y, Vector128<double> addend);
        static Vector128<float> MultiplyAddEstimate(Vector128<float> x, Vector128<float> y, Vector128<float> addend);
    }

    public partial class Vector256
    {
        static Vector256<double> MultiplyAddEstimate(Vector256<double> x, Vector256<double> y, Vector256<double> addend);
        static Vector256<float> MultiplyAddEstimate(Vector256<float> x, Vector256<float> y, Vector256<float> addend);
    }

    public partial class Vector512
    {
        static Vector512<double> MultiplyAddEstimate(Vector512<double> x, Vector512<double> y, Vector512<double> addend);
        static Vector512<float> MultiplyAddEstimate(Vector512<float> x, Vector512<float> y, Vector512<float> addend);
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    api-approvedAPI was approved in API review, it can be implementedarea-System.Numericsin-prThere is an active PR which will close this issue when it is merged

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions