Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
434 changes: 434 additions & 0 deletions .github/scalex/SKILL.md

Large diffs are not rendered by default.

1 change: 0 additions & 1 deletion .github/workflows/autofix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ on:
pull_request:
jobs:
autofix:
if: github.event.pull_request.draft == false
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
Expand Down
63 changes: 63 additions & 0 deletions benchmark/src/ndarrayFloat.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package vecxt.benchmark

import org.openjdk.jmh.annotations.*
import org.openjdk.jmh.infra.Blackhole
import vecxt.all.*
import scala.compiletime.uninitialized

// format: off
/**
* Baseline (flatUnaryOp scalar loop) vs SIMD (FloatArraysCrossCompat) for NDArray[Float] unary ops.
*
* Run with:
* ./mill benchmark.runMain vecxt.benchmark.NDArrayFloatBenchmark
* or via JMH:
* ./mill benchmark.runJmh -t 1 -f 1 -wi 1 -i 3 "NDArrayFloat.*"
*/
// format: on
@State(Scope.Thread)
class NDArrayFloatBenchmark extends BLASBenchmark:

@Param(Array("10", "1000", "100000"))
var n: java.lang.String = uninitialized

var arr: NDArray[Float] = uninitialized
var arr2: NDArray[Float] = uninitialized

@Setup(Level.Trial)
def setup: Unit =
val data = Array.tabulate(n.toInt)(i => (i + 1).toFloat)
arr = NDArray(data, Array(n.toInt))
arr2 = NDArray(data.map(_ * 2.0f), Array(n.toInt))
()
end setup

@Benchmark
def ndarray_float_add(bh: Blackhole): Unit =
bh.consume(arr + arr2)

@Benchmark
def ndarray_float_mul_scalar(bh: Blackhole): Unit =
bh.consume(arr * 2.0f)

@Benchmark
def ndarray_float_exp(bh: Blackhole): Unit =
bh.consume(arr.exp)

@Benchmark
def ndarray_float_log(bh: Blackhole): Unit =
bh.consume(arr.log)

@Benchmark
def ndarray_float_sqrt(bh: Blackhole): Unit =
bh.consume(arr.sqrt)

@Benchmark
def ndarray_float_tanh(bh: Blackhole): Unit =
bh.consume(arr.tanh)

@Benchmark
def ndarray_float_abs(bh: Blackhole): Unit =
bh.consume(arr.abs)

end NDArrayFloatBenchmark
7 changes: 7 additions & 0 deletions build.mill
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
//| - io.github.quafadas:millSite_mill1_3.8:0.0.57
//| - com.goyeau:mill-scalafix_mill1_3:0.6.0
//| - com.lihaoyi::mill-contrib-jmh:$MILL_VERSION
//| - com.lihaoyi::mill-contrib-scoverage:$MILL_VERSION

/** --add-modules=jdk.incubator.vector -Xss100m -Xmx4G
*/
Expand All @@ -29,6 +30,9 @@ import mill.api.Task.Simple
// def format = mill.scalalib.scalafmt.ScalafmtModule
// mill mill.scalalib.scalafmt/
// mill __.compiledClassesAndSemanticDbFiles
// mill vecxt.jvm.scoverage.htmlReport
// jwebserver -d out/vecxt/jvm/scoverage/data.dest]

object V:
val spire: Dep = mvn"org.typelevel::spire::0.18.0"
val laminar: Dep = mvn"com.raquo::laminar::17.2.0"
Expand All @@ -41,6 +45,9 @@ object V:
val catsVersion = "2.13.0"
val disciplineVersion = "2.0.0"
val scalacheckVersion = "1.17.0"
val jsBSP = true
val nativeBSP = false
val jvmBSP = false
end V

trait VecxtPublishModule extends PublishModule, ScalaModule, ScalafixModule:
Expand Down
2 changes: 2 additions & 0 deletions jsSite/package.mill
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ object `package` extends SiteJSModule:
mvn"com.lihaoyi::upickle::4.0.2"
)

override def enableBsp = V.jsBSP

// object test extends ScalaJSTests with CommonTests {
// def moduleKind = ModuleKind.CommonJSModule
// }
Expand Down
74 changes: 74 additions & 0 deletions scripts/scalex-cli
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
#!/usr/bin/env bash
# If executed by a non-bash shell, re-exec with bash.
# When eval'd (e.g. zsh eval), $0 is the shell binary — fall through
# since the script is POSIX-compatible.
if [ -z "${BASH_VERSION:-}" ] && [ -f "$0" ]; then
exec bash "$0" "$@"
fi
set -euo pipefail

EXPECTED_VERSION="1.38.0"
REPO="nguyenyou/scalex"

# Expected SHA-256 checksums for each artifact (updated each release alongside EXPECTED_VERSION)
CHECKSUM_scalex_macos_arm64="6f38cccf85f6e39e3e4095e675c52d547274dd64ae7dd206dfaf06bb2a5ccc4f"
CHECKSUM_scalex_macos_x64="aa2b643c4688aa4bb9f18f7336bda91d6122dd4c7250e110ac8553c702fac0dd"
CHECKSUM_scalex_linux_x64="988a137b0bf2ec5a1585c0a1cdb171a38d1085191277815936ad32086aebc349"

