Browse Source

Use Operator<T>

Former-commit-id: 1bc110efc169542f998698c406473969ff03432a
Former-commit-id: 0a96341575e95754884d20aff07d2f31f4265576
Former-commit-id: 404c8605fcc6a522e96b5812d647a89337ce65cc
pull/1/head
James Jackson-South 10 years ago
parent
commit
cfda01fc44
  1. 58
      GenericImage/Common/Helpers/Class.cs
  2. 100
      GenericImage/Common/Helpers/ExpressionUtil.cs
  3. 479
      GenericImage/Common/Helpers/Operator.cs
  4. 67
      GenericImage/PackedVectors/Bgra.cs
  5. 11
      GenericImage/PackedVectors/IColor.cs
  6. 1
      GenericImage/project.json
  7. 58
      src/ImageProcessorCore/Common/Helpers/Class.cs
  8. 100
      src/ImageProcessorCore/Common/Helpers/ExpressionUtil.cs
  9. 464
      src/ImageProcessorCore/Common/Helpers/Operator.cs
  10. 26
      src/ImageProcessorCore/PackedVector/Bgra32.cs
  11. 24
      src/ImageProcessorCore/PackedVector/IPackedVector.cs
  12. 1
      src/ImageProcessorCore/project.json

58
GenericImage/Common/Helpers/Class.cs

@ -0,0 +1,58 @@
namespace GenericImage.Helpers
{
interface INullOp<T>
{
bool HasValue(T value);
bool AddIfNotNull(ref T accumulator, T value);
}
sealed class StructNullOp<T>
: INullOp<T>, INullOp<T?>
where T : struct
{
public bool HasValue(T value)
{
return true;
}
public bool AddIfNotNull(ref T accumulator, T value)
{
accumulator = Operator<T>.Add(accumulator, value);
return true;
}
public bool HasValue(T? value)
{
return value.HasValue;
}
public bool AddIfNotNull(ref T? accumulator, T? value)
{
if (value.HasValue)
{
accumulator = accumulator.HasValue ?
Operator<T>.Add(
accumulator.GetValueOrDefault(),
value.GetValueOrDefault())
: value;
return true;
}
return false;
}
}
sealed class ClassNullOp<T>
: INullOp<T>
where T : class
{
public bool HasValue(T value)
{
return value != null;
}
public bool AddIfNotNull(ref T accumulator, T value)
{
if (value != null)
{
accumulator = accumulator == null ?
value : Operator<T>.Add(accumulator, value);
return true;
}
return false;
}
}
}

100
GenericImage/Common/Helpers/ExpressionUtil.cs

@ -0,0 +1,100 @@
namespace GenericImage.Helpers
{
using System;
using System.Linq.Expressions;
/// <summary>
/// General purpose Expression utilities
/// </summary>
public static class ExpressionUtil
{
/// <summary>
/// Create a function delegate representing a unary operation
/// </summary>
/// <typeparam name="TArg1">The parameter type</typeparam>
/// <typeparam name="TResult">The return type</typeparam>
/// <param name="body">Body factory</param>
/// <returns>Compiled function delegate</returns>
public static Func<TArg1, TResult> CreateExpression<TArg1, TResult>(
Func<Expression, UnaryExpression> body)
{
ParameterExpression inp = Expression.Parameter(typeof(TArg1), "inp");
try
{
return Expression.Lambda<Func<TArg1, TResult>>(body(inp), inp).Compile();
}
catch (Exception ex)
{
string msg = ex.Message; // avoid capture of ex itself
return delegate { throw new InvalidOperationException(msg); };
}
}
/// <summary>
/// Create a function delegate representing a binary operation
/// </summary>
/// <typeparam name="TArg1">The first parameter type</typeparam>
/// <typeparam name="TArg2">The second parameter type</typeparam>
/// <typeparam name="TResult">The return type</typeparam>
/// <param name="body">Body factory</param>
/// <returns>Compiled function delegate</returns>
public static Func<TArg1, TArg2, TResult> CreateExpression<TArg1, TArg2, TResult>(
Func<Expression, Expression, BinaryExpression> body)
{
return CreateExpression<TArg1, TArg2, TResult>(body, false);
}
/// <summary>
/// Create a function delegate representing a binary operation
/// </summary>
/// <param name="castArgsToResultOnFailure">
/// If no matching operation is possible, attempt to convert
/// TArg1 and TArg2 to TResult for a match? For example, there is no
/// "decimal operator /(decimal, int)", but by converting TArg2 (int) to
/// TResult (decimal) a match is found.
/// </param>
/// <typeparam name="TArg1">The first parameter type</typeparam>
/// <typeparam name="TArg2">The second parameter type</typeparam>
/// <typeparam name="TResult">The return type</typeparam>
/// <param name="body">Body factory</param>
/// <returns>Compiled function delegate</returns>
public static Func<TArg1, TArg2, TResult> CreateExpression<TArg1, TArg2, TResult>(
Func<Expression, Expression, BinaryExpression> body, bool castArgsToResultOnFailure)
{
ParameterExpression lhs = Expression.Parameter(typeof(TArg1), "lhs");
ParameterExpression rhs = Expression.Parameter(typeof(TArg2), "rhs");
try
{
try
{
return Expression.Lambda<Func<TArg1, TArg2, TResult>>(body(lhs, rhs), lhs, rhs).Compile();
}
catch (InvalidOperationException)
{
// If we show retry and the args aren't already "TValue, TValue, TValue"...
// convert both lhs and rhs to TResult (as appropriate)
if (castArgsToResultOnFailure && !(typeof(TArg1) == typeof(TResult) && typeof(TArg2) == typeof(TResult)))
{
Expression castLhs = typeof(TArg1) == typeof(TResult)
? lhs
: (Expression)Expression.Convert(lhs, typeof(TResult));
Expression castRhs = typeof(TArg2) == typeof(TResult)
? rhs
: (Expression)Expression.Convert(rhs, typeof(TResult));
return Expression.Lambda<Func<TArg1, TArg2, TResult>>(
body(castLhs, castRhs), lhs, rhs).Compile();
}
throw;
}
}
catch (Exception ex)
{
string msg = ex.Message; // avoid capture of ex itself
return delegate { throw new InvalidOperationException(msg); };
}
}
}
}

