Skip to content

Commit 4750c98

Browse files
committed
consistent tests across platforms
1 parent 2b94272 commit 4750c98

12 files changed

Lines changed: 372 additions & 142 deletions

vecxt/js-native/src/array.scala

Lines changed: 29 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -93,13 +93,16 @@ object JsNativeDoubleArrays:
9393
// TODO: SIMD
9494
inline def *:*(bmat: Matrix[Boolean])(using inline boundsCheck: BoundsCheck): Matrix[Double] =
9595
sameDimMatCheck(m, bmat)
96-
val newArr = NArray.ofSize[Double](m.rows * m.cols)
97-
var i = 0
98-
while i < newArr.length do
99-
newArr(i) = if bmat.raw(i) then m.raw(i) else 0.0
100-
i += 1
101-
end while
102-
Matrix[Double](newArr, (m.rows, m.cols))
96+
if m.hasSimpleContiguousMemoryLayout then
97+
val newArr = NArray.ofSize[Double](m.rows * m.cols)
98+
var i = 0
99+
while i < newArr.length do
100+
newArr(i) = if bmat.raw(i) then m.raw(i) else 0.0
101+
i += 1
102+
end while
103+
Matrix[Double](newArr, (m.rows, m.cols))
104+
else
105+
???
103106
end *:*
104107

105108
inline def +=(n: Double): Unit =
@@ -135,16 +138,31 @@ object JsNativeDoubleArrays:
135138
end +=
136139

137140
inline def >=(d: Double): Matrix[Boolean] =
138-
Matrix[Boolean](m.raw >= d, m.shape)(using BoundsCheck.DoBoundsCheck.no)
141+
if m.hasSimpleContiguousMemoryLayout then
142+
Matrix[Boolean](vecxt.arrays.>=(m.raw)(d), m.shape)(using BoundsCheck.DoBoundsCheck.no)
143+
else
144+
???
145+
139146

140147
inline def >(d: Double): Matrix[Boolean] =
141-
Matrix[Boolean](m.raw > d, m.shape)(using BoundsCheck.DoBoundsCheck.no)
148+
if m.hasSimpleContiguousMemoryLayout then
149+
Matrix[Boolean](vecxt.arrays.>(m.raw)(d), m.shape)(using BoundsCheck.DoBoundsCheck.no)
150+
else
151+
???
152+
end if
142153

143154
inline def <=(d: Double): Matrix[Boolean] =
144-
Matrix[Boolean](m.raw <= d, m.shape)(using BoundsCheck.DoBoundsCheck.no)
155+
if m.hasSimpleContiguousMemoryLayout then
156+
Matrix[Boolean](vecxt.arrays.<=(m.raw)(d), m.shape)(using BoundsCheck.DoBoundsCheck.no)
157+
else
158+
???
159+
end if
145160

146161
inline def <(d: Double): Matrix[Boolean] =
147-
Matrix[Boolean](m.raw < d, m.shape)(using BoundsCheck.DoBoundsCheck.no)
162+
if m.hasSimpleContiguousMemoryLayout then
163+
Matrix[Boolean](vecxt.arrays.<(m.raw)(d), m.shape)(using BoundsCheck.DoBoundsCheck.no)
164+
else
165+
???
148166
end extension
149167

150168
// extension [@specialized(Double, Int) A: Numeric](m: Matrix[A])

vecxt/js/src/doublematrix.scala

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,29 @@ object JsDoubleMatrix:
1414

1515
inline def matmul(b: Matrix[Double])(using inline boundsCheck: BoundsCheck): Matrix[Double] =
1616
dimMatCheck(m, b)
17-
val newArr = Float64Array(m.rows * b.cols)
18-
// Note, might need to deal with transpose later.
19-
dgemm(
20-
"column-major",
21-
"no-transpose",
22-
"no-transpose",
23-
m.rows,
24-
b.cols,
25-
m.cols,
26-
1.0,
27-
m.raw,
28-
m.rows,
29-
b.raw,
30-
b.rows,
31-
1.0,
32-
newArr,
33-
m.rows
34-
)
35-
Matrix[Double](newArr, (m.rows, b.cols))
17+
if m.hasSimpleContiguousMemoryLayout && b.hasSimpleContiguousMemoryLayout then
18+
val newArr = Float64Array(m.rows * b.cols)
19+
// Note, might need to deal with transpose later.
20+
dgemm(
21+
"column-major",
22+
"no-transpose",
23+
"no-transpose",
24+
m.rows,
25+
b.cols,
26+
m.cols,
27+
1.0,
28+
m.raw,
29+
m.rows,
30+
b.raw,
31+
b.rows,
32+
1.0,
33+
newArr,
34+
m.rows
35+
)
36+
Matrix[Double](newArr, (m.rows, b.cols))
37+
else
38+
???
39+
3640
end matmul
3741
end extension
3842
end JsDoubleMatrix

