Use new System.Numerics.Tensors library for DataFrame arithmetic operations (.net8) (#7179)

* Add dependency to the latest System.Numerics.Tensors library

* Initial implementation of NumericArithmetic for net8 and TensorPrimitives

* Use CompositeArithmetic

* Refcatoring, using .net8 features to improve performance and code readability

* Remove needless changes

* Fix build

* Update System.Numerics.Tensors lib
This commit is contained in:
Aleksei Smirnov 2024-07-24 22:11:33 +03:00 коммит произвёл GitHub
Родитель f51eaa2769
Коммит 0c2e82e7d4
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
9 изменённых файлов: 6412 добавлений и 5874 удалений

Просмотреть файл

@ -1,73 +1,19 @@

// Licensed to the .NET Foundation under one or more agreements.
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// Generated from Arithmetic.tt. Do not modify directly
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Collections.Generic;
using System.Text;
namespace Microsoft.Data.Analysis
{
////////////////////////////////////////
//Factory Class //
////////////////////////////////////////
internal static class Arithmetic
{
public static IArithmetic<T> GetArithmetic<T>()
where T : unmanaged
{
if (typeof(T) == typeof(bool))
return (IArithmetic<T>)new BoolArithmetic();
else if (typeof(T) == typeof(byte))
return (IArithmetic<T>)new ByteArithmetic();
else if (typeof(T) == typeof(char))
return (IArithmetic<T>)new CharArithmetic();
else if (typeof(T) == typeof(decimal))
return (IArithmetic<T>)new DecimalArithmetic();
else if (typeof(T) == typeof(double))
return (IArithmetic<T>)new DoubleArithmetic();
else if (typeof(T) == typeof(float))
return (IArithmetic<T>)new FloatArithmetic();
else if (typeof(T) == typeof(int))
return (IArithmetic<T>)new IntArithmetic();
else if (typeof(T) == typeof(long))
return (IArithmetic<T>)new LongArithmetic();
else if (typeof(T) == typeof(sbyte))
return (IArithmetic<T>)new SByteArithmetic();
else if (typeof(T) == typeof(short))
return (IArithmetic<T>)new ShortArithmetic();
else if (typeof(T) == typeof(uint))
return (IArithmetic<T>)new UIntArithmetic();
else if (typeof(T) == typeof(ulong))
return (IArithmetic<T>)new ULongArithmetic();
else if (typeof(T) == typeof(ushort))
return (IArithmetic<T>)new UShortArithmetic();
else if (typeof(T) == typeof(DateTime))
return (IArithmetic<T>)new DateTimeArithmetic();
throw new NotSupportedException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref Vector<T> AsVector<T>(ref T start, int offset)
where T : struct => ref Unsafe.As<T, Vector<T>>(ref Unsafe.Add(ref start, offset));
}
////////////////////////////////////////
//Base Class for Arithmetic //
////////////////////////////////////////
internal class Arithmetic<T> : IArithmetic<T>
where T : unmanaged
{
public static IArithmetic<T> Instance { get; } = Arithmetic.GetArithmetic<T>();
//Binary operations
#region Binary operations
public void HandleOperation(BinaryOperation operation, ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination)
{
@ -172,9 +118,9 @@ namespace Microsoft.Data.Analysis
throw new NotSupportedException();
}
#endregion
//Binary Int operations
#region Binary Int operations
public void HandleOperation(BinaryIntOperation operation, ReadOnlySpan<T> x, int y, Span<T> destination)
{
@ -188,9 +134,9 @@ namespace Microsoft.Data.Analysis
break;
}
}
#endregion
//Comparison operations
#region Comparison operations
public void HandleOperation(ComparisonOperation operation, ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<bool> destination)
{
@ -241,88 +187,54 @@ namespace Microsoft.Data.Analysis
break;
}
}
#endregion
//Protected methods
#region Protected methods
protected virtual void Add(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination) => throw new NotSupportedException();
protected virtual void Add(ReadOnlySpan<T> x, T y, Span<T> destination) => throw new NotSupportedException();
protected virtual void Add(T x, ReadOnlySpan<T> y, Span<T> destination) => throw new NotSupportedException();
protected virtual void Subtract(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination) => throw new NotSupportedException();
protected virtual void Subtract(ReadOnlySpan<T> x, T y, Span<T> destination) => throw new NotSupportedException();
protected virtual void Subtract(T x, ReadOnlySpan<T> y, Span<T> destination) => throw new NotSupportedException();
protected virtual void Multiply(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination) => throw new NotSupportedException();
protected virtual void Multiply(ReadOnlySpan<T> x, T y, Span<T> destination) => throw new NotSupportedException();
protected virtual void Multiply(T x, ReadOnlySpan<T> y, Span<T> destination) => throw new NotSupportedException();
protected virtual void Divide(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination) => throw new NotSupportedException();
protected virtual void Divide(ReadOnlySpan<T> x, T y, Span<T> destination) => throw new NotSupportedException();
protected virtual void Divide(T x, ReadOnlySpan<T> y, Span<T> destination) => throw new NotSupportedException();
protected virtual void Modulo(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination) => throw new NotSupportedException();
protected virtual void Modulo(ReadOnlySpan<T> x, T y, Span<T> destination) => throw new NotSupportedException();
protected virtual void Modulo(T x, ReadOnlySpan<T> y, Span<T> destination) => throw new NotSupportedException();
protected virtual T Divide(T x, T y) => throw new NotSupportedException();
protected virtual T Modulo(T x, T y) => throw new NotSupportedException();
protected virtual void And(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination) => throw new NotSupportedException();
protected virtual void And(ReadOnlySpan<T> x, T y, Span<T> destination) => throw new NotSupportedException();
protected virtual void And(T x, ReadOnlySpan<T> y, Span<T> destination) => throw new NotSupportedException();
protected virtual void Or(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination) => throw new NotSupportedException();
protected virtual void Or(ReadOnlySpan<T> x, T y, Span<T> destination) => throw new NotSupportedException();
protected virtual void Or(T x, ReadOnlySpan<T> y, Span<T> destination) => throw new NotSupportedException();
protected virtual void Xor(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination) => throw new NotSupportedException();
protected virtual void Xor(ReadOnlySpan<T> x, T y, Span<T> destination) => throw new NotSupportedException();
protected virtual void Xor(T x, ReadOnlySpan<T> y, Span<T> destination) => throw new NotSupportedException();
protected virtual void LeftShift(ReadOnlySpan<T> x, int y, Span<T> destination) => throw new NotSupportedException();
protected virtual void RightShift(ReadOnlySpan<T> x, int y, Span<T> destination) => throw new NotSupportedException();
protected virtual void ElementwiseEquals(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<bool> destination) => throw new NotSupportedException();
protected virtual void ElementwiseEquals(ReadOnlySpan<T> x, T y, Span<bool> destination) => throw new NotSupportedException();
protected virtual void ElementwiseNotEquals(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<bool> destination) => throw new NotSupportedException();
protected virtual void ElementwiseNotEquals(ReadOnlySpan<T> x, T y, Span<bool> destination) => throw new NotSupportedException();
protected virtual void ElementwiseGreaterThanOrEqual(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<bool> destination) => throw new NotSupportedException();
protected virtual void ElementwiseGreaterThanOrEqual(ReadOnlySpan<T> x, T y, Span<bool> destination) => throw new NotSupportedException();
protected virtual void ElementwiseLessThanOrEqual(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<bool> destination) => throw new NotSupportedException();
protected virtual void ElementwiseLessThanOrEqual(ReadOnlySpan<T> x, T y, Span<bool> destination) => throw new NotSupportedException();
protected virtual void ElementwiseGreaterThan(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<bool> destination) => throw new NotSupportedException();
protected virtual void ElementwiseGreaterThan(ReadOnlySpan<T> x, T y, Span<bool> destination) => throw new NotSupportedException();
protected virtual void ElementwiseLessThan(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<bool> destination) => throw new NotSupportedException();
protected virtual void ElementwiseLessThan(ReadOnlySpan<T> x, T y, Span<bool> destination) => throw new NotSupportedException();
protected virtual T Divide(T x, T y) => throw new NotSupportedException();
protected virtual T Modulo(T x, T y) => throw new NotSupportedException();
#endregion
}
}

