   (let [tick (atom (dec v))]
     #(swap! tick inc)))
 
+(defn make-session-name
+  ""
+  ([]
+   (let [^java.text.SimpleDateFormat sdf (java.text.SimpleDateFormat. "yyyyMMddHHmmss")
+         date (java.util.Date.)]
+     [(.format sdf date) (to-hex (hash date))])))
+
+(def ^:dynamic *log-to-file* false)
+
+(let [session-name (atom nil) ; store session name as a current date
+      session-file (agent nil) ; logger Writer, created and used when *log-to-file* is true
+      session-cnt (atom nil) ; counter for next filename fn
+      ^java.text.SimpleDateFormat sdf (java.text.SimpleDateFormat. "yyyy-MM-dd HH:mm:ss")
+      nilfn (fn [_] nil)]
+
+  (defn close-session
+    ""
+    []
+    (when-not (nil? @session-file)
+      (send session-file (fn [^java.io.Writer o]
+                           (.flush o)
+                           (.close o)
+                           nil)))
+    (swap! session-name nilfn)
+    (swap! session-cnt nilfn))
+
+  (defn make-session
+    ""
+    []
+    (let [nname (make-session-name)]
+      (swap! session-name (fn [_] nname))
+
+      (when *log-to-file*
+        (let [fname (str "log/" (first nname) ".log")]
+          (io/make-parents fname)
+          (send session-file (fn [^java.io.Writer o]
+                               (do
+                                 (when-not (nil? o)
+                                   (.flush o)
+                                   (.close o))
+                                 (let [^java.io.Writer no (io/writer fname :append true)]
+                                   (.write no (str "Session id: " (second nname) "\n"))
+                                   no))))))
+
+      (swap! session-cnt (fn [_] (make-counter 0)))))
+
+  (defn log
+    ""
+    [s]
+    (when *log-to-file*
+      (if (nil? @session-file)
+        (do
+          (make-session)
+          (log s))
+        (let [to-log (str (.format sdf (java.util.Date.)) ": " s "\n")]
+          (send session-file (fn [^java.io.Writer o]
+                               (.write o to-log)
+                               (.flush o)
+                               o)))))
+    true)
+
+  (defn next-filename
+    ""
+    [prefix]
+    (if (nil? @session-name)
+      (do
+        (make-session)
+        (next-filename prefix))
+      (str prefix (second @session-name) "_" (format "%06d" (@session-cnt)))))
+
+  (defn get-session-name
+    ""
+    []
+    @session-name)
+
+
+)

  [f ^ints array idx]
  (let [v (aget array idx)]
    (aset array idx ^int (f v))))

(def ainc! (partial array-mutate! inc))
(def adec! (partial array-mutate! dec))

(defmacro amap!
  "Mutating version of amap"

(ns clojure2d.utils
  (:require [clojure.string :as s]
            [clojure2d.math :as m]
            [clojure.java.io :as io]))

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

(defn to-hex
  "return hex value of given number, padded with leading zeroes if given length"
  ([n]
   (format "%X" n))
  ([n pad]
   (format (str "%0" pad "X") n)))

(defmacro time-with-name
  "Evaluates expr and prints the time it took.  Returns the value of