vecxt/jvm/src/doublematrix.scala

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ object JvmDoubleMatrix:
7070

7171
// inline def *:*=(d: Double): Unit = m.raw.multInPlace(d)
7272

73+
74+
//TODO: Dim check
75+
7376
inline def *(vec: Array[Double])(using inline boundsCheck: BoundsCheck): Array[Double] =
7477
val newArr = Array.ofDim[Double](m.rows)
7578
blas.dgemv(
@@ -112,46 +115,64 @@ object JvmDoubleMatrix:
112115
import vecxt.BoundsCheck.DoBoundsCheck.no
113116
if m.hasSimpleContiguousMemoryLayout then vecxt.arrays.+=(m.raw)(n)
114117
else
118+
println(s" .offset: ${m.offset}, m.rowStride: ${m.rowStride}, m.colStride: ${m.colStride}")
115119
// Cache-friendly fallback: iterate with smallest stride in inner loop
116120
// (m.offset + row * m.rowStride + col * m.colStride
117121
if m.rowStride <= m.colStride then
118122
// Row stride is smaller, so iterate rows in inner loop
119123
val rowStrides = IntVector.zero(sp_int_doubleLanes).addIndex(m.rowStride).toArray
124+
// println(m.offset)
125+
// println(s"colStrides: ${rowStrides.mkString(", ")}")
126+
// println(s"m.raw: ${m.raw.mkString(", ")}")
127+
// println(s"m.rows: ${m.rows}, m.cols: ${m.cols}")
128+
// println(s"m.rowStride: ${m.rowStride}, m.colStride: ${m.colStride}")
120129
var j = 0
121130
while j < m.cols do
122131
var i = 0
123132
var blockIndex = m.offset + j * m.colStride
124133
val upperBound = sp_int_doubleLanes.loopBound(m.rows)
125134
while i < upperBound do
135+
val iBlockIndex = blockIndex + i * m.rowStride
126136
DoubleVector
127-
.fromArray(vecxt.arrays.spd, m.raw, blockIndex, rowStrides, 0)
128-
.mul(n)
129-
.intoArray(m.raw, blockIndex, rowStrides, 0)
137+
.fromArray(vecxt.arrays.spd, m.raw, iBlockIndex, rowStrides, 0)
138+
.add(n)
139+
.intoArray(m.raw, iBlockIndex, rowStrides, 0)
130140
i += sp_int_doubleLanes.length
131141
end while
132142
while i < m.rows do
143+
m.elementIndex(i, j)(using BoundsCheck.DoBoundsCheck.yes)
133144
m(i, j) = n + m(i, j)
134145
i += 1
135146
end while
147+
136148
j += 1
137149
end while
138150
else
139151
// Column stride is smaller, so iterate columns in inner loop
140152
val colStrides = IntVector.zero(sp_int_doubleLanes).addIndex(m.colStride).toArray
153+
// println(m.offset)
154+
// println(s"colStrides: ${colStrides.mkString(", ")}")
155+
// println(s"m.raw: ${m.raw.mkString(", ")}")
156+
// println(s"m.rows: ${m.rows}, m.cols: ${m.cols}")
157+
// println(s"m.rowStride: ${m.rowStride}, m.colStride: ${m.colStride}")
141158
var i = 0
142159
while i < m.rows do
143160
var j = 0
144161
val upperBound = sp_int_doubleLanes.loopBound(m.cols)
145-
val blockIndex = m.offset + i * m.rowStride
146-
while j < upperBound do
147162

163+
var blockIndex = m.offset + i * m.rowStride
164+
while j < upperBound do
165+
val jblockIndex = blockIndex + j * m.colStride
148166
DoubleVector
149-
.fromArray(vecxt.arrays.spd, m.raw, blockIndex, colStrides, 0)
167+
.fromArray(vecxt.arrays.spd, m.raw, jblockIndex, colStrides, 0)
150168
.add(n)
151-
.intoArray(m.raw, blockIndex, colStrides, 0)
169+
.intoArray(m.raw, jblockIndex, colStrides, 0)
170+
152171
j += sp_int_doubleLanes.length
153172
end while
173+
154174
while j < m.cols do
175+
m.elementIndex(i, j)(using BoundsCheck.DoBoundsCheck.yes)
155176
m(i, j) = n + m(i, j)
156177
j += 1
157178
end while

vecxt/native/src/doublematrix.scala

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -16,25 +16,30 @@ object NativeDoubleMatrix:
1616

1717
inline def matmul(b: Matrix[Double])(using inline boundsCheck: BoundsCheck): Matrix[Double] =
1818
dimMatCheck(m, b)
19-
val newArr = Array.ofDim[Double](m.rows * b.cols)
20-
// Note, might need to deal with transpose later.
21-
blas.cblas_dgemm(
22-
blasEnums.CblasColMajor,
23-
blasEnums.CblasNoTrans,
24-
blasEnums.CblasNoTrans,
25-
m.rows,
26-
b.cols,
27-
m.cols,
28-
1.0,
29-
m.raw.at(0),
30-
m.rows,
31-
b.raw.at(0),
32-
b.rows,
33-
1.0,
34-
newArr.at(0),
35-
m.rows
36-
)
37-
Matrix(newArr, (m.rows, b.cols))
19+
20+
21+
if m.hasSimpleContiguousMemoryLayout && b.hasSimpleContiguousMemoryLayout then
22+
val newArr = Array.ofDim[Double](m.rows * b.cols)
23+
blas.cblas_dgemm(
24+
blasEnums.CblasColMajor,
25+
blasEnums.CblasNoTrans,
26+
blasEnums.CblasNoTrans,
27+
m.rows,
28+
b.cols,
29+
m.cols,
30+
1.0,
31+
m.raw.at(0),
32+
m.rows,
33+
b.raw.at(0),
34+
b.rows,
35+
1.0,
36+
newArr.at(0),
37+
m.rows
38+
)
39+
Matrix(newArr, (m.rows, b.cols))
40+
else
41+
???
42+
3843
end extension
3944

4045
end NativeDoubleMatrix

vecxt/src/MatrixInstance.scala

Lines changed: 30 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -96,23 +96,28 @@ object MatrixInstance:
9696
val newCols = range(colRange, m.cols)
9797
val newArr = NArray.ofSize[A](newCols.size * newRows.size)
9898

99-
var idx = 0
99+
if newRows.contiguous && newCols.contiguous then
100100

101-
var i = 0
102-
while i < newCols.length do
103-
val colpos = newCols(i)
104-
val stride = colpos * m.rows
105-
var j = 0
106-
while j < newRows.length do
107-
val rowPos = newRows(j)
108-
newArr(idx) = m.raw(stride + rowPos)
109-
idx += 1
110-
j += 1
101+
submatrix(newRows, newCols)
102+
else if m.isDenseColMajor then
103+
var idx = 0
104+
var i = 0
105+
while i < newCols.length do
106+
val colpos = newCols(i)
107+
val stride = colpos * m.rows
108+
var j = 0
109+
while j < newRows.length do
110+
val rowPos = newRows(j)
111+
newArr(idx) = m.raw(stride + rowPos)
112+
idx += 1
113+
j += 1
114+
end while
115+
i += 1
111116
end while
112-
i += 1
113-
end while
114117

115-
Matrix(newArr, (newRows.size, newCols.size))(using BoundsCheck.DoBoundsCheck.no)
118+
Matrix(newArr, (newRows.size, newCols.size))(using BoundsCheck.DoBoundsCheck.no)
119+
else
120+
???
116121

117122
end apply
118123

@@ -123,6 +128,17 @@ object MatrixInstance:
123128
apply(b._1, b._2)
124129
end apply
125130

131+
inline def elementIndex(row: Row, col: Col)(using inline boundsCheck: BoundsCheck): Int =
132+
indexCheckMat(m, (row, col))
133+
inline if(boundsCheck == BoundsCheck.DoBoundsCheck.yes) then
134+
println(s"Element index for ($row, $col) in matrix with shape ${m.shape} is being checked")
135+
println(s"Offset: ${m.offset}, Row stride: ${m.rowStride}, Col stride: ${m.colStride}")
136+
println(s"Calculated index: ${m.offset + row * m.rowStride + col * m.colStride}")
137+
println(s"element: ${m.raw(m.offset + row * m.rowStride + col * m.colStride)}")
138+
m.offset + row * m.rowStride + col * m.colStride
139+
140+
end elementIndex
141+
126142
transparent inline def apply(row: Row, col: Col)(using inline boundsCheck: BoundsCheck): A =
127143
indexCheckMat(m, (row, col))
128144
// Fast path for default column-major layout (contiguous, no offset/stride)

vecxt/src/doublematrix.scala

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,18 @@ import arrayUtil.printArr
2121
object DoubleMatrix:
2222

2323
extension (d: Double)
24-
inline def *(m: Matrix[Double])(using inline boundsCheck: BoundsCheck): Matrix[Double] =
25-
if m.hasSimpleContiguousMemoryLayout then
26-
Matrix[Double](vecxt.arrays.*(m.raw)(d), m.shape)(using BoundsCheck.DoBoundsCheck.no)
27-
else ???
24+
inline def *(m: Matrix[Double])(using inline boundsCheck: BoundsCheck): Matrix[Double] = m * d
25+
inline def +(m: Matrix[Double])(using inline boundsCheck: BoundsCheck): Matrix[Double] = m + d
26+
inline def -(m: Matrix[Double])(using inline boundsCheck: BoundsCheck): Matrix[Double] = ???
27+
inline def /(m: Matrix[Double])(using inline boundsCheck: BoundsCheck): Matrix[Double] = ???
28+
29+
inline def *=(m: Matrix[Double])(using inline boundsCheck: BoundsCheck): Unit = m *= d
30+
inline def +=(m: Matrix[Double])(using inline boundsCheck: BoundsCheck): Unit = ??? //m += d
31+
inline def -=(m: Matrix[Double])(using inline boundsCheck: BoundsCheck): Unit = ??? //m -= d
32+
inline def /=(m: Matrix[Double])(using inline boundsCheck: BoundsCheck): Unit = ???
33+
34+
35+
2836
end extension
2937

3038
extension (m: Matrix[Double])

vecxt/src/matrix.scala

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -34,14 +34,14 @@ object matrix:
3434
):
3535

