;; -*-theme-d-*-

;; Copyright (C) 2014  Tommi Höynälänmaa
;; Distributed under GNU Lesser General Public License version 3,
;; see file doc/LGPL-3.


(define-interface (standard-library matrix)


  (import (standard-library core))


  (define-param-class :matrix (%number) <object> #f #f #t module ()
    ((rows <integer> public hidden)
     (columns <integer> public hidden)
     (contents (:mutable-value-vector %number) public module)))


  (define-param-class :diagonal-matrix (%number) <object> #f #f #t module ()
    ((len <integer> public hidden)
     (contents (:mutable-value-vector %number) public module)))

  (declare matrix
	   (:param-proc (%number)
		     ((:uniform-list (:uniform-list %number)))
		     (:matrix %number)
		     (pure)))

  (declare make-matrix
	   (:param-proc (%number) (<integer> <integer> %number)
			(:matrix %number)
			(pure)))

  (declare column-vector
	   (:param-proc (%number)
		     ((:uniform-list %number))
		     (:matrix %number)
		     (pure)))

  (declare make-column-vector
	   (:param-proc (%number) (<integer> %number)
			(:matrix %number)
			(pure)))

  (declare row-vector
	   (:param-proc (%number)
		     ((:uniform-list %number))
		     (:matrix %number)
		     (pure)))

  (declare make-row-vector
	   (:param-proc (%number) (<integer> %number)
			(:matrix %number)
			(pure)))

  (declare diagonal-matrix
	   (:param-proc (%number)
			((:uniform-list %number))
			(:diagonal-matrix %number)
			(pure)))

  (declare make-diagonal-matrix
	   (:param-proc (%number) (<integer> %number)
			(:diagonal-matrix %number)
			(pure)))

  (declare matrix-copy
	   (:param-proc (%number)
			((:matrix %number))
			(:matrix %number)
			(pure)))

  (declare diagonal-matrix-copy
	   (:param-proc (%number)
			((:diagonal-matrix %number))
			(:diagonal-matrix %number)
			(pure)))

  (declare-method number-of-rows 
		  (:param-proc (%number)
			       ((:matrix %number))
			       <integer>
			       (pure)))

  (declare-method number-of-rows 
		  (:param-proc (%number)
			       ((:diagonal-matrix %number))
			       <integer>
			       (pure)))

  (declare-method number-of-columns
		  (:param-proc (%number)
			       ((:matrix %number))
			       <integer>
			       (pure)))

  (declare-method number-of-columns
		  (:param-proc (%number)
			       ((:diagonal-matrix %number))
			       <integer>
			       (pure)))

  (declare-method matrix-ref
		  (:param-proc (%number)
			       ((:matrix %number) <integer> <integer>)
			       %number (pure)))

  (declare-method matrix-ref
		  (:param-proc (%number)
			       ((:diagonal-matrix %number) <integer> <integer>)
			       %number (pure)))

  (declare-method matrix-set!
		  (:param-proc (%number)
			       ((:matrix %number) <integer> <integer> %number)
			       <none> (nonpure)))

  (declare-method matrix-set!
		  (:param-proc (%number)
			       ((:diagonal-matrix %number) <integer> <integer> %number)
			       <none> (nonpure)))

  (declare diagonal-matrix-ref
	   (:param-proc (%number)
			((:diagonal-matrix %number) <integer>)
			%number (pure)))

  (declare diagonal-matrix-set!
	   (:param-proc (%number)
			((:diagonal-matrix %number) <integer> %number)
			<none> (nonpure)))

  (declare matrix=
	   (:param-proc (%number)
			((:matrix %number) (:matrix %number)) <boolean> pure))
  
  (declare diagonal-matrix=
	   (:param-proc (%number)
			((:diagonal-matrix %number) (:diagonal-matrix %number))
			<boolean> pure))

  (declare matrix-diagonal-matrix=
	   (:param-proc (%number)
			((:matrix %number) (:diagonal-matrix %number))
			<boolean> pure))

  (declare diagonal-matrix-matrix=
	   (:param-proc (%number)
			((:diagonal-matrix %number) (:matrix %number))
			<boolean> pure))

  (declare-method =
		  (:param-proc (%number)
			       ((:matrix %number) (:matrix %number))
			       <boolean> pure))
  
  (declare-method =
		  (:param-proc (%number)
			       ((:diagonal-matrix %number)
				(:diagonal-matrix %number))
			       <boolean> pure))

  (declare-method =
		  (:param-proc (%number)
			       ((:matrix %number) (:diagonal-matrix %number))
			       <boolean> pure))

  (declare-method =
		  (:param-proc (%number)
			       ((:diagonal-matrix %number) (:matrix %number))
			       <boolean> pure))

  (declare matrix*
	   (:param-proc (%number)
			((:matrix %number) (:matrix %number))
			(:matrix %number)
			(pure)))

  (declare diagonal-matrix*
	   (:param-proc (%number)
			((:diagonal-matrix %number) (:diagonal-matrix %number))
			(:diagonal-matrix %number)
			(pure)))

  (declare-method *
		  (:param-proc (%number)
			       ((:matrix %number) (:matrix %number))
			       (:matrix %number)
			       (pure)))

  (declare-method *
		  (:param-proc (%number)
			       (%number (:matrix %number))
			       (:matrix %number)
			       (pure)))

  (declare-method *
		  (:param-proc (%number)
			       ((:matrix %number) %number)
			       (:matrix %number)
			       (pure)))

  (declare-method *
		  (:param-proc (%number)
			       (%number (:diagonal-matrix %number))
			       (:diagonal-matrix %number)
			       (pure)))

  (declare-method *
		  (:param-proc (%number)
			       ((:diagonal-matrix %number) %number)
			       (:diagonal-matrix %number)
			       (pure)))

  (declare-method *
		  (:param-proc (%number)
			       ((:matrix %number) (:diagonal-matrix %number))
			       (:matrix %number)
			       (pure)))

  (declare-method *
		  (:param-proc (%number)
			       ((:diagonal-matrix %number) (:matrix %number))
			       (:matrix %number)
			       (pure)))

  (declare-method *
		  (:param-proc (%number)
			       ((:diagonal-matrix %number) (:diagonal-matrix %number))
			       (:diagonal-matrix %number)
			       (pure)))

  (declare-method /
		  (:param-proc (%number)
			       ((:matrix %number) %number)
			       (:matrix %number)
			       (pure)))

  (declare-method /
		  (:param-proc (%number)
			       ((:diagonal-matrix %number) %number)
			       (:diagonal-matrix %number)
			       (pure)))

  (declare matrix+
	   (:param-proc (%number)
			((:matrix %number) (:matrix %number))
			(:matrix %number)
			(pure)))

  (declare diagonal-matrix+
	   (:param-proc (%number)
			((:diagonal-matrix %number)
			 (:diagonal-matrix %number))
			(:diagonal-matrix %number)
			(pure)))

  (declare-method +
		  (:param-proc (%number)
			       ((:matrix %number) (:matrix %number))
			       (:matrix %number)
			       (pure)))

  (declare-method +
		  (:param-proc (%number)
			       ((:matrix %number) (:diagonal-matrix %number))
			       (:matrix %number)
			       (pure)))

  (declare-method +
		  (:param-proc (%number)
			       ((:diagonal-matrix %number) (:matrix %number))
			       (:matrix %number)
			       (pure)))

  (declare-method +
		  (:param-proc (%number)
			       ((:diagonal-matrix %number) (:diagonal-matrix %number))
			       (:diagonal-matrix %number)
			       (pure)))

  (declare matrix-
	   (:param-proc (%number)
			((:matrix %number) (:matrix %number))
			(:matrix %number)
			(pure)))

  (declare diagonal-matrix-
	   (:param-proc (%number)
			((:diagonal-matrix %number)
			 (:diagonal-matrix %number))
			(:diagonal-matrix %number)
			(pure)))

  (declare-method -
		  (:param-proc (%number)
			       ((:matrix %number) (:matrix %number))
			       (:matrix %number)
			       (pure)))

  (declare-method -
		  (:param-proc (%number)
			       ((:matrix %number) (:diagonal-matrix %number))
			       (:matrix %number)
			       (pure)))

  (declare-method -
		  (:param-proc (%number)
			       ((:diagonal-matrix %number) (:matrix %number))
			       (:matrix %number)
			       (pure)))

  (declare-method -
		  (:param-proc (%number)
			       ((:diagonal-matrix %number) (:diagonal-matrix %number))
			       (:diagonal-matrix %number)
			       (pure)))

  (declare-method -
		  (:param-proc (%number)
			       ((:matrix %number))
			       (:matrix %number)
			       (pure)))

  (declare-method -
		  (:param-proc (%number)
			       ((:diagonal-matrix %number))
			       (:diagonal-matrix %number)
			       (pure))))

