All Downloads are FREE. Search and download functionalities are using the official Maven repository.

.psp-std_2.11.0.6.1.source-code.Vec.scala Maven / Gradle / Ivy

The newest version!
package psp
package std

import api._, all._, StdShow._, StdEq._
import Vec._
import java.lang.{ Math => math }

/** Based on the scala library Vector by Tiark Rompf.
 *    https://issues.scala-lang.org/browse/SI-4442
 *    https://issues.scala-lang.org/browse/SI-4495
 *    https://github.com/scala/scala/pull/3498
 */

object Vec {
  type Array0D[A] = A
  type Array1D[A] = Array[A]
  type Array2D[A] = Array[Array[A]]
  type Array3D[A] = Array[Array[Array[A]]]
  type Array4D[A] = Array[Array[Array[Array[A]]]]
  type Array5D[A] = Array[Array[Array[Array[Array[A]]]]]
  type Array6D[A] = Array[Array[Array[Array[Array[Array[A]]]]]]

  final val WIDTH  = 5
  final val BLOCK  = 1 << WIDTH
  final val LOBITS = BLOCK - 1 // masks all but WIDTH bits
  final val HIBITS = ~LOBITS

  def empty[@fspec A] : Vec[A]                        = NIL.castTo[Vec[A]]
  def apply[@fspec A](xs: A*): Vec[A]                 = newBuilder[A] build (Direct scala xs)
  def unapplySeq[@fspec A](x: Vec[A]): Some[scSeq[A]] = Some(x.seq)
  def newBuilder[@fspec A](): Builder[A]              = new Builder[A]()

  private[std] val NIL = new Vec[Any](0, 0, 0)
  // Constants governing concat strategy for performance
  private[std] final val Log2ConcatFaster = 5
  private[std] final val TinyAppendFaster = 2

  @inline final def arr(xs: AnyRef): Array[AnyRef] = xs.asInstanceOf[Array[AnyRef]]

  @inline final def levelBits(index: Int, level: Int): Int =
    index >>> (level * WIDTH) & LOBITS

  def levelOf(index: Int): Int = {
    @tailrec def loop(level: Int, bits: Int): Int =
      if (bits == 0) level else loop(level + 1, bits >>> WIDTH)

    loop(0, index >>> WIDTH)
  }

  final class Builder[@fspec A]() extends Builds[A, Vec[A]] with VectorPointer[A @uV] {
    // possible alternative: start with display0 = null, blockIndex = -BLOCK, lo = BLOCK
    // to avoid allocating initial array if the result will be empty anyways
    this.display0 = new Array[AnyRef](BLOCK)
    this.depth    = 1

    private[this] var blockIndex = 0
    private[this] var lo = 0

    def build(xs: Foreach[A]): Vec[A] = {
      xs foreach add
      result
    }
    def add(elem: A): Unit = {
      if (lo >= display0.length) {
        val newBlockIndex = blockIndex+BLOCK
        gotoNextBlockStartWritable(newBlockIndex, blockIndex ^ newBlockIndex)
        blockIndex = newBlockIndex
        lo = 0
      }
      display0(lo) = elem.asInstanceOf[AnyRef]
      lo += 1
    }
    def result(): Vec[A] = {
      val size = blockIndex + lo
      if (size == 0)
        return Vec.empty

      val s = new Vec[A](0, size, 0) // should focus front or back?
      s initFrom this
      if (depth > 1) s.gotoPos(0, size - 1) // we're currently focused to size - 1, not size!
      s
    }
  }
}

final class Vec[@fspec A](val startIndex: Int, val endIndex: Int, focus: Int) extends VectorPointer[A @uV] with Direct[A] with ShowSelf {
  self =>

  @inline private def preStartIndex = startIndex - 1

  private def nextVec(s: Int, e: Int, f: Int): Vec[A] = new Vec[A](s, e, f)
  private def newVec(s: Int, e: Int, f: Int): Vec[A]  = doto(nextVec(s, e, f))(_ initFrom this)

  private def updateDirty(s: Vec[A]): Vec[A] = { s.dirty = this.dirty ; s }

  private def newVecInFront(shift: Int, newBlockIndex: Int): Vec[A] =
    updateDirty(newVec(preStartIndex + shift, endIndex + shift, newBlockIndex))

  private def newVecInBack(shift: Int, newBlockIndex: Int): Vec[A] =
    updateDirty(newVec(startIndex - shift, endIndex + 1 - shift, newBlockIndex))

  private[std] var dirty = false

  def to_s = "[ " + (this map (_.any_s) mk_s ", ") + " ]"

  def lastIntIndex         = length - 1
  def length: Int          = endIndex - startIndex
  def size: Precise        = Size(length)
  def elemAt(i: Vindex): A = applyInt(i.getInt)
  def isEmpty              = length <= 0

  @inline def foreach(f: A => Unit): Unit = {
    if (!isEmpty)
      lowlevel.ll.foreachConsecutive(0, lastIntIndex, i => f(applyInt(i)))
  }

  def take(n: Vindex): Vec[A] =
    if (n <= 0) Vec.empty
    else if (n >= length) this
    else dropBack0(startIndex + n.getInt)