# Cache location: follow XDG spec (like Mill uses ~/.cache/mill/download/)
CACHE_DIR="${XDG_CACHE_HOME:-$HOME/.cache}/scalex"

# Detect platform → artifact name
OS=$(uname -s); ARCH=$(uname -m)
case "$OS-$ARCH" in
Darwin-arm64) ARTIFACT="scalex-macos-arm64" ;;
Darwin-x86_64) ARTIFACT="scalex-macos-x64" ;;
Linux-x86_64) ARTIFACT="scalex-linux-x64" ;;
*) echo "scalex: unsupported platform $OS-$ARCH" >&2; exit 1 ;;
esac

# Binary path includes version (like Mill's ~/.cache/mill/download/1.1.3-native-mac-aarch64)
BINARY="$CACHE_DIR/$EXPECTED_VERSION-$ARTIFACT"

# Fast path: binary exists, non-empty, executable → exec immediately
if [ -s "$BINARY" ] && [ -x "$BINARY" ]; then
exec "$BINARY" "$@"
fi

# Download
echo "scalex: downloading v${EXPECTED_VERSION} for ${OS}-${ARCH}..." >&2
mkdir -p "$CACHE_DIR"
TMP=$(mktemp "$CACHE_DIR/scalex-temp.XXXXXX")
trap 'rm -f "$TMP"' EXIT

BASE_URL="https://github.com/${REPO}/releases/download/v${EXPECTED_VERSION}"

curl -f -L -o "$TMP" "${BASE_URL}/${ARTIFACT}" || {
echo "scalex: download failed. Visit https://github.com/${REPO}/releases" >&2
exit 1
}

# Verify checksum
CHECKSUM_VAR="CHECKSUM_${ARTIFACT//-/_}"
EXPECTED_HASH="${!CHECKSUM_VAR}"
if [ -n "$EXPECTED_HASH" ]; then
ACTUAL_HASH=$(shasum -a 256 "$TMP" | awk '{print $1}')
if [ "$ACTUAL_HASH" != "$EXPECTED_HASH" ]; then
echo "scalex: checksum verification FAILED" >&2
echo " expected: $EXPECTED_HASH" >&2
echo " actual: $ACTUAL_HASH" >&2
echo " The downloaded binary may have been tampered with." >&2
exit 1
fi
fi

# Install atomically
chmod +x "$TMP"
mv "$TMP" "$BINARY"
trap - EXIT

# macOS: remove quarantine
[ "$OS" = "Darwin" ] && xattr -d com.apple.quarantine "$BINARY" 2>/dev/null || true

echo "scalex: installed v${EXPECTED_VERSION}" >&2
exec "$BINARY" "$@"
17 changes: 11 additions & 6 deletions vecxt/package.mill
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import mill.scalajslib.api.ModuleKind
import com.goyeau.mill.scalafix.ScalafixModule
import mill.api.Task.Simple

import mill.contrib.scoverage.ScoverageModule

object `package` extends Module:
trait VecxtModule extends PlatformScalaModule with build.VecxtPublishModule:
def mvnDeps = super.mvnDeps() ++ Seq(
Expand All @@ -25,18 +27,21 @@ object `package` extends Module:
(os.sub / "src-jvm-native")
}

object jvm extends VecxtModule:
object jvm extends VecxtModule with ScoverageModule:
override def scalaVersion = build.V.scalaVersion
def scoverageVersion = "2.5.2"
override def forkArgs = super.forkArgs() ++ build.vecIncubatorFlag
override def enableBsp = build.V.jvmBSP
def mvnDeps = super.mvnDeps() ++ Seq(
build.V.blas,
build.V.lapack
)
def sources = Task(super.sources() ++ jvmNativeSharedSources())

object test extends VecxtTest, ScalaTests:
object test extends VecxtTest, ScalaTests, ScoverageTests:
def moduleDeps = Seq(jvm)
override def forkArgs: Simple[Seq[String]] = super.forkArgs() ++ build.vecIncubatorFlag
override def enableBsp = build.V.jvmBSP
end test
end jvm
object js extends VecxtModule with build.CommonJS:
Expand All @@ -46,19 +51,19 @@ object `package` extends Module:
object test extends VecxtTest, ScalaJSTests:
def moduleDeps = Seq(js)
def moduleKind = ModuleKind.CommonJSModule
override def enableBsp = false
override def enableBsp = build.V.jsBSP
end test
override def enableBsp = false
override def enableBsp = build.V.jsBSP
end js
object native extends VecxtModule with build.CommonNative:
override def mvnDeps = super.mvnDeps()

def sources = Task(super.sources() ++ jsNativeSharedSources() ++ jvmNativeSharedSources())
override def enableBsp = false
override def enableBsp = build.V.nativeBSP

object test extends ScalaNativeTests, VecxtTest:
override def moduleDeps = Seq(native)
override def enableBsp = false
override def enableBsp = build.V.nativeBSP
end test

end native
Expand Down
Loading
Loading