1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
|
/*
* Copyright © 2017 Keith Packard <keithp@keithp.com>
*
* 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 2 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.
*/
#include "ao_lisp.h"
#include <math.h>
static void float_mark(void *addr)
{
(void) addr;
}
static int float_size(void *addr)
{
if (!addr)
return 0;
return sizeof (struct ao_lisp_float);
}
static void float_move(void *addr)
{
(void) addr;
}
const struct ao_lisp_type ao_lisp_float_type = {
.mark = float_mark,
.size = float_size,
.move = float_move,
.name = "float",
};
void
ao_lisp_float_write(ao_poly p)
{
struct ao_lisp_float *f = ao_lisp_poly_float(p);
float v = f->value;
if (isnanf(v))
printf("+nan.0");
else if (isinff(v)) {
if (v < 0)
printf("-");
else
printf("+");
printf("inf.0");
} else
printf ("%g", f->value);
}
float
ao_lisp_poly_number(ao_poly p)
{
switch (ao_lisp_poly_base_type(p)) {
case AO_LISP_INT:
return ao_lisp_poly_int(p);
case AO_LISP_OTHER:
switch (ao_lisp_other_type(ao_lisp_poly_other(p))) {
case AO_LISP_BIGINT:
return ao_lisp_bigint_int(ao_lisp_poly_bigint(p)->value);
case AO_LISP_FLOAT:
return ao_lisp_poly_float(p)->value;
}
}
return NAN;
}
ao_poly
ao_lisp_float_get(float value)
{
struct ao_lisp_float *f;
f = ao_lisp_alloc(sizeof (struct ao_lisp_float));
f->type = AO_LISP_FLOAT;
f->value = value;
return ao_lisp_float_poly(f);
}
ao_poly
ao_lisp_do_inexactp(struct ao_lisp_cons *cons)
{
if (!ao_lisp_check_argc(_ao_lisp_atom_led, cons, 1, 1))
return AO_LISP_NIL;
if (ao_lisp_poly_type(ao_lisp_arg(cons, 0)) == AO_LISP_FLOAT)
return _ao_lisp_bool_true;
return _ao_lisp_bool_false;
}
ao_poly
ao_lisp_do_finitep(struct ao_lisp_cons *cons)
{
ao_poly value;
float f;
if (!ao_lisp_check_argc(_ao_lisp_atom_led, cons, 1, 1))
return AO_LISP_NIL;
value = ao_lisp_arg(cons, 0);
switch (ao_lisp_poly_type(value)) {
case AO_LISP_INT:
case AO_LISP_BIGINT:
return _ao_lisp_bool_true;
case AO_LISP_FLOAT:
f = ao_lisp_poly_float(value)->value;
if (!isnan(f) && !isinf(f))
return _ao_lisp_bool_true;
}
return _ao_lisp_bool_false;
}
ao_poly
ao_lisp_do_infinitep(struct ao_lisp_cons *cons)
{
ao_poly value;
float f;
if (!ao_lisp_check_argc(_ao_lisp_atom_led, cons, 1, 1))
return AO_LISP_NIL;
value = ao_lisp_arg(cons, 0);
switch (ao_lisp_poly_type(value)) {
case AO_LISP_FLOAT:
f = ao_lisp_poly_float(value)->value;
if (isinf(f))
return _ao_lisp_bool_true;
}
return _ao_lisp_bool_false;
}
ao_poly
ao_lisp_do_sqrt(struct ao_lisp_cons *cons)
{
ao_poly value;
if (!ao_lisp_check_argc(_ao_lisp_atom_sqrt, cons, 1, 1))
return AO_LISP_NIL;
value = ao_lisp_arg(cons, 0);
if (!ao_lisp_number_typep(ao_lisp_poly_type(value)))
return ao_lisp_error(AO_LISP_INVALID, "%s: non-numeric", ao_lisp_poly_atom(_ao_lisp_atom_sqrt)->name);
return ao_lisp_float_get(sqrtf(ao_lisp_poly_number(value)));
}
|