├── .gitignore ├── .travis.yml ├── README.md ├── project.clj ├── src ├── clj_tuple.clj └── clojure │ └── lang │ ├── PersistentUnrolledMap.java │ └── PersistentUnrolledVector.java └── test └── clj_tuple_test.clj /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | /classes 3 | /checkouts 4 | pom.xml 5 | pom.xml.asc 6 | *.jar 7 | *.class 8 | /.lein-* 9 | /.nrepl-port 10 | push -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: clojure 2 | lein: lein2 3 | script: lein2 do clean, test 4 | jdk: 5 | - openjdk7 6 | - oraclejdk7 7 | - openjdk6 -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This library provides efficient implementations for small maps and vectors, discussed more in [this post](http://blog.factual.com/using-clojure-to-generate-java-to-reimplement-clojure). These implementations will eventually be merged into Clojure proper, but for now can be used by replacing `vector` with `clj-tuple/vector` and `hash-map` with `clj-tuple/hash-map`. 2 | 3 | ### usage 4 | 5 | [![Build Status](https://travis-ci.org/ztellman/clj-tuple.png?branch=master)](https://travis-ci.org/ztellman/clj-tuple) 6 | 7 | ```clj 8 | [clj-tuple "0.2.2"] 9 | ``` 10 | 11 | ```clj 12 | clj-tuple> (vector 1 2 3) 13 | [1 2 3] 14 | clj-tuple> (hash-map 1 2 3 4) 15 | {1 2, 3 4} 16 | ``` 17 | 18 | ### license 19 | 20 | Copyright © 2015 Zachary Tellman 21 | 22 | Distributed under the MIT License 23 | -------------------------------------------------------------------------------- /project.clj: -------------------------------------------------------------------------------- 1 | (defproject clj-tuple "0.2.2" 2 | :description "Efficient small collections." 3 | :license {:name "MIT License" 4 | :url "http://opensource.org/licenses/MIT"} 5 | :dependencies [] 6 | :profiles {:dev {:dependencies [[criterium "0.4.1"] 7 | [collection-check "0.1.5"]]} 8 | :provided {:dependencies [[org.clojure/clojure "1.7.0-alpha5"]]}} 9 | :global-vars {*warn-on-reflection* true} 10 | :test-selectors {:benchmark :benchmark 11 | :stress :stress 12 | :default #(every? (complement #{:benchmark :stress}) (keys %))} 13 | :java-source-paths ["src"] 14 | :javac-options ["-target" "1.5" "-source" "1.5"] 15 | :jvm-opts ^:replace ["-server" "-Xmx500m" "-XX:NewSize=200m"]) 16 | -------------------------------------------------------------------------------- /src/clj_tuple.clj: -------------------------------------------------------------------------------- 1 | (ns clj-tuple 2 | (:import 3 | [clojure.lang 4 | PersistentUnrolledVector 5 | PersistentUnrolledMap]) 6 | (:refer-clojure :exclude [vector hash-map])) 7 | 8 | (defn hash-map 9 | ([] 10 | (PersistentUnrolledMap/create)) 11 | ([k1 v1] 12 | (PersistentUnrolledMap/create k1 v1)) 13 | ([k1 v1 k2 v2] 14 | (PersistentUnrolledMap/create k1 v1 k2 v2)) 15 | ([k1 v1 k2 v2 k3 v3] 16 | (PersistentUnrolledMap/create k1 v1 k2 v2 k3 v3)) 17 | ([k1 v1 k2 v2 k3 v3 k4 v4] 18 | (PersistentUnrolledMap/create k1 v1 k2 v2 k3 v3 k4 v4)) 19 | ([k1 v1 k2 v2 k3 v3 k4 v4 k5 v5] 20 | (PersistentUnrolledMap/create k1 v1 k2 v2 k3 v3 k4 v4 k5 v5)) 21 | ([k1 v1 k2 v2 k3 v3 k4 v4 k5 v5 k6 v6] 22 | (PersistentUnrolledMap/create k1 v1 k2 v2 k3 v3 k4 v4 k5 v5 k6 v6)) 23 | ([k1 v1 k2 v2 k3 v3 k4 v4 k5 v5 k6 v6 & rst] 24 | (let [m (transient (PersistentUnrolledMap/create k1 v1 k2 v2 k3 v3 k4 v4 k5 v5 k6 v6))] 25 | (loop [m m, s rst] 26 | (if (empty? s) 27 | (persistent! m) 28 | (let [k (first s) 29 | s (rest s)] 30 | (when (empty? s) 31 | (throw 32 | (IllegalArgumentException. 33 | "Cannot pass an odd number of arguments into 'map'."))) 34 | (recur (assoc! m k (first s)) (rest s)))))))) 35 | 36 | (defn vector 37 | "Returns a collection which behaves like a vector, but is highly efficient for index lookups, 38 | hash calculations, equality checks, and reduction. If there are more than six elements, 39 | returns a normal vector." 40 | ([] 41 | (PersistentUnrolledVector/create)) 42 | ([x] 43 | (PersistentUnrolledVector/create x)) 44 | ([x y] 45 | (PersistentUnrolledVector/create x y)) 46 | ([x y z] 47 | (PersistentUnrolledVector/create x y z)) 48 | ([x y z w] 49 | (PersistentUnrolledVector/create x y z w)) 50 | ([x y z w u] 51 | (PersistentUnrolledVector/create x y z w u)) 52 | ([x y z w u v] 53 | (PersistentUnrolledVector/create x y z w u v)) 54 | ([x y z w u v & rst] 55 | (let [r (transient (PersistentUnrolledVector/create x y z w u v))] 56 | (loop [r r, s rst] 57 | (if (empty? s) 58 | (persistent! r) 59 | (recur (conj! r (first s)) (rest s))))))) 60 | 61 | (def tuple vector) 62 | -------------------------------------------------------------------------------- /src/clojure/lang/PersistentUnrolledMap.java: -------------------------------------------------------------------------------- 1 | package clojure.lang; 2 | 3 | import java.util.Iterator; 4 | import java.util.Map; 5 | 6 | public class PersistentUnrolledMap { 7 | static IPersistentMap EMPTY = new Card0(); 8 | static Object NOT_FOUND = new Object(); 9 | 10 | public static IPersistentMap create() { 11 | return EMPTY; 12 | } 13 | 14 | public static IPersistentMap create(Object k0, Object v0) { 15 | return new Card1(k0, v0, Util.hasheq(k0)); 16 | } 17 | 18 | public static IPersistentMap create(Object k0, Object v0, Object k1, 19 | Object v1) { 20 | return new Card2(k0, v0, Util.hasheq(k0), k1, v1, Util.hasheq(k1)); 21 | } 22 | 23 | public static IPersistentMap create(Object k0, Object v0, Object k1, 24 | Object v1, Object k2, Object v2) { 25 | return new Card3(k0, v0, Util.hasheq(k0), k1, v1, Util.hasheq(k1), k2, 26 | v2, Util.hasheq(k2)); 27 | } 28 | 29 | public static IPersistentMap create(Object k0, Object v0, Object k1, 30 | Object v1, Object k2, Object v2, Object k3, Object v3) { 31 | return new Card4(k0, v0, Util.hasheq(k0), k1, v1, Util.hasheq(k1), k2, 32 | v2, Util.hasheq(k2), k3, v3, Util.hasheq(k3)); 33 | } 34 | 35 | public static IPersistentMap create(Object k0, Object v0, Object k1, 36 | Object v1, Object k2, Object v2, Object k3, Object v3, Object k4, 37 | Object v4) { 38 | return new Card5(k0, v0, Util.hasheq(k0), k1, v1, Util.hasheq(k1), k2, 39 | v2, Util.hasheq(k2), k3, v3, Util.hasheq(k3), k4, v4, 40 | Util.hasheq(k4)); 41 | } 42 | 43 | public static IPersistentMap create(Object k0, Object v0, Object k1, 44 | Object v1, Object k2, Object v2, Object k3, Object v3, Object k4, 45 | Object v4, Object k5, Object v5) { 46 | return new Card6(k0, v0, Util.hasheq(k0), k1, v1, Util.hasheq(k1), k2, 47 | v2, Util.hasheq(k2), k3, v3, Util.hasheq(k3), k4, v4, 48 | Util.hasheq(k4), k5, v5, Util.hasheq(k5)); 49 | } 50 | 51 | static class Transient extends ATransientMap implements ITransientMap { 52 | private Object k0; 53 | private Object k1; 54 | private Object k2; 55 | private Object k3; 56 | private Object k4; 57 | private Object k5; 58 | private Object v0; 59 | private Object v1; 60 | private Object v2; 61 | private Object v3; 62 | private Object v4; 63 | private Object v5; 64 | private int h0; 65 | private int h1; 66 | private int h2; 67 | private int h3; 68 | private int h4; 69 | private int h5; 70 | private int count = 0; 71 | private boolean edit = true; 72 | 73 | public Transient() { 74 | count = 0; 75 | } 76 | 77 | public Transient(Object k0, Object v0, int h0) { 78 | count = 1; 79 | this.k0 = k0; 80 | this.v0 = v0; 81 | this.h0 = h0; 82 | } 83 | 84 | public Transient(Object k0, Object v0, int h0, Object k1, Object v1, 85 | int h1) { 86 | count = 2; 87 | this.k0 = k0; 88 | this.v0 = v0; 89 | this.h0 = h0; 90 | this.k1 = k1; 91 | this.v1 = v1; 92 | this.h1 = h1; 93 | } 94 | 95 | public Transient(Object k0, Object v0, int h0, Object k1, Object v1, 96 | int h1, Object k2, Object v2, int h2) { 97 | count = 3; 98 | this.k0 = k0; 99 | this.v0 = v0; 100 | this.h0 = h0; 101 | this.k1 = k1; 102 | this.v1 = v1; 103 | this.h1 = h1; 104 | this.k2 = k2; 105 | this.v2 = v2; 106 | this.h2 = h2; 107 | } 108 | 109 | public Transient(Object k0, Object v0, int h0, Object k1, Object v1, 110 | int h1, Object k2, Object v2, int h2, Object k3, Object v3, 111 | int h3) { 112 | count = 4; 113 | this.k0 = k0; 114 | this.v0 = v0; 115 | this.h0 = h0; 116 | this.k1 = k1; 117 | this.v1 = v1; 118 | this.h1 = h1; 119 | this.k2 = k2; 120 | this.v2 = v2; 121 | this.h2 = h2; 122 | this.k3 = k3; 123 | this.v3 = v3; 124 | this.h3 = h3; 125 | } 126 | 127 | public Transient(Object k0, Object v0, int h0, Object k1, Object v1, 128 | int h1, Object k2, Object v2, int h2, Object k3, Object v3, 129 | int h3, Object k4, Object v4, int h4) { 130 | count = 5; 131 | this.k0 = k0; 132 | this.v0 = v0; 133 | this.h0 = h0; 134 | this.k1 = k1; 135 | this.v1 = v1; 136 | this.h1 = h1; 137 | this.k2 = k2; 138 | this.v2 = v2; 139 | this.h2 = h2; 140 | this.k3 = k3; 141 | this.v3 = v3; 142 | this.h3 = h3; 143 | this.k4 = k4; 144 | this.v4 = v4; 145 | this.h4 = h4; 146 | } 147 | 148 | public Transient(Object k0, Object v0, int h0, Object k1, Object v1, 149 | int h1, Object k2, Object v2, int h2, Object k3, Object v3, 150 | int h3, Object k4, Object v4, int h4, Object k5, Object v5, 151 | int h5) { 152 | count = 6; 153 | this.k0 = k0; 154 | this.v0 = v0; 155 | this.h0 = h0; 156 | this.k1 = k1; 157 | this.v1 = v1; 158 | this.h1 = h1; 159 | this.k2 = k2; 160 | this.v2 = v2; 161 | this.h2 = h2; 162 | this.k3 = k3; 163 | this.v3 = v3; 164 | this.h3 = h3; 165 | this.k4 = k4; 166 | this.v4 = v4; 167 | this.h4 = h4; 168 | this.k5 = k5; 169 | this.v5 = v5; 170 | this.h5 = h5; 171 | } 172 | 173 | void ensureEditable() { 174 | if (!edit) { 175 | throw new IllegalAccessError( 176 | "Transient used after persistent! call"); 177 | } 178 | } 179 | 180 | private int indexOf(int h, Object key) { 181 | if (key instanceof Keyword) { 182 | switch (6 - count) { 183 | case 0: 184 | if (k5 == key) { 185 | return 5; 186 | } 187 | case 1: 188 | if (k4 == key) { 189 | return 4; 190 | } 191 | case 2: 192 | if (k3 == key) { 193 | return 3; 194 | } 195 | case 3: 196 | if (k2 == key) { 197 | return 2; 198 | } 199 | case 4: 200 | if (k1 == key) { 201 | return 1; 202 | } 203 | case 5: 204 | if (k0 == key) { 205 | return 0; 206 | } 207 | default: 208 | return -1; 209 | } 210 | } 211 | return indexOfObj(h, key); 212 | } 213 | 214 | private int indexOfObj(int h, Object key) { 215 | Util.EquivPred ep = Util.equivPred(key); 216 | switch (6 - count) { 217 | case 0: 218 | if (h5 == h && ep.equiv(key, k5)) { 219 | return 5; 220 | } 221 | case 1: 222 | if (h4 == h && ep.equiv(key, k4)) { 223 | return 4; 224 | } 225 | case 2: 226 | if (h3 == h && ep.equiv(key, k3)) { 227 | return 3; 228 | } 229 | case 3: 230 | if (h2 == h && ep.equiv(key, k2)) { 231 | return 2; 232 | } 233 | case 4: 234 | if (h1 == h && ep.equiv(key, k1)) { 235 | return 1; 236 | } 237 | case 5: 238 | if (h0 == h && ep.equiv(key, k0)) { 239 | return 0; 240 | } 241 | } 242 | return -1; 243 | } 244 | 245 | ITransientMap doAssoc(Object key, Object val) { 246 | int h = Util.hasheq(key); 247 | int idx = indexOf(h, key); 248 | if (idx == -1) { 249 | switch (count++) { 250 | case 0: 251 | h0 = h; 252 | k0 = key; 253 | v0 = val; 254 | return this; 255 | case 1: 256 | h1 = h; 257 | k1 = key; 258 | v1 = val; 259 | return this; 260 | case 2: 261 | h2 = h; 262 | k2 = key; 263 | v2 = val; 264 | return this; 265 | case 3: 266 | h3 = h; 267 | k3 = key; 268 | v3 = val; 269 | return this; 270 | case 4: 271 | h4 = h; 272 | k4 = key; 273 | v4 = val; 274 | return this; 275 | case 5: 276 | h5 = h; 277 | k5 = key; 278 | v5 = val; 279 | return this; 280 | default: 281 | return PersistentHashMap.EMPTY.asTransient().assoc(k0, v0) 282 | .assoc(k1, v1).assoc(k2, v2).assoc(k3, v3) 283 | .assoc(k4, v4).assoc(k5, v5).assoc(key, val); 284 | } 285 | } else { 286 | switch (idx) { 287 | case 0: 288 | v0 = val; 289 | return this; 290 | case 1: 291 | v1 = val; 292 | return this; 293 | case 2: 294 | v2 = val; 295 | return this; 296 | case 3: 297 | v3 = val; 298 | return this; 299 | case 4: 300 | v4 = val; 301 | return this; 302 | case 5: 303 | v5 = val; 304 | return this; 305 | default: 306 | return null; 307 | } 308 | } 309 | } 310 | 311 | Object doValAt(Object key, Object notFound) { 312 | int h = Util.hasheq(key); 313 | int idx = indexOf(h, key); 314 | switch (idx) { 315 | case 0: 316 | return v0; 317 | case 1: 318 | return v1; 319 | case 2: 320 | return v2; 321 | case 3: 322 | return v3; 323 | case 4: 324 | return v4; 325 | case 5: 326 | return v5; 327 | default: 328 | return notFound; 329 | } 330 | } 331 | 332 | ITransientMap doWithout(Object key) { 333 | int h = Util.hasheq(key); 334 | int idx = indexOf(h, key); 335 | if (idx < 0) { 336 | return this; 337 | } 338 | count--; 339 | switch (idx) { 340 | case 0: 341 | k0 = k1; 342 | v0 = v1; 343 | h0 = h1; 344 | if (count == 1) { 345 | break; 346 | } 347 | case 1: 348 | k1 = k2; 349 | v1 = v2; 350 | h1 = h2; 351 | if (count == 2) { 352 | break; 353 | } 354 | case 2: 355 | k2 = k3; 356 | v2 = v3; 357 | h2 = h3; 358 | if (count == 3) { 359 | break; 360 | } 361 | case 3: 362 | k3 = k4; 363 | v3 = v4; 364 | h3 = h4; 365 | if (count == 4) { 366 | break; 367 | } 368 | case 4: 369 | k4 = k5; 370 | v4 = v5; 371 | h4 = h5; 372 | } 373 | return this; 374 | } 375 | 376 | IPersistentMap doPersistent() { 377 | switch (count) { 378 | case 0: 379 | return EMPTY; 380 | case 1: 381 | return new Card1(k0, v0, h0); 382 | case 2: 383 | return new Card2(k0, v0, h0, k1, v1, h1); 384 | case 3: 385 | return new Card3(k0, v0, h0, k1, v1, h1, k2, v2, h2); 386 | case 4: 387 | return new Card4(k0, v0, h0, k1, v1, h1, k2, v2, h2, k3, v3, h3); 388 | case 5: 389 | return new Card5(k0, v0, h0, k1, v1, h1, k2, v2, h2, k3, v3, 390 | h3, k4, v4, h4); 391 | case 6: 392 | return new Card6(k0, v0, h0, k1, v1, h1, k2, v2, h2, k3, v3, 393 | h3, k4, v4, h4, k5, v5, h5); 394 | } 395 | throw new IllegalStateException(); 396 | } 397 | 398 | int doCount() { 399 | return count; 400 | } 401 | } 402 | 403 | public static class Card0 extends APersistentMap implements IObj, 404 | IEditableCollection, IReduce { 405 | private final IPersistentMap meta; 406 | 407 | Card0(IPersistentMap meta) { 408 | this.meta = meta; 409 | } 410 | 411 | public Card0() { 412 | this.meta = null; 413 | } 414 | 415 | public IPersistentMap meta() { 416 | return meta; 417 | } 418 | 419 | public IObj withMeta(IPersistentMap meta) { 420 | return new Card0(meta); 421 | } 422 | 423 | private int indexOf(int h, Object key) { 424 | if (key instanceof Keyword) { 425 | return -1; 426 | } 427 | return indexOfObj(h, key); 428 | } 429 | 430 | private int indexOfObj(int h, Object key) { 431 | Util.EquivPred ep = Util.equivPred(key); 432 | return -1; 433 | } 434 | 435 | public boolean containsKey(Object key) { 436 | return false; 437 | } 438 | 439 | public IMapEntry entryAt(Object key) { 440 | return null; 441 | } 442 | 443 | public Object valAt(Object key) { 444 | return valAt(key, null); 445 | } 446 | 447 | public Object valAt(Object key, Object notFound) { 448 | return notFound; 449 | } 450 | 451 | public ITransientMap asTransient() { 452 | return new Transient(); 453 | } 454 | 455 | public IPersistentMap assoc(Object key, Object val) { 456 | int h = Util.hasheq(key); 457 | return new Card1(meta, key, val, h); 458 | } 459 | 460 | public IPersistentMap assocEx(Object key, Object val) { 461 | int h = Util.hasheq(key); 462 | return new Card1(meta, key, val, h); 463 | } 464 | 465 | public IPersistentMap without(Object key) { 466 | return this; 467 | } 468 | 469 | public int hashCode() { 470 | if (_hash == -1) { 471 | int h = 0; 472 | _hash = h; 473 | } 474 | return _hash; 475 | } 476 | 477 | public int hasheq() { 478 | if (_hasheq == -1) { 479 | int h = 0; 480 | _hasheq = Murmur3.mixCollHash(h, 0); 481 | } 482 | return _hasheq; 483 | } 484 | 485 | public boolean equiv(Object o) { 486 | if (o instanceof IPersistentMap) { 487 | if (!(o instanceof MapEquivalence)) { 488 | return false; 489 | } 490 | IPersistentMap m = (IPersistentMap) o; 491 | if (m.count() != 0) { 492 | return false; 493 | } 494 | return true; 495 | } else if (o instanceof Map) { 496 | Map m = (Map) o; 497 | if (m.size() != 0) { 498 | return false; 499 | } 500 | return true; 501 | } else { 502 | return false; 503 | } 504 | } 505 | 506 | public boolean equals(Object o) { 507 | if (o instanceof IPersistentMap) { 508 | IPersistentMap m = (IPersistentMap) o; 509 | if (m.count() != 0) { 510 | return false; 511 | } 512 | return true; 513 | } else if (o instanceof Map) { 514 | Map m = (Map) o; 515 | if (m.size() != 0) { 516 | return false; 517 | } 518 | return true; 519 | } else { 520 | return false; 521 | } 522 | } 523 | 524 | public int count() { 525 | return 0; 526 | } 527 | 528 | public IPersistentMap empty() { 529 | return EMPTY; 530 | } 531 | 532 | public Object kvreduce(IFn f, Object init) { 533 | return init; 534 | } 535 | 536 | public Object reduce(IFn f) { 537 | return f.invoke(); 538 | } 539 | 540 | public Object reduce(IFn f, Object init) { 541 | return init; 542 | } 543 | 544 | public Iterator iterator() { 545 | return new Iterator() { 546 | int i = 0; 547 | 548 | public boolean hasNext() { 549 | return false; 550 | } 551 | 552 | public Object next() { 553 | throw new IndexOutOfBoundsException(); 554 | } 555 | 556 | public void remove() { 557 | throw new UnsupportedOperationException(); 558 | } 559 | }; 560 | } 561 | 562 | public Object[] toArray() { 563 | return new Object[] {}; 564 | } 565 | 566 | public ISeq seq() { 567 | return null; 568 | } 569 | } 570 | 571 | public static class Card1 extends APersistentMap implements IObj, 572 | IEditableCollection, IReduce { 573 | final Object k0; 574 | final Object v0; 575 | final int h0; 576 | private final IPersistentMap meta; 577 | 578 | Card1(IPersistentMap meta, Object k0, Object v0, int h0) { 579 | this.meta = meta; 580 | this.k0 = k0; 581 | this.v0 = v0; 582 | this.h0 = h0; 583 | } 584 | 585 | public Card1(Object k0, Object v0, int h0) { 586 | this.meta = null; 587 | this.k0 = k0; 588 | this.v0 = v0; 589 | this.h0 = h0; 590 | } 591 | 592 | public IPersistentMap meta() { 593 | return meta; 594 | } 595 | 596 | public IObj withMeta(IPersistentMap meta) { 597 | return new Card1(meta, k0, v0, h0); 598 | } 599 | 600 | private int indexOf(int h, Object key) { 601 | if (key instanceof Keyword) { 602 | if (k0 == key) { 603 | return 0; 604 | } 605 | return -1; 606 | } 607 | return indexOfObj(h, key); 608 | } 609 | 610 | private int indexOfObj(int h, Object key) { 611 | Util.EquivPred ep = Util.equivPred(key); 612 | if (h0 == h && ep.equiv(key, k0)) { 613 | return 0; 614 | } 615 | return -1; 616 | } 617 | 618 | public boolean containsKey(Object key) { 619 | return indexOf(Util.hasheq(key), key) >= 0; 620 | } 621 | 622 | public IMapEntry entryAt(Object key) { 623 | int idx = indexOf(Util.hasheq(key), key); 624 | switch (idx) { 625 | case 0: 626 | return new MapEntry(k0, v0); 627 | default: 628 | return null; 629 | } 630 | } 631 | 632 | public Object valAt(Object key) { 633 | return valAt(key, null); 634 | } 635 | 636 | public Object valAt(Object key, Object notFound) { 637 | int idx = indexOf(Util.hasheq(key), key); 638 | switch (idx) { 639 | case 0: 640 | return v0; 641 | default: 642 | return notFound; 643 | } 644 | } 645 | 646 | public ITransientMap asTransient() { 647 | return new Transient(k0, v0, h0); 648 | } 649 | 650 | public IPersistentMap assoc(Object key, Object val) { 651 | int h = Util.hasheq(key); 652 | int idx = indexOf(h, key); 653 | switch (idx) { 654 | case 0: 655 | return new Card1(meta, k0, val, h0); 656 | default: 657 | return new Card2(meta, k0, v0, h0, key, val, h); 658 | } 659 | } 660 | 661 | public IPersistentMap assocEx(Object key, Object val) { 662 | int h = Util.hasheq(key); 663 | int idx = indexOf(h, key); 664 | if (idx >= 0) { 665 | throw Util.runtimeException("Key already present"); 666 | } 667 | return new Card2(meta, k0, v0, h0, key, val, h); 668 | } 669 | 670 | public IPersistentMap without(Object key) { 671 | int idx = indexOf(Util.hasheq(key), key); 672 | switch (idx) { 673 | case 0: 674 | return new Card0(meta); 675 | default: 676 | return this; 677 | } 678 | } 679 | 680 | public int hashCode() { 681 | if (_hash == -1) { 682 | int h = 0; 683 | h += Util.hash(k0) ^ Util.hash(v0); 684 | _hash = h; 685 | } 686 | return _hash; 687 | } 688 | 689 | public int hasheq() { 690 | if (_hasheq == -1) { 691 | int h = 0; 692 | h += Murmur3.mixCollHash(31 * (31 + h0) + Util.hasheq(v0), 2); 693 | _hasheq = Murmur3.mixCollHash(h, 1); 694 | } 695 | return _hasheq; 696 | } 697 | 698 | public boolean equiv(Object o) { 699 | if (o instanceof IPersistentMap) { 700 | if (!(o instanceof MapEquivalence)) { 701 | return false; 702 | } 703 | IPersistentMap m = (IPersistentMap) o; 704 | if (m.count() != 1) { 705 | return false; 706 | } 707 | Object o0 = m.valAt(k0, PersistentUnrolledMap.NOT_FOUND); 708 | if (o0 == PersistentUnrolledMap.NOT_FOUND 709 | || !Util.equiv(o0, v0)) { 710 | return false; 711 | } 712 | return true; 713 | } else if (o instanceof Map) { 714 | Map m = (Map) o; 715 | if (m.size() != 1) { 716 | return false; 717 | } 718 | boolean f0 = m.containsKey(k0); 719 | if (!f0 || !Util.equiv(v0, m.get(k0))) { 720 | return false; 721 | } 722 | return true; 723 | } else { 724 | return false; 725 | } 726 | } 727 | 728 | public boolean equals(Object o) { 729 | if (o instanceof IPersistentMap) { 730 | IPersistentMap m = (IPersistentMap) o; 731 | if (m.count() != 1) { 732 | return false; 733 | } 734 | Object o0 = m.valAt(k0, PersistentUnrolledMap.NOT_FOUND); 735 | if (o0 == PersistentUnrolledMap.NOT_FOUND 736 | || !Util.equals(o0, v0)) { 737 | return false; 738 | } 739 | return true; 740 | } else if (o instanceof Map) { 741 | Map m = (Map) o; 742 | if (m.size() != 1) { 743 | return false; 744 | } 745 | boolean f0 = m.containsKey(k0); 746 | if (!f0 || !Util.equals(v0, m.get(k0))) { 747 | return false; 748 | } 749 | return true; 750 | } else { 751 | return false; 752 | } 753 | } 754 | 755 | public int count() { 756 | return 1; 757 | } 758 | 759 | public IPersistentMap empty() { 760 | return EMPTY; 761 | } 762 | 763 | public Object kvreduce(IFn f, Object init) { 764 | init = f.invoke(init, k0, v0); 765 | if (RT.isReduced(init)) { 766 | return ((IDeref) init).deref(); 767 | } 768 | return init; 769 | } 770 | 771 | public Object reduce(IFn f) { 772 | return new MapEntry(k0, v0); 773 | } 774 | 775 | public Object reduce(IFn f, Object init) { 776 | init = f.invoke(init, new MapEntry(k0, v0)); 777 | if (RT.isReduced(init)) { 778 | return ((IDeref) init).deref(); 779 | } 780 | return init; 781 | } 782 | 783 | public Iterator iterator() { 784 | return new Iterator() { 785 | int i = 0; 786 | 787 | public boolean hasNext() { 788 | return i < 1; 789 | } 790 | 791 | public Object next() { 792 | switch (i++) { 793 | case 0: 794 | return new MapEntry(k0, v0); 795 | default: 796 | throw new IndexOutOfBoundsException(); 797 | } 798 | } 799 | 800 | public void remove() { 801 | throw new UnsupportedOperationException(); 802 | } 803 | }; 804 | } 805 | 806 | public Object[] toArray() { 807 | return new Object[] { new MapEntry(k0, v0) }; 808 | } 809 | 810 | class UnrolledChunkedSeq extends ASeq implements IChunkedSeq, Counted { 811 | private final IPersistentMap meta; 812 | private final int offset; 813 | 814 | UnrolledChunkedSeq(IPersistentMap meta, int offset) { 815 | this.offset = offset; 816 | this.meta = meta; 817 | } 818 | 819 | public IChunk chunkedFirst() { 820 | return new ArrayChunk(toArray(), 0); 821 | } 822 | 823 | public ISeq chunkedNext() { 824 | return null; 825 | } 826 | 827 | public ISeq chunkedMore() { 828 | return PersistentList.EMPTY; 829 | } 830 | 831 | public UnrolledChunkedSeq withMeta(IPersistentMap meta) { 832 | return new UnrolledChunkedSeq(meta, offset); 833 | } 834 | 835 | public Object first() { 836 | switch (offset) { 837 | case 0: 838 | return new MapEntry(k0, v0); 839 | } 840 | throw new IndexOutOfBoundsException(); 841 | } 842 | 843 | public ISeq next() { 844 | if (offset < 0) { 845 | return new UnrolledChunkedSeq(null, offset + 1); 846 | } 847 | return null; 848 | } 849 | 850 | public int count() { 851 | return 1 - offset; 852 | } 853 | } 854 | 855 | public ISeq seq() { 856 | return new UnrolledChunkedSeq(null, 0); 857 | } 858 | } 859 | 860 | public static class Card2 extends APersistentMap implements IObj, 861 | IEditableCollection, IReduce { 862 | final Object k0; 863 | final Object k1; 864 | final Object v0; 865 | final Object v1; 866 | final int h0; 867 | final int h1; 868 | private final IPersistentMap meta; 869 | 870 | Card2(IPersistentMap meta, Object k0, Object v0, int h0, Object k1, 871 | Object v1, int h1) { 872 | this.meta = meta; 873 | this.k0 = k0; 874 | this.v0 = v0; 875 | this.h0 = h0; 876 | this.k1 = k1; 877 | this.v1 = v1; 878 | this.h1 = h1; 879 | } 880 | 881 | public Card2(Object k0, Object v0, int h0, Object k1, Object v1, int h1) { 882 | this.meta = null; 883 | this.k0 = k0; 884 | this.v0 = v0; 885 | this.h0 = h0; 886 | this.k1 = k1; 887 | this.v1 = v1; 888 | this.h1 = h1; 889 | } 890 | 891 | public IPersistentMap meta() { 892 | return meta; 893 | } 894 | 895 | public IObj withMeta(IPersistentMap meta) { 896 | return new Card2(meta, k0, v0, h0, k1, v1, h1); 897 | } 898 | 899 | private int indexOf(int h, Object key) { 900 | if (key instanceof Keyword) { 901 | if (k0 == key) { 902 | return 0; 903 | } else if (k1 == key) { 904 | return 1; 905 | } 906 | return -1; 907 | } 908 | return indexOfObj(h, key); 909 | } 910 | 911 | private int indexOfObj(int h, Object key) { 912 | Util.EquivPred ep = Util.equivPred(key); 913 | if (h0 == h && ep.equiv(key, k0)) { 914 | return 0; 915 | } else if (h1 == h && ep.equiv(key, k1)) { 916 | return 1; 917 | } 918 | return -1; 919 | } 920 | 921 | public boolean containsKey(Object key) { 922 | return indexOf(Util.hasheq(key), key) >= 0; 923 | } 924 | 925 | public IMapEntry entryAt(Object key) { 926 | int idx = indexOf(Util.hasheq(key), key); 927 | switch (idx) { 928 | case 0: 929 | return new MapEntry(k0, v0); 930 | case 1: 931 | return new MapEntry(k1, v1); 932 | default: 933 | return null; 934 | } 935 | } 936 | 937 | public Object valAt(Object key) { 938 | return valAt(key, null); 939 | } 940 | 941 | public Object valAt(Object key, Object notFound) { 942 | int idx = indexOf(Util.hasheq(key), key); 943 | switch (idx) { 944 | case 0: 945 | return v0; 946 | case 1: 947 | return v1; 948 | default: 949 | return notFound; 950 | } 951 | } 952 | 953 | public ITransientMap asTransient() { 954 | return new Transient(k0, v0, h0, k1, v1, h1); 955 | } 956 | 957 | public IPersistentMap assoc(Object key, Object val) { 958 | int h = Util.hasheq(key); 959 | int idx = indexOf(h, key); 960 | switch (idx) { 961 | case 0: 962 | return new Card2(meta, k0, val, h0, k1, v1, h1); 963 | case 1: 964 | return new Card2(meta, k0, v0, h0, k1, val, h1); 965 | default: 966 | return new Card3(meta, k0, v0, h0, k1, v1, h1, key, val, h); 967 | } 968 | } 969 | 970 | public IPersistentMap assocEx(Object key, Object val) { 971 | int h = Util.hasheq(key); 972 | int idx = indexOf(h, key); 973 | if (idx >= 0) { 974 | throw Util.runtimeException("Key already present"); 975 | } 976 | return new Card3(meta, k0, v0, h0, k1, v1, h1, key, val, h); 977 | } 978 | 979 | public IPersistentMap without(Object key) { 980 | int idx = indexOf(Util.hasheq(key), key); 981 | switch (idx) { 982 | case 0: 983 | return new Card1(meta, k1, v1, h1); 984 | case 1: 985 | return new Card1(meta, k0, v0, h0); 986 | default: 987 | return this; 988 | } 989 | } 990 | 991 | public int hashCode() { 992 | if (_hash == -1) { 993 | int h = 0; 994 | h += Util.hash(k0) ^ Util.hash(v0); 995 | h += Util.hash(k1) ^ Util.hash(v1); 996 | _hash = h; 997 | } 998 | return _hash; 999 | } 1000 | 1001 | public int hasheq() { 1002 | if (_hasheq == -1) { 1003 | int h = 0; 1004 | h += Murmur3.mixCollHash(31 * (31 + h0) + Util.hasheq(v0), 2); 1005 | h += Murmur3.mixCollHash(31 * (31 + h1) + Util.hasheq(v1), 2); 1006 | _hasheq = Murmur3.mixCollHash(h, 2); 1007 | } 1008 | return _hasheq; 1009 | } 1010 | 1011 | public boolean equiv(Object o) { 1012 | if (o instanceof IPersistentMap) { 1013 | if (!(o instanceof MapEquivalence)) { 1014 | return false; 1015 | } 1016 | IPersistentMap m = (IPersistentMap) o; 1017 | if (m.count() != 2) { 1018 | return false; 1019 | } 1020 | Object o0 = m.valAt(k0, PersistentUnrolledMap.NOT_FOUND); 1021 | if (o0 == PersistentUnrolledMap.NOT_FOUND 1022 | || !Util.equiv(o0, v0)) { 1023 | return false; 1024 | } 1025 | Object o1 = m.valAt(k1, PersistentUnrolledMap.NOT_FOUND); 1026 | if (o1 == PersistentUnrolledMap.NOT_FOUND 1027 | || !Util.equiv(o1, v1)) { 1028 | return false; 1029 | } 1030 | return true; 1031 | } else if (o instanceof Map) { 1032 | Map m = (Map) o; 1033 | if (m.size() != 2) { 1034 | return false; 1035 | } 1036 | boolean f0 = m.containsKey(k0); 1037 | if (!f0 || !Util.equiv(v0, m.get(k0))) { 1038 | return false; 1039 | } 1040 | boolean f1 = m.containsKey(k1); 1041 | if (!f1 || !Util.equiv(v1, m.get(k1))) { 1042 | return false; 1043 | } 1044 | return true; 1045 | } else { 1046 | return false; 1047 | } 1048 | } 1049 | 1050 | public boolean equals(Object o) { 1051 | if (o instanceof IPersistentMap) { 1052 | IPersistentMap m = (IPersistentMap) o; 1053 | if (m.count() != 2) { 1054 | return false; 1055 | } 1056 | Object o0 = m.valAt(k0, PersistentUnrolledMap.NOT_FOUND); 1057 | if (o0 == PersistentUnrolledMap.NOT_FOUND 1058 | || !Util.equals(o0, v0)) { 1059 | return false; 1060 | } 1061 | Object o1 = m.valAt(k1, PersistentUnrolledMap.NOT_FOUND); 1062 | if (o1 == PersistentUnrolledMap.NOT_FOUND 1063 | || !Util.equals(o1, v1)) { 1064 | return false; 1065 | } 1066 | return true; 1067 | } else if (o instanceof Map) { 1068 | Map m = (Map) o; 1069 | if (m.size() != 2) { 1070 | return false; 1071 | } 1072 | boolean f0 = m.containsKey(k0); 1073 | if (!f0 || !Util.equals(v0, m.get(k0))) { 1074 | return false; 1075 | } 1076 | boolean f1 = m.containsKey(k1); 1077 | if (!f1 || !Util.equals(v1, m.get(k1))) { 1078 | return false; 1079 | } 1080 | return true; 1081 | } else { 1082 | return false; 1083 | } 1084 | } 1085 | 1086 | public int count() { 1087 | return 2; 1088 | } 1089 | 1090 | public IPersistentMap empty() { 1091 | return EMPTY; 1092 | } 1093 | 1094 | public Object kvreduce(IFn f, Object init) { 1095 | init = f.invoke(init, k0, v0); 1096 | if (RT.isReduced(init)) { 1097 | return ((IDeref) init).deref(); 1098 | } 1099 | init = f.invoke(init, k1, v1); 1100 | if (RT.isReduced(init)) { 1101 | return ((IDeref) init).deref(); 1102 | } 1103 | return init; 1104 | } 1105 | 1106 | public Object reduce(IFn f) { 1107 | Object init = k0; 1108 | init = f.invoke(init, new MapEntry(k1, v1)); 1109 | if (RT.isReduced(init)) { 1110 | return ((IDeref) init).deref(); 1111 | } 1112 | return init; 1113 | } 1114 | 1115 | public Object reduce(IFn f, Object init) { 1116 | init = f.invoke(init, new MapEntry(k0, v0)); 1117 | if (RT.isReduced(init)) { 1118 | return ((IDeref) init).deref(); 1119 | } 1120 | init = f.invoke(init, new MapEntry(k1, v1)); 1121 | if (RT.isReduced(init)) { 1122 | return ((IDeref) init).deref(); 1123 | } 1124 | return init; 1125 | } 1126 | 1127 | public Iterator iterator() { 1128 | return new Iterator() { 1129 | int i = 0; 1130 | 1131 | public boolean hasNext() { 1132 | return i < 2; 1133 | } 1134 | 1135 | public Object next() { 1136 | switch (i++) { 1137 | case 0: 1138 | return new MapEntry(k0, v0); 1139 | case 1: 1140 | return new MapEntry(k1, v1); 1141 | default: 1142 | throw new IndexOutOfBoundsException(); 1143 | } 1144 | } 1145 | 1146 | public void remove() { 1147 | throw new UnsupportedOperationException(); 1148 | } 1149 | }; 1150 | } 1151 | 1152 | public Object[] toArray() { 1153 | return new Object[] { new MapEntry(k0, v0), new MapEntry(k1, v1) }; 1154 | } 1155 | 1156 | class UnrolledChunkedSeq extends ASeq implements IChunkedSeq, Counted { 1157 | private final IPersistentMap meta; 1158 | private final int offset; 1159 | 1160 | UnrolledChunkedSeq(IPersistentMap meta, int offset) { 1161 | this.offset = offset; 1162 | this.meta = meta; 1163 | } 1164 | 1165 | public IChunk chunkedFirst() { 1166 | return new ArrayChunk(toArray(), 0); 1167 | } 1168 | 1169 | public ISeq chunkedNext() { 1170 | return null; 1171 | } 1172 | 1173 | public ISeq chunkedMore() { 1174 | return PersistentList.EMPTY; 1175 | } 1176 | 1177 | public UnrolledChunkedSeq withMeta(IPersistentMap meta) { 1178 | return new UnrolledChunkedSeq(meta, offset); 1179 | } 1180 | 1181 | public Object first() { 1182 | switch (offset) { 1183 | case 0: 1184 | return new MapEntry(k0, v0); 1185 | case 1: 1186 | return new MapEntry(k1, v1); 1187 | } 1188 | throw new IndexOutOfBoundsException(); 1189 | } 1190 | 1191 | public ISeq next() { 1192 | if (offset < 1) { 1193 | return new UnrolledChunkedSeq(null, offset + 1); 1194 | } 1195 | return null; 1196 | } 1197 | 1198 | public int count() { 1199 | return 2 - offset; 1200 | } 1201 | } 1202 | 1203 | public ISeq seq() { 1204 | return new UnrolledChunkedSeq(null, 0); 1205 | } 1206 | } 1207 | 1208 | public static class Card3 extends APersistentMap implements IObj, 1209 | IEditableCollection, IReduce { 1210 | final Object k0; 1211 | final Object k1; 1212 | final Object k2; 1213 | final Object v0; 1214 | final Object v1; 1215 | final Object v2; 1216 | final int h0; 1217 | final int h1; 1218 | final int h2; 1219 | private final IPersistentMap meta; 1220 | 1221 | Card3(IPersistentMap meta, Object k0, Object v0, int h0, Object k1, 1222 | Object v1, int h1, Object k2, Object v2, int h2) { 1223 | this.meta = meta; 1224 | this.k0 = k0; 1225 | this.v0 = v0; 1226 | this.h0 = h0; 1227 | this.k1 = k1; 1228 | this.v1 = v1; 1229 | this.h1 = h1; 1230 | this.k2 = k2; 1231 | this.v2 = v2; 1232 | this.h2 = h2; 1233 | } 1234 | 1235 | public Card3(Object k0, Object v0, int h0, Object k1, Object v1, 1236 | int h1, Object k2, Object v2, int h2) { 1237 | this.meta = null; 1238 | this.k0 = k0; 1239 | this.v0 = v0; 1240 | this.h0 = h0; 1241 | this.k1 = k1; 1242 | this.v1 = v1; 1243 | this.h1 = h1; 1244 | this.k2 = k2; 1245 | this.v2 = v2; 1246 | this.h2 = h2; 1247 | } 1248 | 1249 | public IPersistentMap meta() { 1250 | return meta; 1251 | } 1252 | 1253 | public IObj withMeta(IPersistentMap meta) { 1254 | return new Card3(meta, k0, v0, h0, k1, v1, h1, k2, v2, h2); 1255 | } 1256 | 1257 | private int indexOf(int h, Object key) { 1258 | if (key instanceof Keyword) { 1259 | if (k0 == key) { 1260 | return 0; 1261 | } else if (k1 == key) { 1262 | return 1; 1263 | } else if (k2 == key) { 1264 | return 2; 1265 | } 1266 | return -1; 1267 | } 1268 | return indexOfObj(h, key); 1269 | } 1270 | 1271 | private int indexOfObj(int h, Object key) { 1272 | Util.EquivPred ep = Util.equivPred(key); 1273 | if (h0 == h && ep.equiv(key, k0)) { 1274 | return 0; 1275 | } else if (h1 == h && ep.equiv(key, k1)) { 1276 | return 1; 1277 | } else if (h2 == h && ep.equiv(key, k2)) { 1278 | return 2; 1279 | } 1280 | return -1; 1281 | } 1282 | 1283 | public boolean containsKey(Object key) { 1284 | return indexOf(Util.hasheq(key), key) >= 0; 1285 | } 1286 | 1287 | public IMapEntry entryAt(Object key) { 1288 | int idx = indexOf(Util.hasheq(key), key); 1289 | switch (idx) { 1290 | case 0: 1291 | return new MapEntry(k0, v0); 1292 | case 1: 1293 | return new MapEntry(k1, v1); 1294 | case 2: 1295 | return new MapEntry(k2, v2); 1296 | default: 1297 | return null; 1298 | } 1299 | } 1300 | 1301 | public Object valAt(Object key) { 1302 | return valAt(key, null); 1303 | } 1304 | 1305 | public Object valAt(Object key, Object notFound) { 1306 | int idx = indexOf(Util.hasheq(key), key); 1307 | switch (idx) { 1308 | case 0: 1309 | return v0; 1310 | case 1: 1311 | return v1; 1312 | case 2: 1313 | return v2; 1314 | default: 1315 | return notFound; 1316 | } 1317 | } 1318 | 1319 | public ITransientMap asTransient() { 1320 | return new Transient(k0, v0, h0, k1, v1, h1, k2, v2, h2); 1321 | } 1322 | 1323 | public IPersistentMap assoc(Object key, Object val) { 1324 | int h = Util.hasheq(key); 1325 | int idx = indexOf(h, key); 1326 | switch (idx) { 1327 | case 0: 1328 | return new Card3(meta, k0, val, h0, k1, v1, h1, k2, v2, h2); 1329 | case 1: 1330 | return new Card3(meta, k0, v0, h0, k1, val, h1, k2, v2, h2); 1331 | case 2: 1332 | return new Card3(meta, k0, v0, h0, k1, v1, h1, k2, val, h2); 1333 | default: 1334 | return new Card4(meta, k0, v0, h0, k1, v1, h1, k2, v2, h2, key, 1335 | val, h); 1336 | } 1337 | } 1338 | 1339 | public IPersistentMap assocEx(Object key, Object val) { 1340 | int h = Util.hasheq(key); 1341 | int idx = indexOf(h, key); 1342 | if (idx >= 0) { 1343 | throw Util.runtimeException("Key already present"); 1344 | } 1345 | return new Card4(meta, k0, v0, h0, k1, v1, h1, k2, v2, h2, key, 1346 | val, h); 1347 | } 1348 | 1349 | public IPersistentMap without(Object key) { 1350 | int idx = indexOf(Util.hasheq(key), key); 1351 | switch (idx) { 1352 | case 0: 1353 | return new Card2(meta, k1, v1, h1, k2, v2, h2); 1354 | case 1: 1355 | return new Card2(meta, k0, v0, h0, k2, v2, h2); 1356 | case 2: 1357 | return new Card2(meta, k0, v0, h0, k1, v1, h1); 1358 | default: 1359 | return this; 1360 | } 1361 | } 1362 | 1363 | public int hashCode() { 1364 | if (_hash == -1) { 1365 | int h = 0; 1366 | h += Util.hash(k0) ^ Util.hash(v0); 1367 | h += Util.hash(k1) ^ Util.hash(v1); 1368 | h += Util.hash(k2) ^ Util.hash(v2); 1369 | _hash = h; 1370 | } 1371 | return _hash; 1372 | } 1373 | 1374 | public int hasheq() { 1375 | if (_hasheq == -1) { 1376 | int h = 0; 1377 | h += Murmur3.mixCollHash(31 * (31 + h0) + Util.hasheq(v0), 2); 1378 | h += Murmur3.mixCollHash(31 * (31 + h1) + Util.hasheq(v1), 2); 1379 | h += Murmur3.mixCollHash(31 * (31 + h2) + Util.hasheq(v2), 2); 1380 | _hasheq = Murmur3.mixCollHash(h, 3); 1381 | } 1382 | return _hasheq; 1383 | } 1384 | 1385 | public boolean equiv(Object o) { 1386 | if (o instanceof IPersistentMap) { 1387 | if (!(o instanceof MapEquivalence)) { 1388 | return false; 1389 | } 1390 | IPersistentMap m = (IPersistentMap) o; 1391 | if (m.count() != 3) { 1392 | return false; 1393 | } 1394 | Object o0 = m.valAt(k0, PersistentUnrolledMap.NOT_FOUND); 1395 | if (o0 == PersistentUnrolledMap.NOT_FOUND 1396 | || !Util.equiv(o0, v0)) { 1397 | return false; 1398 | } 1399 | Object o1 = m.valAt(k1, PersistentUnrolledMap.NOT_FOUND); 1400 | if (o1 == PersistentUnrolledMap.NOT_FOUND 1401 | || !Util.equiv(o1, v1)) { 1402 | return false; 1403 | } 1404 | Object o2 = m.valAt(k2, PersistentUnrolledMap.NOT_FOUND); 1405 | if (o2 == PersistentUnrolledMap.NOT_FOUND 1406 | || !Util.equiv(o2, v2)) { 1407 | return false; 1408 | } 1409 | return true; 1410 | } else if (o instanceof Map) { 1411 | Map m = (Map) o; 1412 | if (m.size() != 3) { 1413 | return false; 1414 | } 1415 | boolean f0 = m.containsKey(k0); 1416 | if (!f0 || !Util.equiv(v0, m.get(k0))) { 1417 | return false; 1418 | } 1419 | boolean f1 = m.containsKey(k1); 1420 | if (!f1 || !Util.equiv(v1, m.get(k1))) { 1421 | return false; 1422 | } 1423 | boolean f2 = m.containsKey(k2); 1424 | if (!f2 || !Util.equiv(v2, m.get(k2))) { 1425 | return false; 1426 | } 1427 | return true; 1428 | } else { 1429 | return false; 1430 | } 1431 | } 1432 | 1433 | public boolean equals(Object o) { 1434 | if (o instanceof IPersistentMap) { 1435 | IPersistentMap m = (IPersistentMap) o; 1436 | if (m.count() != 3) { 1437 | return false; 1438 | } 1439 | Object o0 = m.valAt(k0, PersistentUnrolledMap.NOT_FOUND); 1440 | if (o0 == PersistentUnrolledMap.NOT_FOUND 1441 | || !Util.equals(o0, v0)) { 1442 | return false; 1443 | } 1444 | Object o1 = m.valAt(k1, PersistentUnrolledMap.NOT_FOUND); 1445 | if (o1 == PersistentUnrolledMap.NOT_FOUND 1446 | || !Util.equals(o1, v1)) { 1447 | return false; 1448 | } 1449 | Object o2 = m.valAt(k2, PersistentUnrolledMap.NOT_FOUND); 1450 | if (o2 == PersistentUnrolledMap.NOT_FOUND 1451 | || !Util.equals(o2, v2)) { 1452 | return false; 1453 | } 1454 | return true; 1455 | } else if (o instanceof Map) { 1456 | Map m = (Map) o; 1457 | if (m.size() != 3) { 1458 | return false; 1459 | } 1460 | boolean f0 = m.containsKey(k0); 1461 | if (!f0 || !Util.equals(v0, m.get(k0))) { 1462 | return false; 1463 | } 1464 | boolean f1 = m.containsKey(k1); 1465 | if (!f1 || !Util.equals(v1, m.get(k1))) { 1466 | return false; 1467 | } 1468 | boolean f2 = m.containsKey(k2); 1469 | if (!f2 || !Util.equals(v2, m.get(k2))) { 1470 | return false; 1471 | } 1472 | return true; 1473 | } else { 1474 | return false; 1475 | } 1476 | } 1477 | 1478 | public int count() { 1479 | return 3; 1480 | } 1481 | 1482 | public IPersistentMap empty() { 1483 | return EMPTY; 1484 | } 1485 | 1486 | public Object kvreduce(IFn f, Object init) { 1487 | init = f.invoke(init, k0, v0); 1488 | if (RT.isReduced(init)) { 1489 | return ((IDeref) init).deref(); 1490 | } 1491 | init = f.invoke(init, k1, v1); 1492 | if (RT.isReduced(init)) { 1493 | return ((IDeref) init).deref(); 1494 | } 1495 | init = f.invoke(init, k2, v2); 1496 | if (RT.isReduced(init)) { 1497 | return ((IDeref) init).deref(); 1498 | } 1499 | return init; 1500 | } 1501 | 1502 | public Object reduce(IFn f) { 1503 | Object init = k0; 1504 | init = f.invoke(init, new MapEntry(k1, v1)); 1505 | if (RT.isReduced(init)) { 1506 | return ((IDeref) init).deref(); 1507 | } 1508 | init = f.invoke(init, new MapEntry(k2, v2)); 1509 | if (RT.isReduced(init)) { 1510 | return ((IDeref) init).deref(); 1511 | } 1512 | return init; 1513 | } 1514 | 1515 | public Object reduce(IFn f, Object init) { 1516 | init = f.invoke(init, new MapEntry(k0, v0)); 1517 | if (RT.isReduced(init)) { 1518 | return ((IDeref) init).deref(); 1519 | } 1520 | init = f.invoke(init, new MapEntry(k1, v1)); 1521 | if (RT.isReduced(init)) { 1522 | return ((IDeref) init).deref(); 1523 | } 1524 | init = f.invoke(init, new MapEntry(k2, v2)); 1525 | if (RT.isReduced(init)) { 1526 | return ((IDeref) init).deref(); 1527 | } 1528 | return init; 1529 | } 1530 | 1531 | public Iterator iterator() { 1532 | return new Iterator() { 1533 | int i = 0; 1534 | 1535 | public boolean hasNext() { 1536 | return i < 3; 1537 | } 1538 | 1539 | public Object next() { 1540 | switch (i++) { 1541 | case 0: 1542 | return new MapEntry(k0, v0); 1543 | case 1: 1544 | return new MapEntry(k1, v1); 1545 | case 2: 1546 | return new MapEntry(k2, v2); 1547 | default: 1548 | throw new IndexOutOfBoundsException(); 1549 | } 1550 | } 1551 | 1552 | public void remove() { 1553 | throw new UnsupportedOperationException(); 1554 | } 1555 | }; 1556 | } 1557 | 1558 | public Object[] toArray() { 1559 | return new Object[] { new MapEntry(k0, v0), new MapEntry(k1, v1), 1560 | new MapEntry(k2, v2) }; 1561 | } 1562 | 1563 | class UnrolledChunkedSeq extends ASeq implements IChunkedSeq, Counted { 1564 | private final IPersistentMap meta; 1565 | private final int offset; 1566 | 1567 | UnrolledChunkedSeq(IPersistentMap meta, int offset) { 1568 | this.offset = offset; 1569 | this.meta = meta; 1570 | } 1571 | 1572 | public IChunk chunkedFirst() { 1573 | return new ArrayChunk(toArray(), 0); 1574 | } 1575 | 1576 | public ISeq chunkedNext() { 1577 | return null; 1578 | } 1579 | 1580 | public ISeq chunkedMore() { 1581 | return PersistentList.EMPTY; 1582 | } 1583 | 1584 | public UnrolledChunkedSeq withMeta(IPersistentMap meta) { 1585 | return new UnrolledChunkedSeq(meta, offset); 1586 | } 1587 | 1588 | public Object first() { 1589 | switch (offset) { 1590 | case 0: 1591 | return new MapEntry(k0, v0); 1592 | case 1: 1593 | return new MapEntry(k1, v1); 1594 | case 2: 1595 | return new MapEntry(k2, v2); 1596 | } 1597 | throw new IndexOutOfBoundsException(); 1598 | } 1599 | 1600 | public ISeq next() { 1601 | if (offset < 2) { 1602 | return new UnrolledChunkedSeq(null, offset + 1); 1603 | } 1604 | return null; 1605 | } 1606 | 1607 | public int count() { 1608 | return 3 - offset; 1609 | } 1610 | } 1611 | 1612 | public ISeq seq() { 1613 | return new UnrolledChunkedSeq(null, 0); 1614 | } 1615 | } 1616 | 1617 | public static class Card4 extends APersistentMap implements IObj, 1618 | IEditableCollection, IReduce { 1619 | final Object k0; 1620 | final Object k1; 1621 | final Object k2; 1622 | final Object k3; 1623 | final Object v0; 1624 | final Object v1; 1625 | final Object v2; 1626 | final Object v3; 1627 | final int h0; 1628 | final int h1; 1629 | final int h2; 1630 | final int h3; 1631 | private final IPersistentMap meta; 1632 | 1633 | Card4(IPersistentMap meta, Object k0, Object v0, int h0, Object k1, 1634 | Object v1, int h1, Object k2, Object v2, int h2, Object k3, 1635 | Object v3, int h3) { 1636 | this.meta = meta; 1637 | this.k0 = k0; 1638 | this.v0 = v0; 1639 | this.h0 = h0; 1640 | this.k1 = k1; 1641 | this.v1 = v1; 1642 | this.h1 = h1; 1643 | this.k2 = k2; 1644 | this.v2 = v2; 1645 | this.h2 = h2; 1646 | this.k3 = k3; 1647 | this.v3 = v3; 1648 | this.h3 = h3; 1649 | } 1650 | 1651 | public Card4(Object k0, Object v0, int h0, Object k1, Object v1, 1652 | int h1, Object k2, Object v2, int h2, Object k3, Object v3, 1653 | int h3) { 1654 | this.meta = null; 1655 | this.k0 = k0; 1656 | this.v0 = v0; 1657 | this.h0 = h0; 1658 | this.k1 = k1; 1659 | this.v1 = v1; 1660 | this.h1 = h1; 1661 | this.k2 = k2; 1662 | this.v2 = v2; 1663 | this.h2 = h2; 1664 | this.k3 = k3; 1665 | this.v3 = v3; 1666 | this.h3 = h3; 1667 | } 1668 | 1669 | public IPersistentMap meta() { 1670 | return meta; 1671 | } 1672 | 1673 | public IObj withMeta(IPersistentMap meta) { 1674 | return new Card4(meta, k0, v0, h0, k1, v1, h1, k2, v2, h2, k3, v3, 1675 | h3); 1676 | } 1677 | 1678 | private int indexOf(int h, Object key) { 1679 | if (key instanceof Keyword) { 1680 | if (k0 == key) { 1681 | return 0; 1682 | } else if (k1 == key) { 1683 | return 1; 1684 | } else if (k2 == key) { 1685 | return 2; 1686 | } else if (k3 == key) { 1687 | return 3; 1688 | } 1689 | return -1; 1690 | } 1691 | return indexOfObj(h, key); 1692 | } 1693 | 1694 | private int indexOfObj(int h, Object key) { 1695 | Util.EquivPred ep = Util.equivPred(key); 1696 | if (h0 == h && ep.equiv(key, k0)) { 1697 | return 0; 1698 | } else if (h1 == h && ep.equiv(key, k1)) { 1699 | return 1; 1700 | } else if (h2 == h && ep.equiv(key, k2)) { 1701 | return 2; 1702 | } else if (h3 == h && ep.equiv(key, k3)) { 1703 | return 3; 1704 | } 1705 | return -1; 1706 | } 1707 | 1708 | public boolean containsKey(Object key) { 1709 | return indexOf(Util.hasheq(key), key) >= 0; 1710 | } 1711 | 1712 | public IMapEntry entryAt(Object key) { 1713 | int idx = indexOf(Util.hasheq(key), key); 1714 | switch (idx) { 1715 | case 0: 1716 | return new MapEntry(k0, v0); 1717 | case 1: 1718 | return new MapEntry(k1, v1); 1719 | case 2: 1720 | return new MapEntry(k2, v2); 1721 | case 3: 1722 | return new MapEntry(k3, v3); 1723 | default: 1724 | return null; 1725 | } 1726 | } 1727 | 1728 | public Object valAt(Object key) { 1729 | return valAt(key, null); 1730 | } 1731 | 1732 | public Object valAt(Object key, Object notFound) { 1733 | int idx = indexOf(Util.hasheq(key), key); 1734 | switch (idx) { 1735 | case 0: 1736 | return v0; 1737 | case 1: 1738 | return v1; 1739 | case 2: 1740 | return v2; 1741 | case 3: 1742 | return v3; 1743 | default: 1744 | return notFound; 1745 | } 1746 | } 1747 | 1748 | public ITransientMap asTransient() { 1749 | return new Transient(k0, v0, h0, k1, v1, h1, k2, v2, h2, k3, v3, h3); 1750 | } 1751 | 1752 | public IPersistentMap assoc(Object key, Object val) { 1753 | int h = Util.hasheq(key); 1754 | int idx = indexOf(h, key); 1755 | switch (idx) { 1756 | case 0: 1757 | return new Card4(meta, k0, val, h0, k1, v1, h1, k2, v2, h2, k3, 1758 | v3, h3); 1759 | case 1: 1760 | return new Card4(meta, k0, v0, h0, k1, val, h1, k2, v2, h2, k3, 1761 | v3, h3); 1762 | case 2: 1763 | return new Card4(meta, k0, v0, h0, k1, v1, h1, k2, val, h2, k3, 1764 | v3, h3); 1765 | case 3: 1766 | return new Card4(meta, k0, v0, h0, k1, v1, h1, k2, v2, h2, k3, 1767 | val, h3); 1768 | default: 1769 | return new Card5(meta, k0, v0, h0, k1, v1, h1, k2, v2, h2, k3, 1770 | v3, h3, key, val, h); 1771 | } 1772 | } 1773 | 1774 | public IPersistentMap assocEx(Object key, Object val) { 1775 | int h = Util.hasheq(key); 1776 | int idx = indexOf(h, key); 1777 | if (idx >= 0) { 1778 | throw Util.runtimeException("Key already present"); 1779 | } 1780 | return new Card5(meta, k0, v0, h0, k1, v1, h1, k2, v2, h2, k3, v3, 1781 | h3, key, val, h); 1782 | } 1783 | 1784 | public IPersistentMap without(Object key) { 1785 | int idx = indexOf(Util.hasheq(key), key); 1786 | switch (idx) { 1787 | case 0: 1788 | return new Card3(meta, k1, v1, h1, k2, v2, h2, k3, v3, h3); 1789 | case 1: 1790 | return new Card3(meta, k0, v0, h0, k2, v2, h2, k3, v3, h3); 1791 | case 2: 1792 | return new Card3(meta, k0, v0, h0, k1, v1, h1, k3, v3, h3); 1793 | case 3: 1794 | return new Card3(meta, k0, v0, h0, k1, v1, h1, k2, v2, h2); 1795 | default: 1796 | return this; 1797 | } 1798 | } 1799 | 1800 | public int hashCode() { 1801 | if (_hash == -1) { 1802 | int h = 0; 1803 | h += Util.hash(k0) ^ Util.hash(v0); 1804 | h += Util.hash(k1) ^ Util.hash(v1); 1805 | h += Util.hash(k2) ^ Util.hash(v2); 1806 | h += Util.hash(k3) ^ Util.hash(v3); 1807 | _hash = h; 1808 | } 1809 | return _hash; 1810 | } 1811 | 1812 | public int hasheq() { 1813 | if (_hasheq == -1) { 1814 | int h = 0; 1815 | h += Murmur3.mixCollHash(31 * (31 + h0) + Util.hasheq(v0), 2); 1816 | h += Murmur3.mixCollHash(31 * (31 + h1) + Util.hasheq(v1), 2); 1817 | h += Murmur3.mixCollHash(31 * (31 + h2) + Util.hasheq(v2), 2); 1818 | h += Murmur3.mixCollHash(31 * (31 + h3) + Util.hasheq(v3), 2); 1819 | _hasheq = Murmur3.mixCollHash(h, 4); 1820 | } 1821 | return _hasheq; 1822 | } 1823 | 1824 | public boolean equiv(Object o) { 1825 | if (o instanceof IPersistentMap) { 1826 | if (!(o instanceof MapEquivalence)) { 1827 | return false; 1828 | } 1829 | IPersistentMap m = (IPersistentMap) o; 1830 | if (m.count() != 4) { 1831 | return false; 1832 | } 1833 | Object o0 = m.valAt(k0, PersistentUnrolledMap.NOT_FOUND); 1834 | if (o0 == PersistentUnrolledMap.NOT_FOUND 1835 | || !Util.equiv(o0, v0)) { 1836 | return false; 1837 | } 1838 | Object o1 = m.valAt(k1, PersistentUnrolledMap.NOT_FOUND); 1839 | if (o1 == PersistentUnrolledMap.NOT_FOUND 1840 | || !Util.equiv(o1, v1)) { 1841 | return false; 1842 | } 1843 | Object o2 = m.valAt(k2, PersistentUnrolledMap.NOT_FOUND); 1844 | if (o2 == PersistentUnrolledMap.NOT_FOUND 1845 | || !Util.equiv(o2, v2)) { 1846 | return false; 1847 | } 1848 | Object o3 = m.valAt(k3, PersistentUnrolledMap.NOT_FOUND); 1849 | if (o3 == PersistentUnrolledMap.NOT_FOUND 1850 | || !Util.equiv(o3, v3)) { 1851 | return false; 1852 | } 1853 | return true; 1854 | } else if (o instanceof Map) { 1855 | Map m = (Map) o; 1856 | if (m.size() != 4) { 1857 | return false; 1858 | } 1859 | boolean f0 = m.containsKey(k0); 1860 | if (!f0 || !Util.equiv(v0, m.get(k0))) { 1861 | return false; 1862 | } 1863 | boolean f1 = m.containsKey(k1); 1864 | if (!f1 || !Util.equiv(v1, m.get(k1))) { 1865 | return false; 1866 | } 1867 | boolean f2 = m.containsKey(k2); 1868 | if (!f2 || !Util.equiv(v2, m.get(k2))) { 1869 | return false; 1870 | } 1871 | boolean f3 = m.containsKey(k3); 1872 | if (!f3 || !Util.equiv(v3, m.get(k3))) { 1873 | return false; 1874 | } 1875 | return true; 1876 | } else { 1877 | return false; 1878 | } 1879 | } 1880 | 1881 | public boolean equals(Object o) { 1882 | if (o instanceof IPersistentMap) { 1883 | IPersistentMap m = (IPersistentMap) o; 1884 | if (m.count() != 4) { 1885 | return false; 1886 | } 1887 | Object o0 = m.valAt(k0, PersistentUnrolledMap.NOT_FOUND); 1888 | if (o0 == PersistentUnrolledMap.NOT_FOUND 1889 | || !Util.equals(o0, v0)) { 1890 | return false; 1891 | } 1892 | Object o1 = m.valAt(k1, PersistentUnrolledMap.NOT_FOUND); 1893 | if (o1 == PersistentUnrolledMap.NOT_FOUND 1894 | || !Util.equals(o1, v1)) { 1895 | return false; 1896 | } 1897 | Object o2 = m.valAt(k2, PersistentUnrolledMap.NOT_FOUND); 1898 | if (o2 == PersistentUnrolledMap.NOT_FOUND 1899 | || !Util.equals(o2, v2)) { 1900 | return false; 1901 | } 1902 | Object o3 = m.valAt(k3, PersistentUnrolledMap.NOT_FOUND); 1903 | if (o3 == PersistentUnrolledMap.NOT_FOUND 1904 | || !Util.equals(o3, v3)) { 1905 | return false; 1906 | } 1907 | return true; 1908 | } else if (o instanceof Map) { 1909 | Map m = (Map) o; 1910 | if (m.size() != 4) { 1911 | return false; 1912 | } 1913 | boolean f0 = m.containsKey(k0); 1914 | if (!f0 || !Util.equals(v0, m.get(k0))) { 1915 | return false; 1916 | } 1917 | boolean f1 = m.containsKey(k1); 1918 | if (!f1 || !Util.equals(v1, m.get(k1))) { 1919 | return false; 1920 | } 1921 | boolean f2 = m.containsKey(k2); 1922 | if (!f2 || !Util.equals(v2, m.get(k2))) { 1923 | return false; 1924 | } 1925 | boolean f3 = m.containsKey(k3); 1926 | if (!f3 || !Util.equals(v3, m.get(k3))) { 1927 | return false; 1928 | } 1929 | return true; 1930 | } else { 1931 | return false; 1932 | } 1933 | } 1934 | 1935 | public int count() { 1936 | return 4; 1937 | } 1938 | 1939 | public IPersistentMap empty() { 1940 | return EMPTY; 1941 | } 1942 | 1943 | public Object kvreduce(IFn f, Object init) { 1944 | init = f.invoke(init, k0, v0); 1945 | if (RT.isReduced(init)) { 1946 | return ((IDeref) init).deref(); 1947 | } 1948 | init = f.invoke(init, k1, v1); 1949 | if (RT.isReduced(init)) { 1950 | return ((IDeref) init).deref(); 1951 | } 1952 | init = f.invoke(init, k2, v2); 1953 | if (RT.isReduced(init)) { 1954 | return ((IDeref) init).deref(); 1955 | } 1956 | init = f.invoke(init, k3, v3); 1957 | if (RT.isReduced(init)) { 1958 | return ((IDeref) init).deref(); 1959 | } 1960 | return init; 1961 | } 1962 | 1963 | public Object reduce(IFn f) { 1964 | Object init = k0; 1965 | init = f.invoke(init, new MapEntry(k1, v1)); 1966 | if (RT.isReduced(init)) { 1967 | return ((IDeref) init).deref(); 1968 | } 1969 | init = f.invoke(init, new MapEntry(k2, v2)); 1970 | if (RT.isReduced(init)) { 1971 | return ((IDeref) init).deref(); 1972 | } 1973 | init = f.invoke(init, new MapEntry(k3, v3)); 1974 | if (RT.isReduced(init)) { 1975 | return ((IDeref) init).deref(); 1976 | } 1977 | return init; 1978 | } 1979 | 1980 | public Object reduce(IFn f, Object init) { 1981 | init = f.invoke(init, new MapEntry(k0, v0)); 1982 | if (RT.isReduced(init)) { 1983 | return ((IDeref) init).deref(); 1984 | } 1985 | init = f.invoke(init, new MapEntry(k1, v1)); 1986 | if (RT.isReduced(init)) { 1987 | return ((IDeref) init).deref(); 1988 | } 1989 | init = f.invoke(init, new MapEntry(k2, v2)); 1990 | if (RT.isReduced(init)) { 1991 | return ((IDeref) init).deref(); 1992 | } 1993 | init = f.invoke(init, new MapEntry(k3, v3)); 1994 | if (RT.isReduced(init)) { 1995 | return ((IDeref) init).deref(); 1996 | } 1997 | return init; 1998 | } 1999 | 2000 | public Iterator iterator() { 2001 | return new Iterator() { 2002 | int i = 0; 2003 | 2004 | public boolean hasNext() { 2005 | return i < 4; 2006 | } 2007 | 2008 | public Object next() { 2009 | switch (i++) { 2010 | case 0: 2011 | return new MapEntry(k0, v0); 2012 | case 1: 2013 | return new MapEntry(k1, v1); 2014 | case 2: 2015 | return new MapEntry(k2, v2); 2016 | case 3: 2017 | return new MapEntry(k3, v3); 2018 | default: 2019 | throw new IndexOutOfBoundsException(); 2020 | } 2021 | } 2022 | 2023 | public void remove() { 2024 | throw new UnsupportedOperationException(); 2025 | } 2026 | }; 2027 | } 2028 | 2029 | public Object[] toArray() { 2030 | return new Object[] { new MapEntry(k0, v0), new MapEntry(k1, v1), 2031 | new MapEntry(k2, v2), new MapEntry(k3, v3) }; 2032 | } 2033 | 2034 | class UnrolledChunkedSeq extends ASeq implements IChunkedSeq, Counted { 2035 | private final IPersistentMap meta; 2036 | private final int offset; 2037 | 2038 | UnrolledChunkedSeq(IPersistentMap meta, int offset) { 2039 | this.offset = offset; 2040 | this.meta = meta; 2041 | } 2042 | 2043 | public IChunk chunkedFirst() { 2044 | return new ArrayChunk(toArray(), 0); 2045 | } 2046 | 2047 | public ISeq chunkedNext() { 2048 | return null; 2049 | } 2050 | 2051 | public ISeq chunkedMore() { 2052 | return PersistentList.EMPTY; 2053 | } 2054 | 2055 | public UnrolledChunkedSeq withMeta(IPersistentMap meta) { 2056 | return new UnrolledChunkedSeq(meta, offset); 2057 | } 2058 | 2059 | public Object first() { 2060 | switch (offset) { 2061 | case 0: 2062 | return new MapEntry(k0, v0); 2063 | case 1: 2064 | return new MapEntry(k1, v1); 2065 | case 2: 2066 | return new MapEntry(k2, v2); 2067 | case 3: 2068 | return new MapEntry(k3, v3); 2069 | } 2070 | throw new IndexOutOfBoundsException(); 2071 | } 2072 | 2073 | public ISeq next() { 2074 | if (offset < 3) { 2075 | return new UnrolledChunkedSeq(null, offset + 1); 2076 | } 2077 | return null; 2078 | } 2079 | 2080 | public int count() { 2081 | return 4 - offset; 2082 | } 2083 | } 2084 | 2085 | public ISeq seq() { 2086 | return new UnrolledChunkedSeq(null, 0); 2087 | } 2088 | } 2089 | 2090 | public static class Card5 extends APersistentMap implements IObj, 2091 | IEditableCollection, IReduce { 2092 | final Object k0; 2093 | final Object k1; 2094 | final Object k2; 2095 | final Object k3; 2096 | final Object k4; 2097 | final Object v0; 2098 | final Object v1; 2099 | final Object v2; 2100 | final Object v3; 2101 | final Object v4; 2102 | final int h0; 2103 | final int h1; 2104 | final int h2; 2105 | final int h3; 2106 | final int h4; 2107 | private final IPersistentMap meta; 2108 | 2109 | Card5(IPersistentMap meta, Object k0, Object v0, int h0, Object k1, 2110 | Object v1, int h1, Object k2, Object v2, int h2, Object k3, 2111 | Object v3, int h3, Object k4, Object v4, int h4) { 2112 | this.meta = meta; 2113 | this.k0 = k0; 2114 | this.v0 = v0; 2115 | this.h0 = h0; 2116 | this.k1 = k1; 2117 | this.v1 = v1; 2118 | this.h1 = h1; 2119 | this.k2 = k2; 2120 | this.v2 = v2; 2121 | this.h2 = h2; 2122 | this.k3 = k3; 2123 | this.v3 = v3; 2124 | this.h3 = h3; 2125 | this.k4 = k4; 2126 | this.v4 = v4; 2127 | this.h4 = h4; 2128 | } 2129 | 2130 | public Card5(Object k0, Object v0, int h0, Object k1, Object v1, 2131 | int h1, Object k2, Object v2, int h2, Object k3, Object v3, 2132 | int h3, Object k4, Object v4, int h4) { 2133 | this.meta = null; 2134 | this.k0 = k0; 2135 | this.v0 = v0; 2136 | this.h0 = h0; 2137 | this.k1 = k1; 2138 | this.v1 = v1; 2139 | this.h1 = h1; 2140 | this.k2 = k2; 2141 | this.v2 = v2; 2142 | this.h2 = h2; 2143 | this.k3 = k3; 2144 | this.v3 = v3; 2145 | this.h3 = h3; 2146 | this.k4 = k4; 2147 | this.v4 = v4; 2148 | this.h4 = h4; 2149 | } 2150 | 2151 | public IPersistentMap meta() { 2152 | return meta; 2153 | } 2154 | 2155 | public IObj withMeta(IPersistentMap meta) { 2156 | return new Card5(meta, k0, v0, h0, k1, v1, h1, k2, v2, h2, k3, v3, 2157 | h3, k4, v4, h4); 2158 | } 2159 | 2160 | private int indexOf(int h, Object key) { 2161 | if (key instanceof Keyword) { 2162 | if (k0 == key) { 2163 | return 0; 2164 | } else if (k1 == key) { 2165 | return 1; 2166 | } else if (k2 == key) { 2167 | return 2; 2168 | } else if (k3 == key) { 2169 | return 3; 2170 | } else if (k4 == key) { 2171 | return 4; 2172 | } 2173 | return -1; 2174 | } 2175 | return indexOfObj(h, key); 2176 | } 2177 | 2178 | private int indexOfObj(int h, Object key) { 2179 | Util.EquivPred ep = Util.equivPred(key); 2180 | if (h0 == h && ep.equiv(key, k0)) { 2181 | return 0; 2182 | } else if (h1 == h && ep.equiv(key, k1)) { 2183 | return 1; 2184 | } else if (h2 == h && ep.equiv(key, k2)) { 2185 | return 2; 2186 | } else if (h3 == h && ep.equiv(key, k3)) { 2187 | return 3; 2188 | } else if (h4 == h && ep.equiv(key, k4)) { 2189 | return 4; 2190 | } 2191 | return -1; 2192 | } 2193 | 2194 | public boolean containsKey(Object key) { 2195 | return indexOf(Util.hasheq(key), key) >= 0; 2196 | } 2197 | 2198 | public IMapEntry entryAt(Object key) { 2199 | int idx = indexOf(Util.hasheq(key), key); 2200 | switch (idx) { 2201 | case 0: 2202 | return new MapEntry(k0, v0); 2203 | case 1: 2204 | return new MapEntry(k1, v1); 2205 | case 2: 2206 | return new MapEntry(k2, v2); 2207 | case 3: 2208 | return new MapEntry(k3, v3); 2209 | case 4: 2210 | return new MapEntry(k4, v4); 2211 | default: 2212 | return null; 2213 | } 2214 | } 2215 | 2216 | public Object valAt(Object key) { 2217 | return valAt(key, null); 2218 | } 2219 | 2220 | public Object valAt(Object key, Object notFound) { 2221 | int idx = indexOf(Util.hasheq(key), key); 2222 | switch (idx) { 2223 | case 0: 2224 | return v0; 2225 | case 1: 2226 | return v1; 2227 | case 2: 2228 | return v2; 2229 | case 3: 2230 | return v3; 2231 | case 4: 2232 | return v4; 2233 | default: 2234 | return notFound; 2235 | } 2236 | } 2237 | 2238 | public ITransientMap asTransient() { 2239 | return new Transient(k0, v0, h0, k1, v1, h1, k2, v2, h2, k3, v3, 2240 | h3, k4, v4, h4); 2241 | } 2242 | 2243 | public IPersistentMap assoc(Object key, Object val) { 2244 | int h = Util.hasheq(key); 2245 | int idx = indexOf(h, key); 2246 | switch (idx) { 2247 | case 0: 2248 | return new Card5(meta, k0, val, h0, k1, v1, h1, k2, v2, h2, k3, 2249 | v3, h3, k4, v4, h4); 2250 | case 1: 2251 | return new Card5(meta, k0, v0, h0, k1, val, h1, k2, v2, h2, k3, 2252 | v3, h3, k4, v4, h4); 2253 | case 2: 2254 | return new Card5(meta, k0, v0, h0, k1, v1, h1, k2, val, h2, k3, 2255 | v3, h3, k4, v4, h4); 2256 | case 3: 2257 | return new Card5(meta, k0, v0, h0, k1, v1, h1, k2, v2, h2, k3, 2258 | val, h3, k4, v4, h4); 2259 | case 4: 2260 | return new Card5(meta, k0, v0, h0, k1, v1, h1, k2, v2, h2, k3, 2261 | v3, h3, k4, val, h4); 2262 | default: 2263 | return new Card6(meta, k0, v0, h0, k1, v1, h1, k2, v2, h2, k3, 2264 | v3, h3, k4, v4, h4, key, val, h); 2265 | } 2266 | } 2267 | 2268 | public IPersistentMap assocEx(Object key, Object val) { 2269 | int h = Util.hasheq(key); 2270 | int idx = indexOf(h, key); 2271 | if (idx >= 0) { 2272 | throw Util.runtimeException("Key already present"); 2273 | } 2274 | return new Card6(meta, k0, v0, h0, k1, v1, h1, k2, v2, h2, k3, v3, 2275 | h3, k4, v4, h4, key, val, h); 2276 | } 2277 | 2278 | public IPersistentMap without(Object key) { 2279 | int idx = indexOf(Util.hasheq(key), key); 2280 | switch (idx) { 2281 | case 0: 2282 | return new Card4(meta, k1, v1, h1, k2, v2, h2, k3, v3, h3, k4, 2283 | v4, h4); 2284 | case 1: 2285 | return new Card4(meta, k0, v0, h0, k2, v2, h2, k3, v3, h3, k4, 2286 | v4, h4); 2287 | case 2: 2288 | return new Card4(meta, k0, v0, h0, k1, v1, h1, k3, v3, h3, k4, 2289 | v4, h4); 2290 | case 3: 2291 | return new Card4(meta, k0, v0, h0, k1, v1, h1, k2, v2, h2, k4, 2292 | v4, h4); 2293 | case 4: 2294 | return new Card4(meta, k0, v0, h0, k1, v1, h1, k2, v2, h2, k3, 2295 | v3, h3); 2296 | default: 2297 | return this; 2298 | } 2299 | } 2300 | 2301 | public int hashCode() { 2302 | if (_hash == -1) { 2303 | int h = 0; 2304 | h += Util.hash(k0) ^ Util.hash(v0); 2305 | h += Util.hash(k1) ^ Util.hash(v1); 2306 | h += Util.hash(k2) ^ Util.hash(v2); 2307 | h += Util.hash(k3) ^ Util.hash(v3); 2308 | h += Util.hash(k4) ^ Util.hash(v4); 2309 | _hash = h; 2310 | } 2311 | return _hash; 2312 | } 2313 | 2314 | public int hasheq() { 2315 | if (_hasheq == -1) { 2316 | int h = 0; 2317 | h += Murmur3.mixCollHash(31 * (31 + h0) + Util.hasheq(v0), 2); 2318 | h += Murmur3.mixCollHash(31 * (31 + h1) + Util.hasheq(v1), 2); 2319 | h += Murmur3.mixCollHash(31 * (31 + h2) + Util.hasheq(v2), 2); 2320 | h += Murmur3.mixCollHash(31 * (31 + h3) + Util.hasheq(v3), 2); 2321 | h += Murmur3.mixCollHash(31 * (31 + h4) + Util.hasheq(v4), 2); 2322 | _hasheq = Murmur3.mixCollHash(h, 5); 2323 | } 2324 | return _hasheq; 2325 | } 2326 | 2327 | public boolean equiv(Object o) { 2328 | if (o instanceof IPersistentMap) { 2329 | if (!(o instanceof MapEquivalence)) { 2330 | return false; 2331 | } 2332 | IPersistentMap m = (IPersistentMap) o; 2333 | if (m.count() != 5) { 2334 | return false; 2335 | } 2336 | Object o0 = m.valAt(k0, PersistentUnrolledMap.NOT_FOUND); 2337 | if (o0 == PersistentUnrolledMap.NOT_FOUND 2338 | || !Util.equiv(o0, v0)) { 2339 | return false; 2340 | } 2341 | Object o1 = m.valAt(k1, PersistentUnrolledMap.NOT_FOUND); 2342 | if (o1 == PersistentUnrolledMap.NOT_FOUND 2343 | || !Util.equiv(o1, v1)) { 2344 | return false; 2345 | } 2346 | Object o2 = m.valAt(k2, PersistentUnrolledMap.NOT_FOUND); 2347 | if (o2 == PersistentUnrolledMap.NOT_FOUND 2348 | || !Util.equiv(o2, v2)) { 2349 | return false; 2350 | } 2351 | Object o3 = m.valAt(k3, PersistentUnrolledMap.NOT_FOUND); 2352 | if (o3 == PersistentUnrolledMap.NOT_FOUND 2353 | || !Util.equiv(o3, v3)) { 2354 | return false; 2355 | } 2356 | Object o4 = m.valAt(k4, PersistentUnrolledMap.NOT_FOUND); 2357 | if (o4 == PersistentUnrolledMap.NOT_FOUND 2358 | || !Util.equiv(o4, v4)) { 2359 | return false; 2360 | } 2361 | return true; 2362 | } else if (o instanceof Map) { 2363 | Map m = (Map) o; 2364 | if (m.size() != 5) { 2365 | return false; 2366 | } 2367 | boolean f0 = m.containsKey(k0); 2368 | if (!f0 || !Util.equiv(v0, m.get(k0))) { 2369 | return false; 2370 | } 2371 | boolean f1 = m.containsKey(k1); 2372 | if (!f1 || !Util.equiv(v1, m.get(k1))) { 2373 | return false; 2374 | } 2375 | boolean f2 = m.containsKey(k2); 2376 | if (!f2 || !Util.equiv(v2, m.get(k2))) { 2377 | return false; 2378 | } 2379 | boolean f3 = m.containsKey(k3); 2380 | if (!f3 || !Util.equiv(v3, m.get(k3))) { 2381 | return false; 2382 | } 2383 | boolean f4 = m.containsKey(k4); 2384 | if (!f4 || !Util.equiv(v4, m.get(k4))) { 2385 | return false; 2386 | } 2387 | return true; 2388 | } else { 2389 | return false; 2390 | } 2391 | } 2392 | 2393 | public boolean equals(Object o) { 2394 | if (o instanceof IPersistentMap) { 2395 | IPersistentMap m = (IPersistentMap) o; 2396 | if (m.count() != 5) { 2397 | return false; 2398 | } 2399 | Object o0 = m.valAt(k0, PersistentUnrolledMap.NOT_FOUND); 2400 | if (o0 == PersistentUnrolledMap.NOT_FOUND 2401 | || !Util.equals(o0, v0)) { 2402 | return false; 2403 | } 2404 | Object o1 = m.valAt(k1, PersistentUnrolledMap.NOT_FOUND); 2405 | if (o1 == PersistentUnrolledMap.NOT_FOUND 2406 | || !Util.equals(o1, v1)) { 2407 | return false; 2408 | } 2409 | Object o2 = m.valAt(k2, PersistentUnrolledMap.NOT_FOUND); 2410 | if (o2 == PersistentUnrolledMap.NOT_FOUND 2411 | || !Util.equals(o2, v2)) { 2412 | return false; 2413 | } 2414 | Object o3 = m.valAt(k3, PersistentUnrolledMap.NOT_FOUND); 2415 | if (o3 == PersistentUnrolledMap.NOT_FOUND 2416 | || !Util.equals(o3, v3)) { 2417 | return false; 2418 | } 2419 | Object o4 = m.valAt(k4, PersistentUnrolledMap.NOT_FOUND); 2420 | if (o4 == PersistentUnrolledMap.NOT_FOUND 2421 | || !Util.equals(o4, v4)) { 2422 | return false; 2423 | } 2424 | return true; 2425 | } else if (o instanceof Map) { 2426 | Map m = (Map) o; 2427 | if (m.size() != 5) { 2428 | return false; 2429 | } 2430 | boolean f0 = m.containsKey(k0); 2431 | if (!f0 || !Util.equals(v0, m.get(k0))) { 2432 | return false; 2433 | } 2434 | boolean f1 = m.containsKey(k1); 2435 | if (!f1 || !Util.equals(v1, m.get(k1))) { 2436 | return false; 2437 | } 2438 | boolean f2 = m.containsKey(k2); 2439 | if (!f2 || !Util.equals(v2, m.get(k2))) { 2440 | return false; 2441 | } 2442 | boolean f3 = m.containsKey(k3); 2443 | if (!f3 || !Util.equals(v3, m.get(k3))) { 2444 | return false; 2445 | } 2446 | boolean f4 = m.containsKey(k4); 2447 | if (!f4 || !Util.equals(v4, m.get(k4))) { 2448 | return false; 2449 | } 2450 | return true; 2451 | } else { 2452 | return false; 2453 | } 2454 | } 2455 | 2456 | public int count() { 2457 | return 5; 2458 | } 2459 | 2460 | public IPersistentMap empty() { 2461 | return EMPTY; 2462 | } 2463 | 2464 | public Object kvreduce(IFn f, Object init) { 2465 | init = f.invoke(init, k0, v0); 2466 | if (RT.isReduced(init)) { 2467 | return ((IDeref) init).deref(); 2468 | } 2469 | init = f.invoke(init, k1, v1); 2470 | if (RT.isReduced(init)) { 2471 | return ((IDeref) init).deref(); 2472 | } 2473 | init = f.invoke(init, k2, v2); 2474 | if (RT.isReduced(init)) { 2475 | return ((IDeref) init).deref(); 2476 | } 2477 | init = f.invoke(init, k3, v3); 2478 | if (RT.isReduced(init)) { 2479 | return ((IDeref) init).deref(); 2480 | } 2481 | init = f.invoke(init, k4, v4); 2482 | if (RT.isReduced(init)) { 2483 | return ((IDeref) init).deref(); 2484 | } 2485 | return init; 2486 | } 2487 | 2488 | public Object reduce(IFn f) { 2489 | Object init = k0; 2490 | init = f.invoke(init, new MapEntry(k1, v1)); 2491 | if (RT.isReduced(init)) { 2492 | return ((IDeref) init).deref(); 2493 | } 2494 | init = f.invoke(init, new MapEntry(k2, v2)); 2495 | if (RT.isReduced(init)) { 2496 | return ((IDeref) init).deref(); 2497 | } 2498 | init = f.invoke(init, new MapEntry(k3, v3)); 2499 | if (RT.isReduced(init)) { 2500 | return ((IDeref) init).deref(); 2501 | } 2502 | init = f.invoke(init, new MapEntry(k4, v4)); 2503 | if (RT.isReduced(init)) { 2504 | return ((IDeref) init).deref(); 2505 | } 2506 | return init; 2507 | } 2508 | 2509 | public Object reduce(IFn f, Object init) { 2510 | init = f.invoke(init, new MapEntry(k0, v0)); 2511 | if (RT.isReduced(init)) { 2512 | return ((IDeref) init).deref(); 2513 | } 2514 | init = f.invoke(init, new MapEntry(k1, v1)); 2515 | if (RT.isReduced(init)) { 2516 | return ((IDeref) init).deref(); 2517 | } 2518 | init = f.invoke(init, new MapEntry(k2, v2)); 2519 | if (RT.isReduced(init)) { 2520 | return ((IDeref) init).deref(); 2521 | } 2522 | init = f.invoke(init, new MapEntry(k3, v3)); 2523 | if (RT.isReduced(init)) { 2524 | return ((IDeref) init).deref(); 2525 | } 2526 | init = f.invoke(init, new MapEntry(k4, v4)); 2527 | if (RT.isReduced(init)) { 2528 | return ((IDeref) init).deref(); 2529 | } 2530 | return init; 2531 | } 2532 | 2533 | public Iterator iterator() { 2534 | return new Iterator() { 2535 | int i = 0; 2536 | 2537 | public boolean hasNext() { 2538 | return i < 5; 2539 | } 2540 | 2541 | public Object next() { 2542 | switch (i++) { 2543 | case 0: 2544 | return new MapEntry(k0, v0); 2545 | case 1: 2546 | return new MapEntry(k1, v1); 2547 | case 2: 2548 | return new MapEntry(k2, v2); 2549 | case 3: 2550 | return new MapEntry(k3, v3); 2551 | case 4: 2552 | return new MapEntry(k4, v4); 2553 | default: 2554 | throw new IndexOutOfBoundsException(); 2555 | } 2556 | } 2557 | 2558 | public void remove() { 2559 | throw new UnsupportedOperationException(); 2560 | } 2561 | }; 2562 | } 2563 | 2564 | public Object[] toArray() { 2565 | return new Object[] { new MapEntry(k0, v0), new MapEntry(k1, v1), 2566 | new MapEntry(k2, v2), new MapEntry(k3, v3), 2567 | new MapEntry(k4, v4) }; 2568 | } 2569 | 2570 | class UnrolledChunkedSeq extends ASeq implements IChunkedSeq, Counted { 2571 | private final IPersistentMap meta; 2572 | private final int offset; 2573 | 2574 | UnrolledChunkedSeq(IPersistentMap meta, int offset) { 2575 | this.offset = offset; 2576 | this.meta = meta; 2577 | } 2578 | 2579 | public IChunk chunkedFirst() { 2580 | return new ArrayChunk(toArray(), 0); 2581 | } 2582 | 2583 | public ISeq chunkedNext() { 2584 | return null; 2585 | } 2586 | 2587 | public ISeq chunkedMore() { 2588 | return PersistentList.EMPTY; 2589 | } 2590 | 2591 | public UnrolledChunkedSeq withMeta(IPersistentMap meta) { 2592 | return new UnrolledChunkedSeq(meta, offset); 2593 | } 2594 | 2595 | public Object first() { 2596 | switch (offset) { 2597 | case 0: 2598 | return new MapEntry(k0, v0); 2599 | case 1: 2600 | return new MapEntry(k1, v1); 2601 | case 2: 2602 | return new MapEntry(k2, v2); 2603 | case 3: 2604 | return new MapEntry(k3, v3); 2605 | case 4: 2606 | return new MapEntry(k4, v4); 2607 | } 2608 | throw new IndexOutOfBoundsException(); 2609 | } 2610 | 2611 | public ISeq next() { 2612 | if (offset < 4) { 2613 | return new UnrolledChunkedSeq(null, offset + 1); 2614 | } 2615 | return null; 2616 | } 2617 | 2618 | public int count() { 2619 | return 5 - offset; 2620 | } 2621 | } 2622 | 2623 | public ISeq seq() { 2624 | return new UnrolledChunkedSeq(null, 0); 2625 | } 2626 | } 2627 | 2628 | public static class Card6 extends APersistentMap implements IObj, 2629 | IEditableCollection, IReduce { 2630 | final Object k0; 2631 | final Object k1; 2632 | final Object k2; 2633 | final Object k3; 2634 | final Object k4; 2635 | final Object k5; 2636 | final Object v0; 2637 | final Object v1; 2638 | final Object v2; 2639 | final Object v3; 2640 | final Object v4; 2641 | final Object v5; 2642 | final int h0; 2643 | final int h1; 2644 | final int h2; 2645 | final int h3; 2646 | final int h4; 2647 | final int h5; 2648 | private final IPersistentMap meta; 2649 | 2650 | Card6(IPersistentMap meta, Object k0, Object v0, int h0, Object k1, 2651 | Object v1, int h1, Object k2, Object v2, int h2, Object k3, 2652 | Object v3, int h3, Object k4, Object v4, int h4, Object k5, 2653 | Object v5, int h5) { 2654 | this.meta = meta; 2655 | this.k0 = k0; 2656 | this.v0 = v0; 2657 | this.h0 = h0; 2658 | this.k1 = k1; 2659 | this.v1 = v1; 2660 | this.h1 = h1; 2661 | this.k2 = k2; 2662 | this.v2 = v2; 2663 | this.h2 = h2; 2664 | this.k3 = k3; 2665 | this.v3 = v3; 2666 | this.h3 = h3; 2667 | this.k4 = k4; 2668 | this.v4 = v4; 2669 | this.h4 = h4; 2670 | this.k5 = k5; 2671 | this.v5 = v5; 2672 | this.h5 = h5; 2673 | } 2674 | 2675 | public Card6(Object k0, Object v0, int h0, Object k1, Object v1, 2676 | int h1, Object k2, Object v2, int h2, Object k3, Object v3, 2677 | int h3, Object k4, Object v4, int h4, Object k5, Object v5, 2678 | int h5) { 2679 | this.meta = null; 2680 | this.k0 = k0; 2681 | this.v0 = v0; 2682 | this.h0 = h0; 2683 | this.k1 = k1; 2684 | this.v1 = v1; 2685 | this.h1 = h1; 2686 | this.k2 = k2; 2687 | this.v2 = v2; 2688 | this.h2 = h2; 2689 | this.k3 = k3; 2690 | this.v3 = v3; 2691 | this.h3 = h3; 2692 | this.k4 = k4; 2693 | this.v4 = v4; 2694 | this.h4 = h4; 2695 | this.k5 = k5; 2696 | this.v5 = v5; 2697 | this.h5 = h5; 2698 | } 2699 | 2700 | public IPersistentMap meta() { 2701 | return meta; 2702 | } 2703 | 2704 | public IObj withMeta(IPersistentMap meta) { 2705 | return new Card6(meta, k0, v0, h0, k1, v1, h1, k2, v2, h2, k3, v3, 2706 | h3, k4, v4, h4, k5, v5, h5); 2707 | } 2708 | 2709 | private int indexOf(int h, Object key) { 2710 | if (key instanceof Keyword) { 2711 | if (k0 == key) { 2712 | return 0; 2713 | } else if (k1 == key) { 2714 | return 1; 2715 | } else if (k2 == key) { 2716 | return 2; 2717 | } else if (k3 == key) { 2718 | return 3; 2719 | } else if (k4 == key) { 2720 | return 4; 2721 | } else if (k5 == key) { 2722 | return 5; 2723 | } 2724 | return -1; 2725 | } 2726 | return indexOfObj(h, key); 2727 | } 2728 | 2729 | private int indexOfObj(int h, Object key) { 2730 | Util.EquivPred ep = Util.equivPred(key); 2731 | if (h0 == h && ep.equiv(key, k0)) { 2732 | return 0; 2733 | } else if (h1 == h && ep.equiv(key, k1)) { 2734 | return 1; 2735 | } else if (h2 == h && ep.equiv(key, k2)) { 2736 | return 2; 2737 | } else if (h3 == h && ep.equiv(key, k3)) { 2738 | return 3; 2739 | } else if (h4 == h && ep.equiv(key, k4)) { 2740 | return 4; 2741 | } else if (h5 == h && ep.equiv(key, k5)) { 2742 | return 5; 2743 | } 2744 | return -1; 2745 | } 2746 | 2747 | public boolean containsKey(Object key) { 2748 | return indexOf(Util.hasheq(key), key) >= 0; 2749 | } 2750 | 2751 | public IMapEntry entryAt(Object key) { 2752 | int idx = indexOf(Util.hasheq(key), key); 2753 | switch (idx) { 2754 | case 0: 2755 | return new MapEntry(k0, v0); 2756 | case 1: 2757 | return new MapEntry(k1, v1); 2758 | case 2: 2759 | return new MapEntry(k2, v2); 2760 | case 3: 2761 | return new MapEntry(k3, v3); 2762 | case 4: 2763 | return new MapEntry(k4, v4); 2764 | case 5: 2765 | return new MapEntry(k5, v5); 2766 | default: 2767 | return null; 2768 | } 2769 | } 2770 | 2771 | public Object valAt(Object key) { 2772 | return valAt(key, null); 2773 | } 2774 | 2775 | public Object valAt(Object key, Object notFound) { 2776 | int idx = indexOf(Util.hasheq(key), key); 2777 | switch (idx) { 2778 | case 0: 2779 | return v0; 2780 | case 1: 2781 | return v1; 2782 | case 2: 2783 | return v2; 2784 | case 3: 2785 | return v3; 2786 | case 4: 2787 | return v4; 2788 | case 5: 2789 | return v5; 2790 | default: 2791 | return notFound; 2792 | } 2793 | } 2794 | 2795 | public ITransientMap asTransient() { 2796 | return new Transient(k0, v0, h0, k1, v1, h1, k2, v2, h2, k3, v3, 2797 | h3, k4, v4, h4, k5, v5, h5); 2798 | } 2799 | 2800 | public IPersistentMap assoc(Object key, Object val) { 2801 | int h = Util.hasheq(key); 2802 | int idx = indexOf(h, key); 2803 | switch (idx) { 2804 | case 0: 2805 | return new Card6(meta, k0, val, h0, k1, v1, h1, k2, v2, h2, k3, 2806 | v3, h3, k4, v4, h4, k5, v5, h5); 2807 | case 1: 2808 | return new Card6(meta, k0, v0, h0, k1, val, h1, k2, v2, h2, k3, 2809 | v3, h3, k4, v4, h4, k5, v5, h5); 2810 | case 2: 2811 | return new Card6(meta, k0, v0, h0, k1, v1, h1, k2, val, h2, k3, 2812 | v3, h3, k4, v4, h4, k5, v5, h5); 2813 | case 3: 2814 | return new Card6(meta, k0, v0, h0, k1, v1, h1, k2, v2, h2, k3, 2815 | val, h3, k4, v4, h4, k5, v5, h5); 2816 | case 4: 2817 | return new Card6(meta, k0, v0, h0, k1, v1, h1, k2, v2, h2, k3, 2818 | v3, h3, k4, val, h4, k5, v5, h5); 2819 | case 5: 2820 | return new Card6(meta, k0, v0, h0, k1, v1, h1, k2, v2, h2, k3, 2821 | v3, h3, k4, v4, h4, k5, val, h5); 2822 | default: 2823 | IPersistentMap map = PersistentHashMap.EMPTY.asTransient() 2824 | .assoc(k0, v0).assoc(k1, v1).assoc(k2, v2) 2825 | .assoc(k3, v3).assoc(k4, v4).assoc(k5, v5) 2826 | .assoc(key, val).persistent(); 2827 | return (IPersistentMap) ((IObj) map).withMeta(meta); 2828 | } 2829 | } 2830 | 2831 | public IPersistentMap assocEx(Object key, Object val) { 2832 | int h = Util.hasheq(key); 2833 | int idx = indexOf(h, key); 2834 | if (idx >= 0) { 2835 | throw Util.runtimeException("Key already present"); 2836 | } 2837 | IPersistentMap map = PersistentHashMap.EMPTY.asTransient() 2838 | .assoc(k0, v0).assoc(k1, v1).assoc(k2, v2).assoc(k3, v3) 2839 | .assoc(k4, v4).assoc(k5, v5).assoc(key, val).persistent(); 2840 | return (IPersistentMap) ((IObj) map).withMeta(meta); 2841 | } 2842 | 2843 | public IPersistentMap without(Object key) { 2844 | int idx = indexOf(Util.hasheq(key), key); 2845 | switch (idx) { 2846 | case 0: 2847 | return new Card5(meta, k1, v1, h1, k2, v2, h2, k3, v3, h3, k4, 2848 | v4, h4, k5, v5, h5); 2849 | case 1: 2850 | return new Card5(meta, k0, v0, h0, k2, v2, h2, k3, v3, h3, k4, 2851 | v4, h4, k5, v5, h5); 2852 | case 2: 2853 | return new Card5(meta, k0, v0, h0, k1, v1, h1, k3, v3, h3, k4, 2854 | v4, h4, k5, v5, h5); 2855 | case 3: 2856 | return new Card5(meta, k0, v0, h0, k1, v1, h1, k2, v2, h2, k4, 2857 | v4, h4, k5, v5, h5); 2858 | case 4: 2859 | return new Card5(meta, k0, v0, h0, k1, v1, h1, k2, v2, h2, k3, 2860 | v3, h3, k5, v5, h5); 2861 | case 5: 2862 | return new Card5(meta, k0, v0, h0, k1, v1, h1, k2, v2, h2, k3, 2863 | v3, h3, k4, v4, h4); 2864 | default: 2865 | return this; 2866 | } 2867 | } 2868 | 2869 | public int hashCode() { 2870 | if (_hash == -1) { 2871 | int h = 0; 2872 | h += Util.hash(k0) ^ Util.hash(v0); 2873 | h += Util.hash(k1) ^ Util.hash(v1); 2874 | h += Util.hash(k2) ^ Util.hash(v2); 2875 | h += Util.hash(k3) ^ Util.hash(v3); 2876 | h += Util.hash(k4) ^ Util.hash(v4); 2877 | h += Util.hash(k5) ^ Util.hash(v5); 2878 | _hash = h; 2879 | } 2880 | return _hash; 2881 | } 2882 | 2883 | public int hasheq() { 2884 | if (_hasheq == -1) { 2885 | int h = 0; 2886 | h += Murmur3.mixCollHash(31 * (31 + h0) + Util.hasheq(v0), 2); 2887 | h += Murmur3.mixCollHash(31 * (31 + h1) + Util.hasheq(v1), 2); 2888 | h += Murmur3.mixCollHash(31 * (31 + h2) + Util.hasheq(v2), 2); 2889 | h += Murmur3.mixCollHash(31 * (31 + h3) + Util.hasheq(v3), 2); 2890 | h += Murmur3.mixCollHash(31 * (31 + h4) + Util.hasheq(v4), 2); 2891 | h += Murmur3.mixCollHash(31 * (31 + h5) + Util.hasheq(v5), 2); 2892 | _hasheq = Murmur3.mixCollHash(h, 6); 2893 | } 2894 | return _hasheq; 2895 | } 2896 | 2897 | public boolean equiv(Object o) { 2898 | if (o instanceof IPersistentMap) { 2899 | if (!(o instanceof MapEquivalence)) { 2900 | return false; 2901 | } 2902 | IPersistentMap m = (IPersistentMap) o; 2903 | if (m.count() != 6) { 2904 | return false; 2905 | } 2906 | Object o0 = m.valAt(k0, PersistentUnrolledMap.NOT_FOUND); 2907 | if (o0 == PersistentUnrolledMap.NOT_FOUND 2908 | || !Util.equiv(o0, v0)) { 2909 | return false; 2910 | } 2911 | Object o1 = m.valAt(k1, PersistentUnrolledMap.NOT_FOUND); 2912 | if (o1 == PersistentUnrolledMap.NOT_FOUND 2913 | || !Util.equiv(o1, v1)) { 2914 | return false; 2915 | } 2916 | Object o2 = m.valAt(k2, PersistentUnrolledMap.NOT_FOUND); 2917 | if (o2 == PersistentUnrolledMap.NOT_FOUND 2918 | || !Util.equiv(o2, v2)) { 2919 | return false; 2920 | } 2921 | Object o3 = m.valAt(k3, PersistentUnrolledMap.NOT_FOUND); 2922 | if (o3 == PersistentUnrolledMap.NOT_FOUND 2923 | || !Util.equiv(o3, v3)) { 2924 | return false; 2925 | } 2926 | Object o4 = m.valAt(k4, PersistentUnrolledMap.NOT_FOUND); 2927 | if (o4 == PersistentUnrolledMap.NOT_FOUND 2928 | || !Util.equiv(o4, v4)) { 2929 | return false; 2930 | } 2931 | Object o5 = m.valAt(k5, PersistentUnrolledMap.NOT_FOUND); 2932 | if (o5 == PersistentUnrolledMap.NOT_FOUND 2933 | || !Util.equiv(o5, v5)) { 2934 | return false; 2935 | } 2936 | return true; 2937 | } else if (o instanceof Map) { 2938 | Map m = (Map) o; 2939 | if (m.size() != 6) { 2940 | return false; 2941 | } 2942 | boolean f0 = m.containsKey(k0); 2943 | if (!f0 || !Util.equiv(v0, m.get(k0))) { 2944 | return false; 2945 | } 2946 | boolean f1 = m.containsKey(k1); 2947 | if (!f1 || !Util.equiv(v1, m.get(k1))) { 2948 | return false; 2949 | } 2950 | boolean f2 = m.containsKey(k2); 2951 | if (!f2 || !Util.equiv(v2, m.get(k2))) { 2952 | return false; 2953 | } 2954 | boolean f3 = m.containsKey(k3); 2955 | if (!f3 || !Util.equiv(v3, m.get(k3))) { 2956 | return false; 2957 | } 2958 | boolean f4 = m.containsKey(k4); 2959 | if (!f4 || !Util.equiv(v4, m.get(k4))) { 2960 | return false; 2961 | } 2962 | boolean f5 = m.containsKey(k5); 2963 | if (!f5 || !Util.equiv(v5, m.get(k5))) { 2964 | return false; 2965 | } 2966 | return true; 2967 | } else { 2968 | return false; 2969 | } 2970 | } 2971 | 2972 | public boolean equals(Object o) { 2973 | if (o instanceof IPersistentMap) { 2974 | IPersistentMap m = (IPersistentMap) o; 2975 | if (m.count() != 6) { 2976 | return false; 2977 | } 2978 | Object o0 = m.valAt(k0, PersistentUnrolledMap.NOT_FOUND); 2979 | if (o0 == PersistentUnrolledMap.NOT_FOUND 2980 | || !Util.equals(o0, v0)) { 2981 | return false; 2982 | } 2983 | Object o1 = m.valAt(k1, PersistentUnrolledMap.NOT_FOUND); 2984 | if (o1 == PersistentUnrolledMap.NOT_FOUND 2985 | || !Util.equals(o1, v1)) { 2986 | return false; 2987 | } 2988 | Object o2 = m.valAt(k2, PersistentUnrolledMap.NOT_FOUND); 2989 | if (o2 == PersistentUnrolledMap.NOT_FOUND 2990 | || !Util.equals(o2, v2)) { 2991 | return false; 2992 | } 2993 | Object o3 = m.valAt(k3, PersistentUnrolledMap.NOT_FOUND); 2994 | if (o3 == PersistentUnrolledMap.NOT_FOUND 2995 | || !Util.equals(o3, v3)) { 2996 | return false; 2997 | } 2998 | Object o4 = m.valAt(k4, PersistentUnrolledMap.NOT_FOUND); 2999 | if (o4 == PersistentUnrolledMap.NOT_FOUND 3000 | || !Util.equals(o4, v4)) { 3001 | return false; 3002 | } 3003 | Object o5 = m.valAt(k5, PersistentUnrolledMap.NOT_FOUND); 3004 | if (o5 == PersistentUnrolledMap.NOT_FOUND 3005 | || !Util.equals(o5, v5)) { 3006 | return false; 3007 | } 3008 | return true; 3009 | } else if (o instanceof Map) { 3010 | Map m = (Map) o; 3011 | if (m.size() != 6) { 3012 | return false; 3013 | } 3014 | boolean f0 = m.containsKey(k0); 3015 | if (!f0 || !Util.equals(v0, m.get(k0))) { 3016 | return false; 3017 | } 3018 | boolean f1 = m.containsKey(k1); 3019 | if (!f1 || !Util.equals(v1, m.get(k1))) { 3020 | return false; 3021 | } 3022 | boolean f2 = m.containsKey(k2); 3023 | if (!f2 || !Util.equals(v2, m.get(k2))) { 3024 | return false; 3025 | } 3026 | boolean f3 = m.containsKey(k3); 3027 | if (!f3 || !Util.equals(v3, m.get(k3))) { 3028 | return false; 3029 | } 3030 | boolean f4 = m.containsKey(k4); 3031 | if (!f4 || !Util.equals(v4, m.get(k4))) { 3032 | return false; 3033 | } 3034 | boolean f5 = m.containsKey(k5); 3035 | if (!f5 || !Util.equals(v5, m.get(k5))) { 3036 | return false; 3037 | } 3038 | return true; 3039 | } else { 3040 | return false; 3041 | } 3042 | } 3043 | 3044 | public int count() { 3045 | return 6; 3046 | } 3047 | 3048 | public IPersistentMap empty() { 3049 | return EMPTY; 3050 | } 3051 | 3052 | public Object kvreduce(IFn f, Object init) { 3053 | init = f.invoke(init, k0, v0); 3054 | if (RT.isReduced(init)) { 3055 | return ((IDeref) init).deref(); 3056 | } 3057 | init = f.invoke(init, k1, v1); 3058 | if (RT.isReduced(init)) { 3059 | return ((IDeref) init).deref(); 3060 | } 3061 | init = f.invoke(init, k2, v2); 3062 | if (RT.isReduced(init)) { 3063 | return ((IDeref) init).deref(); 3064 | } 3065 | init = f.invoke(init, k3, v3); 3066 | if (RT.isReduced(init)) { 3067 | return ((IDeref) init).deref(); 3068 | } 3069 | init = f.invoke(init, k4, v4); 3070 | if (RT.isReduced(init)) { 3071 | return ((IDeref) init).deref(); 3072 | } 3073 | init = f.invoke(init, k5, v5); 3074 | if (RT.isReduced(init)) { 3075 | return ((IDeref) init).deref(); 3076 | } 3077 | return init; 3078 | } 3079 | 3080 | public Object reduce(IFn f) { 3081 | Object init = k0; 3082 | init = f.invoke(init, new MapEntry(k1, v1)); 3083 | if (RT.isReduced(init)) { 3084 | return ((IDeref) init).deref(); 3085 | } 3086 | init = f.invoke(init, new MapEntry(k2, v2)); 3087 | if (RT.isReduced(init)) { 3088 | return ((IDeref) init).deref(); 3089 | } 3090 | init = f.invoke(init, new MapEntry(k3, v3)); 3091 | if (RT.isReduced(init)) { 3092 | return ((IDeref) init).deref(); 3093 | } 3094 | init = f.invoke(init, new MapEntry(k4, v4)); 3095 | if (RT.isReduced(init)) { 3096 | return ((IDeref) init).deref(); 3097 | } 3098 | init = f.invoke(init, new MapEntry(k5, v5)); 3099 | if (RT.isReduced(init)) { 3100 | return ((IDeref) init).deref(); 3101 | } 3102 | return init; 3103 | } 3104 | 3105 | public Object reduce(IFn f, Object init) { 3106 | init = f.invoke(init, new MapEntry(k0, v0)); 3107 | if (RT.isReduced(init)) { 3108 | return ((IDeref) init).deref(); 3109 | } 3110 | init = f.invoke(init, new MapEntry(k1, v1)); 3111 | if (RT.isReduced(init)) { 3112 | return ((IDeref) init).deref(); 3113 | } 3114 | init = f.invoke(init, new MapEntry(k2, v2)); 3115 | if (RT.isReduced(init)) { 3116 | return ((IDeref) init).deref(); 3117 | } 3118 | init = f.invoke(init, new MapEntry(k3, v3)); 3119 | if (RT.isReduced(init)) { 3120 | return ((IDeref) init).deref(); 3121 | } 3122 | init = f.invoke(init, new MapEntry(k4, v4)); 3123 | if (RT.isReduced(init)) { 3124 | return ((IDeref) init).deref(); 3125 | } 3126 | init = f.invoke(init, new MapEntry(k5, v5)); 3127 | if (RT.isReduced(init)) { 3128 | return ((IDeref) init).deref(); 3129 | } 3130 | return init; 3131 | } 3132 | 3133 | public Iterator iterator() { 3134 | return new Iterator() { 3135 | int i = 0; 3136 | 3137 | public boolean hasNext() { 3138 | return i < 6; 3139 | } 3140 | 3141 | public Object next() { 3142 | switch (i++) { 3143 | case 0: 3144 | return new MapEntry(k0, v0); 3145 | case 1: 3146 | return new MapEntry(k1, v1); 3147 | case 2: 3148 | return new MapEntry(k2, v2); 3149 | case 3: 3150 | return new MapEntry(k3, v3); 3151 | case 4: 3152 | return new MapEntry(k4, v4); 3153 | case 5: 3154 | return new MapEntry(k5, v5); 3155 | default: 3156 | throw new IndexOutOfBoundsException(); 3157 | } 3158 | } 3159 | 3160 | public void remove() { 3161 | throw new UnsupportedOperationException(); 3162 | } 3163 | }; 3164 | } 3165 | 3166 | public Object[] toArray() { 3167 | return new Object[] { new MapEntry(k0, v0), new MapEntry(k1, v1), 3168 | new MapEntry(k2, v2), new MapEntry(k3, v3), 3169 | new MapEntry(k4, v4), new MapEntry(k5, v5) }; 3170 | } 3171 | 3172 | class UnrolledChunkedSeq extends ASeq implements IChunkedSeq, Counted { 3173 | private final IPersistentMap meta; 3174 | private final int offset; 3175 | 3176 | UnrolledChunkedSeq(IPersistentMap meta, int offset) { 3177 | this.offset = offset; 3178 | this.meta = meta; 3179 | } 3180 | 3181 | public IChunk chunkedFirst() { 3182 | return new ArrayChunk(toArray(), 0); 3183 | } 3184 | 3185 | public ISeq chunkedNext() { 3186 | return null; 3187 | } 3188 | 3189 | public ISeq chunkedMore() { 3190 | return PersistentList.EMPTY; 3191 | } 3192 | 3193 | public UnrolledChunkedSeq withMeta(IPersistentMap meta) { 3194 | return new UnrolledChunkedSeq(meta, offset); 3195 | } 3196 | 3197 | public Object first() { 3198 | switch (offset) { 3199 | case 0: 3200 | return new MapEntry(k0, v0); 3201 | case 1: 3202 | return new MapEntry(k1, v1); 3203 | case 2: 3204 | return new MapEntry(k2, v2); 3205 | case 3: 3206 | return new MapEntry(k3, v3); 3207 | case 4: 3208 | return new MapEntry(k4, v4); 3209 | case 5: 3210 | return new MapEntry(k5, v5); 3211 | } 3212 | throw new IndexOutOfBoundsException(); 3213 | } 3214 | 3215 | public ISeq next() { 3216 | if (offset < 5) { 3217 | return new UnrolledChunkedSeq(null, offset + 1); 3218 | } 3219 | return null; 3220 | } 3221 | 3222 | public int count() { 3223 | return 6 - offset; 3224 | } 3225 | } 3226 | 3227 | public ISeq seq() { 3228 | return new UnrolledChunkedSeq(null, 0); 3229 | } 3230 | } 3231 | } 3232 | -------------------------------------------------------------------------------- /src/clojure/lang/PersistentUnrolledVector.java: -------------------------------------------------------------------------------- 1 | package clojure.lang; 2 | 3 | import java.util.Iterator; 4 | 5 | public class PersistentUnrolledVector { 6 | static IPersistentVector EMPTY = new Card0(); 7 | 8 | public static IPersistentVector create() { 9 | return EMPTY; 10 | } 11 | 12 | public static IPersistentVector create(Object e0) { 13 | return new Card1(e0); 14 | } 15 | 16 | public static IPersistentVector create(Object e0, Object e1) { 17 | return new Card2(e0, e1); 18 | } 19 | 20 | public static IPersistentVector create(Object e0, Object e1, Object e2) { 21 | return new Card3(e0, e1, e2); 22 | } 23 | 24 | public static IPersistentVector create(Object e0, Object e1, Object e2, 25 | Object e3) { 26 | return new Card4(e0, e1, e2, e3); 27 | } 28 | 29 | public static IPersistentVector create(Object e0, Object e1, Object e2, 30 | Object e3, Object e4) { 31 | return new Card5(e0, e1, e2, e3, e4); 32 | } 33 | 34 | public static IPersistentVector create(Object e0, Object e1, Object e2, 35 | Object e3, Object e4, Object e5) { 36 | return new Card6(e0, e1, e2, e3, e4, e5); 37 | } 38 | 39 | public static class Card0 extends APersistentVector implements IObj, 40 | IEditableCollection, IReduce { 41 | private final IPersistentMap meta; 42 | 43 | Card0(IPersistentMap meta) { 44 | this.meta = meta; 45 | } 46 | 47 | public Card0() { 48 | this.meta = null; 49 | } 50 | 51 | public IPersistentMap meta() { 52 | return meta; 53 | } 54 | 55 | public IObj withMeta(IPersistentMap meta) { 56 | return new Card0(meta); 57 | } 58 | 59 | public Object nth(int i) { 60 | throw new IndexOutOfBoundsException(); 61 | } 62 | 63 | public Object nth(int i, Object notFound) { 64 | return notFound; 65 | } 66 | 67 | public int count() { 68 | return 0; 69 | } 70 | 71 | public IPersistentVector empty() { 72 | return EMPTY; 73 | } 74 | 75 | public IPersistentVector assocN(int i, Object val) { 76 | switch (i) { 77 | case 0: 78 | return cons(val); 79 | default: 80 | throw new IndexOutOfBoundsException(); 81 | } 82 | } 83 | 84 | public IPersistentVector cons(Object val) { 85 | return new Card1(meta, val); 86 | } 87 | 88 | public ITransientCollection asTransient() { 89 | return new Transient(); 90 | } 91 | 92 | public IPersistentVector pop() { 93 | throw new IllegalStateException("Can't pop empty vector"); 94 | } 95 | 96 | public Object kvreduce(IFn f, Object init) { 97 | return init; 98 | } 99 | 100 | public Object reduce(IFn f) { 101 | return f.invoke(); 102 | } 103 | 104 | public Object reduce(IFn f, Object init) { 105 | return init; 106 | } 107 | 108 | public int hashCode() { 109 | if (_hash == -1) { 110 | int hash = 1; 111 | _hash = hash; 112 | } 113 | return _hash; 114 | } 115 | 116 | public int hasheq() { 117 | if (_hasheq == -1) { 118 | int hash = 1; 119 | hash = Murmur3.mixCollHash(hash, 0); 120 | _hasheq = hash; 121 | } 122 | return _hasheq; 123 | } 124 | 125 | public boolean equals(Object o) { 126 | return o == this ? true : super.equals(o); 127 | } 128 | 129 | public boolean equiv(Object o) { 130 | return o == this ? true : super.equiv(o); 131 | } 132 | 133 | public Object[] toArray() { 134 | return new Object[] {}; 135 | } 136 | 137 | public Iterator iterator() { 138 | return new Iterator() { 139 | int i = 0; 140 | 141 | public boolean hasNext() { 142 | return i < 0; 143 | } 144 | 145 | public Object next() { 146 | return nth(i++); 147 | } 148 | 149 | public void remove() { 150 | throw new UnsupportedOperationException(); 151 | } 152 | }; 153 | } 154 | 155 | public ISeq seq() { 156 | return null; 157 | } 158 | } 159 | 160 | public static class Card1 extends APersistentVector implements IObj, 161 | IEditableCollection, IReduce { 162 | final Object e0; 163 | private final IPersistentMap meta; 164 | 165 | Card1(IPersistentMap meta, Object e0) { 166 | this.meta = meta; 167 | this.e0 = e0; 168 | } 169 | 170 | public Card1(Object e0) { 171 | this.meta = null; 172 | this.e0 = e0; 173 | } 174 | 175 | public IPersistentMap meta() { 176 | return meta; 177 | } 178 | 179 | public IObj withMeta(IPersistentMap meta) { 180 | return new Card1(meta, e0); 181 | } 182 | 183 | public Object nth(int i) { 184 | switch (i) { 185 | case 0: 186 | return e0; 187 | default: 188 | throw new IndexOutOfBoundsException(); 189 | } 190 | } 191 | 192 | public Object nth(int i, Object notFound) { 193 | switch (i) { 194 | case 0: 195 | return e0; 196 | default: 197 | return notFound; 198 | } 199 | } 200 | 201 | public int count() { 202 | return 1; 203 | } 204 | 205 | public IPersistentVector empty() { 206 | return EMPTY; 207 | } 208 | 209 | public IPersistentVector assocN(int i, Object val) { 210 | switch (i) { 211 | case 0: 212 | return new Card1(meta, val); 213 | case 1: 214 | return cons(val); 215 | default: 216 | throw new IndexOutOfBoundsException(); 217 | } 218 | } 219 | 220 | public IPersistentVector cons(Object val) { 221 | return new Card2(meta, e0, val); 222 | } 223 | 224 | public ITransientCollection asTransient() { 225 | return new Transient(e0); 226 | } 227 | 228 | public IPersistentVector pop() { 229 | return new Card0(meta); 230 | } 231 | 232 | public Object kvreduce(IFn f, Object init) { 233 | init = f.invoke(init, 0, e0); 234 | if (RT.isReduced(init)) { 235 | return ((IDeref) init).deref(); 236 | } 237 | return init; 238 | } 239 | 240 | public Object reduce(IFn f) { 241 | return e0; 242 | } 243 | 244 | public Object reduce(IFn f, Object init) { 245 | init = f.invoke(init, e0); 246 | if (RT.isReduced(init)) { 247 | return ((IDeref) init).deref(); 248 | } 249 | return init; 250 | } 251 | 252 | public int hashCode() { 253 | if (_hash == -1) { 254 | int hash = 1; 255 | hash = (31 * hash) + (e0 == null ? 0 : e0.hashCode()); 256 | _hash = hash; 257 | } 258 | return _hash; 259 | } 260 | 261 | public int hasheq() { 262 | if (_hasheq == -1) { 263 | int hash = 1; 264 | hash = (31 * hash) + Util.hasheq(e0); 265 | hash = Murmur3.mixCollHash(hash, 1); 266 | _hasheq = hash; 267 | } 268 | return _hasheq; 269 | } 270 | 271 | public boolean equals(Object o) { 272 | if (o instanceof Card1) { 273 | return Util.equals(e0, ((Card1) o).e0); 274 | } else { 275 | return super.equals(o); 276 | } 277 | } 278 | 279 | public boolean equiv(Object o) { 280 | if (o instanceof Card1) { 281 | return Util.equiv(e0, ((Card1) o).e0); 282 | } else { 283 | return super.equiv(o); 284 | } 285 | } 286 | 287 | public Object[] toArray() { 288 | return new Object[] { e0 }; 289 | } 290 | 291 | public Iterator iterator() { 292 | return new Iterator() { 293 | int i = 0; 294 | 295 | public boolean hasNext() { 296 | return i < 1; 297 | } 298 | 299 | public Object next() { 300 | return nth(i++); 301 | } 302 | 303 | public void remove() { 304 | throw new UnsupportedOperationException(); 305 | } 306 | }; 307 | } 308 | 309 | class UnrolledChunkedSeq extends ASeq implements IChunkedSeq, Counted { 310 | private final IPersistentMap meta; 311 | private final int offset; 312 | 313 | UnrolledChunkedSeq(IPersistentMap meta, int offset) { 314 | this.offset = offset; 315 | this.meta = meta; 316 | } 317 | 318 | public IChunk chunkedFirst() { 319 | return new ArrayChunk(toArray(), 0); 320 | } 321 | 322 | public ISeq chunkedNext() { 323 | return null; 324 | } 325 | 326 | public ISeq chunkedMore() { 327 | return PersistentList.EMPTY; 328 | } 329 | 330 | public UnrolledChunkedSeq withMeta(IPersistentMap meta) { 331 | return new UnrolledChunkedSeq(meta, offset); 332 | } 333 | 334 | public Object first() { 335 | return nth(offset); 336 | } 337 | 338 | public ISeq next() { 339 | if (offset < 0) { 340 | return new UnrolledChunkedSeq(null, offset + 1); 341 | } 342 | return null; 343 | } 344 | 345 | public int count() { 346 | return 1 - offset; 347 | } 348 | } 349 | 350 | public ISeq seq() { 351 | return new UnrolledChunkedSeq(null, 0); 352 | } 353 | } 354 | 355 | public static class Card2 extends APersistentVector implements IObj, 356 | IEditableCollection, IReduce, IMapEntry { 357 | final Object e0; 358 | final Object e1; 359 | private final IPersistentMap meta; 360 | 361 | public Object key() { 362 | return e0; 363 | } 364 | 365 | public Object getKey() { 366 | return e0; 367 | } 368 | 369 | public Object val() { 370 | return e1; 371 | } 372 | 373 | public Object getValue() { 374 | return e1; 375 | } 376 | 377 | public Object setValue(Object v) { 378 | throw new UnsupportedOperationException(); 379 | } 380 | 381 | Card2(IPersistentMap meta, Object e0, Object e1) { 382 | this.meta = meta; 383 | this.e0 = e0; 384 | this.e1 = e1; 385 | } 386 | 387 | public Card2(Object e0, Object e1) { 388 | this.meta = null; 389 | this.e0 = e0; 390 | this.e1 = e1; 391 | } 392 | 393 | public IPersistentMap meta() { 394 | return meta; 395 | } 396 | 397 | public IObj withMeta(IPersistentMap meta) { 398 | return new Card2(meta, e0, e1); 399 | } 400 | 401 | public Object nth(int i) { 402 | switch (i) { 403 | case 0: 404 | return e0; 405 | case 1: 406 | return e1; 407 | default: 408 | throw new IndexOutOfBoundsException(); 409 | } 410 | } 411 | 412 | public Object nth(int i, Object notFound) { 413 | switch (i) { 414 | case 0: 415 | return e0; 416 | case 1: 417 | return e1; 418 | default: 419 | return notFound; 420 | } 421 | } 422 | 423 | public int count() { 424 | return 2; 425 | } 426 | 427 | public IPersistentVector empty() { 428 | return EMPTY; 429 | } 430 | 431 | public IPersistentVector assocN(int i, Object val) { 432 | switch (i) { 433 | case 0: 434 | return new Card2(meta, val, e1); 435 | case 1: 436 | return new Card2(meta, e0, val); 437 | case 2: 438 | return cons(val); 439 | default: 440 | throw new IndexOutOfBoundsException(); 441 | } 442 | } 443 | 444 | public IPersistentVector cons(Object val) { 445 | return new Card3(meta, e0, e1, val); 446 | } 447 | 448 | public ITransientCollection asTransient() { 449 | return new Transient(e0, e1); 450 | } 451 | 452 | public IPersistentVector pop() { 453 | return new Card1(meta, e0); 454 | } 455 | 456 | public Object kvreduce(IFn f, Object init) { 457 | init = f.invoke(init, 0, e0); 458 | if (RT.isReduced(init)) { 459 | return ((IDeref) init).deref(); 460 | } 461 | init = f.invoke(init, 1, e1); 462 | if (RT.isReduced(init)) { 463 | return ((IDeref) init).deref(); 464 | } 465 | return init; 466 | } 467 | 468 | public Object reduce(IFn f) { 469 | Object init = e0; 470 | init = f.invoke(init, e1); 471 | if (RT.isReduced(init)) { 472 | return ((IDeref) init).deref(); 473 | } 474 | return init; 475 | } 476 | 477 | public Object reduce(IFn f, Object init) { 478 | init = f.invoke(init, e0); 479 | if (RT.isReduced(init)) { 480 | return ((IDeref) init).deref(); 481 | } 482 | init = f.invoke(init, e1); 483 | if (RT.isReduced(init)) { 484 | return ((IDeref) init).deref(); 485 | } 486 | return init; 487 | } 488 | 489 | public int hashCode() { 490 | if (_hash == -1) { 491 | int hash = 1; 492 | hash = (31 * hash) + (e0 == null ? 0 : e0.hashCode()); 493 | hash = (31 * hash) + (e1 == null ? 0 : e1.hashCode()); 494 | _hash = hash; 495 | } 496 | return _hash; 497 | } 498 | 499 | public int hasheq() { 500 | if (_hasheq == -1) { 501 | int hash = 1; 502 | hash = (31 * hash) + Util.hasheq(e0); 503 | hash = (31 * hash) + Util.hasheq(e1); 504 | hash = Murmur3.mixCollHash(hash, 2); 505 | _hasheq = hash; 506 | } 507 | return _hasheq; 508 | } 509 | 510 | public boolean equals(Object o) { 511 | if (o instanceof Card2) { 512 | return Util.equals(e0, ((Card2) o).e0) 513 | && Util.equals(e1, ((Card2) o).e1); 514 | } else { 515 | return super.equals(o); 516 | } 517 | } 518 | 519 | public boolean equiv(Object o) { 520 | if (o instanceof Card2) { 521 | return Util.equiv(e0, ((Card2) o).e0) 522 | && Util.equiv(e1, ((Card2) o).e1); 523 | } else { 524 | return super.equiv(o); 525 | } 526 | } 527 | 528 | public Object[] toArray() { 529 | return new Object[] { e0, e1 }; 530 | } 531 | 532 | public Iterator iterator() { 533 | return new Iterator() { 534 | int i = 0; 535 | 536 | public boolean hasNext() { 537 | return i < 2; 538 | } 539 | 540 | public Object next() { 541 | return nth(i++); 542 | } 543 | 544 | public void remove() { 545 | throw new UnsupportedOperationException(); 546 | } 547 | }; 548 | } 549 | 550 | class UnrolledChunkedSeq extends ASeq implements IChunkedSeq, Counted { 551 | private final IPersistentMap meta; 552 | private final int offset; 553 | 554 | UnrolledChunkedSeq(IPersistentMap meta, int offset) { 555 | this.offset = offset; 556 | this.meta = meta; 557 | } 558 | 559 | public IChunk chunkedFirst() { 560 | return new ArrayChunk(toArray(), 0); 561 | } 562 | 563 | public ISeq chunkedNext() { 564 | return null; 565 | } 566 | 567 | public ISeq chunkedMore() { 568 | return PersistentList.EMPTY; 569 | } 570 | 571 | public UnrolledChunkedSeq withMeta(IPersistentMap meta) { 572 | return new UnrolledChunkedSeq(meta, offset); 573 | } 574 | 575 | public Object first() { 576 | return nth(offset); 577 | } 578 | 579 | public ISeq next() { 580 | if (offset < 1) { 581 | return new UnrolledChunkedSeq(null, offset + 1); 582 | } 583 | return null; 584 | } 585 | 586 | public int count() { 587 | return 2 - offset; 588 | } 589 | } 590 | 591 | public ISeq seq() { 592 | return new UnrolledChunkedSeq(null, 0); 593 | } 594 | } 595 | 596 | public static class Card3 extends APersistentVector implements IObj, 597 | IEditableCollection, IReduce { 598 | final Object e0; 599 | final Object e1; 600 | final Object e2; 601 | private final IPersistentMap meta; 602 | 603 | Card3(IPersistentMap meta, Object e0, Object e1, Object e2) { 604 | this.meta = meta; 605 | this.e0 = e0; 606 | this.e1 = e1; 607 | this.e2 = e2; 608 | } 609 | 610 | public Card3(Object e0, Object e1, Object e2) { 611 | this.meta = null; 612 | this.e0 = e0; 613 | this.e1 = e1; 614 | this.e2 = e2; 615 | } 616 | 617 | public IPersistentMap meta() { 618 | return meta; 619 | } 620 | 621 | public IObj withMeta(IPersistentMap meta) { 622 | return new Card3(meta, e0, e1, e2); 623 | } 624 | 625 | public Object nth(int i) { 626 | switch (i) { 627 | case 0: 628 | return e0; 629 | case 1: 630 | return e1; 631 | case 2: 632 | return e2; 633 | default: 634 | throw new IndexOutOfBoundsException(); 635 | } 636 | } 637 | 638 | public Object nth(int i, Object notFound) { 639 | switch (i) { 640 | case 0: 641 | return e0; 642 | case 1: 643 | return e1; 644 | case 2: 645 | return e2; 646 | default: 647 | return notFound; 648 | } 649 | } 650 | 651 | public int count() { 652 | return 3; 653 | } 654 | 655 | public IPersistentVector empty() { 656 | return EMPTY; 657 | } 658 | 659 | public IPersistentVector assocN(int i, Object val) { 660 | switch (i) { 661 | case 0: 662 | return new Card3(meta, val, e1, e2); 663 | case 1: 664 | return new Card3(meta, e0, val, e2); 665 | case 2: 666 | return new Card3(meta, e0, e1, val); 667 | case 3: 668 | return cons(val); 669 | default: 670 | throw new IndexOutOfBoundsException(); 671 | } 672 | } 673 | 674 | public IPersistentVector cons(Object val) { 675 | return new Card4(meta, e0, e1, e2, val); 676 | } 677 | 678 | public ITransientCollection asTransient() { 679 | return new Transient(e0, e1, e2); 680 | } 681 | 682 | public IPersistentVector pop() { 683 | return new Card2(meta, e0, e1); 684 | } 685 | 686 | public Object kvreduce(IFn f, Object init) { 687 | init = f.invoke(init, 0, e0); 688 | if (RT.isReduced(init)) { 689 | return ((IDeref) init).deref(); 690 | } 691 | init = f.invoke(init, 1, e1); 692 | if (RT.isReduced(init)) { 693 | return ((IDeref) init).deref(); 694 | } 695 | init = f.invoke(init, 2, e2); 696 | if (RT.isReduced(init)) { 697 | return ((IDeref) init).deref(); 698 | } 699 | return init; 700 | } 701 | 702 | public Object reduce(IFn f) { 703 | Object init = e0; 704 | init = f.invoke(init, e1); 705 | if (RT.isReduced(init)) { 706 | return ((IDeref) init).deref(); 707 | } 708 | init = f.invoke(init, e2); 709 | if (RT.isReduced(init)) { 710 | return ((IDeref) init).deref(); 711 | } 712 | return init; 713 | } 714 | 715 | public Object reduce(IFn f, Object init) { 716 | init = f.invoke(init, e0); 717 | if (RT.isReduced(init)) { 718 | return ((IDeref) init).deref(); 719 | } 720 | init = f.invoke(init, e1); 721 | if (RT.isReduced(init)) { 722 | return ((IDeref) init).deref(); 723 | } 724 | init = f.invoke(init, e2); 725 | if (RT.isReduced(init)) { 726 | return ((IDeref) init).deref(); 727 | } 728 | return init; 729 | } 730 | 731 | public int hashCode() { 732 | if (_hash == -1) { 733 | int hash = 1; 734 | hash = (31 * hash) + (e0 == null ? 0 : e0.hashCode()); 735 | hash = (31 * hash) + (e1 == null ? 0 : e1.hashCode()); 736 | hash = (31 * hash) + (e2 == null ? 0 : e2.hashCode()); 737 | _hash = hash; 738 | } 739 | return _hash; 740 | } 741 | 742 | public int hasheq() { 743 | if (_hasheq == -1) { 744 | int hash = 1; 745 | hash = (31 * hash) + Util.hasheq(e0); 746 | hash = (31 * hash) + Util.hasheq(e1); 747 | hash = (31 * hash) + Util.hasheq(e2); 748 | hash = Murmur3.mixCollHash(hash, 3); 749 | _hasheq = hash; 750 | } 751 | return _hasheq; 752 | } 753 | 754 | public boolean equals(Object o) { 755 | if (o instanceof Card3) { 756 | return Util.equals(e0, ((Card3) o).e0) 757 | && Util.equals(e1, ((Card3) o).e1) 758 | && Util.equals(e2, ((Card3) o).e2); 759 | } else { 760 | return super.equals(o); 761 | } 762 | } 763 | 764 | public boolean equiv(Object o) { 765 | if (o instanceof Card3) { 766 | return Util.equiv(e0, ((Card3) o).e0) 767 | && Util.equiv(e1, ((Card3) o).e1) 768 | && Util.equiv(e2, ((Card3) o).e2); 769 | } else { 770 | return super.equiv(o); 771 | } 772 | } 773 | 774 | public Object[] toArray() { 775 | return new Object[] { e0, e1, e2 }; 776 | } 777 | 778 | public Iterator iterator() { 779 | return new Iterator() { 780 | int i = 0; 781 | 782 | public boolean hasNext() { 783 | return i < 3; 784 | } 785 | 786 | public Object next() { 787 | return nth(i++); 788 | } 789 | 790 | public void remove() { 791 | throw new UnsupportedOperationException(); 792 | } 793 | }; 794 | } 795 | 796 | class UnrolledChunkedSeq extends ASeq implements IChunkedSeq, Counted { 797 | private final IPersistentMap meta; 798 | private final int offset; 799 | 800 | UnrolledChunkedSeq(IPersistentMap meta, int offset) { 801 | this.offset = offset; 802 | this.meta = meta; 803 | } 804 | 805 | public IChunk chunkedFirst() { 806 | return new ArrayChunk(toArray(), 0); 807 | } 808 | 809 | public ISeq chunkedNext() { 810 | return null; 811 | } 812 | 813 | public ISeq chunkedMore() { 814 | return PersistentList.EMPTY; 815 | } 816 | 817 | public UnrolledChunkedSeq withMeta(IPersistentMap meta) { 818 | return new UnrolledChunkedSeq(meta, offset); 819 | } 820 | 821 | public Object first() { 822 | return nth(offset); 823 | } 824 | 825 | public ISeq next() { 826 | if (offset < 2) { 827 | return new UnrolledChunkedSeq(null, offset + 1); 828 | } 829 | return null; 830 | } 831 | 832 | public int count() { 833 | return 3 - offset; 834 | } 835 | } 836 | 837 | public ISeq seq() { 838 | return new UnrolledChunkedSeq(null, 0); 839 | } 840 | } 841 | 842 | public static class Card4 extends APersistentVector implements IObj, 843 | IEditableCollection, IReduce { 844 | final Object e0; 845 | final Object e1; 846 | final Object e2; 847 | final Object e3; 848 | private final IPersistentMap meta; 849 | 850 | Card4(IPersistentMap meta, Object e0, Object e1, Object e2, Object e3) { 851 | this.meta = meta; 852 | this.e0 = e0; 853 | this.e1 = e1; 854 | this.e2 = e2; 855 | this.e3 = e3; 856 | } 857 | 858 | public Card4(Object e0, Object e1, Object e2, Object e3) { 859 | this.meta = null; 860 | this.e0 = e0; 861 | this.e1 = e1; 862 | this.e2 = e2; 863 | this.e3 = e3; 864 | } 865 | 866 | public IPersistentMap meta() { 867 | return meta; 868 | } 869 | 870 | public IObj withMeta(IPersistentMap meta) { 871 | return new Card4(meta, e0, e1, e2, e3); 872 | } 873 | 874 | public Object nth(int i) { 875 | switch (i) { 876 | case 0: 877 | return e0; 878 | case 1: 879 | return e1; 880 | case 2: 881 | return e2; 882 | case 3: 883 | return e3; 884 | default: 885 | throw new IndexOutOfBoundsException(); 886 | } 887 | } 888 | 889 | public Object nth(int i, Object notFound) { 890 | switch (i) { 891 | case 0: 892 | return e0; 893 | case 1: 894 | return e1; 895 | case 2: 896 | return e2; 897 | case 3: 898 | return e3; 899 | default: 900 | return notFound; 901 | } 902 | } 903 | 904 | public int count() { 905 | return 4; 906 | } 907 | 908 | public IPersistentVector empty() { 909 | return EMPTY; 910 | } 911 | 912 | public IPersistentVector assocN(int i, Object val) { 913 | switch (i) { 914 | case 0: 915 | return new Card4(meta, val, e1, e2, e3); 916 | case 1: 917 | return new Card4(meta, e0, val, e2, e3); 918 | case 2: 919 | return new Card4(meta, e0, e1, val, e3); 920 | case 3: 921 | return new Card4(meta, e0, e1, e2, val); 922 | case 4: 923 | return cons(val); 924 | default: 925 | throw new IndexOutOfBoundsException(); 926 | } 927 | } 928 | 929 | public IPersistentVector cons(Object val) { 930 | return new Card5(meta, e0, e1, e2, e3, val); 931 | } 932 | 933 | public ITransientCollection asTransient() { 934 | return new Transient(e0, e1, e2, e3); 935 | } 936 | 937 | public IPersistentVector pop() { 938 | return new Card3(meta, e0, e1, e2); 939 | } 940 | 941 | public Object kvreduce(IFn f, Object init) { 942 | init = f.invoke(init, 0, e0); 943 | if (RT.isReduced(init)) { 944 | return ((IDeref) init).deref(); 945 | } 946 | init = f.invoke(init, 1, e1); 947 | if (RT.isReduced(init)) { 948 | return ((IDeref) init).deref(); 949 | } 950 | init = f.invoke(init, 2, e2); 951 | if (RT.isReduced(init)) { 952 | return ((IDeref) init).deref(); 953 | } 954 | init = f.invoke(init, 3, e3); 955 | if (RT.isReduced(init)) { 956 | return ((IDeref) init).deref(); 957 | } 958 | return init; 959 | } 960 | 961 | public Object reduce(IFn f) { 962 | Object init = e0; 963 | init = f.invoke(init, e1); 964 | if (RT.isReduced(init)) { 965 | return ((IDeref) init).deref(); 966 | } 967 | init = f.invoke(init, e2); 968 | if (RT.isReduced(init)) { 969 | return ((IDeref) init).deref(); 970 | } 971 | init = f.invoke(init, e3); 972 | if (RT.isReduced(init)) { 973 | return ((IDeref) init).deref(); 974 | } 975 | return init; 976 | } 977 | 978 | public Object reduce(IFn f, Object init) { 979 | init = f.invoke(init, e0); 980 | if (RT.isReduced(init)) { 981 | return ((IDeref) init).deref(); 982 | } 983 | init = f.invoke(init, e1); 984 | if (RT.isReduced(init)) { 985 | return ((IDeref) init).deref(); 986 | } 987 | init = f.invoke(init, e2); 988 | if (RT.isReduced(init)) { 989 | return ((IDeref) init).deref(); 990 | } 991 | init = f.invoke(init, e3); 992 | if (RT.isReduced(init)) { 993 | return ((IDeref) init).deref(); 994 | } 995 | return init; 996 | } 997 | 998 | public int hashCode() { 999 | if (_hash == -1) { 1000 | int hash = 1; 1001 | hash = (31 * hash) + (e0 == null ? 0 : e0.hashCode()); 1002 | hash = (31 * hash) + (e1 == null ? 0 : e1.hashCode()); 1003 | hash = (31 * hash) + (e2 == null ? 0 : e2.hashCode()); 1004 | hash = (31 * hash) + (e3 == null ? 0 : e3.hashCode()); 1005 | _hash = hash; 1006 | } 1007 | return _hash; 1008 | } 1009 | 1010 | public int hasheq() { 1011 | if (_hasheq == -1) { 1012 | int hash = 1; 1013 | hash = (31 * hash) + Util.hasheq(e0); 1014 | hash = (31 * hash) + Util.hasheq(e1); 1015 | hash = (31 * hash) + Util.hasheq(e2); 1016 | hash = (31 * hash) + Util.hasheq(e3); 1017 | hash = Murmur3.mixCollHash(hash, 4); 1018 | _hasheq = hash; 1019 | } 1020 | return _hasheq; 1021 | } 1022 | 1023 | public boolean equals(Object o) { 1024 | if (o instanceof Card4) { 1025 | return Util.equals(e0, ((Card4) o).e0) 1026 | && Util.equals(e1, ((Card4) o).e1) 1027 | && Util.equals(e2, ((Card4) o).e2) 1028 | && Util.equals(e3, ((Card4) o).e3); 1029 | } else { 1030 | return super.equals(o); 1031 | } 1032 | } 1033 | 1034 | public boolean equiv(Object o) { 1035 | if (o instanceof Card4) { 1036 | return Util.equiv(e0, ((Card4) o).e0) 1037 | && Util.equiv(e1, ((Card4) o).e1) 1038 | && Util.equiv(e2, ((Card4) o).e2) 1039 | && Util.equiv(e3, ((Card4) o).e3); 1040 | } else { 1041 | return super.equiv(o); 1042 | } 1043 | } 1044 | 1045 | public Object[] toArray() { 1046 | return new Object[] { e0, e1, e2, e3 }; 1047 | } 1048 | 1049 | public Iterator iterator() { 1050 | return new Iterator() { 1051 | int i = 0; 1052 | 1053 | public boolean hasNext() { 1054 | return i < 4; 1055 | } 1056 | 1057 | public Object next() { 1058 | return nth(i++); 1059 | } 1060 | 1061 | public void remove() { 1062 | throw new UnsupportedOperationException(); 1063 | } 1064 | }; 1065 | } 1066 | 1067 | class UnrolledChunkedSeq extends ASeq implements IChunkedSeq, Counted { 1068 | private final IPersistentMap meta; 1069 | private final int offset; 1070 | 1071 | UnrolledChunkedSeq(IPersistentMap meta, int offset) { 1072 | this.offset = offset; 1073 | this.meta = meta; 1074 | } 1075 | 1076 | public IChunk chunkedFirst() { 1077 | return new ArrayChunk(toArray(), 0); 1078 | } 1079 | 1080 | public ISeq chunkedNext() { 1081 | return null; 1082 | } 1083 | 1084 | public ISeq chunkedMore() { 1085 | return PersistentList.EMPTY; 1086 | } 1087 | 1088 | public UnrolledChunkedSeq withMeta(IPersistentMap meta) { 1089 | return new UnrolledChunkedSeq(meta, offset); 1090 | } 1091 | 1092 | public Object first() { 1093 | return nth(offset); 1094 | } 1095 | 1096 | public ISeq next() { 1097 | if (offset < 3) { 1098 | return new UnrolledChunkedSeq(null, offset + 1); 1099 | } 1100 | return null; 1101 | } 1102 | 1103 | public int count() { 1104 | return 4 - offset; 1105 | } 1106 | } 1107 | 1108 | public ISeq seq() { 1109 | return new UnrolledChunkedSeq(null, 0); 1110 | } 1111 | } 1112 | 1113 | public static class Card5 extends APersistentVector implements IObj, 1114 | IEditableCollection, IReduce { 1115 | final Object e0; 1116 | final Object e1; 1117 | final Object e2; 1118 | final Object e3; 1119 | final Object e4; 1120 | private final IPersistentMap meta; 1121 | 1122 | Card5(IPersistentMap meta, Object e0, Object e1, Object e2, Object e3, 1123 | Object e4) { 1124 | this.meta = meta; 1125 | this.e0 = e0; 1126 | this.e1 = e1; 1127 | this.e2 = e2; 1128 | this.e3 = e3; 1129 | this.e4 = e4; 1130 | } 1131 | 1132 | public Card5(Object e0, Object e1, Object e2, Object e3, Object e4) { 1133 | this.meta = null; 1134 | this.e0 = e0; 1135 | this.e1 = e1; 1136 | this.e2 = e2; 1137 | this.e3 = e3; 1138 | this.e4 = e4; 1139 | } 1140 | 1141 | public IPersistentMap meta() { 1142 | return meta; 1143 | } 1144 | 1145 | public IObj withMeta(IPersistentMap meta) { 1146 | return new Card5(meta, e0, e1, e2, e3, e4); 1147 | } 1148 | 1149 | public Object nth(int i) { 1150 | switch (i) { 1151 | case 0: 1152 | return e0; 1153 | case 1: 1154 | return e1; 1155 | case 2: 1156 | return e2; 1157 | case 3: 1158 | return e3; 1159 | case 4: 1160 | return e4; 1161 | default: 1162 | throw new IndexOutOfBoundsException(); 1163 | } 1164 | } 1165 | 1166 | public Object nth(int i, Object notFound) { 1167 | switch (i) { 1168 | case 0: 1169 | return e0; 1170 | case 1: 1171 | return e1; 1172 | case 2: 1173 | return e2; 1174 | case 3: 1175 | return e3; 1176 | case 4: 1177 | return e4; 1178 | default: 1179 | return notFound; 1180 | } 1181 | } 1182 | 1183 | public int count() { 1184 | return 5; 1185 | } 1186 | 1187 | public IPersistentVector empty() { 1188 | return EMPTY; 1189 | } 1190 | 1191 | public IPersistentVector assocN(int i, Object val) { 1192 | switch (i) { 1193 | case 0: 1194 | return new Card5(meta, val, e1, e2, e3, e4); 1195 | case 1: 1196 | return new Card5(meta, e0, val, e2, e3, e4); 1197 | case 2: 1198 | return new Card5(meta, e0, e1, val, e3, e4); 1199 | case 3: 1200 | return new Card5(meta, e0, e1, e2, val, e4); 1201 | case 4: 1202 | return new Card5(meta, e0, e1, e2, e3, val); 1203 | case 5: 1204 | return cons(val); 1205 | default: 1206 | throw new IndexOutOfBoundsException(); 1207 | } 1208 | } 1209 | 1210 | public IPersistentVector cons(Object val) { 1211 | return new Card6(meta, e0, e1, e2, e3, e4, val); 1212 | } 1213 | 1214 | public ITransientCollection asTransient() { 1215 | return new Transient(e0, e1, e2, e3, e4); 1216 | } 1217 | 1218 | public IPersistentVector pop() { 1219 | return new Card4(meta, e0, e1, e2, e3); 1220 | } 1221 | 1222 | public Object kvreduce(IFn f, Object init) { 1223 | init = f.invoke(init, 0, e0); 1224 | if (RT.isReduced(init)) { 1225 | return ((IDeref) init).deref(); 1226 | } 1227 | init = f.invoke(init, 1, e1); 1228 | if (RT.isReduced(init)) { 1229 | return ((IDeref) init).deref(); 1230 | } 1231 | init = f.invoke(init, 2, e2); 1232 | if (RT.isReduced(init)) { 1233 | return ((IDeref) init).deref(); 1234 | } 1235 | init = f.invoke(init, 3, e3); 1236 | if (RT.isReduced(init)) { 1237 | return ((IDeref) init).deref(); 1238 | } 1239 | init = f.invoke(init, 4, e4); 1240 | if (RT.isReduced(init)) { 1241 | return ((IDeref) init).deref(); 1242 | } 1243 | return init; 1244 | } 1245 | 1246 | public Object reduce(IFn f) { 1247 | Object init = e0; 1248 | init = f.invoke(init, e1); 1249 | if (RT.isReduced(init)) { 1250 | return ((IDeref) init).deref(); 1251 | } 1252 | init = f.invoke(init, e2); 1253 | if (RT.isReduced(init)) { 1254 | return ((IDeref) init).deref(); 1255 | } 1256 | init = f.invoke(init, e3); 1257 | if (RT.isReduced(init)) { 1258 | return ((IDeref) init).deref(); 1259 | } 1260 | init = f.invoke(init, e4); 1261 | if (RT.isReduced(init)) { 1262 | return ((IDeref) init).deref(); 1263 | } 1264 | return init; 1265 | } 1266 | 1267 | public Object reduce(IFn f, Object init) { 1268 | init = f.invoke(init, e0); 1269 | if (RT.isReduced(init)) { 1270 | return ((IDeref) init).deref(); 1271 | } 1272 | init = f.invoke(init, e1); 1273 | if (RT.isReduced(init)) { 1274 | return ((IDeref) init).deref(); 1275 | } 1276 | init = f.invoke(init, e2); 1277 | if (RT.isReduced(init)) { 1278 | return ((IDeref) init).deref(); 1279 | } 1280 | init = f.invoke(init, e3); 1281 | if (RT.isReduced(init)) { 1282 | return ((IDeref) init).deref(); 1283 | } 1284 | init = f.invoke(init, e4); 1285 | if (RT.isReduced(init)) { 1286 | return ((IDeref) init).deref(); 1287 | } 1288 | return init; 1289 | } 1290 | 1291 | public int hashCode() { 1292 | if (_hash == -1) { 1293 | int hash = 1; 1294 | hash = (31 * hash) + (e0 == null ? 0 : e0.hashCode()); 1295 | hash = (31 * hash) + (e1 == null ? 0 : e1.hashCode()); 1296 | hash = (31 * hash) + (e2 == null ? 0 : e2.hashCode()); 1297 | hash = (31 * hash) + (e3 == null ? 0 : e3.hashCode()); 1298 | hash = (31 * hash) + (e4 == null ? 0 : e4.hashCode()); 1299 | _hash = hash; 1300 | } 1301 | return _hash; 1302 | } 1303 | 1304 | public int hasheq() { 1305 | if (_hasheq == -1) { 1306 | int hash = 1; 1307 | hash = (31 * hash) + Util.hasheq(e0); 1308 | hash = (31 * hash) + Util.hasheq(e1); 1309 | hash = (31 * hash) + Util.hasheq(e2); 1310 | hash = (31 * hash) + Util.hasheq(e3); 1311 | hash = (31 * hash) + Util.hasheq(e4); 1312 | hash = Murmur3.mixCollHash(hash, 5); 1313 | _hasheq = hash; 1314 | } 1315 | return _hasheq; 1316 | } 1317 | 1318 | public boolean equals(Object o) { 1319 | if (o instanceof Card5) { 1320 | return Util.equals(e0, ((Card5) o).e0) 1321 | && Util.equals(e1, ((Card5) o).e1) 1322 | && Util.equals(e2, ((Card5) o).e2) 1323 | && Util.equals(e3, ((Card5) o).e3) 1324 | && Util.equals(e4, ((Card5) o).e4); 1325 | } else { 1326 | return super.equals(o); 1327 | } 1328 | } 1329 | 1330 | public boolean equiv(Object o) { 1331 | if (o instanceof Card5) { 1332 | return Util.equiv(e0, ((Card5) o).e0) 1333 | && Util.equiv(e1, ((Card5) o).e1) 1334 | && Util.equiv(e2, ((Card5) o).e2) 1335 | && Util.equiv(e3, ((Card5) o).e3) 1336 | && Util.equiv(e4, ((Card5) o).e4); 1337 | } else { 1338 | return super.equiv(o); 1339 | } 1340 | } 1341 | 1342 | public Object[] toArray() { 1343 | return new Object[] { e0, e1, e2, e3, e4 }; 1344 | } 1345 | 1346 | public Iterator iterator() { 1347 | return new Iterator() { 1348 | int i = 0; 1349 | 1350 | public boolean hasNext() { 1351 | return i < 5; 1352 | } 1353 | 1354 | public Object next() { 1355 | return nth(i++); 1356 | } 1357 | 1358 | public void remove() { 1359 | throw new UnsupportedOperationException(); 1360 | } 1361 | }; 1362 | } 1363 | 1364 | class UnrolledChunkedSeq extends ASeq implements IChunkedSeq, Counted { 1365 | private final IPersistentMap meta; 1366 | private final int offset; 1367 | 1368 | UnrolledChunkedSeq(IPersistentMap meta, int offset) { 1369 | this.offset = offset; 1370 | this.meta = meta; 1371 | } 1372 | 1373 | public IChunk chunkedFirst() { 1374 | return new ArrayChunk(toArray(), 0); 1375 | } 1376 | 1377 | public ISeq chunkedNext() { 1378 | return null; 1379 | } 1380 | 1381 | public ISeq chunkedMore() { 1382 | return PersistentList.EMPTY; 1383 | } 1384 | 1385 | public UnrolledChunkedSeq withMeta(IPersistentMap meta) { 1386 | return new UnrolledChunkedSeq(meta, offset); 1387 | } 1388 | 1389 | public Object first() { 1390 | return nth(offset); 1391 | } 1392 | 1393 | public ISeq next() { 1394 | if (offset < 4) { 1395 | return new UnrolledChunkedSeq(null, offset + 1); 1396 | } 1397 | return null; 1398 | } 1399 | 1400 | public int count() { 1401 | return 5 - offset; 1402 | } 1403 | } 1404 | 1405 | public ISeq seq() { 1406 | return new UnrolledChunkedSeq(null, 0); 1407 | } 1408 | } 1409 | 1410 | public static class Card6 extends APersistentVector implements IObj, 1411 | IEditableCollection, IReduce { 1412 | final Object e0; 1413 | final Object e1; 1414 | final Object e2; 1415 | final Object e3; 1416 | final Object e4; 1417 | final Object e5; 1418 | private final IPersistentMap meta; 1419 | 1420 | Card6(IPersistentMap meta, Object e0, Object e1, Object e2, Object e3, 1421 | Object e4, Object e5) { 1422 | this.meta = meta; 1423 | this.e0 = e0; 1424 | this.e1 = e1; 1425 | this.e2 = e2; 1426 | this.e3 = e3; 1427 | this.e4 = e4; 1428 | this.e5 = e5; 1429 | } 1430 | 1431 | public Card6(Object e0, Object e1, Object e2, Object e3, Object e4, 1432 | Object e5) { 1433 | this.meta = null; 1434 | this.e0 = e0; 1435 | this.e1 = e1; 1436 | this.e2 = e2; 1437 | this.e3 = e3; 1438 | this.e4 = e4; 1439 | this.e5 = e5; 1440 | } 1441 | 1442 | public IPersistentMap meta() { 1443 | return meta; 1444 | } 1445 | 1446 | public IObj withMeta(IPersistentMap meta) { 1447 | return new Card6(meta, e0, e1, e2, e3, e4, e5); 1448 | } 1449 | 1450 | public Object nth(int i) { 1451 | switch (i) { 1452 | case 0: 1453 | return e0; 1454 | case 1: 1455 | return e1; 1456 | case 2: 1457 | return e2; 1458 | case 3: 1459 | return e3; 1460 | case 4: 1461 | return e4; 1462 | case 5: 1463 | return e5; 1464 | default: 1465 | throw new IndexOutOfBoundsException(); 1466 | } 1467 | } 1468 | 1469 | public Object nth(int i, Object notFound) { 1470 | switch (i) { 1471 | case 0: 1472 | return e0; 1473 | case 1: 1474 | return e1; 1475 | case 2: 1476 | return e2; 1477 | case 3: 1478 | return e3; 1479 | case 4: 1480 | return e4; 1481 | case 5: 1482 | return e5; 1483 | default: 1484 | return notFound; 1485 | } 1486 | } 1487 | 1488 | public int count() { 1489 | return 6; 1490 | } 1491 | 1492 | public IPersistentVector empty() { 1493 | return EMPTY; 1494 | } 1495 | 1496 | public IPersistentVector assocN(int i, Object val) { 1497 | switch (i) { 1498 | case 0: 1499 | return new Card6(meta, val, e1, e2, e3, e4, e5); 1500 | case 1: 1501 | return new Card6(meta, e0, val, e2, e3, e4, e5); 1502 | case 2: 1503 | return new Card6(meta, e0, e1, val, e3, e4, e5); 1504 | case 3: 1505 | return new Card6(meta, e0, e1, e2, val, e4, e5); 1506 | case 4: 1507 | return new Card6(meta, e0, e1, e2, e3, val, e5); 1508 | case 5: 1509 | return new Card6(meta, e0, e1, e2, e3, e4, val); 1510 | case 6: 1511 | return cons(val); 1512 | default: 1513 | throw new IndexOutOfBoundsException(); 1514 | } 1515 | } 1516 | 1517 | public IPersistentVector cons(Object val) { 1518 | return new PersistentVector(meta, 7, 5, 1519 | PersistentVector.EMPTY_NODE, new Object[] { e0, e1, e2, e3, 1520 | e4, e5, val }); 1521 | } 1522 | 1523 | public ITransientCollection asTransient() { 1524 | return new Transient(e0, e1, e2, e3, e4, e5); 1525 | } 1526 | 1527 | public IPersistentVector pop() { 1528 | return new Card5(meta, e0, e1, e2, e3, e4); 1529 | } 1530 | 1531 | public Object kvreduce(IFn f, Object init) { 1532 | init = f.invoke(init, 0, e0); 1533 | if (RT.isReduced(init)) { 1534 | return ((IDeref) init).deref(); 1535 | } 1536 | init = f.invoke(init, 1, e1); 1537 | if (RT.isReduced(init)) { 1538 | return ((IDeref) init).deref(); 1539 | } 1540 | init = f.invoke(init, 2, e2); 1541 | if (RT.isReduced(init)) { 1542 | return ((IDeref) init).deref(); 1543 | } 1544 | init = f.invoke(init, 3, e3); 1545 | if (RT.isReduced(init)) { 1546 | return ((IDeref) init).deref(); 1547 | } 1548 | init = f.invoke(init, 4, e4); 1549 | if (RT.isReduced(init)) { 1550 | return ((IDeref) init).deref(); 1551 | } 1552 | init = f.invoke(init, 5, e5); 1553 | if (RT.isReduced(init)) { 1554 | return ((IDeref) init).deref(); 1555 | } 1556 | return init; 1557 | } 1558 | 1559 | public Object reduce(IFn f) { 1560 | Object init = e0; 1561 | init = f.invoke(init, e1); 1562 | if (RT.isReduced(init)) { 1563 | return ((IDeref) init).deref(); 1564 | } 1565 | init = f.invoke(init, e2); 1566 | if (RT.isReduced(init)) { 1567 | return ((IDeref) init).deref(); 1568 | } 1569 | init = f.invoke(init, e3); 1570 | if (RT.isReduced(init)) { 1571 | return ((IDeref) init).deref(); 1572 | } 1573 | init = f.invoke(init, e4); 1574 | if (RT.isReduced(init)) { 1575 | return ((IDeref) init).deref(); 1576 | } 1577 | init = f.invoke(init, e5); 1578 | if (RT.isReduced(init)) { 1579 | return ((IDeref) init).deref(); 1580 | } 1581 | return init; 1582 | } 1583 | 1584 | public Object reduce(IFn f, Object init) { 1585 | init = f.invoke(init, e0); 1586 | if (RT.isReduced(init)) { 1587 | return ((IDeref) init).deref(); 1588 | } 1589 | init = f.invoke(init, e1); 1590 | if (RT.isReduced(init)) { 1591 | return ((IDeref) init).deref(); 1592 | } 1593 | init = f.invoke(init, e2); 1594 | if (RT.isReduced(init)) { 1595 | return ((IDeref) init).deref(); 1596 | } 1597 | init = f.invoke(init, e3); 1598 | if (RT.isReduced(init)) { 1599 | return ((IDeref) init).deref(); 1600 | } 1601 | init = f.invoke(init, e4); 1602 | if (RT.isReduced(init)) { 1603 | return ((IDeref) init).deref(); 1604 | } 1605 | init = f.invoke(init, e5); 1606 | if (RT.isReduced(init)) { 1607 | return ((IDeref) init).deref(); 1608 | } 1609 | return init; 1610 | } 1611 | 1612 | public int hashCode() { 1613 | if (_hash == -1) { 1614 | int hash = 1; 1615 | hash = (31 * hash) + (e0 == null ? 0 : e0.hashCode()); 1616 | hash = (31 * hash) + (e1 == null ? 0 : e1.hashCode()); 1617 | hash = (31 * hash) + (e2 == null ? 0 : e2.hashCode()); 1618 | hash = (31 * hash) + (e3 == null ? 0 : e3.hashCode()); 1619 | hash = (31 * hash) + (e4 == null ? 0 : e4.hashCode()); 1620 | hash = (31 * hash) + (e5 == null ? 0 : e5.hashCode()); 1621 | _hash = hash; 1622 | } 1623 | return _hash; 1624 | } 1625 | 1626 | public int hasheq() { 1627 | if (_hasheq == -1) { 1628 | int hash = 1; 1629 | hash = (31 * hash) + Util.hasheq(e0); 1630 | hash = (31 * hash) + Util.hasheq(e1); 1631 | hash = (31 * hash) + Util.hasheq(e2); 1632 | hash = (31 * hash) + Util.hasheq(e3); 1633 | hash = (31 * hash) + Util.hasheq(e4); 1634 | hash = (31 * hash) + Util.hasheq(e5); 1635 | hash = Murmur3.mixCollHash(hash, 6); 1636 | _hasheq = hash; 1637 | } 1638 | return _hasheq; 1639 | } 1640 | 1641 | public boolean equals(Object o) { 1642 | if (o instanceof Card6) { 1643 | return Util.equals(e0, ((Card6) o).e0) 1644 | && Util.equals(e1, ((Card6) o).e1) 1645 | && Util.equals(e2, ((Card6) o).e2) 1646 | && Util.equals(e3, ((Card6) o).e3) 1647 | && Util.equals(e4, ((Card6) o).e4) 1648 | && Util.equals(e5, ((Card6) o).e5); 1649 | } else { 1650 | return super.equals(o); 1651 | } 1652 | } 1653 | 1654 | public boolean equiv(Object o) { 1655 | if (o instanceof Card6) { 1656 | return Util.equiv(e0, ((Card6) o).e0) 1657 | && Util.equiv(e1, ((Card6) o).e1) 1658 | && Util.equiv(e2, ((Card6) o).e2) 1659 | && Util.equiv(e3, ((Card6) o).e3) 1660 | && Util.equiv(e4, ((Card6) o).e4) 1661 | && Util.equiv(e5, ((Card6) o).e5); 1662 | } else { 1663 | return super.equiv(o); 1664 | } 1665 | } 1666 | 1667 | public Object[] toArray() { 1668 | return new Object[] { e0, e1, e2, e3, e4, e5 }; 1669 | } 1670 | 1671 | public Iterator iterator() { 1672 | return new Iterator() { 1673 | int i = 0; 1674 | 1675 | public boolean hasNext() { 1676 | return i < 6; 1677 | } 1678 | 1679 | public Object next() { 1680 | return nth(i++); 1681 | } 1682 | 1683 | public void remove() { 1684 | throw new UnsupportedOperationException(); 1685 | } 1686 | }; 1687 | } 1688 | 1689 | class UnrolledChunkedSeq extends ASeq implements IChunkedSeq, Counted { 1690 | private final IPersistentMap meta; 1691 | private final int offset; 1692 | 1693 | UnrolledChunkedSeq(IPersistentMap meta, int offset) { 1694 | this.offset = offset; 1695 | this.meta = meta; 1696 | } 1697 | 1698 | public IChunk chunkedFirst() { 1699 | return new ArrayChunk(toArray(), 0); 1700 | } 1701 | 1702 | public ISeq chunkedNext() { 1703 | return null; 1704 | } 1705 | 1706 | public ISeq chunkedMore() { 1707 | return PersistentList.EMPTY; 1708 | } 1709 | 1710 | public UnrolledChunkedSeq withMeta(IPersistentMap meta) { 1711 | return new UnrolledChunkedSeq(meta, offset); 1712 | } 1713 | 1714 | public Object first() { 1715 | return nth(offset); 1716 | } 1717 | 1718 | public ISeq next() { 1719 | if (offset < 5) { 1720 | return new UnrolledChunkedSeq(null, offset + 1); 1721 | } 1722 | return null; 1723 | } 1724 | 1725 | public int count() { 1726 | return 6 - offset; 1727 | } 1728 | } 1729 | 1730 | public ISeq seq() { 1731 | return new UnrolledChunkedSeq(null, 0); 1732 | } 1733 | } 1734 | 1735 | static class Transient extends AFn implements ITransientVector, Counted { 1736 | Object e0; 1737 | Object e1; 1738 | Object e2; 1739 | Object e3; 1740 | Object e4; 1741 | Object e5; 1742 | private int count; 1743 | private transient boolean edit = true; 1744 | 1745 | Transient() { 1746 | this.count = 0; 1747 | } 1748 | 1749 | Transient(Object e0) { 1750 | this.count = 1; 1751 | this.e0 = e0; 1752 | } 1753 | 1754 | Transient(Object e0, Object e1) { 1755 | this.count = 2; 1756 | this.e0 = e0; 1757 | this.e1 = e1; 1758 | } 1759 | 1760 | Transient(Object e0, Object e1, Object e2) { 1761 | this.count = 3; 1762 | this.e0 = e0; 1763 | this.e1 = e1; 1764 | this.e2 = e2; 1765 | } 1766 | 1767 | Transient(Object e0, Object e1, Object e2, Object e3) { 1768 | this.count = 4; 1769 | this.e0 = e0; 1770 | this.e1 = e1; 1771 | this.e2 = e2; 1772 | this.e3 = e3; 1773 | } 1774 | 1775 | Transient(Object e0, Object e1, Object e2, Object e3, Object e4) { 1776 | this.count = 5; 1777 | this.e0 = e0; 1778 | this.e1 = e1; 1779 | this.e2 = e2; 1780 | this.e3 = e3; 1781 | this.e4 = e4; 1782 | } 1783 | 1784 | Transient(Object e0, Object e1, Object e2, Object e3, Object e4, 1785 | Object e5) { 1786 | this.count = 6; 1787 | this.e0 = e0; 1788 | this.e1 = e1; 1789 | this.e2 = e2; 1790 | this.e3 = e3; 1791 | this.e4 = e4; 1792 | this.e5 = e5; 1793 | } 1794 | 1795 | private void ensureEditable() { 1796 | if (!edit) { 1797 | throw new IllegalAccessError( 1798 | "Transient used after persistent! call"); 1799 | } 1800 | } 1801 | 1802 | public int count() { 1803 | ensureEditable(); 1804 | return count; 1805 | } 1806 | 1807 | public ITransientVector conj(Object val) { 1808 | ensureEditable(); 1809 | if (count == 6) { 1810 | return new PersistentVector(7, 5, PersistentVector.EMPTY_NODE, 1811 | new Object[] { e0, e1, e2, e3, e4, e5, val }) 1812 | .asTransient(); 1813 | } 1814 | switch (++count) { 1815 | case 1: 1816 | e0 = val; 1817 | break; 1818 | case 2: 1819 | e1 = val; 1820 | break; 1821 | case 3: 1822 | e2 = val; 1823 | break; 1824 | case 4: 1825 | e3 = val; 1826 | break; 1827 | case 5: 1828 | e4 = val; 1829 | break; 1830 | case 6: 1831 | e5 = val; 1832 | break; 1833 | } 1834 | return this; 1835 | } 1836 | 1837 | public Object valAt(Object key, Object notFound) { 1838 | if (Util.isInteger(key)) { 1839 | return nth(((Number) key).intValue(), notFound); 1840 | } 1841 | return notFound; 1842 | } 1843 | 1844 | public Object valAt(Object key) { 1845 | if (Util.isInteger(key)) { 1846 | return nth(((Number) key).intValue()); 1847 | } 1848 | throw new IllegalArgumentException("Key must be integer"); 1849 | } 1850 | 1851 | public Object invoke(Object key) { 1852 | return valAt(key); 1853 | } 1854 | 1855 | public Object nth(int idx) { 1856 | if (idx >= 0 && idx < count) { 1857 | switch (idx) { 1858 | case 0: 1859 | return e0; 1860 | case 1: 1861 | return e1; 1862 | case 2: 1863 | return e2; 1864 | case 3: 1865 | return e3; 1866 | case 4: 1867 | return e4; 1868 | case 5: 1869 | return e5; 1870 | } 1871 | } 1872 | throw new IndexOutOfBoundsException(); 1873 | } 1874 | 1875 | public Object nth(int idx, Object notFound) { 1876 | if (idx >= 0 && idx < count) { 1877 | return nth(idx); 1878 | } 1879 | return notFound; 1880 | } 1881 | 1882 | public ITransientVector assoc(Object key, Object val) { 1883 | if (Util.isInteger(key)) { 1884 | return assocN(((Number) key).intValue(), val); 1885 | } 1886 | throw new IllegalArgumentException("Key must be integer"); 1887 | } 1888 | 1889 | public ITransientVector assocN(int idx, Object val) { 1890 | ensureEditable(); 1891 | if (idx >= 0 && idx < count) { 1892 | switch (idx) { 1893 | case 0: 1894 | e0 = val; 1895 | break; 1896 | case 1: 1897 | e1 = val; 1898 | break; 1899 | case 2: 1900 | e2 = val; 1901 | break; 1902 | case 3: 1903 | e3 = val; 1904 | break; 1905 | case 4: 1906 | e4 = val; 1907 | break; 1908 | case 5: 1909 | e5 = val; 1910 | break; 1911 | } 1912 | return this; 1913 | } else if (idx == count) { 1914 | return conj(val); 1915 | } 1916 | throw new IndexOutOfBoundsException(); 1917 | } 1918 | 1919 | public ITransientVector pop() { 1920 | ensureEditable(); 1921 | if (count == 0) { 1922 | throw new IllegalStateException("Can't pop empty vector"); 1923 | } else { 1924 | count--; 1925 | } 1926 | return this; 1927 | } 1928 | 1929 | public IPersistentVector persistent() { 1930 | ensureEditable(); 1931 | edit = false; 1932 | switch (count) { 1933 | case 0: 1934 | return EMPTY; 1935 | case 1: 1936 | return new Card1(e0); 1937 | case 2: 1938 | return new Card2(e0, e1); 1939 | case 3: 1940 | return new Card3(e0, e1, e2); 1941 | case 4: 1942 | return new Card4(e0, e1, e2, e3); 1943 | case 5: 1944 | return new Card5(e0, e1, e2, e3, e4); 1945 | case 6: 1946 | return new Card6(e0, e1, e2, e3, e4, e5); 1947 | } 1948 | throw new IllegalStateException(); 1949 | } 1950 | } 1951 | } 1952 | -------------------------------------------------------------------------------- /test/clj_tuple_test.clj: -------------------------------------------------------------------------------- 1 | (ns clj-tuple-test 2 | (:require 3 | [clojure.test :refer :all] 4 | [clj-tuple :as t] 5 | [criterium.core :as c] 6 | [collection-check :as check] 7 | [clojure.test.check.generators :as gen] 8 | [clojure.pprint :as pprint])) 9 | 10 | (deftest test-pprint-able 11 | (is (= (with-out-str (pprint/pprint [1 2 3])) 12 | (with-out-str (pprint/pprint (t/vector 1 2 3))))) 13 | (is (= (with-out-str (pprint/pprint {1 2 3 4})) 14 | (with-out-str (pprint/pprint (t/hash-map 1 2 3 4)))))) 15 | 16 | (deftest test-equivalency 17 | (check/assert-vector-like 1e3 (t/vector) gen/int) 18 | (check/assert-map-like 1e3 (t/hash-map) gen/int gen/int)) 19 | --------------------------------------------------------------------------------