Why is it illegal to call mean on this 3x2 matrix of doubles in Scala Breeze?

599 Views Asked by At

I am new to Breeze (formerly Scalala), and can't figure out why the following simple program throws an exception. i am using Scala 2.9.2 and Breeze 0.1:

import breeze.linalg._
val m = DenseMatrix((3.0, 1.0, 2.0), (-2.0, 1.0, 3.0))
val n = mean(m, Axis._1)

It works as expected if I use a 2x2 or a 3x2 matrix, but a 2x3 matrix causes the following exception:

-- org.jblas ERROR Couldn't load copied link file: java.lang.UnsatisfiedLinkError: C:\Users\daved\AppData\Local\Temp\jblas8588491482847885553jblas.dll: Can't find dependent libraries.

Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 6
    at breeze.linalg.package$$anon$1.apply$mcD$sp(package.scala:203)
    at breeze.linalg.package$$anon$1.apply(package.scala:196)
    at breeze.linalg.package$$anon$1.apply(package.scala:186)
    at breeze.linalg.DenseVector.ureduce(DenseVector.scala:91)
    at breeze.linalg.Tensor$$anon$1.apply(Tensor.scala:149)
    at breeze.generic.UReduceable$class.apply$mcD$sp(URFunc.scala:56)
    at breeze.linalg.Tensor$$anon$1.apply$mcD$sp(Tensor.scala:148)
    at breeze.generic.URFunc$mcD$sp$class.apply$mcD$sp(URFunc.scala:32)
    at breeze.linalg.package$$anon$1.apply$mcD$sp(package.scala:186)
    at breeze.generic.URFunc$mcD$sp$$anonfun$apply$mcD$sp$1.apply(URFunc.scala:36)
    at breeze.linalg.LowPriorityDenseMatrix1$$anon$17.apply(DenseMatrix.scala:444)
    at breeze.linalg.LowPriorityDenseMatrix1$$anon$17.apply(DenseMatrix.scala:440)
    at breeze.generic.URFunc$mcD$sp$class.apply$mcD$sp(URFunc.scala:36)
    at breeze.linalg.package$$anon$1.apply$mcD$sp(package.scala:186)
    at com.tennisedge.opencv.BreezePlay$delayedInit$body.apply(BreezePlay.scala:24)
2

There are 2 best solutions below

4
On

This is a perfect example (referring to this) of the problem with exceptions thrown in constructors! What is masquerading as a dependency problem is really an ArrayIndexOutOfBoundsException that was encountered in a constructor that was called during on-demand class loading. It's often very perplexing. (This is my "favorite" (most infamous) consequence of throwing exceptions in constructors.)

At least that's what it appears to be to me. I can't be sure, really.

0
On

I believe this is a bug in Breeze. In particular, the DenseMatrix canCollapseCols implicit conversion.

If I define my own implicit conversion in the local file, everyting works as expected:

implicit def myCanCollapseCols[V, R:ClassManifest] = new CanCollapseAxis[DenseMatrix[V], Axis._1.type, DenseVector[V], R, DenseVector[R]] {
  def apply(from: DenseMatrix[V], axis: Axis._1.type)(f: (DenseVector[V]) => R): DenseVector[R] = {
    val result = DenseVector.zeros[R](from.rows)
    val t = from.t
    for(r <- 0 until t.cols) { // BUG WAS HERE: was from.cols in original defintion.
      result(r) = f(t(::, r))
    }
    result
  }
}

val m = breeze.linalg.DenseMatrix((3.0, 1.0, 2.0), (-2.0, 1.0, 3.0))
val n = breeze.linalg.mean(m, breeze.linalg.Axis._1)

This is still there in head, so I will create a pull request for it in GitHub to fix. In the meantime I can just use my own implicit conversion.