Lars Martin Hambro <lars_martin4 AT hotmail DOT com>
[reactos.git] / reactos / base / applications / calc / fun_mpfr.c
1 #include "calc.h"
2 #include <limits.h>
3
4 void apply_int_mask(calc_number_t *r)
5 {
6 mpz_t a, mask;
7
8 switch (calc.size) {
9 case IDC_RADIO_QWORD:
10 mpz_init_set_str(mask, "FFFFFFFFFFFFFFFF", 16);
11 break;
12 case IDC_RADIO_DWORD:
13 mpz_init_set_str(mask, "00000000FFFFFFFF", 16);
14 break;
15 case IDC_RADIO_WORD:
16 mpz_init_set_str(mask, "000000000000FFFF", 16);
17 break;
18 case IDC_RADIO_BYTE:
19 mpz_init_set_str(mask, "00000000000000FF", 16);
20 break;
21 default:
22 mpz_init_set_si(mask, -1);
23 }
24 mpz_init(a);
25 mpfr_get_z(a, r->mf, MPFR_DEFAULT_RND);
26 mpz_and(a, a, mask);
27 mpfr_set_z(r->mf, a, MPFR_DEFAULT_RND);
28 mpz_clear(a);
29 mpz_clear(mask);
30 }
31
32 void validate_rad2angle(calc_number_t *r)
33 {
34 mpfr_t mult, divs;
35
36 mpfr_init(mult);
37 mpfr_init(divs);
38 switch (calc.degr) {
39 case IDC_RADIO_DEG:
40 mpfr_set_ui(mult, 180, MPFR_DEFAULT_RND);
41 mpfr_const_pi(divs, MPFR_DEFAULT_RND);
42 break;
43 case IDC_RADIO_RAD:
44 mpfr_set_ui(mult, 1, MPFR_DEFAULT_RND);
45 mpfr_set_ui(divs, 1, MPFR_DEFAULT_RND);
46 break;
47 case IDC_RADIO_GRAD:
48 mpfr_set_ui(mult, 200, MPFR_DEFAULT_RND);
49 mpfr_const_pi(divs, MPFR_DEFAULT_RND);
50 break;
51 }
52 mpfr_mul(r->mf, r->mf, mult, MPFR_DEFAULT_RND);
53 mpfr_div(r->mf, r->mf, divs, MPFR_DEFAULT_RND);
54
55 mpfr_clear(mult);
56 mpfr_clear(divs);
57 }
58
59 void validate_angle2rad(calc_number_t *r)
60 {
61 mpfr_t mult, divs;
62
63 if (!mpfr_number_p(r->mf)) {
64 calc.is_nan = TRUE;
65 return;
66 }
67 mpfr_init(mult);
68 mpfr_init(divs);
69 switch (calc.degr) {
70 case IDC_RADIO_DEG:
71 mpfr_const_pi(mult, MPFR_DEFAULT_RND);
72 mpfr_set_ui(divs, 180, MPFR_DEFAULT_RND);
73 break;
74 case IDC_RADIO_RAD:
75 mpfr_set_ui(mult, 1, MPFR_DEFAULT_RND);
76 mpfr_set_ui(divs, 1, MPFR_DEFAULT_RND);
77 break;
78 case IDC_RADIO_GRAD:
79 mpfr_const_pi(mult, MPFR_DEFAULT_RND);
80 mpfr_set_ui(divs, 200, MPFR_DEFAULT_RND);
81 break;
82 }
83 mpfr_mul(r->mf, r->mf, mult, MPFR_DEFAULT_RND);
84 mpfr_div(r->mf, r->mf, divs, MPFR_DEFAULT_RND);
85
86 mpfr_clear(mult);
87 mpfr_clear(divs);
88 }
89
90 static void build_rad_const(
91 mpfr_t *mp_pi,
92 mpfr_t *mp_pi_2,
93 mpfr_t *mp_3_pi_2,
94 mpfr_t *mp_2_pi)
95 {
96 mpfr_init(*mp_pi);
97 mpfr_init(*mp_pi_2);
98 mpfr_init(*mp_3_pi_2);
99 mpfr_init(*mp_2_pi);
100 mpfr_const_pi(*mp_pi, MPFR_DEFAULT_RND);
101 mpfr_div_ui(*mp_pi_2, *mp_pi, 2, MPFR_DEFAULT_RND);
102 mpfr_mul_ui(*mp_3_pi_2, *mp_pi, 3, MPFR_DEFAULT_RND);
103 mpfr_div_ui(*mp_3_pi_2, *mp_3_pi_2, 2, MPFR_DEFAULT_RND);
104 mpfr_mul_ui(*mp_2_pi, *mp_pi, 2, MPFR_DEFAULT_RND);
105 }
106
107 void rpn_sin(calc_number_t *c)
108 {
109 mpfr_t mp_pi, mp_pi_2, mp_3_pi_2, mp_2_pi;
110
111 validate_angle2rad(c);
112 build_rad_const(&mp_pi, &mp_pi_2, &mp_3_pi_2, &mp_2_pi);
113
114 if (rpn_is_zero(c) || !mpfr_cmp(c->mf, mp_pi) || !mpfr_cmp(c->mf, mp_2_pi))
115 rpn_zero(c);
116 else
117 if (!mpfr_cmp(c->mf, mp_3_pi_2))
118 mpfr_set_si(c->mf, -1, MPFR_DEFAULT_RND);
119 else
120 if (!mpfr_cmp(c->mf, mp_pi_2))
121 mpfr_set_si(c->mf, 1, MPFR_DEFAULT_RND);
122 else {
123 mpfr_sin(c->mf, c->mf, MPFR_DEFAULT_RND);
124 if (!mpfr_number_p(c->mf)) calc.is_nan = TRUE;
125 }
126 mpfr_clear(mp_pi);
127 mpfr_clear(mp_pi_2);
128 mpfr_clear(mp_3_pi_2);
129 mpfr_clear(mp_2_pi);
130 }
131 void rpn_cos(calc_number_t *c)
132 {
133 mpfr_t mp_pi, mp_pi_2, mp_3_pi_2, mp_2_pi;
134
135 validate_angle2rad(c);
136 build_rad_const(&mp_pi, &mp_pi_2, &mp_3_pi_2, &mp_2_pi);
137
138 if (!mpfr_cmp(c->mf, mp_pi_2) || !mpfr_cmp(c->mf, mp_3_pi_2))
139 rpn_zero(c);
140 else
141 if (!mpfr_cmp(c->mf, mp_pi))
142 mpfr_set_si(c->mf, -1, MPFR_DEFAULT_RND);
143 else
144 if (!mpfr_cmp(c->mf, mp_2_pi))
145 mpfr_set_si(c->mf, 1, MPFR_DEFAULT_RND);
146 else {
147 mpfr_cos(c->mf, c->mf, MPFR_DEFAULT_RND);
148 if (!mpfr_number_p(c->mf)) calc.is_nan = TRUE;
149 }
150 mpfr_clear(mp_pi);
151 mpfr_clear(mp_pi_2);
152 mpfr_clear(mp_3_pi_2);
153 mpfr_clear(mp_2_pi);
154 }
155 void rpn_tan(calc_number_t *c)
156 {
157 mpfr_t mp_pi, mp_pi_2, mp_3_pi_2, mp_2_pi;
158
159 validate_angle2rad(c);
160 build_rad_const(&mp_pi, &mp_pi_2, &mp_3_pi_2, &mp_2_pi);
161
162 if (!mpfr_cmp(c->mf, mp_pi_2) || !mpfr_cmp(c->mf, mp_3_pi_2))
163 calc.is_nan = TRUE;
164 else
165 if (!mpfr_cmp(c->mf, mp_pi) || !mpfr_cmp(c->mf, mp_2_pi))
166 rpn_zero(c);
167 else {
168 mpfr_tan(c->mf, c->mf, MPFR_DEFAULT_RND);
169 if (!mpfr_number_p(c->mf)) calc.is_nan = TRUE;
170 }
171 mpfr_clear(mp_pi);
172 mpfr_clear(mp_pi_2);
173 mpfr_clear(mp_3_pi_2);
174 mpfr_clear(mp_2_pi);
175 }
176
177 void rpn_asin(calc_number_t *c)
178 {
179 mpfr_asin(c->mf, c->mf, MPFR_DEFAULT_RND);
180 validate_rad2angle(c);
181 }
182 void rpn_acos(calc_number_t *c)
183 {
184 mpfr_acos(c->mf, c->mf, MPFR_DEFAULT_RND);
185 validate_rad2angle(c);
186 }
187 void rpn_atan(calc_number_t *c)
188 {
189 mpfr_atan(c->mf, c->mf, MPFR_DEFAULT_RND);
190 validate_rad2angle(c);
191 }
192
193 void rpn_sinh(calc_number_t *c)
194 {
195 mpfr_sinh(c->mf, c->mf, MPFR_DEFAULT_RND);
196 if (!mpfr_number_p(c->mf)) calc.is_nan = TRUE;
197 }
198 void rpn_cosh(calc_number_t *c)
199 {
200 mpfr_cosh(c->mf, c->mf, MPFR_DEFAULT_RND);
201 if (!mpfr_number_p(c->mf)) calc.is_nan = TRUE;
202 }
203 void rpn_tanh(calc_number_t *c)
204 {
205 mpfr_tanh(c->mf, c->mf, MPFR_DEFAULT_RND);
206 if (!mpfr_number_p(c->mf)) calc.is_nan = TRUE;
207 }
208
209 void rpn_asinh(calc_number_t *c)
210 {
211 mpfr_asinh(c->mf, c->mf, MPFR_DEFAULT_RND);
212 if (!mpfr_number_p(c->mf)) calc.is_nan = TRUE;
213 }
214 void rpn_acosh(calc_number_t *c)
215 {
216 mpfr_acosh(c->mf, c->mf, MPFR_DEFAULT_RND);
217 if (!mpfr_number_p(c->mf)) calc.is_nan = TRUE;
218 }
219 void rpn_atanh(calc_number_t *c)
220 {
221 mpfr_atanh(c->mf, c->mf, MPFR_DEFAULT_RND);
222 if (!mpfr_number_p(c->mf)) calc.is_nan = TRUE;
223 }
224
225 void rpn_int(calc_number_t *c)
226 {
227 mpfr_trunc(c->mf, c->mf);
228 }
229
230 void rpn_frac(calc_number_t *c)
231 {
232 mpfr_frac(c->mf, c->mf, MPFR_DEFAULT_RND);
233 }
234
235 void rpn_reci(calc_number_t *c)
236 {
237 if (mpfr_sgn(c->mf) == 0)
238 calc.is_nan = TRUE;
239 else
240 mpfr_ui_div(c->mf, 1, c->mf, MPFR_DEFAULT_RND);
241 }
242
243 void rpn_fact(calc_number_t *c)
244 {
245 if (mpfr_sgn(c->mf) < 0) {
246 calc.is_nan = TRUE;
247 return;
248 }
249
250 mpfr_trunc(c->mf, c->mf);
251 if (mpfr_fits_ulong_p(c->mf, MPFR_DEFAULT_RND) == 0)
252 calc.is_nan = TRUE;
253 else {
254 mpfr_fac_ui(c->mf, mpfr_get_ui(c->mf, MPFR_DEFAULT_RND), MPFR_DEFAULT_RND);
255 if (!mpfr_number_p(c->mf)) calc.is_nan = TRUE;
256 }
257 }
258
259 void rpn_not(calc_number_t *c)
260 {
261 mpz_t a;
262
263 mpz_init(a);
264 mpfr_get_z(a, c->mf, MPFR_DEFAULT_RND);
265 mpz_com(a, a);
266 mpfr_set_z(c->mf, a, MPFR_DEFAULT_RND);
267 mpz_clear(a);
268 }
269
270 void rpn_pi(calc_number_t *c)
271 {
272 mpfr_const_pi(c->mf, MPFR_DEFAULT_RND);
273 }
274
275 void rpn_2pi(calc_number_t *c)
276 {
277 mpfr_const_pi(c->mf, MPFR_DEFAULT_RND);
278 mpfr_mul_ui(c->mf, c->mf, 2, MPFR_DEFAULT_RND);
279 }
280
281 void rpn_sign(calc_number_t *c)
282 {
283 mpfr_mul_si(c->mf, c->mf, -1, MPFR_DEFAULT_RND);
284 }
285
286 void rpn_exp2(calc_number_t *c)
287 {
288 mpfr_sqr(c->mf, c->mf, MPFR_DEFAULT_RND);
289 if (!mpfr_number_p(c->mf)) calc.is_nan = TRUE;
290 }
291
292 void rpn_exp3(calc_number_t *c)
293 {
294 mpfr_pow_ui(c->mf, c->mf, 3, MPFR_DEFAULT_RND);
295 if (!mpfr_number_p(c->mf)) calc.is_nan = TRUE;
296 }
297
298 void rpn_sqrt(calc_number_t *c)
299 {
300 mpfr_sqrt(c->mf, c->mf, MPFR_DEFAULT_RND);
301 if (!mpfr_number_p(c->mf)) calc.is_nan = TRUE;
302 }
303
304 void rpn_cbrt(calc_number_t *c)
305 {
306 mpfr_cbrt(c->mf, c->mf, MPFR_DEFAULT_RND);
307 if (!mpfr_number_p(c->mf)) calc.is_nan = TRUE;
308 }
309
310 void rpn_exp(calc_number_t *c)
311 {
312 mpfr_exp(c->mf, c->mf, MPFR_DEFAULT_RND);
313 if (!mpfr_number_p(c->mf)) calc.is_nan = TRUE;
314 }
315
316 void rpn_exp10(calc_number_t *c)
317 {
318 mpfr_exp10(c->mf, c->mf, MPFR_DEFAULT_RND);
319 if (!mpfr_number_p(c->mf)) calc.is_nan = TRUE;
320 }
321
322 void rpn_ln(calc_number_t *c)
323 {
324 mpfr_log(c->mf, c->mf, MPFR_DEFAULT_RND);
325 if (!mpfr_number_p(c->mf)) calc.is_nan = TRUE;
326 }
327
328 void rpn_log(calc_number_t *c)
329 {
330 mpfr_log10(c->mf, c->mf, MPFR_DEFAULT_RND);
331 if (!mpfr_number_p(c->mf)) calc.is_nan = TRUE;
332 }
333
334 static void stat_sum(mpfr_t sum)
335 {
336 statistic_t *p = calc.stat;
337
338 mpfr_set_ui(sum, 0, MPFR_DEFAULT_RND);
339 while (p != NULL) {
340 mpfr_add(sum, sum, p->num.mf, MPFR_DEFAULT_RND);
341 p = (statistic_t *)(p->next);
342 }
343 }
344
345 void rpn_ave(calc_number_t *c)
346 {
347 int n;
348
349 stat_sum(c->mf);
350 n = SendDlgItemMessage(calc.hStatWnd, IDC_LIST_STAT, LB_GETCOUNT, 0, 0);
351
352 if (n)
353 mpfr_div_ui(c->mf, c->mf, n, MPFR_DEFAULT_RND);
354
355 if (calc.base != IDC_RADIO_DEC)
356 mpfr_trunc(c->mf, c->mf);
357 }
358
359 void rpn_sum(calc_number_t *c)
360 {
361 stat_sum(c->mf);
362
363 if (calc.base != IDC_RADIO_DEC)
364 mpfr_trunc(c->mf, c->mf);
365 }
366
367 static void rpn_s_ex(calc_number_t *c, int pop_type)
368 {
369 mpfr_t dev;
370 mpfr_t num;
371 unsigned long n = 0;
372 statistic_t *p = calc.stat;
373
374 n = SendDlgItemMessage(calc.hStatWnd, IDC_LIST_STAT, LB_GETCOUNT, 0, 0);
375 if (n < 2) {
376 mpfr_set_ui(c->mf, 0, MPFR_DEFAULT_RND);
377 return;
378 }
379
380 stat_sum(c->mf);
381 mpfr_div_ui(c->mf, c->mf, n, MPFR_DEFAULT_RND);
382
383 mpfr_init(dev);
384 mpfr_init(num);
385
386 mpfr_set_ui(dev, 0, MPFR_DEFAULT_RND);
387 p = calc.stat;
388 while (p != NULL) {
389 mpfr_sub(num, p->num.mf, c->mf, MPFR_DEFAULT_RND);
390 mpfr_sqr(num, num, MPFR_DEFAULT_RND);
391 mpfr_add(dev, dev, num, MPFR_DEFAULT_RND);
392 p = (statistic_t *)(p->next);
393 }
394 mpfr_div_ui(c->mf, dev, pop_type ? n-1 : n, MPFR_DEFAULT_RND);
395 mpfr_sqrt(c->mf, c->mf, MPFR_DEFAULT_RND);
396
397 if (calc.base != IDC_RADIO_DEC)
398 mpfr_trunc(c->mf, c->mf);
399
400 mpfr_clear(dev);
401 mpfr_clear(num);
402 }
403
404 void rpn_s(calc_number_t *c)
405 {
406 rpn_s_ex(c, 0);
407 }
408
409 void rpn_s_m1(calc_number_t *c)
410 {
411 rpn_s_ex(c, 1);
412 }
413
414 void rpn_dms2dec(calc_number_t *c)
415 {
416 mpfr_t d, m, s;
417
418 mpfr_init(d);
419 mpfr_init(m);
420 mpfr_init(s);
421
422 mpfr_trunc(d, c->mf);
423 mpfr_frac(m, c->mf, MPFR_DEFAULT_RND);
424 mpfr_mul_ui(m, m, 100, MPFR_DEFAULT_RND);
425
426 mpfr_frac(s, m, MPFR_DEFAULT_RND);
427 mpfr_trunc(m, m);
428 mpfr_mul_ui(s, s, 100, MPFR_DEFAULT_RND);
429 mpfr_ceil(s, s);
430
431 mpfr_div_ui(m, m, 60, MPFR_DEFAULT_RND);
432 mpfr_div_ui(s, s, 3600, MPFR_DEFAULT_RND);
433 mpfr_add(c->mf, d, m, MPFR_DEFAULT_RND);
434 mpfr_add(c->mf, c->mf, s, MPFR_DEFAULT_RND);
435
436 mpfr_clear(d);
437 mpfr_clear(m);
438 mpfr_clear(s);
439 }
440
441 void rpn_dec2dms(calc_number_t *c)
442 {
443 mpfr_t d, m, s;
444
445 mpfr_init(d);
446 mpfr_init(m);
447 mpfr_init(s);
448
449 mpfr_trunc(d, c->mf);
450 mpfr_frac(m, c->mf, MPFR_DEFAULT_RND);
451 mpfr_mul_ui(m, m, 60, MPFR_DEFAULT_RND);
452
453 mpfr_frac(s, m, MPFR_DEFAULT_RND);
454 mpfr_trunc(m, m);
455 mpfr_mul_ui(s, s, 60, MPFR_DEFAULT_RND);
456 mpfr_ceil(s, s);
457
458 mpfr_div_ui(m, m, 100, MPFR_DEFAULT_RND);
459 mpfr_div_ui(s, s, 10000, MPFR_DEFAULT_RND);
460 mpfr_add(c->mf, d, m, MPFR_DEFAULT_RND);
461 mpfr_add(c->mf, c->mf, s, MPFR_DEFAULT_RND);
462
463 mpfr_clear(d);
464 mpfr_clear(m);
465 mpfr_clear(s);
466 }
467
468 void rpn_zero(calc_number_t *c)
469 {
470 mpfr_set_ui(c->mf, 0, MPFR_DEFAULT_RND);
471 }
472
473 void rpn_copy(calc_number_t *dst, calc_number_t *src)
474 {
475 mpfr_set(dst->mf, src->mf, MPFR_DEFAULT_RND);
476 }
477
478 int rpn_is_zero(calc_number_t *c)
479 {
480 return (mpfr_sgn(c->mf) == 0);
481 }
482
483 void rpn_alloc(calc_number_t *c)
484 {
485 mpfr_init(c->mf);
486 }
487
488 void rpn_free(calc_number_t *c)
489 {
490 mpfr_clear(c->mf);
491 }