<commit_before>(ns algorithms-clj.perf-fibo
  (:require
    [criterium.core :as perf]))

(set! *unchecked-math* true)
(set! *warn-on-reflection* true)

(defn fibo-iterate
  [n]
  (let [next-fib (fn [[a b]] [b (+ a b)])
        fibs (iterate next-fib [0N 1N])]
    (first (nth fibs n))))

(defn fibo-lazy-seq
  [n]
  (letfn [(fibs [a b] (cons a (lazy-seq (fibs b (+ a b)))))]
    (nth (fibs 0N 1N) n)))

(defn fibo-recur
  [n]
  (loop [curr 0N
         next 1N
         iter n]
    (if-not (zero? iter)
      (recur next (+ curr next) (dec iter))
      curr)))

(defn fibo-imperative
  [n]
  (with-local-vars [curr 0N
                    next 1N
                    iter n]
    (while (> @iter 0)
      (let [nnext (+ @curr @next)]
        (var-set curr @next)
        (var-set next nnext)
        (var-set iter (dec @iter))
        ))
    @curr))

(defn fibo-volatile
  [n]
  (let [curr (volatile! 0N)
        next (volatile! 1N)
        iter (volatile! n)]
    (while (> @iter 0)
      (let [nnext (+ @curr @next)]
        (vreset! curr @next)
        (vreset! next nnext)
        (vswap! iter dec)
        ))
    @curr))

(defn fibo-lazy-cat
  ; TODO - This is weird... it should be a var, but then...
  [n]
  (letfn [(fibs [] (lazy-cat [0N 1N] (map + (rest (fibs)) (fibs))))]
    (nth (fibs) n)))

;; This gets really weird now...

(defprotocol Advance
  (advance [this n]))

(deftype FiboType [^:unsynchronized-mutable curr
                   ^:unsynchronized-mutable next]
  Advance
  (advance [_ n]
    (loop [n n]
      (if-not (zero? n)
        (let [nnext (+ curr next)]
          (set! curr next)
          (set! next nnext)
          (recur (dec n))
          )))
    curr))

(defn fibo-with-type
  [n]
  (advance (FiboType. 0N 1N) n))

(defn run-benches
  []
  (let [n 1000]
    (perf/quick-bench (fibo-iterate n))
    (perf/quick-bench (fibo-lazy-seq n))
    (perf/quick-bench (fibo-recur n))
    (perf/quick-bench (fibo-imperative n))
    (perf/quick-bench (fibo-volatile n))
    (perf/quick-bench (fibo-with-type n))
    #_(perf/quick-bench (fibo-lazy-cat n))
    ))
<commit_msg>perf tests<commit_after>(ns algorithms-clj.perf-fibo
  (:require
    [criterium.core :as perf]))

(set! *unchecked-math* true)
(set! *warn-on-reflection* true)

(defn fibo-iterate
  [n]
  (let [next-fib (fn [[a b]] [b (+ a b)])
        fibs (iterate next-fib [0N 1N])]
    (first (nth fibs n))))

(defn fibo-lazy-seq
  [n]
  (letfn [(fibs [a b] (cons a (lazy-seq (fibs b (+ a b)))))]
    (nth (fibs 0N 1N) n)))

(defn fibo-recur
  [n]
  (loop [curr 0N
         next 1N
         iter n]
    (if-not (zero? iter)
      (recur next (+ curr next) (dec iter))
      curr)))

(defn fibo-imperative
  [n]
  (with-local-vars [curr 0N
                    next 1N
                    iter n]
    (while (> @iter 0)
      (let [nnext (+ @curr @next)]
        (var-set curr @next)
        (var-set next nnext)
        (var-set iter (dec @iter))
        ))
    @curr))

(defn fibo-volatile
  [n]
  (let [curr (volatile! 0N)
        next (volatile! 1N)
        iter (volatile! n)]
    (while (> @iter 0)
      (let [nnext (+ @curr @next)]
        (vreset! curr @next)
        (vreset! next nnext)
        (vswap! iter dec)
        ))
    @curr))

(defn fibo-lazy-cat
  ; TODO - This is weird... it should be a var, but then...
  [n]
  (letfn [(fibs [] (lazy-cat [0N 1N] (map + (rest (fibs)) (fibs))))]
    (nth (fibs) n)))

;; This gets really weird now...

(defprotocol Advance
  (advance [this n]))

(deftype FiboType [^:unsynchronized-mutable curr
                   ^:unsynchronized-mutable next]
  Advance
  (advance [_ n]
    (loop [n n]
      (if-not (zero? n)
        (let [nnext (+ curr next)]
          (set! curr next)
          (set! next nnext)
          (recur (dec n))
          )))
    curr))

(defn fibo-with-type
  [n]
  (advance (FiboType. 0N 1N) n))

; -----------------------------------------------

(defn run-bench*
  [name f n]
  (println name ": ------------------------------")
  (perf/quick-bench (f n)))

(defmacro run-bench
  [[f n]]
  `(run-bench* ~(name f) ~f ~n))

(defn run-benches
  []
  (let [n 1000]
    (run-bench (fibo-iterate n))
    (run-bench (fibo-lazy-seq n))
    (run-bench (fibo-recur n))
    (run-bench (fibo-imperative n))
    (run-bench (fibo-volatile n))
    (run-bench (fibo-with-type n))
    #_(perf/quick-bench (fibo-lazy-cat n))
    ))

{'fraction_non_alphanumeric': 0.18814373998626688, 'fraction_numerical': 0.009155413138017853, 'mean_word_length': 1.9407806191117092, 'pattern_counts': {'":': 1, '<': 3, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5433401', 'n_tokens_mistral': 1829, 'n_tokens_neox': 1733, 'n_words': 476}