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

breeze.linalg.Vector.scala Maven / Gradle / Ivy

The newest version!
package breeze.linalg
/*
 Copyright 2012 David Hall

 Licensed under the Apache License, Version 2.0 (the "License")
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

 http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
*/
import operators._
import scala.{specialized=>spec}
import breeze.generic.CanMapValues
import breeze.math.{TensorSpace, Ring, Field}
import collection.immutable.BitSet
import support.{CanZipMapValues, CanCopy}
import util.Random
import breeze.storage.{DefaultArrayValue, Storage}
import scala.reflect.ClassTag
import breeze.stats.distributions.Rand

/**
 * Trait for operators and such used in vectors.
 * @author dlwh
 */
trait VectorLike[@spec E, +Self <: Vector[E]] extends Tensor[Int, E] with TensorLike[Int, E, Self] {
  def map[E2, That](fn: E=>E2)(implicit canMapValues: CanMapValues[Self, E, E2, That]):That = values map fn

  def foreach[U](fn: E=>U) { values foreach fn }

  def copy: Self
}


/**
 * A Vector represents the mathematical concept of a vector in math.
 * @tparam E
 */
trait Vector[@spec(Int, Double, Float) E] extends VectorLike[E, Vector[E]]{

  /**
   * @return the set of keys in this vector (0 until length)
   */
  def keySet: Set[Int] = BitSet( (0 until length) :_*)

  def length: Int
  override def size = length

  def iterator = Iterator.range(0, size).map{i => i -> apply(i)}

  def valuesIterator = Iterator.range(0, size).map{i => apply(i)}

  def keysIterator = Iterator.range(0, size)


  override def equals(p1: Any) = p1 match {
    case x: Vector[_] =>
        this.length == x.length &&
          (valuesIterator sameElements x.valuesIterator)
    case _ => false
  }



  /** Returns the k-norm of this Vector. */
  def norm(n : Double)(implicit field: Ring[E]) : Double = {
    if (n == 1) {
      var sum = 0.0
      activeValuesIterator foreach (v => sum += field.norm(v))
      sum
    } else if (n == 2) {
      var sum = 0.0
      activeValuesIterator foreach (v => { val nn = field.norm(v); sum += nn * nn })
      math.sqrt(sum)
    } else if (n == Double.PositiveInfinity) {
      var max = Double.NegativeInfinity
      activeValuesIterator foreach (v => { val nn = field.norm(v); if (nn > max) max = nn })
      max
    } else {
      var sum = 0.0
      activeValuesIterator foreach (v => { val nn = field.norm(v); sum += math.pow(nn,n) })
      math.pow(sum, 1.0 / n)
    }
  }

  def toDenseVector(implicit cm: ClassTag[E]) = {
    new DenseVector(toArray)
  }

  def toArray(implicit cm: ClassTag[E]) = {
    val result = new Array[E](length)
    var i = 0
    while(i < length) {
      result(i) = apply(i)
      i += 1
    }
    result
  }

}

