82bd6f4661761b3668e8de0a226c44064f197c24
[reactos.git] / reactos / base / applications / calc / function.c
1 #include "calc.h"
2
3 void apply_int_mask(calc_number_t *r)
4 {
5 unsigned __int64 mask;
6
7 switch (calc.size) {
8 case IDC_RADIO_QWORD:
9 mask = _UI64_MAX;
10 break;
11 case IDC_RADIO_DWORD:
12 mask = ULONG_MAX;
13 break;
14 case IDC_RADIO_WORD:
15 mask = USHRT_MAX;
16 break;
17 case IDC_RADIO_BYTE:
18 mask = UCHAR_MAX;
19 break;
20 default:
21 mask = (unsigned __int64)-1;
22 }
23 r->i &= mask;
24 }
25
26 double asinh(double x)
27 {
28 return log(x+sqrt(x*x+1));
29 }
30
31 double acosh(double x)
32 {
33 // must be x>=1, if not return Nan (Not a Number)
34 if(!(x>=1.0)) return sqrt(-1.0);
35
36 // return only the positive result (as sqrt does).
37 return log(x+sqrt(x*x-1.0));
38 }
39
40 double atanh(double x)
41 {
42 // must be x>-1, x<1, if not return Nan (Not a Number)
43 if(!(x>-1.0 && x<1.0)) return sqrt(-1.0);
44
45 return log((1.0+x)/(1.0-x))/2.0;
46 }
47
48 double validate_rad2angle(double a)
49 {
50 switch (calc.degr) {
51 case IDC_RADIO_DEG:
52 a = a * (180.0/CALC_PI);
53 break;
54 case IDC_RADIO_RAD:
55 break;
56 case IDC_RADIO_GRAD:
57 a = a * (200.0/CALC_PI);
58 break;
59 }
60 return a;
61 }
62
63 double validate_angle2rad(calc_number_t *c)
64 {
65 switch (calc.degr) {
66 case IDC_RADIO_DEG:
67 c->f = c->f * (CALC_PI/180.0);
68 break;
69 case IDC_RADIO_RAD:
70 break;
71 case IDC_RADIO_GRAD:
72 c->f = c->f * (CALC_PI/200.0);
73 break;
74 }
75 return c->f;
76 }
77
78 void rpn_sin(calc_number_t *c)
79 {
80 double angle = validate_angle2rad(c);
81
82 if (angle == 0 || angle == CALC_PI)
83 c->f = 0;
84 else
85 if (angle == CALC_3_PI_2)
86 c->f = -1;
87 else
88 if (angle == CALC_2_PI)
89 c->f = 1;
90 else
91 c->f = sin(angle);
92 }
93 void rpn_cos(calc_number_t *c)
94 {
95 double angle = validate_angle2rad(c);
96
97 if (angle == CALC_PI_2 || angle == CALC_3_PI_2)
98 c->f = 0;
99 else
100 if (angle == CALC_PI)
101 c->f = -1;
102 else
103 if (angle == CALC_2_PI)
104 c->f = 1;
105 else
106 c->f = cos(angle);
107 }
108 void rpn_tan(calc_number_t *c)
109 {
110 double angle = validate_angle2rad(c);
111
112 if (angle == CALC_PI_2 || angle == CALC_3_PI_2)
113 calc.is_nan = TRUE;
114 else
115 if (angle == CALC_PI || angle == CALC_2_PI)
116 c->f = 0;
117 else
118 c->f = tan(angle);
119 }
120
121 void rpn_asin(calc_number_t *c)
122 {
123 c->f = validate_rad2angle(asin(c->f));
124 if (_isnan(c->f))
125 calc.is_nan = TRUE;
126 }
127 void rpn_acos(calc_number_t *c)
128 {
129 c->f = validate_rad2angle(acos(c->f));
130 if (_isnan(c->f))
131 calc.is_nan = TRUE;
132 }
133 void rpn_atan(calc_number_t *c)
134 {
135 c->f = validate_rad2angle(atan(c->f));
136 if (_isnan(c->f))
137 calc.is_nan = TRUE;
138 }
139
140 void rpn_sinh(calc_number_t *c)
141 {
142 c->f = sinh(c->f);
143 if (_isnan(c->f))
144 calc.is_nan = TRUE;
145 }
146 void rpn_cosh(calc_number_t *c)
147 {
148 c->f = cosh(c->f);
149 if (_isnan(c->f))
150 calc.is_nan = TRUE;
151 }
152 void rpn_tanh(calc_number_t *c)
153 {
154 c->f = tanh(c->f);
155 if (_isnan(c->f))
156 calc.is_nan = TRUE;
157 }
158
159 void rpn_asinh(calc_number_t *c)
160 {
161 c->f = asinh(c->f);
162 if (_isnan(c->f))
163 calc.is_nan = TRUE;
164 }
165 void rpn_acosh(calc_number_t *c)
166 {
167 c->f = acosh(c->f);
168 if (_isnan(c->f))
169 calc.is_nan = TRUE;
170 }
171 void rpn_atanh(calc_number_t *c)
172 {
173 c->f = atanh(c->f);
174 if (_isnan(c->f))
175 calc.is_nan = TRUE;
176 }
177
178 void rpn_int(calc_number_t *c)
179 {
180 double int_part;
181
182 modf(calc.code.f, &int_part);
183 c->f = int_part;
184 }
185
186 void rpn_frac(calc_number_t *c)
187 {
188 double int_part;
189
190 c->f = modf(calc.code.f, &int_part);
191 }
192
193 void rpn_reci(calc_number_t *c)
194 {
195 if (c->f == 0)
196 calc.is_nan = TRUE;
197 else
198 c->f = 1./c->f;
199 }
200
201 void rpn_fact(calc_number_t *c)
202 {
203 double fact, mult, num;
204
205 if (calc.base == IDC_RADIO_DEC)
206 num = c->f;
207 else
208 num = (double)c->i;
209 if (num > 1000) {
210 calc.is_nan = TRUE;
211 return;
212 }
213 if (num < 0) {
214 calc.is_nan = TRUE;
215 return;
216 } else
217 if (num == 0)
218 fact = 1;
219 else {
220 rpn_int(c);
221 fact = 1;
222 mult = 2;
223 while (mult <= num) {
224 fact *= mult;
225 mult++;
226 }
227 c->f = fact;
228 }
229 if (_finite(fact) == 0)
230 calc.is_nan = TRUE;
231 else
232 if (calc.base == IDC_RADIO_DEC)
233 c->f = fact;
234 else
235 c->i = (__int64)fact;
236 }
237
238 __int64 logic_dbl2int(calc_number_t *a)
239 {
240 double int_part;
241 int width;
242
243 modf(a->f, &int_part);
244 width = (int_part==0) ? 1 : (int)log10(fabs(int_part))+1;
245 if (width > 63) {
246 calc.is_nan = TRUE;
247 return 0;
248 }
249 return (__int64)int_part;
250 }
251 double logic_int2dbl(calc_number_t *a)
252 {
253 return (double)a->i;
254 }
255
256 void rpn_not(calc_number_t *c)
257 {
258 if (calc.base == IDC_RADIO_DEC) {
259 calc_number_t n;
260 n.i = logic_dbl2int(c);
261 c->f = (long double)(~n.i);
262 } else
263 c->i = ~c->i;
264 }
265
266 void rpn_pi(calc_number_t *c)
267 {
268 c->f = CALC_PI;
269 }
270
271 void rpn_2pi(calc_number_t *c)
272 {
273 c->f = CALC_PI*2;
274 }
275
276 void rpn_sign(calc_number_t *c)
277 {
278 if (calc.base == IDC_RADIO_DEC)
279 c->f = 0-c->f;
280 else
281 c->i = 0-c->i;
282 }
283
284 void rpn_exp2(calc_number_t *c)
285 {
286 if (calc.base == IDC_RADIO_DEC) {
287 c->f *= c->f;
288 if (_finite(c->f) == 0)
289 calc.is_nan = TRUE;
290 } else
291 c->i *= c->i;
292 }
293
294 void rpn_exp3(calc_number_t *c)
295 {
296 if (calc.base == IDC_RADIO_DEC) {
297 c->f = pow(c->f, 3.);
298 if (_finite(c->f) == 0)
299 calc.is_nan = TRUE;
300 } else
301 c->i *= (c->i*c->i);
302 }
303
304 static __int64 myabs64(__int64 number)
305 {
306 return (number < 0) ? 0-number : number;
307 }
308
309 static unsigned __int64 sqrti(unsigned __int64 number)
310 {
311 /* modified form of Newton's method for approximating roots */
312 #define NEXT(n, i) (((n) + (i)/(n)) >> 1)
313 unsigned __int64 n, n1;
314
315 #ifdef __GNUC__
316 if (number == 0xffffffffffffffffLL)
317 #else
318 if (number == 0xffffffffffffffff)
319 #endif
320 return 0xffffffff;
321
322 n = 1;
323 n1 = NEXT(n, number);
324 while (myabs64(n1 - n) > 1) {
325 n = n1;
326 n1 = NEXT(n, number);
327 }
328 while((n1*n1) > number)
329 n1--;
330 return n1;
331 #undef NEXT
332 }
333
334 void rpn_sqrt(calc_number_t *c)
335 {
336 if (calc.base == IDC_RADIO_DEC) {
337 if (c->f < 0)
338 calc.is_nan = TRUE;
339 else
340 c->f = sqrt(c->f);
341 } else {
342 c->i = sqrti(c->i);
343 }
344 }
345
346 static __int64 cbrti(__int64 x) {
347 __int64 s, y, b;
348
349 s = 60;
350 y = 0;
351 while(s >= 0) {
352 y = 2*y;
353 b = (3*y*(y + 1) + 1) << s;
354 s = s - 3;
355 if (x >= b) {
356 x = x - b;
357 y = y + 1;
358 }
359 }
360 return y;
361 }
362
363 void rpn_cbrt(calc_number_t *c)
364 {
365 if (calc.base == IDC_RADIO_DEC)
366 #if defined(__GNUC__) && !defined(__REACTOS__)
367 c->f = cbrt(c->f);
368 #else
369 c->f = pow(c->f,1./3.);
370 #endif
371 else {
372 c->i = cbrti(c->i);
373 }
374 }
375
376 void rpn_exp(calc_number_t *c)
377 {
378 c->f = exp(c->f);
379 if (_finite(c->f) == 0)
380 calc.is_nan = TRUE;
381 }
382
383 void rpn_exp10(calc_number_t *c)
384 {
385 double int_part;
386
387 modf(c->f, &int_part);
388 if (fmod(int_part, 2.) == 0.)
389 calc.is_nan = TRUE;
390 else {
391 c->f = pow(10., c->f);
392 if (_finite(c->f) == 0)
393 calc.is_nan = TRUE;
394 }
395 }
396
397 void rpn_ln(calc_number_t *c)
398 {
399 if (c->f <= 0)
400 calc.is_nan = TRUE;
401 else
402 c->f = log(c->f);
403 }
404
405 void rpn_log(calc_number_t *c)
406 {
407 if (c->f <= 0)
408 calc.is_nan = TRUE;
409 else
410 c->f = log10(c->f);
411 }
412
413 static double stat_sum(void)
414 {
415 double sum = 0;
416 statistic_t *p = calc.stat;
417
418 while (p != NULL) {
419 if (p->base == IDC_RADIO_DEC)
420 sum += p->num.f;
421 else
422 sum += p->num.i;
423 p = (statistic_t *)(p->next);
424 }
425 return sum;
426 }
427
428 void rpn_ave(calc_number_t *c)
429 {
430 double ave = 0;
431 int n;
432
433 ave = stat_sum();
434 n = SendDlgItemMessage(calc.hStatWnd, IDC_LIST_STAT, LB_GETCOUNT, 0, 0);
435
436 if (n)
437 ave = ave / (double)n;
438 if (calc.base == IDC_RADIO_DEC)
439 c->f = ave;
440 else
441 c->i = (__int64)ave;
442 }
443
444 void rpn_sum(calc_number_t *c)
445 {
446 double sum = stat_sum();
447
448 if (calc.base == IDC_RADIO_DEC)
449 c->f = sum;
450 else
451 c->i = (__int64)sum;
452 }
453
454 static void rpn_s_ex(calc_number_t *c, int pop_type)
455 {
456 double ave = 0;
457 double n = 0;
458 double dev = 0;
459 double num = 0;
460 statistic_t *p = calc.stat;
461
462 ave = stat_sum();
463 n = (double)SendDlgItemMessage(calc.hStatWnd, IDC_LIST_STAT, LB_GETCOUNT, 0, 0);
464
465 if (n == 0) {
466 c->f = 0;
467 return;
468 }
469 ave = ave / n;
470
471 dev = 0;
472 p = calc.stat;
473 while (p != NULL) {
474 if (p->base == IDC_RADIO_DEC)
475 num = p->num.f;
476 else
477 num = (double)p->num.i;
478 dev += pow(num-ave, 2.);
479 p = (statistic_t *)(p->next);
480 }
481 dev = sqrt(dev/(pop_type ? n-1 : n));
482 if (calc.base == IDC_RADIO_DEC)
483 c->f = dev;
484 else
485 c->i = (__int64)dev;
486 }
487
488 void rpn_s(calc_number_t *c)
489 {
490 rpn_s_ex(c, 0);
491 }
492
493 void rpn_s_m1(calc_number_t *c)
494 {
495 rpn_s_ex(c, 1);
496 }
497
498 void rpn_dms2dec(calc_number_t *c)
499 {
500 double d, m, s;
501
502 m = modf(c->f, &d) * 100;
503 s = (modf(m, &m) * 100)+.5;
504 modf(s, &s);
505
506 m = m/60;
507 s = s/3600;
508
509 c->f = d + m + s;
510 }
511
512 void rpn_dec2dms(calc_number_t *c)
513 {
514 double d, m, s;
515
516 m = modf(c->f, &d) * 60;
517 s = ceil(modf(m, &m) * 60);
518 c->f = d + m/100. + s/10000.;
519 }
520
521 void rpn_zero(calc_number_t *c)
522 {
523 c->f = 0;
524 }
525
526 void rpn_copy(calc_number_t *dst, calc_number_t *src)
527 {
528 *dst = *src;
529 }
530
531 int rpn_is_zero(calc_number_t *c)
532 {
533 return (c->f == 0);
534 }
535
536 void rpn_alloc(calc_number_t *c)
537 {
538 }
539
540 void rpn_free(calc_number_t *c)
541 {
542 }