479
GenericImage/Common/Helpers/Operator.cs

@ -0,0 +1,479 @@
namespace GenericImage.Helpers
{
using System;
using System.Linq.Expressions;
using System.Reflection;
/// <summary>
/// The Operator class provides easy access to the standard operators
/// (addition, etc) for generic types, using type inference to simplify
/// usage.
/// </summary>
public static class Operator
{
/// <summary>
/// Indicates if the supplied value is non-null,
/// for reference-types or Nullable&lt;T&gt;
/// </summary>
/// <returns>True for non-null values, else false</returns>
public static bool HasValue<T>(T value)
{
return Operator<T>.NullOp.HasValue(value);
}
/// <summary>
/// Increments the accumulator only
/// if the value is non-null. If the accumulator
/// is null, then the accumulator is given the new
/// value; otherwise the accumulator and value
/// are added.
/// </summary>
/// <param name="accumulator">The current total to be incremented (can be null)</param>
/// <param name="value">The value to be tested and added to the accumulator</param>
/// <returns>True if the value is non-null, else false - i.e.
/// "has the accumulator been updated?"</returns>
public static bool AddIfNotNull<T>(ref T accumulator, T value)
{
return Operator<T>.NullOp.AddIfNotNull(ref accumulator, value);
}
/// <summary>
/// Evaluates unary negation (-) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static T Negate<T>(T value)
{
return Operator<T>.Negate(value);
}
/// <summary>
/// Evaluates bitwise not (~) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static T Not<T>(T value)
{
return Operator<T>.Not(value);
}
/// <summary>
/// Evaluates bitwise or (|) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static T Or<T>(T value1, T value2)
{
return Operator<T>.Or(value1, value2);
}
/// <summary>
/// Evaluates bitwise and (&amp;) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static T And<T>(T value1, T value2)
{
return Operator<T>.And(value1, value2);
}
/// <summary>
/// Evaluates bitwise xor (^) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static T Xor<T>(T value1, T value2)
{
return Operator<T>.Xor(value1, value2);
}
/// <summary>
/// Performs a conversion between the given types; this will throw
/// an InvalidOperationException if the type T does not provide a suitable cast, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this cast.
/// </summary>
public static TTo Convert<TFrom, TTo>(TFrom value)
{
return Operator<TFrom, TTo>.Convert(value);
}
/// <summary>
/// Evaluates binary addition (+) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static T Add<T>(T value1, T value2)
{
return Operator<T>.Add(value1, value2);
}
/// <summary>
/// Evaluates binary addition (+) for the given type(s); this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static TArg1 AddAlternative<TArg1, TArg2>(TArg1 value1, TArg2 value2)
{
return Operator<TArg2, TArg1>.Add(value1, value2);
}
/// <summary>
/// Evaluates binary subtraction (-) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static T Subtract<T>(T value1, T value2)
{
return Operator<T>.Subtract(value1, value2);
}
/// <summary>
/// Evaluates binary subtraction(-) for the given type(s); this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static TArg1 SubtractAlternative<TArg1, TArg2>(TArg1 value1, TArg2 value2)
{
return Operator<TArg2, TArg1>.Subtract(value1, value2);
}
/// <summary>
/// Evaluates binary multiplication (*) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static T Multiply<T>(T value1, T value2)
{
return Operator<T>.Multiply(value1, value2);
}
/// <summary>
/// Evaluates binary multiplication (*) for the given type(s); this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static TArg1 MultiplyAlternative<TArg1, TArg2>(TArg1 value1, TArg2 value2)
{
return Operator<TArg2, TArg1>.Multiply(value1, value2);
}
/// <summary>
/// Evaluates binary division (/) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static T Divide<T>(T value1, T value2)
{
return Operator<T>.Divide(value1, value2);
}
/// <summary>
/// Evaluates binary division (/) for the given type(s); this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static TArg1 DivideAlternative<TArg1, TArg2>(TArg1 value1, TArg2 value2)
{
return Operator<TArg2, TArg1>.Divide(value1, value2);
}
/// <summary>
/// Evaluates binary equality (==) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static bool Equal<T>(T value1, T value2)
{
return Operator<T>.Equal(value1, value2);
}
/// <summary>
/// Evaluates binary inequality (!=) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static bool NotEqual<T>(T value1, T value2)
{
return Operator<T>.NotEqual(value1, value2);
}
/// <summary>
/// Evaluates binary greater-than (&gt;) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static bool GreaterThan<T>(T value1, T value2)
{
return Operator<T>.GreaterThan(value1, value2);
}
/// <summary>
/// Evaluates binary less-than (&lt;) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static bool LessThan<T>(T value1, T value2)
{
return Operator<T>.LessThan(value1, value2);
}
/// <summary>
/// Evaluates binary greater-than-on-eqauls (&gt;=) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static bool GreaterThanOrEqual<T>(T value1, T value2)
{
return Operator<T>.GreaterThanOrEqual(value1, value2);
}
/// <summary>
/// Evaluates binary less-than-or-equal (&lt;=) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static bool LessThanOrEqual<T>(T value1, T value2)
{
return Operator<T>.LessThanOrEqual(value1, value2);
}
/// <summary>
/// Evaluates integer division (/) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary><remarks>
/// This operation is particularly useful for computing averages and
/// similar aggregates.
/// </remarks>
public static T DivideInt32<T>(T value, int divisor)
{
return Operator<int, T>.Divide(value, divisor);
}
}
/// <summary>
/// Provides standard operators (such as addition) that operate over operands of
/// different types. For operators, the return type is assumed to match the first
/// operand.
/// </summary>
/// <seealso cref="Operator&lt;T&gt;"/>
/// <seealso cref="Operator"/>
public static class Operator<TValue, TResult>
{
private static readonly Func<TValue, TResult> convert;
/// <summary>
/// Returns a delegate to convert a value between two types; this delegate will throw
/// an InvalidOperationException if the type T does not provide a suitable cast, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this cast.
/// </summary>
public static Func<TValue, TResult> Convert => convert;
static Operator()
{
convert = ExpressionUtil.CreateExpression<TValue, TResult>(body => Expression.Convert(body, typeof(TResult)));
add = ExpressionUtil.CreateExpression<TResult, TValue, TResult>(Expression.Add, true);
subtract = ExpressionUtil.CreateExpression<TResult, TValue, TResult>(Expression.Subtract, true);
multiply = ExpressionUtil.CreateExpression<TResult, TValue, TResult>(Expression.Multiply, true);
divide = ExpressionUtil.CreateExpression<TResult, TValue, TResult>(Expression.Divide, true);
}
private static readonly Func<TResult, TValue, TResult> add, subtract, multiply, divide;
private static readonly Func<TResult, float, TResult> multiplyF, divideF;
/// <summary>
/// Returns a delegate to evaluate binary addition (+) for the given types; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<TResult, TValue, TResult> Add => add;
/// <summary>
/// Returns a delegate to evaluate binary subtraction (-) for the given types; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<TResult, TValue, TResult> Subtract => subtract;
/// <summary>
/// Returns a delegate to evaluate binary multiplication (*) for the given types; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<TResult, TValue, TResult> Multiply => multiply;
/// <summary>
/// Returns a delegate to evaluate binary division (/) for the given types; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<TResult, TValue, TResult> Divide => divide;
public static Func<TResult, float, TResult> MultiplyF => multiplyF;
public static Func<TResult, float, TResult> DivideF => divideF;
}
/// <summary>
/// Provides standard operators (such as addition) over a single type
/// </summary>
/// <seealso cref="Operator"/>
/// <seealso cref="Operator&lt;TValue,TResult&gt;"/>
public static class Operator<T>
{
static readonly INullOp<T> nullOp;
internal static INullOp<T> NullOp => nullOp;
static readonly T zero;
/// <summary>
/// Returns the zero value for value-types (even full Nullable&lt;TInner&gt;) - or null for reference types
/// </summary>
public static T Zero => zero;
static readonly Func<T, T> negate, not;
static readonly Func<T, T, T> or, and, xor;
/// <summary>
/// Returns a delegate to evaluate unary negation (-) for the given type; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<T, T> Negate => negate;
/// <summary>
/// Returns a delegate to evaluate bitwise not (~) for the given type; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<T, T> Not => not;
/// <summary>
/// Returns a delegate to evaluate bitwise or (|) for the given type; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<T, T, T> Or => or;
/// <summary>
/// Returns a delegate to evaluate bitwise and (&amp;) for the given type; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<T, T, T> And => and;
/// <summary>
/// Returns a delegate to evaluate bitwise xor (^) for the given type; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<T, T, T> Xor => xor;
static readonly Func<T, T, T> add, subtract, multiply, divide;
static readonly Func<T, float, T> multiplyF, divideF;
/// <summary>
/// Returns a delegate to evaluate binary addition (+) for the given type; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<T, T, T> Add => add;
/// <summary>
/// Returns a delegate to evaluate binary subtraction (-) for the given type; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<T, T, T> Subtract => subtract;
/// <summary>
/// Returns a delegate to evaluate binary multiplication (*) for the given type; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<T, T, T> Multiply => multiply;
/// <summary>
/// Returns a delegate to evaluate binary division (/) for the given type; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<T, T, T> Divide => divide;
public static Func<T, float, T> MultiplyF => multiplyF;
public static Func<T, float, T> DivideF => divideF;
static readonly Func<T, T, bool> equal, notEqual, greaterThan, lessThan, greaterThanOrEqual, lessThanOrEqual;
/// <summary>
/// Returns a delegate to evaluate binary equality (==) for the given type; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<T, T, bool> Equal => equal;
/// <summary>
/// Returns a delegate to evaluate binary inequality (!=) for the given type; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<T, T, bool> NotEqual => notEqual;
/// <summary>
/// Returns a delegate to evaluate binary greater-then (&gt;) for the given type; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<T, T, bool> GreaterThan => greaterThan;
/// <summary>
/// Returns a delegate to evaluate binary less-than (&lt;) for the given type; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<T, T, bool> LessThan => lessThan;
/// <summary>
/// Returns a delegate to evaluate binary greater-than-or-equal (&gt;=) for the given type; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<T, T, bool> GreaterThanOrEqual => greaterThanOrEqual;
/// <summary>
/// Returns a delegate to evaluate binary less-than-or-equal (&lt;=) for the given type; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<T, T, bool> LessThanOrEqual => lessThanOrEqual;
static Operator()
{
add = ExpressionUtil.CreateExpression<T, T, T>(Expression.Add);
subtract = ExpressionUtil.CreateExpression<T, T, T>(Expression.Subtract);
divide = ExpressionUtil.CreateExpression<T, T, T>(Expression.Divide);
multiply = ExpressionUtil.CreateExpression<T, T, T>(Expression.Multiply);
multiplyF = ExpressionUtil.CreateExpression<T, float, T>(Expression.Multiply);
divideF = ExpressionUtil.CreateExpression<T, float, T>(Expression.Multiply);
greaterThan = ExpressionUtil.CreateExpression<T, T, bool>(Expression.GreaterThan);
greaterThanOrEqual = ExpressionUtil.CreateExpression<T, T, bool>(Expression.GreaterThanOrEqual);
lessThan = ExpressionUtil.CreateExpression<T, T, bool>(Expression.LessThan);
lessThanOrEqual = ExpressionUtil.CreateExpression<T, T, bool>(Expression.LessThanOrEqual);
equal = ExpressionUtil.CreateExpression<T, T, bool>(Expression.Equal);
notEqual = ExpressionUtil.CreateExpression<T, T, bool>(Expression.NotEqual);
negate = ExpressionUtil.CreateExpression<T, T>(Expression.Negate);
and = ExpressionUtil.CreateExpression<T, T, T>(Expression.And);
or = ExpressionUtil.CreateExpression<T, T, T>(Expression.Or);
not = ExpressionUtil.CreateExpression<T, T>(Expression.Not);
xor = ExpressionUtil.CreateExpression<T, T, T>(Expression.ExclusiveOr);
Type typeT = typeof(T);
if (typeT.GetTypeInfo().IsValueType && typeT.GetTypeInfo().IsGenericType && (typeT.GetGenericTypeDefinition() == typeof(Nullable<>)))
{
// get the *inner* zero (not a null Nullable<TValue>, but default(TValue))
Type nullType = typeT.GetTypeInfo().GenericTypeArguments[0];
zero = (T)Activator.CreateInstance(nullType);
nullOp = (INullOp<T>)Activator.CreateInstance(
typeof(StructNullOp<>).MakeGenericType(nullType));
}
else
{
zero = default(T);
if (typeT.GetTypeInfo().IsValueType)
{
nullOp = (INullOp<T>)Activator.CreateInstance(
typeof(StructNullOp<>).MakeGenericType(typeT));
}
else
{
nullOp = (INullOp<T>)Activator.CreateInstance(
typeof(ClassNullOp<>).MakeGenericType(typeT));
}
}
}
}
}

