;; -*-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 extra-math)

  (import (standard-library core)
	  (standard-library math))

  (declare fmod (:simple-proc (<real> <real>) <real> pure))
  (declare r-remainder (:simple-proc (<real> <real>) <real> pure))
  (declare fma (:simple-proc (<real> <real> <real>) <real> pure))
  (declare fast-fma? (:simple-proc () <boolean> pure))
  (declare fmin (:simple-proc (<real> <real>) <real> pure))
  (declare fmax (:simple-proc (<real> <real>) <real> pure))
  (declare fdim (:simple-proc (<real> <real>) <real> pure))
  (declare r-exp2 (:simple-proc (<real>) <real> pure))
  (declare r-expm1 (:simple-proc (<real>) <real> pure))
  (declare r-log2 (:simple-proc (<real>) <real> pure))
  (declare r-log1p (:simple-proc (<real>) <real> pure))
  (declare logb (:simple-proc (<real>) <real> pure))
  (declare ilogb (:simple-proc (<real>) <integer> pure))
  (declare ilogb0 (:simple-proc () <integer> pure))
  (declare ilogbnan (:simple-proc () <integer> pure))
  (declare r-cbrt (:simple-proc (<real>) <real> pure))
  (declare r-hypot (:simple-proc (<real> <real>) <real> pure))
  (declare r-erf (:simple-proc (<real>) <real> pure))
  (declare r-erfc (:simple-proc (<real>) <real> pure))
  (declare r-lgamma (:simple-proc (<real>) <real> pure))
  (declare r-tgamma (:simple-proc (<real>) <real> pure))
  (declare r-nearbyint (:simple-proc (<real>) <real> pure))
  (declare rint (:simple-proc (<real>) <real> pure))
  (declare frexp (:simple-proc (<real>) (:pair <real> <integer>) pure))
  (declare ldexp (:simple-proc (<real> <integer>) <real> pure))
  (declare modf (:simple-proc (<real>) (:pair <real> <real>) pure))
  (declare r-nextafter (:simple-proc (<real> <real>) <real> pure))
  (declare r-copysign (:simple-proc (<real> <real>) <real> pure))
  (declare fpclassify (:simple-proc (<real>) <integer> pure))
  (declare fpclassify-nan (:simple-proc () <integer> pure))
  (declare fpclassify-infinite (:simple-proc () <integer> pure))
  (declare fpclassify-zero (:simple-proc () <integer> pure))
  (declare fpclassify-subnormal (:simple-proc () <integer> pure))
  (declare fpclassify-normal (:simple-proc () <integer> pure))
  (declare r-isnormal? (:simple-proc (<real>) <boolean> pure))
  (declare r-signbit (:simple-proc (<real>) <integer> pure))

  (declare r-log2-neg (:simple-proc (<real>) <complex> pure))
  (declare i-cbrt (:simple-proc (<integer>) (:union <real> <integer>) pure))
  (declare rat-cbrt (:simple-proc (<rational>)
				  (:union <real> <rational> <integer>) pure))

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

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

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

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

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

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

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

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

  ;; We may later change the gamma function result types if we
  ;; implement computation of exact values for them.

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

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