1020 lines
61 KiB
HTML
1020 lines
61 KiB
HTML
<html>
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
|
<link rel="stylesheet" href="../coverage.css"/> <title> sparse_array/core.clj </title>
|
|
</head>
|
|
<body>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
001 (ns sparse-array.core
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
002 "Operations on sparse arrays.")
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
003
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
004 (declare put get)
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
005
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
006 (def ^:dynamic *safe-sparse-operations*
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
007 "Whether spase array operations should be conducted safely, with careful
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
008 checking of data conventions and exceptions thrown if expectations are not
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
009 met. Normally `false`."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
010 false)
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
011
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
012 (defn- unsafe-sparse-operations?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
013 "returns `true` if `*safe-sparse-operations*` is `false`, and vice versa."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
014 []
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
015 (not (true? *safe-sparse-operations*)))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
016
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
017 (defn make-sparse-array
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
018 "Make a sparse array with these `dimensions`. Every member of `dimensions`
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
019 must be a keyword; otherwise, `nil` will be returned."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
020 [& dimensions]
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
021 (when
|
|
</span><br/>
|
|
<span class="partial" title="7 out of 8 forms covered">
|
|
022 (and (pos? (count dimensions))
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
023 (every? keyword? dimensions))
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
024 {:dimensions (count dimensions)
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
025 :coord (first dimensions)
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
026 :content (if
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
027 (empty? (rest dimensions))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
028 :data
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
029 (rest dimensions))}))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
030
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
031 (defn- safe-test-or-throw
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
032 "If `v` is truthy or `*safe-sparse-operations*` is false, return `v`;
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
033 otherwise, throw an `ExceptionInfo` with this `message` and the map `m`."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
034 [v message m]
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
035 (if-not
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
036 v
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
037 (if
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
038 *safe-sparse-operations*
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
039 (throw (ex-info message m))
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
040 v)
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
041 v))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
042
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
043 (defn sparse-array?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
044 "`true` if `x` is a sparse array conforming to the conventions established
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
045 by this library, else `false`."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
046 ;; TODO: sparse-array? should not throw exceptions even when
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
047 ;; *safe-sparse-operations* is true, since we may use to test
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
048 ;; whether an object is a sparse array. The place to throw the exceptions
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
049 ;; (if required) is after it has failed.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
050 ([x]
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
051 (apply
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
052 sparse-array?
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
053 (cons
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
054 x
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
055 (cons
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
056 (:coord x)
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
057 (when
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
058 (coll? (:content x))
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
059 (:content x))))))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
060 ([x & axes]
|
|
</span><br/>
|
|
<span class="partial" title="16 out of 17 forms covered">
|
|
061 (and
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
062 (safe-test-or-throw
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
063 (map? x)
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
064 "Array must be a map" {:array x})
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
065 (safe-test-or-throw
|
|
</span><br/>
|
|
<span class="covered" title="13 out of 13 forms covered">
|
|
066 (and (integer? (:dimensions x)) (pos? (:dimensions x)))
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
067 (str "The value of `:dimensions` must be a positive integer, not " (:dimensions x))
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
068 {:array x})
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
069 (safe-test-or-throw
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
070 (keyword? (:coord x))
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
071 (str "The value of `:coord` must be a keyword, not " (:coord x))
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
072 {:array x})
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
073 (safe-test-or-throw
|
|
</span><br/>
|
|
<span class="covered" title="7 out of 7 forms covered">
|
|
074 (= (:coord x) (first axes))
|
|
</span><br/>
|
|
<span class="covered" title="10 out of 10 forms covered">
|
|
075 (str "The value of `:coord` must be " (first axes) ", not " (:coord x))
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
076 {:array x})
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
077 (if
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
078 (empty? (rest axes))
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
079 (safe-test-or-throw
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
080 (= (:content x) :data)
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
081 "If there are no further axes the value of `:content` must be `:data`"
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
082 {:array x})
|
|
</span><br/>
|
|
<span class="partial" title="4 out of 5 forms covered">
|
|
083 (and
|
|
</span><br/>
|
|
<span class="covered" title="7 out of 7 forms covered">
|
|
084 (= (:content x) (rest axes))
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
085 (every?
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
086 sparse-array?
|
|
</span><br/>
|
|
<span class="covered" title="12 out of 12 forms covered">
|
|
087 (map #(x %) (filter integer? (keys x)))))))))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
088
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
089 (defn- unsafe-put
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
090 [array value coordinates]
|
|
</span><br/>
|
|
<span class="partial" title="1 out of 2 forms covered">
|
|
091 (cond
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
092 (every?
|
|
</span><br/>
|
|
<span class="partial" title="14 out of 15 forms covered">
|
|
093 #(and (integer? %) (or (zero? %) (pos? %)))
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
094 coordinates)
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
095 (assoc
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
096 array
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
097 (first coordinates)
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
098 (if
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
099 (= :data (:content array))
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
100 value
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
101 (apply
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
102 put
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
103 (cons
|
|
</span><br/>
|
|
<span class="partial" title="4 out of 5 forms covered">
|
|
104 (or
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
105 (array (first coordinates))
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
106 (apply make-sparse-array (:content array)))
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
107 (cons value (rest coordinates))))))))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
108
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
109 (defn put
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
110 "Return a sparse array like this `array` but with this `value` at these
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
111 `coordinates`. Returns `nil` if any coordinate is invalid."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
112 [array value & coordinates]
|
|
</span><br/>
|
|
<span class="partial" title="6 out of 7 forms covered">
|
|
113 (cond
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
114 (nil? value)
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
115 nil
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
116 (unsafe-sparse-operations?)
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
117 (unsafe-put array value coordinates)
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
118 (not (sparse-array? array))
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 7 forms covered">
|
|
119 (throw (ex-info "Sparse array expected" {:array array}))
|
|
</span><br/>
|
|
<span class="covered" title="7 out of 7 forms covered">
|
|
120 (not= (:dimensions array) (count coordinates))
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
121 (throw
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
122 (ex-info
|
|
</span><br/>
|
|
<span class="covered" title="9 out of 9 forms covered">
|
|
123 (str "Expected " (:dimensions array) " coordinates; found " (count coordinates))
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
124 {:array array
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
125 :coordinates coordinates}))
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
126 (not
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
127 (every?
|
|
</span><br/>
|
|
<span class="partial" title="13 out of 15 forms covered">
|
|
128 #(and (integer? %) (or (zero? %) (pos? %)))
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
129 coordinates))
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 1 forms covered">
|
|
130 (throw
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 3 forms covered">
|
|
131 (ex-info
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
132 "Coordinates must be zero or positive integers"
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 5 forms covered">
|
|
133 {:array array
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 1 forms covered">
|
|
134 :coordinates coordinates
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 13 forms covered">
|
|
135 :invalid (remove #(and (pos? %) (integer? %)) coordinates)}))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
136 :else
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
137 (unsafe-put array value coordinates)))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
138
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
139 (defn- unsafe-get
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
140 ;; TODO: I am CERTAIN there is a more elegant solution to this.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
141 [array coordinates]
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
142 (let [v (array (first coordinates))]
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
143 (cond
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
144 (= :data (:content array))
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
145 v
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
146 (nil? v)
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
147 nil
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
148 :else
|
|
</span><br/>
|
|
<span class="covered" title="9 out of 9 forms covered">
|
|
149 (apply get (cons v (rest coordinates))))))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
150
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
151 (defn get
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
152 "Return the value in this sparse `array` at these `coordinates`."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
153 [array & coordinates]
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
154 (cond
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
155 (unsafe-sparse-operations?)
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
156 (unsafe-get array coordinates)
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
157 (not (sparse-array? array))
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 7 forms covered">
|
|
158 (throw (ex-info "Sparse array expected" {:array array}))
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
159 (not (every?
|
|
</span><br/>
|
|
<span class="partial" title="13 out of 15 forms covered">
|
|
160 #(and (integer? %) (or (zero? %) (pos? %)))
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
161 coordinates))
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 1 forms covered">
|
|
162 (throw
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 3 forms covered">
|
|
163 (ex-info
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
164 "Coordinates must be zero or positive integers"
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 5 forms covered">
|
|
165 {:array array
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 1 forms covered">
|
|
166 :coordinates coordinates
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 13 forms covered">
|
|
167 :invalid (remove #(and (pos? %) (integer? %)) coordinates)}))
|
|
</span><br/>
|
|
<span class="covered" title="8 out of 8 forms covered">
|
|
168 (not (= (:dimensions array) (count coordinates)))
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
169 (throw
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
170 (ex-info
|
|
</span><br/>
|
|
<span class="covered" title="9 out of 9 forms covered">
|
|
171 (str "Expected " (:dimensions array) " coordinates; found " (count coordinates))
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
172 {:array array
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
173 :coordinates coordinates}))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
174 :else
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
175 (unsafe-get array coordinates)))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
176
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
177 (defn dense-dimensions
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
178 "How many usable dimensions (represented as vectors) does the dense array
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
179 `x` have?"
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
180 [x]
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
181 (if
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
182 (vector? x)
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
183 (if
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
184 (every? vector? x)
|
|
</span><br/>
|
|
<span class="covered" title="8 out of 8 forms covered">
|
|
185 (inc (apply min (map dense-dimensions x)))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
186 ;; `min` is right here, not `max`, because otherwise
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
187 ;; we will get malformed arrays. Be liberal with what you
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
188 ;; consume, conservative with what you return!
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
189 1)
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
190 0))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
191
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
192 (defn dense-array?
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
193 "Basically, any vector can be considered as a dense array of one dimension.
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
194 If we're seeking a dense array of more than one dimension, the number of
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
195 dimensions should be specified as `d`."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
196 ([x]
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
197 (vector? x))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
198 ([x d]
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 12 forms covered">
|
|
199 (and (vector? x) (< d (dense-dimensions x)))))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
200
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
201 (defn merge-sparse-arrays
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
202 "Return a sparse array taking values from sparse arrays `a1` and `a2`,
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
203 but preferring values from `a2` where there is a conflict. `a1` and `a2`
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
204 must have the **same** dimensions in the **same** order, or `nil` will
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
205 be returned."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
206 [a1 a2]
|
|
</span><br/>
|
|
<span class="partial" title="5 out of 7 forms covered">
|
|
207 (cond
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
208 (nil? a1) a2
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
209 (nil? a2) a1
|
|
</span><br/>
|
|
<span class="covered" title="9 out of 9 forms covered">
|
|
210 (not (= (:content a1) (:content a2)))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
211 ;; can't reasonably merge arrays with different dimensions
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
212 nil
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
213 (= :data (:content a1))
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
214 (merge a1 a2)
|
|
</span><br/>
|
|
<span class="partial" title="6 out of 16 forms covered">
|
|
215 (or (unsafe-sparse-operations?) (and (sparse-array? a1) (sparse-array? a2)))
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
216 (reduce
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
217 merge
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
218 a2
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
219 (map
|
|
</span><br/>
|
|
<span class="covered" title="12 out of 12 forms covered">
|
|
220 #(assoc a2 % (merge-sparse-arrays (a1 %) (a2 %)))
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
221 (filter
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
222 integer?
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
223 (set
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
224 (concat
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
225 (keys a1)
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
226 (keys a2))))))))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
227
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
228 (defn merge-dense-with-sparse
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
229 "Merge this dense array `d` with this sparse array `s`, returning a new
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
230 dense array with the same arity as `d`, preferring values from `s` where
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
231 there is conflict"
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
232 [d s]
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
233 (apply
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
234 vector
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
235 (map
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
236 #(cond
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
237 (= :data (:content s))
|
|
</span><br/>
|
|
<span class="covered" title="8 out of 8 forms covered">
|
|
238 (or (s %2) %1)
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
239 (nil? (s %2))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
240 %1
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
241 :else
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
242 (merge-dense-with-sparse %1 (s %2)))
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
243 d
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
244 (range))))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
245
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
246 (defn merge-arrays
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
247 "Merge two arrays `a1`, `a2`, which may be either dense or sparse but which
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
248 should have the same number of axes and compatible dimensions, and return a
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
249 new dense array preferring values from `a2`."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
250 [a1 a2]
|
|
</span><br/>
|
|
<span class="partial" title="3 out of 5 forms covered">
|
|
251 (cond
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
252 (dense-array? a2)
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 1 forms covered">
|
|
253 a2 ;; if a2 is dense, no values from a1 will be returned
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
254 (sparse-array? a1)
|
|
</span><br/>
|
|
<span class="partial" title="1 out of 3 forms covered">
|
|
255 (cond
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
256 (sparse-array? a2)
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
257 (merge-sparse-arrays a1 a2)
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 1 forms covered">
|
|
258 *safe-sparse-operations*
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 1 forms covered">
|
|
259 (throw
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 3 forms covered">
|
|
260 (ex-info
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
261 "Object passed as array is neither dense not sparse"
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 3 forms covered">
|
|
262 {:array a2})))
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
263 (dense-array? a1)
|
|
</span><br/>
|
|
<span class="partial" title="1 out of 3 forms covered">
|
|
264 (cond
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
265 (sparse-array? a2)
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
266 (merge-dense-with-sparse a1 a2)
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 1 forms covered">
|
|
267 *safe-sparse-operations*
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 1 forms covered">
|
|
268 (throw
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 3 forms covered">
|
|
269 (ex-info
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
270 "Object passed as array is neither dense not sparse"
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 3 forms covered">
|
|
271 {:array a2})))
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 1 forms covered">
|
|
272 *safe-sparse-operations*
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 1 forms covered">
|
|
273 (throw
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 3 forms covered">
|
|
274 (ex-info
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
275 "Object passed as array is neither dense not sparse"
|
|
</span><br/>
|
|
<span class="not-covered" title="0 out of 3 forms covered">
|
|
276 {:array a1}))))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
277
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
278 (defn dense-to-sparse
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
279 "Return a sparse array representing the content of the dense array `x`,
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
280 assuming these `axes` if specified. *NOTE THAT* if insufficient
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
281 values of `axes` are specified, the resulting sparse array will
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
282 be malformed."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
283 ([x]
|
|
</span><br/>
|
|
<span class="covered" title="14 out of 14 forms covered">
|
|
284 (dense-to-sparse x (map #(keyword (str "i" %)) (range))))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
285 ([x axes]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
286 (let
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
287 [dimensions (dense-dimensions x)]
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
288 (reduce
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
289 merge
|
|
</span><br/>
|
|
<span class="covered" title="7 out of 7 forms covered">
|
|
290 (apply make-sparse-array (take dimensions axes))
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
291 (map
|
|
</span><br/>
|
|
<span class="covered" title="10 out of 10 forms covered">
|
|
292 (fn [i v] (if (nil? v) nil (hash-map i v)))
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
293 (range)
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
294 (if
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
295 (> dimensions 1)
|
|
</span><br/>
|
|
<span class="covered" title="10 out of 10 forms covered">
|
|
296 (map #(dense-to-sparse % (rest axes)) x)
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
297 x))))))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
298
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
299 (defn arity
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
300 "Return the arity of the sparse array `x`."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
301 [x]
|
|
</span><br/>
|
|
<span class="covered" title="10 out of 10 forms covered">
|
|
302 (inc (apply max (filter integer? (keys x)))))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
303
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
304 (defn child-arity
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
305 "Return the largest arity among the arities of the next dimension layer of
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
306 the sparse array `x`."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
307 [x]
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
308 (apply
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
309 max
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
310 (cons
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
311 -1 ;; if no children are sparse arrays, we should return 0ß
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
312 (map
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
313 arity
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
314 (filter sparse-array? (vals x))))))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
315
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
316 (defn sparse-to-dense
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
317 "Return a dense array representing the content of the sparse array `x`.
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
318
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
319 **NOTE THAT** this has the potential to consume very large amounts of memory."
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
320 ([x]
|
|
</span><br/>
|
|
<span class="covered" title="6 out of 6 forms covered">
|
|
321 (sparse-to-dense x (arity x)))
|
|
</span><br/>
|
|
<span class="not-tracked" title="0 out of 0 forms covered">
|
|
322 ([x arity]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
323 (if
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
324 (map? x)
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
325 (let [a (child-arity x)]
|
|
</span><br/>
|
|
<span class="covered" title="2 out of 2 forms covered">
|
|
326 (apply
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
327 vector
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
328 (map
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
329 #(let [v (x %)]
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
330 (if
|
|
</span><br/>
|
|
<span class="covered" title="5 out of 5 forms covered">
|
|
331 (= :data (:content x))
|
|
</span><br/>
|
|
<span class="covered" title="1 out of 1 forms covered">
|
|
332 v
|
|
</span><br/>
|
|
<span class="covered" title="4 out of 4 forms covered">
|
|
333 (sparse-to-dense v a)))
|
|
</span><br/>
|
|
<span class="covered" title="3 out of 3 forms covered">
|
|
334 (range arity))))
|
|
</span><br/>
|
|
<span class="covered" title="7 out of 7 forms covered">
|
|
335 (apply vector (repeat arity nil)))))
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
336
|
|
</span><br/>
|
|
<span class="blank" title="0 out of 0 forms covered">
|
|
337
|
|
</span><br/>
|
|
</body>
|
|
</html>
|