object Vector extends VectorOps_Int 
                      with VectorOps_Double 
                      with VectorOps_Float 
                      with VectorOps_Complex {

  implicit def canCopy[E]:CanCopy[Vector[E]] = new CanCopy[Vector[E]] {
    // Should not inherit from T=>T because those get  used by the compiler.
    def apply(t: Vector[E]): Vector[E] = t.copy
  }

  // There's a bizarre error specializing float's here.
  class CanZipMapValuesVector[@specialized(Int, Double) V, @specialized(Int, Double) RV:ClassTag] extends CanZipMapValues[Vector[V],V,RV,Vector[RV]] {
    def create(length : Int) = new DenseVector(new Array[RV](length))

    /**Maps all corresponding values from the two collection. */
    def map(from: Vector[V], from2: Vector[V], fn: (V, V) => RV) = {
      require(from.length == from2.length, "Vector lengths must match!")
      val result = create(from.length)
      var i = 0
      while (i < from.length) {
        result.data(i) = fn(from(i), from2(i))
        i += 1
      }
      result
    }
  }

  implicit def canMapValues[V, V2](implicit man: ClassTag[V2]):CanMapValues[Vector[V], V, V2, Vector[V2]] = {
    new CanMapValues[Vector[V], V, V2, Vector[V2]] {
      /**Maps all key-value pairs from the given collection. */
      def map(from: Vector[V], fn: (V) => V2) = {
        DenseVector.tabulate(from.length)(i => fn(from(i)))
      }

      /**Maps all active key-value pairs from the given collection. */
      def mapActive(from: Vector[V], fn: (V) => V2) = {
        map(from, fn)
      }
    }
  }

  implicit def negFromScale[@specialized(Int, Float, Double) V, Double](implicit scale: BinaryOp[Vector[V], V, OpMulScalar, Vector[V]], field: Ring[V]) = {
    new UnaryOp[Vector[V], OpNeg, Vector[V]] {
      override def apply(a : Vector[V]) = {
        scale(a, field.negate(field.one))
      }
    }
  }


  implicit def zipMap[V, R:ClassTag] = new CanZipMapValuesVector[V, R]
  implicit val zipMap_d = new CanZipMapValuesVector[Double, Double]
  implicit val zipMap_f = new CanZipMapValuesVector[Float, Float]
  implicit val zipMap_i = new CanZipMapValuesVector[Int, Int]


  implicit val space_d = TensorSpace.make[Vector[Double], Int, Double]
  implicit val space_f = TensorSpace.make[Vector[Float], Int, Float]
  implicit val space_i = TensorSpace.make[Vector[Int], Int, Int]

}


/**
 * Trait that can mixed to companion objects to enable utility methods for creating vectors.
 * @tparam Vec
 */
trait VectorConstructors[Vec[T]<:Vector[T]] {
  /**
   * Creates a Vector of size size.
   * @param size
   * @tparam V
   * @return
   */
  def zeros[V:ClassTag:DefaultArrayValue](size: Int):Vec[V]

  /**
   * Creates a vector with the specified elements
   * @param values
   * @tparam V
   * @return
   */
  def apply[@spec(Double, Int, Float) V](values: Array[V]):Vec[V]

  /**
   * Creates a vector with the specified elements
   * @param values
   * @tparam V
   * @return
   */
  def apply[V:ClassTag](values: V*):Vec[V] = {
    // manual specialization so that we create the right DenseVector specialization... @specialized doesn't work here
    val man = implicitly[ClassTag[V]]
    if(man == manifest[Double]) apply(values.toArray.asInstanceOf[Array[Double]]).asInstanceOf[Vec[V]]
    else if (man == manifest[Float]) apply(values.toArray.asInstanceOf[Array[Float]]).asInstanceOf[Vec[V]]
    else if (man == manifest[Int]) apply(values.toArray.asInstanceOf[Array[Int]]).asInstanceOf[Vec[V]]
    else apply(values.toArray)
//     apply(values.toArray)
  }

  /**
   * Analogous to Array.fill
   * @param size
   * @param v
   * @tparam V
   * @return
   */
  def fill[@spec(Double, Int, Float) V:ClassTag](size: Int)(v: =>V):Vec[V] = apply(Array.fill(size)(v))

  /**
   * Analogous to Array.tabulate
   * @param size
   * @param f
   * @tparam V
   * @return
   */
  def tabulate[@spec(Double, Int, Float) V:ClassTag](size: Int)(f: Int=>V):Vec[V]= apply(Array.tabulate(size)(f))

  /**
   * Creates a Vector of uniform random numbers in (0,1)
   * @param size
   * @param rand
   * @return
   */
  def rand[T:ClassTag](size: Int, rand: Rand[T] = Rand.uniform) = {
    // Array#fill is slow.
    val arr = new Array[T](size)
    var i = 0
    while(i < arr.length) {
      arr(i) = rand.draw()
      i += 1
    }

    apply(arr)
  }

  def range(start:Int, end: Int): Vec[Int] = range(start,end,1)
  def range(start:Int, end: Int, step: Int): Vec[Int] = apply[Int](Array.range(start,end,step))


}

trait StorageVector[E] extends Vector[E] with Storage[E]




© 2015 - 2025 Weber Informatics LLC | Privacy Policy