GCC Code Coverage Report
Directory: ../src/ Exec Total Coverage
File: /home/joels/Current/lispbm/src/extensions/math_extensions.c Lines: 123 126 97.6 %
Date: 2024-12-05 14:36:58 Branches: 59 68 86.8 %

Line Branch Exec Source
1
/*
2
    Copyright 2022, 2023 Joel Svensson        svenssonjoel@yahoo.se
3
    Copyright 2022, 2023 Benjamin Vedder
4
5
    This program is free software: you can redistribute it and/or modify
6
    it under the terms of the GNU General Public License as published by
7
    the Free Software Foundation, either version 3 of the License, or
8
    (at your option) any later version.
9
10
    This program is distributed in the hope that it will be useful,
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
    GNU General Public License for more details.
14
15
    You should have received a copy of the GNU General Public License
16
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
*/
18
19
#include "extensions.h"
20
#include "lbm_utils.h"
21
22
#include <math.h>
23
24
#ifdef __STRICT_ANSI__
25
#define isnanf isnan
26
#define isinff isinf
27
#endif
28
29
// Math
30
31
56
static lbm_value ext_sin(lbm_value *args, lbm_uint argn) {
32
56
  LBM_CHECK_ARGN_NUMBER(1);
33
28
  return lbm_enc_float(sinf(lbm_dec_as_float(args[0])));
34
}
35
36
56
static lbm_value ext_cos(lbm_value *args, lbm_uint argn) {
37
56
  LBM_CHECK_ARGN_NUMBER(1);
38
28
  return lbm_enc_float(cosf(lbm_dec_as_float(args[0])));
39
}
40
41
56
static lbm_value ext_tan(lbm_value *args, lbm_uint argn) {
42
56
  LBM_CHECK_ARGN_NUMBER(1);
43
28
  return lbm_enc_float(tanf(lbm_dec_as_float(args[0])));
44
}
45
46
56
static lbm_value ext_asin(lbm_value *args, lbm_uint argn) {
47
56
  LBM_CHECK_ARGN_NUMBER(1);
48
28
  return lbm_enc_float(asinf(lbm_dec_as_float(args[0])));
49
}
50
51
56
static lbm_value ext_acos(lbm_value *args, lbm_uint argn) {
52
56
  LBM_CHECK_ARGN_NUMBER(1);
53
28
  return lbm_enc_float(acosf(lbm_dec_as_float(args[0])));
54
}
55
56
56
static lbm_value ext_atan(lbm_value *args, lbm_uint argn) {
57
56
  LBM_CHECK_ARGN_NUMBER(1);
58
28
  return lbm_enc_float(atanf(lbm_dec_as_float(args[0])));
59
}
60
61
56
static lbm_value ext_atan2(lbm_value *args, lbm_uint argn) {
62
56
  LBM_CHECK_ARGN_NUMBER(2);
63
28
  return lbm_enc_float(atan2f(lbm_dec_as_float(args[0]), lbm_dec_as_float(args[1])));
64
}
65
66
56
static lbm_value ext_pow(lbm_value *args, lbm_uint argn) {
67
56
  LBM_CHECK_ARGN_NUMBER(2);
68
28
  return lbm_enc_float(powf(lbm_dec_as_float(args[0]), lbm_dec_as_float(args[1])));
69
}
70
71
56
static lbm_value ext_exp(lbm_value *args, lbm_uint argn) {
72
56
  LBM_CHECK_ARGN_NUMBER(1);
73
28
  return lbm_enc_float(expf(lbm_dec_as_float(args[0])));
74
}
75
76
84
static lbm_value ext_sqrt(lbm_value *args, lbm_uint argn) {
77
84
    LBM_CHECK_ARGN_NUMBER(1);
78
56
    return lbm_enc_float(sqrtf(lbm_dec_as_float(args[0])));
79
}
80
81
56
static lbm_value ext_log(lbm_value *args, lbm_uint argn) {
82
56
  LBM_CHECK_ARGN_NUMBER(1);
83
28
  return lbm_enc_float(logf(lbm_dec_as_float(args[0])));
84
}
85
86
84
static lbm_value ext_log10(lbm_value *args, lbm_uint argn) {
87
84
  LBM_CHECK_ARGN_NUMBER(1);
88
56
  return lbm_enc_float(log10f(lbm_dec_as_float(args[0])));
89
}
90
91
56
static lbm_value ext_floor(lbm_value *args, lbm_uint argn) {
92
56
  LBM_CHECK_ARGN_NUMBER(1);
93
28
  return lbm_enc_float(floorf(lbm_dec_as_float(args[0])));
94
}
95
96
56
static lbm_value ext_ceil(lbm_value *args, lbm_uint argn) {
97
56
  LBM_CHECK_ARGN_NUMBER(1);
98
28
  return lbm_enc_float(ceilf(lbm_dec_as_float(args[0])));
99
}
100
101
56
static lbm_value ext_round(lbm_value *args, lbm_uint argn) {
102
56
  LBM_CHECK_ARGN_NUMBER(1);
103
28
  return lbm_enc_float(roundf(lbm_dec_as_float(args[0])));
104
}
105
106
168
 static lbm_value ext_deg2rad(lbm_value *args, lbm_uint argn) {
107
168
   LBM_CHECK_NUMBER_ALL();
108
109
168
   if (argn == 1) {
110
112
     return lbm_enc_float(DEG2RAD_f(lbm_dec_as_float(args[0])));
111
   } else {
112
56
     lbm_value out_list = ENC_SYM_NIL;
113
140
     for (int i = (int)(argn - 1);i >= 0;i--) {
114
84
       out_list = lbm_cons(lbm_enc_float(DEG2RAD_f(lbm_dec_as_float(args[i]))), out_list);
115
     }
116
56
     return out_list;
117
   }
118
 }
