                       (vs ds))
                 w))
 
-(defn walk [ds D & idxs]
-  "Returns the result of applying the D-symbol operators on ds with the
-   given indices in order, starting with the element D. If the result of
-   any step is undefined, nil is returned."
-  (reduce #(s ds %2 %1) D idxs))
-
-(defn r [ds i j D]
-  (loop [n 1, E D]
-    (when-let [F (walk ds E i j)]
-      (if (= F D)
-        n
-        (recur (inc n) F)))))
-
-(defn m [ds i j D]
-  (let [v (v ds i j D)
-        r (r ds i j D)]
-    (when (and v r) (* v r))))
-
-(defn chain-end [ds D i j]
-  "Returns the result of alternately applying operators indexed i and j,
-   starting with the element D, until the end of the chain is reached.
-   In case of a cycle, nil is returned."
-  (loop [E (walk ds D i)]
-    (let [E* (walk ds E j)]
-      (cond
-        (nil? E*) E
-        (= E E*) E
-        (= D E*) nil
-        :else (recur (walk ds E j i))))))
-
-(defn pretty-traversal [ds indices seeds]
-  (let [stacks (map #(vector % ()) (take 2 indices))
-        queues (map #(vector % empty-queue) (drop 2 indices))
-        as-root #(vector % :root)
-        unseen (fn [i seen bag] (pop-while #(seen [% i]) bag))
-        pop-seen #(for [[i ys] %1] (vector i (unseen i %2 ys)))
-        push-neighbors #(for [[i ys] %1] (vector i (conj ys %2)))]
-    ((fn collect [seeds-left todo seen]
-       (let [seeds-left (drop-while (comp seen as-root) seeds-left)
-             todo (pop-seen todo seen)
-             [i todo-for-i] (->> todo (filter (comp seq second)) first)]
-         (cond
-           (seq todo-for-i)
-           (let [D (first todo-for-i)
-                 Di (walk ds D i)
-                 todo (if Di (doall (push-neighbors todo Di)) todo)
-                 seen (conj seen (as-root Di) [D i] [Di i])]
-             (lazy-seq (cons [D i Di] (collect seeds-left todo seen))))
-           (seq seeds-left)
-           (let [D (first seeds-left)
-                 todo (doall (push-neighbors todo D))
-                 seen (conj seen (as-root D))]
-             (lazy-seq
-               (cons (as-root D) (collect (rest seeds-left) todo seen))))
-           :else
-           ())))
-      (seq seeds) (doall (concat stacks queues)) #{})))
-
-(defn orbit-reps
-  ([ds indices seeds]
-    (for [[D i] (pretty-traversal ds indices seeds) :when (= :root i)] D))
-  ([ds indices]
-    (orbit-reps ds indices (elements ds))))
-
-(defn orbit [ds indices seed]
-  (for [[D i] (pretty-traversal ds indices [seed])] D))
-
-(defn orbit-loopless? [ds indices D]
-  (empty? (for [[D i] (pretty-traversal ds indices [D])
-                :when (and (not= i :root) (or (nil? D) (= D (walk ds D i))))]
-            D)))
-
-(defn curvature
-  ([ds default-v]
-    (reduce +
-            (- (size ds))
-            (for [[i j] [[0 1] [0 2] [1 2]]
-                  :let [s #(if (orbit-loopless? ds [i j] %) 2 1)
-                        v #(or (v ds i j %) default-v)]
-                  D (orbit-reps ds [i j])]
-              (/ (s D) (v D)))))
-  ([ds]
-    (curvature ds 0)))
 
 ;; === Tests
 
-(deftest add-elements
-  (is (= (dsconj (DSymbol. 0 0 {} {}) 2)
+(deftest adding-elements
+  (is (= (dsconj (DSymbol. 0 0 {} {})
+                 2)
          (DSymbol. 0 2 {} {}))))
 
 (deftest removing-elements
   (is (= (dsdisj (DSymbol. 2 2
                            {0 {1 1, 2 2} 1 {1 2, 2 1} 2 {1 2, 2 1}}
-                           {0 {1 4, 2 4} 1 {1 4, 2 4}}) 2)
+                           {0 {1 4, 2 4} 1 {1 4, 2 4}})
+                 2)
          (DSymbol. 2 1 {0 {1 1} 1 {} 2 {}} {0 {1 4} 1 {1 4}}))))
 
 (deftest gluing
-  (is (= (glue (DSymbol. 0 0 {} {}) 2 1 2)
+  (is (= (glue (DSymbol. 0 0 {} {})
+               2 1 2)
          (DSymbol. 2 2 {2 {1 2 2 1}} {}))))
+
+(deftest spinning
+  (is (= (spin (DSymbol. 2 2
+                         {0 {1 1, 2 2} 1 {1 2, 2 1} 2 {1 2, 2 1}}
+                         {})
+               0 1 1 3)
+         (DSymbol. 2 2
+                   {0 {1 1, 2 2} 1 {1 2, 2 1} 2 {1 2, 2 1}}
+                   {0 {1 3, 2 3}})))
+  (is (= (unspin (DSymbol. 2 2
+                           {0 {1 1, 2 2} 1 {1 2, 2 1} 2 {1 2, 2 1}}
+                           {0 {1 4, 2 4} 1 {1 4, 2 4}})
+                 0 1 2)
+         (DSymbol. 2 2
+                   {0 {1 1, 2 2} 1 {1 2, 2 1} 2 {1 2, 2 1}}
+                   {1 {1 4, 2 4}})))
+  )

             [i (into {} (for [D (elements ds)
                               :when (v ds i (inc i) D)]
                           [D (v ds i (inc i) D)]))])))

(deftype DSymbol [dim size s# v#]
  IDSymbol

(ns org.gavrog.clojure.delaney
  (:use (clojure [test])
        (org.gavrog.clojure [util :only [empty-queue pop-while unique]]))
  (:import (org.gavrog.joss.dsyms.basic DelaneySymbol)
           (java.io Writer)))