67
GenericImage/PackedVectors/Bgra.cs

@ -1,52 +1,85 @@
using System;
using System.Numerics;
using GenericImage.Helpers;
using GenericImage.PackedVectors;
namespace GenericImage.PackedVectors
{
public struct Bgra<TDepth> : IColor4<TDepth>
public struct Bgra<TDepth> : IColor<TDepth>
where TDepth : struct
{
public TDepth X { get; set; }
public TDepth Y { get; set; }
private static readonly TDepth[] Components = new TDepth[4];
public TDepth Z { get; set; }
public TDepth W { get; set; }
public TDepth[] Values => Components;
public void Add<TColor>(TColor value) where TColor : IColor<TDepth>
{
throw new NotImplementedException();
for (int i = 0; i < value.Values.Length; i++)
{
this.Values[i] = Operator<TDepth>.Add(this.Values[i], value.Values[i]);
}
}
public void Multiply<TColor>(TColor value) where TColor : IColor<TDepth>
{
throw new NotImplementedException();
for (int i = 0; i < value.Values.Length; i++)
{
this.Values[i] = Operator<TDepth>.Multiply(this.Values[i], value.Values[i]);
}
}
public void Multiply<TColor>(float value) where TColor : IColor<TDepth>
{
throw new NotImplementedException();
for (int i = 0; i < this.Values.Length; i++)
{
this.Values[i] = Operator<TDepth>.MultiplyF(this.Values[i], value);
}
}
public void Divide<TColor>(TColor value) where TColor : IColor<TDepth>
{
throw new NotImplementedException();
for (int i = 0; i < value.Values.Length; i++)
{
this.Values[i] = Operator<TDepth>.Divide(this.Values[i], value.Values[i]);
}
}
public void PackVector(Vector4 vector)
public void Divide<TColor>(float value) where TColor : IColor<TDepth>
{
throw new NotImplementedException();
for (int i = 0; i < this.Values.Length; i++)
{
this.Values[i] = Operator<TDepth>.DivideF(this.Values[i], value);
}
}
public Vector4 ToVector()
public byte[] ToBytes()
{
throw new NotImplementedException();
if (typeof(TDepth) == typeof(byte))
{
return new[]
{
(byte)(object)this.Values[0],
(byte)(object)this.Values[1],
(byte)(object)this.Values[2],
(byte)(object)this.Values[3]
};
}
return null;
}
public byte[] ToBytes()
public void FromBytes(byte[] bytes)
{
throw new System.NotImplementedException();
if (bytes.Length != 4)
{
throw new ArgumentOutOfRangeException(nameof(bytes));
}
for (int i = 0; i < bytes.Length; i++)
{
this.Values[i] = (TDepth)(object)bytes[i];
}
}
}
}

