ReactOS 0.4.16-dev-340-g0540c21
utl_mpfr.c
Go to the documentation of this file.
1/*
2 * ReactOS Calc (Utility functions for GMP/MPFR engine)
3 *
4 * Copyright 2007-2017, Carlo Bramini
5 *
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.
10 *
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.
15 *
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
19 */
20
21#include "calc.h"
22
24{
25 char temp[1024];
26 char *ptr, *dst;
27 int width, max_ld_width;
28 unsigned long int n, q;
29 mpz_t zz;
30 mpf_t ff;
31
32 mpz_init(zz);
33 mpf_init(ff);
34 mpfr_get_z(zz, rpn->mf, MPFR_DEFAULT_RND);
35 mpfr_get_f(ff, rpn->mf, MPFR_DEFAULT_RND);
36
37 switch (base) {
38 case IDC_RADIO_HEX:
39 gmp_sprintf(temp, "%ZX", zz);
40 break;
41 case IDC_RADIO_DEC:
42 /*
43 * The output display is much shorter in standard mode,
44 * so I'm forced to reduce the precision here :(
45 */
47 max_ld_width = 16;
48 else
49 max_ld_width = 64;
50
51 /* calculate the width of integer number */
52 if (mpf_sgn(ff) == 0)
53 width = 1;
54 else {
55 mpfr_t t;
56 mpfr_init(t);
57 mpfr_abs(t, rpn->mf, MPFR_DEFAULT_RND);
58 mpfr_log10(t, t, MPFR_DEFAULT_RND);
59 width = 1 + mpfr_get_si(t, MPFR_DEFAULT_RND);
60 mpfr_clear(t);
61 }
62 if (calc.sci_out == TRUE || width > max_ld_width || width < -max_ld_width)
63 ptr = temp + gmp_sprintf(temp, "%*.*#Fe", 1, max_ld_width, ff);
64 else {
65 ptr = temp + gmp_sprintf(temp, "%#*.*Ff", width, ((max_ld_width-width-1)>=0) ? max_ld_width-width-1 : 0, ff);
66 dst = strchr(temp, '.');
67 while (--ptr > dst)
68 if (*ptr != '0')
69 break;
70
71 /* put the string terminator for removing the final '0' (if any) */
72 ptr[1] = '\0';
73 /* check if the number finishes with '.' */
74 if (ptr == dst)
75 /* remove the dot (it will be re-added later) */
76 ptr[0] = '\0';
77 }
78 break;
79 case IDC_RADIO_OCT:
80 gmp_sprintf(temp, "%Zo", zz);
81 break;
82 case IDC_RADIO_BIN:
83 /* if the number is zero, just write 0 ;) */
84 if (rpn_is_zero(rpn)) {
85 temp[0] = _T('0');
86 temp[1] = _T('\0');
87 break;
88 }
89 /* repeat until a bit set to '1' is found */
90 n = 0;
91 do {
92 q = mpz_scan1(zz, n);
93 if (q == ULONG_MAX)
94 break;
95 while (n < q)
96 temp[n++] = '0';
97 temp[n++] = '1';
98 } while (1);
99 /* now revert the string into TCHAR buffer */
100 for (q=0; q<n; q++)
101 buffer[n-q-1] = (temp[q] == '1') ? _T('1') : _T('0');
102 buffer[n] = _T('\0');
103
104 mpz_clear(zz);
105 mpf_clear(ff);
106 return;
107 }
108 mpz_clear(zz);
109 mpf_clear(ff);
110 StringCchPrintf(buffer, size, _T("%hs"), temp);
111}
112
114{
115 int base;
116#ifdef UNICODE
117 int sz;
118 char *temp;
119#endif
120
121 switch (calc.base) {
122 case IDC_RADIO_HEX: base = 16; break;
123 case IDC_RADIO_DEC: base = 10; break;
124 case IDC_RADIO_OCT: base = 8; break;
125 case IDC_RADIO_BIN: base = 2; break;
126 default: return;
127 }
128#ifdef UNICODE
129/*
130 * libmpfr and libgmp accept only ascii chars.
131 */
132 sz = WideCharToMultiByte(CP_ACP, 0, calc.buffer, -1, NULL, 0, NULL, NULL);
133 if (!sz)
134 return;
135 temp = (char *)_alloca(sz);
136 sz = WideCharToMultiByte(CP_ACP, 0, calc.buffer, -1, temp, sz, NULL, NULL);
137 mpfr_strtofr(a->mf, temp, NULL, base, MPFR_DEFAULT_RND);
138#else
139 mpfr_strtofr(a->mf, calc.buffer, NULL, base, MPFR_DEFAULT_RND);
140#endif
141}
142
143void convert_real_integer(unsigned int base)
144{
145 switch (base) {
146 case IDC_RADIO_DEC:
147 break;
148 case IDC_RADIO_OCT:
149 case IDC_RADIO_BIN:
150 case IDC_RADIO_HEX:
151 if (calc.base == IDC_RADIO_DEC) {
152 mpfr_trunc(calc.code.mf, calc.code.mf);
154 }
155 break;
156 }
157}
char * strchr(const char *String, int ch)
Definition: utclib.c:501
#define IDC_RADIO_BIN
Definition: resource.h:26
#define IDC_RADIO_OCT
Definition: resource.h:25
#define IDC_RADIO_DEC
Definition: resource.h:24
#define IDC_RADIO_HEX
Definition: resource.h:23
void apply_int_mask(calc_number_t *a)
Definition: fun_ieee.c:26
calc_t calc
Definition: winmain.c:247
int rpn_is_zero(calc_number_t *c)
Definition: fun_ieee.c:596
@ CALC_LAYOUT_STANDARD
Definition: calc.h:162
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define CP_ACP
Definition: compat.h:109
#define WideCharToMultiByte
Definition: compat.h:111
GLdouble GLdouble t
Definition: gl.h:2047
GLint GLint GLsizei width
Definition: gl.h:1546
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
GLsizeiptr size
Definition: glext.h:5919
GLdouble n
Definition: glext.h:7729
GLuint buffer
Definition: glext.h:5915
GLenum GLenum dst
Definition: glext.h:6340
GLboolean GLboolean GLboolean GLboolean a
Definition: glext.h:6204
#define ULONG_MAX
Definition: intsafe.h:155
static PVOID ptr
Definition: dispmode.c:27
static calc_node_t temp
Definition: rpn_ieee.c:38
#define StringCchPrintf
Definition: strsafe.h:517
DWORD layout
Definition: calc.h:174
TCHAR buffer[MAX_CALC_SIZE]
Definition: calc.h:175
calc_number_t code
Definition: calc.h:178
BOOL sci_out
Definition: calc.h:184
DWORD base
Definition: calc.h:189
void prepare_rpn_result_2(calc_number_t *rpn, TCHAR *buffer, int size, int base)
Definition: utl_mpfr.c:23
void convert_text2number_2(calc_number_t *a)
Definition: utl_mpfr.c:113
void convert_real_integer(unsigned int base)
Definition: utl_mpfr.c:143
#define _T(x)
Definition: vfdio.h:22
char TCHAR
Definition: xmlstorage.h:189