119
120
84
 static lbm_value ext_rad2deg(lbm_value *args, lbm_uint argn) {
121
84
   LBM_CHECK_NUMBER_ALL();
122
123
84
   if (argn == 1) {
124
28
     return lbm_enc_float(RAD2DEG_f(lbm_dec_as_float(args[0])));
125
   } else {
126
56
     lbm_value out_list = ENC_SYM_NIL;
127
140
     for (int i = (int)(argn - 1);i >= 0;i--) {
128
84
       out_list = lbm_cons(lbm_enc_float(RAD2DEG_f(lbm_dec_as_float(args[i]))), out_list);
129
     }
130
56
     return out_list;
131
   }
132
 }
133
134
135
168
static lbm_value ext_is_nan(lbm_value *args, lbm_uint argn) {
136
168
  lbm_value res = ENC_SYM_EERROR;
137
168
  if (argn == 1) {
138
140
    res = ENC_SYM_TERROR;
139
140
    if (lbm_is_number(args[0])) {
140
140
      lbm_uint t = lbm_type_of(args[0]);
141
140
      switch(t) {
142
28
      case LBM_TYPE_DOUBLE:
143
28
        if (isnan(lbm_dec_double(args[0]))) {
144
          res = ENC_SYM_TRUE;
145
        } else {
146
28
          res = ENC_SYM_NIL;
147
        }
148
28
        break;
149
84
      case LBM_TYPE_FLOAT:
150
84
        if (isnanf(lbm_dec_float(args[0]))) {
151
28
          res = ENC_SYM_TRUE;
152
        } else {
153
56
          res = ENC_SYM_NIL;
154
        }
155
84
        break;
156
28
      default:
157
28
        res = ENC_SYM_NIL;
158
28
        break;
159
      }
160
28
    }
161
  }
162
168
  return res;
163
}
164
165
112
static lbm_value ext_is_inf(lbm_value *args, lbm_uint argn) {
166
112
  lbm_value res = ENC_SYM_EERROR;
167
112
  if (argn == 1) {
168
84
    res = ENC_SYM_TERROR;
169
84
    if (lbm_is_number(args[0])) {
170
84
      lbm_uint t = lbm_type_of(args[0]);
171
84
      switch(t) {
172
28
      case LBM_TYPE_DOUBLE:
173

28
        if (isinf(lbm_dec_double(args[0]))) {
174
          res = ENC_SYM_TRUE;
175
        } else {
176
28
          res = ENC_SYM_NIL;
177
        }
178
28
        break;
179
28
      case LBM_TYPE_FLOAT:
180

28
        if (isinff(lbm_dec_float(args[0]))) {
181
          res = ENC_SYM_TRUE;
182
        } else {
183
28
          res = ENC_SYM_NIL;
184
        }
185
28
        break;
186
28
      default:
187
28
        res = ENC_SYM_NIL;
188
28
        break;
189
      }
190
28
    }
191
  }
192
112
  return res;
193
}
194
195
196
21672
void lbm_math_extensions_init(void) {
197
198
21672
  lbm_add_extension("sin", ext_sin);
199
21672
  lbm_add_extension("cos", ext_cos);
200
21672
  lbm_add_extension("tan", ext_tan);
201
21672
  lbm_add_extension("asin", ext_asin);
202
21672
  lbm_add_extension("acos", ext_acos);
203
21672
  lbm_add_extension("atan", ext_atan);
204
21672
  lbm_add_extension("atan2", ext_atan2);
205
21672
  lbm_add_extension("pow", ext_pow);
206
21672
  lbm_add_extension("exp", ext_exp);
207
21672
  lbm_add_extension("sqrt", ext_sqrt);
208
21672
  lbm_add_extension("log", ext_log);
209
21672
  lbm_add_extension("log10", ext_log10);
210
21672
  lbm_add_extension("floor", ext_floor);
211
21672
  lbm_add_extension("ceil", ext_ceil);
212
21672
  lbm_add_extension("round", ext_round);
213
21672
  lbm_add_extension("deg2rad", ext_deg2rad);
214
21672
  lbm_add_extension("rad2deg", ext_rad2deg);
215
21672
  lbm_add_extension("is-nan", ext_is_nan);
216
21672
  lbm_add_extension("is-inf", ext_is_inf);
217
21672
}