11
GenericImage/PackedVectors/IColor.cs

@ -17,6 +17,8 @@
public interface IColor<TDepth> : IColor
where TDepth : struct
{
TDepth[] Values { get; }
void Add<TColor>(TColor value) where TColor : IColor<TDepth>;
void Multiply<TColor>(TColor value) where TColor : IColor<TDepth>;
@ -24,14 +26,17 @@
void Multiply<TColor>(float value) where TColor : IColor<TDepth>;
void Divide<TColor>(TColor value) where TColor : IColor<TDepth>;
void Divide<TColor>(float value) where TColor : IColor<TDepth>;
void FromBytes(byte[] bytes);
byte[] ToBytes();
}
public interface IColor
{
void PackVector(Vector4 vector);
Vector4 ToVector();
byte[] ToBytes();
}
}

1
GenericImage/project.json

@ -12,6 +12,7 @@
"System.IO": "4.1.0",
"System.IO.Compression": "4.1.0",
"System.Linq": "4.1.0",
"System.Linq.Expressions": "4.1.0",
"System.Numerics.Vectors": "4.1.1",
"System.Resources.ResourceManager": "4.0.1",
"System.Runtime.Extensions": "4.1.0",

58
src/ImageProcessorCore/Common/Helpers/Class.cs

@ -0,0 +1,58 @@
namespace ImageProcessorCore.Helpers
{
interface INullOp<T>
{
bool HasValue(T value);
bool AddIfNotNull(ref T accumulator, T value);
}
sealed class StructNullOp<T>
: INullOp<T>, INullOp<T?>
where T : struct
{
public bool HasValue(T value)
{
return true;
}
public bool AddIfNotNull(ref T accumulator, T value)
{
accumulator = Operator<T>.Add(accumulator, value);
return true;
}
public bool HasValue(T? value)
{
return value.HasValue;
}
public bool AddIfNotNull(ref T? accumulator, T? value)
{
if (value.HasValue)
{
accumulator = accumulator.HasValue ?
Operator<T>.Add(
accumulator.GetValueOrDefault(),
value.GetValueOrDefault())
: value;
return true;
}
return false;
}
}
sealed class ClassNullOp<T>
: INullOp<T>
where T : class
{
public bool HasValue(T value)
{
return value != null;
}
public bool AddIfNotNull(ref T accumulator, T value)
{
if (value != null)
{
accumulator = accumulator == null ?
value : Operator<T>.Add(accumulator, value);
return true;
}
return false;
}
}
}

