1

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.

Ed S.
  • 122,712
  • 22
  • 185
  • 265
  • 4
    Math.Sqrt() takes about 5 nanoseconds. This code ... doesn't. – Hans Passant Jul 24 '13 at 02:48
  • 1
    @IgbyLargeman I'm not sure who the 1st and 2nd parties are (the poster and Stack Exchange?), but this question is just as legitimate as one about, say, the .NET Framework, a notable "third party library"... – AakashM Jul 24 '13 at 08:02
  • @HansPassant: I'm not overly concerned about performance at the moment, I just want to get it working. I can worry about that later. My current use case is to call this once after aggregating a lot of other statistics. One call to this isn't going to come anywhere near the time it takes to prepare the data. I don't plan on releasing this to the general public. – Ed S. Jul 24 '13 at 17:07
  • 4
    @IgbyLargeman: Seriously? Not sure where you got that idea. If questions which refer to a third party library aren't allowed on SO then I suppose you have millions of questions to hunt down and close. What's your definition of "third party" here? Anything that is not in the standard library of a language? – Ed S. Jul 24 '13 at 17:07
  • What's the square root of a `string`? Or a `DateTime`? I don't think the idea is a good fit for generics. You would need type constraints that aren't easy to express. – Matt Johnson-Pint Jul 24 '13 at 19:28
  • @MattJohnson: I don't care about that case. Generic math is certainly a good fit for generics. Unfortunately, C#'s generics implementation is not a good fit for generic math. This is the closest we can get.This code works with any type which exposes mathematical operators. A string or DateTime would rightfully throw an exception at runtime. Anyone who is in this code will know full well that it would make 0 sense to pass in a string. Please, I appreciate the attempt at giving me advice, but I assure you that the request itself is not ill-conceived. – Ed S. Jul 24 '13 at 21:04
  • @MattJohnson: I understand the problem at hand, I just need to know if the solution is possible. Having a generic math library (as you could easily have in, say, C++) would cut out 2/3 of a code base I am working on. Lot's of redundant code processing pixel arrays where the only difference between each method is the type of the array (int, byte, ushort, or float). You cannot constrain a generic type to a numeric type which supports mathematical operators in C#. The closest you can get is `struct`, which isn't enough. If you have a better idea I am all ears. – Ed S. Jul 24 '13 at 21:04
  • I'm digging a bit deeper into your question, and I am a bit confused about what you are asking. Are you just wanting to know how to work around the exception? Or are you looking for a different `Sqrt` method than the one you provided? If the latter, what is the signature of the function you're expecting? – Matt Johnson-Pint Jul 24 '13 at 21:24
  • @MattJohnson: I know that my Sqrt method is going to have to change because it simply doesn't work right now. Unfortunately, I need to spend some time studying up on expression trees. The problem with my current implementation is that no conversion exists from double to `N`. If I passed in an `N` the code would work fine because I have defined an implicit conversion from `T` to `N`. So, I figured I would post here and work on something more pressing for the moment, but I will have to come back to this soon. – Ed S. Jul 24 '13 at 21:28
  • @MattJohnson: I need a generic `Sqrt` function. Input can be anything that defines operators / and +, but in practice, the input will be limited to numerical primitives. – Ed S. Jul 24 '13 at 21:28
  • I am probably missing something but if you are jsut wanting to use primitive numeric types why aren't you just taking advantage of the fact there are implicit conversions in general between the numeric types? Though I have to admit I'm not sure I see what the point of your `N` class is... – Chris Jul 24 '13 at 21:43
  • @Chris: So, the background here is that I am converting a bunch of code from a public domain library to C#. They currently have four classes which do extremely similar things. The difference is that they operate on different types (float, int, byte, ushort). You simply cannot make this generic in C# without something like the above because the second you try to write `Add(T lhs, T rhs)` it will blow up because there is no guarantee that both types implement an appropriate operator+. So, you need four functions, one for each different type of array. – Ed S. Jul 24 '13 at 21:47
  • @Chris: Take this for example; `var pixels = x.Pixels; var sqrt = Math.Sqrt(pixels[0]);`. `pixels` could be any of; `int[]`, `float[]`, `byte[]`, or `ushort[]`. The problem essentially boils down to that. Of course, there is no suitable generic constraint to allow for it. If I can solve that then I can implement the rest. Currently, there are four implementations, one for each type. – Ed S. Jul 24 '13 at 21:52
  • @Chris: And, of course, I am open to entirely different approaches. – Ed S. Jul 24 '13 at 21:54
  • @Chris: Oh, and that `N` class is a heavily trimmed down example. It is a generic wrapper for numeric types. It implements all of the binary and unary operators needed to work with any other type which also implements them via the Expression API. – Ed S. Jul 24 '13 at 22:01
  • @EdS.: Thanks for the explanation. I think I see the problem a bit better now but sadly I can't think of a solution either. Thanks for taking the time to explain though. Its an interesting problem... – Chris Jul 25 '13 at 08:43

