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

  (import (standard-library core)
	  (standard-library object-string-conversion))

  ;; Maybe we should change the constructor access to module.
  (define-class <rational> <object> #f #t #t public
    (make <rational> 0 1)
    ((i-numer <integer> public hidden)
     (i-denom <integer> public hidden)))

  (define <rational-number> (:union <rational> <integer>))

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

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

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

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

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

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

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

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

  (declare simplify-rational (:simple-proc (<rational>) <rational> pure))

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

  (declare rat-sign (:simple-proc (<rational>) <integer> pure))

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

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

  (declare rat-zero (:simple-proc () <rational> pure))

  (declare rat-one (:simple-proc () <rational> pure))

  (declare rat-zero? (:simple-proc (<rational>) <boolean> pure))

  (declare rat-one? (:simple-proc (<rational>) <boolean> pure))

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

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

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

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

  (declare rat-neg (:simple-proc (<rational>) <rational> pure))

  (declare rat-abs (:simple-proc (<rational>) <rational> pure))

  (declare rat-square (:simple-proc (<rational>) <rational> pure))

  (declare rat-inverse (:simple-proc (<rational>) <rational> pure))

  (declare rat-nonneg-int-expt (:simple-proc (<rational> <integer>)
					     <rational> pure))

  (declare rat-int-expt (:simple-proc (<rational> <integer>) <rational> pure))

  (declare i-expt (:simple-proc (<integer> <integer>) <rational-number> pure))

  (declare rat-log10-exact (:simple-proc (<rational>) (:maybe <integer>) pure))
  (declare rat-log2-exact (:simple-proc (<rational>) (:maybe <integer>) pure))
  
  (declare-method equal? (:simple-proc (<rational> <rational>) <boolean> pure))
  (declare-method = (:simple-proc (<rational> <rational>) <boolean> pure))
  (declare-method = (:simple-proc (<rational> <integer>) <boolean> pure))
  (declare-method = (:simple-proc (<integer> <rational>) <boolean> pure))

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

  (declare-method <= (:simple-proc (<rational-number> <rational-number>)
				   <boolean> pure))
  (declare-method <= (:simple-proc (<rational> <rational>) <boolean> pure))
  (declare-method <= (:simple-proc (<rational> <integer>) <boolean> pure))
  (declare-method <= (:simple-proc (<integer> <rational>) <boolean> pure))

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

  (declare-method >= (:simple-proc (<rational-number> <rational-number>)
				   <boolean> pure))
  (declare-method >= (:simple-proc (<rational> <rational>) <boolean> pure))
  (declare-method >= (:simple-proc (<rational> <integer>) <boolean> pure))
  (declare-method >= (:simple-proc (<integer> <rational>) <boolean> pure))

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

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

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

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

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

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

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

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

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

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

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