polymorphic numeric functions
Brought to you by:
bonniot
I'm not sure if this is a problem with Nice, or a problem
with what I did. Sending it as a bug report let's me
attach the files more easily.
I've tried this with the development nice.jar
The first version (matrix.nice int) multiplies 2 int arrays,
and works fine.
I tried (various ways) to change it to work with 2 arrays
of any primitive numeric type, but get the wrong answer
0 0 0 0
Logged In: YES
user_id=88952
The problem is that the JVM does not allow to use int[]
where double[] is expected (and of course it does not have
type parameters).
So what happens is that nicec compiles mmult as taking
parameters of type double[][]. If you can it with int[][],
the array is first copied into a double[][]. This works okay
if you just read from the array. But if you write, you of
course write in the copy, and the change is lost after you
return from the function.
You can look at the bytecode generated t osee it for yourself.
Knowing this, you could change your code, so that mmult
creates the result array. In that case, it would be
converted to int[][] at the return of the call, so the
semantic would be correct. This would mean allocating a
result matrix for each call (but the polymorphic code also
does that implicitely, by copying).
If you intend to submit to shootout, you should probably
consider the monomorphic int version.
Of course this does not solve the issue for Nice. I think
the current behaviour is not acceptable. Since there is a
limited number of primitive types, a possibility would be to
generate several instances of the polymorphic function, one
for T=double, one for T=float, ...
That would probably be the best for efficiency, since it
would be similar to monomorphic code.
Another possibility is to treat int[][] and double[][] as
Object[]. Then it is possible to use the methods in
java.lang.reflect.Array to access the array.
That would probably be slower, but also easier to implement.
Would you be able to do some benchmarks on the
java.lang.reflect.Array, so we know how much slower they
are? Is it 10%? 10x?
I cannot guarantee when this will be fixed. It depends if
somebody is interested to look into that, or if I find the
time for it. Having some benchmarks would be a good start to
make decisions.
Logged In: YES
user_id=536291
>Would you be able to do some benchmarks
maybe I'll look into that
I'm starting to appreciate how much work you (as compiler
writer) have to do to work around JVM limitations.
Logged In: YES
user_id=88952
I did some investigation about java.lang.reflect.Array, and
it seems that we cannot use it for this purpose:
Array.setLong(array, 0, someLong)
will fail at runtime if array is not of type double[].
It would work to use
Array.set(array, 0, numericValue)
if numeric value is a Number object. But then it would
basically mean doing all the computations on wrapped
numbers, which would be catastrophic for performance.
At this point, it seems that duplication of code for the
several type cases (always a few, since we are dealing with
primitive types here) would be the best option. It would
allow to preserve the semantics, and it would have perfect
performance (as good as the monomorphic version).
It's also more work of course, as I said before.