[gcalctool] Support floor, ceiling, round, fractional notation. Fix fractional result for negative numbers
- From: Robert Ancell <rancell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gcalctool] Support floor, ceiling, round, fractional notation. Fix fractional result for negative numbers
- Date: Mon, 17 May 2010 06:44:26 +0000 (UTC)
commit 036cc9954a12c6c17392d4904b1aee55624f22e5
Author: Robert Ancell <robert ancell gmail com>
Date: Wed May 12 19:31:32 2010 +0200
Support floor, ceiling, round, fractional notation. Fix fractional result for negative numbers
src/mp-binary.c | 2 +-
src/mp-convert.c | 8 ++++----
src/mp-equation-lexer.l | 4 ++++
src/mp-equation-parser.y | 5 +++++
src/mp-equation.c | 2 +-
src/mp.c | 45 +++++++++++++++++++++++++++++++++++++++++----
src/mp.h | 12 +++++++++---
src/unittest.c | 30 ++++++++++++++++++++++++++----
8 files changed, 91 insertions(+), 17 deletions(-)
---
diff --git a/src/mp-binary.c b/src/mp-binary.c
index 4f75e40..8e11970 100644
--- a/src/mp-binary.c
+++ b/src/mp-binary.c
@@ -185,7 +185,7 @@ mp_shift(const MPNumber *x, int count, MPNumber *z)
for (i = 0; i < -count; i++)
multiplier *= 2;
mp_divide_integer(x, multiplier, &temp);
- mp_integer_component(&temp, z);
+ mp_floor(&temp, z);
}
}
diff --git a/src/mp-convert.c b/src/mp-convert.c
index f527b13..c57ee9e 100644
--- a/src/mp-convert.c
+++ b/src/mp-convert.c
@@ -523,7 +523,7 @@ mp_cast_to_string_real(const MPNumber *x, int default_base, int base, int accura
mp_add(&number, &temp, &number);
/* Split into integer and fractional component */
- mp_integer_component(&number, &integer_component);
+ mp_floor(&number, &integer_component);
mp_fractional_component(&number, &fractional_component);
/* Write out the integer component least significant digit to most */
@@ -532,11 +532,11 @@ mp_cast_to_string_real(const MPNumber *x, int default_base, int base, int accura
MPNumber t, t2, t3;
mp_divide_integer(&temp, base, &t);
- mp_integer_component(&t, &t);
+ mp_floor(&t, &t);
mp_multiply_integer(&t, base, &t2);
mp_subtract(&temp, &t2, &t3);
- mp_integer_component(&t3, &t3);
+ mp_floor(&t3, &t3);
g_string_prepend_c(string, digits[mp_cast_to_int(&t3)]);
@@ -553,7 +553,7 @@ mp_cast_to_string_real(const MPNumber *x, int default_base, int base, int accura
MPNumber digit;
mp_multiply_integer(&temp, base, &temp);
- mp_integer_component(&temp, &digit);
+ mp_floor(&temp, &digit);
d = mp_cast_to_int(&digit);
g_string_append_c(string, digits[d]);
diff --git a/src/mp-equation-lexer.l b/src/mp-equation-lexer.l
index 17956c6..bbc9765 100644
--- a/src/mp-equation-lexer.l
+++ b/src/mp-equation-lexer.l
@@ -87,6 +87,10 @@ IN [iI][nN]
"*"|"Ã?" {return tMULTIPLY;}
"/"|"â??"|"÷" {return tDIVIDE;}
{MOD} {return tMOD;}
+"â??" {return tLFLOOR;}
+"â??" {return tRFLOOR;}
+"â??" {return tLCEILING;}
+"â??" {return tRCEILING;}
"â??" {return tROOT;}
"â??" {return tROOT3;}
"â??" {return tROOT4;}
diff --git a/src/mp-equation-parser.y b/src/mp-equation-parser.y
index c4696fb..29e476d 100644
--- a/src/mp-equation-parser.y
+++ b/src/mp-equation-parser.y
@@ -178,6 +178,7 @@ static void do_conversion(yyscan_t yyscanner, const MPNumber *x, const char *x_u
}
%left <int_t> tNUMBER
+%left tLFLOOR tRFLOOR tLCEILING tRCEILING
%left UNARY_PLUS
%left tADD tSUBTRACT
%left tAND tOR tXOR tXNOR
@@ -215,6 +216,10 @@ unit:
exp:
'(' exp ')' {mp_set_from_mp(&$2, &$$);}
| exp '(' exp ')' {mp_multiply(&$1, &$3, &$$);}
+| tLFLOOR exp tRFLOOR {mp_floor(&$2, &$$);}
+| tLCEILING exp tRCEILING {mp_ceiling(&$2, &$$);}
+| '[' exp ']' {mp_round(&$2, &$$);}
+| '{' exp '}' {mp_fractional_component(&$2, &$$);}
| '|' exp '|' {mp_abs(&$2, &$$);}
| exp '^' exp {mp_xpowy(&$1, &$3, &$$);}
| exp tSUPNUM {mp_xpowy_integer(&$1, $2, &$$);}
diff --git a/src/mp-equation.c b/src/mp-equation.c
index ceac748..89fcdf3 100644
--- a/src/mp-equation.c
+++ b/src/mp-equation.c
@@ -184,7 +184,7 @@ get_function(MPEquationParserState *state, const char *name, const MPNumber *x,
else if (strcmp(lower_name, "conj") == 0)
mp_conjugate(x, z);
else if (strcmp(lower_name, "int") == 0)
- mp_integer_component(x, z);
+ mp_floor(x, z);
else if (strcmp(lower_name, "frac") == 0)
mp_fractional_component(x, z);
else if (strcmp(lower_name, "re") == 0)
diff --git a/src/mp.c b/src/mp.c
index edb6591..2533c89 100644
--- a/src/mp.c
+++ b/src/mp.c
@@ -450,11 +450,13 @@ mp_fractional_component(const MPNumber *x, MPNumber *z)
}
if (z->fraction[0] == 0)
z->sign = 0;
+ if (z->sign < 0)
+ z->sign = -z->sign;
}
void
-mp_integer_component(const MPNumber *x, MPNumber *z)
+mp_floor(const MPNumber *x, MPNumber *z)
{
int i;
@@ -477,6 +479,41 @@ mp_integer_component(const MPNumber *x, MPNumber *z)
}
+void
+mp_ceiling(const MPNumber *x, MPNumber *z)
+{
+ MPNumber f;
+
+ mp_floor(x, z);
+ mp_fractional_component(x, &f);
+ if (mp_is_zero(&f))
+ return;
+
+ if (mp_is_negative(x))
+ mp_add_integer(z, -1, z);
+ else
+ mp_add_integer(z, 1, z);
+}
+
+
+void
+mp_round(const MPNumber *x, MPNumber *z)
+{
+ MPNumber f, one;
+
+ mp_floor(x, z);
+ mp_fractional_component(x, &f);
+ mp_multiply_integer(&f, 2, &f);
+ mp_set_from_integer(1, &one);
+ if (mp_is_less_than(&f, &one))
+ return;
+
+ if (mp_is_negative(x))
+ mp_add_integer(z, -1, z);
+ else
+ mp_add_integer(z, 1, z);
+}
+
int
mp_compare_mp_to_mp(const MPNumber *x, const MPNumber *y)
{
@@ -733,12 +770,12 @@ mp_is_integer(const MPNumber *x)
/* This fix is required for 1/3 repiprocal not being detected as an integer */
/* Multiplication and division by 10000 is used to get around a
* limitation to the "fix" for Sun bugtraq bug #4006391 in the
- * mp_integer_component() routine in mp.c, when the exponent is less than 1.
+ * mp_floor() routine in mp.c, when the exponent is less than 1.
*/
mp_set_from_integer(10000, &t3);
mp_multiply(x, &t3, &t1);
mp_divide(&t1, &t3, &t1);
- mp_integer_component(&t1, &t2);
+ mp_floor(&t1, &t2);
return mp_is_equal(&t1, &t2);
/* Correct way to check for integer */
@@ -1814,7 +1851,7 @@ mp_modulus_divide(const MPNumber *x, const MPNumber *y, MPNumber *z)
}
mp_divide(x, y, &t1);
- mp_integer_component(&t1, &t1);
+ mp_floor(&t1, &t1);
mp_multiply(&t1, y, &t2);
mp_subtract(x, &t2, z);
diff --git a/src/mp.h b/src/mp.h
index 28fbbc0..2e356dd 100644
--- a/src/mp.h
+++ b/src/mp.h
@@ -167,11 +167,17 @@ void mp_divide_integer(const MPNumber *x, int64_t y, MPNumber *z);
/* Sets z = 1 ÷ x */
void mp_reciprocal(const MPNumber *, MPNumber *);
-/* Sets z = fractional part of x */
+/* Sets z = {x} */
void mp_fractional_component(const MPNumber *x, MPNumber *z);
-/* Sets z = integer part of x */
-void mp_integer_component(const MPNumber *x, MPNumber *z);
+/* Sets z = â??xâ?? */
+void mp_floor(const MPNumber *x, MPNumber *z);
+
+/* Sets z = â??xâ?? */
+void mp_ceiling(const MPNumber *x, MPNumber *z);
+
+/* Sets z = [x] */
+void mp_round(const MPNumber *x, MPNumber *z);
/* Sets z = ln x */
void mp_ln(const MPNumber *x, MPNumber *z);
diff --git a/src/unittest.c b/src/unittest.c
index ac57e21..3ea51a2 100644
--- a/src/unittest.c
+++ b/src/unittest.c
@@ -401,10 +401,32 @@ test_equations()
test("8 mod 7", "1", 0);
test("â??1 mod 7", "6", 0);
- test("int 3.2", "3", 0);
- test("frac 3.2", "0.2", 0);
- test("int (â??3.2)", "â??3", 0);
- test("frac (â??3.2)", "â??0.2", 0);
+ test("â??3â??", "3", 0);
+ test("â??3â??", "3", 0);
+ test("[3]", "3", 0);
+ test("â??â??3â??", "â??3", 0);
+ test("â??â??3â??", "â??3", 0);
+ test("[â??3]", "â??3", 0);
+ test("â??3.2â??", "3", 0);
+ test("â??3.2â??", "4", 0);
+ test("[3.2]", "3", 0);
+ test("â??â??3.2â??", "â??3", 0);
+ test("â??â??3.2â??", "â??4", 0);
+ test("[â??3.2]", "â??3", 0);
+ test("â??3.5â??", "3", 0);
+ test("â??3.5â??", "4", 0);
+ test("[3.5]", "4", 0);
+ test("â??â??3.5â??", "â??3", 0);
+ test("â??â??3.5â??", "â??4", 0);
+ test("[â??3.5]", "â??4", 0);
+ test("â??3.7â??", "3", 0);
+ test("â??3.7â??", "4", 0);
+ test("[3.7]", "4", 0);
+ test("â??â??3.7â??", "â??3", 0);
+ test("â??â??3.7â??", "â??4", 0);
+ test("[â??3.7]", "â??4", 0);
+ test("{3.2}", "0.2", 0);
+ test("{â??3.2}", "0.2", 0);
test("|1|", "1", 0);
test("|â??1|", "1", 0);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]