> The real hit would come with bignums, no? But as far as the routine > use of MOD goes we're probably talking about fixnums > 99% of the time.
Good point, I tried some more timings on various configurations: ; Currently submitted (soon to be dethroned) patch (defn mod1 "Modulus of num and div. Truncates toward negative infinity." [num div] (let [m (rem num div)] (if (or (zero? m) (pos? (* num div))) m (+ m div)))) ; verbatim from SBCL (defn mod2 "Modulus of num and div. Truncates toward negative infinity." [num div] (let [rem (rem num div)] (if (and (not (zero? rem)) (if (neg? div) (pos? num) (neg? num))) (+ rem div) rem))) ; comparing the signs, inverse logic to SBCL for slightly less function calls and common case first (defn mod3 "Modulus of num and div. Truncates toward negative infinity." [num div] (let [r (rem num div)] (if (or (= (pos? num) (pos? div)) (zero? r)) r (+ r div)))) ; use SBCL style if trick instead of comparing signs (defn mod4 "Modulus of num and div. Truncates toward negative infinity." [num div] (let [r (rem num div)] (if (or (if (pos? num) (pos? div) (neg? div)) (zero? r)) r (+ r div)))) user=> (time (dorun (map #(mod4 % 3) (range -9 9000000)) )) "Elapsed time: 13119.193251 msecs" user=> (time (dorun (map #(mod4 % 3) (range -9000000 9)) )) "Elapsed time: 14771.158608 msecs" user=> (time (dotimes [i 10000] (mod4 (bigint 1e1000M) (inc i)))) "Elapsed time: 3809.305116 msecs" user=> (time (dorun (map #(mod3 % 3) (range -9 9000000)) )) "Elapsed time: 13109.544278 msecs" user=> (time (dorun (map #(mod3 % 3) (range -9000000 9)) )) "Elapsed time: 15408.188226 msecs" user=> (time (dotimes [i 10000] (mod3 (bigint 1e1000M) (inc i)))) "Elapsed time: 3801.648725 msecs" user=> (time (dorun (map #(mod2 % 3) (range -9 9000000)) )) "Elapsed time: 14642.528284 msecs" user=> (time (dorun (map #(mod2 % 3) (range -9000000 9)) )) "Elapsed time: 16286.011241 msecs" user=> (time (dotimes [i 10000] (mod2 (bigint 1e1000M) (inc i)))) "Elapsed time: 3826.870597 msecs" user=> (time (dorun (map #(mod1 % 3) (range -9 9000000)) )) "Elapsed time: 14151.776571 msecs" user=> (time (dorun (map #(mod1 % 3) (range -9000000 9)) )) "Elapsed time: 14975.93798 msecs" user=> (time (dotimes [i 10000] (mod1 (bigint 1e1000M) (inc i)))) "Elapsed time: 3840.114813 msecs" Obviously these numbers are subject to variance etc... but the upshot seemed to be that there wasn't a substantial difference between any of the forms (I was especially surprised by bigint not playing a factor, perhaps my tests were flawed. In terms of style I think checking that the signs are equal is in some ways more obvious than multiplying, however = pos? pos? is arguably confusing also. The SBCL if nesting is neat too, so I really don't know which is best. Regards, Tim. --~--~---------~--~----~------------~-------~--~----~ 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 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 -~----------~----~----~----~------~----~------~--~---