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

de.sciss.lucre.geom.LongSpace.scala Maven / Gradle / Ivy

/*
 *  LongSpace.scala
 *  (LucreData)
 *
 *  Copyright (c) 2011-2014 Hanns Holger Rutz. All rights reserved.
 *
 *  This software is published under the GNU Lesser General Public License v2.1+
 *
 *
 *  For further information, please contact Hanns Holger Rutz at
 *  [email protected]
 */

package de.sciss.lucre
package geom

import annotation.tailrec
import de.sciss.serial.{DataInput, DataOutput, ImmutableSerializer}

/**
 * Provides spaces in which coordinates are expressed using `Long` values.
 * Note that the current implementation due to performance considerations
 * requires that the coordinates are clipped to 62-bit range. That is,
 * they should be >= -0x2000000000000000L and < 0x2000000000000000L
 */
object LongSpace {
  sealed trait TwoDim extends Space[TwoDim] {
    type PointLike      = LongPoint2DLike
    type Point          = LongPoint2D
    type HyperCubeLike  = LongSquareLike
    type HyperCube      = LongSquare
  }

  implicit object TwoDim extends TwoDim {
    final val maxPoint  = LongPoint2D(Long.MaxValue, Long.MaxValue)
    final val dim       = 2

    implicit object lexicalOrder extends Ordering[LongPoint2DLike] {
      def compare(a: LongPoint2DLike, b: LongPoint2DLike): Int = {
        val ax = a.x
        val bx = b.x
        if (ax < bx) -1 else if (ax > bx) 1 else {
          val ay = a.y
          val by = b.y
          if (ay < by) -1 else if (ay > by) 1 else 0
        }
      }
    }


    implicit object pointSerializer extends ImmutableSerializer[LongPoint2D] {
      def read(in: DataInput): LongPoint2D = {
        val x = in.readLong()
        val y = in.readLong()
        LongPoint2D(x, y)
      }

      def write(p: LongPoint2D, out: DataOutput): Unit = {
        out.writeLong(p.x)
        out.writeLong(p.y)
      }
    }

    implicit object hyperCubeSerializer extends ImmutableSerializer[LongSquare] {
      def read(in: DataInput): LongSquare = {
        val cx = in.readLong()
        val cy = in.readLong()
        val extent = in.readLong()
        LongSquare(cx, cy, extent)
      }

      def write(q: LongSquare, out: DataOutput): Unit = {
        out.writeLong(q.cx)
        out.writeLong(q.cy)
        out.writeLong(q.extent)
      }
    }
  }

  /**
   * A helper method which efficiently calculates the unique integer in an interval [a, b] which has
   * the maximum number of trailing zeros in its binary representation (a and b are integers > 0).
   * This is used by the `HyperCube` implementations to find the greatest interesting square for
   * two given children.
   *
   * Thanks to Rex Kerr and Daniel Sobral
   * ( http://stackoverflow.com/questions/6156502/integer-in-an-interval-with-maximized-number-of-trailing-zero-bits )
   */
  def binSplit(a: Long, b: Long): Long = binSplitRec(a, b, 0xFFFFFFFF00000000L, 16)

  @tailrec private def binSplitRec(a: Long, b: Long, mask: Long, shift: Int): Long = {
    val gt = a > (b & mask)
    if (shift == 0) {
      if (gt) mask >> 1 else mask
    } else {
      binSplitRec(a, b, if (gt) mask >> shift else mask << shift, shift >> 1)
    }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy