gcalctool r2310 - in branches/gnome-2-24: . gcalctool
- From: rancell svn gnome org
- To: svn-commits-list gnome org
- Subject: gcalctool r2310 - in branches/gnome-2-24: . gcalctool
- Date: Sun, 23 Nov 2008 09:54:51 +0000 (UTC)
Author: rancell
Date: Sun Nov 23 09:54:51 2008
New Revision: 2310
URL: http://svn.gnome.org/viewvc/gcalctool?rev=2310&view=rev
Log:
Removed double conversion in boolean and 32 bit and 16 bit mask operations so they can handle larger numbers (Robert Ancell, Bug #509988)
Modified:
branches/gnome-2-24/ChangeLog
branches/gnome-2-24/gcalctool/mpmath.c
branches/gnome-2-24/gcalctool/mpmath.h
branches/gnome-2-24/gcalctool/unittest.c
Modified: branches/gnome-2-24/gcalctool/mpmath.c
==============================================================================
--- branches/gnome-2-24/gcalctool/mpmath.c (original)
+++ branches/gnome-2-24/gcalctool/mpmath.c Sun Nov 23 09:54:51 2008
@@ -14,8 +14,7 @@
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
- * 02111-1307, USA.
- */
+ * 02111-1307, USA. */
#include <assert.h>
#include <errno.h>
@@ -31,87 +30,95 @@
2.582249878e+120 /* Hexadecimal. */
};
-BOOLEAN
-ibool(double x)
-{
- BOOLEAN p = (BOOLEAN) x;
- return(p);
+static int hex_to_int(char digit)
+{
+ if (digit >= '0' && digit <= '9')
+ return digit - '0';
+ if (digit >= 'A' && digit <= 'F')
+ return digit - 'A' + 10;
+ if (digit >= 'a' && digit <= 'f')
+ return digit - 'a' + 10;
+ return 0;
}
-double
-setbool(BOOLEAN p)
+static void
+calc_bitwise(const int s1[MP_SIZE], const int s2[MP_SIZE], int (*bitwise_operator)(int, int), int t[MP_SIZE])
{
- BOOLEAN q;
- double val;
-
- q = p & 0x80000000;
- p &= 0x7fffffff;
- val = p;
- if (q) {
- val += 2147483648.0;
+ char text1[MAX_DIGITS], text2[MAX_DIGITS], text_out[MAX_DIGITS];
+ int offset1, offset2, offset_out;
+
+ make_fixed(text1, MAX_DIGITS, s1, HEX, MAX_DIGITS);
+ make_fixed(text2, MAX_DIGITS, s2, HEX, MAX_DIGITS);
+ offset1 = strlen(text1) - 1;
+ offset2 = strlen(text2) - 1;
+ offset_out = offset1 > offset2 ? offset1 : offset2;
+
+ /* Be at least 32 bits wide so inverse operations make sense */
+ if (offset_out < 7)
+ offset_out = 7;
+
+ /* Perform bitwise operator on each character from right to left */
+ for (text_out[offset_out+1] = '\0'; offset_out >= 0; offset_out--) {
+ int v1 = 0, v2 = 0;
+
+ if (offset1 >= 0) {
+ v1 = hex_to_int(text1[offset1]);
+ offset1--;
+ }
+ if (offset2 >= 0) {
+ v2 = hex_to_int(text2[offset2]);
+ offset2--;
+ }
+ text_out[offset_out] = digits[bitwise_operator(v1, v2)];
}
-
- return(val);
+
+ MPstr_to_num(text_out, HEX, t);
}
+static int calc_bitwise_and(int v1, int v2) { return v1 & v2; }
+static int calc_bitwise_or(int v1, int v2) { return v1 | v2; }
+static int calc_bitwise_xor(int v1, int v2) { return v1 ^ v2; }
+static int calc_bitwise_xnor(int v1, int v2) { return v1 ^ v2 ^ 0xF; }
+static int calc_bitwise_not(int v1, int dummy) { return v1 ^ 0xF; }
+
+
void
calc_and(const int s1[MP_SIZE], const int s2[MP_SIZE], int t[MP_SIZE])
{
- double dres, dval;
-
- dres = mp_cast_to_double(s1);
- dval = mp_cast_to_double(s2);
- dres = setbool(ibool(dres) & ibool(dval));
- mp_set_from_double(dres, t);
+ calc_bitwise(s1, s2, calc_bitwise_and, t);
}
void
calc_or(const int s1[MP_SIZE], const int s2[MP_SIZE], int t[MP_SIZE])
{
- double dres, dval;
-
- dres = mp_cast_to_double(s1);
- dval = mp_cast_to_double(s2);
- dres = setbool(ibool(dres) | ibool(dval));
- mp_set_from_double(dres, t);
+ calc_bitwise(s1, s2, calc_bitwise_or, t);
}
void
calc_xor(const int s1[MP_SIZE], const int s2[MP_SIZE], int t[MP_SIZE])
{
- double dres, dval;
-
- dres = mp_cast_to_double(s1);
- dval = mp_cast_to_double(s2);
- dres = setbool(ibool(dres) ^ ibool(dval));
- mp_set_from_double(dres, t);
+ calc_bitwise(s1, s2, calc_bitwise_xor, t);
}
void
calc_xnor(const int s1[MP_SIZE], const int s2[MP_SIZE], int t[MP_SIZE])
{
- double dres, dval;
-
- dres = mp_cast_to_double(s1);
- dval = mp_cast_to_double(s2);
- dres = setbool(~ibool(dres) ^ ibool(dval));
- mp_set_from_double(dres, t);
+ calc_bitwise(s1, s2, calc_bitwise_xnor, t);
}
void
calc_not(const int s1[MP_SIZE], int t[MP_SIZE])
{
- double dval = mp_cast_to_double(s1);
-
- dval = setbool(~ibool(dval));
- mp_set_from_double(dval, t);
+ int dummy[MP_SIZE];
+ mp_set_from_integer(0, dummy);
+ calc_bitwise(s1, dummy, calc_bitwise_not, t);
}
@@ -125,18 +132,28 @@
void
calc_u32(const int s1[MP_SIZE], int t1[MP_SIZE])
{
- double dval = mp_cast_to_double(s1);
- dval = setbool(ibool(dval));
- mp_set_from_double(dval, t1);
+ char text[MAX_DIGITS];
+ size_t len, offset;
+
+ /* Convert to a hexadecimal string and use last 8 characters */
+ make_fixed(text, MAX_DIGITS, s1, HEX, MAX_DIGITS);
+ len = strlen(text);
+ offset = len > 8 ? len - 8: 0;
+ MPstr_to_num(text + offset, HEX, t1);
}
void
calc_u16(const int s1[MP_SIZE], int t1[MP_SIZE])
{
- double dval = mp_cast_to_double(s1);
- dval = setbool(ibool(dval) & 0xffff);
- mp_set_from_double(dval, t1);
+ char text[MAX_DIGITS];
+ size_t len, offset;
+
+ /* Convert to a hexadecimal string and use last 4 characters */
+ make_fixed(text, MAX_DIGITS, s1, HEX, MAX_DIGITS);
+ len = strlen(text);
+ offset = len > 4 ? len - 4: 0;
+ MPstr_to_num(text + offset, HEX, t1);
}
@@ -201,8 +218,8 @@
int
calc_modulus(int op1[MP_SIZE],
- int op2[MP_SIZE],
- int result[MP_SIZE])
+ int op2[MP_SIZE],
+ int result[MP_SIZE])
{
int MP1[MP_SIZE], MP2[MP_SIZE];
@@ -217,8 +234,8 @@
mp_set_from_integer(0, MP1);
if ((mp_is_less_than(op2, MP1)
- && mp_is_greater_than(result, MP1)) ||
- mp_is_less_than(result, MP1)) {
+ && mp_is_greater_than(result, MP1)) ||
+ mp_is_less_than(result, MP1)) {
mp_add(result, op2, result);
}
@@ -673,34 +690,52 @@
void
calc_shift(int s[MP_SIZE], int t[MP_SIZE], int times)
{
- /* Implementation derived from old code.
- * Using BOOLEAN is strange at least. Assumed that
- * boolean means BINARY representation
- */
-
- BOOLEAN temp;
- double dval = mp_cast_to_double(s);
- temp = ibool(dval);
-
- /* There is a reason to do shift like this. Reason is that
- * processors define shift only in a certain range. i386 uses only 5
- * bits to describe shiftable amount. So, shift 32 times gives original
- * number. That can cause very strange results (and bugs).
- */
+ char text[MAX_DIGITS+1], text_out[MAX_DIGITS];
+ size_t i, length, out_length;
+ int upper_offset, lower_offset;
- if (times > 0)
- {
- while (times--) {
- temp = temp << 1;
- }
+ make_fixed(text, MAX_DIGITS+1, s, HEX, MAX_DIGITS);
+ length = out_length = strlen(text);
+
+ /* How many nibbles we are offset by */
+ if (times >= 0) {
+ upper_offset = times/4;
+ lower_offset = upper_offset + 1;
} else {
- while (times++) {
- temp = temp >> 1;
+ lower_offset = times/4;
+ upper_offset = lower_offset - 1;
+ }
+
+ /* If shifting left need more space for digits */
+ if (times >= 0) {
+ size_t extra = (times+3) / 4;
+ out_length += extra;
+ upper_offset -= extra;
+ lower_offset -= extra;
+ if (out_length > MAX_DIGITS)
+ return; // FIXME
+ }
+
+ for (i = 0; i < out_length; i++) {
+ int upper_bits = 0, lower_bits = 0;
+
+ if (i+upper_offset >= 0 && i+upper_offset < length)
+ upper_bits = hex_to_int(text[i+upper_offset]);
+ if (i+lower_offset >= 0 && i+lower_offset < length)
+ lower_bits = hex_to_int(text[i+lower_offset]);
+
+ if (times >= 0) {
+ upper_bits <<= times % 4;
+ lower_bits >>= 4 - (times % 4);
+ } else {
+ upper_bits <<= 4 - (-times % 4);
+ lower_bits >>= -times % 4;
}
+ text_out[i] = digits[(upper_bits | lower_bits) & 0xF];
}
-
- dval = setbool(temp);
- mp_set_from_double(dval, t);
+ text_out[i] = '\0';
+
+ MPstr_to_num(text_out, HEX, t);
}
@@ -811,7 +846,7 @@
*/
void
-make_fixed(char *target, int target_len, int *MPnumber, int base, int cmax, int toclear)
+make_fixed(char *target, int target_len, const int *MPnumber, int base, int cmax)
{
char half[MAXLINE], *optr;
int MP1base[MP_SIZE], MP1[MP_SIZE], MP2[MP_SIZE], MPval[MP_SIZE];
@@ -883,7 +918,7 @@
/* Convert engineering or scientific number in the given base. */
void
-make_eng_sci(char *target, int target_len, int *MPnumber, int base)
+make_eng_sci(char *target, int target_len, const int *MPnumber, int base)
{
char half[MAXLINE], fixed[MAX_DIGITS], *optr;
int MP1[MP_SIZE], MPatmp[MP_SIZE], MPval[MP_SIZE];
@@ -938,7 +973,7 @@
}
}
- make_fixed(fixed, MAX_DIGITS, MPmant, base, MAX_DIGITS-6, TRUE);
+ make_fixed(fixed, MAX_DIGITS, MPmant, base, MAX_DIGITS-6);
len = strlen(fixed);
for (i = 0; i < len; i++) {
*optr++ = fixed[i];
@@ -979,7 +1014,7 @@
/* Convert MP number to character string in the given base. */
void
-make_number(char *target, int target_len, int *MPnumber, int base, int ignoreError)
+make_number(char *target, int target_len, const int *MPnumber, int base, int ignoreError)
{
double val;
@@ -1003,7 +1038,7 @@
(v->dtype == FIX && val != 0.0 && (val > max_fix[base]))) {
make_eng_sci(target, target_len, MPnumber, base);
} else {
- make_fixed(target, target_len, MPnumber, base, MAX_DIGITS, TRUE);
+ make_fixed(target, target_len, MPnumber, base, MAX_DIGITS);
}
}
Modified: branches/gnome-2-24/gcalctool/mpmath.h
==============================================================================
--- branches/gnome-2-24/gcalctool/mpmath.h (original)
+++ branches/gnome-2-24/gcalctool/mpmath.h Sun Nov 23 09:54:51 2008
@@ -25,16 +25,9 @@
#include "mp.h"
#include "calctool.h"
-typedef unsigned long BOOLEAN;
-
-/* function parameters: t=target, s=source) */
-
-BOOLEAN ibool(double x);
-double setbool(BOOLEAN p);
-
/* Trigonometric functions types */
-enum trigfunc_type { sin_t, cos_t, tan_t, sinh_t, cosh_t, tanh_t,
- asin_t, acos_t, atan_t, asinh_t, acosh_t, atanh_t };
+enum trigfunc_type { sin_t, cos_t, tan_t, sinh_t, cosh_t, tanh_t,
+ asin_t, acos_t, atan_t, asinh_t, acosh_t, atanh_t };
int calc_trigfunc(enum trigfunc_type type, int s1[MP_SIZE], int t1[MP_SIZE]);
@@ -80,7 +73,7 @@
// FIXME: These should be merged together
void MPstr_to_num(const char *, enum base_type, int *);
void mp_set_from_string(const char *number, int t[MP_SIZE]);
-void make_fixed(char *, int, int *, int, int, int);
-void make_number(char *, int, int *, int, int);
+void make_fixed(char *, int, const int *, int, int);
+void make_number(char *, int, const int *, int, int);
#endif /*MPMATH_H*/
Modified: branches/gnome-2-24/gcalctool/unittest.c
==============================================================================
--- branches/gnome-2-24/gcalctool/unittest.c (original)
+++ branches/gnome-2-24/gcalctool/unittest.c Sun Nov 23 09:54:51 2008
@@ -44,7 +44,7 @@
return;
}
- make_fixed(result_str, MAXLINE, result, DEC, 10, FALSE);
+ make_fixed(result_str, MAXLINE, result, DEC, 100);
if(strcmp(result_str, expected) != 0)
printf("FAIL: '%s' -> '%s', expected '%s'\n", expression, result_str, expected);
else
@@ -101,7 +101,7 @@
test("(-10)^2", "100", 0);
test("Sqrt(4)", "2", 0);
- test("Sqrt(2)", "1.4142135", 0);
+ test("Sqrt(2)", "1.414213562", 0);
test("Int(3.2)", "3", 0);
test("Frac(3.2)", "0.2", 0);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]