100
src/ImageProcessorCore/Common/Helpers/ExpressionUtil.cs

@ -0,0 +1,100 @@
namespace ImageProcessorCore.Helpers
{
using System;
using System.Linq.Expressions;
/// <summary>
/// General purpose Expression utilities
/// </summary>
public static class ExpressionUtil
{
/// <summary>
/// Create a function delegate representing a unary operation
/// </summary>
/// <typeparam name="TArg1">The parameter type</typeparam>
/// <typeparam name="TResult">The return type</typeparam>
/// <param name="body">Body factory</param>
/// <returns>Compiled function delegate</returns>
public static Func<TArg1, TResult> CreateExpression<TArg1, TResult>(
Func<Expression, UnaryExpression> body)
{
ParameterExpression inp = Expression.Parameter(typeof(TArg1), "inp");
try
{
return Expression.Lambda<Func<TArg1, TResult>>(body(inp), inp).Compile();
}
catch (Exception ex)
{
string msg = ex.Message; // avoid capture of ex itself
return delegate { throw new InvalidOperationException(msg); };
}
}
/// <summary>
/// Create a function delegate representing a binary operation
/// </summary>
/// <typeparam name="TArg1">The first parameter type</typeparam>
/// <typeparam name="TArg2">The second parameter type</typeparam>
/// <typeparam name="TResult">The return type</typeparam>
/// <param name="body">Body factory</param>
/// <returns>Compiled function delegate</returns>
public static Func<TArg1, TArg2, TResult> CreateExpression<TArg1, TArg2, TResult>(
Func<Expression, Expression, BinaryExpression> body)
{
return CreateExpression<TArg1, TArg2, TResult>(body, false);
}
/// <summary>
/// Create a function delegate representing a binary operation
/// </summary>
/// <param name="castArgsToResultOnFailure">
/// If no matching operation is possible, attempt to convert
/// TArg1 and TArg2 to TResult for a match? For example, there is no
/// "decimal operator /(decimal, int)", but by converting TArg2 (int) to
/// TResult (decimal) a match is found.
/// </param>
/// <typeparam name="TArg1">The first parameter type</typeparam>
/// <typeparam name="TArg2">The second parameter type</typeparam>
/// <typeparam name="TResult">The return type</typeparam>
/// <param name="body">Body factory</param>
/// <returns>Compiled function delegate</returns>
public static Func<TArg1, TArg2, TResult> CreateExpression<TArg1, TArg2, TResult>(
Func<Expression, Expression, BinaryExpression> body, bool castArgsToResultOnFailure)
{
ParameterExpression lhs = Expression.Parameter(typeof(TArg1), "lhs");
ParameterExpression rhs = Expression.Parameter(typeof(TArg2), "rhs");
try
{
try
{
return Expression.Lambda<Func<TArg1, TArg2, TResult>>(body(lhs, rhs), lhs, rhs).Compile();
}
catch (InvalidOperationException)
{
// If we show retry and the args aren't already "TValue, TValue, TValue"...
// convert both lhs and rhs to TResult (as appropriate)
if (castArgsToResultOnFailure && !(typeof(TArg1) == typeof(TResult) && typeof(TArg2) == typeof(TResult)))
{
Expression castLhs = typeof(TArg1) == typeof(TResult)
? lhs
: (Expression)Expression.Convert(lhs, typeof(TResult));
Expression castRhs = typeof(TArg2) == typeof(TResult)
? rhs
: (Expression)Expression.Convert(rhs, typeof(TResult));
return Expression.Lambda<Func<TArg1, TArg2, TResult>>(
body(castLhs, castRhs), lhs, rhs).Compile();
}
throw;
}
}
catch (Exception ex)
{
string msg = ex.Message; // avoid capture of ex itself
return delegate { throw new InvalidOperationException(msg); };
}
}
}
}

