Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
breeze.linalg.SliceMatrix.scala Maven / Gradle / Ivy
package breeze.linalg
import breeze.linalg.operators.OpSet
import breeze.linalg.support.CanTraverseKeyValuePairs.KeyValuePairsVisitor
import breeze.linalg.support.CanTraverseValues.ValuesVisitor
import breeze.linalg.support._
import breeze.math.Semiring
import breeze.storage.Zero
import spire.syntax.cfor.cforRange
import scala.reflect.ClassTag
class SliceMatrix[@specialized(Int) K1,
@specialized(Int) K2,
@specialized(Double, Int, Float, Long) V:Semiring:ClassTag](val tensor: Tensor[(K1, K2),V],
val slice1: IndexedSeq[K1],
val slice2: IndexedSeq[K2])
extends Matrix[V] with MatrixLike[V, SliceMatrix[K1, K2, V]] {
def apply(i: Int, j: Int): V = tensor(slice1(i)->slice2(j))
def update(i: Int, j: Int, e: V) {tensor(slice1(i)->slice2(j)) = e}
def rows: Int = slice1.length
def cols: Int = slice2.length
def activeValuesIterator: Iterator[V] = valuesIterator
def activeIterator: Iterator[((Int, Int), V)] = iterator
def activeKeysIterator: Iterator[(Int, Int)] = keysIterator
def activeSize: Int = size
def repr: SliceMatrix[K1, K2, V] = this
def copy: Matrix[V] = {
if (rows == 0) Matrix.zeroRows[V](cols)
else if (cols == 0) Matrix.zeroCols[V](rows)
else {
val result = new DenseMatrix[V](rows, cols, new Array[V](size))
result := (this:Matrix[V])
result
}
}
def flatten(view: View=View.Copy): Vector[V] = {
view match {
case View.Require => throw new UnsupportedOperationException("Cannot make Vector as view of SliceMatrix.")
case View.Copy =>
val vb = new VectorBuilder[V](rows*cols,activeSize)
val ai = activeIterator
while (ai.hasNext) {
val ((r,c),v) = ai.next()
vb.add(c*rows+r,v)
}
vb.toVector
case View.Prefer => flatten(View.Copy)
}
}
}
object SliceMatrix extends LowPrioritySliceMatrix with SliceMatrixOps {
implicit def canMapKeyValuePairs[K1, K2, V, V2: ClassTag: Zero]: CanMapKeyValuePairs[SliceMatrix[K1, K2, V], (Int, Int), V, V2, DenseMatrix[V2]] = {
new CanMapKeyValuePairs[SliceMatrix[K1, K2, V], (Int, Int), V, V2, DenseMatrix[V2]] {
override def map(from: SliceMatrix[K1, K2, V], fn: ((Int, Int), V) => V2): DenseMatrix[V2] = {
DenseMatrix.tabulate(from.rows, from.cols)((i, j) => fn((i, j), from(i, j)))
}
override def mapActive(from: SliceMatrix[K1, K2, V], fn: ((Int, Int), V) => V2): DenseMatrix[V2] = {
map(from, fn)
}
}
}
implicit def canMapValues[K1, K2, @specialized(Int, Float, Double) V, @specialized(Int, Float, Double) V2: ClassTag: Zero]: CanMapValues[SliceMatrix[K1, K2, V], V, V2, DenseMatrix[V2]] = {
new CanMapValues[SliceMatrix[K1, K2, V], V, V2, DenseMatrix[V2]] {
override def apply(from: SliceMatrix[K1, K2, V], fn: (V) => V2): DenseMatrix[V2] = {
DenseMatrix.tabulate(from.rows, from.cols)((i, j) => fn(from(i, j)))
}
}
}
implicit def canCreateZerosLike[K1, K2, V: ClassTag : Zero]: CanCreateZerosLike[SliceMatrix[K1, K2, V], DenseMatrix[V]] = {
new CanCreateZerosLike[SliceMatrix[K1, K2, V], DenseMatrix[V]] {
def apply(v1: SliceMatrix[K1, K2, V]): DenseMatrix[V] = {
DenseMatrix.zeros[V](v1.rows, v1.cols)
}
}
}
implicit def canIterateValues[K1, K2, V]: CanTraverseValues[SliceMatrix[K1, K2, V], V] =
new CanTraverseValues[SliceMatrix[K1, K2, V], V] {
def isTraversableAgain(from: SliceMatrix[K1, K2, V]): Boolean = true
/** Iterates all key-value pairs from the given collection. */
def traverse(from: SliceMatrix[K1, K2, V], fn: ValuesVisitor[V]): Unit = {
from.activeValuesIterator foreach {
fn.visit(_)
}
}
}
implicit def canIterateKeyValuePairs[K1, K2, V]: CanTraverseKeyValuePairs[SliceMatrix[K1, K2, V], (Int, Int), V] = {
new CanTraverseKeyValuePairs[SliceMatrix[K1, K2, V], (Int, Int), V] {
/** Traverses all values from the given collection. */
override def traverse(from: SliceMatrix[K1, K2, V], fn: KeyValuePairsVisitor[(Int, Int), V]): Unit = {
from.iterator foreach {
case (k, v) => fn.visit(k, v)
}
}
def isTraversableAgain(from: SliceMatrix[K1, K2, V]): Boolean = true
}
}
implicit def canTransformValues[K1, K2, V]: CanTransformValues[SliceMatrix[K1, K2, V], V] = {
new CanTransformValues[SliceMatrix[K1, K2, V], V] {
def transform(from: SliceMatrix[K1, K2, V], fn: (V) => V) {
for (j <- 0 until from.cols; i <- 0 until from.rows) {
from(i, j) = fn(from(i, j))
}
}
def transformActive(from: SliceMatrix[K1, K2, V], fn: (V) => V) {
transform(from, fn)
}
}
}
// slices
implicit def canSliceRow[K1, K2, V: Semiring : ClassTag]: CanSlice2[SliceMatrix[K1, K2, V], Int, ::.type, Transpose[SliceVector[(K1, K2), V]]] = {
new CanSlice2[SliceMatrix[K1, K2, V], Int, ::.type, Transpose[SliceVector[(K1, K2), V]]] {
def apply(from: SliceMatrix[K1, K2, V], sliceRow: Int, ignored: ::.type): Transpose[SliceVector[(K1, K2), V]] = {
val row = SliceUtils.mapRow(sliceRow, from.rows)
val k1: K1 = from.slice1(row)
new SliceVector(from.tensor, from.slice2.map(k1 -> _)).t
}
}
}
implicit def canSliceCol[K1, K2, V: Semiring : ClassTag]: CanSlice2[SliceMatrix[K1, K2, V], ::.type, Int, SliceVector[(K1, K2), V]] = {
new CanSlice2[SliceMatrix[K1, K2, V], ::.type, Int, SliceVector[(K1, K2), V]] {
def apply(from: SliceMatrix[K1, K2, V], ignored: ::.type, sliceCol: Int): SliceVector[(K1, K2), V] = {
val col = SliceUtils.mapColumn(sliceCol, from.cols)
val k2: K2 = from.slice2(col)
new SliceVector(from.tensor, from.slice1.map(_ -> k2))
}
}
}
}
trait LowPrioritySliceMatrix { this: SliceMatrix.type =>
// Note: can't have a separate implicit for Range and Seq since they will be ambiguous as both will return a
// SliceMatrix which differs from dense matrix where a Range will return another DenseMatrix and only a seq will
// return a SliceMatrix
implicit def canSliceWeirdRows[K1, K2, V: Semiring : ClassTag]: CanSlice2[SliceMatrix[K1, K2, V], Seq[Int], ::.type, SliceMatrix[K1, K2, V]] = {
new CanSlice2[SliceMatrix[K1, K2, V], Seq[Int], ::.type, SliceMatrix[K1, K2, V]] {
def apply(from: SliceMatrix[K1, K2, V], rows: Seq[Int], ignored: ::.type): SliceMatrix[K1, K2, V] = {
new SliceMatrix(from.tensor, SliceUtils.mapRowSeq(rows, from.rows).map(from.slice1), from.slice2)
}
}
}
// Note: can't have a separate implicit for Range and Seq since they will be ambiguous as both will return a
// SliceMatrix which differs from dense matrix where a Range will return another DenseMatrix and only a seq will
// return a SliceMatrix
implicit def canSliceWeirdCols[K1, K2, V: Semiring : ClassTag]: CanSlice2[SliceMatrix[K1, K2, V], ::.type, Seq[Int], SliceMatrix[K1, K2, V]] = {
new CanSlice2[SliceMatrix[K1, K2, V], ::.type, Seq[Int], SliceMatrix[K1, K2, V]] {
def apply(from: SliceMatrix[K1, K2, V], ignored: ::.type, cols: Seq[Int]): SliceMatrix[K1, K2, V] = {
new SliceMatrix(from.tensor, from.slice1, SliceUtils.mapColumnSeq(cols, from.cols).map(from.slice2))
}
}
}
implicit def handholdCanMapRows[K1, K2, V]: CanCollapseAxis.HandHold[SliceMatrix[K1, K2, V], Axis._0.type, Vector[V]] = new CanCollapseAxis.HandHold[SliceMatrix[K1, K2, V], Axis._0.type, Vector[V]]()
implicit def handholdCanMapCols[K1, K2, V]: CanCollapseAxis.HandHold[SliceMatrix[K1, K2, V], Axis._1.type, Vector[V]] = new CanCollapseAxis.HandHold[SliceMatrix[K1, K2, V], Axis._1.type, Vector[V]]()
implicit def canCollapseRows[K1, K2, V: Semiring : ClassTag, R:ClassTag:Zero]: CanCollapseAxis[SliceMatrix[K1, K2, V], Axis._0.type, Vector[V], R, Transpose[Vector[R]]] =
new CanCollapseAxis[SliceMatrix[K1, K2, V], Axis._0.type, Vector[V], R, Transpose[Vector[R]]] {
def apply(from: SliceMatrix[K1, K2, V], axis: Axis._0.type)(f: (Vector[V]) => R): Transpose[Vector[R]] = {
val result = Vector.zeros[R](from.cols)
cforRange(0 until from.cols) { c =>
result(c) = f(from(::, c)(canSliceCol[K1, K2, V]))
}
result.t
}
}
implicit def canCollapseCols[K1, K2, V: Semiring : ClassTag, R:ClassTag:Zero]: CanCollapseAxis[SliceMatrix[K1, K2, V], Axis._1.type, Vector[V], R, Vector[R]] = {
new CanCollapseAxis[SliceMatrix[K1, K2, V], Axis._1.type, Vector[V], R, Vector[R]] {
def apply(from: SliceMatrix[K1, K2, V], axis: Axis._1.type)(f: (Vector[V]) => R): Vector[R] = {
val result = Vector.zeros[R](from.rows)
for (r <- 0 until from.rows) {
result(r) = f(from(r, ::).t)
}
result
}
}
}
}
trait SliceMatrixOps {
// todo: all all the other ops (can this be done with some macro magic?
implicit def opSetInPlace[K1, K2, V]: OpSet.InPlaceImpl2[SliceMatrix[K1, K2, V], V] = new SMOpSetInPlace[K1, K2, V]
class SMOpSetInPlace[@specialized(Int) K1,
@specialized(Int) K2,
@specialized(Double, Int, Float, Long) V] extends OpSet.InPlaceImpl2[SliceMatrix[K1, K2, V], V] {
def apply(a: SliceMatrix[K1, K2, V], b: V): Unit = a.keysIterator.foreach(k => a.update(k, b))
}
}