  def drop(n: Vindex): Vec[A] =
    if (n.get <= 0) this
    else if (n >= length) Vec.empty
    else dropFront0(startIndex + n.getInt)

  def takeRight(n: Vindex): Vec[A] =
    if (n.get <= 0) Vec.empty
    else if (n >= length) this
    else dropFront0(endIndex - n.getInt)

  def dropRight(n: Vindex): Vec[A] =
    if (n.get <= 0) this
    else if (endIndex - n.getInt > startIndex) dropBack0(endIndex - n.getInt)
    else Vec.empty

  def takeWhile(p: ToBool[A]): Vec[A]      = take(iterator count p)
  def dropWhile(p: ToBool[A]): Vec[A]      = drop(iterator count p)
  def takeRightWhile(p: ToBool[A]): Vec[A] = takeRight(reverseIterator count p)
  def dropRightWhile(p: ToBool[A]): Vec[A] = dropRight(reverseIterator count p)

  @inline def foldl[@fspec B](zero: B)(f: (B, A) => B): B = {
    var res = zero
    if (length > 0)
      lowlevel.ll.foreachConsecutive(0, lastIntIndex, i => res = f(res, applyInt(i)))
    res
  }

  def updated(i: Vindex, elem: A): Vec[A] = updateAt(i.getInt, elem)
  def :+(elem: A): Vec[A] = appendBack(elem)
  def +:(elem: A): Vec[A] = appendFront(elem)

  def ++(that: Vec[A]): Vec[A] = (
    if (that.isEmpty) this
    else if (this.isEmpty) that
    else {
      val b = Vec.newBuilder[A]
      this foreach b.add
      that foreach b.add
      b.result
    }
  )

  private[std] final def initIterator(s: VectorIterator[A]): VectorIterator[A] = {
    s.initFrom(this)
    if (dirty) s.stabilize(focus)
    if (s.depth > 1) s.gotoPos(startIndex, startIndex ^ focus)
    s
  }

  def iterator: VectorIterator[A]                    = initIterator(new VectorIterator[A](startIndex, endIndex))
  def reverseIterator: BiIterator.ReverseIterator[A] = BiIterator reverse this
  def reverse: Vec[A]                                = reverseIterator.toVec
  def applyInt(index: Int): A                        = getElemWithFocus(checkRangeConvert(index))

  private def getElemWithFocus(idx: Int): A = getElem(idx, idx ^ focus)
  private[std] def checkRangeConvert(index: Int): Int = (
    if (0 <= index && index < length) index + startIndex
    else indexOutOfBoundsException(index)
  )

  // semi-private[std] api

  private[std] def gotoPosWritable(oldIndex: Int, newIndex: Int): Unit = {
    if (dirty)
      gotoPosWritable1(oldIndex, newIndex)
    else {
      gotoPosWritable0(newIndex)
      dirty = true
    }
  }

  private[std] def gotoFreshPosWritable(oldIndex: Int, newIndex: Int, xor: Int): Unit = {
    val wasDirty = dirty
    if (wasDirty)
      stabilize(oldIndex)

    gotoFreshPosWritable0(oldIndex, newIndex, xor)

    if (!wasDirty)
      dirty = true
  }

  private def updateAt(index: Int, elem: A): Vec[A] = {
    val idx = checkRangeConvert(index)
    val s = updateDirty(newVec(startIndex, endIndex, idx))
    s.gotoPosWritable(focus, idx)  // if dirty commit changes; go to new pos and prepare for writing
    s.display0(idx & LOBITS) = elem.asInstanceOf[AnyRef]
    s
  }

  private[std] def appendFront(value: A): Vec[A] = {
    if (endIndex == startIndex)
      return makeSingletonAtBack(value)

    val blockIndex = preStartIndex & HIBITS
    val lo         = preStartIndex & LOBITS

    if (startIndex != blockIndex + BLOCK) {
      val s = newVecInFront(0, blockIndex)
      s.gotoPosWritable(focus, blockIndex)
      s.display0(lo) = value.asInstanceOf[AnyRef]
      s
    }
    else {
      val freeSpace   = ((1 << 5*(depth)) - endIndex) // free space at the right given the current tree-structure depth
      val shift       = freeSpace & ~((1 << 5*(depth-1))-1) // number of elements by which we'll shift right (only move at top level)
      val shiftBlocks = freeSpace >>> 5*(depth-1) // number of top-level blocks

      //println("----- appendFront " + value + " at " + (preStartIndex) + " reached block start")
      if (shift != 0) {
        // case A: we can shift right on the top level

        if (depth > 1) {
          val newBlockIndex = blockIndex + shift
          val newFocus = focus + shift
          val s = newVecInFront(shift, newBlockIndex)
          s.shiftTopLevel(0, shiftBlocks) // shift right by n blocks
          s.gotoFreshPosWritable(newFocus, newBlockIndex, newFocus ^ newBlockIndex) // maybe create pos; prepare for writing
          s.display0(lo) = value.asInstanceOf[AnyRef]
          //assert(depth == s.depth)
          s
        } else {
          val newBlockIndex = blockIndex + BLOCK
          val newFocus = focus

          //assert(newBlockIndex == 0)
          //assert(newFocus == 0)

          val s = newVecInFront(shift, newBlockIndex)
          s.shiftTopLevel(0, shiftBlocks) // shift right by n elements
          s.gotoPosWritable(newFocus, newBlockIndex) // prepare for writing
          s.display0(shift-1) = value.asInstanceOf[AnyRef]
          s
        }
      } else if (blockIndex < 0) {
        // case B: we need to move the whole structure
        val move = (1 << 5*(depth+1)) - (1 << 5*(depth))

        val newBlockIndex = blockIndex + move
        val newFocus = focus + move


        val s = newVecInFront(move, newBlockIndex)
        s.gotoFreshPosWritable(newFocus, newBlockIndex, newFocus ^ newBlockIndex) // could optimize: we know it will create a whole branch
        s.display0(lo) = value.asInstanceOf[AnyRef]
        //assert(s.depth == depth+1)
        s
      } else {
        val newBlockIndex = blockIndex
        val newFocus = focus

        val s = newVecInFront(0, newBlockIndex)
        s.gotoFreshPosWritable(newFocus, newBlockIndex, newFocus ^ newBlockIndex)
        s.display0(lo) = value.asInstanceOf[AnyRef]
        //assert(s.depth == depth)
        s
      }
    }
  }

