mirror of
https://github.com/justinethier/cyclone.git
synced 2025-05-18 21:29:18 +02:00
149 lines
4.8 KiB
Scheme
149 lines
4.8 KiB
Scheme
;;;; Cyclone Scheme
|
|
;;;; https://github.com/justinethier/cyclone
|
|
;;;;
|
|
;;;; Copyright (c) 2014-2016, Justin Ethier
|
|
;;;; All rights reserved.
|
|
;;;;
|
|
;;;; This module contains the inexact library from r7rs.
|
|
;;;;
|
|
(define-library (scheme inexact)
|
|
(import (scheme base))
|
|
(export
|
|
acos
|
|
asin
|
|
atan
|
|
cos
|
|
exp
|
|
finite?
|
|
infinite?
|
|
log
|
|
nan?
|
|
sin
|
|
sqrt
|
|
tan
|
|
)
|
|
(begin
|
|
(define-syntax define-inexact-op
|
|
(er-macro-transformer
|
|
(lambda (expr rename compare)
|
|
(let* ((fnc (cadr expr))
|
|
(op (caddr expr))
|
|
(complex-op (cadddr expr))
|
|
)
|
|
`(define-c ,fnc
|
|
"(void *data, int argc, closure _, object k, object z)"
|
|
,(string-append
|
|
" return_inexact_double_or_cplx_op(data, k, " op ", " complex-op ", z);")
|
|
"(void *data, object ptr, object z)"
|
|
,(string-append
|
|
" return_inexact_double_or_cplx_op_no_cps(data, ptr, " op ", " complex-op ", z);"))))))
|
|
|
|
(define-c nan?
|
|
"(void *data, int argc, closure _, object k, object z)"
|
|
" Cyc_check_num(data, z);
|
|
if (obj_is_int(z) ||
|
|
type_of(z) == integer_tag ||
|
|
type_of(z) == bignum_tag ||
|
|
!isnan(((double_type *)z)->value))
|
|
{
|
|
return_closcall1(data, k, boolean_f);
|
|
}
|
|
return_closcall1(data, k, boolean_t);")
|
|
(define-c infinite?
|
|
"(void *data, int argc, closure _, object k, object z)"
|
|
" Cyc_check_num(data, z);
|
|
if (obj_is_int(z) ||
|
|
type_of(z) == integer_tag ||
|
|
type_of(z) == bignum_tag ||
|
|
!isinf(((double_type *)z)->value))
|
|
{
|
|
return_closcall1(data, k, boolean_f);
|
|
}
|
|
return_closcall1(data, k, boolean_t);")
|
|
(define (finite? z)
|
|
(if (infinite? z) #f #t))
|
|
(define (log z1 . z2)
|
|
(if (null? z2)
|
|
(c-log z1)
|
|
(let ((z2* (car z2)))
|
|
(/ (c-log z1) (c-log z2*)))))
|
|
(define-inexact-op c-log "log" "clog")
|
|
(define-inexact-op exp "exp" "cexp")
|
|
(define-inexact-op sin "sin" "csin")
|
|
(define-inexact-op cos "cos" "ccos")
|
|
(define-inexact-op tan "tan" "ctan")
|
|
(define-inexact-op asin "asin" "casin")
|
|
(define-inexact-op acos "acos" "cacos")
|
|
(define-inexact-op atan1 "atan" "catan")
|
|
|
|
;; Support for two-argument atan, from Chibi Scheme
|
|
(define (atan y . o)
|
|
(define (inf? z) (if (= +inf.0 z) #t (= -inf.0 z)))
|
|
(if (null? o)
|
|
(atan1 y)
|
|
(let ((x (inexact (car o))))
|
|
(if (and (inf? x) (inf? y))
|
|
(* (if (< y 0) -1 1) (if (= x -inf.0) 3 1) 0.7853981633974483)
|
|
(if (negative? x)
|
|
(if (or (negative? y) (eqv? y -0.0))
|
|
(- (atan1 (/ y x)) 3.141592653589793)
|
|
(- 3.141592653589793 (atan1 (/ y (- x)))))
|
|
(if (and (zero? x) (zero? y))
|
|
(* (if (eqv? y -0.0) -1 1)
|
|
(if (eqv? x -0.0) 3.141592653589793 x))
|
|
(atan1 (/ y x))))))))
|
|
|
|
(define-c
|
|
sqrt
|
|
"(void *data, int argc, closure _, object k, object z)"
|
|
" double complex result;
|
|
Cyc_check_num(data, z);
|
|
if (obj_is_int(z)) {
|
|
result = csqrt(obj_obj2int(z));
|
|
} else if (type_of(z) == integer_tag) {
|
|
result = csqrt(((integer_type *)z)->value);
|
|
} else if (type_of(z) == bignum_tag) {
|
|
result = csqrt(mp_get_double(&bignum_value(z)));
|
|
} else if (type_of(z) == complex_num_tag) {
|
|
result = csqrt(complex_num_value(z));
|
|
} else {
|
|
result = csqrt(((double_type *)z)->value);
|
|
}
|
|
|
|
if (cimag(result) == 0.0) {
|
|
if (obj_is_int(z) && creal(result) == round(creal(result))) {
|
|
return_closcall1(data, k, obj_int2obj(creal(result)));
|
|
}
|
|
make_double(d, creal(result));
|
|
return_closcall1(data, k, &d);
|
|
} else {
|
|
complex_num_type cn;
|
|
assign_complex_num((&cn), result);
|
|
return_closcall1(data, k, &cn);
|
|
} "
|
|
"(void *data, object ptr, object z)"
|
|
" double complex result;
|
|
Cyc_check_num(data, z);
|
|
if (obj_is_int(z)) {
|
|
result = csqrt(obj_obj2int(z));
|
|
} else if (type_of(z) == integer_tag) {
|
|
result = csqrt(((integer_type *)z)->value);
|
|
} else if (type_of(z) == bignum_tag) {
|
|
result = csqrt(mp_get_double(&bignum_value(z)));
|
|
} else if (type_of(z) == complex_num_tag) {
|
|
result = csqrt(complex_num_value(z));
|
|
} else {
|
|
result = csqrt(((double_type *)z)->value);
|
|
}
|
|
|
|
if (cimag(result) == 0.0) {
|
|
if (obj_is_int(z) && creal(result) == round(creal(result))) {
|
|
return obj_int2obj(creal(result));
|
|
}
|
|
assign_double(ptr, creal(result));
|
|
} else {
|
|
assign_complex_num(ptr, result);
|
|
}
|
|
return ptr;
|
|
")
|
|
))
|