This library is a Clojure/Clojurescript port of Mikola Lysenko’s ndarray core JS library with extended features to make more sense in a Clojure context.
(require '[thi.ng.ndarray.core :as nd])
The ndarray
constructor automatically coerces a Clojure seq into the
correct array type (if not given as array already). transpose
allows
swapping the axis order without any copying.
(def a (nd/ndarray :float64 (range 16) [4 4]))
(seq a)
;; => (0.0 1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0 11.0 12.0 13.0 14.0 15.0)
(seq (nd/transpose a 1 0))
;; => (0.0 4.0 8.0 12.0 1.0 5.0 9.0 13.0 2.0 6.0 10.0 14.0 3.0 7.0 11.0 15.0)
Likewise, step order can be independently flipped/manipulated in any dimension…
(def a (nd/ndarray :float64 (range 16) [4 4]))
(seq (nd/step a -1 nil))
;; => (12.0 13.0 14.0 15.0 8.0 9.0 10.0 11.0 4.0 5.0 6.0 7.0 0.0 1.0 2.0 3.0)
(seq (nd/step a nil -1))
;; => (3.0 2.0 1.0 0.0 7.0 6.0 5.0 4.0 11.0 10.0 9.0 8.0 15.0 14.0 13.0 12.0)
(def a (nd/ndarray :float64 (range 16) [4 4]))
(seq (nd/step a 2 2))
;; => (0.0 2.0 8.0 10.0)
;; ...optionally with offset
(-> a (nd/truncate-l 0 1) (nd/step 2 2) seq)
;; => (1.0 3.0 9.0 11.0)
(def a (nd/ndarray :float32 (range 27) [3 3 3]))
(seq (nd/pick a 2 nil nil))
;; => (18.0 19.0 20.0 21.0 22.0 23.0 24.0 25.0 26.0)
(seq (nd/pick a nil 2 nil))
;; => (6.0 7.0 8.0 15.0 16.0 17.0 24.0 25.0 26.0)
(seq (nd/pick a nil nil 2))
;; => (2.0 5.0 8.0 11.0 14.0 17.0 20.0 23.0 26.0)
(seq (nd/pick a nil 0 0))
;; (0.0 9.0 18.0)
(def a (nd/ndarray :int8 (byte-array 25) [5 5]))
(dorun
(for [i (-> a (nd/truncate-h 4 4) (nd/truncate-l 1 1) nd/index-seq)]
(nd/set-at-index a i 1)))
(seq a)
;; (0 0 0 0 0
;; 0 1 1 1 0
;; 0 1 1 1 0
;; 0 1 1 1 0
;; 0 0 0 0 0)
Code for this example is in the contours namespace.
A slightly larger example to demonstrate connected component queries on a graph:
(defn adjacency-mat
[ids]
(let [n (count ids)]
(nd/ndarray :boolean (repeat (* n n) false) [n n])))
(defn add-edge
[index mat [a b]]
(-> mat
(nd/set-at (index a) (index b) true)
(nd/set-at (index b) (index a) true)))
(defn edge?
[index mat [a b]]
(nd/get-at mat (index a) (index b)))
(defn neighbors
[index rev-index mat x]
(sequence
(comp
(map-indexed (fn [i rel] (if rel (rev-index i))))
(filter identity))
(nd/pick mat (index x) nil)))
(defn all-connected
([index rev-index mat q]
(all-connected index rev-index mat #{} #{} [q]))
([index rev-index mat acc seen q]
(let [n (->> q
(filter (complement seen))
(mapcat #(neighbors index rev-index graph %)))
acc' (into acc n)]
(if (= acc acc')
acc
(recur index rev-index mat acc' (into seen q) n)))))
(def index {:a 0 :b 1 :c 2 :d 3 :e 4 :f 5})
(def rev-index (reduce-kv #(assoc % %3 %2) {} index))
(def graph
(reduce
(partial add-edge index)
(adjacency-mat index)
[[:a :b] [:b :d] [:d :c] [:e :f]]))
(edge? index graph [:b :a]) ;; => true
(edge? index graph [:a :c]) ;; => false
(neighbors index rev-index graph :c) ;; => (:a :d)
(all-connected index rev-index graph :a) ;; => #{:c :b :d :a}
(all-connected index rev-index graph :f) ;; => #{:e :f}
0.3.3
[org.clojure/clojure "1.11.1"]
[org.clojure/clojurescript "1.11.4"]
[thi.ng/typedarrays "0.1.7"]
[thi.ng/math "0.3.1"]
[com.cemerick/clojurescript.test "0.3.3"]
[lein-cljsbuild "1.1.8"]
[lein-auto "0.1.2"]
[criterium "0.4.6"]
[thi.ng/ndarray "0.3.3"]
This project is written in a literate programming format and requires
Emacs & Org-mode to generate usable source code. Assuming both tools
are installed, the easiest way to generate a working project is via
command line (make sure emacs
is on your path or else edit its path
in tangle.sh
):
git clone https://github.com/thi.ng/ndarray.git
cd ndarray
./tangle.sh src/*.org test/*.org
Tangling is the process of extracting & combining source blocks from
.org
files into an actual working project/source tree. Once tangling
is complete, you can cd
into the generated project directory
(babel
) and then use lein
as usual.
The project.clj
file defines an alias to trigger a complete build &
tests for both Clojure & Clojurescript. Since PhantomJS (the usual
test runner for other thi.ng projects) doesn’t support typed arrays,
the cleantest
command will run the Clojurescript tests in your
default browser and test results are displayed in the dev console.
cd babel
lein cleantest
;; or use auto test runner via lein-auto
lein auto test
Tangling this file will also generate a small HTML harness for the
resulting JS file and will be placed in the main folder
(babel/index.html
), allowing for further experimentation in the
browser.
(defproject thi.ng/ndarray "<<version>>"
:description "ndarray for Clojure/Clojurescript"
:url "<<project-url>>"
:license {:name "Apache Software License 2.0"
:url "http://www.apache.org/licenses/LICENSE-2.0"
:distribution :repo}
:scm {:name "git"
:url "[email protected]:thi-ng/ndarray.git"}
:min-lein-vesion "2.4.0"
:dependencies [<<dep-clj>>
<<dep-cljs>>
<<dep-arrays>>
<<dep-math>>]
:plugins [<<dep-autotest>>]
:profiles {:dev {:dependencies [<<dep-criterium>>]
:plugins [<<dep-cljsbuild>>
<<dep-cljs-test>>]
:global-vars {*warn-on-reflection* true}
:jvm-opts ^:replace []
:aliases {"cleantest" ["do" "clean," "test," "cljsbuild" "test"]}}}
:auto {:default {:file-pattern #"\.(clj|cljs|cljc)$"}}
:cljsbuild {:builds [{:id "simple"
:source-paths ["src" "test"]
:compiler {:output-to "<<cljs-artefact-path>>"
:optimizations :whitespace
:pretty-print true}}]
:test-commands {"unit-tests" ["open" :runner "index.html"]}}
:pom-addition [:developers [:developer
[:name "Karsten Schmidt"]
[:url "https://thi.ng"]
[:timezone "1"]]])
<!DOCTYPE html>
<html lang="en">
<head>
<title><<lein-coords>> test</title>
</head>
<body>
<script type="text/javascript" src="<<cljs-artefact-path>>"></script>
</body>
</html>
The autogenerated namespace thi.ng.ndarray.version
contains a single
symbol version
holding the version string defined above:
(use '[thi.ng.ndarray.version])
(prn version)
; "<<version>>"
Version | Released | Description | Lein coordinates | Tagged Github URL |
---|---|---|---|---|
0.3.3 | 2022-04-23 | update deps | [thi.ng/ndarray "0.3.3"] | 0.3.3 |
0.3.2 | 2016-03-19 | update thi.ng/math dep | [thi.ng/ndarray "0.3.2"] | 0.3.2 |
0.3.1 | 2016-03-19 | fix refl. warning, refactor reduce impls, update deps | [thi.ng/ndarray "0.3.1"] | 0.3.1 |
0.3.0 | 2015-06-20 | CollReduce support, cljs bugfix contour ns, update deps | [thi.ng/ndarray "0.3.0"] | 0.3.0 |
0.2.0 | 2015-06-14 | add contour ns, bugfixes, updated deps | [thi.ng/ndarray "0.2.0"] | 0.2.0 |
0.1.0 | 2015-05-31 | initial test release | [thi.ng/ndarray "0.1.0"] | 0.1.0 |
Name | Role | Website |
---|---|---|
Karsten Schmidt | initiator & principal developer | https://thi.ng |
I’ve got a fairly detailed roadmap and task list to implement over the coming months, but am always happy to receive feedback & suggestions and have issues filed. Once the core engine is more refined I’ll be gladly welcoming other contributions. Thanks for understanding!
This project is open source and licensed under the Apache Software License 2.0.