3636
/** If the matrix is dense and contiguous, it means that the data is stored in a single block of memory in row or
37-
* column major, or row major order.
37+
* column major, or row major order, with the exact number of elements matching the number of rows and columns.
3838
*
3939
* We can take advantage of this for performance.
4040
*
4141
* @return
4242
*/
4343
lazy val hasSimpleContiguousMemoryLayout: Boolean =
44-
isDenseRowMajor || isDenseColMajor
44+
isDenseRowMajor || isDenseColMajor && raw.length == numel
4545

4646
/** If the matrix is dense and contiguous in row major order, it means that the data is stored in a single block of
4747
* memory in row major order. Useful for performance optimizations.
@@ -92,6 +92,15 @@ object matrix:
9292
)
9393
end apply
9494

95+
/**
96+
* Assumes column major order.
97+
*
98+
* @param raw
99+
* @param rows
100+
* @param cols
101+
* @param boundsCheck
102+
* @return
103+
*/
95104
inline def apply[@specialized(Double, Boolean, Int) A](raw: NArray[A], rows: Row, cols: Col)(using
96105
inline boundsCheck: BoundsCheck
97106
): Matrix[A] =
@@ -109,15 +118,7 @@ object matrix:
109118
inline def apply[@specialized(Double, Boolean, Int) A](dim: RowCol, raw: NArray[A])(using
110119
inline boundsCheck: BoundsCheck
111120
): Matrix[A] =
112-
dimMatInstantiateCheck(raw, dim)
113-
new Matrix(
114-
raw = raw,
115-
rows = dim._1,
116-
cols = dim._2,
117-
rowStride = 1,
118-
colStride = dim._1,
119-
offset = 0
120-
)
121+
Matrix(raw, dim._1, dim._2)(using boundsCheck)
121122
end apply
122123
end Matrix
123124

0 commit comments

Comments
 (0)