;;;;
;;;; flonum.stk         -- Implementation of (scheme flonum) aka SRFI-144
;;;;
;;;; Copyright © 2020 Jeronimo Pellegrini - <j_p@aleph0.info>
;;;;
;;;;
;;;; This program is free software; you can redistribute it and/or modify
;;;; it under the terms of the GNU General Public License as published by
;;;; the Free Software Foundation; either version 3 of the License, or
;;;; (at your option) any later version.
;;;;
;;;; This program is distributed in the hope that it will be useful,
;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;;;; GNU General Public License for more details.
;;;;
;;;; You should have received a copy of the GNU General Public License
;;;; along with this program; if not, write to the Free Software
;;;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
;;;; USA.
;;;;
;;;;           Author: Jeronimo Pellegrini [j_p@aleph0.info]
;;;;    Creation date: 03-Dec-2021 00:00 (jpellegrini)
;;;;
(select-module scheme/flonum)

(%compile-time-define fl/ fllog %flinteger-exponent flinteger-fraction
                      %fl-integer-exponent-nan  %fl-integer-exponent-zero)

(export ;; constants:
        fl-integer-exponent-zero
        fl-integer-exponent-nan

        ;; arithmetic:
        flnumerator
        fldenominator
        flround

        ;; accessors:
        flinteger-exponent

        ;; exponents and logarithms:
        make-fllog-base)

;;;
;;; CONSTANTS -- DONE
;;;

;; these are defined as inexacts in the C code and defined again here
;; with their proper name becuse defining exact constants in C would
;; require us to include more parts of number.c in srfi-144.c, and it
;; wasn't worth it.
(define fl-integer-exponent-zero (inexact->exact %fl-integer-exponent-zero))
(define fl-integer-exponent-nan  (inexact->exact %fl-integer-exponent-nan))

;;;
;;; CONSTRUCTORS -- DONE
;;;
;; (define (flonum n)
;;   (if (real? n) (inexact n) +nan.0))

;;;
;;; ARITHMETIC -- DONE
;;;

(define (flnumerator x)
  (cond ((or (infinite? x) (nan? x) (zero? x))
         x) ; -0.0 is handled here
        ((let-values (( (i f) (flinteger-fraction x))) (zero? f))
         x)
        (else
         (exact->inexact (numerator (exact x))))))

;; From Gauche:
(define (fldenominator x)
  (cond ((or (infinite? x) (zero? x)) 1.0)
        ((nan? x) x)
        (else (exact->inexact (denominator (exact x))))))

(define (flround x)
  (assume (flonum? x))
  (round x))

;;;
;;; ACCESSORS -- DONE
;;;

;; FIXME: check it %flinteger-exponent is necessary
(define (flinteger-exponent x)
  (inexact->exact (%flinteger-exponent x)))

;;;
;;; EXPONENTS AND LOGARITHMS -- DONE
;;;

;; FIXME: inefficient?
(define (make-fllog-base base)
  (lambda (x) (fl/ (fllog x) (fllog base))))

;;;
;;; TRIGONOMETRIC FUNCTIONS -- DONE
;;;

;;;
;;; INTEGER DIVISION -- DONE
;;;

;;;
;;; SPECIAL FUNCTIONS -- DONE
;;;

(provide "scheme/flonum")
