<commit_before>#+SETUPFILE: ../../src/setup.org

* Namespace: thi.ng.geom.core.matrix

** Matrix macros

Some matrix operations (e.g. computing the determinant or inverse of
matrix) require quite long mathematical expressions and we therefore
define some macros to simplify them.

#+BEGIN_SRC clojure :tangle ../babel/src/cljx/thi/ng/geom/core/macros.clj :mkdirp yes :padline no
  (ns thi.ng.geom.core.macros
    (:require [thi.ng.macromath.core :as mm]))

  (defmacro det-item
    [a b c d, e f g h, i j k l, m n o p]
    `(+ (mm/sub
         (mm/mul ~a ~b ~c ~d)
         (mm/mul ~e ~f ~g ~h)
         (mm/mul ~i ~j ~k ~l))
        (mm/mul ~m ~n ~o ~p)))

  (defmacro inv-item
    [a b c d e f g]
    `(* (mm/msubadd ~a ~b ~c ~d ~e ~f) ~g))
#+END_SRC

** Protocol helpers
#+BEGIN_SRC clojure :noweb-ref proto-helpers
  ,#+clj
  (defn- hash-coll*
    [coll]
    (reduce
     #(-> % (unchecked-multiply-int 31) (unchecked-add-int (hash %2)))
     1 coll))
#+END_SRC
** Matrix implementations
*** 3x2 Matrix (Affine 2D transform)
#+BEGIN_SRC clojure :noweb-ref mat32
  (deftype Matrix32
    #+clj  [^double m00 ^double m01 ^double m02
            ^double m10 ^double m11 ^double m12
            ^:unsynchronized-mutable _hasheq
            ^:unsynchronized-mutable _hashc]
    #+cljs [m00 m01 m02 m10 m11 m12
            ^:mutable _hasheq]
#+END_SRC

