From 8cc7de74d35b437b7126d02a6219796b5872ac14 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Fri, 17 Feb 2012 16:35:48 +0100 Subject: New FlatArray scheme for handling value classes. --- src/library/scala/Boxed.scala | 18 --- src/library/scala/BoxingConversions.scala | 5 + .../scala/collection/generic/RowFactory.scala | 49 ------- .../scala/collection/mutable/FlatArray.scala | 150 +++++++++++++++++++++ 4 files changed, 155 insertions(+), 67 deletions(-) delete mode 100644 src/library/scala/Boxed.scala create mode 100644 src/library/scala/BoxingConversions.scala delete mode 100644 src/library/scala/collection/generic/RowFactory.scala create mode 100644 src/library/scala/collection/mutable/FlatArray.scala (limited to 'src') diff --git a/src/library/scala/Boxed.scala b/src/library/scala/Boxed.scala deleted file mode 100644 index 6055b3f436..0000000000 --- a/src/library/scala/Boxed.scala +++ /dev/null @@ -1,18 +0,0 @@ -/* __ *\ -** ________ ___ / / ___ Scala API ** -** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** -** __\ \/ /__/ __ |/ /__/ __ | http://www.scala-lang.org/ ** -** /____/\___/_/ |_/____/_/ | | ** -** |/ ** -\* */ - -package scala - -/** A trait that can be implemented by user-defined value classes - */ -trait Boxed[Unboxed] extends Any { - - /** The underlying value wrapped by the value class */ - def unbox: Unboxed -} - diff --git a/src/library/scala/BoxingConversions.scala b/src/library/scala/BoxingConversions.scala new file mode 100644 index 0000000000..fd1bd6c121 --- /dev/null +++ b/src/library/scala/BoxingConversions.scala @@ -0,0 +1,5 @@ +package scala +abstract class BoxingConversions[Boxed, Unboxed] { + def box(x: Unboxed): Boxed + def unbox(x: Boxed): Unboxed +} diff --git a/src/library/scala/collection/generic/RowFactory.scala b/src/library/scala/collection/generic/RowFactory.scala deleted file mode 100644 index c1559c9397..0000000000 --- a/src/library/scala/collection/generic/RowFactory.scala +++ /dev/null @@ -1,49 +0,0 @@ -package scala.collection -package generic - -import mutable.{Builder, ArrayBuffer} -import scala.specialized - -/** A factory class for rows -- flat arrays of value classes that use the unboxed representation - * of the element type. - * - */ -abstract class RowFactory[@specialized Unboxed: ClassManifest, Boxed <: scala.Boxed[Unboxed]] extends (Unboxed => Boxed) { box => - - /** Convert to boxed representation - */ - def apply(x: Unboxed): Boxed - - class Row(elems: Array[Unboxed]) extends mutable.IndexedSeq[Boxed] with mutable.IndexedSeqLike[Boxed, Row] { - - override protected[this] def newBuilder: Builder[Boxed, Row] = Row.newBuilder - - def apply(idx: Int): Boxed = box(elems(idx)) - - def update(idx: Int, elem: Boxed): Unit = elems(idx) = elem.unbox - - def length = elems.length - - override def foreach[U](f: Boxed => U): Unit = elems foreach (elem => f(box(elem))) - - } - - object Row { - def fromSeq(elems: Seq[Boxed]): Row = { - val xs: Array[Unboxed] = new Array[Unboxed](elems.length) - var i = 0 - for (elem <- elems) { xs(i) = elem.unbox; i += 1 } - new Row(xs) - } - - def apply(elems: Boxed*) = fromSeq(elems) - - def newBuilder: Builder[Boxed, Row] = new ArrayBuffer mapResult fromSeq - - implicit def canBuildFrom: CanBuildFrom[Row, Boxed, Row] = - new CanBuildFrom[Row, Boxed, Row] { - def apply(): Builder[Boxed, Row] = newBuilder - def apply(from: Row): Builder[Boxed, Row] = newBuilder - } - } -} diff --git a/src/library/scala/collection/mutable/FlatArray.scala b/src/library/scala/collection/mutable/FlatArray.scala new file mode 100644 index 0000000000..0650d09861 --- /dev/null +++ b/src/library/scala/collection/mutable/FlatArray.scala @@ -0,0 +1,150 @@ +/* __ *\ +** ________ ___ / / ___ Scala API ** +** / __/ __// _ | / / / _ | (c) 2002-2011, LAMP/EPFL ** +** __\ \/ /__/ __ |/ /__/ __ | http://scala-lang.org/ ** +** /____/\___/_/ |_/____/_/ | | ** +** |/ ** +\* */ + + + +package scala.collection +package mutable + +import scala.reflect.ClassManifest +import generic.CanBuildFrom + +/** + * A class representing `Array[T]`. + * + * @tparam T type of the elements in this wrapped array. + * + * @author Martin Odersky, Stephane Micheloud + * @version 1.0 + * @since 2.8 + * @define Coll WrappedArray + * @define coll wrapped array + * @define orderDependent + * @define orderDependentFold + * @define mayNotTerminateInf + * @define willNotTerminateInf + */ +abstract sealed class FlatArray[T] +extends AbstractSeq[T] + with IndexedSeq[T] + with IndexedSeqOptimized[T, FlatArray[T]] +{ + + override protected[this] def thisCollection: FlatArray[T] = this + override protected[this] def toCollection(repr: FlatArray[T]): FlatArray[T] = repr + + /** The length of the array */ + def length: Int + + /** The element at given index */ + def apply(index: Int): T + + /** Update element at given index */ + def update(index: Int, elem: T): Unit + + override def stringPrefix = "FlatArray" + + override protected[this] def newBuilder: Builder[T, FlatArray[T]] = ??? // implemented in FlatArray.Impl + + /** Clones this object, including the underlying Array. */ + override def clone: FlatArray[T] = ??? // implemented in FlatArray.Impl +} + + +/** A companion object used to create instances of `WrappedArray`. + */ +object FlatArray { + + def empty[Boxed, Unboxed](elems: Boxed*) + (implicit boxings: BoxingConversions[Boxed, Unboxed], elemManifest: ClassManifest[Unboxed]): FlatArray[Boxed] = apply() + + def apply[Boxed, Unboxed](elems: Boxed*) + (implicit boxings: BoxingConversions[Boxed, Unboxed], elemManifest: ClassManifest[Unboxed]): FlatArray[Boxed] = { + val b = newBuilder[Boxed, Unboxed] + b.sizeHint(elems.length) + b ++= elems + b.result + } + + def newBuilder[Boxed, Unboxed] + (implicit boxings: BoxingConversions[Boxed, Unboxed], elemManifest: ClassManifest[Unboxed]): Builder[Boxed, FlatArray[Boxed]] = + new Bldr[Boxed, Unboxed](boxings, elemManifest) + + implicit def canBuildFrom[Boxed, Unboxed]( + implicit + boxings: BoxingConversions[Boxed, Unboxed], + elemManifest: ClassManifest[Unboxed]): CanBuildFrom[FlatArray[_], Boxed, FlatArray[Boxed]] = + new CanBuildFrom[FlatArray[_], Boxed, FlatArray[Boxed]] { + def apply(from: FlatArray[_]): Builder[Boxed, FlatArray[Boxed]] = + newBuilder[Boxed, Unboxed] + def apply: Builder[Boxed, FlatArray[Boxed]] = + newBuilder[Boxed, Unboxed] + } + + private class Bldr[Boxed, Unboxed](boxings: BoxingConversions[Boxed, Unboxed], manifest: ClassManifest[Unboxed]) extends Builder[Boxed, FlatArray[Boxed]] { + + private var elems: Array[Unboxed] = _ + private var capacity: Int = 0 + private var size: Int = 0 + + private def resize(size: Int) { + val newelems = manifest.newArray(size) + if (this.size > 0) Array.copy(elems, 0, newelems, 0, this.size) + elems = newelems + capacity = size + } + + override def sizeHint(size: Int) { + if (capacity < size) resize(size) + } + + private def ensureSize(size: Int) { + if (capacity < size) { + var newsize = if (capacity == 0) 16 else capacity * 2 + while (newsize < size) newsize *= 2 + resize(newsize) + } + } + + def +=(elem: Boxed): this.type = { + ensureSize(size + 1) + elems(size) = boxings.unbox(elem) + size += 1 + this + } + + def clear() { + size = 0 + } + + def result(): FlatArray[Boxed] = { + if (capacity == 0 || capacity != size) resize(size) + new FlatArray.Impl(elems, boxings, manifest) + } + } + + private class Impl[Boxed, Unboxed]( + elems: Array[Unboxed], + boxings: BoxingConversions[Boxed, Unboxed], + elemManifest: ClassManifest[Unboxed]) extends FlatArray[Boxed] { + + def length = elems.length + + def apply(idx: Int): Boxed = boxings.box(elems(idx)) + + def update(idx: Int, elem: Boxed) = elems(idx) = boxings.unbox(elem) + + /** Creates new builder for this collection ==> move to subclasses + */ + override protected[this] def newBuilder: Builder[Boxed, FlatArray[Boxed]] = + new Bldr[Boxed, Unboxed](boxings, elemManifest) + + /** Clones this object, including the underlying Array. */ + override def clone: FlatArray[Boxed] = new Impl[Boxed, Unboxed](elems.clone(), boxings, elemManifest) + } +} -- cgit v1.2.3