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

kdtree_2.11.1.0.5.source-code.DimensionalOrdering.scala Maven / Gradle / Ivy

The newest version!
package com.thesamet.spatial

import scala.annotation.tailrec
import scala.language.implicitConversions

/** DimensionalOrdering is a trait whose instances each represent a strategy for ordering instances
  * of a multidimensional type by a projection on a given dimension.
  */
trait DimensionalOrdering[A] extends Serializable{
  /** How many dimensions type A has. */
  def dimensions: Int

  /** Returns an integer whose sign communicates how x's projection on a given dimension compares
    * to y's.
    *
    * Denote the projection of x and y on `dimension` by x' and y' respectively. The result sign has
    * the following meaning:
    *
    * - negative if x' < y'
    * - positive if x' > y'
    * - zero if x' == y'
    */
  def compareProjection(dimension: Int)(x: A, y: A): Int

  /** Returns an Ordering of A in which the given dimension is the primary ordering criteria.
    * If x and y have the same projection on that dimension, then they are compared on the lowest
    * dimension that is different.
    */
  def orderingBy(dimension: Int): Ordering[A] = new Ordering[A] {
    def compare(x: A, y: A): Int = {
      @tailrec
      def compare0(cd: Int): Int = {
        if (cd == dimensions) 0
        else {
          val c = compareProjection(cd)(x, y)
          if (c != 0) c
          else compare0(cd + 1)
        }
      }

      compareProjection(dimension)(x, y) match {
        case t if t != 0 => t
        case 0 => compare0(0)
      }
    }
  }
}

object DimensionalOrdering {
  def dimensionalOrderingForTuple[T <: Product, A](dim: Int)(implicit ord: Ordering[A]): DimensionalOrdering[T] =
    new DimensionalOrdering[T] {
      val dimensions = dim

      def compareProjection(d: Int)(x: T, y: T) = ord.compare(
        x.productElement(d).asInstanceOf[A], y.productElement(d).asInstanceOf[A])
    }

  def dimensionalOrderingForSeq[T <: Seq[A], A](dim: Int)(implicit ord: Ordering[A]): DimensionalOrdering[T] =
    new DimensionalOrdering[T] {
      val dimensions = dim
      
      def compareProjection(d: Int)(x: T, y: T) = ord.compare(
        x(d), y(d))
    }

  implicit def dimensionalOrderingForTuple2[A](implicit ord: Ordering[A]): DimensionalOrdering[(A, A)] =
    dimensionalOrderingForTuple[(A, A), A](2)

  implicit def dimensionalOrderingForTuple3[A](implicit ord: Ordering[A]): DimensionalOrdering[(A, A, A)] =
    dimensionalOrderingForTuple[(A, A, A), A](3)

  implicit def dimensionalOrderingForTuple4[A](implicit ord: Ordering[A]): DimensionalOrdering[(A, A, A, A)] =
    dimensionalOrderingForTuple[(A, A, A, A), A](4)

  implicit def dimensionalOrderingForTuple5[A](implicit ord: Ordering[A]): DimensionalOrdering[(A, A, A, A, A)] =
    dimensionalOrderingForTuple[(A, A, A, A, A), A](5)
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy