Skip to content

Commit

Permalink
Numeric operators
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewvk committed Apr 8, 2016
1 parent b2ab32d commit 9bfab8b
Show file tree
Hide file tree
Showing 13 changed files with 338 additions and 8 deletions.
113 changes: 113 additions & 0 deletions Main/src/Arithmetic/Operators.Numeric.generated.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using System;
using System.Linq.Expressions;
using System.Threading;

using JetBrains.Annotations;

using static CodeJam.Arithmetic.OperatorsFactory;

namespace CodeJam.Arithmetic
{
partial class Operators<T>
{
private static readonly Lazy<Func<T, T, T>> _plus
= new Lazy<Func<T, T, T>>(() => CreateNumOperFunc<T>(ExpressionType.Add), LazyThreadSafetyMode.PublicationOnly);

/// <summary>
/// Plus operator.
/// </summary>
[NotNull]
public static Func<T, T, T> Plus => _plus.Value;

private static readonly Lazy<Func<T, T, T>> _minus
= new Lazy<Func<T, T, T>>(() => CreateNumOperFunc<T>(ExpressionType.Subtract), LazyThreadSafetyMode.PublicationOnly);

/// <summary>
/// Minus operator.
/// </summary>
[NotNull]
public static Func<T, T, T> Minus => _minus.Value;

private static readonly Lazy<Func<T, T, T>> _mul
= new Lazy<Func<T, T, T>>(() => CreateNumOperFunc<T>(ExpressionType.Multiply), LazyThreadSafetyMode.PublicationOnly);

/// <summary>
/// Mul operator.
/// </summary>
[NotNull]
public static Func<T, T, T> Mul => _mul.Value;

private static readonly Lazy<Func<T, T, T>> _div
= new Lazy<Func<T, T, T>>(() => CreateNumOperFunc<T>(ExpressionType.Divide), LazyThreadSafetyMode.PublicationOnly);

/// <summary>
/// Div operator.
/// </summary>
[NotNull]
public static Func<T, T, T> Div => _div.Value;

private static readonly Lazy<Func<T, T, T>> _modulo
= new Lazy<Func<T, T, T>>(() => CreateNumOperFunc<T>(ExpressionType.Modulo), LazyThreadSafetyMode.PublicationOnly);

/// <summary>
/// Modulo operator.
/// </summary>
[NotNull]
public static Func<T, T, T> Modulo => _modulo.Value;

private static readonly Lazy<Func<T, T, T>> _xor
= new Lazy<Func<T, T, T>>(() => CreateNumOperFunc<T>(ExpressionType.ExclusiveOr), LazyThreadSafetyMode.PublicationOnly);

/// <summary>
/// Xor operator.
/// </summary>
[NotNull]
public static Func<T, T, T> Xor => _xor.Value;

private static readonly Lazy<Func<T, T, T>> _bitwiseand
= new Lazy<Func<T, T, T>>(() => CreateNumOperFunc<T>(ExpressionType.And), LazyThreadSafetyMode.PublicationOnly);

/// <summary>
/// BitwiseAnd operator.
/// </summary>
[NotNull]
public static Func<T, T, T> BitwiseAnd => _bitwiseand.Value;

private static readonly Lazy<Func<T, T, T>> _bitwiseor
= new Lazy<Func<T, T, T>>(() => CreateNumOperFunc<T>(ExpressionType.Or), LazyThreadSafetyMode.PublicationOnly);

/// <summary>
/// BitwiseOr operator.
/// </summary>
[NotNull]
public static Func<T, T, T> BitwiseOr => _bitwiseor.Value;

private static readonly Lazy<Func<T, T, T>> _leftshift
= new Lazy<Func<T, T, T>>(() => CreateNumOperFunc<T>(ExpressionType.LeftShift), LazyThreadSafetyMode.PublicationOnly);

/// <summary>
/// LeftShift operator.
/// </summary>
[NotNull]
public static Func<T, T, T> LeftShift => _leftshift.Value;

private static readonly Lazy<Func<T, T, T>> _rightshift
= new Lazy<Func<T, T, T>>(() => CreateNumOperFunc<T>(ExpressionType.RightShift), LazyThreadSafetyMode.PublicationOnly);

/// <summary>
/// RightShift operator.
/// </summary>
[NotNull]
public static Func<T, T, T> RightShift => _rightshift.Value;

}
}
42 changes: 42 additions & 0 deletions Main/src/Arithmetic/Operators.Numeric.tt
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core"
#><#@ include file="Operators.ttinclude"
#><#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Linq.Expressions" #>
<#@ output extension=".generated.cs"
#>//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using System;
using System.Linq.Expressions;
using System.Threading;

