[CALC] Improve multi-precision support, and powers/roots. CORE-8486
authorCarlo-Bramini <carlo_bramini@users.sourceforge.net>
Mon, 6 Aug 2018 07:54:21 +0000 (09:54 +0200)
committerHermès Bélusca-Maïto <hermes.belusca-maito@reactos.org>
Mon, 18 Mar 2019 00:34:00 +0000 (01:34 +0100)
- 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
base/applications/calc/fun_ieee.c
base/applications/calc/fun_mpfr.c
base/applications/calc/help.txt
base/applications/calc/resource.h
base/applications/calc/rpn_ieee.c
base/applications/calc/rpn_mpfr.c
base/applications/calc/utl_ieee.c
base/applications/calc/utl_mpfr.c
base/applications/calc/winmain.c

index d1f23a2..702ad47 100644 (file)
@@ -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);
index b5f4ab8..3e8ba68 100644 (file)
@@ -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;
index 8d15340..27c7f37 100644 (file)
@@ -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;
index be9ccd8..453ba26 100644 (file)
@@ -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
index 8218462..c9a3ac0 100644 (file)
 #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
index a6f4e41..0649789 100644 (file)
@@ -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)
 {
 }
-
index 93d6f00..d555bc2 100644 (file)
@@ -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);
 }
index c240bf2..69be266 100644 (file)
@@ -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;
index 048b3b9..5c2d797 100644 (file)
@@ -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;
     }
 }
-
index e976131..c6723ba 100644 (file)
@@ -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)