https://git.reactos.org/?p=reactos.git;a=commitdiff;h=295eaf4e326f9ac090402…
commit 295eaf4e326f9ac09040222833fcf58ee28fd107
Author: Carlo-Bramini <carlo_bramini(a)users.sourceforge.net>
AuthorDate: Mon Aug 6 09:54:21 2018 +0200
Commit: Hermès Bélusca-Maïto <hermes.belusca-maito(a)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)