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