4 Answers4

1

Math.Sqrt needs a double, so why not just provide it with one?

public static double Sqrt<T>(T value)
{
    return Math.Sqrt(Convert.ToDouble(value));
}

You might also consider casting to dynamic.

public static double Sqrt<T>(T value)
{   
    return Math.Sqrt((dynamic) value);
}

This technique can also be used for operators like addition:

public static T Add<T>(T a, T b)
{
    return (dynamic) a + (dynamic) b;
}
Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
0

Console application creating array of objects (unknown types) and calculating square route (double)

using System;

namespace GenericSqrt
{
    class Program
    {
        static void Main(string[] args)
        {
            var array = new object[] { "2", null, 4.1f, 4.444D, "11.3", 0, "Text", new DateTime(1, 1, 1) };

            foreach (var value in array)
            {
                try
                {
                    Console.WriteLine(Sqrt(value));
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
            Console.ReadLine();
        }

        private static double Sqrt(object value)
        {
            double converterValue = Convert.ToDouble(value);
            return Math.Sqrt(converterValue);
        }
    }
}

Output looks like this:

1.4142135623731
0
2.02484564958235
2.10807969488822
3.36154726279432
0
Input string was not in a correct format.
Invalid cast from 'DateTime' to 'Double'.

If type is indeed any of number types, as you stated, there is no problem to solve.

Nenad
  • 24,809
  • 11
  • 75
  • 93
  • It's just boxing the value and doing the exact same thing I posted an hour ago in my answer to convert it to a double. So, thanks... but I already thought of that. You're right about one thing though; I was making this more complicated than it needed to be. – Ed S. Jul 24 '13 at 22:57
  • Where is your code that converts object to specific type? I think you're actually creating problem trying to use generics where you don't need them at all. Your output type is always constant - double. – Nenad Jul 24 '13 at 23:01
  • It's in an answer, not the question. I think I made a mistake in trying to simplify the scenario here and went too far. Considering the way in which I initially phrased the question, your answer is the best. I added some more info to the question just now. I really do need generic types here to avoid duplicating code in four classes. What I do *not* need is that `N` type at all. I got all focused in on wrapping numeric types when there was no need to. I should (am, now) just use the MiscUtils operators in `ImageProcessor` and forego the stupid `N` stuff. – Ed S. Jul 24 '13 at 23:03
  • Maybe your choosing wrong tool for the problem you have? Tool should simplify problem, not make it more complicated. – Nenad Jul 24 '13 at 23:08
  • Well, a wrapper around numerics types would allow for a nicer syntax. Instead of `Operator.Subtract(x, y)` you can just use `x - y`. However, it gets complicated when there are attempted conversions from, say, `double` to `N`. `double` to `N` is fine, but anything else will fail. I can fix that, but IMO it's too much converting back and forth for a nicer syntax. However, again, generics are not the problem here. If you can think of a way to create one class which can analyze any type of pixel data without using generics than I would love to hear it. – Ed S. Jul 24 '13 at 23:12
  • Everything is convertible to double, so convert object to double, perform analysis and you're done. Your analysis result is double anyway. No need for anything fancy here. – Nenad Jul 24 '13 at 23:17
  • Again, you're focusing only on Sqrt... that was an example. I'm analyzing huge images here, converting every value to a double at all times just to add, multiple, divide, and subtract would be a massive waste. If I were just going to convert everything to a double then I may as well just take an array of double and be done with it. Another detail I probably should have thrown out there to begin with. – Ed S. Jul 24 '13 at 23:22
  • Of course you should convert it once, not on each operation. Could be additional field of your non-generic ImageProcessor class. Array of doubles? Yes, why not? What are you actually achieving using generic operators? – Nenad Jul 25 '13 at 01:06
  • I have 3+GB images here, so thats's millions and millions of conversions. Please stop focusing on Sqrt, it's more than that. It's every possible mathematical operator. The data itself is an array of pixels coming from an image which could be in one of four formats (possibly more in the future). The images are scans of tissue which are uploaded to the analysis server, analyzed, and then the results reviewed by a doctor. The longer it takes the more time the doc will be waiting for a report. So, while I *could* convert everything to a double and perform FP arithmetic, I would prefer not to. – Ed S. Jul 25 '13 at 04:04
  • If you receive array - object[], you have to determine type to convert it to generic class, yes? You're doing conversions anyway and everything from that point is more expensive, since use of generic class is heavier then use built-in simple type. – Nenad Jul 25 '13 at 06:53
0

Let me preface this by saying it probably isn't worth the effort, considering how this code would need to be maintained. I wrote this in about 10 minutes, so don't expect anything too spectacular.

// You'll need this
public interface ISquareRootHelper
{
    double Sqrt<T>(T value)
        where T : struct;
}

class Program
{
    private static ISquareRootHelper helper; 

