scala - Array.map returns ArraySeq? -
i making small example of linear algebra sequential , parallel implementations. below current code:
import util.random import system.currenttimemillis import actors.futures._ import numeric.implicits._ object parallel extends app{ val rnd = new random(1337)//seeded rng //create 2 matrices dimension nxn val n = 550 val a:array[array[double]] = array.fill(n,n){ rnd.nextdouble } val b:array[array[double]] = array.fill(n,n){ rnd.nextdouble } //time call-by-name block , return milli-seconds def time(b: => unit):long = { val start = currenttimemillis b currenttimemillis-start } val sequentialprogram = new linearalgebra sequentiallinearalgebra { println("sequential time: "+time { * b } ) } val parcolprogram = new linearalgebra parcollinearalgebra { println("parcol time: "+time { * b } ) } val futureprogram = new linearalgebra futurelinearalgebra { println("future time: "+time { * b } ) } } //interface, knows nothing implementation trait linearalgebra{ type vector[t] = array[t] type matrix[t] = vector[vector[t]] implicit class vectorops[t:numeric](v:vector[t]){ def dot(that:vector[t]):t = innerprod(v,that) } implicit class matrixops[t:numeric](m:matrix[t]){ def *(that:matrix[t]):matrix[t] = matmul(m,that) } //functionality deferred implementing traits def innerprod[t:numeric](a:vector[t],b:vector[t]):t def matmul[t:numeric](a:matrix[t],b:matrix[t]):matrix[t] } //implements linearalgebra interface in sequential fashion trait sequentiallinearalgebra extends linearalgebra { def innerprod[t:numeric](a:vector[t],b:vector[t]) = ((a,b).zipped map (_*_)).sum def matmul[t:numeric](a:matrix[t],b:matrix[t]) = { val bt = b.transpose a.map(row => bt.map(col => row dot col)) } } //implements linearalgebra interface using parallel collections trait parcollinearalgebra extends linearalgebra { def innerprod[t:numeric](a:vector[t],b:vector[t]) = ((a,b).zipped map (_*_)).sum def matmul[t:numeric](a:matrix[t],b:matrix[t]) = { val bt = b.transpose (a.par map (row => bt map (col => row dot col))).toarray } } //implements linearalgebra interface using futures, i.e. explicit workload distribution trait futurelinearalgebra extends linearalgebra { def innerprod[t:numeric](a:vector[t],b:vector[t]) = ((a,b).zipped map (_*_)).sum def matmul[t:numeric](a:matrix[t],b:matrix[t]) = { val bt = b.transpose val res = map ( row => future {bt map (col => row dot col)}) res.map(_.apply) } }
the code seems correct me, following errors:
fsc parallel.scala /home/felix/documents/teaching/2014/dm509/scala/parallel.scala:61: error: type mismatch; found : array[scala.collection.mutable.arrayseq[t]] required: sequentiallinearalgebra.this.matrix[t] (which expands to) array[array[t]] a.map(row => bt.map(col => row dot col)) ^ /home/felix/documents/teaching/2014/dm509/scala/parallel.scala:71: error: type mismatch; found : array[scala.collection.mutable.arrayseq[t]] required: parcollinearalgebra.this.matrix[t] (which expands to) array[array[t]] (a.par map (row => bt map (col => row dot col))).toarray ^ /home/felix/documents/teaching/2014/dm509/scala/parallel.scala:82: error: type mismatch; found : array[scala.collection.mutable.arrayseq[t]] required: futurelinearalgebra.this.matrix[t] (which expands to) array[array[t]] res.map(_.apply) ^ 3 errors found
the problem seems array.map
returns arrayseq
oppposed expected array
. if search-replace array , list, program works expected. reason moving array wish compare efficiency imperative implementation, i.e., need efficient random access. can explain behaviour?
the context bound makes difference:
scala> val = array.tabulate(10,10)((x,y)=>y) as: array[array[int]] = array(array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9), array(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)) scala> map (x => x.sum) res0: array[int] = array(45, 45, 45, 45, 45, 45, 45, 45, 45, 45) scala> def f[a: numeric](as: array[array[a]]) = map (x => x.sum) f: [a](as: array[array[a]])(implicit evidence$1: numeric[a])scala.collection.mutable.arrayseq[a] scala> def f[a](as: array[array[a]]) = map (x => 42) f: [a](as: array[array[a]])array[int]
presumably uses fallback canbuildfrom
yields seq
.
edit: fix it, supply reflect.classtag[t]
can create array[t]
want.
you'll need on:
def matmul[t:numeric](a:matrix[t],b:matrix[t])(implicit ev1: classtag[t])
and
implicit class matrixops[t:numeric](m:matrix[t])(implicit ev1: classtag[t])
Comments
Post a Comment