;; -*-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 complex)

  (import (standard-library core)
	  (standard-library rational)
	  (standard-library real-math)
	  (standard-library object-string-conversion))

  (define-class <complex> <object> #f #t #t public
    (make <complex> 0.0 0.0)
    ((re <real> public hidden)
     (im <real> public hidden)))

  (define-generic-proc complex)

  (declare-method complex (:simple-proc (<real-number> <real-number>)
					<complex> pure))
  (declare-method complex (:simple-proc (<real> <real>) <complex> pure))
  (declare-method complex (:simple-proc (<real> <integer>) <complex> pure))
  (declare-method complex (:simple-proc (<real> <rational>) <complex> pure))
  (declare-method complex (:simple-proc (<integer> <real>) <complex> pure))
  (declare-method complex (:simple-proc (<integer> <integer>) <complex> pure))
  (declare-method complex (:simple-proc (<integer> <rational>) <complex> pure))
  (declare-method complex (:simple-proc (<rational> <real>) <complex> pure))
  (declare-method complex (:simple-proc (<rational> <integer>) <complex> pure))
  (declare-method complex (:simple-proc (<rational> <rational>) <complex> pure))

  (declare real->complex (:simple-proc (<real>) <complex> (pure)))
  (declare integer->complex (:simple-proc (<integer>) <complex> (pure)))
  (declare rational->complex (:simple-proc (<rational>) <complex> (pure)))

  (declare complex=? (:simple-proc (<complex> <complex>) <boolean> pure))
  (declare complex= (:simple-proc (<complex> <complex>) <boolean> pure))
  (declare complex-integer= (:simple-proc (<complex> <integer>) <boolean>
					   pure))
  (declare integer-complex= (:simple-proc (<integer> <complex>) <boolean>
					   pure))
  (declare complex-real= (:simple-proc (<complex> <real>) <boolean> pure))
  (declare real-complex= (:simple-proc (<real> <complex>) <boolean> pure))
  (declare complex-rational= (:simple-proc (<complex> <rational>) <boolean>
					    pure))
  (declare rational-complex= (:simple-proc (<rational> <complex>) <boolean>
					    pure))

  (declare-method equal? (:simple-proc (<complex> <complex>) <boolean> pure))
  (declare-method = (:simple-proc (<complex> <complex>) <boolean> pure))
  (declare-method = (:simple-proc (<complex> <integer>) <boolean> pure))
  (declare-method = (:simple-proc (<integer> <complex>) <boolean> pure))
  (declare-method = (:simple-proc (<complex> <real>) <boolean> pure))
  (declare-method = (:simple-proc (<real> <complex>) <boolean> pure))
  (declare-method = (:simple-proc (<complex> <rational>) <boolean> pure))
  (declare-method = (:simple-proc (<rational> <complex>) <boolean> pure))

  (declare real-part (:simple-proc (<complex>) <real> (pure)))
  (declare imag-part (:simple-proc (<complex>) <real> (pure)))
  (declare make-polar (:simple-proc (<real> <real>) <complex> (pure)))
  (declare c-abs (:simple-proc (<complex>) <real> (pure)))
  (declare c-angle (:simple-proc (<complex>) <real> (pure)))

  (declare c-neg (:simple-proc (<complex>) <complex> pure))
  (declare c-square (:simple-proc (<complex>) <complex> pure))

  (declare-method abs (:simple-proc (<complex>) <real> (pure)))
  (declare-method - (:simple-proc (<complex>) <complex> (pure)))
  (declare-method square (:simple-proc (<complex>) <complex> (pure)))

  (declare complex+ (:simple-proc (<complex> <complex>) <complex> (pure)))
  (declare complex- (:simple-proc (<complex> <complex>) <complex> (pure)))
  (declare complex* (:simple-proc (<complex> <complex>) <complex> (pure)))
  (declare complex/ (:simple-proc (<complex> <complex>) <complex> (pure)))

  (declare real-complex+ (:simple-proc (<real> <complex>) <complex> (pure)))
  (declare real-complex- (:simple-proc (<real> <complex>) <complex> (pure)))
  (declare real-complex* (:simple-proc (<real> <complex>) <complex> (pure)))
  (declare real-complex/ (:simple-proc (<real> <complex>) <complex> (pure)))

  (declare complex-real+ (:simple-proc (<complex> <real>) <complex> (pure)))
  (declare complex-real- (:simple-proc (<complex> <real>) <complex> (pure)))
  (declare complex-real* (:simple-proc (<complex> <real>) <complex> (pure)))
  (declare complex-real/ (:simple-proc (<complex> <real>) <complex> (pure)))

  (declare integer-complex+
	   (:simple-proc (<integer> <complex>) <complex> (pure)))
  (declare integer-complex-
	   (:simple-proc (<integer> <complex>) <complex> (pure)))
  (declare integer-complex*
	   (:simple-proc (<integer> <complex>) <complex> (pure)))
  (declare integer-complex/
	   (:simple-proc (<integer> <complex>) <complex> (pure)))

  (declare complex-integer+
	   (:simple-proc (<complex> <integer>) <complex> (pure)))
  (declare complex-integer-
	   (:simple-proc (<complex> <integer>) <complex> (pure)))
  (declare complex-integer*
	   (:simple-proc (<complex> <integer>) <complex> (pure)))
  (declare complex-integer/
	   (:simple-proc (<complex> <integer>) <complex> (pure)))

  (declare rational-complex+
	   (:simple-proc (<rational> <complex>) <complex> (pure)))
  (declare rational-complex-
	   (:simple-proc (<rational> <complex>) <complex> (pure)))
  (declare rational-complex*
	   (:simple-proc (<rational> <complex>) <complex> (pure)))
  (declare rational-complex/
	   (:simple-proc (<rational> <complex>) <complex> (pure)))

  (declare complex-rational+
	   (:simple-proc (<complex> <rational>) <complex> (pure)))
  (declare complex-rational-
	   (:simple-proc (<complex> <rational>) <complex> (pure)))
  (declare complex-rational*
	   (:simple-proc (<complex> <rational>) <complex> (pure)))
  (declare complex-rational/
	   (:simple-proc (<complex> <rational>) <complex> (pure)))

  (declare-method + (:simple-proc (<complex> <complex>) <complex> (pure)))
  (declare-method + (:simple-proc (<real> <complex>) <complex> (pure)))
  (declare-method + (:simple-proc (<integer> <complex>) <complex> (pure)))
  (declare-method + (:simple-proc (<rational> <complex>) <complex> (pure)))
  (declare-method + (:simple-proc (<complex> <real>) <complex> (pure)))
  (declare-method + (:simple-proc (<complex> <integer>) <complex> (pure)))
  (declare-method + (:simple-proc (<complex> <rational>) <complex> (pure)))

  (declare-method - (:simple-proc (<complex> <complex>) <complex> (pure)))
  (declare-method - (:simple-proc (<real> <complex>) <complex> (pure)))
  (declare-method - (:simple-proc (<integer> <complex>) <complex> (pure)))
  (declare-method - (:simple-proc (<rational> <complex>) <complex> (pure)))
  (declare-method - (:simple-proc (<complex> <real>) <complex> (pure)))
  (declare-method - (:simple-proc (<complex> <integer>) <complex> (pure)))
  (declare-method - (:simple-proc (<complex> <rational>) <complex> (pure)))

  (declare-method * (:simple-proc (<complex> <complex>) <complex> (pure)))
  (declare-method * (:simple-proc (<real> <complex>) <complex> (pure)))
  (declare-method * (:simple-proc (<integer> <complex>) <complex> (pure)))
  (declare-method * (:simple-proc (<rational> <complex>) <complex> (pure)))
  (declare-method * (:simple-proc (<complex> <real>) <complex> (pure)))
  (declare-method * (:simple-proc (<complex> <integer>) <complex> (pure)))
  (declare-method * (:simple-proc (<complex> <rational>) <complex> (pure)))

  (declare-method / (:simple-proc (<complex> <complex>) <complex> (pure)))
  (declare-method / (:simple-proc (<real> <complex>) <complex> (pure)))
  (declare-method / (:simple-proc (<integer> <complex>) <complex> (pure)))
  (declare-method / (:simple-proc (<rational> <complex>) <complex> (pure)))
  (declare-method / (:simple-proc (<complex> <real>) <complex> (pure)))
  (declare-method / (:simple-proc (<complex> <integer>) <complex> (pure)))
  (declare-method / (:simple-proc (<complex> <rational>) <complex> (pure)))

  (declare c-sqrt (:simple-proc (<complex>) <complex> (pure)))
  (declare c-exp (:simple-proc (<complex>) <complex> (pure)))
  (declare c-log (:simple-proc (<complex>) <complex> (pure)))
  (declare c-log10 (:simple-proc (<complex>) <complex> (pure)))  
  (declare c-expt (:simple-proc (<complex> <complex>) <complex> (pure)))
  (declare c-sin (:simple-proc (<complex>) <complex> (pure)))
  (declare c-cos (:simple-proc (<complex>) <complex> (pure)))
  (declare c-tan (:simple-proc (<complex>) <complex> (pure)))
  (declare c-asin (:simple-proc (<complex>) <complex> (pure)))
  (declare c-acos (:simple-proc (<complex>) <complex> (pure)))
  (declare c-atan (:simple-proc (<complex>) <complex> (pure)))
  (declare c-sinh (:simple-proc (<complex>) <complex> (pure)))
  (declare c-cosh (:simple-proc (<complex>) <complex> (pure)))
  (declare c-tanh (:simple-proc (<complex>) <complex> (pure)))
  (declare c-asinh (:simple-proc (<complex>) <complex> (pure)))
  (declare c-acosh (:simple-proc (<complex>) <complex> (pure)))
  (declare c-atanh (:simple-proc (<complex>) <complex> (pure)))

  (declare r-complex-log (:simple-proc (<real>) <complex> pure))
  (declare complex-real-expt (:simple-proc (<complex> <real>) <complex> pure))
  (declare real-complex-expt (:simple-proc (<real> <complex>) <complex> pure))
  (declare r-log-neg (:simple-proc (<real>) <complex> pure))
  (declare r-log10-neg (:simple-proc (<real>) <complex> pure))
  (declare r-complex-expt (:simple-proc (<real> <real>) <complex> pure))
  (declare c-exp2 (:simple-proc (<complex>) <complex> (pure)))
  
  (declare c-nonneg-int-expt
	   (:simple-proc (<complex> <integer>) <complex> (pure)))
  (declare c-int-expt
	   (:simple-proc (<complex> <integer>) <complex> (pure)))

  (declare complex->string
	   (:simple-proc (<complex>) <string> pure))

  (declare-method object->string
		  (:simple-proc (<complex>) <string> pure)))
