Github user jkbradley commented on a diff in the pull request: https://github.com/apache/spark/pull/2451#discussion_r17803218 --- Diff: mllib/src/main/scala/org/apache/spark/mllib/linalg/Matrices.scala --- @@ -57,13 +250,709 @@ trait Matrix extends Serializable { * @param numCols number of columns * @param values matrix entries in column major */ -class DenseMatrix(val numRows: Int, val numCols: Int, val values: Array[Double]) extends Matrix { +class DenseMatrix(val numRows: Int, val numCols: Int, val values: Array[Double]) extends Matrix with Serializable { - require(values.length == numRows * numCols) + require(values.length == numRows * numCols, "The number of values supplied doesn't match the " + + s"size of the matrix! values.length: ${values.length}, numRows * numCols: ${numRows * numCols}") override def toArray: Array[Double] = values - private[mllib] override def toBreeze: BM[Double] = new BDM[Double](numRows, numCols, values) + private[mllib] def toBreeze: BM[Double] = new BDM[Double](numRows, numCols, values) + + private[mllib] def apply(i: Int): Double = values(i) + + private[mllib] def apply(i: Int, j: Int): Double = values(index(i, j)) + + private[mllib] def index(i: Int, j: Int): Int = i + numRows * j + + private[mllib] def update(i: Int, j: Int, v: Double): Unit = { + values(index(i, j)) = v + } + + override def copy = new DenseMatrix(numRows, numCols, values.clone()) + + private[mllib] def elementWiseOperateOnColumnsInPlace( + f: (Double, Double) => Double, + y: Matrix): DenseMatrix = { + val y_vals = y.toArray + val len = y_vals.length + require(y_vals.length == numRows) + var j = 0 + while (j < numCols){ + var i = 0 + while (i < len){ + val idx = index(i, j) + values(idx) = f(values(idx), y_vals(i)) + i += 1 + } + j += 1 + } + this + } + + private[mllib] def elementWiseOperateOnRowsInPlace( + f: (Double, Double) => Double, + y: Matrix): DenseMatrix = { + val y_vals = y.toArray + require(y_vals.length == numCols) + var j = 0 + while (j < numCols){ + var i = 0 + while (i < numRows){ + val idx = index(i, j) + values(idx) = f(values(idx), y_vals(j)) + i += 1 + } + j += 1 + } + this + } + + private[mllib] def elementWiseOperateInPlace(f: (Double, Double) => Double, y: Matrix): DenseMatrix = { + val y_val = y.toArray + val len = values.length + require(y_val.length == values.length) + var j = 0 + while (j < len){ + values(j) = f(values(j), y_val(j)) + j += 1 + } + this + } + + private[mllib] def elementWiseOperateScalarInPlace(f: (Double, Double) => Double, y: Double): DenseMatrix = { + var j = 0 + val len = values.length + while (j < len){ + values(j) = f(values(j), y) + j += 1 + } + this + } + + private[mllib] def operateInPlace(f: (Double, Double) => Double, y: Matrix): DenseMatrix = { + if (y.numCols==1 || y.numRows == 1){ + require(numCols != numRows, "Operation is ambiguous. Please use elementWiseOperateOnRows " + + "or elementWiseOperateOnColumns instead") + } + if (y.numCols == 1 && y.numRows == 1){ + elementWiseOperateScalarInPlace(f, y.toArray(0)) + } else { + if (y.numCols==1) { + elementWiseOperateOnColumnsInPlace(f, y) + }else if (y.numRows==1){ + elementWiseOperateOnRowsInPlace(f, y) + }else{ + elementWiseOperateInPlace(f, y) + } + } + } + + private[mllib] def elementWiseOperateOnColumns(f: (Double, Double) => Double, y: Matrix): DenseMatrix = { + val dup = this.copy + dup.elementWiseOperateOnColumnsInPlace(f, y) + } + + private[mllib] def elementWiseOperateOnRows(f: (Double, Double) => Double, y: Matrix): DenseMatrix = { + val dup = this.copy + dup.elementWiseOperateOnRowsInPlace(f, y) + } + + private[mllib] def elementWiseOperate(f: (Double, Double) => Double, y: Matrix): DenseMatrix = { + val dup = this.copy + dup.elementWiseOperateInPlace(f, y) + } + + private[mllib] def elementWiseOperateScalar(f: (Double, Double) => Double, y: Double): DenseMatrix = { + val dup = this.copy + dup.elementWiseOperateScalarInPlace(f, y) + } + + private[mllib] def operate(f: (Double, Double) => Double, y: Matrix): DenseMatrix = { + val dup = this.copy + dup.operateInPlace(f, y) + } + + def map(f: Double => Double) = new DenseMatrix(numRows, numCols, values.map(f)) + + def update(f: Double => Double): DenseMatrix = { + val len = values.length + var i = 0 + while (i < len) { + values(i) = f(values(i)) + i += 1 + } + this + } + + def colNorms(p: Double): DenseMatrix = { + if (p==1.0) return colSums(true) + val sums = new DenseMatrix(1, numCols, Array.fill(numCols)(0.0)) + var j = 0 + while (j < numCols){ + var i = 0 + while (i < numRows){ + val idx = index(i, j) + sums.update(0,j, sums(j) + math.pow(values(idx),p)) + i += 1 + } + j += 1 + } + j = 0 + while (j < numCols){ + sums.update(0, j, math.pow(sums(j), 1/p)) --- End diff -- "1/p" --> "1 / p"
--- If your project is set up for it, you can reply to this email and have your reply appear on GitHub as well. If your project does not have this feature enabled and wishes so, or if the feature is enabled but not working, please contact infrastructure at infrastruct...@apache.org or file a JIRA ticket with INFRA. --- --------------------------------------------------------------------- To unsubscribe, e-mail: reviews-unsubscr...@spark.apache.org For additional commands, e-mail: reviews-h...@spark.apache.org