【scala中文源码系列】 breeze.linalg.DenseVector 用法示例源码详解

breeze.linalg.DenseVector 用法示例源码详解

构造函数

构造函数描述
new DenseVector(data: Array[E], offset: Int)创建一个具有给定数据和偏移量的稠密向量。
new DenseVector(data: Array[E])创建一个具有给定数据的稠密向量,偏移量为0。
new DenseVector(data: Array[E], offset: Int, stride: Int, length: Int)创建一个具有给定数据、偏移量、步幅和长度的稠密向量。

以上是DenseVector类的实例构造函数及其描述。这些构造函数用于创建新的DenseVector对象,并根据提供的参数初始化向量的属性。

方法总结

方法描述
%(b)对每个元素取模,当 b 是标量时的别名。
%=(b)对每个元素进行取模并将结果赋值给当前向量,当 b 是标量时的别名。
&(b)对每个元素进行逻辑与操作,对所有的 b 都是 :&&(b) 的别名。
&=(b)将当前向量和 b 逐元素进行与运算,并将结果赋值给当前向量。
*(b)矩阵乘法。
*=(b)b 是标量时,将当前向量每个元素与 b 相乘并将结果赋值给当前向量的每个元素,即逐元素乘法。
+(b)对每个元素进行求和,对所有的 b 都是 :+(b) 的别名。
+=(b)将当前向量和 b 逐元素相加,并将结果赋值给当前向量。
-(b)对每个元素进行求差,对所有的 b 都是 :-(b) 的别名。
-=(b)将当前向量和 b 逐元素相减,并将结果赋值给当前向量。
/(b)对每个元素进行求商,当 b 是标量时的别名。
/=(b)将当前向量每个元素除以 b 并将结果赋值给当前向量的每个元素,即逐元素除法。
:!=(b)对当前向量和 b 进行逐元素不等比较。
%(b)对当前向量和 b 进行逐元素取模。
%=(b)将当前向量每个元素取模并将结果赋值给当前向量的每个元素,即逐元素取模。
&(b)对当前向量和 b 进行逐元素与运算,返回 true 如果对应元素都非零。
&=(b)将当前向量和 b 逐元素进行与运算,并将结果赋值给当前向量。
*(b)对当前向量和 b 进行逐元素乘法。
*=(b)b 是标量时,将当前向量每个元素与 b 相乘并将结果赋值给当前向量的每个元素,即逐元素乘法。
+(b)对当前向量和 b 进行逐元素加法。
+=(b)将当前向量和 b 逐元素相加,并将结果赋值给当前向量。
-(b)对当前向量和 b 进行逐元素减法。
-=(b)将当前向量和 b 逐元素相减,并将结果赋值给当前向量。
/(b)对当前向量和 b 进行逐元素除法,当 b 是标量时的别名。
/=(b)将当前向量每个元素除以 b 并将结果赋值给当前向量的每个元素,即逐元素除法。
:!=(b)对当前向量和 b 进行逐元素不等比较。
:%(b)对当前向量和 b 进行逐元素取模。
:%=(b)将当前向量每个元素取模并将结果赋值给当前向量的每个元素,即逐元素取模。
:&(b)对当前向量和 b 进行逐元素与运算,返回 true 如果对应元素都非零。
:&=(b)将当前向量和 b 逐元素进行与运算,并将结果赋值给当前向量。
:*(b)对当前向量和 b 进行逐元素乘法。
:*=(b)b 是标量时,将当前向量每个元素与 b 相乘并将结果赋值给当前向量的每个元素,即逐元素乘法。
:+(b)对当前向量和 b 进行逐元素加法。
:+=(b)将当前向量和 b 逐元素相加,并将结果赋值给当前向量。
:-(b)对当前向量和 b 进行逐元素减法。
:-=(b)将当前向量和 b 逐元素相减,并将结果赋值给当前向量。
:/(b)对当前向量和 b 进行逐元素除法,当 b 是标量时的别名。
:/=(b)将当前向量每个元素除以 b 并将结果赋值给当前向量的每个元素,即逐元素除法。
:!=(b)对当前向量和 b 进行逐元素不等比较。
:<(b)对当前向量和 b 进行逐元素小于比较。
:<=(b)对当前向量和 b 进行逐元素小于等于比较。
:=(b)将当前向量每个元素赋值为 b 并将结果赋值给当前向量的每个元素,即逐元素赋值。
:==(b)对当前向量和 b 进行逐元素等于比较。
:>(b)对当前向量和 b 进行逐元素大于比较。
:>=(b)对当前向量和 b 进行逐元素大于等于比较。
:^(b)`对当前向量和 b 进行逐元素幂运算。
:^=(b)将当前向量每个元素的幂指数设为 b 并将结果赋值给当前向量的每个元素,即逐元素幂运算。
:^^(b)对当前向量和 b 进行逐元素异或运算。
:^^=(b)将当前向量和 b 逐元素进行异或运算,并将结果赋值给当前向量。
`:(b)
`:=(b)`
\[TT >: DenseVector[E], B, That](b: B)求解方程组。
:^^(b)`对当前向量和 b 进行逐元素异或运算。
:^^=(b)将当前向量和 b 逐元素进行异或运算,并将结果赋值给当前向量。
active返回一个表示稀疏向量中非零元素的 TensorActive 对象。
activeIterator返回迭代器,遍历稀疏向量中的非零元素。
activeKeysIterator返回迭代器,遍历稀疏向量中非零元素的索引。
activeSize返回稀疏向量中非零元素的数量。
apply(i)获取指定索引位置的元素。
apply[Slice1, Slice2, Result](slice1, slice2)切片操作,针对矩阵进行了优化。
apply[Result](a: Int, slice: Int*)对一系列元素进行切片。
apply[Slice, Result](slice)对张量进行切片。
argmax返回向量中最大元素的索引。
argmin返回向量中最小元素的索引。
argsort返回向量按升序排序后的索引序列。
argtopk(k)返回最大的 k 个元素的索引。
asDenseMatrix创建一个表示当前向量的 1xlength 的 DenseMatrix 视图。
copy返回当前向量的副本。
data返回底层数据数组。
dot(b)计算当前向量和另一个向量 b 的内积。
equals(p1)检查当前向量是否与另一个对象相等。
findAll(f)返回满足给定条件的元素的索引序列。
forall(fn)判断是否对所有元素都满足给定的条件。
forallValues(fn)判断是否对所有元素的值都满足给定的条件。
foreach(fn)对每个元素应用指定的函数,更快的迭代方式。
foreachKey(fn)对张量中的每个键应用给定的函数。
foreachPair(fn)对张量中的每个键值对应用给定的函数。
foreachValue(fn)对张量中的每个值应用给定的函数。
indexAt(i)根据物理索引返回逻辑索引。
isActive(i)始终返回 true。
iterableSize返回需要使用 valueAtindexAt 进行迭代的元素数量。
iterator返回一个迭代器,遍历稀疏向量中的键值对。
keySet返回稀疏向量中非零元素的索引集合。
keys返回表示稀疏向量键的 TensorKeys 对象。
keysIterator返回迭代器,遍历稀疏向量中非零元素的索引。
length返回向量的长度。
map(fn)对当前向量的每个元素应用给定的函数,并返回结果向量。
mapActivePairs(f)对稀疏向量中的每对非零键值对进行映射。
mapActiveValues(f)对稀疏向量中的每个非零值进行映射。
mapPairs(f)创建一个包含对当前向量每个键值对应用给定函数的新向量。
mapValues(f)创建一个包含对当前向量每个值应用给定函数的新向量。
max返回向量中的最大值。
min返回向量中的最小值。
norm(b)计算向量的范数。
norm()计算向量的“自然”范数,对于不支持任意范数的类型使用。
offset返回第一个元素的索引。
pairs返回表示稀疏向量键值对的 TensorPairs 对象。
repr返回当前向量的副本。
size返回稀疏向量中非零元素的数量。
slice(start, end, stride)对向量进行切片操作。
stride返回元素之间的分隔距离。
sum返回向量中所有元素的总和。
t返回转置后的当前对象。
toArray将当前向量转换为数组。
toDenseMatrix创建一个表示当前向量的 1xlength 的 DenseMatrix 的副本。
toDenseVector返回当前向量的副本。
toString()返回向量的字符串表示形式。
unary_!对当前向量应用逻辑非运算。
unary_-对当前向量应用一元负运算。
update(i, v)更新指定索引位置的元素。
valueAt(i)获取指定索引位置的元素。
values返回表示稀疏向量值的 TensorValues 对象。
valuesIterator返回迭代器,遍历稀疏向量中的值。
`(b)`
`=(b)`

以上是DenseVector类中可用的方法及其描述。这些方法可以对DenseVector对象执行各种操作,如数学运算、切片、迭代等。

示例

package org.example.spark

import breeze.numerics.pow

object BreezeDenseVectorTest {
  import breeze.linalg._

    def main(args: Array[String]): Unit = {
      // 示例1:创建稠密向量
      val vec1 = DenseVector(1, 2, 3, 4, 5)

      // 示例2:向量加法
      val vec2 = DenseVector(2, 4, 6, 8, 10)
      val sum = vec1 + vec2

      // 示例3:点积运算
      val dotProduct = vec1 dot vec2

      // 示例4:逐元素乘法
      val elementWiseProduct = vec1 :* vec2

      // 示例5:切片操作
      val slicedVec = vec1(1 to 3)

      // 示例6:范数计算
      val norm = breeze.linalg.norm(vec1)

      // 示例7:元素求和
      val vec3 = DenseVector(1, 2, 3, 4, 5)
      val sumElements = breeze.linalg.sum(vec3)

      // 示例8:最大值和最小值
      val maxVal = breeze.linalg.max(vec1)
      val minVal = breeze.linalg.min(vec1)

      // 示例9:判断所有元素是否满足条件
      val allEven = vec1.forall(_ % 2 == 0)

      // 示例10:遍历向量
      vec1.foreach(println)

      // 示例11:取反
      val negVec = -vec1

      // 示例12:除法
      val divided = vec2 / 2

      // 示例15:查找元素的索引
      val index = vec1.findAll( x => x > 3)

      // 示例17:拷贝向量
      val copyVec = copy(vec1)

      // 示例18:转换为数组
      val array = vec1.toArray

      // 示例19:转置向量
      val transposed = vec1.t

      // 示例20:判断向量相等
      val equal = vec1 == vec2

      // 示例21:获取指定索引位置的元素
      val elementAtIndex = vec1(2)

      // 示例22:更新指定索引位置的元素
      vec1(3) = 10

      // 示例23:获取非零元素的数量
      val activeSize = vec1.activeSize

      // 示例24:获取所有非零元素的索引
      val activeKeys = vec1.activeKeysIterator.toIndexedSeq

      // 示例25:获取所有非零元素的值
      val activeValues = vec1.activeValuesIterator.toIndexedSeq

      // 示例26:对所有非零元素进行迭代
      vec1.activeIterator.foreach(println)

      // 示例27:对非零元素应用函数
      val mappedActive = vec1.activeValuesIterator.map(_ * 2).toIndexedSeq

      // 示例28:获取向量的长度
      val length = vec1.length

      // 示例31:将稠密向量转换为稀疏向量并返回非零元素的数量
      val nnz = vec1.activeSize

      // 示例32:计算向量的平方
      val squaredVec = vec1.mapValues(x => x * x)

      // 示例33:对每个元素应用函数并生成新的向量
      val mappedVec = vec1.map(_ * 2)

      // 示例34:获取最大元素的索引
      val argmax = breeze.linalg.argmax(vec1)

      // 示例35:获取最小元素的索引
      val argmin = breeze.linalg.argmin(vec1)

      // 示例36:判断所有元素是否都满足条件
      val allPositive = vec1.forall(_ > 0)

      // 示例37:判断是否存在满足条件的元素
      val existsEven = vec1.exists(_ % 2 == 0)

      // 示例38:返回非零元素的副本
      val activeCopy = vec1.active

      // 示例39:根据索引获取元素
      val valueAtIndex = vec1.apply(2)

      // 示例40:判断两个向量是否逐元素相等
      val isEqual = vec1 == vec2

      // 示例41:对向量进行求和
      val totalSum =  breeze.linalg.sum(vec1)

      // 示例42:对向量进行求差
      val diff = vec1 - vec2

      // 示例43:对向量进行求积
      val product = vec1 * vec2

      // 示例44:对向量进行取模
      val modResult = vec1 % 3

      // 示例45:对向量进行乘方
      val powResult = pow(vec1, 2)

      // 示例46:判断两个向量是否逐元素不等
      val notEqual = vec1 :!= vec2

      // 示例47:将向量转换为字符串
      val str = vec1.toString()

      // 示例48:将向量转换为数组
      val arrayVec = vec1.toArray

      // 示例49:获取向量的维度
      val dim = vec1.size

      // 示例50:将向量转置
      val transposedVec = vec1.t

      // 输出结果
      println("vec1: " + vec1)
      println("vec2: " + vec2)
      println("sum: " + sum)
      println("dotProduct: " + dotProduct)
      println("elementWiseProduct: " + elementWiseProduct)
      println("slicedVec: " + slicedVec)
      println("norm: " + norm)
      println("sumElements: " + sumElements)
      println("maxVal: " + maxVal)
      println("minVal: " + minVal)
      println("allEven: " + allEven)
      println("negVec: " + negVec)
      println("divided: " + divided)
      println("index: " + index)
      println("copyVec: " + copyVec)
      println("array: " + array.mkString(", "))
      println("transposed: " + transposed)
      println("equal: " + equal)
      println("elementAtIndex: " + elementAtIndex)
      println("activeSize: " + activeSize)
      println("activeKeys: " + activeKeys.mkString(", "))
      println("activeValues: " + activeValues.mkString(", "))
      println("mappedActive: " + mappedActive.mkString(", "))
      println("length: " + length)
      println("nnz: " + nnz)
      println("squaredVec: " + squaredVec)
      println("mappedVec: " + mappedVec)
      println("argmax: " + argmax)
      println("argmin: " + argmin)
      println("allPositive: " + allPositive)
      println("existsEven: " + existsEven)
      println("activeCopy: " + activeCopy)
      println("valueAtIndex: " + valueAtIndex)
      println("isEqual: " + isEqual)
      println("totalSum: " + totalSum)
      println("diff: " + diff)
      println("product: " + product)
      println("modResult: " + modResult)
      println("powResult: " + powResult)
      println("notEqual: " + notEqual)
      println("str: " + str)
      println("arrayVec: " + arrayVec.mkString(", "))
      println("dim: " + dim)
      println("transposedVec: " + transposedVec)
    }
}
//1
//2
//3
//4
//5
//(0,1)
//(1,2)
//(2,3)
//(3,10)
//(4,5)
//vec1: DenseVector(1, 2, 3, 10, 5)
//vec2: DenseVector(2, 4, 6, 8, 10)
//sum: DenseVector(3, 6, 9, 12, 15)
//dotProduct: 110
//elementWiseProduct: DenseVector(2, 8, 18, 32, 50)
//slicedVec: DenseVector(2, 3, 10)
//norm: 7.416198487095663
//sumElements: 15
//maxVal: 5
//minVal: 1
//allEven: false
//negVec: DenseVector(-1, -2, -3, -4, -5)
//divided: DenseVector(1, 2, 3, 4, 5)
//index: Vector(3, 4)
//copyVec: DenseVector(1, 2, 3, 4, 5)
//array: 1, 2, 3, 4, 5
//transposed: Transpose(DenseVector(1, 2, 3, 10, 5))
//equal: false
//elementAtIndex: 3
//activeSize: 5
//activeKeys: 0, 1, 2, 3, 4
//activeValues: 1, 2, 3, 10, 5
//mappedActive: 2, 4, 6, 20, 10
//length: 5
//nnz: 5
//squaredVec: DenseVector(1, 4, 9, 100, 25)
//mappedVec: DenseVector(2, 4, 6, 20, 10)
//argmax: 3
//argmin: 0
//allPositive: true
//existsEven: true
//activeCopy: breeze.linalg.support.TensorActive@6a370f4
//valueAtIndex: 3
//isEqual: false
//totalSum: 21
//diff: DenseVector(-1, -2, -3, 2, -5)
//product: DenseVector(2, 8, 18, 80, 50)
//modResult: DenseVector(1, 2, 0, 1, 2)
//powResult: DenseVector(1, 4, 9, 100, 25)
//notEqual: BitVector(0, 1, 2, 3, 4)
//str: DenseVector(1, 2, 3, 10, 5)
//arrayVec: 1, 2, 3, 10, 5
//dim: 5
//transposedVec: Transpose(DenseVector(1, 2, 3, 10, 5))

源码

import breeze.generic.UFunc.SinkImpl2
import scala.{specialized=>spec}
import breeze.generic._
import breeze.linalg.support._
import breeze.linalg.operators._
import breeze.math._
import breeze.util.{ArrayUtil, Isomorphism}
import breeze.storage.Zero
import scala.reflect.ClassTag
import com.github.fommil.netlib.BLAS.{getInstance => blas}
import breeze.macros.expand
import scala.math.BigInt
import spire.syntax.cfor._
import CanTraverseValues.ValuesVisitor
import CanZipAndTraverseValues.PairValuesVisitor
import java.io.ObjectStreamException
import scalaxy.debug._

/**
 * 一个DenseVector是Vector的一种"明显"实现,但有一个区别。
 * 底层数据可能比Vector有更多的数据,使用数组的偏移量(offset)和步长(stride)表示(对于第0个元素)。
 *
 * 第i个元素在offset + i * stride位置
 *
 * @param data 数据数组
 * @param offset 第0个元素的索引
 * @param stride 元素之间的间隔
 * @param length 元素数量
 */
@SerialVersionUID(1L) // TODO: scala doesn't propagate this to specialized subclasses. Sigh.
class DenseVector[@spec(Double, Int, Float, Long) V](val data: Array[V],
                                               val offset: Int,
                                               val stride: Int,
                                               val length: Int) extends StorageVector[V]
                                              with VectorLike[V, DenseVector[V]] with Serializable{
  def this(data: Array[V]) = this(data, 0, 1, data.length)
  def this(data: Array[V], offset: Int) = this(data, offset, 1, data.length)
  def this(length: Int)(implicit man: ClassTag[V]) = this(new Array[V](length), 0, 1, length)



  // 确保所有运算符都加载了
  DenseVector.init()

  def repr: DenseVector[V] = this

  def activeSize = length

  def apply(i: Int): V = {
    if(i < - size || i >= size) throw new IndexOutOfBoundsException(i + " not in [-"+size+","+size+")")
    val trueI = if(i<0) i+size else i
    if (noOffsetOrStride) {
      data(trueI)
    } else {
      data(offset + trueI * stride)
    }
  }

  def update(i: Int, v: V): Unit = {
    if(i < - size || i >= size) throw new IndexOutOfBoundsException(i + " not in [-"+size+","+size+")")
    val trueI = if(i<0) i+size else i
    if (noOffsetOrStride) {
      data(trueI) = v
    } else {
      data(offset + trueI * stride) = v
    }
  }

  private[linalg] val noOffsetOrStride = offset == 0 && stride == 1
  @deprecated("This isn't actually any faster any more", "0.12-SNAPSHOT")
  def unsafeUpdate(i: Int, v: V): Unit = if (noOffsetOrStride) data(i) = v else data(offset+i*stride) = v

  private def checkIfSpecialized(): Unit = {
    if(data.isInstanceOf[Array[Double]] && getClass.getName() == "breeze.linalg.DenseVector") throw new Exception("...")
  }
  // uncomment to debug places where specialization fails
  //  checkIfSpecialized()


  def activeIterator: Iterator[(Int, V)] = iterator

  def activeValuesIterator: Iterator[V] = valuesIterator

  def activeKeysIterator: Iterator[Int] = keysIterator

  override def equals(p1: Any) = p1 match {
    case y: DenseVector[_] =>
      y.length == length && ArrayUtil.nonstupidEquals(data, offset, stride, length, y.data, y.offset, y.stride, y.length)
    case _ => super.equals(p1)
  }


  // TODO: this is only consistent if the hashcode of inactive elements is 0!!!
  override def hashCode(): Int = ArrayUtil.zeroSkippingHashCode(data, offset, stride, length)

  override def toString = {
    valuesIterator.mkString("DenseVector(",", ", ")")
  }

  /**
   * 返回此DenseVector的副本。步长将始终为1,偏移量将始终为0。
   * @return
   */
  def copy: DenseVector[V] = {
    if (stride == 1) {
      val newData = ArrayUtil.copyOfRange(data, offset, offset + length)
      new DenseVector(newData)
    } else {
      implicit val man = ClassTag[V](data.getClass.getComponentType.asInstanceOf[Class[V]])
      val r = new DenseVector(new Array[V](length))
      r := this
      r
    }
  }

  /**
   * 同apply(i)。给出底层偏移处的值。
   * @param i 数据数组的索引
   * @return apply(i)
   */
  def valueAt(i: Int): V = apply(i)

  /**
    * 上面的不安全版本,用于跳过检查的方法。
    */
  @deprecated("This isn't actually any faster any more", "0.12-SNAPSHOT")
  def unsafeValueAt(i: Int): V = data(offset + i * stride)

  /**
   * 给出物理索引的逻辑索引。
   * @param i
   * @return i
   */
  def indexAt(i: Int): Int = i

  /**
   * 总是返回true。
   *
   * 一些存储(特别是HashStorage)可能没有活动的索引打包。这让你知道该箱是否正在使用中。
   * @param i 索引到索引/数据数组
   * @return
   */
  def isActive(i: Int): Boolean = true


  /**
   * 总是返回true。
   * @return
   */
  def allVisitableIndicesActive: Boolean = true

  /**
   * 更快的foreach
   * @param fn
   * @tparam U
   */
  override def foreach[@spec(Unit) U](fn: (V) => U): Unit = {
    if (stride == 1) { // ABCE stuff
      cforRange(offset until (offset + length)) { j =>
        fn(data(j))
      }
    } else {
      var i = offset
      cforRange(0 until length) { j =>
        fn(data(i))
        i += stride
      }
    }
  }

  /**
   * 切片DenseVector,在[start,end]范围内以步长stride。
   * @param start
   * @param end
   * @param stride
   */
  def slice(start: Int, end: Int, stride: Int=1): DenseVector[V] = {
    if(start > end || start < 0) throw new IllegalArgumentException("Slice arguments " + start +", " +end +" invalid.")
    if(end > length || end < 0) throw new IllegalArgumentException("End " + end + "is out of bounds for slice of DenseVector of length " + length)
    new DenseVector(data, start * this.stride + offset, stride * this.stride, (end-start)/stride)
  }

  // <editor-fold defaultstate="collapsed" desc=" Conversions (DenseMatrix, Array, Scala Vector) ">

  /** Creates a copy of this DenseVector that is represented as a 1 by length DenseMatrix */
  def toDenseMatrix: DenseMatrix[V] = {
     copy.asDenseMatrix
  }

  /** Creates a view of this DenseVector that is represented as a 1 by length DenseMatrix */
  def asDenseMatrix: DenseMatrix[V] = {
    new DenseMatrix[V](1, length, data, offset, stride)
  }



  override def toArray(implicit cm: ClassTag[V]): Array[V] = if(stride == 1){
    ArrayUtil.copyOfRange(data, offset, offset + length)
  } else {
    val arr = new Array[V](length)
    var i = 0
    var off = offset
    while(i < length) {
      arr(i) = data(off)
      off += stride
      i += 1
    }
    arr
  }

  /**Returns copy of this [[breeze.linalg.DenseVector]] as a [[scala.Vector]]*/
  def toScalaVector()(implicit cm: ClassTag[V]): scala.Vector[V] = this.toArray.toVector
  // </editor-fold>

  @throws(classOf[ObjectStreamException])
  protected def writeReplace(): Object = {
    new DenseVector.SerializedForm(data, offset, stride, length)
  }

}



object DenseVector extends VectorConstructors[DenseVector]
                      with DenseVector_GenericOps
                      with DenseVectorOps
                      with DenseVector_OrderingOps
                      with DenseVector_SpecialOps {


  def zeros[@spec(Double, Int, Float, Long) V: ClassTag : Zero](size: Int): DenseVector[V] = {
    val data = new Array[V](size)
    if(size != 0 && data(0) != implicitly[Zero[V]].zero)
      ArrayUtil.fill(data, 0, data.length, implicitly[Zero[V]].zero)
    apply(data)
  }

  def apply[@spec(Double, Int, Float, Long) V](values: Array[V]): DenseVector[V] = {
    // ensure we get specialized implementations even from non-specialized calls
    (values:AnyRef) match {
      case v: Array[Double] => new DenseVector(v).asInstanceOf[DenseVector[V]]
      case v: Array[Float] => new DenseVector(v).asInstanceOf[DenseVector[V]]
      case v: Array[Int] => new DenseVector(v).asInstanceOf[DenseVector[V]]
      case v: Array[Long] => new DenseVector(v).asInstanceOf[DenseVector[V]]
      case _ => new DenseVector(values)
    }
  }

  /**
   *
   * 使用提供的数组创建一个新的DenseVector(不进行复制!)。在通用环境中,最好使用这个(或apply)而不是`new DenseVector[V](data, offset, stride, length)`,因为一般情况下不能得到专门化的实现。
   * @param rows
   * @param cols
   * @param data
   * @tparam V
   * @return
   */
  def create[V](data: Array[V], offset: Int, stride: Int, length: Int): DenseVector[V] = {
    (data:AnyRef) match {
      case v: Array[Double] => new DenseVector(v, offset = offset, stride = stride, length = length).asInstanceOf[DenseVector[V]]
      case v: Array[Float] => new DenseVector(v, offset = offset, stride = stride, length = length).asInstanceOf[DenseVector[V]]
      case v: Array[Int] => new DenseVector(v, offset = offset, stride = stride, length = length).asInstanceOf[DenseVector[V]]
      case v: Array[Long] => new DenseVector(v, offset = offset, stride = stride, length = length).asInstanceOf[DenseVector[V]]
      case _ => new DenseVector(data, offset = offset, stride = stride, length = length)
    }
  }

  def ones[@spec(Double, Int, Float, Long) V: ClassTag:Semiring](size: Int): DenseVector[V] = fill[V](size, implicitly[Semiring[V]].one)

  def fill[@spec(Double, Int, Float, Long) V: ClassTag:Semiring](size: Int, v: V): DenseVector[V] = {
    val r = apply(new Array[V](size))
    assert(r.stride == 1)
    ArrayUtil.fill(r.data, r.offset, r.length, v)
    r
  }

    // concatenation
  /**
   * 将两个或多个向量水平连接成一个矩阵。
   * @throws IllegalArgumentException 如果向量大小不同
   */
  def horzcat[V: ClassTag:Zero](vectors: DenseVector[V]*): DenseMatrix[V] = {
    val size = vectors.head.size
    if (!(vectors forall (_.size == size)))
      throw new IllegalArgumentException("All vectors must have the same size!")
    val result = DenseMatrix.zeros[V](size, vectors.size)
    for ((v, col) <- vectors.zipWithIndex)
      result(::, col) := v
    result
  }

  /**
   * 将两个或多个列向量垂直连接成一个大向量。
   */
  def vertcat[V](vectors: DenseVector[V]*)(implicit canSet: OpSet.InPlaceImpl2[DenseVector[V], DenseVector[V]], vman: ClassTag[V], zero: Zero[V]): DenseVector[V] = {
    val size = vectors.foldLeft(0)(_ + _.size)
    val result = zeros[V](size)
    var offset = 0
    for (v <- vectors) {
      result.slice(offset, offset + v.size) := v
      offset += v.size
    }
    result
  }

  // capabilities

  implicit def canCreateZerosLike[V:ClassTag:Zero]:CanCreateZerosLike[DenseVector[V], DenseVector[V]] =
  new CanCreateZerosLike[DenseVector[V], DenseVector[V]] {
    def apply(v1: DenseVector[V]): DenseVector[V] = {
      zeros[V](v1.length)
    }
  }

  implicit def canCopyDenseVector[V:ClassTag]: CanCopy[DenseVector[V]] = {
    new CanCopy[DenseVector[V]] {
      def apply(v1: DenseVector[V]): DenseVector[V] = {
        v1.copy
      }
    }
  }



  implicit def negFromScale[V](implicit scale: OpMulScalar.Impl2[DenseVector[V], V, DenseVector[V]], field: Ring[V]) = {
    new OpNeg.Impl[DenseVector[V], DenseVector[V]] {
      override def apply(a : DenseVector[V]): DenseVector[V] = {
        scale(a, field.negate(field.one))
      }
    }
  }


  implicit def canMapValues[@specialized(Int, Float, Double) V, @specialized(Int, Float, Double) V2](implicit man: ClassTag[V2]): CanMapValues[DenseVector[V], V, V2, DenseVector[V2]] = {
    new CanMapValues[DenseVector[V], V, V2, DenseVector[V2]] {
      /**Maps all key-value pairs from the given collection. */
      def apply(from: DenseVector[V], fn: (V) => V2): DenseVector[V2] = {
        val out = new Array[V2](from.length)

        // threeway fork, following benchmarks and hotspot docs on Array Bounds Check Elimination (ABCE)
        // https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination
        if (from.noOffsetOrStride) {
          fastestPath(out, fn, from.data)
        } else if (from.stride == 1) {
          mediumPath(out, fn, from.data, from.offset)
        } else {
          slowPath(out, fn, from.data, from.offset, from.stride)
        }
        DenseVector[V2](out)
      }

      private def mediumPath(out: Array[V2], fn: (V) => V2, data: Array[V], off: Int): Unit = {
        cforRange(0 until out.length) { j =>
          out(j) = fn(data(j + off))
        }
      }

      private def fastestPath(out: Array[V2], fn: (V) => V2, data: Array[V]): Unit = {
        cforRange(0 until out.length) { j =>
          out(j) = fn(data(j))
        }
      }

      final private def slowPath(out: Array[V2], fn: (V) => V2, data: Array[V], off: Int, stride: Int): Unit = {
        var i = 0
        var j = off
        while (i < out.length) {
          out(i) = fn(data(j))
          i += 1
          j += stride
        }
      }
    }
  }

  implicit def canMapValuesToSink[@specialized(Int, Float, Double) V, @specialized(Int, Float, Double) V2]: mapValues.SinkImpl2[DenseVector[V2], DenseVector[V], V =>V2] = {
    new mapValues.SinkImpl2[DenseVector[V2], DenseVector[V], V=>V2] {
      /**Maps all key-value pairs from the given collection. */
      def apply(sink: DenseVector[V2], from: DenseVector[V], fn: (V) => V2) = {
        require(sink.length == from.length)

        // threeway fork, following benchmarks and hotspot docs on Array Bounds Check Elimination (ABCE)
        // https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination
        if (sink.noOffsetOrStride && from.noOffsetOrStride) {
          fastestPath(sink, fn, from.data)
        } else if (sink.stride == 1 && from.stride == 1) {
          mediumPath(sink, fn, from.data, from.offset)
        } else {
          slowPath(sink, fn, from.data, from.offset, from.stride)
        }
      }

      private def mediumPath(sink: DenseVector[V2], fn: (V) => V2, data: Array[V], off: Int): Unit = {
        val out = sink.data
        val ooff = sink.offset
        cforRange(0 until sink.length) { j =>
          out(j + ooff) = fn(data(j + off))
        }
      }

      private def fastestPath(sink: DenseVector[V2], fn: (V) => V2, data: Array[V]): Unit = {
        val out = sink.data
        cforRange(0 until sink.length) { j =>
          out(j) = fn(data(j))
        }
      }

      final private def slowPath(out: DenseVector[V2], fn: (V) => V2, data: Array[V], off: Int, stride: Int): Unit = {
        var i = 0
        var j = off
        while (i < out.length) {
          out(i) = fn(data(j))
          i += 1
          j += stride
        }
      }
    }
  }
 
  implicit def scalarOf[T]: ScalarOf[DenseVector[T], T] = ScalarOf.dummy

  implicit def canIterateValues[V]: CanTraverseValues[DenseVector[V], V] =

    new CanTraverseValues[DenseVector[V], V] {

      def isTraversableAgain(from: DenseVector[V]): Boolean = true

      /** 遍历给定集合的所有键值对。 */
      def traverse(from: DenseVector[V], fn: ValuesVisitor[V]): Unit = {
        fn.visitArray(from.data, from.offset, from.length, from.stride)
      }

    }


  implicit def canTraverseZipValues[V,W]: CanZipAndTraverseValues[DenseVector[V], DenseVector[W], V,W] =

    new CanZipAndTraverseValues[DenseVector[V], DenseVector[W], V,W] {
      /** 遍历给定集合的所有键值对。 */
      def traverse(from1: DenseVector[V], from2: DenseVector[W], fn: PairValuesVisitor[V,W]): Unit = {
        if (from1.size != from2.size) {
          throw new IllegalArgumentException("Vectors to be zipped must have same size")
        }
        cfor(0)(i => i < from1.size, i => i+1)(i => {
          fn.visit(from1(i), from2(i))
        })
      }
  }


  implicit def canTraverseKeyValuePairs[V]: CanTraverseKeyValuePairs[DenseVector[V], Int, V] =

    new CanTraverseKeyValuePairs[DenseVector[V], Int, V] {
      def isTraversableAgain(from: DenseVector[V]): Boolean = true

      def traverse(from: DenseVector[V], fn: CanTraverseKeyValuePairs.KeyValuePairsVisitor[Int, V]): Unit = {
        import from._

        fn.visitArray((ind: Int)=> (ind - offset)/stride, data, offset, length, stride)
      }

    }


  implicit def canTransformValues[@specialized(Int, Float, Double) V]: CanTransformValues[DenseVector[V], V] =

    new CanTransformValues[DenseVector[V], V] {
      def transform(from: DenseVector[V], fn: (V) => V) {
        val data = from.data
        val length = from.length
        val stride = from.stride

        val offset = from.offset
        if (stride == 1)  {
          cforRange(offset until offset + length) { j =>
            data(j) = fn(data(j))
          }
        } else {
          slowPath(fn, data, length, stride, offset)
        }
      }

      private def slowPath(fn: (V) => V, data: Array[V], length: Int, stride: Int, offset: Int): Unit = {
        val end = offset + stride * length
        var j = offset
        while (j != end) {
          data(j) = fn(data(j))
          j += stride
        }
      }

      def transformActive(from: DenseVector[V], fn: (V) => V) {
        transform(from, fn)
      }
    }


  implicit def canMapPairs[V, V2](implicit man: ClassTag[V2]):CanMapKeyValuePairs[DenseVector[V], Int, V, V2, DenseVector[V2]] =

    new CanMapKeyValuePairs[DenseVector[V], Int, V, V2, DenseVector[V2]] {
      /**Maps all key-value pairs from the given collection. */
      def map(from: DenseVector[V], fn: (Int, V) => V2): DenseVector[V2] = {
        // slow: DenseVector.tabulate(from.length)(i => fn(i, from(i)))
        val arr = new Array[V2](from.length)

        val d = from.data
        val stride = from.stride

        var i = 0
        var j = from.offset
        while(i < arr.length) {
          arr(i) = fn(i, d(j))
          i += 1
          j += stride
        }
        DenseVector[V2](arr)
      }

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

  // 切片
  // 特殊化以获得好的类
  implicit def canSlice[V]: CanSlice[DenseVector[V], Range, DenseVector[V]] = {
    new CanSlice[DenseVector[V], Range, DenseVector[V]] {
      def apply(v: DenseVector[V], re: Range): DenseVector[V] = {

        val range: Range = re.getRangeWithoutNegativeIndexes( v.length )

        require(range.isEmpty || range.last < v.length)
        require(range.isEmpty || range.start >= 0)
        DenseVector.create(v.data, offset = v.offset + v.stride * range.start, stride = v.stride * range.step, length = range.length)
      }
    }
  }

  implicit def canTransposeComplex: CanTranspose[DenseVector[Complex], DenseMatrix[Complex]] = {
    new CanTranspose[DenseVector[Complex], DenseMatrix[Complex]] {
      def apply(from: DenseVector[Complex]): DenseMatrix[Complex] = {
        new DenseMatrix(data = from.data map { _.conjugate },
                        offset = from.offset,
                        cols = from.length,
                        rows = 1,
                        majorStride = from.stride)
      }
    }
  }

  class CanZipMapValuesDenseVector[@spec(Double, Int, Float, Long) V, @spec(Int, Double) RV:ClassTag] extends CanZipMapValues[DenseVector[V],V,RV,DenseVector[RV]] {
    def create(length : Int) = DenseVector(new Array[RV](length))

    /**Maps all corresponding values from the two collection. */
    def map(from: DenseVector[V], from2: DenseVector[V], fn: (V, V) => RV): DenseVector[RV] = {
      require(from.length == from2.length, s"Vectors must have same length")
      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 zipMap[V, R:ClassTag]: CanZipMapValuesDenseVector[V, R] = new CanZipMapValuesDenseVector[V, R]
  implicit val zipMap_d: CanZipMapValuesDenseVector[Double, Double] = new CanZipMapValuesDenseVector[Double, Double]
  implicit val zipMap_f: CanZipMapValuesDenseVector[Float, Float] = new CanZipMapValuesDenseVector[Float, Float]
  implicit val zipMap_i: CanZipMapValuesDenseVector[Int, Int] = new CanZipMapValuesDenseVector[Int, Int]

  class CanZipMapKeyValuesDenseVector[@spec(Double, Int, Float, Long) V, @spec(Int, Double) RV:ClassTag] extends CanZipMapKeyValues[DenseVector[V],Int, V,RV,DenseVector[RV]] {
    def create(length : Int) = DenseVector(new Array[RV](length))

    /**Maps all corresponding values from the two collection. */
    def map(from: DenseVector[V], from2: DenseVector[V], fn: (Int, V, V) => RV): DenseVector[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(i, from(i), from2(i))
        i += 1
      }
      result
    }


    override def mapActive(from: DenseVector[V], from2: DenseVector[V], fn: ((Int), V, V) => RV): DenseVector[RV] = {
      map(from, from2, fn)
    }
  }


  implicit def zipMapKV[V, R:ClassTag]: CanZipMapKeyValuesDenseVector[V, R] = new CanZipMapKeyValuesDenseVector[V, R]

  implicit val canAddIntoD: OpAdd.InPlaceImpl2[DenseVector[Double], DenseVector[Double]] = {
    new OpAdd.InPlaceImpl2[DenseVector[Double], DenseVector[Double]] {
      def apply(a: DenseVector[Double], b: DenseVector[Double]) = {
        canDaxpy(a, 1.0, b)
      }
      implicitly[BinaryUpdateRegistry[Vector[Double], Vector[Double], OpAdd.type]].register(this)
    }
  }

  implicit object canDaxpy extends scaleAdd.InPlaceImpl3[DenseVector[Double], Double, DenseVector[Double]] with Serializable {
    def apply(y: DenseVector[Double], a: Double, x: DenseVector[Double]) {
      require(x.length == y.length, s"Vectors must have same length")
      // using blas here is always a bad idea.
      if (x.noOffsetOrStride && y.noOffsetOrStride) {
        val ad = x.data
        val bd = y.data
        cforRange(0 until x.length) { i =>
          bd(i) += ad(i) * a
        }
      } else {
        cforRange(0 until x.length) { i =>
          y(i) += x(i) * a
        }
      }
    }

  }
  implicitly[TernaryUpdateRegistry[Vector[Double], Double, Vector[Double], scaleAdd.type]].register(canDaxpy)

  implicit val canAddD: OpAdd.Impl2[DenseVector[Double], DenseVector[Double], DenseVector[Double]] = {
    pureFromUpdate_Double(canAddIntoD)
  }
  implicitly[BinaryRegistry[Vector[Double], Vector[Double], OpAdd.type, Vector[Double]]].register(canAddD)

  implicit val canSubIntoD: OpSub.InPlaceImpl2[DenseVector[Double], DenseVector[Double]] = {
    new OpSub.InPlaceImpl2[DenseVector[Double], DenseVector[Double]] {
      def apply(a: DenseVector[Double], b: DenseVector[Double]) = {
        canDaxpy(a, -1.0, b)
      }
      implicitly[BinaryUpdateRegistry[Vector[Double], Vector[Double], OpSub.type]].register(this)
    }

  }
  implicit val canSubD: OpSub.Impl2[DenseVector[Double], DenseVector[Double], DenseVector[Double]] = {
    pureFromUpdate_Double(canSubIntoD)
  }
  implicitly[BinaryRegistry[Vector[Double], Vector[Double], OpSub.type, Vector[Double]]].register(canSubD)

  implicit object canDotD extends OpMulInner.Impl2[DenseVector[Double], DenseVector[Double], Double] {
    def apply(a: DenseVector[Double], b: DenseVector[Double]) = {
      require(a.length == b.length, s"Vectors must have same length")
      if (a.noOffsetOrStride && b.noOffsetOrStride && a.length < DenseVectorSupportMethods.MAX_SMALL_DOT_PRODUCT_LENGTH) {
        DenseVectorSupportMethods.smallDotProduct_Double(a.data, b.data, a.length)
      } else {
        blasPath(a, b)
      }
    }

    val UNROLL_FACTOR = 6

    private def blasPath(a: DenseVector[Double], b: DenseVector[Double]): Double = {
      if ((a.length <= 300 || !usingNatives) && a.stride == 1 && b.stride == 1) {
        DenseVectorSupportMethods.dotProduct_Double(a.data, a.offset, b.data, b.offset, a.length)
      } else  {
        val boff = if (b.stride >= 0) b.offset else (b.offset + b.stride * (b.length - 1))
        val aoff = if (a.stride >= 0) a.offset else (a.offset + a.stride * (a.length - 1))
        blas.ddot(
          a.length, b.data, boff, b.stride, a.data, aoff, a.stride)
      }
    }

  }
  implicitly[BinaryRegistry[Vector[Double], Vector[Double], OpMulInner.type, Double]].register(canDotD)


  /*
  TODO: scaladoc crashes on this. I don't know why. It makes me want to die a little.
  返回此向量的k-范数。
  */
  @expand
  @expand.valify
  implicit def canNorm[@expand.args(Int, Float, Long, BigInt, Complex) T]: norm.Impl2[DenseVector[T], Double, Double] = {

    new norm.Impl2[DenseVector[T], Double, Double] {
      def apply(v: DenseVector[T], n: Double): Double = {
        import v._
        if (n == 1) {
          var sum = 0.0
          foreach (v => sum += v.abs.toDouble )
          sum
        } else if (n == 2) {
          var sum = 0.0
          foreach (v => { val nn = v.abs.toDouble; sum += nn * nn })
          math.sqrt(sum)
        } else if (n == Double.PositiveInfinity) {
          var max = 0.0
          foreach (v => { val nn = v.abs.toDouble; if (nn > max) max = nn })
          max
        } else {
          var sum = 0.0
          foreach (v => { val nn = v.abs.toDouble; sum += math.pow(nn,n) })
          math.pow(sum, 1.0 / n)
        }
      }
    }
  }

  /**
   *  返回此向量的p-范数(特殊化为Double)。
   */
  implicit def canNorm_Double: norm.Impl2[DenseVector[Double], Double, Double] = {
    new norm.Impl2[DenseVector[Double], Double, Double] {
      def apply(v: DenseVector[Double], p: Double): Double = {
        if (p == 2) {
          var sq = 0.0
          v.foreach (x => sq += x * x)
          math.sqrt(sq)
        } else if (p == 1) {
          var sum = 0.0
          v.foreach (x => sum += math.abs(x))
          sum
        } else if (p == Double.PositiveInfinity) {
          var max = 0.0
          v.foreach (x => max = math.max(max, math.abs(x)))
          max
        } else if (p == 0) {
          var nnz = 0
          v.foreach (x => if (x != 0) nnz += 1)
          nnz
        } else {
          var sum = 0.0
          v.foreach (x => sum += math.pow(math.abs(x), p))
          math.pow(sum, 1.0 / p)
        }
      }
    }
  }

  implicit def canDim[E]: dim.Impl[DenseVector[E],Int] = new dim.Impl[DenseVector[E],Int] {
    def apply(v: DenseVector[E]): Int = v.length
  }

  // this produces bad spaces for builtins (inefficient because of bad implicit lookup)
  implicit def space[E](implicit field: Field[E], man: ClassTag[E]): MutableFiniteCoordinateField[DenseVector[E],Int,E] = {
    import field._
    implicit val cmv = canMapValues[E,E]
    MutableFiniteCoordinateField.make[DenseVector[E],Int,E]
  }

  implicit val space_Double: MutableFiniteCoordinateField[DenseVector[Double], Int, Double] = {
    MutableFiniteCoordinateField.make[DenseVector[Double],Int,Double]
  }

  implicit val space_Float: MutableFiniteCoordinateField[DenseVector[Float], Int, Float] = {
    MutableFiniteCoordinateField.make[DenseVector[Float],Int,Float]
  }

  implicit val space_Int: MutableFiniteCoordinateField[DenseVector[Int], Int, Int] = {
    MutableFiniteCoordinateField.make[DenseVector[Int],Int,Int]
  }

  implicit val space_Long: MutableFiniteCoordinateField[DenseVector[Long], Int, Long] = {
    MutableFiniteCoordinateField.make[DenseVector[Long],Int,Long]
  }

  object TupleIsomorphisms {
    implicit object doubleIsVector extends Isomorphism[Double,DenseVector[Double]] {
      def forward(t: Double) = DenseVector(t)
      def backward(t: DenseVector[Double]) = { assert(t.size == 1); t(0)}
    }

    implicit object pdoubleIsVector extends Isomorphism[(Double,Double),DenseVector[Double]] {
      def forward(t: (Double,Double)) = DenseVector(t._1,t._2)
      def backward(t: DenseVector[Double]) = { assert(t.size == 2); (t(0),t(1))}
    }
  }


  /**
   * This class exists because @specialized instances don't respect the serial
   * @param data
   * @param offset
   * @param stride
   * @param length
   */
  @SerialVersionUID(1L)
  case class SerializedForm(data: Array[_],
                            offset: Int,
                            stride: Int,
                            length: Int) extends Serializable {

    @throws(classOf[ObjectStreamException])
    def readResolve():Object = {
      data match {//switch to make specialized happy
        case x: Array[Int] => new DenseVector(x, offset, stride, length)
        case x: Array[Long] => new DenseVector(x, offset, stride, length)
        case x: Array[Double] => new DenseVector(x, offset, stride, length)
        case x: Array[Float] => new DenseVector(x, offset, stride, length)
        case x: Array[Short] => new DenseVector(x, offset, stride, length)
        case x: Array[Byte] => new DenseVector(x, offset, stride, length)
        case x: Array[Char] => new DenseVector(x, offset, stride, length)
        case x: Array[_] => new DenseVector(x, offset, stride, length)
      }

    }
  }


  // used to make sure the operators are loaded
  @noinline
  private def init() = {}
}

参考链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BigDataMLApplication

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值