2 * ReactOS Calc (Math functions, IEEE-754 engine)
4 * Copyright 2007-2017, Carlo Bramini
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 static double validate_rad2angle(double a
);
24 static double validate_angle2rad(calc_number_t
*c
);
26 void apply_int_mask(calc_number_t
*r
)
28 unsigned __int64 mask
;
44 mask
= (unsigned __int64
)-1;
49 double asinh(double x
)
51 return log(x
+sqrt(x
*x
+1));
54 double acosh(double x
)
56 // must be x>=1, if not return Nan (Not a Number)
57 if(!(x
>=1.0)) return sqrt(-1.0);
59 // return only the positive result (as sqrt does).
60 return log(x
+sqrt(x
*x
-1.0));
63 double atanh(double x
)
65 // must be x>-1, x<1, if not return Nan (Not a Number)
66 if(!(x
>-1.0 && x
<1.0)) return sqrt(-1.0);
68 return log((1.0+x
)/(1.0-x
))/2.0;
71 static double validate_rad2angle(double a
)
75 a
= a
* (180.0/CALC_PI
);
80 a
= a
* (200.0/CALC_PI
);
86 static double validate_angle2rad(calc_number_t
*c
)
90 c
->f
= c
->f
* (CALC_PI
/180.0);
95 c
->f
= c
->f
* (CALC_PI
/200.0);
101 void rpn_sin(calc_number_t
*c
)
103 double angle
= validate_angle2rad(c
);
105 if (angle
== 0 || angle
== CALC_PI
)
108 if (angle
== CALC_3_PI_2
)
111 if (angle
== CALC_2_PI
)
116 void rpn_cos(calc_number_t
*c
)
118 double angle
= validate_angle2rad(c
);
120 if (angle
== CALC_PI_2
|| angle
== CALC_3_PI_2
)
123 if (angle
== CALC_PI
)
126 if (angle
== CALC_2_PI
)
131 void rpn_tan(calc_number_t
*c
)
133 double angle
= validate_angle2rad(c
);
135 if (angle
== CALC_PI_2
|| angle
== CALC_3_PI_2
)
138 if (angle
== CALC_PI
|| angle
== CALC_2_PI
)
144 void rpn_asin(calc_number_t
*c
)
146 c
->f
= validate_rad2angle(asin(c
->f
));
150 void rpn_acos(calc_number_t
*c
)
152 c
->f
= validate_rad2angle(acos(c
->f
));
156 void rpn_atan(calc_number_t
*c
)
158 c
->f
= validate_rad2angle(atan(c
->f
));
163 void rpn_sinh(calc_number_t
*c
)
169 void rpn_cosh(calc_number_t
*c
)
175 void rpn_tanh(calc_number_t
*c
)
182 void rpn_asinh(calc_number_t
*c
)
188 void rpn_acosh(calc_number_t
*c
)
194 void rpn_atanh(calc_number_t
*c
)
201 void rpn_int(calc_number_t
*c
)
205 modf(calc
.code
.f
, &int_part
);
209 void rpn_frac(calc_number_t
*c
)
213 c
->f
= modf(calc
.code
.f
, &int_part
);
216 void rpn_reci(calc_number_t
*c
)
224 void rpn_fact(calc_number_t
*c
)
226 double fact
, mult
, num
;
228 if (calc
.base
== IDC_RADIO_DEC
)
246 while (mult
<= num
) {
252 if (_finite(fact
) == 0)
255 if (calc
.base
== IDC_RADIO_DEC
)
258 c
->i
= (__int64
)fact
;
261 __int64
logic_dbl2int(calc_number_t
*a
)
266 modf(a
->f
, &int_part
);
267 width
= (int_part
==0) ? 1 : (int)log10(fabs(int_part
))+1;
272 return (__int64
)int_part
;
275 double logic_int2dbl(calc_number_t
*a
)
280 void rpn_not(calc_number_t
*c
)
282 if (calc
.base
== IDC_RADIO_DEC
) {
284 n
.i
= logic_dbl2int(c
);
285 c
->f
= (long double)(~n
.i
);
290 void rpn_pi(calc_number_t
*c
)
295 void rpn_2pi(calc_number_t
*c
)
300 void rpn_sign(calc_number_t
*c
)
302 if (calc
.base
== IDC_RADIO_DEC
)
308 void rpn_exp2(calc_number_t
*c
)
310 if (calc
.base
== IDC_RADIO_DEC
) {
312 if (_finite(c
->f
) == 0)
318 void rpn_exp3(calc_number_t
*c
)
320 if (calc
.base
== IDC_RADIO_DEC
) {
321 c
->f
= pow(c
->f
, 3.);
322 if (_finite(c
->f
) == 0)
328 static __int64
myabs64(__int64 number
)
330 return (number
< 0) ? 0-number
: number
;
333 static unsigned __int64
sqrti(unsigned __int64 number
)
335 /* modified form of Newton's method for approximating roots */
336 #define NEXT(n, i) (((n) + (i)/(n)) >> 1)
337 unsigned __int64 n
, n1
;
340 if (number
== 0xffffffffffffffffULL
)
342 if (number
== 0xffffffffffffffffUI
64)
347 n1
= NEXT(n
, number
);
348 while (myabs64(n1
- n
) > 1) {
350 n1
= NEXT(n
, number
);
352 while((n1
*n1
) > number
)
358 void rpn_sqrt(calc_number_t
*c
)
360 if (calc
.base
== IDC_RADIO_DEC
) {
370 static __int64
cbrti(__int64 x
) {
377 b
= (3*y
*(y
+ 1) + 1) << s
;
387 void rpn_cbrt(calc_number_t
*c
)
389 if (calc
.base
== IDC_RADIO_DEC
)
390 #if defined(__GNUC__) && !defined(__REACTOS__)
393 c
->f
= pow(c
->f
,1./3.);
400 void rpn_exp(calc_number_t
*c
)
403 if (_finite(c
->f
) == 0)
407 void rpn_exp10(calc_number_t
*c
)
411 modf(c
->f
, &int_part
);
412 if (fmod(int_part
, 2.) == 0.)
415 c
->f
= pow(10., c
->f
);
416 if (_finite(c
->f
) == 0)
421 void rpn_ln(calc_number_t
*c
)
429 void rpn_log(calc_number_t
*c
)
437 static double stat_sum(void)
440 statistic_t
*p
= calc
.stat
;
443 if (p
->base
== IDC_RADIO_DEC
)
447 p
= (statistic_t
*)(p
->next
);
452 static double stat_sum2(void)
455 statistic_t
*p
= calc
.stat
;
458 if (p
->base
== IDC_RADIO_DEC
)
459 sum
+= p
->num
.f
* p
->num
.f
;
461 sum
+= (double)p
->num
.i
* (double)p
->num
.i
;
462 p
= (statistic_t
*)(p
->next
);
467 void rpn_ave(calc_number_t
*c
)
473 n
= SendDlgItemMessage(calc
.hStatWnd
, IDC_LIST_STAT
, LB_GETCOUNT
, 0, 0);
476 ave
= ave
/ (double)n
;
477 if (calc
.base
== IDC_RADIO_DEC
)
483 void rpn_ave2(calc_number_t
*c
)
489 n
= SendDlgItemMessage(calc
.hStatWnd
, IDC_LIST_STAT
, LB_GETCOUNT
, 0, 0);
492 ave
= ave
/ (double)n
;
493 if (calc
.base
== IDC_RADIO_DEC
)
499 void rpn_sum(calc_number_t
*c
)
501 double sum
= stat_sum();
503 if (calc
.base
== IDC_RADIO_DEC
)
509 void rpn_sum2(calc_number_t
*c
)
511 double sum
= stat_sum2();
513 if (calc
.base
== IDC_RADIO_DEC
)
519 static void rpn_s_ex(calc_number_t
*c
, int pop_type
)
525 statistic_t
*p
= calc
.stat
;
528 n
= (double)SendDlgItemMessage(calc
.hStatWnd
, IDC_LIST_STAT
, LB_GETCOUNT
, 0, 0);
539 if (p
->base
== IDC_RADIO_DEC
)
542 num
= (double)p
->num
.i
;
543 dev
+= pow(num
-ave
, 2.);
544 p
= (statistic_t
*)(p
->next
);
546 dev
= sqrt(dev
/(pop_type
? n
-1 : n
));
547 if (calc
.base
== IDC_RADIO_DEC
)
553 void rpn_s(calc_number_t
*c
)
558 void rpn_s_m1(calc_number_t
*c
)
563 void rpn_dms2dec(calc_number_t
*c
)
567 m
= modf(c
->f
, &d
) * 100;
568 s
= (modf(m
, &m
) * 100)+.5;
577 void rpn_dec2dms(calc_number_t
*c
)
581 m
= modf(c
->f
, &d
) * 60;
582 s
= ceil(modf(m
, &m
) * 60);
583 c
->f
= d
+ m
/100. + s
/10000.;
586 void rpn_zero(calc_number_t
*c
)
591 void rpn_copy(calc_number_t
*dst
, calc_number_t
*src
)
596 int rpn_is_zero(calc_number_t
*c
)
601 void rpn_alloc(calc_number_t
*c
)
605 void rpn_free(calc_number_t
*c
)