  private def newSingleArray(startIndex: Int, endIndex: Int, elem: A): Vec[A] = {
    val elems = allocateArray(BLOCK)
    elems(startIndex) = elem.asInstanceOf[AnyRef]
    val s = nextVec(startIndex, endIndex, 0)
    s.depth = 1
    s.display0 = elems
    s
  }

  private def makeSingletonAtBack(value: A): Vec[A]  = newSingleArray(BLOCK - 1, BLOCK, value)
  private def makeSingletonAtFront(value: A): Vec[A] = newSingleArray(0, 1, value)

  private[std] def appendBack(value: A): Vec[A] = {
    if (endIndex == startIndex)
      return makeSingletonAtFront(value)

    val blockIndex = endIndex & HIBITS
    val lo         = endIndex & LOBITS

    if (endIndex != blockIndex) {
      val s = newVecInBack(0, blockIndex)
      s.gotoPosWritable(focus, blockIndex)
      s.display0(lo) = value.asInstanceOf[AnyRef]
      s
    }
    else {
      val shift = startIndex & ~((1<<5*(depth-1))-1)
      val shiftBlocks = startIndex >>> 5*(depth-1)

      if (shift != 0) {
        if (depth > 1) {
          val newBlockIndex = blockIndex - shift
          val newFocus = focus - shift
          val s = newVecInBack(shift, newBlockIndex)
          s.shiftTopLevel(shiftBlocks, 0) // shift left by n blocks
          s.gotoFreshPosWritable(newFocus, newBlockIndex, newFocus ^ newBlockIndex)
          s.display0(lo) = value.asInstanceOf[AnyRef]
          //assert(depth == s.depth)
          s
        } else {
          val newBlockIndex = blockIndex - BLOCK
          val newFocus = focus

          //assert(newBlockIndex == 0)
          //assert(newFocus == 0)

          val s = newVecInBack(shift, newBlockIndex)
          s.shiftTopLevel(shiftBlocks, 0) // shift right by n elements
          s.gotoPosWritable(newFocus, newBlockIndex)
          s.display0(BLOCK - shift) = value.asInstanceOf[AnyRef]
          s
        }
      } else {
        val newBlockIndex = blockIndex
        val newFocus = focus

        val s = newVecInBack(0, newBlockIndex)
        s.gotoFreshPosWritable(newFocus, newBlockIndex, newFocus ^ newBlockIndex)
        s.display0(lo) = value.asInstanceOf[AnyRef]
        //assert(s.depth == depth+1) might or might not create new level!
        s
      }
    }
  }

  // low-level implementation (needs cleanup, maybe move to util class)

  private[std] def shiftTopLevel(oldLeft: Int, newLeft: Int) = (depth - 1) match {
    case 0 => display0 = copyRange(display0, oldLeft, newLeft)
    case 1 => display1 = copyRange(display1, oldLeft, newLeft)
    case 2 => display2 = copyRange(display2, oldLeft, newLeft)
    case 3 => display3 = copyRange(display3, oldLeft, newLeft)
    case 4 => display4 = copyRange(display4, oldLeft, newLeft)
    case 5 => display5 = copyRange(display5, oldLeft, newLeft)
  }

  private[std] def zeroLeft(array: Array[AnyRef], index: Int): Unit = {
    var i = 0; while (i < index) { array(i) = null; i+=1 }
  }

  private[std] def zeroRight(array: Array[AnyRef], index: Int): Unit = {
    var i = index; while (i < array.length) { array(i) = null; i+=1 }
  }

  private[std] def preClean(depth: Int) = {
    this.depth = depth
    (depth - 1) match {
      case 0 =>
        display1 = null
        display2 = null
        display3 = null
        display4 = null
        display5 = null
      case 1 =>
        display2 = null
        display3 = null
        display4 = null
        display5 = null
      case 2 =>
        display3 = null
        display4 = null
        display5 = null
      case 3 =>
        display4 = null
        display5 = null
      case 4 =>
        display5 = null
      case 5 =>
    }
  }

