Skip to content

TensorPrimitives asymmetry between MultiplyAdd and MultiplyAddEstimate with trivial inputs #112989

@HobbsCode

Description

@HobbsCode

Description

I am seeing some wrong results from TensorPrimitives.MultiplyAddEstimate() when using 64-bit integral types.

Reproduction Steps

In the program below, various types are tested for symmetry of results between MultiplyAdd and MultiplyAddEstimate. On my machine, the 64-bit integral types are producing "4, 5, 6" for MultiplyAddEstimate. All results should be "11, 19, 27". Notably, the wrong results coincide with the values of the addends argument.

using System.Numerics.Tensors;

CompareMultiplyAddWithMultiplyAddEstimate<Half>();   
CompareMultiplyAddWithMultiplyAddEstimate<float>();  
CompareMultiplyAddWithMultiplyAddEstimate<double>(); 
CompareMultiplyAddWithMultiplyAddEstimate<NFloat>(); 
CompareMultiplyAddWithMultiplyAddEstimate<Complex>();
CompareMultiplyAddWithMultiplyAddEstimate<sbyte>();  
CompareMultiplyAddWithMultiplyAddEstimate<byte>();   
CompareMultiplyAddWithMultiplyAddEstimate<short>();  
CompareMultiplyAddWithMultiplyAddEstimate<ushort>(); 
CompareMultiplyAddWithMultiplyAddEstimate<int>();    
CompareMultiplyAddWithMultiplyAddEstimate<uint>();   
CompareMultiplyAddWithMultiplyAddEstimate<long>();   // problem
CompareMultiplyAddWithMultiplyAddEstimate<ulong>();  // problem
CompareMultiplyAddWithMultiplyAddEstimate<nint>();   // problem
CompareMultiplyAddWithMultiplyAddEstimate<nuint>();  // problem
CompareMultiplyAddWithMultiplyAddEstimate<Int128>(); 
CompareMultiplyAddWithMultiplyAddEstimate<UInt128>();

Console.WriteLine("\n\nPress any key...");
Console.ReadKey(true);
return;

static void CompareMultiplyAddWithMultiplyAddEstimate<TNum>() where TNum : INumberBase<TNum>
{
    TNum one = TNum.One;
    TNum two = one + one;
    TNum three = two + one;
    TNum four = three + one;
    TNum five = four + one;
    TNum six = five + one;
    TNum seven = six + one;

    ReadOnlySpan<TNum> initialValues = [one, two, three];
    ReadOnlySpan<TNum> addends = [four, five, six];
    TNum multiplier = seven;

    TNum[] resultsOfMultiplyAddEstimate = new TNum[3];
    TNum[] resultsOfMultiplyAdd = new TNum[3];

    TensorPrimitives.MultiplyAddEstimate(initialValues, multiplier, addends, resultsOfMultiplyAddEstimate);
    TensorPrimitives.MultiplyAdd(initialValues, multiplier, addends, resultsOfMultiplyAdd);

    Console.WriteLine($"Type: {typeof(TNum).Name}");

    Console.Write($"   MultiplyAddEstimate: "); 
    PrintValues(resultsOfMultiplyAddEstimate);
    Console.WriteLine();

    Console.Write($"           MultiplyAdd: ");
    PrintValues(resultsOfMultiplyAdd);
    Console.WriteLine();
    Console.WriteLine();
}

static void PrintValues<TNum>(TNum[] values)
{
    foreach (var item in values)
    {
        Console.Write($"{item}, ");
    }   
}

Expected behavior

All results should be "11, 19, 27".

Actual behavior

The 64-bit integral types are producing "4, 5, 6" for MultiplyAddEstimate.

Regression?

unknown

Known Workarounds

Use MultiplyAdd instead of MultiplyAddEstimate.

Configuration

Windows 11 (10.0.26100) x64
.NET 9.0.200

Other information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions