/* Copyright 2010 Aaron J. Radke Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ package cc.drx /**a generic discrete Grid container or 2d Matrix of m rows by n cols*/ trait Grid[A] extends Iterable[A]{ //--required def m:Int //number of rows (indexed by i) def n:Int //number of cols (indexed by j) def apply(k:Int):A //--overridable for efficiency override def size:Int = m*n //--features def get(i:Int,j:Int):Option[A] = {val k = i*n+j; if(k >= m*n) None else Some(apply(k)) } def apply(i:Int,j:Int):A = apply(i*n+j) def zipWithIndices:Iterable[(A,Int,Int)] = for(i <- 0 to (m-1); j <- 0 to (n-1)) yield (apply(i*n+j),i,j) //row first def iterator:Iterator[A] = Iterator.range(0,size) map apply def row(i:Int):Iterable[A] = for(j <- 0 to (n-1)) yield apply(i*n+j) //TODO test def col(j:Int):Iterable[A] = for(i <- 0 to (m-1)) yield apply(i*n+j) //TODO test override def toString = s"Grid($m-by-$n, ${Format(take(3).toList)} ...)" } object Grid{ def apply[A](vs:Array[A],nCols:Int):GridArray[A] = new GridArray[A](vs.size/nCols, nCols, vs) /**specialized array**/ def apply(ds:Iterable[Double],nCols:Int):GridArray[Double] = apply[Double](ds.toArray, nCols) def fill(n:Int,m:Int)(f: => Double) = new GridArray[Double](n,m,Array.fill(n*m)(f)) def fill(n:Int,m:Int)(v:Int) = new GridArray[Int](n,m,Array.fill(n*m)(v)) // def readDouble(in:Input):GridArray[Double] = in.read{is => ??? } } /**a Grid or Matrix of m rows by n cols stored in an Array*/ class GridArray[A](val m:Int, val n:Int, private val vs:Array[A]) extends Grid[A]{ def apply(k:Int):A = vs(k) def update(k:Int, v:A):Unit = vs(k) = v //danger allows mutable access } object GridArrayDoubleFile{ def apply(m:Int, n:Int, f:File):GridArrayDoubleFile = new GridArrayDoubleFile(m,n,ArrayDoubleFile(f,m*n)) } class GridArrayDoubleFile(val m:Int, val n:Int, private val vs:ArrayDoubleFile) extends Grid[Double]{ def apply(k:Int):Double = vs(k) override def row(i:Int):Iterable[Double] = drop(i*n).take(n) } //TODO make a file memory mapped file, there are many levels of potential abstraction.. LargeArray based and reading and writing methods /* class GridArrayDouble extends GridArray[Double]{ // def write(out:Output):Unit = out.write{os => ??? } } */ //TODO transpose // class GridArrayTranspose[A](val m:Int, val n:Int, private val vs:Array[A]) extends GridArray[A]{ // override def apply(i:Int,j:Int):A = apply(j*n+i) // }