  // requires structure is at index cutIndex and writable at level 0
  private[std] def cleanLeftEdge(cutIndex: Int) = (levelOf(cutIndex): @switch) match {
    case 0 =>
      zeroLeft(display0, cutIndex)
    case 1 =>
      zeroLeft(display0, cutIndex & LOBITS)
      display1 = copyRight(display1, cutIndex >>>  5)
    case 2 =>
      zeroLeft(display0, cutIndex & LOBITS)
      display1 = copyRight(display1, cutIndex >>>  5 & LOBITS)
      display2 = copyRight(display2, cutIndex >>> 10 & LOBITS)
    case 3 =>
      zeroLeft(display0, cutIndex & LOBITS)
      display1 = copyRight(display1, cutIndex >>>  5 & LOBITS)
      display2 = copyRight(display2, cutIndex >>> 10 & LOBITS)
      display3 = copyRight(display3, cutIndex >>> 15 & LOBITS)
    case 4 =>
      zeroLeft(display0, cutIndex & LOBITS)
      display1 = copyRight(display1, cutIndex >>>  5 & LOBITS)
      display2 = copyRight(display2, cutIndex >>> 10 & LOBITS)
      display3 = copyRight(display3, cutIndex >>> 15 & LOBITS)
      display4 = copyRight(display4, cutIndex >>> 20 & LOBITS)
    case 5 =>
      zeroLeft(display0, cutIndex & LOBITS)
      display1 = copyRight(display1, cutIndex >>>  5 & LOBITS)
      display2 = copyRight(display2, cutIndex >>> 10 & LOBITS)
      display3 = copyRight(display3, cutIndex >>> 15 & LOBITS)
      display4 = copyRight(display4, cutIndex >>> 20 & LOBITS)
      display5 = copyRight(display5, cutIndex >>> 25 & LOBITS)
    case _ =>
      illegalArgumentException(cutIndex)
  }

  private def copyRight(array: Array[AnyRef], left: Int): Array[AnyRef] =
    doto(new Array[AnyRef](array.length))(a2 => arraycopy(array, left, a2, left, a2.length - left))

  private def copyLeft(array: Array[AnyRef], right: Int): Array[AnyRef] =
    doto(new Array[AnyRef](array.length))(a2 => arraycopy(array, 0, a2, 0, right))

  // requires structure is writable and at index cutIndex
  private[std] def cleanRightEdge(cutIndex: Int): Unit = {
    val preCut = cutIndex - 1

    // we're actually sitting one block left if cutIndex lies on a block boundary
    // this means that we'll end up erasing the whole block!!
    (levelOf(preCut): @switch) match {
      case 0 =>
        zeroRight(display0, cutIndex)
      case 1 =>
        zeroRight(display0, (preCut & LOBITS) + 1)
        display1 = copyLeft(display1, cutIndex >>>  5)
      case 2 =>
        zeroRight(display0, (preCut & LOBITS) + 1)
        display1 = copyLeft(display1, (preCut >>>  5 & LOBITS) + 1)
        display2 = copyLeft(display2, cutIndex >>> 10)
      case 3 =>
        zeroRight(display0, (preCut & LOBITS) + 1)
        display1 = copyLeft(display1, (preCut >>>  5 & LOBITS) + 1)
        display2 = copyLeft(display2, (preCut >>> 10 & LOBITS) + 1)
        display3 = copyLeft(display3, cutIndex >>> 15)
      case 4 =>
        zeroRight(display0, (preCut & LOBITS) + 1)
        display1 = copyLeft(display1, (preCut >>>  5 & LOBITS) + 1)
        display2 = copyLeft(display2, (preCut >>> 10 & LOBITS) + 1)
        display3 = copyLeft(display3, (preCut >>> 15 & LOBITS) + 1)
        display4 = copyLeft(display4, cutIndex >>> 20)
      case 5 =>
        zeroRight(display0, (preCut & LOBITS) + 1)
        display1 = copyLeft(display1, (preCut >>>  5 & LOBITS) + 1)
        display2 = copyLeft(display2, (preCut >>> 10 & LOBITS) + 1)
        display3 = copyLeft(display3, (preCut >>> 15 & LOBITS) + 1)
        display4 = copyLeft(display4, (preCut >>> 20 & LOBITS) + 1)
        display5 = copyLeft(display5, cutIndex >>> 25)
      case x =>
        illegalArgumentException(x)
    }
  }

  private def requiredDepth(xor: Int): Int = levelOf(xor) + 1

  private[std] def dropFront0(cutIndex: Int): Vec[A] = {
    val blockIndex = cutIndex & HIBITS
    val xor        = cutIndex ^ (endIndex - 1)
    val d          = requiredDepth(xor)
    val shift      = cutIndex & ~((1 << (5*d))-1)

    // need to init with full display iff going to cutIndex requires swapping block at level >= d
    val s = newVec(cutIndex-shift, endIndex-shift, blockIndex-shift)
    s.dirty = dirty
    s.gotoPosWritable(focus, blockIndex)
    s.preClean(d)
    s.cleanLeftEdge(cutIndex - shift)
    s
  }

  private[std] def dropBack0(cutIndex: Int): Vec[A] = {
    val blockIndex = (cutIndex - 1) & HIBITS
    val xor = startIndex ^ (cutIndex - 1)
    val d = requiredDepth(xor)
    val shift = startIndex & ~((1 << 5 * d) - 1)
    val s = newVec(startIndex-shift, cutIndex-shift, blockIndex-shift)
    s.dirty = dirty
    s.gotoPosWritable(focus, blockIndex)
    s.preClean(d)
    s.cleanRightEdge(cutIndex-shift)
    s
  }
}


final class VectorIterator[@fspec A](_startIndex: Int, endIndex: Int) extends scIterator[A] with VectorPointer[A @uV] {
  private[std] var blockIndex: Int = _startIndex & HIBITS
  private[std] var lo: Int         = _startIndex & LOBITS
  private[std] var endLo           = math.min(endIndex - blockIndex, BLOCK)
  private[std] var _hasNext        = blockIndex + lo < endIndex

  def hasNext = _hasNext
  def next(): A = {
    if (!_hasNext) noSuchElementException("reached iterator end")

    val res = display0(lo).asInstanceOf[A]
    lo += 1

    if (lo == endLo) {
      if (blockIndex + lo < endIndex) {
        val newBlockIndex = blockIndex+BLOCK
        gotoNextBlockStart(newBlockIndex, blockIndex ^ newBlockIndex)

        blockIndex = newBlockIndex
        endLo = math.min(endIndex - blockIndex, BLOCK)
        lo = 0
      } else {
        _hasNext = false
      }
    }

    res
  }
}

sealed trait VectorPointer[@fspec T] {
  def allocateArray(len: Int): Array[AnyRef] = newArray[AnyRef](len)

  val displays: Displays = new Displays()

  def depth: Int            = displays.depth
  def depth_=(x: Int): Unit = displays.depth = x

  def display0: Array[AnyRef] = displays getDisplay 0
  def display1: Array[AnyRef] = displays getDisplay 1
  def display2: Array[AnyRef] = displays getDisplay 2
  def display3: Array[AnyRef] = displays getDisplay 3
  def display4: Array[AnyRef] = displays getDisplay 4
  def display5: Array[AnyRef] = displays getDisplay 5

  def display0_=(xs: Array[AnyRef]): Unit = displays.setDisplay(0, xs)
  def display1_=(xs: Array[AnyRef]): Unit = displays.setDisplay(1, xs)
  def display2_=(xs: Array[AnyRef]): Unit = displays.setDisplay(2, xs)
  def display3_=(xs: Array[AnyRef]): Unit = displays.setDisplay(3, xs)
  def display4_=(xs: Array[AnyRef]): Unit = displays.setDisplay(4, xs)
  def display5_=(xs: Array[AnyRef]): Unit = displays.setDisplay(5, xs)

  private def ensure0(): Unit = display0 = new Array(BLOCK)
  private def ensure1(xs: AnyRef): Unit = xs match {
    case null => display1 = new Array(BLOCK)
    case _    => display1 = arr(xs)
  }
  private def ensure2(xs: AnyRef): Unit = xs match {
    case null => display2 = new Array(BLOCK)
    case _    => display2 = arr(xs)
  }
  private def ensure3(xs: AnyRef): Unit = xs match {
    case null => display3 = new Array(BLOCK)
    case _    => display3 = arr(xs)
  }
  private def ensure4(xs: AnyRef): Unit = xs match {
    case null => display4 = new Array(BLOCK)
    case _    => display4 = arr(xs)
  }

  private[std] final def initFrom(that: VectorPointer[T]): VectorPointer[T] = {
    this.depth = that.depth
    displays initFrom that.displays
    this
  }

  // requires structure is at pos oldIndex = xor ^ index
  private[std] final def getElem(index: Int, xor: Int): T = (levelOf(xor): @switch) match {
    case 0 => display0(index & LOBITS).asInstanceOf[T]
    case 1 => display1(index >> 5 & LOBITS).asInstanceOf[Array[AnyRef]](index & LOBITS).asInstanceOf[T]
    case 2 => display2(index >> 10 & LOBITS).asInstanceOf[Array[AnyRef]](index >> 5 & LOBITS).asInstanceOf[Array[AnyRef]](index & LOBITS).asInstanceOf[T]
    case 3 => display3(index >> 15 & LOBITS).asInstanceOf[Array[AnyRef]](index >> 10 & LOBITS).asInstanceOf[Array[AnyRef]](index >> 5 & LOBITS).asInstanceOf[Array[AnyRef]](index & LOBITS).asInstanceOf[T]
    case 4 => display4(index >> 20 & LOBITS).asInstanceOf[Array[AnyRef]](index >> 15 & LOBITS).asInstanceOf[Array[AnyRef]](index >> 10 & LOBITS).asInstanceOf[Array[AnyRef]](index >> 5 & LOBITS).asInstanceOf[Array[AnyRef]](index & LOBITS).asInstanceOf[T]
    case 5 => display5(index >> 25 & LOBITS).asInstanceOf[Array[AnyRef]](index >> 20 & LOBITS).asInstanceOf[Array[AnyRef]](index >> 15 & LOBITS).asInstanceOf[Array[AnyRef]](index >> 10 & LOBITS).asInstanceOf[Array[AnyRef]](index >> 5 & LOBITS).asInstanceOf[Array[AnyRef]](index & LOBITS).asInstanceOf[T]
    case _ => illegalArgumentException(xor)
  }

