Skip to content

Commit

Permalink
Added many NArrayOps extensions and some tests.
Browse files Browse the repository at this point in the history
Broke NArrayBuilder into two traits and implemented a special version for js.Array[T] called NativeArrayBuilder.
Added copyAs and copyOf, but they don't seem to work.
Added NArrayView[T].
Added test helper method: assertArray2NArrayEquality
  • Loading branch information
c committed Dec 18, 2024
1 parent 55b3c00 commit 4acd5b2
Show file tree
Hide file tree
Showing 10 changed files with 1,154 additions and 149 deletions.
842 changes: 764 additions & 78 deletions narr/js/src/main/scala/narr/native/Extensions.scala

Large diffs are not rendered by default.

62 changes: 62 additions & 0 deletions narr/js/src/main/scala/narr/native/NativeArrayBuilder.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
* Copyright 2023 dragonfly.ai
*
* 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.
*/

package narr.native

import narr.{NArray, NArrayBuilder, NativeArray}

import scala.reflect.ClassTag


// in JavaScript, just use a js.Array.
case class NativeArrayBuilder[T](initCapacity:Int = NArrayBuilder.DefaultInitialSize)(using ClassTag[T]) extends NArrayBuilder[T] {
//given clz:Class[T] = implicitly[ClassTag[T]].runtimeClass.asInstanceOf[Class[T]]
override inline def makeNArray(len: Int): NArray[T] = new scala.scalajs.js.Array[T]().asInstanceOf[NArray[T]]

override inline def copyInto(src: NArray[T], dest: NArray[T], dstPos: Int): Unit = NArray.copyNativeArray(
src.asInstanceOf[NativeArray[T]], dest.asInstanceOf[NativeArray[T]], dstPos
)
override inline def copyInto(src: NArray[T], srcPos: Int, dest: NArray[T], dstPos: Int, length: Int): Unit = {
NArray.copyNativeArray(src.asInstanceOf[NativeArray[T]], srcPos, dest.asInstanceOf[NativeArray[T]], dstPos, length)
}

private var elements: scala.scalajs.js.Array[T] = new scala.scalajs.js.Array[T](initCapacity).asInstanceOf[NativeArray[T]]

private var length:Int = 0

override def size: Int = length

override def addOne(e: T): this.type = {
elements(length) = e
length = length + 1
this
}

override def addAll(es: NArray[T]): this.type = {
//copyInto(es, elements.asInstanceOf[NArray[T]], length) // slow copy
elements = result.asInstanceOf[NArr[T]].concat(es.asInstanceOf[NArr[T]]).asInstanceOf[scala.scalajs.js.Array[T]]
length = length + es.asInstanceOf[NArr[T]].length
this
}

override def result: NArray[T] = {
elements.slice(0, length).asInstanceOf[NArray[T]]
}

override def apply(idx: Int): T = if (idx > -1 && idx < length) elements(idx) else throw ArrayIndexOutOfBoundsException(
s"No index: $idx for array builder of length: $length."
)
}
48 changes: 39 additions & 9 deletions narr/js/src/main/scala/narr/native/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,9 @@ package object native {
inline def copyIntArray(src: IntArray, dest: IntArray, destPos: Int): Unit = dest.set(src, destPos)
inline def copyFloatArray(src: FloatArray, dest: FloatArray, destPos: Int): Unit = dest.set(src, destPos)
inline def copyDoubleArray(src: DoubleArray, dest: DoubleArray, destPos: Int): Unit = dest.set(src, destPos)
inline def copyNArray[T](src: NArray[T], dest: NArray[T], destPos: Int): Unit = {
//println(s"copyNArray[T](src, dest, $destPos)")
val availableSpace = dest.length - destPos
if (src.length > availableSpace) throw Exception(s"Can't copy source array into destination. The source is too long.")
inline def copyNativeArray[T](src: NativeArray[T], dest: NativeArray[T], destPos: Int): Unit = {
//val availableSpace = dest.length - destPos
//if (src.length > availableSpace) throw Exception(s"Can't copy source array into destination. The source is too long.")
var i:Int = 0; while (i < src.length) {
dest(destPos + i) = src(i)
i = i + 1
Expand Down Expand Up @@ -131,18 +130,49 @@ package object native {
}
else dest.set(src, destPos)
}
inline def copyNArray[T](src: NArray[T], srcPos: Int, dest: NArray[T], destPos: Int, length:Int): Unit = {
val availableSpace = dest.length - destPos
if (length > availableSpace) throw Exception(s"Can't copy source array into destination. The source is too long.")
inline def copyNativeArray[T](src: NativeArray[T], srcPos: Int, dest: NativeArray[T], destPos: Int, length:Int): Unit = {
//val availableSpace = dest.length - destPos
//if (length > availableSpace) throw Exception(s"Can't copy source array into destination. The source is too long.")
var i: Int = 0; while (i < length) {
dest(destPos + i) = src(srcPos + i)
i = i + 1
}
}
}

/** Copy one array to another, truncating or padding with default values (if
* necessary) so the copy has the specified length. The new array can have
* a different type than the original one as long as the values are
* assignment-compatible. When copying between primitive and object arrays,
* boxing and unboxing are supported.
*
* Equivalent to Java's
* `java.util.Arrays.copyOf(original, newLength, newType)`,
* except that this works for all combinations of primitive and object arrays
* in a single method.
*
* @see `java.util.Arrays#copyOf`
*/
def copyAs[T, B >: T](original: NArray[T], newLength: Int)(using ClassTag[B]): NArray[B] = {
narr.NArray.copy( original.asInstanceOf[NArray[B]], narr.NArray.ofSize[B](newLength), 0 )
}

/** Copy one array to another, truncating or padding with default values (if
* necessary) so the copy has the specified length.
*
* Equivalent to Java's
* `java.util.Arrays.copyOf(original, newLength)`,
* except that this works for primitive and object arrays in a single method.
*
* @see `java.util.Arrays#copyOf`
*/
def copyOf[T: ClassTag](original: NArray[T], newLength: Int): NArray[T] = {
val cp = narr.NArray.ofSize[T](newLength)
println(s"cp = $cp, newLength = $newLength")
narr.NArray.copy[T]( original, cp, 0 )
}
}


inline def makeNativeArrayOfSize[A: ClassTag](n:Int):NativeArray[A] = new scala.scalajs.js.Array[A](n)
inline def makeNativeArrayOfSize[A](n:Int)(using ClassTag[A]):NativeArray[A] = (new scala.scalajs.js.Array[Any](n)).asInstanceOf[NativeArray[A]]

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/*
* Copyright 2023 dragonfly.ai
*
* 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.
*/

package narr.native

import narr.{NArray, NArrayBuilder, NativeArray, TypedArrayBuilder}

import scala.reflect.ClassTag


// in JavaScript, just use a js.Array.
case class NativeArrayBuilder[T](override val initCapacity:Int = NArrayBuilder.DefaultInitialSize)(using ClassTag[T]) extends TypedArrayBuilder[T] {
//given clz:Class[T] = implicitly[ClassTag[T]].runtimeClass.asInstanceOf[Class[T]]
override inline def makeNArray(len: Int): NArray[T] = NArray.ofSize[T](len)

override inline def make2DNArray(len: Int): NArray[NArray[T]] = {
narr.native.makeNativeArrayOfSize[NativeArray[T]](len).asInstanceOf[NArray[NArray[T]]]
}

override inline def copyInto(src: NArray[T], dest: NArray[T], dstPos: Int): Unit = NArray.copyNativeArray(
src.asInstanceOf[NativeArray[T]], dest.asInstanceOf[NativeArray[T]], dstPos
)
override inline def copyInto(src: NArray[T], srcPos: Int, dest: NArray[T], dstPos: Int, length: Int): Unit = {
NArray.copyNativeArray(src.asInstanceOf[NativeArray[T]], srcPos, dest.asInstanceOf[NativeArray[T]], dstPos, length)
}

}
24 changes: 21 additions & 3 deletions narr/jvm-native/src/main/scala/narr/native/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ package object native {
type NArr[T] = Array[T]
type SortableNArr[T] = Array[T]

inline def makeNativeArrayOfSize[A:ClassTag](n:Int):NativeArray[A] = new Array[A](n)
inline def makeNativeArrayOfSize[A](n:Int)(using ClassTag[A]):NativeArray[A] = new Array[A](n)

object NArray {
export Array.*
Expand All @@ -55,7 +55,7 @@ package object native {
inline def copyIntArray(src: IntArray, dest: IntArray, destPos: Int): Unit = Array.copy(src, 0, dest, destPos, src.length)
inline def copyFloatArray(src: FloatArray, dest: FloatArray, destPos: Int): Unit = Array.copy(src, 0, dest, destPos, src.length)
inline def copyDoubleArray(src: DoubleArray, dest: DoubleArray, destPos: Int): Unit = Array.copy(src, 0, dest, destPos, src.length)
inline def copyNArray[T](src: NArray[T], dest: NArray[T], destPos: Int): Unit = Array.copy(src, 0, dest, destPos, src.length)
inline def copyNativeArray[T](src: NArray[T], dest: NArray[T], destPos: Int): Unit = Array.copy(src, 0, dest, destPos, src.length)

/** Copy one array to another.
* Equivalent to Java's
Expand All @@ -76,7 +76,25 @@ package object native {
inline def copyIntArray(src: IntArray, srcPos: Int, dest: IntArray, destPos: Int, length: Int): Unit = java.lang.System.arraycopy(src, srcPos, dest, destPos, length)
inline def copyFloatArray(src: FloatArray, srcPos: Int, dest: FloatArray, destPos: Int, length: Int): Unit = java.lang.System.arraycopy(src, srcPos, dest, destPos, length)
inline def copyDoubleArray(src: DoubleArray, srcPos: Int, dest: DoubleArray, destPos: Int, length: Int): Unit = java.lang.System.arraycopy(src, srcPos, dest, destPos, length)
inline def copyNArray[T](src: NArray[T], srcPos: Int, dest: NArray[T], destPos: Int, length: Int): Unit = Array.copy(src, srcPos, dest, destPos, length)
inline def copyNativeArray[T](src: NativeArray[T], srcPos: Int, dest: NativeArray[T], destPos: Int, length: Int): Unit = Array.copy(src, srcPos, dest, destPos, length)

/** Copy one array to another, truncating or padding with default values (if
* necessary) so the copy has the specified length. The new array can have
* a different type than the original one as long as the values are
* assignment-compatible. When copying between primitive and object arrays,
* boxing and unboxing are supported.
*
* Equivalent to Java's
* `java.util.Arrays.copyOf(original, newLength, newType)`,
* except that this works for all combinations of primitive and object arrays
* in a single method.
*
* @see `java.util.Arrays#copyOf`
*/
inline def copyAs[T, B >: T](original: NArray[T], newLength: Int)(using ClassTag[B]): NArray[B] = {
Array.copyAs[B](original, newLength)
}

}

object Extensions {
Expand Down
Loading

0 comments on commit 4acd5b2

Please sign in to comment.