Dominick,
On Dec 27, 2010, at 11:56 PM, Dominick Samperi wrote:
> After some trial and error I figured out how to pass matrices from R to
java
> and back using rJava, but this method is not documented and I wonder if
there is a
> better way?
>
stats-rosuda-devel is the rJava list you want to use.
> Anyway, here is what I found works:
>
> (m = matrix(as.double(1:12),3,4))
> [shows m as you would expect]
>
> jtest <- .jnew("JTest")
> (v <- .jcall(jtest, '[[D], 'myfunc', .jarray(m),
evalArray=FALSE))
> [shows v = m + 10]
>
> Here the JTest class has a method named myfunc that accepts
> a double[][] and returns a double[][]. It simply adds 10 to every
> element.
>
The above is plain wrong (well, that's actually a guess since you didn't
provide even the signature of the method) - matrices in R are vectors, so the
type is double[]. In Java there is no matrix type, so it's up to the
application to represent matrices and there are many ways - some more efficient
than others. From your example above it seems that you are using double[][] --
so you have to allocate the extra objects one way or another (that's why
it's inefficient to represent matrices that way).
But from your e-mail I have the feeling that your questions is rather about
calling a method that returns double[][], so for example:
public static double[][] pass();
where double[][] is a rectangular array (i.e. length of all inner arrays is
equal).
Unfortunately .jcall is a bit inconsistent due to bug that was introduced with
the new J() API. So the intended behavior is (using class Test with the method
above):> J("Test")$pass()
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 5 6 7 8
[3,] 9 10 11 12
[4,] 13 14 15 16
The $ operator makes sure that the result is converted to a native R form where
possible, including recursive structures like double[][].
However, the intention of .jcall() was to never perform recursive evaluation, so
this is intended:
> .jcall("Test","[[D","pass", evalArray=TRUE)
[[1]]
[1] "Java-Array-Object[D:[D at 11ddcde"
[[2]]
[1] "Java-Array-Object[D:[D at 18fb1f7"
[[3]]
[1] "Java-Array-Object[D:[D at ed0338"
[[4]]
[1] "Java-Array-Object[D:[D at 6e70c7"
The intended behavior (and true in older version of rJava) was for .jcall with
evalArray=FALSE to return the reference:
> .jcall("Test","[[D","pass", evalArray=FALSE)
[1] "Java-Array-Object[[D:[[D at 8f4fb3"
Unfortunately, the bug is that .jcall uses rJava:::newArray() to create the
reference which defaults to simplify=TRUE so the current (buggy) behavior is:
> .jcall("Test","[[D","pass", evalArray=FALSE)
[,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 5 6 7 8
[3,] 9 10 11 12
[4,] 13 14 15 16
The real issue is that:
a) if the bug is fixed, .jcall() can return just the reference which is intended
but
b) there is currently no exposed API for rJava:::newArray so the simplification
is not available in any form for references if the bug is fixed (other than
using the J/$ API).
That's why I was hesitant so far to fix the bug, but I really should --
which is why the behavior your discovered will change. However, then I need to
add some API to be able to convert a reference in the same way that
rJava:::newArray provides and expose it - I didn't think through that part,
so that's why I got stuck.
I hope it helps...
Cheers,
Simon
(PS: please continue any discussion on stats-rosuda-devel)
> The parameter 'evalArray' is confusing because when
> evalArray=TRUE the result is NOT evaluated (a list is returned
> that you then have to apply .jevalArray to do get the answer).
>
> There seems to be an option to have a java reference returned
> instead of the actual matrix. Can the R side manipulate the
> matrix (on the java side) through this reference?
>
> Thanks,
> Dominick
>
> [[alternative HTML version deleted]]
>
> ______________________________________________
> R-devel at r-project.org mailing list
> https://stat.ethz.ch/mailman/listinfo/r-devel
>
>