  // go to specific position
  // requires structure is at pos oldIndex = xor ^ index,
  // ensures structure is at pos index
  private[std] final def gotoPos(index: Int, xor: Int): Unit = (levelOf(xor): @switch) match {
    case 0 =>
    case 1 =>
      display0 = arr(display1(index >> 5 & LOBITS))
    case 2 =>
      display1 = arr(display2(index >> 10 & LOBITS))
      display0 = arr(display1(index >>  5 & LOBITS))
    case 3 =>
      display2 = arr(display3(index >> 15 & LOBITS))
      display1 = arr(display2(index >> 10 & LOBITS))
      display0 = arr(display1(index >>  5 & LOBITS))
    case 4 =>
      display3 = arr(display4(index >> 20 & LOBITS))
      display2 = arr(display3(index >> 15 & LOBITS))
      display1 = arr(display2(index >> 10 & LOBITS))
      display0 = arr(display1(index >>  5 & LOBITS))
    case 5 =>
      display4 = arr(display5(index >> 25 & LOBITS))
      display3 = arr(display4(index >> 20 & LOBITS))
      display2 = arr(display3(index >> 15 & LOBITS))
      display1 = arr(display2(index >> 10 & LOBITS))
      display0 = arr(display1(index >>  5 & LOBITS))
    case _ =>
      illegalArgumentException(xor)
  }

  // USED BY ITERATOR

  // xor: oldIndex ^ index
  // goto block start pos
  private[std] final def gotoNextBlockStart(index: Int, xor: Int): Unit = (levelOf(xor): @switch) match {
    case 0 | 1 =>
      display0 = arr(display1(index >> 5 & LOBITS))
    case 2 =>
      display1 = arr(display2(index >> 10 & LOBITS))
      display0 = arr(display1(0))
    case 3 =>
      display2 = arr(display3(index >> 15 & LOBITS))
      display1 = arr(display2(0))
      display0 = arr(display1(0))
    case 4 =>
      display3 = arr(display4(index >> 20 & LOBITS))
      display2 = arr(display3(0))
      display1 = arr(display2(0))
      display0 = arr(display1(0))
    case 5 =>
      display4 = arr(display5(index >> 25 & LOBITS))
      display3 = arr(display4(0))
      display2 = arr(display3(0))
      display1 = arr(display2(0))
      display0 = arr(display1(0))
    case _ =>
      illegalArgumentException(xor)
  }

  // USED BY BUILDER

  // xor: oldIndex ^ index
  // goto block start pos
  private[std] final def gotoNextBlockStartWritable(index: Int, xor: Int): Unit = (levelOf(xor): @switch) match {
    case 0 | 1 =>
      if (depth == 1) { display1 = new Array(BLOCK); display1(0) = display0; depth+=1}
      display0 = new Array(BLOCK)
      display1(index >>  5 & LOBITS) = display0
    case 2 =>
      if (depth == 2) { display2 = new Array(BLOCK); display2(0) = display1; depth+=1}
      display0 = new Array(BLOCK)
      display1 = new Array(BLOCK)
      display1(index >>  5 & LOBITS) = display0
      display2(index >> 10 & LOBITS) = display1
    case 3 =>
      if (depth == 3) { display3 = new Array(BLOCK); display3(0) = display2; depth+=1}
      display0 = new Array(BLOCK)
      display1 = new Array(BLOCK)
      display2 = new Array(BLOCK)
      display1(index >>  5 & LOBITS) = display0
      display2(index >> 10 & LOBITS) = display1
      display3(index >> 15 & LOBITS) = display2
    case 4 =>
      if (depth == 4) { display4 = new Array(BLOCK); display4(0) = display3; depth+=1}
      display0 = new Array(BLOCK)
      display1 = new Array(BLOCK)
      display2 = new Array(BLOCK)
      display3 = new Array(BLOCK)
      display1(index >>  5 & LOBITS) = display0
      display2(index >> 10 & LOBITS) = display1
      display3(index >> 15 & LOBITS) = display2
      display4(index >> 20 & LOBITS) = display3
    case 5 =>
      if (depth == 5) { display5 = new Array(BLOCK); display5(0) = display4; depth+=1}
      display0 = new Array(BLOCK)
      display1 = new Array(BLOCK)
      display2 = new Array(BLOCK)
      display3 = new Array(BLOCK)
      display4 = new Array(BLOCK)
      display1(index >>  5 & LOBITS) = display0
      display2(index >> 10 & LOBITS) = display1
      display3(index >> 15 & LOBITS) = display2
      display4(index >> 20 & LOBITS) = display3
      display5(index >> 25 & LOBITS) = display4
    case _ =>
      illegalArgumentException(xor)
  }