Просмотреть файл

@ -0,0 +1,736 @@

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#if NET8_0_OR_GREATER
using System;
using System.Numerics;
using System.Numerics.Tensors;
namespace Microsoft.Data.Analysis
{
internal static partial class Arithmetic
{
#region Nested classes for Operations
private interface IBitwiseOperations<T>
where T : unmanaged
{
static abstract void And(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination);
static abstract void And(ReadOnlySpan<T> x, T y, Span<T> destination);
static abstract void And(T x, ReadOnlySpan<T> y, Span<T> destination);
static abstract void Or(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination);
static abstract void Or(ReadOnlySpan<T> x, T y, Span<T> destination);
static abstract void Or(T x, ReadOnlySpan<T> y, Span<T> destination);
static abstract void Xor(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination);
static abstract void Xor(ReadOnlySpan<T> x, T y, Span<T> destination);
static abstract void Xor(T x, ReadOnlySpan<T> y, Span<T> destination);
}
private interface IShiftOperations<T>
where T : unmanaged
{
static abstract void LeftShift(ReadOnlySpan<T> x, int shiftAmount, Span<T> destination);
static abstract void RightShift(ReadOnlySpan<T> x, int shiftAmount, Span<T> destination);
}
private interface INumericOperations<T>
where T : unmanaged
{
static abstract void Add(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination);
static abstract void Add(ReadOnlySpan<T> x, T y, Span<T> destination);
static abstract void Add(T x, ReadOnlySpan<T> y, Span<T> destination);
static abstract void Subtract(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination);
static abstract void Subtract(ReadOnlySpan<T> x, T y, Span<T> destination);
static abstract void Subtract(T x, ReadOnlySpan<T> y, Span<T> destination);
static abstract void Multiply(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination);
static abstract void Multiply(ReadOnlySpan<T> x, T y, Span<T> destination);
static abstract void Multiply(T x, ReadOnlySpan<T> y, Span<T> destination);
static abstract void Divide(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination);
static abstract void Divide(ReadOnlySpan<T> x, T y, Span<T> destination);
static abstract void Divide(T x, ReadOnlySpan<T> y, Span<T> destination);
static abstract T Divide(T x, T y);
static abstract void Modulo(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination);
static abstract void Modulo(ReadOnlySpan<T> x, T y, Span<T> destination);
static abstract void Modulo(T x, ReadOnlySpan<T> y, Span<T> destination);
static abstract T Modulo(T x, T y);
static abstract void ElementwiseEquals(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<bool> destination);
static abstract void ElementwiseEquals(ReadOnlySpan<T> x, T y, Span<bool> destination);
static abstract void ElementwiseNotEquals(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<bool> destination);
static abstract void ElementwiseNotEquals(ReadOnlySpan<T> x, T y, Span<bool> destination);
static abstract void ElementwiseGreaterThanOrEqual(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<bool> destination);
static abstract void ElementwiseGreaterThanOrEqual(ReadOnlySpan<T> x, T y, Span<bool> destination);
static abstract void ElementwiseLessThanOrEqual(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<bool> destination);
static abstract void ElementwiseLessThanOrEqual(ReadOnlySpan<T> x, T y, Span<bool> destination);
static abstract void ElementwiseGreaterThan(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<bool> destination);
static abstract void ElementwiseGreaterThan(ReadOnlySpan<T> x, T y, Span<bool> destination);
static abstract void ElementwiseLessThan(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<bool> destination);
static abstract void ElementwiseLessThan(ReadOnlySpan<T> x, T y, Span<bool> destination);
}
private readonly struct BitwiseOperations<T> : IBitwiseOperations<T>
where T : unmanaged, IBitwiseOperators<T, T, T>
{
public static void And(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination) => TensorPrimitives.BitwiseAnd(x, y, destination);
public static void And(ReadOnlySpan<T> x, T y, Span<T> destination) => TensorPrimitives.BitwiseAnd(x, y, destination);
public static void And(T x, ReadOnlySpan<T> y, Span<T> destination) => TensorPrimitives.BitwiseAnd(y, x, destination);
public static void Or(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination) => TensorPrimitives.BitwiseOr(x, y, destination);
public static void Or(ReadOnlySpan<T> x, T y, Span<T> destination) => TensorPrimitives.BitwiseOr(x, y, destination);
public static void Or(T x, ReadOnlySpan<T> y, Span<T> destination) => TensorPrimitives.BitwiseOr(y, x, destination);
public static void Xor(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination) => TensorPrimitives.Xor(x, y, destination);
public static void Xor(ReadOnlySpan<T> x, T y, Span<T> destination) => TensorPrimitives.Xor(x, y, destination);
public static void Xor(T x, ReadOnlySpan<T> y, Span<T> destination) => TensorPrimitives.Xor(y, x, destination);
}
private readonly struct ShiftOperations<T> : IShiftOperations<T>
where T : unmanaged, IShiftOperators<T, int, T>
{
public static void LeftShift(ReadOnlySpan<T> x, int shiftAmount, Span<T> destination) => TensorPrimitives.ShiftLeft(x, shiftAmount, destination);
public static void RightShift(ReadOnlySpan<T> x, int shiftAmount, Span<T> destination) => TensorPrimitives.ShiftRightArithmetic(x, shiftAmount, destination);
}
private readonly struct NumericOperations<T> : INumericOperations<T>
where T : unmanaged, INumber<T>
{
public static void Add(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination) => TensorPrimitives.Add(x, y, destination);
public static void Add(ReadOnlySpan<T> x, T y, Span<T> destination) => TensorPrimitives.Add(x, y, destination);
public static void Add(T x, ReadOnlySpan<T> y, Span<T> destination) => TensorPrimitives.Add(y, x, destination);
public static void Subtract(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination) => TensorPrimitives.Subtract(x, y, destination);
public static void Subtract(ReadOnlySpan<T> x, T y, Span<T> destination) => TensorPrimitives.Subtract(x, y, destination);
public static void Subtract(T x, ReadOnlySpan<T> y, Span<T> destination) => TensorPrimitives.Subtract(x, y, destination);
public static void Multiply(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination) => TensorPrimitives.Multiply(x, y, destination);
public static void Multiply(ReadOnlySpan<T> x, T y, Span<T> destination) => TensorPrimitives.Multiply(x, y, destination);
public static void Multiply(T x, ReadOnlySpan<T> y, Span<T> destination) => TensorPrimitives.Multiply(y, x, destination);
public static void Divide(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination) => TensorPrimitives.Divide(x, y, destination);
public static void Divide(ReadOnlySpan<T> x, T y, Span<T> destination) => TensorPrimitives.Divide(x, y, destination);
public static void Divide(T x, ReadOnlySpan<T> y, Span<T> destination) => TensorPrimitives.Divide(x, y, destination);
public static T Divide(T x, T y) => x / y;
public static void Modulo(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = x[i] % y[i];
}
}
public static void Modulo(ReadOnlySpan<T> x, T y, Span<T> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = x[i] % y;
}
}
public static void Modulo(T x, ReadOnlySpan<T> y, Span<T> destination)
{
for (var i = 0; i < y.Length; i++)
{
destination[i] = x % y[i];
}
}
public static T Modulo(T x, T y) => x % y;
public static void ElementwiseEquals(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] == y[i]);
}
}
public static void ElementwiseEquals(ReadOnlySpan<T> x, T y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] == y);
}
}
public static void ElementwiseNotEquals(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] != y[i]);
}
}
public static void ElementwiseNotEquals(ReadOnlySpan<T> x, T y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] != y);
}
}
public static void ElementwiseGreaterThanOrEqual(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] >= y[i]);
}
}
public static void ElementwiseGreaterThanOrEqual(ReadOnlySpan<T> x, T y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] >= y);
}
}
public static void ElementwiseLessThanOrEqual(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] <= y[i]);
}
}
public static void ElementwiseLessThanOrEqual(ReadOnlySpan<T> x, T y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] <= y);
}
}
public static void ElementwiseGreaterThan(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] > y[i]);
}
}
public static void ElementwiseGreaterThan(ReadOnlySpan<T> x, T y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] > y);
}
}
public static void ElementwiseLessThan(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] < y[i]);
}
}
public static void ElementwiseLessThan(ReadOnlySpan<T> x, T y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] < y);
}
}
}
#endregion
#region Nested classes for Arithmetics
private class CompositeArithmetic<T, TNumericOperations> : IArithmetic<T>
where T : unmanaged
where TNumericOperations : struct, INumericOperations<T>
{
public virtual void HandleOperation(BinaryOperation operation, ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination)
{
switch (operation)
{
case BinaryOperation.Add:
TNumericOperations.Add(x, y, destination);
break;
case BinaryOperation.Subtract:
TNumericOperations.Subtract(x, y, destination);
break;
case BinaryOperation.Multiply:
TNumericOperations.Multiply(x, y, destination);
break;
case BinaryOperation.Divide:
TNumericOperations.Divide(x, y, destination);
break;
case BinaryOperation.Modulo:
TNumericOperations.Modulo(x, y, destination);
break;
default:
throw new NotSupportedException();
}
}
public virtual void HandleOperation(BinaryOperation operation, ReadOnlySpan<T> x, T y, Span<T> destination)
{
switch (operation)
{
case BinaryOperation.Add:
TNumericOperations.Add(x, y, destination);
break;
case BinaryOperation.Subtract:
TNumericOperations.Subtract(x, y, destination);
break;
case BinaryOperation.Multiply:
TNumericOperations.Multiply(x, y, destination);
break;
case BinaryOperation.Divide:
TNumericOperations.Divide(x, y, destination);
break;
case BinaryOperation.Modulo:
TNumericOperations.Modulo(x, y, destination);
break;
default:
throw new NotSupportedException();
}
}
public virtual void HandleOperation(BinaryOperation operation, T x, ReadOnlySpan<T> y, Span<T> destination)
{
switch (operation)
{
case BinaryOperation.Add:
TNumericOperations.Add(x, y, destination);
break;
case BinaryOperation.Subtract:
TNumericOperations.Subtract(x, y, destination);
break;
case BinaryOperation.Multiply:
TNumericOperations.Multiply(x, y, destination);
break;
case BinaryOperation.Divide:
TNumericOperations.Divide(x, y, destination);
break;
case BinaryOperation.Modulo:
TNumericOperations.Modulo(x, y, destination);
break;
default:
throw new NotSupportedException();
}
}
public T HandleOperation(BinaryOperation operation, T x, T y)
{
if (operation == BinaryOperation.Divide)
return TNumericOperations.Divide(x, y);
if (operation == BinaryOperation.Modulo)
return TNumericOperations.Modulo(x, y);
throw new NotSupportedException();
}
public virtual void HandleOperation(BinaryIntOperation operation, ReadOnlySpan<T> x, int y, Span<T> destination)
{
throw new NotSupportedException();
}
public void HandleOperation(ComparisonOperation operation, ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<bool> destination)
{
switch (operation)
{
case ComparisonOperation.ElementwiseEquals:
TNumericOperations.ElementwiseEquals(x, y, destination);
break;
case ComparisonOperation.ElementwiseNotEquals:
TNumericOperations.ElementwiseNotEquals(x, y, destination);
break;
case ComparisonOperation.ElementwiseGreaterThanOrEqual:
TNumericOperations.ElementwiseGreaterThanOrEqual(x, y, destination);
break;
case ComparisonOperation.ElementwiseLessThanOrEqual:
TNumericOperations.ElementwiseLessThanOrEqual(x, y, destination);
break;
case ComparisonOperation.ElementwiseGreaterThan:
TNumericOperations.ElementwiseGreaterThan(x, y, destination);
break;
case ComparisonOperation.ElementwiseLessThan:
TNumericOperations.ElementwiseLessThan(x, y, destination);
break;
default:
throw new NotSupportedException();
}
}
public void HandleOperation(ComparisonOperation operation, ReadOnlySpan<T> x, T y, Span<bool> destination)
{
switch (operation)
{
case ComparisonOperation.ElementwiseEquals:
TNumericOperations.ElementwiseEquals(x, y, destination);
break;
case ComparisonOperation.ElementwiseNotEquals:
TNumericOperations.ElementwiseNotEquals(x, y, destination);
break;
case ComparisonOperation.ElementwiseGreaterThanOrEqual:
TNumericOperations.ElementwiseGreaterThanOrEqual(x, y, destination);
break;
case ComparisonOperation.ElementwiseLessThanOrEqual:
TNumericOperations.ElementwiseLessThanOrEqual(x, y, destination);
break;
case ComparisonOperation.ElementwiseGreaterThan:
TNumericOperations.ElementwiseGreaterThan(x, y, destination);
break;
case ComparisonOperation.ElementwiseLessThan:
TNumericOperations.ElementwiseLessThan(x, y, destination);
break;
default:
throw new NotSupportedException();
}
}
}
private class CompositeArithmetic<T, TNumericOperations, TBitwiseOperations> : CompositeArithmetic<T, TNumericOperations>, IArithmetic<T>
where T : unmanaged
where TNumericOperations : struct, INumericOperations<T>
where TBitwiseOperations : struct, IBitwiseOperations<T>
{
public override void HandleOperation(BinaryOperation operation, ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination)
{
switch (operation)
{
case BinaryOperation.And:
TBitwiseOperations.And(x, y, destination);
return;
case BinaryOperation.Or:
TBitwiseOperations.Or(x, y, destination);
return;
case BinaryOperation.Xor:
TBitwiseOperations.Xor(x, y, destination);
return;
}
base.HandleOperation(operation, x, y, destination);
}
public override void HandleOperation(BinaryOperation operation, ReadOnlySpan<T> x, T y, Span<T> destination)
{
switch (operation)
{
case BinaryOperation.And:
TBitwiseOperations.And(x, y, destination);
return;
case BinaryOperation.Or:
TBitwiseOperations.Or(x, y, destination);
return;
case BinaryOperation.Xor:
TBitwiseOperations.Xor(x, y, destination);
return;
}
base.HandleOperation(operation, x, y, destination);
}
public override void HandleOperation(BinaryOperation operation, T x, ReadOnlySpan<T> y, Span<T> destination)
{
switch (operation)
{
case BinaryOperation.And:
TBitwiseOperations.And(x, y, destination);
return;
case BinaryOperation.Or:
TBitwiseOperations.Or(x, y, destination);
return;
case BinaryOperation.Xor:
TBitwiseOperations.Xor(x, y, destination);
return;
}
base.HandleOperation(operation, x, y, destination);
}
}
private class CompositeArithmetic<T, TNumericOperations, TBitwiseOperations, TShiftOperations> : CompositeArithmetic<T, TNumericOperations, TBitwiseOperations>, IArithmetic<T>
where T : unmanaged
where TNumericOperations : struct, INumericOperations<T>
where TBitwiseOperations : struct, IBitwiseOperations<T>
where TShiftOperations : struct, IShiftOperations<T>
{
public override void HandleOperation(BinaryIntOperation operation, ReadOnlySpan<T> x, int y, Span<T> destination)
{
switch (operation)
{
case BinaryIntOperation.LeftShift:
TShiftOperations.LeftShift(x, y, destination);
break;
case BinaryIntOperation.RightShift:
TShiftOperations.RightShift(x, y, destination);
break;
default:
throw new NotSupportedException();
}
}
}
//Special case
internal class DateTimeArithmetic : Arithmetic<DateTime>
{
protected override void ElementwiseEquals(ReadOnlySpan<DateTime> x, ReadOnlySpan<DateTime> y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] == y[i]);
}
}
protected override void ElementwiseEquals(ReadOnlySpan<DateTime> x, DateTime y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] == y);
}
}
protected override void ElementwiseNotEquals(ReadOnlySpan<DateTime> x, ReadOnlySpan<DateTime> y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] != y[i]);
}
}
protected override void ElementwiseNotEquals(ReadOnlySpan<DateTime> x, DateTime y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] != y);
}
}
protected override void ElementwiseGreaterThanOrEqual(ReadOnlySpan<DateTime> x, ReadOnlySpan<DateTime> y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] >= y[i]);
}
}
protected override void ElementwiseGreaterThanOrEqual(ReadOnlySpan<DateTime> x, DateTime y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] == y);
}
}
protected override void ElementwiseLessThanOrEqual(ReadOnlySpan<DateTime> x, ReadOnlySpan<DateTime> y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] <= y[i]);
}
}
protected override void ElementwiseLessThanOrEqual(ReadOnlySpan<DateTime> x, DateTime y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] <= y);
}
}
protected override void ElementwiseGreaterThan(ReadOnlySpan<DateTime> x, ReadOnlySpan<DateTime> y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] > y[i]);
}
}
protected override void ElementwiseGreaterThan(ReadOnlySpan<DateTime> x, DateTime y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] > y);
}
}
protected override void ElementwiseLessThan(ReadOnlySpan<DateTime> x, ReadOnlySpan<DateTime> y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] < y[i]);
}
}
protected override void ElementwiseLessThan(ReadOnlySpan<DateTime> x, DateTime y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] < y);
}
}
}
internal class BoolArithmetic : Arithmetic<bool>
{
protected override void And(ReadOnlySpan<bool> x, ReadOnlySpan<bool> y, Span<bool> destination)
{
int i = 0;
while (i < x.Length)
{
destination[i] = (bool)(x[i] & y[i]);
i++;
}
}
protected override void And(ReadOnlySpan<bool> x, bool y, Span<bool> destination)
{
int i = 0;
while (i < x.Length)
{
destination[i] = (bool)(x[i] & y);
i++;
}
}
protected override void And(bool x, ReadOnlySpan<bool> y, Span<bool> destination)
{
int i = 0;
while (i < y.Length)
{
destination[i] = (bool)(x & y[i]);
i++;
}
}
protected override void Or(ReadOnlySpan<bool> x, ReadOnlySpan<bool> y, Span<bool> destination)
{
int i = 0;
while (i < x.Length)
{
destination[i] = (bool)(x[i] | y[i]);
i++;
}
}
protected override void Or(ReadOnlySpan<bool> x, bool y, Span<bool> destination)
{
int i = 0;
while (i < x.Length)
{
destination[i] = (bool)(x[i] | y);
i++;
}
}
protected override void Or(bool x, ReadOnlySpan<bool> y, Span<bool> destination)
{
int i = 0;
while (i < y.Length)
{
destination[i] = (bool)(x | y[i]);
i++;
}
}
protected override void Xor(ReadOnlySpan<bool> x, ReadOnlySpan<bool> y, Span<bool> destination)
{
int i = 0;
while (i < x.Length)
{
destination[i] = (bool)(x[i] ^ y[i]);
i++;
}
}
protected override void Xor(ReadOnlySpan<bool> x, bool y, Span<bool> destination)
{
int i = 0;
while (i < x.Length)
{
destination[i] = (bool)(x[i] ^ y);
i++;
}
}
protected override void Xor(bool x, ReadOnlySpan<bool> y, Span<bool> destination)
{
int i = 0;
while (i < y.Length)
{
destination[i] = (bool)(x ^ y[i]);
i++;
}
}
protected override void ElementwiseEquals(ReadOnlySpan<bool> x, ReadOnlySpan<bool> y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] == y[i]);
}
}
protected override void ElementwiseEquals(ReadOnlySpan<bool> x, bool y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] == y);
}
}
protected override void ElementwiseNotEquals(ReadOnlySpan<bool> x, ReadOnlySpan<bool> y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] != y[i]);
}
}
protected override void ElementwiseNotEquals(ReadOnlySpan<bool> x, bool y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] != y);
}
}
}
#endregion
internal static IArithmetic<T> GetArithmetic<T>()
where T : unmanaged
{
if (typeof(T) == typeof(double))
return (IArithmetic<T>)new CompositeArithmetic<double, NumericOperations<double>, BitwiseOperations<double>>();
if (typeof(T) == typeof(float))
return (IArithmetic<T>)new CompositeArithmetic<float, NumericOperations<float>, BitwiseOperations<float>>();
if (typeof(T) == typeof(int))
return (IArithmetic<T>)new CompositeArithmetic<int, NumericOperations<int>, BitwiseOperations<int>, ShiftOperations<int>>();
if (typeof(T) == typeof(long))
return (IArithmetic<T>)new CompositeArithmetic<long, NumericOperations<long>, BitwiseOperations<long>, ShiftOperations<long>>();
if (typeof(T) == typeof(sbyte))
return (IArithmetic<T>)new CompositeArithmetic<sbyte, NumericOperations<sbyte>, BitwiseOperations<sbyte>, ShiftOperations<sbyte>>();
if (typeof(T) == typeof(short))
return (IArithmetic<T>)new CompositeArithmetic<short, NumericOperations<short>, BitwiseOperations<short>, ShiftOperations<short>>();
if (typeof(T) == typeof(uint))
return (IArithmetic<T>)new CompositeArithmetic<uint, NumericOperations<uint>, BitwiseOperations<uint>, ShiftOperations<uint>>();
if (typeof(T) == typeof(ulong))
return (IArithmetic<T>)new CompositeArithmetic<ulong, NumericOperations<ulong>, BitwiseOperations<ulong>, ShiftOperations<ulong>>();
if (typeof(T) == typeof(ushort))
return (IArithmetic<T>)new CompositeArithmetic<ushort, NumericOperations<ushort>, BitwiseOperations<ushort>, ShiftOperations<ushort>>();
if (typeof(T) == typeof(byte))
return (IArithmetic<T>)new CompositeArithmetic<byte, NumericOperations<byte>, BitwiseOperations<byte>, ShiftOperations<byte>>();
if (typeof(T) == typeof(char))
return (IArithmetic<T>)new CompositeArithmetic<char, NumericOperations<char>, BitwiseOperations<char>, ShiftOperations<char>>();
if (typeof(T) == typeof(decimal))
return (IArithmetic<T>)new CompositeArithmetic<decimal, NumericOperations<decimal>>();
if (typeof(T) == typeof(DateTime))
return (IArithmetic<T>)new DateTimeArithmetic();
if (typeof(T) == typeof(bool))
return (IArithmetic<T>)new BoolArithmetic();
throw new NotSupportedException();
}
}
}
#endif

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -0,0 +1,199 @@
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<#@ include file="$(ProjectDir)\ColumnArithmeticTemplate.ttinclude" #>
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// Generated from Arithmetic.tt. Do not modify directly
#if !NET8_0_OR_GREATER
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Microsoft.Data.Analysis
{
////////////////////////////////////////
//Factory Class //
////////////////////////////////////////
internal static partial class Arithmetic
{
#region Nested classes for Arithmetics
<# foreach (TypeConfiguration type in typeConfiguration) { #>
internal class <#=type.ClassPrefix#>Arithmetic : Arithmetic<<#=type.TypeName#>>
{
<# foreach (MethodConfiguration method in methodConfiguration) { #>
<# if (!((method.IsNumeric && !type.SupportsNumeric) || (method.IsBitwise && !type.SupportsBitwise) || (type.UnsupportedMethods.Contains(method.MethodName))) && method.Operator != null) { #>
<# if (method.MethodType == MethodType.Comparison) { #>
protected override void <#=method.MethodName#>(ReadOnlySpan<<#=type.TypeName#>> x, ReadOnlySpan<<#=type.TypeName#>> y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] <#= method.Operator #> y[i]);
}
}
<# } else if (method.MethodType == MethodType.ComparisonScalar) {#>
protected override void <#=method.MethodName#>(ReadOnlySpan<<#=type.TypeName#>> x, <#=type.TypeName#> y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] <#= method.Operator #> y);
}
}
<# } else if (method.MethodType == MethodType.Binary) { #>
<# if (method.MethodName == "Divide" || method.MethodName == "Modulo") { #>
protected override <#=type.TypeName#> <#=method.MethodName#>(<#=type.TypeName#> x, <#=type.TypeName#> y)
{
return (<#=type.TypeName#>)(x <#= method.Operator #> y);
}
<# } #>
protected override void <#=method.MethodName#>(ReadOnlySpan<<#=type.TypeName#>> x, ReadOnlySpan<<#=type.TypeName#>> y, Span<<#=type.TypeName#>> destination)
{
int i = 0;
<# if (method.SupportsVectorization && type.SupportsVectorization) { #>
if (Vector.IsHardwareAccelerated)
{
ref <#=type.TypeName#> xRef = ref MemoryMarshal.GetReference(x);
ref <#=type.TypeName#> yRef = ref MemoryMarshal.GetReference(y);
ref <#=type.TypeName#> dRef = ref MemoryMarshal.GetReference(destination);
var vectorSize = Vector<<#=type.TypeName#>>.Count;
var oneVectorFromEnd = x.Length - vectorSize;
if (oneVectorFromEnd >= 0)
{
// Loop handling one vector at a time.
do
{
Arithmetic.AsVector(ref dRef, i) = (Arithmetic.AsVector(ref xRef, i) <#= method.Operator #> Arithmetic.AsVector(ref yRef, i));
i += vectorSize;
}
while (i <= oneVectorFromEnd);
}
}
<# } #>
while (i < x.Length)
{
destination[i] = (<#=type.TypeName#>)(x[i] <#= method.Operator #> y[i]);
i++;
}
}
<# } #>
<# else if (method.MethodType == MethodType.BinaryScalar) { #>
protected override void <#=method.MethodName#>(ReadOnlySpan<<#=type.TypeName#>> x, <#=type.TypeName#> y, Span<<#=type.TypeName#>> destination)
{
int i = 0;
<# if (method.SupportsVectorization && type.SupportsVectorization) { #>
if (Vector.IsHardwareAccelerated)
{
ref <#=type.TypeName#> xRef = ref MemoryMarshal.GetReference(x);
ref <#=type.TypeName#> dRef = ref MemoryMarshal.GetReference(destination);
var vectorSize = Vector<<#=type.TypeName#>>.Count;
var oneVectorFromEnd = x.Length - vectorSize;
if (oneVectorFromEnd >= 0)
{
Vector<<#=type.TypeName#>> yVec = new(y);
// Loop handling one vector at a time.
do
{
Arithmetic.AsVector(ref dRef, i) = (Arithmetic.AsVector(ref xRef, i) <#= method.Operator #> yVec);
i += vectorSize;
}
while (i <= oneVectorFromEnd);
}
}
<# } #>
while (i < x.Length)
{
destination[i] = (<#=type.TypeName#>)(x[i] <#= method.Operator #> y);
i++;
}
}
protected override void <#=method.MethodName#>(<#=type.TypeName#> x, ReadOnlySpan<<#=type.TypeName#>> y, Span<<#=type.TypeName#>> destination)
{
int i = 0;
<# if (method.SupportsVectorization && type.SupportsVectorization) { #>
if (Vector.IsHardwareAccelerated)
{
ref <#=type.TypeName#> yRef = ref MemoryMarshal.GetReference(y);
ref <#=type.TypeName#> dRef = ref MemoryMarshal.GetReference(destination);
var vectorSize = Vector<<#=type.TypeName#>>.Count;
var oneVectorFromEnd = y.Length - vectorSize;
if (oneVectorFromEnd >= 0)
{
Vector<<#=type.TypeName#>> xVec = new(x);
// Loop handling one vector at a time.
do
{
Arithmetic.AsVector(ref dRef, i) = (xVec <#= method.Operator #> Arithmetic.AsVector(ref yRef, i));
i += vectorSize;
}
while (i <= oneVectorFromEnd);
}
}
<# } #>
while (i < y.Length)
{
destination[i] = (<#=type.TypeName#>)(x <#= method.Operator #> y[i]);
i++;
}
}
<# } #>
<# else if (method.MethodType == MethodType.BinaryInt) { #>
protected override void <#=method.MethodName#>(ReadOnlySpan<<#=type.TypeName#>> x, int y, Span<<#=type.TypeName#>> destination)
{
for (var i = 0; i < x.Length; i++)
destination[i] = (<#=type.TypeName#>)(x[i] <#= method.Operator #> y);
}
<# } #>
<# } #>
<# } #>
}
<# } #>
#endregion
internal static IArithmetic<T> GetArithmetic<T>()
where T : unmanaged
{
<# foreach (TypeConfiguration type in typeConfiguration) { #>
<#=GenerateIfStatementHeader(type)#>
return (IArithmetic<T>)new <#=type.ClassPrefix#>Arithmetic();
<# } #>
throw new NotSupportedException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref Vector<T> AsVector<T>(ref T start, int offset)
where T : struct => ref Unsafe.As<T, Vector<T>>(ref Unsafe.Add(ref start, offset));
}
}
#endif

Просмотреть файл

@ -1,185 +0,0 @@
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<#@ include file="$(ProjectDir)\ColumnArithmeticTemplate.ttinclude" #>
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// Generated from Arithmetic.tt. Do not modify directly
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
namespace Microsoft.Data.Analysis
{
////////////////////////////////////////
//Factory Class //
////////////////////////////////////////
internal static class Arithmetic
{
public static IArithmetic<T> GetArithmetic<T>()
where T : unmanaged
{
<# foreach (TypeConfiguration type in typeConfiguration) { #>
<#=GenerateIfStatementHeader(type)#>
return (IArithmetic<T>)new <#=type.ClassPrefix#>Arithmetic();
<# } #>
throw new NotSupportedException();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ref Vector<T> AsVector<T>(ref T start, int offset)
where T : struct => ref Unsafe.As<T, Vector<T>>(ref Unsafe.Add(ref start, offset));
}
////////////////////////////////////////
//Base Class for Arithmetic //
////////////////////////////////////////
internal class Arithmetic<T> : IArithmetic<T>
where T : unmanaged
{
public static IArithmetic<T> Instance { get; } = Arithmetic.GetArithmetic<T>();
//Binary operations
public void HandleOperation(BinaryOperation operation, ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination)
{
switch (operation)
{
<# foreach (MethodConfiguration method in methodConfiguration) { #>
<# if (method.MethodType == MethodType.Binary) { #>
case BinaryOperation.<#=method.MethodName#>:
<#=method.MethodName#>(x, y, destination);
break;
<# } #>
<# } #>
}
}
public void HandleOperation(BinaryOperation operation, ReadOnlySpan<T> x, T y, Span<T> destination)
{
switch (operation)
{
<# foreach (MethodConfiguration method in methodConfiguration) { #>
<# if (method.MethodType == MethodType.BinaryScalar) { #>
case BinaryOperation.<#=method.MethodName#>:
<#=method.MethodName#>(x, y, destination);
break;
<# } #>
<# } #>
}
}
public void HandleOperation(BinaryOperation operation, T x, ReadOnlySpan<T> y, Span<T> destination)
{
switch (operation)
{
<# foreach (MethodConfiguration method in methodConfiguration) { #>
<# if (method.MethodType == MethodType.BinaryScalar) { #>
case BinaryOperation.<#=method.MethodName#>:
<#=method.MethodName#>(x, y, destination);
break;
<# } #>
<# } #>
}
}
public T HandleOperation(BinaryOperation operation, T x, T y)
{
if (operation == BinaryOperation.Divide)
return Divide(x, y);
if (operation == BinaryOperation.Modulo)
return Modulo(x, y);
throw new NotSupportedException();
}
//Binary Int operations
public void HandleOperation(BinaryIntOperation operation, ReadOnlySpan<T> x, int y, Span<T> destination)
{
switch (operation)
{
<# foreach (MethodConfiguration method in methodConfiguration) { #>
<# if (method.MethodType == MethodType.BinaryInt) { #>
case BinaryIntOperation.<#=method.MethodName#>:
<#=method.MethodName#>(x, y, destination);
break;
<# } #>
<# } #>
}
}
//Comparison operations
public void HandleOperation(ComparisonOperation operation, ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<bool> destination)
{
switch (operation)
{
<# foreach (MethodConfiguration method in methodConfiguration) { #>
<# if (method.MethodType == MethodType.Comparison) { #>
case ComparisonOperation.<#=method.MethodName#>:
<#=method.MethodName#>(x, y, destination);
break;
<# } #>
<# } #>
}
}
public void HandleOperation(ComparisonOperation operation, ReadOnlySpan<T> x, T y, Span<bool> destination)
{
switch (operation)
{
<# foreach (MethodConfiguration method in methodConfiguration) { #>
<# if (method.MethodType == MethodType.ComparisonScalar) { #>
case ComparisonOperation.<#=method.MethodName#>:
<#=method.MethodName#>(x, y, destination);
break;
<# } #>
<# } #>
}
}
//Protected methods
<# foreach (MethodConfiguration method in methodConfiguration) { #>
<# if (method.MethodType == MethodType.Comparison) { #>
protected virtual void <#=method.MethodName#>(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<bool> destination) => throw new NotSupportedException();
<# } #>
<# else if (method.MethodType == MethodType.ComparisonScalar) { #>
protected virtual void <#=method.MethodName#>(ReadOnlySpan<T> x, T y, Span<bool> destination) => throw new NotSupportedException();
<# } #>
<# else if (method.MethodType == MethodType.Binary) { #>
protected virtual void <#=method.MethodName#>(ReadOnlySpan<T> x, ReadOnlySpan<T> y, Span<T> destination) => throw new NotSupportedException();
<# } else if (method.MethodType == MethodType.BinaryScalar) { #>
protected virtual void <#=method.MethodName#>(ReadOnlySpan<T> x, T y, Span<T> destination) => throw new NotSupportedException();
protected virtual void <#=method.MethodName#>(T x, ReadOnlySpan<T> y, Span<T> destination) => throw new NotSupportedException();
<# } else if (method.MethodType == MethodType.BinaryInt) { #>
protected virtual void <#=method.MethodName#>(ReadOnlySpan<T> x, int y, Span<T> destination) => throw new NotSupportedException();
<# } #>
<# } #>
protected virtual T Divide(T x, T y) => throw new NotSupportedException();
protected virtual T Modulo(T x, T y) => throw new NotSupportedException();
}
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -1,171 +0,0 @@
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ output extension=".cs" #>
<#@ include file="$(ProjectDir)\ColumnArithmeticTemplate.ttinclude" #>
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// Generated from Arithmetics.tt. Do not modify directly
using System;
using System.Numerics;
using System.Runtime.InteropServices;
namespace Microsoft.Data.Analysis
{
<# foreach (TypeConfiguration type in typeConfiguration) { #>
internal class <#=type.ClassPrefix#>Arithmetic : Arithmetic<<#=type.TypeName#>>
{
<# foreach (MethodConfiguration method in methodConfiguration) { #>
<# if (!((method.IsNumeric && !type.SupportsNumeric) || (method.IsBitwise && !type.SupportsBitwise) || (type.UnsupportedMethods.Contains(method.MethodName))) && method.Operator != null) { #>
<# if (method.MethodType == MethodType.Comparison) { #>
protected override void <#=method.MethodName#>(ReadOnlySpan<<#=type.TypeName#>> x, ReadOnlySpan<<#=type.TypeName#>> y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] <#= method.Operator #> y[i]);
}
}
<# } else if (method.MethodType == MethodType.ComparisonScalar) {#>
protected override void <#=method.MethodName#>(ReadOnlySpan<<#=type.TypeName#>> x, <#=type.TypeName#> y, Span<bool> destination)
{
for (var i = 0; i < x.Length; i++)
{
destination[i] = (x[i] <#= method.Operator #> y);
}
}
<# } else if (method.MethodType == MethodType.Binary) { #>
<# if (method.MethodName == "Divide" || method.MethodName == "Modulo") { #>
protected override <#=type.TypeName#> <#=method.MethodName#>(<#=type.TypeName#> x, <#=type.TypeName#> y)
{
return (<#=type.TypeName#>)(x <#= method.Operator #> y);
}
<# } #>
protected override void <#=method.MethodName#>(ReadOnlySpan<<#=type.TypeName#>> x, ReadOnlySpan<<#=type.TypeName#>> y, Span<<#=type.TypeName#>> destination)
{
int i = 0;
<# if (method.SupportsVectorization && type.SupportsVectorization) { #>
if (Vector.IsHardwareAccelerated)
{
ref <#=type.TypeName#> xRef = ref MemoryMarshal.GetReference(x);
ref <#=type.TypeName#> yRef = ref MemoryMarshal.GetReference(y);
ref <#=type.TypeName#> dRef = ref MemoryMarshal.GetReference(destination);
var vectorSize = Vector<<#=type.TypeName#>>.Count;
var oneVectorFromEnd = x.Length - vectorSize;
if (oneVectorFromEnd >= 0)
{
// Loop handling one vector at a time.
do
{
Arithmetic.AsVector(ref dRef, i) = (Arithmetic.AsVector(ref xRef, i) <#= method.Operator #> Arithmetic.AsVector(ref yRef, i));
i += vectorSize;
}
while (i <= oneVectorFromEnd);
}
}
<# } #>
while (i < x.Length)
{
destination[i] = (<#=type.TypeName#>)(x[i] <#= method.Operator #> y[i]);
i++;
}
}
<# } #>
<# else if (method.MethodType == MethodType.BinaryScalar) { #>
protected override void <#=method.MethodName#>(ReadOnlySpan<<#=type.TypeName#>> x, <#=type.TypeName#> y, Span<<#=type.TypeName#>> destination)
{
int i = 0;
<# if (method.SupportsVectorization && type.SupportsVectorization) { #>
if (Vector.IsHardwareAccelerated)
{
ref <#=type.TypeName#> xRef = ref MemoryMarshal.GetReference(x);
ref <#=type.TypeName#> dRef = ref MemoryMarshal.GetReference(destination);
var vectorSize = Vector<<#=type.TypeName#>>.Count;
var oneVectorFromEnd = x.Length - vectorSize;
if (oneVectorFromEnd >= 0)
{
Vector<<#=type.TypeName#>> yVec = new(y);
// Loop handling one vector at a time.
do
{
Arithmetic.AsVector(ref dRef, i) = (Arithmetic.AsVector(ref xRef, i) <#= method.Operator #> yVec);
i += vectorSize;
}
while (i <= oneVectorFromEnd);
}
}
<# } #>
while (i < x.Length)
{
destination[i] = (<#=type.TypeName#>)(x[i] <#= method.Operator #> y);
i++;
}
}
protected override void <#=method.MethodName#>(<#=type.TypeName#> x, ReadOnlySpan<<#=type.TypeName#>> y, Span<<#=type.TypeName#>> destination)
{
int i = 0;
<# if (method.SupportsVectorization && type.SupportsVectorization) { #>
if (Vector.IsHardwareAccelerated)
{
ref <#=type.TypeName#> yRef = ref MemoryMarshal.GetReference(y);
ref <#=type.TypeName#> dRef = ref MemoryMarshal.GetReference(destination);
var vectorSize = Vector<<#=type.TypeName#>>.Count;
var oneVectorFromEnd = y.Length - vectorSize;
if (oneVectorFromEnd >= 0)
{
Vector<<#=type.TypeName#>> xVec = new(x);
// Loop handling one vector at a time.
do
{
Arithmetic.AsVector(ref dRef, i) = (xVec <#= method.Operator #> Arithmetic.AsVector(ref yRef, i));
i += vectorSize;
}
while (i <= oneVectorFromEnd);
}
}
<# } #>
while (i < y.Length)
{
destination[i] = (<#=type.TypeName#>)(x <#= method.Operator #> y[i]);
i++;
}
}
<# } #>
<# else if (method.MethodType == MethodType.BinaryInt) { #>
protected override void <#=method.MethodName#>(ReadOnlySpan<<#=type.TypeName#>> x, int y, Span<<#=type.TypeName#>> destination)
{
for (var i = 0; i < x.Length; i++)
destination[i] = (<#=type.TypeName#>)(x[i] <#= method.Operator #> y);
}
<# } #>
<# } #>
<# } #>
}
<# } #>
}

Просмотреть файл

@ -44,6 +44,10 @@
<DependentUpon>PrimitiveDataFrameColumn.BinaryOperators.tt</DependentUpon>
</None>
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
<PackageReference Include="System.Numerics.Tensors" Version="9.0.0-preview.6.24327.7" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFrameworkIdentifier)' == '.NETStandard'">
<PackageReference Include="System.Memory" Version="$(SystemMemoryVersion)" />
@ -64,9 +68,9 @@
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>ColumnArithmetic.OperationEnums.cs</LastGenOutput>
</None>
<None Update="Computations\Arithmetic.tt">
<None Update="Computations\Arithmetic.netstandard.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Arithmetic.cs</LastGenOutput>
<LastGenOutput>Arithmetic.netstandard.cs</LastGenOutput>
</None>
<None Update="Converters.tt">
<Generator>TextTemplatingFileGenerator</Generator>
@ -125,18 +129,10 @@
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>PrimitiveDataFrameColumn.Computations.cs</LastGenOutput>
</None>
<None Update="Computations\Arithmetics.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>PrimitiveColumnArithmetic.cs</LastGenOutput>
</None>
<None Update="PrimitiveDataFrameColumnComputations.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>PrimitiveDataFrameColumnComputations.cs</LastGenOutput>
</None>
<None Update="Computations\Arithmetics.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Arithmetics.cs</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
@ -144,10 +140,10 @@
</ItemGroup>
<ItemGroup>
<Compile Update="Computations\Arithmetic.cs">
<Compile Update="Computations\Arithmetic.netstandard.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Arithmetic.tt</DependentUpon>
<DependentUpon>Arithmetic.netstandard.tt</DependentUpon>
</Compile>
<Compile Update="Converters.cs">
<DesignTime>True</DesignTime>
@ -214,21 +210,11 @@
<AutoGen>True</AutoGen>
<DependentUpon>PrimitiveDataFrameColumn.Computations.tt</DependentUpon>
</Compile>
<Compile Update="Computations\Arithmetics.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>PrimitiveColumnArithmetic.tt</DependentUpon>
</Compile>
<Compile Update="PrimitiveDataFrameColumnComputations.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>PrimitiveDataFrameColumnComputations.tt</DependentUpon>
</Compile>
<Compile Update="Computations\Arithmetics.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Arithmetics.tt</DependentUpon>
</Compile>
<Compile Update="Strings.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>

Просмотреть файл

@ -24,30 +24,39 @@ namespace Microsoft.Data.Analysis.Tests
var ret = df.Add(5);
Assert.Equal(0, df[0, 0]);
Assert.Equal(5, ret[0, 0]);
ret = df.Add(listOfInts);
Assert.Equal(0, df[0, 0]);
Assert.Equal(5, ret[0, 0]);
ret = df.Subtract(5);
Assert.Equal(0, df[0, 0]);
Assert.Equal(-5, ret[0, 0]);
ret = df.Subtract(listOfInts);
Assert.Equal(0, df[0, 0]);
Assert.Equal(-5, ret[0, 0]);
ret = df.Multiply(5);
Assert.Equal(1, df[1, 0]);
Assert.Equal(5, ret[1, 0]);
ret = df.Multiply(listOfInts);
Assert.Equal(1, df[1, 0]);
Assert.Equal(5, ret[1, 0]);
ret = df.Divide(5);
Assert.Equal(5, df[5, 0]);
Assert.Equal(1, ret[5, 0]);
ret = df.Divide(listOfInts);
Assert.Equal(5, df[5, 0]);
Assert.Equal(1, ret[5, 0]);
ret = df.Modulo(5);
Assert.Equal(5, df[5, 0]);
Assert.Equal(0, ret[5, 0]);
ret = df.Modulo(listOfInts);
Assert.Equal(5, df[5, 0]);
Assert.Equal(0, ret[5, 0]);