Skip to content
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,13 @@ sealed trait Vector extends Serializable {
*/
@Since("2.0.0")
def argmax: Int

/**
* Calculate the dot product of this vector with another.
*
* If `size` does not match an [IllegalArgumentException] is thrown.
*/
def dot(v: Vector): Double = BLAS.dot(this, v)
}

/**
Expand Down Expand Up @@ -239,6 +246,13 @@ object Vectors {
}.toSeq)
}

/**
* Calculate the dot product of two vectors.
*
* If `size` does not match an [IllegalArgumentException] is thrown.
*/
def dot(v1: Vector, v2: Vector): Double = BLAS.dot(v1, v2)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, do we need this method? BLAS.dot() already exists. I can see an instance method taking a single arg for parity with Pyspark, but this doesn't add much.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah right, fair point. Still you can just call a.dot(b) after the first method is added, no?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes indeed I can. Lemme fix. Thanks!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, I meant, I don't think there is value in adding this method, because a caller can use a.dot(b) directly.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I got ya. Yep, I can remove those.


/**
* Creates a vector of all zeros.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -380,4 +380,29 @@ class VectorsSuite extends SparkMLFunSuite {
Vectors.sparse(-1, Array((1, 2.0)))
}
}

test("dot product only supports vectors of same size") {
intercept[IllegalArgumentException]{ Vectors.dot(Vectors.dense(arr), Vectors.zeros(1)) }
}

test("dense vector dot product") {
val dv = Vectors.dense(arr)
assert(Vectors.dot(dv, dv) === 0.26)
assert(dv.dot(dv) === 0.26)
}

test("sparse vector dot product") {
val sv = Vectors.sparse(n, indices, values)
assert(Vectors.dot(sv, sv) === 0.26)
assert(sv.dot(sv) === 0.26)
}

test("mixed sparse and dense vector dot product") {
val sv = Vectors.sparse(n, indices, values)
val dv = Vectors.dense(arr)
assert(Vectors.dot(sv, dv) === 0.26)
assert(Vectors.dot(dv, sv) === 0.26)
assert(sv.dot(dv) === 0.26)
assert(dv.dot(sv) === 0.26)
}
}
14 changes: 14 additions & 0 deletions mllib/src/main/scala/org/apache/spark/mllib/linalg/Vectors.scala
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,13 @@ sealed trait Vector extends Serializable {
*/
@Since("2.0.0")
def asML: newlinalg.Vector

/**
* Calculate the dot product of this vector with another.
*
* If `size` does not match an [IllegalArgumentException] is thrown.
*/
def dot(v: Vector): Double = BLAS.dot(this, v)
}

/**
Expand Down Expand Up @@ -351,6 +358,13 @@ object Vectors {
}.toSeq)
}

/**
* Calculate the dot product of two vectors.
*
* If `size` does not match an [IllegalArgumentException] is thrown.
*/
def dot(v1: Vector, v2: Vector): Double = BLAS.dot(v1, v2)

/**
* Creates a vector of all zeros.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -510,4 +510,29 @@ class VectorsSuite extends SparkFunSuite with Logging {
Vectors.sparse(-1, Array((1, 2.0)))
}
}

test("dot product only supports vectors of same size") {
intercept[IllegalArgumentException]{ Vectors.dot(Vectors.dense(arr), Vectors.zeros(1)) }
}

test("dense vector dot product") {
val dv = Vectors.dense(arr)
assert(Vectors.dot(dv, dv) === 0.26)
assert(dv.dot(dv) === 0.26)
}

test("sparse vector dot product") {
val sv = Vectors.sparse(n, indices, values)
assert(Vectors.dot(sv, sv) === 0.26)
assert(sv.dot(sv) === 0.26)
}

test("mixed sparse and dense vector dot product") {
val sv = Vectors.sparse(n, indices, values)
val dv = Vectors.dense(arr)
assert(Vectors.dot(sv, dv) === 0.26)
assert(Vectors.dot(dv, sv) === 0.26)
assert(sv.dot(dv) === 0.26)
assert(dv.dot(sv) === 0.26)
}
}