    // Build the helper
    public static void BuildSqrtHelper()
    {
        // Let's use a guid for the assembly name, because guid!
        var assemblyName = new AssemblyName(Guid.NewGuid().ToString());

        // Blah, blah, boiler-plate dynamicXXX stuff
        var dynamicAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
        var dynamicModule = dynamicAssembly.DefineDynamicModule(assemblyName.Name);
        var dynamicType = dynamicModule.DefineType("SquareRootHelper");

        // Let's create our generic square root method in our dynamic type
        var sqrtMethod = dynamicType.DefineMethod("Sqrt", MethodAttributes.Public | MethodAttributes.Final | MethodAttributes.Virtual);
        sqrtMethod.SetReturnType(typeof(double));

        // Well, I guess here is where we actually make the method generic
        var genericParam = sqrtMethod.DefineGenericParameters(new[] {"T"});
        genericParam[0].SetGenericParameterAttributes(GenericParameterAttributes.NotNullableValueTypeConstraint);

        // Add a generic parameter, and set it to override our interface method
        sqrtMethod.SetParameters(genericParam);
        dynamicType.DefineMethodOverride(sqrtMethod, typeof(ISquareRootHelper).GetMethod("Sqrt"));

        // Magic sauce!
        var ilGenerator = sqrtMethod.GetILGenerator();

        // Math.Sqrt((double)value);
        ilGenerator.Emit(OpCodes.Ldarg_1); // arg_0 is this*
        ilGenerator.Emit(OpCodes.Conv_R8);

        var mathSqrtMethodInfo = typeof(Math).GetMethod("Sqrt");
        ilGenerator.EmitCall(OpCodes.Call, mathSqrtMethodInfo, null);

        ilGenerator.Emit(OpCodes.Ret);

        // Since we're overriding the interface method, we need to have the type
        // implement the interface
        dynamicType.AddInterfaceImplementation(typeof(ISquareRootHelper));

        // Create an instance of the class
        var sqrtHelperType = dynamicType.CreateType();
        helper = (ISquareRootHelper)Activator.CreateInstance(sqrtHelperType);
    }