464
src/ImageProcessorCore/Common/Helpers/Operator.cs

@ -0,0 +1,464 @@
namespace ImageProcessorCore.Helpers
{
using System;
using System.Linq.Expressions;
using System.Reflection;
/// <summary>
/// The Operator class provides easy access to the standard operators
/// (addition, etc) for generic types, using type inference to simplify
/// usage.
/// </summary>
public static class Operator
{
/// <summary>
/// Indicates if the supplied value is non-null,
/// for reference-types or Nullable&lt;T&gt;
/// </summary>
/// <returns>True for non-null values, else false</returns>
public static bool HasValue<T>(T value)
{
return Operator<T>.NullOp.HasValue(value);
}
/// <summary>
/// Increments the accumulator only
/// if the value is non-null. If the accumulator
/// is null, then the accumulator is given the new
/// value; otherwise the accumulator and value
/// are added.
/// </summary>
/// <param name="accumulator">The current total to be incremented (can be null)</param>
/// <param name="value">The value to be tested and added to the accumulator</param>
/// <returns>True if the value is non-null, else false - i.e.
/// "has the accumulator been updated?"</returns>
public static bool AddIfNotNull<T>(ref T accumulator, T value)
{
return Operator<T>.NullOp.AddIfNotNull(ref accumulator, value);
}
/// <summary>
/// Evaluates unary negation (-) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static T Negate<T>(T value)
{
return Operator<T>.Negate(value);
}
/// <summary>
/// Evaluates bitwise not (~) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static T Not<T>(T value)
{
return Operator<T>.Not(value);
}
/// <summary>
/// Evaluates bitwise or (|) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static T Or<T>(T value1, T value2)
{
return Operator<T>.Or(value1, value2);
}
/// <summary>
/// Evaluates bitwise and (&amp;) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static T And<T>(T value1, T value2)
{
return Operator<T>.And(value1, value2);
}
/// <summary>
/// Evaluates bitwise xor (^) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static T Xor<T>(T value1, T value2)
{
return Operator<T>.Xor(value1, value2);
}
/// <summary>
/// Performs a conversion between the given types; this will throw
/// an InvalidOperationException if the type T does not provide a suitable cast, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this cast.
/// </summary>
public static TTo Convert<TFrom, TTo>(TFrom value)
{
return Operator<TFrom, TTo>.Convert(value);
}
/// <summary>
/// Evaluates binary addition (+) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static T Add<T>(T value1, T value2)
{
return Operator<T>.Add(value1, value2);
}
/// <summary>
/// Evaluates binary addition (+) for the given type(s); this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static TArg1 AddAlternative<TArg1, TArg2>(TArg1 value1, TArg2 value2)
{
return Operator<TArg2, TArg1>.Add(value1, value2);
}
/// <summary>
/// Evaluates binary subtraction (-) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static T Subtract<T>(T value1, T value2)
{
return Operator<T>.Subtract(value1, value2);
}
/// <summary>
/// Evaluates binary subtraction(-) for the given type(s); this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static TArg1 SubtractAlternative<TArg1, TArg2>(TArg1 value1, TArg2 value2)
{
return Operator<TArg2, TArg1>.Subtract(value1, value2);
}
/// <summary>
/// Evaluates binary multiplication (*) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static T Multiply<T>(T value1, T value2)
{
return Operator<T>.Multiply(value1, value2);
}
/// <summary>
/// Evaluates binary multiplication (*) for the given type(s); this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static TArg1 MultiplyAlternative<TArg1, TArg2>(TArg1 value1, TArg2 value2)
{
return Operator<TArg2, TArg1>.Multiply(value1, value2);
}
/// <summary>
/// Evaluates binary division (/) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static T Divide<T>(T value1, T value2)
{
return Operator<T>.Divide(value1, value2);
}
/// <summary>
/// Evaluates binary division (/) for the given type(s); this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static TArg1 DivideAlternative<TArg1, TArg2>(TArg1 value1, TArg2 value2)
{
return Operator<TArg2, TArg1>.Divide(value1, value2);
}
/// <summary>
/// Evaluates binary equality (==) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static bool Equal<T>(T value1, T value2)
{
return Operator<T>.Equal(value1, value2);
}
/// <summary>
/// Evaluates binary inequality (!=) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static bool NotEqual<T>(T value1, T value2)
{
return Operator<T>.NotEqual(value1, value2);
}
/// <summary>
/// Evaluates binary greater-than (&gt;) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static bool GreaterThan<T>(T value1, T value2)
{
return Operator<T>.GreaterThan(value1, value2);
}
/// <summary>
/// Evaluates binary less-than (&lt;) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static bool LessThan<T>(T value1, T value2)
{
return Operator<T>.LessThan(value1, value2);
}
/// <summary>
/// Evaluates binary greater-than-on-eqauls (&gt;=) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static bool GreaterThanOrEqual<T>(T value1, T value2)
{
return Operator<T>.GreaterThanOrEqual(value1, value2);
}
/// <summary>
/// Evaluates binary less-than-or-equal (&lt;=) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static bool LessThanOrEqual<T>(T value1, T value2)
{
return Operator<T>.LessThanOrEqual(value1, value2);
}
/// <summary>
/// Evaluates integer division (/) for the given type; this will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary><remarks>
/// This operation is particularly useful for computing averages and
/// similar aggregates.
/// </remarks>
public static T DivideInt32<T>(T value, int divisor)
{
return Operator<int, T>.Divide(value, divisor);
}
}
/// <summary>
/// Provides standard operators (such as addition) that operate over operands of
/// different types. For operators, the return type is assumed to match the first
/// operand.
/// </summary>
/// <seealso cref="Operator&lt;T&gt;"/>
/// <seealso cref="Operator"/>
public static class Operator<TValue, TResult>
{
private static readonly Func<TValue, TResult> convert;
/// <summary>
/// Returns a delegate to convert a value between two types; this delegate will throw
/// an InvalidOperationException if the type T does not provide a suitable cast, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this cast.
/// </summary>
public static Func<TValue, TResult> Convert => convert;
static Operator()
{
convert = ExpressionUtil.CreateExpression<TValue, TResult>(body => Expression.Convert(body, typeof(TResult)));
add = ExpressionUtil.CreateExpression<TResult, TValue, TResult>(Expression.Add, true);
subtract = ExpressionUtil.CreateExpression<TResult, TValue, TResult>(Expression.Subtract, true);
multiply = ExpressionUtil.CreateExpression<TResult, TValue, TResult>(Expression.Multiply, true);
divide = ExpressionUtil.CreateExpression<TResult, TValue, TResult>(Expression.Divide, true);
}
private static readonly Func<TResult, TValue, TResult> add, subtract, multiply, divide;
/// <summary>
/// Returns a delegate to evaluate binary addition (+) for the given types; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<TResult, TValue, TResult> Add => add;
/// <summary>
/// Returns a delegate to evaluate binary subtraction (-) for the given types; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<TResult, TValue, TResult> Subtract => subtract;
/// <summary>
/// Returns a delegate to evaluate binary multiplication (*) for the given types; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<TResult, TValue, TResult> Multiply => multiply;
/// <summary>
/// Returns a delegate to evaluate binary division (/) for the given types; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<TResult, TValue, TResult> Divide => divide;
}
/// <summary>
/// Provides standard operators (such as addition) over a single type
/// </summary>
/// <seealso cref="Operator"/>
/// <seealso cref="Operator&lt;TValue,TResult&gt;"/>
public static class Operator<T>
{
static readonly INullOp<T> nullOp;
internal static INullOp<T> NullOp => nullOp;
static readonly T zero;
/// <summary>
/// Returns the zero value for value-types (even full Nullable&lt;TInner&gt;) - or null for reference types
/// </summary>
public static T Zero => zero;
static readonly Func<T, T> negate, not;
static readonly Func<T, T, T> or, and, xor;
/// <summary>
/// Returns a delegate to evaluate unary negation (-) for the given type; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<T, T> Negate => negate;
/// <summary>
/// Returns a delegate to evaluate bitwise not (~) for the given type; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<T, T> Not => not;
/// <summary>
/// Returns a delegate to evaluate bitwise or (|) for the given type; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<T, T, T> Or => or;
/// <summary>
/// Returns a delegate to evaluate bitwise and (&amp;) for the given type; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<T, T, T> And => and;
/// <summary>
/// Returns a delegate to evaluate bitwise xor (^) for the given type; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<T, T, T> Xor => xor;
static readonly Func<T, T, T> add, subtract, multiply, divide;
/// <summary>
/// Returns a delegate to evaluate binary addition (+) for the given type; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<T, T, T> Add => add;
/// <summary>
/// Returns a delegate to evaluate binary subtraction (-) for the given type; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<T, T, T> Subtract => subtract;
/// <summary>
/// Returns a delegate to evaluate binary multiplication (*) for the given type; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<T, T, T> Multiply => multiply;
/// <summary>
/// Returns a delegate to evaluate binary division (/) for the given type; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<T, T, T> Divide => divide;
static readonly Func<T, T, bool> equal, notEqual, greaterThan, lessThan, greaterThanOrEqual, lessThanOrEqual;
/// <summary>
/// Returns a delegate to evaluate binary equality (==) for the given type; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<T, T, bool> Equal => equal;
/// <summary>
/// Returns a delegate to evaluate binary inequality (!=) for the given type; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<T, T, bool> NotEqual => notEqual;
/// <summary>
/// Returns a delegate to evaluate binary greater-then (&gt;) for the given type; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<T, T, bool> GreaterThan => greaterThan;
/// <summary>
/// Returns a delegate to evaluate binary less-than (&lt;) for the given type; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<T, T, bool> LessThan => lessThan;
/// <summary>
/// Returns a delegate to evaluate binary greater-than-or-equal (&gt;=) for the given type; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<T, T, bool> GreaterThanOrEqual => greaterThanOrEqual;
/// <summary>
/// Returns a delegate to evaluate binary less-than-or-equal (&lt;=) for the given type; this delegate will throw
/// an InvalidOperationException if the type T does not provide this operator, or for
/// Nullable&lt;TInner&gt; if TInner does not provide this operator.
/// </summary>
public static Func<T, T, bool> LessThanOrEqual => lessThanOrEqual;
static Operator()
{
add = ExpressionUtil.CreateExpression<T, T, T>(Expression.Add);
subtract = ExpressionUtil.CreateExpression<T, T, T>(Expression.Subtract);
divide = ExpressionUtil.CreateExpression<T, T, T>(Expression.Divide);
multiply = ExpressionUtil.CreateExpression<T, T, T>(Expression.Multiply);
greaterThan = ExpressionUtil.CreateExpression<T, T, bool>(Expression.GreaterThan);
greaterThanOrEqual = ExpressionUtil.CreateExpression<T, T, bool>(Expression.GreaterThanOrEqual);
lessThan = ExpressionUtil.CreateExpression<T, T, bool>(Expression.LessThan);
lessThanOrEqual = ExpressionUtil.CreateExpression<T, T, bool>(Expression.LessThanOrEqual);
equal = ExpressionUtil.CreateExpression<T, T, bool>(Expression.Equal);
notEqual = ExpressionUtil.CreateExpression<T, T, bool>(Expression.NotEqual);
negate = ExpressionUtil.CreateExpression<T, T>(Expression.Negate);
and = ExpressionUtil.CreateExpression<T, T, T>(Expression.And);
or = ExpressionUtil.CreateExpression<T, T, T>(Expression.Or);
not = ExpressionUtil.CreateExpression<T, T>(Expression.Not);
xor = ExpressionUtil.CreateExpression<T, T, T>(Expression.ExclusiveOr);
Type typeT = typeof(T);
if (typeT.GetTypeInfo().IsValueType && typeT.GetTypeInfo().IsGenericType && (typeT.GetGenericTypeDefinition() == typeof(Nullable<>)))
{
// get the *inner* zero (not a null Nullable<TValue>, but default(TValue))
Type nullType = typeT.GetTypeInfo().GenericTypeArguments[0];
zero = (T)Activator.CreateInstance(nullType);
nullOp = (INullOp<T>)Activator.CreateInstance(
typeof(StructNullOp<>).MakeGenericType(nullType));
}
else
{
zero = default(T);
if (typeT.GetTypeInfo().IsValueType)
{
nullOp = (INullOp<T>)Activator.CreateInstance(
typeof(StructNullOp<>).MakeGenericType(typeT));
}
else
{
nullOp = (INullOp<T>)Activator.CreateInstance(
typeof(ClassNullOp<>).MakeGenericType(typeT));
}
}
}
}
}

