<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>