;; -*-theme-d-*-

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


(define-interface (standard-library math)

  (import (standard-library core))

  (import-and-reexport (standard-library basic-math))
  (import-and-reexport (standard-library rational))
  (import-and-reexport (standard-library real-math))
  (import-and-reexport (standard-library complex))

  (define <number> (:union <integer> <rational> <real> <complex>))

  (declare-method = (:simple-proc (<number> <number>) <boolean> pure))
  
  (declare integer-valued? (:simple-proc (<object>) <boolean> pure))

  (declare real-valued? (:simple-proc (<object>) <boolean> pure))

  (declare rational-valued? (:simple-proc (<object>) <boolean> pure))

  (declare exact? (:simple-proc (<number>) <boolean> pure))

  (declare inexact? (:simple-proc (<number>) <boolean> pure))

  (declare-method exact->inexact
		  (:simple-proc (<number>) <number> pure))

  (declare-method exact->inexact
		  (:simple-proc (<real-number>) <real-number> pure))

  (declare-method exact->inexact
		  (:simple-proc (<integer>) <real> pure))

  (declare-method exact->inexact
		  (:simple-proc (<rational>) <real> pure))

  (declare-method exact->inexact
		  (:simple-proc (<real>) <real> pure))

  (declare-method exact->inexact
		  (:simple-proc (<complex>) <complex> pure))

  (declare real->exact (:simple-proc (<real>) <rational-number> pure))

  (declare complex->exact (:simple-proc (<complex>) <rational-number> pure))

  (declare-method inexact->exact
		  (:simple-proc (<number>) <rational-number> pure))

  (declare-method inexact->exact
		  (:simple-proc (<integer>) <integer> pure))

  (declare-method inexact->exact
		  (:simple-proc (<rational>) <rational> pure))

  (declare-method inexact->exact
		  (:simple-proc (<real>) <rational-number> pure))

  (declare-method inexact->exact
		  (:simple-proc (<complex>) <rational-number> pure))

;;  (declare-method complex (:simple-proc (<number> <number>) <complex> pure))

  (declare-method + (:simple-proc (<number> <number>) <number> pure))

  (declare-method - (:simple-proc (<number> <number>) <number> pure))

  (declare-method * (:simple-proc (<number> <number>) <number> pure))

  (declare-method / (:simple-proc (<number> <number>) <number> pure))

  (declare-method - (:simple-proc (<number>) <number> pure))

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

  (declare-method square (:simple-proc (<number>) <number> pure))

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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