         (error (str "Invalid dimension! Expecting dimension to be between inclusive 0 and "
                     (dec ndims) ", but got " dimension-number "instead!"))
         (aget shape dimension-number)))))
+
+(extend-protocol mp/PCoercion
+  NDArray
+  (coerce-param [m param]
+    (cond (instance? NDArray param)
+          param
+          (number? param) (double param)
+          :else
+          (mp/construct-matrix m param))))
 
 (defn- all?
   "returns true if every element in coll (or the mapped version, if 

(defmethod construct-matrix Number
  [data]
  (double data))
(defmethod construct-matrix :default
  [data]
  (let [ndims (m/dimensionality data)
          shape (m/shape data)]

      (count indexes) [m m] indexes
      (.set m (long-array indexes) v))))

(defmacro with-coerce-param [bindings & body]
  (assert (= (count bindings) 2))
  (assert (symbol? (first bindings)))
  (let [param-sym (first bindings)
        param-val (second bindings)]
    `(cond (number? ~param-val)
           (let [~param-sym (double ~param-val)]
             ~@body)
           (instance? NDArray ~param-val)
           (let [~(vary-meta param-sym assoc :tag `NDArray) ~param-val]
             ~@body)
           ; unkown type, we need to coerce it to NDArray
           :else
           (let [~(vary-meta param-sym assoc :tag `NDArray)
                 (mp/coerce-param (gpu.matrix.NDArray/sample) ~param-val)]
             ~@body))))

(extend-protocol mp/PMatrixAdd
  NDArray
  (matrix-add [^NDArray m a]
    (with-coerce-param [a a] (.add m a)))
  (matrix-sub [^NDArray m a]
    (with-coerce-param [a a] (.sub m a))))

(extend-protocol mp/PMatrixMultiply
  NDArray
  (element-multiply [^NDArray m a]
    (with-coerce-param [a a] (.mul m a))))

(extend-protocol mp/PMatrixDivide
  NDArray
  (element-divide [^NDArray m a]
    (with-coerce-param [a a] (.div m a))))

