https://git.reactos.org/?p=reactos.git;a=commitdiff;h=295eaf4e326f9ac0904022...
commit 295eaf4e326f9ac09040222833fcf58ee28fd107 Author: Carlo-Bramini carlo_bramini@users.sourceforge.net AuthorDate: Mon Aug 6 09:54:21 2018 +0200 Commit: Hermès Bélusca-Maïto hermes.belusca-maito@reactos.org CommitDate: Mon Mar 18 01:34:00 2019 +0100
[CALC] Improve multi-precision support, and powers/roots. CORE-8486
- Added support for average of squares and mean of squares into statistical functions. - pop() and push() functions in RPN engines now work with nodes instead of stack units. - Moved the POW and SQR operations near the operators. CORE-12766
- Fix number of digits for IEEE-754 constants. - Show all available digits in exp notation. CORE-14871
- Update help correspondingly. --- base/applications/calc/calc.h | 27 +++++----- base/applications/calc/fun_ieee.c | 73 ++++++++++++++++++++++++-- base/applications/calc/fun_mpfr.c | 64 ++++++++++++++++++++++- base/applications/calc/help.txt | 10 +++- base/applications/calc/resource.h | 1 + base/applications/calc/rpn_ieee.c | 80 ++++++++++++++++++---------- base/applications/calc/rpn_mpfr.c | 106 ++++++++++++++++++++++---------------- base/applications/calc/utl_ieee.c | 58 ++++++++++++++------- base/applications/calc/utl_mpfr.c | 33 +++++++++--- base/applications/calc/winmain.c | 50 +++++++++--------- 10 files changed, 360 insertions(+), 142 deletions(-)
diff --git a/base/applications/calc/calc.h b/base/applications/calc/calc.h index d1f23a2811..702ad47e77 100644 --- a/base/applications/calc/calc.h +++ b/base/applications/calc/calc.h @@ -11,6 +11,7 @@ #ifndef DISABLE_HTMLHELP_SUPPORT #include <htmlhelp.h> #endif +#include <limits.h>
/* Messages reserved for the main dialog */ #define WM_CLOSE_STATS (WM_APP+1) @@ -21,8 +22,9 @@ #define WM_HANDLE_FROM (WM_APP+6) #define WM_HANDLE_TO (WM_APP+7)
+/* GNU MULTI-PRECISION LIBRARY support */ #ifdef ENABLE_MULTI_PRECISION -#include <mpfr.h> +#include "mpfr.h"
#ifndef MPFR_DEFAULT_RND #define MPFR_DEFAULT_RND mpfr_get_default_rounding_mode () @@ -155,11 +157,11 @@ typedef struct {
extern calc_t calc;
-#define CALC_E 2.7182818284590452354 - -#define CALC_PI_2 1.57079632679489661923 -#define CALC_PI 3.14159265358979323846 -#define CALC_3_PI_2 4.71238898038468985769 +/* IEEE constants */ +#define CALC_E 2.718281828459045235360 +#define CALC_PI_2 1.570796326794896619231 +#define CALC_PI 3.141592653589793238462 +#define CALC_3_PI_2 4.712388980384689857694 #define CALC_2_PI 6.283185307179586476925
#define MODIFIER_INV 0x01 @@ -167,14 +169,9 @@ extern calc_t calc; #define NO_CHAIN 0x04
void apply_int_mask(calc_number_t *a); -#ifdef ENABLE_MULTI_PRECISION -void validate_rad2angle(calc_number_t *c); -void validate_angle2rad(calc_number_t *c); -#else +#ifndef ENABLE_MULTI_PRECISION __int64 logic_dbl2int(calc_number_t *a); double logic_int2dbl(calc_number_t *a); -double validate_rad2angle(double a); -double validate_angle2rad(calc_number_t *c); #endif void rpn_sin(calc_number_t *c); void rpn_cos(calc_number_t *c); @@ -206,7 +203,9 @@ void rpn_exp10(calc_number_t *c); void rpn_ln(calc_number_t *c); void rpn_log(calc_number_t *c); void rpn_ave(calc_number_t *c); +void rpn_ave2(calc_number_t *c); void rpn_sum(calc_number_t *c); +void rpn_sum2(calc_number_t *c); void rpn_s(calc_number_t *c); void rpn_s_m1(calc_number_t *c); void rpn_dms2dec(calc_number_t *c); @@ -217,10 +216,14 @@ int rpn_is_zero(calc_number_t *c); void rpn_alloc(calc_number_t *c); void rpn_free(calc_number_t *c);
+// + void prepare_rpn_result_2(calc_number_t *rpn, TCHAR *buffer, int size, int base); void convert_text2number_2(calc_number_t *a); void convert_real_integer(unsigned int base);
+// + INT_PTR CALLBACK AboutDlgProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp);
void ConvExecute(HWND hWnd); diff --git a/base/applications/calc/fun_ieee.c b/base/applications/calc/fun_ieee.c index b5f4ab8824..3e8ba68de8 100644 --- a/base/applications/calc/fun_ieee.c +++ b/base/applications/calc/fun_ieee.c @@ -1,6 +1,27 @@ +/* + * ReactOS Calc (Math functions, IEEE-754 engine) + * + * Copyright 2007-2017, Carlo Bramini + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + #include "calc.h"
-#include <limits.h> +static double validate_rad2angle(double a); +static double validate_angle2rad(calc_number_t *c);
void apply_int_mask(calc_number_t *r) { @@ -47,7 +68,7 @@ double atanh(double x) return log((1.0+x)/(1.0-x))/2.0; }
-double validate_rad2angle(double a) +static double validate_rad2angle(double a) { switch (calc.degr) { case IDC_RADIO_DEG: @@ -62,7 +83,7 @@ double validate_rad2angle(double a) return a; }
-double validate_angle2rad(calc_number_t *c) +static double validate_angle2rad(calc_number_t *c) { switch (calc.degr) { case IDC_RADIO_DEG: @@ -250,6 +271,7 @@ __int64 logic_dbl2int(calc_number_t *a) } return (__int64)int_part; } + double logic_int2dbl(calc_number_t *a) { return (double)a->i; @@ -315,9 +337,9 @@ static unsigned __int64 sqrti(unsigned __int64 number) unsigned __int64 n, n1;
#ifdef __GNUC__ - if (number == 0xffffffffffffffffLL) + if (number == 0xffffffffffffffffULL) #else - if (number == 0xffffffffffffffff) + if (number == 0xffffffffffffffffUI64) #endif return 0xffffffff;
@@ -427,6 +449,21 @@ static double stat_sum(void) return sum; }
+static double stat_sum2(void) +{ + double sum = 0; + statistic_t *p = calc.stat; + + while (p != NULL) { + if (p->base == IDC_RADIO_DEC) + sum += p->num.f * p->num.f; + else + sum += (double)p->num.i * (double)p->num.i; + p = (statistic_t *)(p->next); + } + return sum; +} + void rpn_ave(calc_number_t *c) { double ave = 0; @@ -443,6 +480,22 @@ void rpn_ave(calc_number_t *c) c->i = (__int64)ave; }
+void rpn_ave2(calc_number_t *c) +{ + double ave = 0; + int n; + + ave = stat_sum2(); + n = SendDlgItemMessage(calc.hStatWnd, IDC_LIST_STAT, LB_GETCOUNT, 0, 0); + + if (n) + ave = ave / (double)n; + if (calc.base == IDC_RADIO_DEC) + c->f = ave; + else + c->i = (__int64)ave; +} + void rpn_sum(calc_number_t *c) { double sum = stat_sum(); @@ -453,6 +506,16 @@ void rpn_sum(calc_number_t *c) c->i = (__int64)sum; }
+void rpn_sum2(calc_number_t *c) +{ + double sum = stat_sum2(); + + if (calc.base == IDC_RADIO_DEC) + c->f = sum; + else + c->i = (__int64)sum; +} + static void rpn_s_ex(calc_number_t *c, int pop_type) { double ave = 0; diff --git a/base/applications/calc/fun_mpfr.c b/base/applications/calc/fun_mpfr.c index 8d1534048a..27c7f37b7e 100644 --- a/base/applications/calc/fun_mpfr.c +++ b/base/applications/calc/fun_mpfr.c @@ -1,5 +1,28 @@ +/* + * ReactOS Calc (Math functions, GMP/MPFR engine) + * + * Copyright 2007-2017, Carlo Bramini + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + #include "calc.h"
+static void validate_rad2angle(calc_number_t *c); +static void validate_angle2rad(calc_number_t *c); + void apply_int_mask(calc_number_t *r) { mpz_t a, mask; @@ -28,7 +51,7 @@ void apply_int_mask(calc_number_t *r) mpz_clear(mask); }
-void validate_rad2angle(calc_number_t *r) +static void validate_rad2angle(calc_number_t *r) { mpfr_t mult, divs;
@@ -55,7 +78,7 @@ void validate_rad2angle(calc_number_t *r) mpfr_clear(divs); }
-void validate_angle2rad(calc_number_t *r) +static void validate_angle2rad(calc_number_t *r) { mpfr_t mult, divs;
@@ -341,6 +364,21 @@ static void stat_sum(mpfr_t sum) } }
+static void stat_sum2(mpfr_t sum) +{ + statistic_t *p = calc.stat; + mpfr_t sqr; + + mpfr_init(sqr); + mpfr_set_ui(sum, 0, MPFR_DEFAULT_RND); + while (p != NULL) { + mpfr_mul(sqr, p->num.mf, p->num.mf, MPFR_DEFAULT_RND); + mpfr_add(sum, sum, sqr, MPFR_DEFAULT_RND); + p = (statistic_t *)(p->next); + } + mpfr_clear(sqr); +} + void rpn_ave(calc_number_t *c) { int n; @@ -355,6 +393,20 @@ void rpn_ave(calc_number_t *c) mpfr_trunc(c->mf, c->mf); }
+void rpn_ave2(calc_number_t *c) +{ + int n; + + stat_sum2(c->mf); + n = SendDlgItemMessage(calc.hStatWnd, IDC_LIST_STAT, LB_GETCOUNT, 0, 0); + + if (n) + mpfr_div_ui(c->mf, c->mf, n, MPFR_DEFAULT_RND); + + if (calc.base != IDC_RADIO_DEC) + mpfr_trunc(c->mf, c->mf); +} + void rpn_sum(calc_number_t *c) { stat_sum(c->mf); @@ -363,6 +415,14 @@ void rpn_sum(calc_number_t *c) mpfr_trunc(c->mf, c->mf); }
+void rpn_sum2(calc_number_t *c) +{ + stat_sum2(c->mf); + + if (calc.base != IDC_RADIO_DEC) + mpfr_trunc(c->mf, c->mf); +} + static void rpn_s_ex(calc_number_t *c, int pop_type) { mpfr_t dev; diff --git a/base/applications/calc/help.txt b/base/applications/calc/help.txt index be9ccd87fd..453ba2641d 100644 --- a/base/applications/calc/help.txt +++ b/base/applications/calc/help.txt @@ -204,10 +204,16 @@ It deletes all numbers currently stored into the list. While the statistical window is shown, four additional buttons are enabled: [Ave] It calculates the arithmetic average of the numbers stored into the list. +[Ave] + [Inv] +It calculates the arithmetic average of the squares of the numbers stored into the list. [Sum] It calculates the sum of all numbers stored into the list. +[Sum] + [Inv] +It calculates the sum of the squares of all numbers stored into the list. [s] -It calculates the population standard deviations of the numbers stored into the list. +It calculates the population standard deviations with base 'n-1' of the numbers stored into the list. +[s] + [Inv] +It calculates the population standard deviations with base 'n' of the numbers stored into the list. [Dat] It inserts the number shown into the output display into the list.
@@ -483,10 +489,12 @@ Shortcut from keyboard: CTRL-S
Ave It calculates the arithmetic average of the numbers stored into the statistical box. +When used with [Inv] modifier it calculates the average of squares. Shortcut from keyboard: CTRL-A
Sum It calculates the sum of the numbers stored into the statistical box. +When used with [Inv] modifier it calculates the summation of squares. Shortcut from keyboard: CTRL-T
s diff --git a/base/applications/calc/resource.h b/base/applications/calc/resource.h index 82184624c5..c9a3ac0e21 100644 --- a/base/applications/calc/resource.h +++ b/base/applications/calc/resource.h @@ -101,6 +101,7 @@ #define IDC_COMBO_FROM 1091 #define IDC_COMBO_TO 1092 #define IDC_BUTTON_RSH 1093 +#define IDC_BUTTON_XrY 1094
/* TYPES OF CONVERSIONS */ #define IDS_CONV_ANGLE 2000 diff --git a/base/applications/calc/rpn_ieee.c b/base/applications/calc/rpn_ieee.c index a6f4e417b0..0649789a4f 100644 --- a/base/applications/calc/rpn_ieee.c +++ b/base/applications/calc/rpn_ieee.c @@ -1,3 +1,23 @@ +/* + * ReactOS Calc (RPN encoder/decoder for IEEE-754 engine) + * + * Copyright 2007-2017, Carlo Bramini + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + #include "calc.h"
typedef struct { @@ -15,7 +35,7 @@ typedef struct { } calc_operator_t;
static stack_node_t *stack; -static stack_node_t temp; +static calc_node_t temp; static BOOL percent_mode;
static void rpn_add_f(calc_number_t *r, calc_number_t *a, calc_number_t *b); @@ -67,14 +87,20 @@ static const calc_operator_t operator_list[] = { { 7, rpn_sqr_f, NULL, NULL, }, // RPN_OPERATOR_SQR };
-static stack_node_t *pop(void) +static calc_node_t *pop(void) { + void *next; + if (stack == NULL) return NULL;
- temp = *stack; + /* copy the node */ + temp = stack->node; + next = stack->next; + + /* free the node */ free(stack); - stack = temp.next; + stack = next;
return &temp; } @@ -84,11 +110,11 @@ static int is_stack_empty(void) return (stack == NULL); }
-static void push(stack_node_t *op) +static void push(calc_node_t *op) { stack_node_t *z = (stack_node_t *)malloc(sizeof(stack_node_t));
- *z = *op; + z->node = *op; z->next = stack; stack = z; } @@ -330,20 +356,20 @@ void run_operator(calc_node_t *result,
static void evalStack(calc_number_t *number) { - stack_node_t *op, ip; + calc_node_t *op, ip; unsigned int prec;
op = pop(); ip = *op; - prec = operator_list[ip.node.operation].prec; + prec = operator_list[ip.operation].prec; while (!is_stack_empty()) { op = pop();
- if (prec <= operator_list[op->node.operation].prec) { - if (op->node.operation == RPN_OPERATOR_PARENT) continue; + if (prec <= operator_list[op->operation].prec) { + if (op->operation == RPN_OPERATOR_PARENT) continue;
- calc.prev = ip.node.number; - run_operator(&ip.node, &op->node, &ip.node, op->node.operation); + calc.prev = ip.number; + run_operator(&ip, op, &ip, op->operation); if (calc.is_nan) { flush_postfix(); return; @@ -354,17 +380,17 @@ static void evalStack(calc_number_t *number) } }
- if(ip.node.operation != RPN_OPERATOR_EQUAL && ip.node.operation != RPN_OPERATOR_PERCENT) + if (ip.operation != RPN_OPERATOR_EQUAL && ip.operation != RPN_OPERATOR_PERCENT) push(&ip);
- calc.prev_operator = op->node.operation; + calc.prev_operator = op->operation;
- *number = ip.node.number; + *number = ip.number; }
int exec_infix2postfix(calc_number_t *number, unsigned int func) { - stack_node_t tmp; + calc_node_t tmp;
if (is_stack_empty() && func == RPN_OPERATOR_EQUAL) { /* if a number has been entered with exponential */ @@ -377,10 +403,9 @@ int exec_infix2postfix(calc_number_t *number, unsigned int func) if (func == RPN_OPERATOR_PERCENT) percent_mode = TRUE;
- tmp.node.number = *number; - tmp.node.base = calc.base; - tmp.node.operation = func; - tmp.next = NULL; + tmp.number = *number; + tmp.base = calc.base; + tmp.operation = func;
push(&tmp);
@@ -410,23 +435,23 @@ void exec_change_infix(void)
void exec_closeparent(calc_number_t *number) { - stack_node_t *op, ip; + calc_node_t *op, ip;
- ip.node.number = *number; - ip.node.base = calc.base; + ip.number = *number; + ip.base = calc.base; while (!is_stack_empty()) { op = pop();
- if (op->node.operation == RPN_OPERATOR_PARENT) + if (op->operation == RPN_OPERATOR_PARENT) break;
- run_operator(&ip.node, &op->node, &ip.node, op->node.operation); + run_operator(&ip, op, &ip, op->operation); if (calc.is_nan) { flush_postfix(); return; } } - *number = ip.node.number; + *number = ip.number; }
int eval_parent_count(void) @@ -442,7 +467,7 @@ int eval_parent_count(void) return n; }
-void flush_postfix() +void flush_postfix(void) { while (!is_stack_empty()) pop(); @@ -459,4 +484,3 @@ void start_rpn_engine(void) void stop_rpn_engine(void) { } - diff --git a/base/applications/calc/rpn_mpfr.c b/base/applications/calc/rpn_mpfr.c index 93d6f00f20..d555bc2108 100644 --- a/base/applications/calc/rpn_mpfr.c +++ b/base/applications/calc/rpn_mpfr.c @@ -1,3 +1,23 @@ +/* + * ReactOS Calc (RPN encoder/decoder for GMP/MPFR engine) + * + * Copyright 2007-2017, Carlo Bramini + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + #include "calc.h"
typedef struct { @@ -15,7 +35,7 @@ typedef struct { } calc_operator_t;
static stack_node_t *stack; -static stack_node_t temp; +static calc_node_t temp; static BOOL percent_mode;
static void rpn_add_f(calc_number_t *r, calc_number_t *a, calc_number_t *b); @@ -61,25 +81,27 @@ static const calc_operator_t operator_list[] = { { 7, rpn_sqr_f, NULL, NULL, }, // RPN_OPERATOR_SQR };
-static void node_copy(stack_node_t *dst, stack_node_t *src) +static void node_copy(calc_node_t *dst, calc_node_t *src) { - mpfr_set(dst->node.number.mf,src->node.number.mf,MPFR_DEFAULT_RND); - dst->node.operation = src->node.operation; - dst->next = src->next; + mpfr_set(dst->number.mf, src->number.mf, MPFR_DEFAULT_RND); + dst->operation = src->operation; }
-static stack_node_t *pop() +static calc_node_t *pop(void) { + void *next; + if (stack == NULL) return NULL;
/* copy the node */ - node_copy(&temp, stack); + node_copy(&temp, &stack->node); + next = stack->next;
/* free the node */ mpfr_clear(stack->node.number.mf); free(stack); - stack = temp.next; + stack = next;
return &temp; } @@ -89,12 +111,12 @@ static int is_stack_empty(void) return (stack == NULL); }
-static void push(stack_node_t *op) +static void push(calc_node_t *op) { stack_node_t *z = (stack_node_t *)malloc(sizeof(stack_node_t));
- mpfr_init_set(z->node.number.mf,op->node.number.mf,MPFR_DEFAULT_RND); - z->node.operation = op->node.operation; + mpfr_init_set(z->node.number.mf, op->number.mf, MPFR_DEFAULT_RND); + z->node.operation = op->operation; z->next = stack; stack = z; } @@ -109,8 +131,7 @@ static unsigned int get_prec(unsigned int opc) } */
-typedef -__GMP_DECLSPEC void (*exec_call_t) +typedef void (*exec_call_t) __GMP_PROTO ((mpz_ptr, mpz_srcptr, mpz_srcptr));
static void rpn_exec_int(calc_number_t *r, calc_number_t *a, calc_number_t *b, exec_call_t cb) @@ -286,7 +307,6 @@ static void rpn_div_p(calc_number_t *r, calc_number_t *a, calc_number_t *b) } }
- void run_operator(calc_node_t *result, calc_node_t *a, calc_node_t *b, @@ -307,44 +327,44 @@ void run_operator(calc_node_t *result,
static void evalStack(calc_number_t *number) { - stack_node_t *op, ip; + calc_node_t *op, ip; unsigned int prec;
- mpfr_init(ip.node.number.mf); + mpfr_init(ip.number.mf); op = pop(); node_copy(&ip, op); - prec = operator_list[ip.node.operation].prec; + prec = operator_list[ip.operation].prec; while (!is_stack_empty()) { op = pop();
- if (prec <= operator_list[op->node.operation].prec) { - if (op->node.operation == RPN_OPERATOR_PARENT) continue; + if (prec <= operator_list[op->operation].prec) { + if (op->operation == RPN_OPERATOR_PARENT) continue;
- rpn_copy(&calc.prev, &ip.node.number); - run_operator(&ip.node, &op->node, &ip.node, op->node.operation); + rpn_copy(&calc.prev, &ip.number); + run_operator(&ip, op, &ip, op->operation); if (calc.is_nan) { flush_postfix(); - mpfr_clear(ip.node.number.mf); + mpfr_clear(ip.number.mf); return; } } else { push(op); break; - } + } }
- if(ip.node.operation != RPN_OPERATOR_EQUAL && ip.node.operation != RPN_OPERATOR_PERCENT) + if (ip.operation != RPN_OPERATOR_EQUAL && ip.operation != RPN_OPERATOR_PERCENT) push(&ip);
- calc.prev_operator = op->node.operation; + calc.prev_operator = op->operation;
- rpn_copy(number, &ip.node.number); - mpfr_clear(ip.node.number.mf); + rpn_copy(number, &ip.number); + mpfr_clear(ip.number.mf); }
int exec_infix2postfix(calc_number_t *number, unsigned int func) { - stack_node_t tmp; + calc_node_t tmp;
if (is_stack_empty() && func == RPN_OPERATOR_EQUAL) { /* if a number has been entered with exponential */ @@ -357,12 +377,12 @@ int exec_infix2postfix(calc_number_t *number, unsigned int func) if (func == RPN_OPERATOR_PERCENT) percent_mode = TRUE;
- mpfr_init(tmp.node.number.mf); - rpn_copy(&tmp.node.number, number); - tmp.node.operation = func; + mpfr_init(tmp.number.mf); + rpn_copy(&tmp.number, number); + tmp.operation = func;
push(&tmp); - mpfr_clear(tmp.node.number.mf); + mpfr_clear(tmp.number.mf);
if (func == RPN_OPERATOR_NONE) return 0; @@ -390,24 +410,24 @@ void exec_change_infix(void)
void exec_closeparent(calc_number_t *number) { - stack_node_t *op, ip; + calc_node_t *op, ip;
- rpn_alloc(&ip.node.number); - rpn_copy(&ip.node.number, number); + rpn_alloc(&ip.number); + rpn_copy(&ip.number, number); while (!is_stack_empty()) { op = pop();
- if (op->node.operation == RPN_OPERATOR_PARENT) + if (op->operation == RPN_OPERATOR_PARENT) break;
- run_operator(&ip.node, &op->node, &ip.node, op->node.operation); + run_operator(&ip, op, &ip, op->operation); if (calc.is_nan) { flush_postfix(); return; } } - rpn_copy(number, &ip.node.number); - rpn_free(&ip.node.number); + rpn_copy(number, &ip.number); + rpn_free(&ip.number); }
int eval_parent_count(void) @@ -423,12 +443,12 @@ int eval_parent_count(void) return n; }
-void flush_postfix() +void flush_postfix(void) { while (!is_stack_empty()) pop(); /* clear prev and last typed operators */ - calc.prev_operator = + calc.prev_operator = calc.last_operator = 0; }
@@ -440,7 +460,7 @@ void start_rpn_engine(void) mpfr_init(calc.code.mf); mpfr_init(calc.prev.mf); mpfr_init(calc.memory.number.mf); - mpfr_init(temp.node.number.mf); + mpfr_init(temp.number.mf); rpn_zero(&calc.memory.number); }
@@ -449,5 +469,5 @@ void stop_rpn_engine(void) mpfr_clear(calc.code.mf); mpfr_clear(calc.prev.mf); mpfr_clear(calc.memory.number.mf); - mpfr_clear(temp.node.number.mf); + mpfr_clear(temp.number.mf); } diff --git a/base/applications/calc/utl_ieee.c b/base/applications/calc/utl_ieee.c index c240bf2855..69be266f61 100644 --- a/base/applications/calc/utl_ieee.c +++ b/base/applications/calc/utl_ieee.c @@ -1,3 +1,23 @@ +/* + * ReactOS Calc (Utility functions for IEEE-754 engine) + * + * Copyright 2007-2017, Carlo Bramini + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + #include "calc.h"
void prepare_rpn_result_2(calc_number_t *rpn, TCHAR *buffer, int size, int base) @@ -7,7 +27,7 @@ void prepare_rpn_result_2(calc_number_t *rpn, TCHAR *buffer, int size, int base)
switch (base) { case IDC_RADIO_HEX: - _stprintf(buffer, TEXT("%I64X"), rpn->i); + _stprintf(buffer, _T("%I64X"), rpn->i); break; case IDC_RADIO_DEC: /* @@ -19,44 +39,44 @@ void prepare_rpn_result_2(calc_number_t *rpn, TCHAR *buffer, int size, int base) #define MAX_LD_WIDTH 16 /* calculate the width of integer number */ width = (rpn->f==0) ? 1 : (int)log10(fabs(rpn->f))+1; - if ((calc.sci_out != FALSE) || (width > MAX_LD_WIDTH) || (width < -MAX_LD_WIDTH)) - _stprintf(buffer, TEXT("%#e"), rpn->f); + if (calc.sci_out == TRUE || width > MAX_LD_WIDTH || width < -MAX_LD_WIDTH) + _stprintf(buffer, _T("%#.*e"), MAX_LD_WIDTH-1, rpn->f); else { TCHAR *ptr, *dst;
- ptr = buffer + _stprintf(buffer, TEXT("%#*.*f"), width, ((MAX_LD_WIDTH-width-1)>=0) ? MAX_LD_WIDTH-width-1 : 0, rpn->f); + ptr = buffer + _stprintf(buffer, _T("%#*.*f"), width, ((MAX_LD_WIDTH-width-1)>=0) ? MAX_LD_WIDTH-width-1 : 0, rpn->f); /* format string ensures there is a '.': */ - dst = _tcschr(buffer, TEXT('.')); + dst = _tcschr(buffer, _T('.')); while (--ptr > dst) - if (*ptr != TEXT('0')) + if (*ptr != _T('0')) break;
/* put the string terminator for removing the final '0' (if any) */ - ptr[1] = TEXT('\0'); + ptr[1] = _T('\0'); /* check if the number finishes with '.' */ if (ptr == dst) /* remove the dot (it will be re-added later) */ - ptr[0] = TEXT('\0'); + ptr[0] = _T('\0'); } #undef MAX_LD_WIDTH break; case IDC_RADIO_OCT: - _stprintf(buffer, TEXT("%I64o"), rpn->i); + _stprintf(buffer, _T("%I64o"), rpn->i); break; case IDC_RADIO_BIN: if (rpn->i == 0) { - buffer[0] = TEXT('0'); - buffer[1] = TEXT('\0'); + buffer[0] = _T('0'); + buffer[1] = _T('\0'); break; } tmp = *rpn; - buffer[0] = TEXT('\0'); + buffer[0] = _T('\0'); while (tmp.u) { memmove(buffer+1, buffer, (size-1)*sizeof(TCHAR)); if (tmp.u & 1) - calc.buffer[0] = TEXT('1'); + buffer[0] = _T('1'); else - calc.buffer[0] = TEXT('0'); + buffer[0] = _T('0'); tmp.u >>= 1; } break; @@ -69,20 +89,20 @@ void convert_text2number_2(calc_number_t *a)
switch (calc.base) { case IDC_RADIO_HEX: - _stscanf(calc.buffer, TEXT("%I64X"), &(a->i)); + _stscanf(calc.buffer, _T("%I64X"), &(a->i)); break; case IDC_RADIO_DEC: - _stscanf(calc.buffer, TEXT("%lf"), &(a->f)); + _stscanf(calc.buffer, _T("%lf"), &(a->f)); break; case IDC_RADIO_OCT: - _stscanf(calc.buffer, TEXT("%I64o"), &(a->i)); + _stscanf(calc.buffer, _T("%I64o"), &(a->i)); break; case IDC_RADIO_BIN: ptr = calc.buffer; a->i = 0; - while (*ptr != TEXT('\0')) { + while (*ptr != _T('\0')) { a->i <<= 1; - if (*ptr++ == TEXT('1')) + if (*ptr++ == _T('1')) a->i |= 1; } break; diff --git a/base/applications/calc/utl_mpfr.c b/base/applications/calc/utl_mpfr.c index 048b3b92c6..5c2d797e80 100644 --- a/base/applications/calc/utl_mpfr.c +++ b/base/applications/calc/utl_mpfr.c @@ -1,3 +1,23 @@ +/* + * ReactOS Calc (Utility functions for GMP/MPFR engine) + * + * Copyright 2007-2017, Carlo Bramini + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + #include "calc.h"
void prepare_rpn_result_2(calc_number_t *rpn, TCHAR *buffer, int size, int base) @@ -39,7 +59,7 @@ void prepare_rpn_result_2(calc_number_t *rpn, TCHAR *buffer, int size, int base) width = 1 + mpfr_get_si(t, MPFR_DEFAULT_RND); mpfr_clear(t); } - if ((calc.sci_out != FALSE) || (width > max_ld_width) || (width < -max_ld_width)) + if (calc.sci_out == TRUE || width > max_ld_width || width < -max_ld_width) ptr = temp + gmp_sprintf(temp, "%*.*#Fe", 1, max_ld_width, ff); else { ptr = temp + gmp_sprintf(temp, "%#*.*Ff", width, ((max_ld_width-width-1)>=0) ? max_ld_width-width-1 : 0, ff); @@ -62,8 +82,8 @@ void prepare_rpn_result_2(calc_number_t *rpn, TCHAR *buffer, int size, int base) case IDC_RADIO_BIN: /* if the number is zero, just write 0 ;) */ if (rpn_is_zero(rpn)) { - temp[0] = TEXT('0'); - temp[1] = TEXT('\0'); + temp[0] = _T('0'); + temp[1] = _T('\0'); break; } /* repeat until a bit set to '1' is found */ @@ -78,8 +98,8 @@ void prepare_rpn_result_2(calc_number_t *rpn, TCHAR *buffer, int size, int base) } while (1); /* now revert the string into TCHAR buffer */ for (q=0; q<n; q++) - buffer[n-q-1] = (temp[q] == '1') ? TEXT('1') : TEXT('0'); - buffer[n] = TEXT('\0'); + buffer[n-q-1] = (temp[q] == '1') ? _T('1') : _T('0'); + buffer[n] = _T('\0');
mpz_clear(zz); mpf_clear(ff); @@ -87,7 +107,7 @@ void prepare_rpn_result_2(calc_number_t *rpn, TCHAR *buffer, int size, int base) } mpz_clear(zz); mpf_clear(ff); - _sntprintf(buffer, SIZEOF(calc.buffer), TEXT("%s"), temp); + _sntprintf(buffer, SIZEOF(calc.buffer), _T("%hs"), temp); }
void convert_text2number_2(calc_number_t *a) @@ -135,4 +155,3 @@ void convert_real_integer(unsigned int base) break; } } - diff --git a/base/applications/calc/winmain.c b/base/applications/calc/winmain.c index e976131996..c6723bac18 100644 --- a/base/applications/calc/winmain.c +++ b/base/applications/calc/winmain.c @@ -166,6 +166,8 @@ static const WORD operator_codes[] = { IDC_BUTTON_MULT, // RPN_OPERATOR_MULT IDC_BUTTON_DIV, // RPN_OPERATOR_DIV IDC_BUTTON_MOD, // RPN_OPERATOR_MOD + IDC_BUTTON_XeY, // RPN_OPERATOR_POW + IDC_BUTTON_XrY, // RPN_OPERATOR_SQR };
typedef void (*rpn_callback1)(calc_number_t *); @@ -180,8 +182,6 @@ typedef struct { rpn_callback1 inv_hyp; } function_table_t;
-static void run_pow(calc_number_t *number); -static void run_sqr(calc_number_t *number); static void run_fe(calc_number_t *number); static void run_dat_sta(calc_number_t *number); static void run_mp(calc_number_t *c); @@ -205,10 +205,9 @@ static const function_table_t function_table[] = { { IDC_BUTTON_LN, MODIFIER_INV, 1, rpn_ln, rpn_exp, NULL, NULL }, { IDC_BUTTON_LOG, MODIFIER_INV, 1, rpn_log, rpn_exp10, NULL, NULL }, { IDC_BUTTON_NF, 0, 1, rpn_fact, NULL, NULL, NULL }, - { IDC_BUTTON_AVE, 0, 0, rpn_ave, NULL, NULL, NULL }, - { IDC_BUTTON_SUM, 0, 0, rpn_sum, NULL, NULL, NULL }, + { IDC_BUTTON_AVE, MODIFIER_INV, 0, rpn_ave, rpn_ave2, NULL, NULL }, + { IDC_BUTTON_SUM, MODIFIER_INV, 0, rpn_sum, rpn_sum2, NULL, NULL }, { IDC_BUTTON_S, MODIFIER_INV, 0, rpn_s_m1, rpn_s, NULL, NULL }, - { IDC_BUTTON_XeY, MODIFIER_INV, 1, run_pow, run_sqr, NULL, NULL }, { IDC_BUTTON_SQRT, MODIFIER_INV, 1, rpn_sqrt, NULL, NULL, NULL }, { IDC_BUTTON_DMS, MODIFIER_INV, 1, rpn_dec2dms, rpn_dms2dec, NULL, NULL }, { IDC_BUTTON_FE, 0, 1, run_fe, NULL, NULL, NULL }, @@ -1132,16 +1131,6 @@ static statistic_t *upload_stat_number(int n) return p; }
-static void run_pow(calc_number_t *number) -{ - exec_infix2postfix(number, RPN_OPERATOR_POW); -} - -static void run_sqr(calc_number_t *number) -{ - exec_infix2postfix(number, RPN_OPERATOR_SQR); -} - static void run_fe(calc_number_t *number) { calc.sci_out = ((calc.sci_out != FALSE) ? FALSE : TRUE); @@ -1531,17 +1520,29 @@ static INT_PTR CALLBACK DlgMainProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) case IDC_BUTTON_LSH: case IDC_BUTTON_RSH: case IDC_BUTTON_EQU: + case IDC_BUTTON_XeY: + case IDC_BUTTON_XrY: if (calc.is_nan) break; /* - * LSH button holds the RSH function too with INV modifier, - * but since it's a two operand operator, it must be handled here. + * LSH and XeY buttons hold also the RSH and XrY functions with INV modifier, + * but since they are two operand operators, they must be handled here. */ - if (LOWORD(wp) == IDC_BUTTON_LSH && - (get_modifiers(hWnd) & MODIFIER_INV)) { - PostMessage(hWnd, WM_COMMAND, MAKEWPARAM(IDC_BUTTON_RSH, BN_CLICKED), 0); - SendDlgItemMessage(hWnd, IDC_CHECK_INV, BM_SETCHECK, 0, 0); - break; + if ((get_modifiers(hWnd) & MODIFIER_INV)) + { + WPARAM IdcSim = IDC_STATIC; + + switch (LOWORD(wp)) { + case IDC_BUTTON_LSH: IdcSim = MAKEWPARAM(IDC_BUTTON_RSH, BN_CLICKED); break; + case IDC_BUTTON_XeY: IdcSim = MAKEWPARAM(IDC_BUTTON_XrY, BN_CLICKED); break; + } + + if (IdcSim != IDC_STATIC) + { + PostMessage(hWnd, WM_COMMAND, IdcSim, 0); + CheckDlgButton(hWnd, IDC_CHECK_INV, BST_UNCHECKED); + } } + for (x=0; x<SIZEOF(operator_codes); x++) { if (LOWORD(wp) == operator_codes[x]) { convert_text2number(&calc.code); @@ -1668,7 +1669,6 @@ static INT_PTR CALLBACK DlgMainProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) case IDC_BUTTON_SIN: case IDC_BUTTON_COS: case IDC_BUTTON_TAN: - case IDC_BUTTON_XeY: case IDC_BUTTON_MS: for (x=0; x<SIZEOF(function_table); x++) { if (LOWORD(wp) == function_table[x].idc) { @@ -1697,8 +1697,8 @@ static INT_PTR CALLBACK DlgMainProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) convert_text2number(&calc.code); cb(&calc.code); display_rpn_result(hWnd, &calc.code); - if (!(function_table[x].range & NO_CHAIN)) - exec_infix2postfix(&calc.code, RPN_OPERATOR_NONE); +// if (!(function_table[x].range & NO_CHAIN)) +// exec_infix2postfix(&calc.code, RPN_OPERATOR_NONE); if (function_table[x].range & MODIFIER_INV) SendDlgItemMessage(hWnd, IDC_CHECK_INV, BM_SETCHECK, 0, 0); if (function_table[x].range & MODIFIER_HYP)