26
src/ImageProcessorCore/PackedVector/Bgra32.cs

@ -43,14 +43,14 @@ namespace ImageProcessorCore
// The maths are wrong here I just wanted to test the performance to see if the
// issues are caused by the Vector transform or something else.
public void Add(IPackedVector<uint> value)
public void Add(IPackedVector value)
{
}
public void Subtract(IPackedVector value)
{
}
public void Multiply(IPackedVector value)
@ -65,12 +65,12 @@ namespace ImageProcessorCore
public void Divide(IPackedVector value)
{
}
public void Divide(float value)
{
}
/// <summary>
@ -132,11 +132,11 @@ namespace ImageProcessorCore
{
return new[]
{
(byte)(this.PackedValue & 0xFF),
(byte)((this.PackedValue >> 8) & 0xFF),
(byte)((this.PackedValue >> 16) & 0xFF),
(byte)((this.PackedValue >> 24) & 0xFF)
};
(byte)(this.PackedValue & 0xFF),
(byte)((this.PackedValue >> 8) & 0xFF),
(byte)((this.PackedValue >> 16) & 0xFF),
(byte)((this.PackedValue >> 24) & 0xFF)
};
}
/// <inheritdoc/>
@ -178,9 +178,9 @@ namespace ImageProcessorCore
private static uint Pack(ref Vector4 vector)
{
return (uint)Math.Round(vector.X) |
((uint)Math.Round(vector.Y) << 8) |
((uint)Math.Round(vector.Z) << 16) |
((uint)Math.Round(vector.W) << 24);
((uint)Math.Round(vector.Y) << 8) |
((uint)Math.Round(vector.Z) << 16) |
((uint)Math.Round(vector.W) << 24);
}
/// <summary>