    public static void Main(string[] args)
    {
        BuildSqrtHelper();

        Console.WriteLine(helper.Sqrt((short)64));    // Works!
        Console.WriteLine(helper.Sqrt((ushort)64));   // Works!
        Console.WriteLine(helper.Sqrt((int)64));      // Works!
        Console.WriteLine(helper.Sqrt((uint)64));     // Works*!
        Console.WriteLine(helper.Sqrt((byte)64));     // Works!
        Console.WriteLine(helper.Sqrt((sbyte)64));    // Works!
        Console.WriteLine(helper.Sqrt((float)64));    // Works!
        Console.WriteLine(helper.Sqrt((double)64));   // Works!
        Console.WriteLine(helper.Sqrt((long)64));     // Works!
        Console.WriteLine(helper.Sqrt((ulong)64));    // Works*!

        // Let's try non-primitives!
        Console.WriteLine(helper.Sqrt(DateTime.Now)); // Doesn't fail, but doesn't actually work
        Console.WriteLine(helper.Sqrt(Guid.NewGuid())); // InvalidProgramException!
    }
}

Anyway, I guess this proves it can be done. Just make sure when you use it, you only pass in primitive types, otherwise all fail will break loose. Actually, it will only throw an exception when you pass in a struct that is a greater size that 8 bytes, since that will unbalance the stack. You can't do a check like sizeof(T) in the method though, because it would fail during the JITing process.

Also, there are some *s next to some of the types up there. There is some extra logic done by the compiler and/or Math.Sqrt when you pass in unsigned numbers vs signed numbers, and how this related to negative numbers. For example:

Console.WriteLine(Math.Sqrt(unchecked((uint)-2)));   // 65535.9999847412
Console.WriteLine(helper.Sqrt(unchecked((uint)-2))); // NaN :(

You could improve it and checks above to catch that, though. Also, I don't recommend this solution, especially if you're not comfortable with IL. Plus, this is probably more verbose and complicated than just writing a bunch of different methods to handle the operations you want.

Christopher Currens
  • 29,917
  • 5
  • 57
  • 77
  • Yeah... the Sqrt function (as well as add, mul, div, sub, etc.) will be performed millions and millions of times. Reflection is probably a bad idea. I'd stick with the four classes approach. It can be done in a more simple way, I posted the answer a while back. After going back and forth I think I'm better off abandoning the silly wrapper type altogether and just using MiscUtil's Operator within ImageProcessor itself. I lose the nice syntax of operators, but it keeps things simple and flexible. – Ed S. Jul 25 '13 at 04:06
  • Well, I'm still not really condoning the above, but the reflection only happens one time. Basically, what you want done is possible in the .NET runtime, but not C#. I'm generating the class and code at runtime that you need to get what you want done. It's building the type and method one time, then you're calling it as if you have compiled the class in code, so it's almost as fast as if you were able to write it out in C#. There is a minor performance loss, due to it being dynamic and that it can't be inlined, but we're likely talking about microseconds. – Christopher Currens Jul 25 '13 at 06:36
-1

This works, but it's a bit ugly:

public static implicit operator Numeric<T>(double value)
{
    return new Numeric<T>((T)Convert.ChangeType(value, typeof(T)));
}

public static implicit operator double(Numeric<T> n)
{
    return Convert.ToDouble(n.Value);           
}

It will have to be repeated for each supported type, which makes this a lot less generic. I slapped an IConvertible constraint on there for good measure. If anyone has a better solution I'm all ears.

Ed S.
  • 122,712
  • 22
  • 185
  • 265
  • 1
    Downvoter, explain please. This is the only answer that actually solves the original problem. – Ed S. Jul 24 '13 at 23:03