Bit operations is one area where I'd actually recommend writing in Java before wrapping in Clojure for several reasons: 1) You can port / compare directly with canonical C implementation 2) You can be pretty sure of avoiding boxing / other overheads by sticking to Java primitive maths 3) Clojure still doesn't quite have the full range of bitwise functionality as far as I'm aware
Feel free to use any of my Java bitwise code, if helpful: https://github.com/mikera/mikera/blob/master/src/main/java/mikera/util/Bits.java On Tuesday, 24 February 2015 02:59:32 UTC+8, danl...@gmail.com wrote: > > So, much of the pain involved in handling UUID's correctly on the JVM > relates to the fact that there is no primitive unsigned numeric type > that can represent the full range of possible values of the msb and lsb. > Ie., we need to always deal with the unpleasant "am I negative?" approach > to > reading (writing) that 64th bit. To avoid the complexity of all the > edge cases, we encapsulate the basic primitives of working with > unsigned numbers entirely within the abstraction of "mask" and > "mask offset". Using these, we built the two fundamental bitwise > operations > that are used for most of the UUID calculation: ldb (load-byte) and > dpb (deposit-byte). > > This scrap of code from my clj-uuid.bitmop library is extremely useful for > working > with "unsigned" long/binary values (analogously to how one might using the > common-lisp > functions by the same name). And, it has been "good enough" to do pretty > well > so far in terms of performance. But I'm sure that there are gifted > binariticians > in the audience that can improve this. (Note, the namespace uses > ztellman/primitive-math > which changes the semantics of some arithmetic operations and some type > hinting. Also > some of the 'let's are there for that reason. It may be helpful to refer > to the link. > > ;;; > https://github.com/danlentz/clj-uuid/blob/master/src/clj_uuid/bitmop.clj > > > (defn ^long expt2 [^long pow] > (bit-set 0 pow)) > > (defn ^long mask [^long width ^long offset] > (if (< (+ width offset) 64) > (bit-shift-left (dec (bit-shift-left 1 width)) offset) > (let [x (expt2 offset)] > (bit-and-not -1 (dec ^long x))))) > > (declare ^long mask-offset ^long mask-width) > > (defn ^long mask-offset [^long m] > (cond > (zero? m) 0 > (neg? m) (- 64 ^long (mask-width m)) > :else (loop [c 0] > (if (pos? (bit-and 1 (bit-shift-right m c))) > c > (recur (inc c)))))) > > (defn ^long mask-width [^long m] > (if (neg? m) > (let [x (mask-width (- (inc m)))] > (- 64 ^long x)) > (loop [m (bit-shift-right m (mask-offset m)) c 0] > (if (zero? (bit-and 1 (bit-shift-right m c))) > c > (recur m (inc c)))))) > > (defn ^long ldb > "Load Byte" > [^long bitmask ^long num] > (let [off (mask-offset bitmask)] > (bit-and (>>> bitmask ^long off) > (bit-shift-right num off)))) > > (defn ^long dpb > "Deposit Byte" > [^long bitmask ^long num ^long value] > (bit-or (bit-and-not num bitmask) > (bit-and bitmask > (bit-shift-left value (mask-offset bitmask))))) > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en --- You received this message because you are subscribed to the Google Groups "Clojure" group. To unsubscribe from this group and stop receiving emails from it, send an email to clojure+unsubscr...@googlegroups.com. For more options, visit https://groups.google.com/d/optout.