**** Clojure protocols
#+BEGIN_SRC clojure :noweb-ref mat32
  ,#+clj java.util.Collection
  ,#+clj clojure.lang.IPersistentCollection
  ,#+clj clojure.lang.IPersistentVector
  ,#+clj clojure.lang.ISeq
  ,#+clj clojure.lang.Seqable
  ,#+clj clojure.lang.Sequential
  ,#+clj clojure.lang.IHashEq
  ,#+cljs ISequential
  ,#+clj (empty [_] (err/unsupported!))

  ,#+cljs ICounted
  (#+clj count #+cljs -count [_] 6)

  ,#+cljs ISeqable
  (#+clj seq #+cljs -seq [_] _)

  ,#+cljs ISeq
  (#+clj more #+cljs -rest [_] (next _))
  (#+clj first #+cljs -first [_] m00)
  ,#+cljs INext
  (#+clj next #+cljs -next [_] (seq [m01 m02 m10 m11 m12]))

  ,#+cljs ICollection
  ,#+clj  (cons [_ x] (VectorSeq. 0 7 [m00 m01 m02 m10 m11 m12 x] nil))
  ,#+cljs (-conj[_ x] [m00 m01 m02 m10 m11 m12 x])

  ,#+cljs IIndexed
  (#+clj nth #+cljs -nth [_ k]
         (case (int k)
           0 m00 1 m01 2 m02 3 m10 4 m11 5 m12
           (err/illegal-arg! k)))
  (#+clj nth #+cljs -nth [_ k nf]
         (case (int k) 0 m00 1 m01 2 m02 3 m10 4 m11 5 m12 nf))

  ,#+cljs IEquiv
  (#+clj equiv #+cljs -equiv [_ o]
         (and
          (sequential? o)
          (== 6 (count o))
          (every? #(= (% 0) (% 1)) (map vector _ o))))

  ,#+cljs IHash
  (#+clj hasheq #+cljs -hash  [_]
         (if (== -1 _hasheq)
           (set! _hasheq (hash-ordered-coll _))
           _hasheq))

  ,#+clj (hashCode [_] (if (== -1 _hashc) (set! _hashc (hash-coll* _)) _hashc))

  ,#+clj (equals
         [_ o]
         (and
          (sequential? o)
          (== 6 (count o))
          (every? #(clojure.lang.Util/equals (% 0) (% 1)) (map vector _ o))))
  ,#+clj (isEmpty
         [_] false)
  ,#+clj (iterator
         [_] (.iterator ^java.util.Collection (list m00 m01 m02 m10 m11 m12)))
  ,#+clj (toArray
         [_] (object-array _))
  ,#+clj (size [_] 6)
  ,#+clj (length [_] 6)

  Object
  (toString
   [_] (apply str (concat "[" (interpose \space _) "]")))
#+END_SRC

**** PMathOps
#+BEGIN_SRC clojure :noweb-ref mat32
  g/PMathOps
  (*
   [_ m]
   (let [m ^Matrix32 m]
     (Matrix32.
      (mm/madd m00 (.-m00 m) m01 (.-m10 m))
      (mm/madd m00 (.-m01 m) m01 (.-m11 m))
      (mm/madd m00 (.-m02 m) m01 (.-m12 m) m02)
      (mm/madd m10 (.-m00 m) m11 (.-m10 m))
      (mm/madd m10 (.-m01 m) m11 (.-m11 m))
      (mm/madd m10 (.-m02 m) m11 (.-m12 m) m12)
      -1 #+clj -1)))
#+END_SRC

**** PDeltaEquals
#+BEGIN_SRC clojure :noweb-ref mat32
  m/PDeltaEquals
  (delta=
   [_ m] (m/delta= _ m *eps*))
  (delta=
   [_ m eps]
   (and (sequential? m)
        (== 6 (count m))
        (m/delta= m00 (nth m 0) eps)
        (m/delta= m01 (nth m 1) eps)
        (m/delta= m02 (nth m 2) eps)
        (m/delta= m10 (nth m 3) eps)
        (m/delta= m11 (nth m 4) eps)
        (m/delta= m12 (nth m 5) eps)))
#+END_SRC
**** PDeterminant
#+BEGIN_SRC clojure :noweb-ref mat32
  g/PDeterminant
  (determinant
   [_] (mm/msub m00 m11 m01 m10))
#+END_SRC

**** PInvert
#+BEGIN_SRC clojure :noweb-ref mat32
  g/PInvert
  (invert
   [_]
   (let [d (g/determinant _)]
     (when-not (zero? d)
       (Matrix32.
        (/ m11 d) (- (/ m01 d)) (/ (mm/msub m01 m12 m11 m02) d)
        (- (/ m10 d)) (/ m00 d) (/ (mm/msub m10 m02 m00 m12) d)
        -1 #+clj -1))))
#+END_SRC

**** PRotate, PScale, PTranslate, PTransform
#+BEGIN_SRC clojure :noweb-ref mat32
  g/PRotate
  (rotate
   [_ theta]
   (let [s (Math/sin theta), c (Math/cos theta)]
     (g/* _ (Matrix32. c (- s) 0.0, s c 0.0 -1 #+clj -1))))

  g/PScale
  (scale
   [_ s]
   (g/* _ (Matrix32.
             (if (number? s) s (s 0)) 0.0 0.0
             0.0 (if (number? s) s (s 1)) 0.0
             -1 #+clj -1)))
  (scale
   [_ sx sy]
   (if (number? sx)
     (if (number? sy)
       (g/* _ (Matrix32. sx 0.0 0.0, 0.0 sy 0.0 -1 #+clj -1))
       (g/* _ (Matrix32. (* sx (sy 0)) 0.0 0.0, 0.0 (* sx (sy 1)) 0.0 -1 #+clj -1)))
     (if (number? sy)
       (g/* _ (Matrix32. (* sy (sx 0)) 0.0 0.0, 0.0 (* sy (sx 1)) 0.0 -1 #+clj -1))
       (g/* _ (Matrix32. (* (sx 0) (sy 0)) 0.0 0.0, 0.0 (* (sx 1) (sy 1)) 0.0 -1 #+clj -1)))))

  g/PShear<commit_msg>add PTranspose impl for Matrix32<commit_after>#+SETUPFILE: ../../src/setup.org

* Namespace: thi.ng.geom.core.matrix

** Matrix macros

Some matrix operations (e.g. computing the determinant or inverse of
matrix) require quite long mathematical expressions and we therefore
define some macros to simplify them.

#+BEGIN_SRC clojure :tangle ../babel/src/cljx/thi/ng/geom/core/macros.clj :mkdirp yes :padline no
  (ns thi.ng.geom.core.macros
    (:require [thi.ng.macromath.core :as mm]))

  (defmacro det-item
    [a b c d, e f g h, i j k l, m n o p]
    `(+ (mm/sub
         (mm/mul ~a ~b ~c ~d)
         (mm/mul ~e ~f ~g ~h)
         (mm/mul ~i ~j ~k ~l))
        (mm/mul ~m ~n ~o ~p)))

  (defmacro inv-item
    [a b c d e f g]
    `(* (mm/msubadd ~a ~b ~c ~d ~e ~f) ~g))
#+END_SRC

** Protocol helpers
#+BEGIN_SRC clojure :noweb-ref proto-helpers
  ,#+clj
  (defn- hash-coll*
    [coll]
    (reduce
     #(-> % (unchecked-multiply-int 31) (unchecked-add-int (hash %2)))
     1 coll))
#+END_SRC
** Matrix implementations
*** 3x2 Matrix (Affine 2D transform)
#+BEGIN_SRC clojure :noweb-ref mat32
  (deftype Matrix32
    #+clj  [^double m00 ^double m01 ^double m02
            ^double m10 ^double m11 ^double m12
            ^:unsynchronized-mutable _hasheq
            ^:unsynchronized-mutable _hashc]
    #+cljs [m00 m01 m02 m10 m11 m12
            ^:mutable _hasheq]
#+END_SRC

**** Clojure protocols
#+BEGIN_SRC clojure :noweb-ref mat32
  ,#+clj java.util.Collection
  ,#+clj clojure.lang.IPersistentCollection
  ,#+clj clojure.lang.IPersistentVector
  ,#+clj clojure.lang.ISeq
  ,#+clj clojure.lang.Seqable
  ,#+clj clojure.lang.Sequential
  ,#+clj clojure.lang.IHashEq
  ,#+cljs ISequential
  ,#+clj (empty [_] (err/unsupported!))

  ,#+cljs ICounted
  (#+clj count #+cljs -count [_] 6)

  ,#+cljs ISeqable
  (#+clj seq #+cljs -seq [_] _)

  ,#+cljs ISeq
  (#+clj more #+cljs -rest [_] (next _))
  (#+clj first #+cljs -first [_] m00)
  ,#+cljs INext
  (#+clj next #+cljs -next [_] (seq [m01 m02 m10 m11 m12]))

  ,#+cljs ICollection
  ,#+clj  (cons [_ x] (VectorSeq. 0 7 [m00 m01 m02 m10 m11 m12 x] nil))
  ,#+cljs (-conj[_ x] [m00 m01 m02 m10 m11 m12 x])

  ,#+cljs IIndexed
  (#+clj nth #+cljs -nth [_ k]
         (case (int k)
           0 m00 1 m01 2 m02 3 m10 4 m11 5 m12
           (err/illegal-arg! k)))
  (#+clj nth #+cljs -nth [_ k nf]
         (case (int k) 0 m00 1 m01 2 m02 3 m10 4 m11 5 m12 nf))

  ,#+cljs IEquiv
  (#+clj equiv #+cljs -equiv [_ o]
         (and
          (sequential? o)
          (== 6 (count o))
          (every? #(= (% 0) (% 1)) (map vector _ o))))

  ,#+cljs IHash
  (#+clj hasheq #+cljs -hash  [_]
         (if (== -1 _hasheq)
           (set! _hasheq (hash-ordered-coll _))
           _hasheq))

  ,#+clj (hashCode [_] (if (== -1 _hashc) (set! _hashc (hash-coll* _)) _hashc))

  ,#+clj (equals
         [_ o]
         (and
          (sequential? o)
          (== 6 (count o))
          (every? #(clojure.lang.Util/equals (% 0) (% 1)) (map vector _ o))))
  ,#+clj (isEmpty
         [_] false)
  ,#+clj (iterator
         [_] (.iterator ^java.util.Collection (list m00 m01 m02 m10 m11 m12)))
  ,#+clj (toArray
         [_] (object-array _))
  ,#+clj (size [_] 6)
  ,#+clj (length [_] 6)

  Object
  (toString
   [_] (apply str (concat "[" (interpose \space _) "]")))
#+END_SRC

**** PMathOps
#+BEGIN_SRC clojure :noweb-ref mat32
  g/PMathOps
  (*
   [_ m]
   (let [m ^Matrix32 m]
     (Matrix32.
      (mm/madd m00 (.-m00 m) m01 (.-m10 m))
      (mm/madd m00 (.-m01 m) m01 (.-m11 m))
      (mm/madd m00 (.-m02 m) m01 (.-m12 m) m02)
      (mm/madd m10 (.-m00 m) m11 (.-m10 m))
      (mm/madd m10 (.-m01 m) m11 (.-m11 m))
      (mm/madd m10 (.-m02 m) m11 (.-m12 m) m12)
      -1 #+clj -1)))
#+END_SRC

**** PDeltaEquals
#+BEGIN_SRC clojure :noweb-ref mat32
  m/PDeltaEquals
  (delta=
   [_ m] (m/delta= _ m *eps*))
  (delta=
   [_ m eps]
   (and (sequential? m)
        (== 6 (count m))
        (m/delta= m00 (nth m 0) eps)
        (m/delta= m01 (nth m 1) eps)
        (m/delta= m02 (nth m 2) eps)
        (m/delta= m10 (nth m 3) eps)
        (m/delta= m11 (nth m 4) eps)
        (m/delta= m12 (nth m 5) eps)))
#+END_SRC
**** PDeterminant
#+BEGIN_SRC clojure :noweb-ref mat32
  g/PDeterminant
  (determinant
   [_] (mm/msub m00 m11 m01 m10))
#+END_SRC

**** PInvert
#+BEGIN_SRC clojure :noweb-ref mat32
  g/PInvert
  (invert
   [_]
   (let [d (g/determinant _)]
     (when-not (zero? d)
       (Matrix32.
        (/ m11 d) (- (/ m01 d)) (/ (mm/msub m01 m12 m11 m02) d)
        (- (/ m10 d)) (/ m00 d) (/ (mm/msub m10 m02 m00 m12) d)
        -1 #+clj -1))))
#+END_SRC

**** PTranspose
#+BEGIN_SRC clojure :noweb-ref mat32
  g/PTranspose
  (transpose
   [_]
   (Matrix32. m00 m10 m01 m11 m02 m12 -1 #+clj -1))
#+END_SRC

**** PRotate, PScale, PTranslate, PTransform
#+BEGIN_SRC clojure :noweb-ref mat32
  g/PRotate
  (rotate
   [_ theta]
   (let [s (Math/sin theta), c (Math/cos theta)]
     (g/* _ (Matrix32. c (- s) 0.0, s c 0.0 -1 #+clj -1))))

  g/PScale
  (scale
   [_ s]
   (g/* _ (Matrix32.
             (if (number? s) s (s 0)) 0.0 0.0
             0.0 (if (number? s) s (s 1)) 0.0
             -1 #+clj -1)))
  (scale
   [_ sx sy]
   (if (number? sx)
     (if (number? sy)
       (g/* _ (Matrix32. sx 0.0 0.0, 0.0 sy 0.0 -1 #+clj -1))
       (g/* _ (Matrix32. (* sx (sy 0)) 0.0 0.0, 0.0 (* sx (sy 1)) 0.0 -1 #+clj -1)))
     (if (number? sy)
       (g/* _ (Matrix32. (* sy (sx 0)) 0.0 0.0, 0.0 (* sy (sx 1)) 0.0 -1 #+clj -1))
       (g/* _ (Matrix32. (* (sx 0) (sy 0)) 0.0 0.0, 0.0 (* (sx 1) (sy 1)) 0.0 -1 #+clj -1)))))

  g/PShear
{'fraction_non_alphanumeric': 0.18529304696032034, 'fraction_numerical': 0.06279577721150346, 'mean_word_length': 2.2028563101136696, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 5, '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': '4004439', 'n_tokens_mistral': 5420, 'n_tokens_neox': 4808, 'n_words': 1371}