24
src/ImageProcessorCore/PackedVector/IPackedVector.cs

@ -31,29 +31,29 @@ namespace ImageProcessorCore
/// </summary>
public interface IPackedVector
{
void Add<U>(U value);
//void Add<U>(U value);
void Subtract<U>(U value);
//void Subtract<U>(U value);
void Multiply<U>(U value);
//void Multiply<U>(U value);
void Multiply(float value);
//void Multiply(float value);
void Divide<U>(U value);
//void Divide<U>(U value);
void Divide(float value);
//void Divide(float value);
//void Add(IPackedVector value);
void Add(IPackedVector value);
//void Subtract(IPackedVector value);
void Subtract(IPackedVector value);
//void Multiply(IPackedVector value);
void Multiply(IPackedVector value);
//void Multiply(float value);
void Multiply(float value);
//void Divide(IPackedVector value);
void Divide(IPackedVector value);
//void Divide(float value);
void Divide(float value);
/// <summary>
/// Sets the packed representation from a <see cref="Vector4"/>.

1
src/ImageProcessorCore/project.json

@ -23,6 +23,7 @@
"System.IO": "4.1.0",
"System.IO.Compression": "4.1.0",
"System.Linq": "4.1.0",
"System.Linq.Expressions": "4.1.0",
"System.Numerics.Vectors": "4.1.1",
"System.Resources.ResourceManager": "4.0.1",
"System.Runtime.Extensions": "4.1.0",

Loading…
Cancel
Save