using JetBrains.Annotations;

using static CodeJam.Arithmetic.OperatorsFactory;

namespace CodeJam.Arithmetic
{
partial class Operators<T>
{
<#foreach (var op in ops) {#>
private static readonly Lazy<Func<T, T, T>> _<#=op.Name.ToLower()#>
= new Lazy<Func<T, T, T>>(() => CreateNumOperFunc<T>(ExpressionType.<#=op.Type#>), LazyThreadSafetyMode.PublicationOnly);

/// <summary>
/// <#=op.Name#> operator.
/// </summary>
[NotNull]
public static Func<T, T, T> <#=op.Name#> => _<#=op.Name.ToLower()#>.Value;

<#}#>
}
}
2 changes: 1 addition & 1 deletion Main/src/Arithmetic/Operators.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ namespace CodeJam.Arithmetic
/// </summary>
// IMPORTANT: DO NOT declare static .ctor on the type. The class should be marked as beforefieldinit.
[PublicAPI]
public static class Operators<T>
public static partial class Operators<T>
{
/// <summary>
/// Comparison callback
Expand Down
38 changes: 38 additions & 0 deletions Main/src/Arithmetic/Operators.ttinclude
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<#@ template debug="false" hostspecific="false" language="C#" #>
<#@ assembly name="System.Core" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.Collections.Generic" #>
<#@ import namespace="System.Linq.Expressions" #>
<#
var ops =
new []
{
new OpInfo("Plus", "+", ExpressionType.Add, false),
new OpInfo("Minus", "-", ExpressionType.Subtract, false),
new OpInfo("Mul", "*", ExpressionType.Multiply, false),
new OpInfo("Div", "/", ExpressionType.Divide, false),
new OpInfo("Modulo", "%", ExpressionType.Modulo, true),
new OpInfo("Xor", "^", ExpressionType.ExclusiveOr, true),
new OpInfo("BitwiseAnd", "&", ExpressionType.And, true),
new OpInfo("BitwiseOr", "|", ExpressionType.Or, true),
new OpInfo("LeftShift", "<<", ExpressionType.LeftShift, true),
new OpInfo("RightShift", ">>", ExpressionType.RightShift, true),
};
#>
<#+
private class OpInfo
{
public string Name { get; }
public string Sign { get; }
public ExpressionType Type { get; }
public bool IntOnly { get; }
public OpInfo(string name, string sign, ExpressionType type, bool intOnly)
{
Name = name;
Type = type;
Sign = sign;
IntOnly = intOnly;
}
}
#>
19 changes: 15 additions & 4 deletions Main/src/Arithmetic/OperatorsFactory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ public static Func<T, T, int> GetComparisonCallback<T>()

[CanBeNull]
public static Func<T, T, bool> GetComparisonCallback<T>(ExpressionType comparisonType) =>
CompareUsingOperators<T>(comparisonType) ??
CompareUsingComparer<T>(comparisonType);
CompareUsingOperators<T>(comparisonType)
?? CompareUsingComparer<T>(comparisonType);

[CanBeNull]
public static Func<T, T, bool> CompareUsingOperators<T>(ExpressionType comparisonType)
private static Func<T, T, bool> CompareUsingOperators<T>(ExpressionType comparisonType)
{
switch (comparisonType)
{
Expand Down Expand Up @@ -81,7 +81,7 @@ public static Func<T, T, bool> CompareUsingOperators<T>(ExpressionType compariso
}

[CanBeNull]
public static Func<T, T, bool> CompareUsingComparer<T>(ExpressionType comparisonType)
private static Func<T, T, bool> CompareUsingComparer<T>(ExpressionType comparisonType)
{
switch (comparisonType)
{
Expand Down Expand Up @@ -112,5 +112,16 @@ public static Func<T, T, bool> CompareUsingComparer<T>(ExpressionType comparison
nameof(comparisonType), comparisonType);
}
}

public static Func<T, T, T> CreateNumOperFunc<T>(ExpressionType operatorType)
{
var arg1 = Expression.Parameter(typeof(T));
var arg2 = Expression.Parameter(typeof(T));
var expr = Expression.MakeBinary(operatorType, arg1, arg2);
return
Expression
.Lambda<Func<T, T, T>>(expr, "plus", new[] { arg1, arg2 })
.Compile();
}
}
}
10 changes: 10 additions & 0 deletions Main/src/CodeJam.Main.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@
<Compile Include="Algorithms\Memoize.cs" />
<Compile Include="Algorithms\Swap.cs" />
<Compile Include="Algorithms\UpperBound.cs" />
<Compile Include="Arithmetic\Operators.Numeric.generated.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Operators.Numeric.tt</DependentUpon>
</Compile>
<Compile Include="Arithmetic\OperatorsFactory.cs" />
<Compile Include="Arithmetic\Operators.cs" />
<Compile Include="Assertions\Code.NonDebug.cs" />
Expand Down Expand Up @@ -161,6 +166,11 @@
<Compile Include="Reflection\ReflectionExtension.CreateInstance.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="Arithmetic\Operators.Numeric.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Operators.Numeric.generated.cs</LastGenOutput>
</Content>
<None Include="Arithmetic\Operators.ttinclude" />
<Content Include="Assertions\DebugCode.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>DebugCode.generated.cs</LastGenOutput>
Expand Down
7 changes: 7 additions & 0 deletions Main/tests-performance/Arithmetic/OperatorsBenchmarkBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,31 @@

using BenchmarkDotNet.Attributes;

using JetBrains.Annotations;

namespace CodeJam.Arithmetic
{
/// <summary>
/// Base class for all operator test cases;
/// </summary>
public abstract class OperatorsBenchmarkBase<T, TStorage>
{
// ReSharper disable once MemberCanBePrivate.Global
// ReSharper disable AutoPropertyCanBeMadeGetOnly.Global
protected int Count { get; set; } = 1000 * 1000;
protected int ValueBRepeats { get; set; } = 5;
// ReSharper restore AutoPropertyCanBeMadeGetOnly.Global

protected T[] ValuesA;
protected T[] ValuesB;
// ReSharper disable once NotAccessedField.Global
protected TStorage Storage;

protected abstract T GetValueA(int i);
protected abstract T GetValueB(int i);

[Setup]
[UsedImplicitly]
public void Setup()
{
var count = Count;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;

using BenchmarkDotNet.Attributes;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq.Expressions;

using BenchmarkDotNet.Attributes;
Expand Down
62 changes: 62 additions & 0 deletions Main/tests/Arithmetic/OperatorsTest.Numeric.generated.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using NUnit.Framework;

using IntOp = CodeJam.Arithmetic.Operators<int>;
using NullableDoubleOp = CodeJam.Arithmetic.Operators<double?>;

namespace CodeJam.Arithmetic
{
partial class OperatorsTest
{
[Test]
public void IntPlus() => Assert.AreEqual(1 + 2, IntOp.Plus(1, 2));

[Test]
public void NullableDoublePlus() => Assert.AreEqual(1f + 2f, NullableDoubleOp.Plus(1, 2));

[Test]
public void IntMinus() => Assert.AreEqual(1 - 2, IntOp.Minus(1, 2));

[Test]
public void NullableDoubleMinus() => Assert.AreEqual(1f - 2f, NullableDoubleOp.Minus(1, 2));

[Test]
public void IntMul() => Assert.AreEqual(1 * 2, IntOp.Mul(1, 2));

[Test]
public void NullableDoubleMul() => Assert.AreEqual(1f * 2f, NullableDoubleOp.Mul(1, 2));

[Test]
public void IntDiv() => Assert.AreEqual(1 / 2, IntOp.Div(1, 2));

[Test]
public void NullableDoubleDiv() => Assert.AreEqual(1f / 2f, NullableDoubleOp.Div(1, 2));

[Test]
public void IntModulo() => Assert.AreEqual(1 % 2, IntOp.Modulo(1, 2));

[Test]
public void IntXor() => Assert.AreEqual(1 ^ 2, IntOp.Xor(1, 2));

[Test]
public void IntBitwiseAnd() => Assert.AreEqual(1 & 2, IntOp.BitwiseAnd(1, 2));

[Test]
public void IntBitwiseOr() => Assert.AreEqual(1 | 2, IntOp.BitwiseOr(1, 2));

[Test]
public void IntLeftShift() => Assert.AreEqual(1 << 2, IntOp.LeftShift(1, 2));

[Test]
public void IntRightShift() => Assert.AreEqual(1 >> 2, IntOp.RightShift(1, 2));

}
}
Loading

0 comments on commit 9bfab8b

Please sign in to comment.