  // STUFF BELOW USED BY APPEND / UPDATE
  private[std] final def copyOf(a: Array[AnyRef]) =
    doto(new Array[AnyRef](a.length))(b => arraycopy(a, 0, b, 0, a.length))

  private[std] final def nullSlotAndCopy(array: Array[AnyRef], index: Int) = {
    val x = array(index)
    array(index) = null
    copyOf(x.asInstanceOf[Array[AnyRef]])
  }

  // make sure there is no aliasing
  // requires structure is at pos index
  // ensures structure is clean and at pos index and writable at all levels except 0

  private[std] final def stabilize(index: Int) = (depth - 1) match {
    case 5 =>
      display5 = copyOf(display5)
      display4 = copyOf(display4)
      display3 = copyOf(display3)
      display2 = copyOf(display2)
      display1 = copyOf(display1)
      display5(index >> 25 & LOBITS) = display4
      display4(index >> 20 & LOBITS) = display3
      display3(index >> 15 & LOBITS) = display2
      display2(index >> 10 & LOBITS) = display1
      display1(index >>  5 & LOBITS) = display0
    case 4 =>
      display4 = copyOf(display4)
      display3 = copyOf(display3)
      display2 = copyOf(display2)
      display1 = copyOf(display1)
      display4(index >> 20 & LOBITS) = display3
      display3(index >> 15 & LOBITS) = display2
      display2(index >> 10 & LOBITS) = display1
      display1(index >>  5 & LOBITS) = display0
    case 3 =>
      display3 = copyOf(display3)
      display2 = copyOf(display2)
      display1 = copyOf(display1)
      display3(index >> 15 & LOBITS) = display2
      display2(index >> 10 & LOBITS) = display1
      display1(index >>  5 & LOBITS) = display0
    case 2 =>
      display2 = copyOf(display2)
      display1 = copyOf(display1)
      display2(index >> 10 & LOBITS) = display1
      display1(index >>  5 & LOBITS) = display0
    case 1 =>
      display1 = copyOf(display1)
      display1(index >>  5 & LOBITS) = display0
    case 0 =>
  }

  /// USED IN UPDATE AND APPEND BACK

  // prepare for writing at an existing position

  // requires structure is clean and at pos oldIndex = xor ^ newIndex,
  // ensures structure is dirty and at pos newIndex and writable at level 0
  private[std] final def gotoPosWritable0(newIndex: Int): Unit = (depth - 1) match {
    case 5 =>
      display5 = copyOf(display5)
      display4 = arr(nullSlotAndCopy(display5, newIndex >> 25 & LOBITS))
      display3 = arr(nullSlotAndCopy(display4, newIndex >> 20 & LOBITS))
      display2 = arr(nullSlotAndCopy(display3, newIndex >> 15 & LOBITS))
      display1 = arr(nullSlotAndCopy(display2, newIndex >> 10 & LOBITS))
      display0 = arr(nullSlotAndCopy(display1, newIndex >>  5 & LOBITS))
    case 4 =>
      display4 = copyOf(display4)
      display3 = arr(nullSlotAndCopy(display4, newIndex >> 20 & LOBITS))
      display2 = arr(nullSlotAndCopy(display3, newIndex >> 15 & LOBITS))
      display1 = arr(nullSlotAndCopy(display2, newIndex >> 10 & LOBITS))
      display0 = arr(nullSlotAndCopy(display1, newIndex >>  5 & LOBITS))
    case 3 =>
      display3 = copyOf(display3)
      display2 = arr(nullSlotAndCopy(display3, newIndex >> 15 & LOBITS))
      display1 = arr(nullSlotAndCopy(display2, newIndex >> 10 & LOBITS))
      display0 = arr(nullSlotAndCopy(display1, newIndex >>  5 & LOBITS))
    case 2 =>
      display2 = copyOf(display2)
      display1 = arr(nullSlotAndCopy(display2, newIndex >> 10 & LOBITS))
      display0 = arr(nullSlotAndCopy(display1, newIndex >>  5 & LOBITS))
    case 1 =>
      display1 = copyOf(display1)
      display0 = arr(nullSlotAndCopy(display1, newIndex >>  5 & LOBITS))
    case 0 =>
      display0 = copyOf(display0)
  }


