comparison src/float.c @ 24780:7bc92a651472 v8.2.2928

patch 8.2.2928: the evalfunc.c file is too big Commit: https://github.com/vim/vim/commit/01c798c31a94a50ad0c4a022fc21c1a31553be21 Author: Yegappan Lakshmanan <yegappan@yahoo.com> Date: Wed Jun 2 17:07:18 2021 +0200 patch 8.2.2928: the evalfunc.c file is too big Problem: The evalfunc.c file is too big. Solution: Move float related functionality to a separate file. (Yegappan Lakshmanan, closes #8287)
author Bram Moolenaar <Bram@vim.org>
date Wed, 02 Jun 2021 17:15:03 +0200
parents
children 5f8dd7b3ae41
comparison
equal deleted inserted replaced
24779:3675d97a795e 24780:7bc92a651472
1 /* vi:set ts=8 sts=4 sw=4 noet:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 * See README.txt for an overview of the Vim source code.
8 */
9
10 /*
11 * float.c: Floating point functions
12 */
13 #define USING_FLOAT_STUFF
14
15 #include "vim.h"
16
17 #if (defined(FEAT_EVAL) && defined(FEAT_FLOAT)) || defined(PROTO)
18
19 #ifdef VMS
20 # include <float.h>
21 #endif
22
23 /*
24 * Convert the string "text" to a floating point number.
25 * This uses strtod(). setlocale(LC_NUMERIC, "C") has been used to make sure
26 * this always uses a decimal point.
27 * Returns the length of the text that was consumed.
28 */
29 int
30 string2float(
31 char_u *text,
32 float_T *value) // result stored here
33 {
34 char *s = (char *)text;
35 float_T f;
36
37 // MS-Windows does not deal with "inf" and "nan" properly.
38 if (STRNICMP(text, "inf", 3) == 0)
39 {
40 *value = INFINITY;
41 return 3;
42 }
43 if (STRNICMP(text, "-inf", 3) == 0)
44 {
45 *value = -INFINITY;
46 return 4;
47 }
48 if (STRNICMP(text, "nan", 3) == 0)
49 {
50 *value = NAN;
51 return 3;
52 }
53 f = strtod(s, &s);
54 *value = f;
55 return (int)((char_u *)s - text);
56 }
57
58 /*
59 * Get the float value of "argvars[0]" into "f".
60 * Returns FAIL when the argument is not a Number or Float.
61 */
62 static int
63 get_float_arg(typval_T *argvars, float_T *f)
64 {
65 if (argvars[0].v_type == VAR_FLOAT)
66 {
67 *f = argvars[0].vval.v_float;
68 return OK;
69 }
70 if (argvars[0].v_type == VAR_NUMBER)
71 {
72 *f = (float_T)argvars[0].vval.v_number;
73 return OK;
74 }
75 emsg(_("E808: Number or Float required"));
76 return FAIL;
77 }
78
79 /*
80 * "abs(expr)" function
81 */
82 void
83 f_abs(typval_T *argvars, typval_T *rettv)
84 {
85 if (argvars[0].v_type == VAR_FLOAT)
86 {
87 rettv->v_type = VAR_FLOAT;
88 rettv->vval.v_float = fabs(argvars[0].vval.v_float);
89 }
90 else
91 {
92 varnumber_T n;
93 int error = FALSE;
94
95 n = tv_get_number_chk(&argvars[0], &error);
96 if (error)
97 rettv->vval.v_number = -1;
98 else if (n > 0)
99 rettv->vval.v_number = n;
100 else
101 rettv->vval.v_number = -n;
102 }
103 }
104
105 /*
106 * "acos()" function
107 */
108 void
109 f_acos(typval_T *argvars, typval_T *rettv)
110 {
111 float_T f = 0.0;
112
113 rettv->v_type = VAR_FLOAT;
114 if (get_float_arg(argvars, &f) == OK)
115 rettv->vval.v_float = acos(f);
116 else
117 rettv->vval.v_float = 0.0;
118 }
119
120 /*
121 * "asin()" function
122 */
123 void
124 f_asin(typval_T *argvars, typval_T *rettv)
125 {
126 float_T f = 0.0;
127
128 rettv->v_type = VAR_FLOAT;
129 if (get_float_arg(argvars, &f) == OK)
130 rettv->vval.v_float = asin(f);
131 else
132 rettv->vval.v_float = 0.0;
133 }
134
135 /*
136 * "atan()" function
137 */
138 void
139 f_atan(typval_T *argvars, typval_T *rettv)
140 {
141 float_T f = 0.0;
142
143 rettv->v_type = VAR_FLOAT;
144 if (get_float_arg(argvars, &f) == OK)
145 rettv->vval.v_float = atan(f);
146 else
147 rettv->vval.v_float = 0.0;
148 }
149
150 /*
151 * "atan2()" function
152 */
153 void
154 f_atan2(typval_T *argvars, typval_T *rettv)
155 {
156 float_T fx = 0.0, fy = 0.0;
157
158 rettv->v_type = VAR_FLOAT;
159 if (get_float_arg(argvars, &fx) == OK
160 && get_float_arg(&argvars[1], &fy) == OK)
161 rettv->vval.v_float = atan2(fx, fy);
162 else
163 rettv->vval.v_float = 0.0;
164 }
165
166 /*
167 * "ceil({float})" function
168 */
169 void
170 f_ceil(typval_T *argvars, typval_T *rettv)
171 {
172 float_T f = 0.0;
173
174 rettv->v_type = VAR_FLOAT;
175 if (get_float_arg(argvars, &f) == OK)
176 rettv->vval.v_float = ceil(f);
177 else
178 rettv->vval.v_float = 0.0;
179 }
180
181 /*
182 * "cos()" function
183 */
184 void
185 f_cos(typval_T *argvars, typval_T *rettv)
186 {
187 float_T f = 0.0;
188
189 rettv->v_type = VAR_FLOAT;
190 if (get_float_arg(argvars, &f) == OK)
191 rettv->vval.v_float = cos(f);
192 else
193 rettv->vval.v_float = 0.0;
194 }
195
196 /*
197 * "cosh()" function
198 */
199 void
200 f_cosh(typval_T *argvars, typval_T *rettv)
201 {
202 float_T f = 0.0;
203
204 rettv->v_type = VAR_FLOAT;
205 if (get_float_arg(argvars, &f) == OK)
206 rettv->vval.v_float = cosh(f);
207 else
208 rettv->vval.v_float = 0.0;
209 }
210
211 /*
212 * "exp()" function
213 */
214 void
215 f_exp(typval_T *argvars, typval_T *rettv)
216 {
217 float_T f = 0.0;
218
219 rettv->v_type = VAR_FLOAT;
220 if (get_float_arg(argvars, &f) == OK)
221 rettv->vval.v_float = exp(f);
222 else
223 rettv->vval.v_float = 0.0;
224 }
225
226 /*
227 * "float2nr({float})" function
228 */
229 void
230 f_float2nr(typval_T *argvars, typval_T *rettv)
231 {
232 float_T f = 0.0;
233
234 if (get_float_arg(argvars, &f) == OK)
235 {
236 if (f <= (float_T)-VARNUM_MAX + DBL_EPSILON)
237 rettv->vval.v_number = -VARNUM_MAX;
238 else if (f >= (float_T)VARNUM_MAX - DBL_EPSILON)
239 rettv->vval.v_number = VARNUM_MAX;
240 else
241 rettv->vval.v_number = (varnumber_T)f;
242 }
243 }
244
245 /*
246 * "floor({float})" function
247 */
248 void
249 f_floor(typval_T *argvars, typval_T *rettv)
250 {
251 float_T f = 0.0;
252
253 rettv->v_type = VAR_FLOAT;
254 if (get_float_arg(argvars, &f) == OK)
255 rettv->vval.v_float = floor(f);
256 else
257 rettv->vval.v_float = 0.0;
258 }
259
260 /*
261 * "fmod()" function
262 */
263 void
264 f_fmod(typval_T *argvars, typval_T *rettv)
265 {
266 float_T fx = 0.0, fy = 0.0;
267
268 rettv->v_type = VAR_FLOAT;
269 if (get_float_arg(argvars, &fx) == OK
270 && get_float_arg(&argvars[1], &fy) == OK)
271 rettv->vval.v_float = fmod(fx, fy);
272 else
273 rettv->vval.v_float = 0.0;
274 }
275
276 # if defined(HAVE_MATH_H) || defined(PROTO)
277 /*
278 * "isinf()" function
279 */
280 void
281 f_isinf(typval_T *argvars, typval_T *rettv)
282 {
283 if (argvars[0].v_type == VAR_FLOAT && isinf(argvars[0].vval.v_float))
284 rettv->vval.v_number = argvars[0].vval.v_float > 0.0 ? 1 : -1;
285 }
286
287 /*
288 * "isnan()" function
289 */
290 void
291 f_isnan(typval_T *argvars, typval_T *rettv)
292 {
293 rettv->vval.v_number = argvars[0].v_type == VAR_FLOAT
294 && isnan(argvars[0].vval.v_float);
295 }
296 # endif
297
298 /*
299 * "log()" function
300 */
301 void
302 f_log(typval_T *argvars, typval_T *rettv)
303 {
304 float_T f = 0.0;
305
306 rettv->v_type = VAR_FLOAT;
307 if (get_float_arg(argvars, &f) == OK)
308 rettv->vval.v_float = log(f);
309 else
310 rettv->vval.v_float = 0.0;
311 }
312
313 /*
314 * "log10()" function
315 */
316 void
317 f_log10(typval_T *argvars, typval_T *rettv)
318 {
319 float_T f = 0.0;
320
321 rettv->v_type = VAR_FLOAT;
322 if (get_float_arg(argvars, &f) == OK)
323 rettv->vval.v_float = log10(f);
324 else
325 rettv->vval.v_float = 0.0;
326 }
327
328 /*
329 * "pow()" function
330 */
331 void
332 f_pow(typval_T *argvars, typval_T *rettv)
333 {
334 float_T fx = 0.0, fy = 0.0;
335
336 rettv->v_type = VAR_FLOAT;
337 if (get_float_arg(argvars, &fx) == OK
338 && get_float_arg(&argvars[1], &fy) == OK)
339 rettv->vval.v_float = pow(fx, fy);
340 else
341 rettv->vval.v_float = 0.0;
342 }
343
344
345 /*
346 * round() is not in C90, use ceil() or floor() instead.
347 */
348 float_T
349 vim_round(float_T f)
350 {
351 return f > 0 ? floor(f + 0.5) : ceil(f - 0.5);
352 }
353
354 /*
355 * "round({float})" function
356 */
357 void
358 f_round(typval_T *argvars, typval_T *rettv)
359 {
360 float_T f = 0.0;
361
362 rettv->v_type = VAR_FLOAT;
363 if (get_float_arg(argvars, &f) == OK)
364 rettv->vval.v_float = vim_round(f);
365 else
366 rettv->vval.v_float = 0.0;
367 }
368
369 /*
370 * "sin()" function
371 */
372 void
373 f_sin(typval_T *argvars, typval_T *rettv)
374 {
375 float_T f = 0.0;
376
377 rettv->v_type = VAR_FLOAT;
378 if (get_float_arg(argvars, &f) == OK)
379 rettv->vval.v_float = sin(f);
380 else
381 rettv->vval.v_float = 0.0;
382 }
383
384 /*
385 * "sinh()" function
386 */
387 void
388 f_sinh(typval_T *argvars, typval_T *rettv)
389 {
390 float_T f = 0.0;
391
392 rettv->v_type = VAR_FLOAT;
393 if (get_float_arg(argvars, &f) == OK)
394 rettv->vval.v_float = sinh(f);
395 else
396 rettv->vval.v_float = 0.0;
397 }
398
399 /*
400 * "sqrt()" function
401 */
402 void
403 f_sqrt(typval_T *argvars, typval_T *rettv)
404 {
405 float_T f = 0.0;
406
407 rettv->v_type = VAR_FLOAT;
408 if (get_float_arg(argvars, &f) == OK)
409 rettv->vval.v_float = sqrt(f);
410 else
411 rettv->vval.v_float = 0.0;
412 }
413
414 /*
415 * "str2float()" function
416 */
417 void
418 f_str2float(typval_T *argvars, typval_T *rettv)
419 {
420 char_u *p = skipwhite(tv_get_string(&argvars[0]));
421 int isneg = (*p == '-');
422
423 if (*p == '+' || *p == '-')
424 p = skipwhite(p + 1);
425 (void)string2float(p, &rettv->vval.v_float);
426 if (isneg)
427 rettv->vval.v_float *= -1;
428 rettv->v_type = VAR_FLOAT;
429 }
430
431 /*
432 * "tan()" function
433 */
434 void
435 f_tan(typval_T *argvars, typval_T *rettv)
436 {
437 float_T f = 0.0;
438
439 rettv->v_type = VAR_FLOAT;
440 if (get_float_arg(argvars, &f) == OK)
441 rettv->vval.v_float = tan(f);
442 else
443 rettv->vval.v_float = 0.0;
444 }
445
446 /*
447 * "tanh()" function
448 */
449 void
450 f_tanh(typval_T *argvars, typval_T *rettv)
451 {
452 float_T f = 0.0;
453
454 rettv->v_type = VAR_FLOAT;
455 if (get_float_arg(argvars, &f) == OK)
456 rettv->vval.v_float = tanh(f);
457 else
458 rettv->vval.v_float = 0.0;
459 }
460
461 /*
462 * "trunc({float})" function
463 */
464 void
465 f_trunc(typval_T *argvars, typval_T *rettv)
466 {
467 float_T f = 0.0;
468
469 rettv->v_type = VAR_FLOAT;
470 if (get_float_arg(argvars, &f) == OK)
471 // trunc() is not in C90, use floor() or ceil() instead.
472 rettv->vval.v_float = f > 0 ? floor(f) : ceil(f);
473 else
474 rettv->vval.v_float = 0.0;
475 }
476
477 #endif