I'm using the MiscUtils library (thanks Marc G. and Jon S.) and am trying to add a generic Sqrt
function to it. The problem can be easily reproduced with this:
class N<T>
{
public N(T value)
{
Value = value;
}
public readonly T Value;
public static implicit operator T(N<T> n)
{
return n.Value;
}
public static implicit operator N<T>(T value)
{
return new N<T>(value);
}
public static T operator /(N<T> lhs, T rhs)
{
// Operator.Divide is essentially a wrapper around
// System.Linq.Expressions.Expression.Divide
return Operator.Divide(lhs.Value, rhs);
}
}
// fails with: No coercion operator is defined
// between types 'System.Double' and 'N`1[System.Single]'.
var n = new Numeric<float>(1f);
var x = Operator.DivideAlternative(n, 1.0);
// this works as the N<T> is first converted to a
// float via the implicit conversion operator
var result = n / 1.0;
Now, I realize why this is happening, but I have not yet been able to think of a way around it. For reference, here is the current Sqrt
implementation. I have little experience building expression trees.
public static double Sqrt<T>(T value)
{
double oldGuess = -1;
double guess = 1;
while(Abs(guess - oldGuess) > 1)
{
oldGuess = guess;
// the first evaluated call to DivideAlternative throws
guess = Operator.Divide(
Operator.AddAlternative(guess,
Operator.DivideAlternative(value, guess)),
2);
}
return guess;
}
EDIT: Ok, so I solved this on my own, but in an attempt to keep the question as simple as possible I apparently went too far and spent far too much time answering questions from confused people trying to help.
So, this is the problem in its entirety.
I two classes; one that performs transformations and another which performs statistical analysis of image data (pixels). Let's focus on the latter as the problem is the same:
abstract class ImageStatistics
{
private readonly object _pixels;
public ImageStatistics(object pixelArray)
{
Pixels = pixelArray;
}
// calculate the standard deviation of pixel values
public double CalcStdDev();
}
The array of pixels can be any numeric type. In practice, it will be either float
, int
, ushort
, or byte
. Now, because generics cannot do things like this:
public T Add<T>(T lhs, T rhs)
{
return lhs + rhs; // oops, no operator + for T
}
I cannot perform any sort of statistical analyses on the pixel values themselves without casting to the proper array type. So, I need to have N sub-classes of ImageProcessor
to support N pixel types.
Well, that sucks. I would love to just have a generic ImageProcessor<T>
class which has a T[]
of pixel data. So, I looked into the MiscUtils library which would allow just this.
This question was asked 10 years ago; since then, .NET has solved this problem: https://devblogs.microsoft.com/dotnet/dotnet-7-generic-math/
Example:
class N<T> where T: IRootFunctions<T> // interface provided by .NET
{
public required T Value { get; init; }
public void DoWork()
{
var result = T.Sqrt(Value); // Sqrt is available on T
Console.WriteLine(result);
}
}
var myN = new N<float>() { Value = 10 };
myN.DoWork(); // prints 3.1622777
var myN2 = new N<double>() { Value = 10 };
myN2.DoWork(); // prints 3.1622776601683795
Note that int
and decimal
do not implement IRootFunctions<T>
. (Maybe in a future release of .NET...)