  // requires structure is dirty and at pos oldIndex,
  // ensures structure is dirty and at pos newIndex and writable at level 0
  private[std] final def gotoPosWritable1(oldIndex: Int, newIndex: Int): Unit = (levelOf(oldIndex ^ newIndex): @switch) match {
    case 0 =>
      display0 = copyOf(display0)
    case 1 =>
      display1 = copyOf(display1)
      display1(oldIndex >> 5 & LOBITS) = display0
      display0 = nullSlotAndCopy(display1, newIndex >>  5 & LOBITS)
    case 2 =>
      display1 = copyOf(display1)
      display2 = copyOf(display2)
      display1(oldIndex >>  5 & LOBITS) = display0
      display2(oldIndex >> 10 & LOBITS) = display1
      display1 = arr(nullSlotAndCopy(display2, newIndex >> 10 & LOBITS))
      display0 = arr(nullSlotAndCopy(display1, newIndex >>  5 & LOBITS))
    case 3 =>
      display1 = copyOf(display1)
      display2 = copyOf(display2)
      display3 = copyOf(display3)
      display1(oldIndex >>  5 & LOBITS) = display0
      display2(oldIndex >> 10 & LOBITS) = display1
      display3(oldIndex >> 15 & LOBITS) = display2
      display2 = arr(nullSlotAndCopy(display3, newIndex >> 15 & LOBITS))
      display1 = arr(nullSlotAndCopy(display2, newIndex >> 10 & LOBITS))
      display0 = arr(nullSlotAndCopy(display1, newIndex >>  5 & LOBITS))
    case 4 =>
      display1 = copyOf(display1)
      display2 = copyOf(display2)
      display3 = copyOf(display3)
      display4 = copyOf(display4)
      display1(oldIndex >>  5 & LOBITS) = display0
      display2(oldIndex >> 10 & LOBITS) = display1
      display3(oldIndex >> 15 & LOBITS) = display2
      display4(oldIndex >> 20 & LOBITS) = display3
      display3 = arr(nullSlotAndCopy(display4, newIndex >> 20 & LOBITS))
      display2 = arr(nullSlotAndCopy(display3, newIndex >> 15 & LOBITS))
      display1 = arr(nullSlotAndCopy(display2, newIndex >> 10 & LOBITS))
      display0 = arr(nullSlotAndCopy(display1, newIndex >>  5 & LOBITS))
    case 5 =>
      display1 = copyOf(display1)
      display2 = copyOf(display2)
      display3 = copyOf(display3)
      display4 = copyOf(display4)
      display5 = copyOf(display5)
      display1(oldIndex >>  5 & LOBITS) = display0
      display2(oldIndex >> 10 & LOBITS) = display1
      display3(oldIndex >> 15 & LOBITS) = display2
      display4(oldIndex >> 20 & LOBITS) = display3
      display5(oldIndex >> 25 & LOBITS) = display4
      display4 = arr(nullSlotAndCopy(display5, newIndex >> 25 & LOBITS))
      display3 = arr(nullSlotAndCopy(display4, newIndex >> 20 & LOBITS))
      display2 = arr(nullSlotAndCopy(display3, newIndex >> 15 & LOBITS))
      display1 = arr(nullSlotAndCopy(display2, newIndex >> 10 & LOBITS))
      display0 = arr(nullSlotAndCopy(display1, newIndex >>  5 & LOBITS))
    case x =>
      illegalArgumentException(x)
  }

  // USED IN DROP

  private[std] final def copyRange(array: Array[AnyRef], oldLeft: Int, newLeft: Int) = {
    val elems = allocateArray(BLOCK)
    arraycopy(array, oldLeft, elems, newLeft, BLOCK - math.max(newLeft,oldLeft))
    elems
  }

  // USED IN APPEND
  // create a new block at the bottom level (and possibly nodes on its path) and prepares for writing

  // requires structure is clean and at pos oldIndex,
  // ensures structure is dirty and at pos newIndex and writable at level 0
  // goto block start pos
  private[std] final def gotoFreshPosWritable0(oldIndex: Int, newIndex: Int, xor: Int): Unit = (levelOf(xor): @switch) match {
    case 0 => ()
    case 1 =>
      if (depth == 1) {
        display1 = new Array(BLOCK)
        display1(oldIndex >>  5 & LOBITS) = display0
        depth +=1
      }
      ensure0()
    case 2 =>
      if (depth == 2) {
        display2 = new Array(BLOCK)
        display2(oldIndex >> 10 & LOBITS) = display1
        depth +=1
      }
      ensure1(display2(newIndex >> 10 & LOBITS))
      ensure0()
    case 3 =>
      if (depth == 3) {
        display3 = new Array(BLOCK)
        display3(oldIndex >> 15 & LOBITS) = display2
        depth +=1
      }
      ensure2(display3(newIndex >> 15 & LOBITS))
      ensure1(display2(newIndex >> 10 & LOBITS))
      ensure0()
    case 4 =>
      if (depth == 4) {
        display4 = new Array(BLOCK)
        display4(oldIndex >> 20 & LOBITS) = display3
        depth +=1
      }
      ensure3(display4(newIndex >> 20 & LOBITS))
      ensure2(display3(newIndex >> 15 & LOBITS))
      ensure1(display2(newIndex >> 10 & LOBITS))
      ensure0()
    case 5 =>
      if (depth == 5) {
        display5 = new Array(BLOCK)
        display5(oldIndex >>  25 & LOBITS) = display4
        depth +=1
      }
      ensure4(display5(newIndex >> 25 & LOBITS))
      ensure3(display4(newIndex >> 20 & LOBITS))
      ensure2(display3(newIndex >> 15 & LOBITS))
      ensure1(display2(newIndex >> 10 & LOBITS))
      ensure0()
    case x =>
      illegalArgumentException(x)
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy