1 /* 2 * ReactOS Calc (Utility functions for IEEE-754 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 23 void prepare_rpn_result_2(calc_number_t *rpn, TCHAR *buffer, int size, int base) 24 { 25 calc_number_t tmp; 26 int width; 27 28 switch (base) { 29 case IDC_RADIO_HEX: 30 _stprintf(buffer, _T("%I64X"), rpn->i); 31 break; 32 case IDC_RADIO_DEC: 33 /* 34 * Modified from 17 to 16 for fixing this bug: 35 * 14+14+6.3+6.3= 40.5999999 instead of 40.6 36 * So, it's probably better to leave the least 37 * significant digit out of the display. 38 */ 39 #define MAX_LD_WIDTH 16 40 /* calculate the width of integer number */ 41 width = (rpn->f==0) ? 1 : (int)log10(fabs(rpn->f))+1; 42 if (calc.sci_out == TRUE || width > MAX_LD_WIDTH || width < -MAX_LD_WIDTH) 43 _stprintf(buffer, _T("%#.*e"), MAX_LD_WIDTH-1, rpn->f); 44 else { 45 TCHAR *ptr, *dst; 46 47 ptr = buffer + _stprintf(buffer, _T("%#*.*f"), width, ((MAX_LD_WIDTH-width-1)>=0) ? MAX_LD_WIDTH-width-1 : 0, rpn->f); 48 /* format string ensures there is a '.': */ 49 dst = _tcschr(buffer, _T('.')); 50 while (--ptr > dst) 51 if (*ptr != _T('0')) 52 break; 53 54 /* put the string terminator for removing the final '0' (if any) */ 55 ptr[1] = _T('\0'); 56 /* check if the number finishes with '.' */ 57 if (ptr == dst) 58 /* remove the dot (it will be re-added later) */ 59 ptr[0] = _T('\0'); 60 } 61 #undef MAX_LD_WIDTH 62 break; 63 case IDC_RADIO_OCT: 64 _stprintf(buffer, _T("%I64o"), rpn->i); 65 break; 66 case IDC_RADIO_BIN: 67 if (rpn->i == 0) { 68 buffer[0] = _T('0'); 69 buffer[1] = _T('\0'); 70 break; 71 } 72 tmp = *rpn; 73 buffer[0] = _T('\0'); 74 while (tmp.u) { 75 memmove(buffer+1, buffer, (size-1)*sizeof(TCHAR)); 76 if (tmp.u & 1) 77 buffer[0] = _T('1'); 78 else 79 buffer[0] = _T('0'); 80 tmp.u >>= 1; 81 } 82 break; 83 } 84 } 85 86 void convert_text2number_2(calc_number_t *a) 87 { 88 TCHAR *ptr; 89 90 switch (calc.base) { 91 case IDC_RADIO_HEX: 92 _stscanf(calc.buffer, _T("%I64X"), &(a->i)); 93 break; 94 case IDC_RADIO_DEC: 95 _stscanf(calc.buffer, _T("%lf"), &(a->f)); 96 break; 97 case IDC_RADIO_OCT: 98 _stscanf(calc.buffer, _T("%I64o"), &(a->i)); 99 break; 100 case IDC_RADIO_BIN: 101 ptr = calc.buffer; 102 a->i = 0; 103 while (*ptr != _T('\0')) { 104 a->i <<= 1; 105 if (*ptr++ == _T('1')) 106 a->i |= 1; 107 } 108 break; 109 } 110 } 111 112 void convert_real_integer(unsigned int base) 113 { 114 switch (base) { 115 case IDC_RADIO_DEC: 116 calc.code.f = (double)calc.code.i; 117 break; 118 case IDC_RADIO_OCT: 119 case IDC_RADIO_BIN: 120 case IDC_RADIO_HEX: 121 if (calc.base == IDC_RADIO_DEC) { 122 calc.code.i = (__int64)calc.code.f; 123 apply_int_mask(&calc.code); 124 } 125 break; 126 } 127 } 128