[gcalctool/gcalctool-newui2] ...
- From: Robert Ancell <rancell src gnome org>
- To: svn-commits-list gnome org
- Subject: [gcalctool/gcalctool-newui2] ...
- Date: Fri, 17 Jul 2009 07:22:38 +0000 (UTC)
commit 073970ccaac2cc1a0f2104354f830fbdb49cc7e9
Author: Robert Ancell <robert ancell gmail com>
Date: Fri Jul 17 17:22:17 2009 +1000
...
src/mp-convert.c | 64 +++++------------------
src/mp-equation-parser.y | 2 +-
src/mp-equation.c | 2 +-
src/mp-trigonometric.c | 50 +-----------------
src/mp.c | 126 ++++++++++++++-------------------------------
src/unittest.c | 40 +++++++++------
6 files changed, 82 insertions(+), 202 deletions(-)
---
diff --git a/src/mp-convert.c b/src/mp-convert.c
index 93a8d88..d03577e 100644
--- a/src/mp-convert.c
+++ b/src/mp-convert.c
@@ -28,9 +28,6 @@
#include "mp.h"
#include "mp-internal.h"
-/* SETS Y = X FOR MP X AND Y.
- * SEE IF X AND Y HAVE THE SAME ADDRESS (THEY OFTEN DO)
- */
void
mp_set_from_mp(const MPNumber *x, MPNumber *z)
{
@@ -38,11 +35,7 @@ mp_set_from_mp(const MPNumber *x, MPNumber *z)
memcpy(z, x, sizeof(MPNumber));
}
-/* CONVERTS SINGLE-PRECISION NUMBER RX TO MULTIPLE-PRECISION Z.
- * SOME NUMBERS WILL NOT CONVERT EXACTLY ON MACHINES
- * WITH BASE OTHER THAN TWO, FOUR OR SIXTEEN.
- * CHECK LEGALITY OF B, T, M AND MXR
- */
+
void
mp_set_from_float(float rx, MPNumber *z)
{
@@ -122,19 +115,7 @@ mp_set_from_float(float rx, MPNumber *z)
return;
}
-void
-mp_set_from_random(MPNumber *z)
-{
- mp_set_from_double(drand48(), z);
-}
-/* CONVERTS DOUBLE-PRECISION NUMBER DX TO MULTIPLE-PRECISION Z.
- * SOME NUMBERS WILL NOT CONVERT EXACTLY ON MACHINES
- * WITH BASE OTHER THAN TWO, FOUR OR SIXTEEN.
- * THIS ROUTINE IS NOT CALLED BY ANY OTHER ROUTINE IN MP,
- * SO MAY BE OMITTED IF DOUBLE-PRECISION IS NOT AVAILABLE.
- * CHECK LEGALITY OF B, T, M AND MXR
- */
void
mp_set_from_double(double dx, MPNumber *z)
{
@@ -209,9 +190,6 @@ mp_set_from_double(double dx, MPNumber *z)
}
-/* CONVERTS INTEGER IX TO MULTIPLE-PRECISION Z.
- * CHECK LEGALITY OF B, T, M AND MXR
- */
void
mp_set_from_integer(int x, MPNumber *z)
{
@@ -238,7 +216,7 @@ mp_set_from_integer(int x, MPNumber *z)
}
}
-/* CONVERTS THE RATIONAL NUMBER I/J TO MULTIPLE PRECISION Q. */
+
void
mp_set_from_fraction(int i, int j, MPNumber *z)
{
@@ -260,16 +238,14 @@ mp_set_from_fraction(int i, int j, MPNumber *z)
mp_divide_integer(z, j, z);
}
-/* CONVERTS MULTIPLE-PRECISION X TO INTEGER, AND
- * RETURNS RESULT.
- * ASSUMING THAT X NOT TOO LARGE (ELSE USE MP_INTEGER_COMPONENT)
- * X IS TRUNCATED TOWARDS ZERO.
- * IF INT(X)IS TOO LARGE TO BE REPRESENTED AS A SINGLE-
- * PRECISION INTEGER, IZ IS RETURNED AS ZERO. THE USER
- * MAY CHECK FOR THIS POSSIBILITY BY TESTING IF
- * ((X(1).NE.0).AND.(X(2).GT.0).AND.(IZ.EQ.0)) IS TRUE ON
- * RETURN FROM MP_CAST_TO_INST.
- */
+
+void
+mp_set_from_random(MPNumber *z)
+{
+ mp_set_from_double(drand48(), z);
+}
+
+
int
mp_cast_to_int(const MPNumber *x)
{
@@ -320,6 +296,7 @@ mp_cast_to_int(const MPNumber *x)
*/
}
+
static double
mppow_ri(float ap, int bp)
{
@@ -348,11 +325,7 @@ mppow_ri(float ap, int bp)
return pow;
}
-/* CONVERTS MULTIPLE-PRECISION X TO SINGLE-PRECISION.
- * ASSUMES X IN ALLOWABLE RANGE. THERE IS SOME LOSS OF
- * ACCURACY IF THE EXPONENT IS LARGE.
- * CHECK LEGALITY OF B, T, M AND MXR
- */
+
float
mp_cast_to_float(const MPNumber *x)
{
@@ -391,6 +364,7 @@ mp_cast_to_float(const MPNumber *x)
return rz;
}
+
static double
mppow_di(double ap, int bp)
{
@@ -412,13 +386,7 @@ mppow_di(double ap, int bp)
return(pow);
}
-/* CONVERTS MULTIPLE-PRECISION X TO DOUBLE-PRECISION,
- * AND RETURNS RESULT.
- * ASSUMES X IS IN ALLOWABLE RANGE FOR DOUBLE-PRECISION
- * NUMBERS. THERE IS SOME LOSS OF ACCURACY IF THE
- * EXPONENT IS LARGE.
- * CHECK LEGALITY OF B, T, M AND MXR
- */
+
double
mp_cast_to_double(const MPNumber *x)
{
@@ -466,9 +434,6 @@ mp_cast_to_double(const MPNumber *x)
}
-/* Convert MP number to fixed number string in the given base to the
- * maximum number of digits specified.
- */
void
mp_cast_to_string(const MPNumber *x, int base, int accuracy, int trim_zeroes, char *buffer, int buffer_length)
{
@@ -630,7 +595,6 @@ char_val(char **c, int base)
}
-/* Convert string into an MP number */
void
mp_set_from_string(const char *str, MPNumber *z)
{
diff --git a/src/mp-equation-parser.y b/src/mp-equation-parser.y
index 66aee9f..f8cc342 100644
--- a/src/mp-equation-parser.y
+++ b/src/mp-equation-parser.y
@@ -102,11 +102,11 @@ static void do_mod(yyscan_t yyscanner, const MPNumber *x, const MPNumber *y, MPN
%left tNOT
%left tROOT tROOT3 tROOT4
%left <name> tVARIABLE tFUNCTION
-%right '^' tINVERSE '!'
%right <integer> tSUBNUM tSUPNUM
%left BOOLEAN_OPERATOR
%left PERCENTAGE
%left UNARY_MINUS
+%right '^' tINVERSE '!'
%type <int_t> exp function
%start statement
diff --git a/src/mp-equation.c b/src/mp-equation.c
index 0cbe134..0890ce2 100644
--- a/src/mp-equation.c
+++ b/src/mp-equation.c
@@ -39,7 +39,7 @@ get_variable(MPEquationParserState *state, const char *name, MPNumber *z)
lower_name = strdup(name);
for (c = lower_name; *c; c++)
*c = tolower(*c);
-
+
if (lower_name[0] == 'r')
mp_set_from_mp(register_get_value(atoi(name+1)), z);
else if (strcmp(lower_name, "ans") == 0)
diff --git a/src/mp-trigonometric.c b/src/mp-trigonometric.c
index 29e4ed2..ad98c36 100644
--- a/src/mp-trigonometric.c
+++ b/src/mp-trigonometric.c
@@ -28,11 +28,6 @@
#include "mp.h"
#include "mp-internal.h"
-/* COMPARES MP NUMBER X WITH INTEGER I, RETURNING
- * +1 IF X > I,
- * 0 IF X == I,
- * -1 IF X < I
- */
static int
mp_compare_mp_to_int(const MPNumber *x, int i)
{
@@ -102,8 +97,8 @@ convert_from_radians(const MPNumber *x, MPAngleUnit unit, MPNumber *z)
}
-/* COMPUTES Z = SIN(X) IF DO_SIN != 0, Z = COS(X) IF DO_SIN == 0,
- * USING TAYLOR SERIES. ASSUMES ABS(X) <= 1.
+/* z = sin(x) -1 >= x >= 1, do_sin = 1
+ * z = cos(x) -1 >= x >= 1, do_sin = 0
*/
static void
mpsin1(const MPNumber *x, MPNumber *z, int do_sin)
@@ -135,6 +130,7 @@ mpsin1(const MPNumber *x, MPNumber *z, int do_sin)
i = 2;
}
+ /* Taylor series */
/* POWER SERIES LOOP. REDUCE T IF POSSIBLE */
b2 = max(MP_BASE, 64) << 1;
do {
@@ -161,12 +157,6 @@ mpsin1(const MPNumber *x, MPNumber *z, int do_sin)
}
-/* RETURNS Z = SIN(X) FOR MP X AND Z,
- * METHOD IS TO REDUCE X TO (-1, 1) AND USE MPSIN1, SO
- * TIME IS O(M(T)T/LOG(T)).
- * DIMENSION OF R IN CALLING PROGRAM MUST BE AT LEAST 5T+12
- * CHECK LEGALITY OF B, T, M AND MXR
- */
void
mp_sin(const MPNumber *x, MPAngleUnit unit, MPNumber *z)
{
@@ -252,9 +242,6 @@ mp_sin(const MPNumber *x, MPAngleUnit unit, MPNumber *z)
}
-/* RETURNS Z = COS(X) FOR MP X AND Z, USING MP_SIN AND MPSIN1.
- * DIMENSION OF R IN COMMON AT LEAST 5T+12.
- */
void
mp_cos(const MPNumber *xi, MPAngleUnit unit, MPNumber *z)
{
@@ -301,13 +288,6 @@ mp_tan(const MPNumber *x, MPAngleUnit unit, MPNumber *z)
}
-/* RETURNS Z = ARCSIN(X), ASSUMING ABS(X) <= 1,
- * FOR MP NUMBERS X AND Z.
- * Z IS IN THE RANGE -PI/2 TO +PI/2.
- * METHOD IS TO USE MP_ATAN, SO TIME IS O(M(T)T).
- * DIMENSION OF R MUST BE AT LEAST 5T+12
- * CHECK LEGALITY OF B, T, M AND MXR
- */
void
mp_asin(const MPNumber *x, MPAngleUnit unit, MPNumber *z)
{
@@ -345,20 +325,6 @@ mp_asin(const MPNumber *x, MPAngleUnit unit, MPNumber *z)
}
-/* MP precision arc cosine.
- *
- * 1. If (x < -1 or x > 1) then report DOMAIN error and return 0.
- *
- * 2. If (x == 0) then acos(x) = PI/2.
- *
- * 3. If (x == 1) then acos(x) = 0
- *
- * 4. If (x == -1) then acos(x) = PI.
- *
- * 5. If (0 < x < 1) then acos(x) = atan(sqrt(1-x^2) / x)
- *
- * 6. If (-1 < x < 0) then acos(x) = atan(sqrt(1-x^2) / x) + PI
- */
void
mp_acos(const MPNumber *x, MPAngleUnit unit, MPNumber *z)
{
@@ -395,16 +361,6 @@ mp_acos(const MPNumber *x, MPAngleUnit unit, MPNumber *z)
}
-/* RETURNS Z = ARCTAN(X) FOR MP X AND Z, USING AN O(T.M(T)) METHOD
- * WHICH COULD EASILY BE MODIFIED TO AN O(SQRT(T)M(T))
- * METHOD (AS IN MPEXP). Z IS IN THE RANGE -PI/2 TO +PI/2.
- * FOR AN ASYMPTOTICALLY FASTER METHOD, SEE - FAST MULTIPLE-
- * PRECISION EVALUATION OF ELEMENTARY FUNCTIONS
- * (BY R. P. BRENT), J. ACM 23 (1976), 242-251,
- * AND THE COMMENTS IN MPPIGL.
- * DIMENSION OF R IN CALLING PROGRAM MUST BE AT LEAST 5T+12
- * CHECK LEGALITY OF B, T, M AND MXR
- */
void
mp_atan(const MPNumber *x, MPAngleUnit unit, MPNumber *z)
{
diff --git a/src/mp.c b/src/mp.c
index 84eb531..6f6e566 100644
--- a/src/mp.c
+++ b/src/mp.c
@@ -299,9 +299,6 @@ mp_add2(const MPNumber *x, const MPNumber *y, int y_sign, MPNumber *z)
}
-/* ADDS X AND Y, FORMING RESULT IN Z, WHERE X, Y AND Z ARE MP
- * NUMBERS. FOUR GUARD DIGITS ARE USED, AND THEN R*-ROUNDING.
- */
void
mp_add(const MPNumber *x, const MPNumber *y, MPNumber *z)
{
@@ -328,6 +325,13 @@ mp_add_fraction(const MPNumber *x, int i, int j, MPNumber *y)
void
+mp_subtract(const MPNumber *x, const MPNumber *y, MPNumber *z)
+{
+ mp_add2(x, y, -y->sign, z);
+}
+
+
+void
mp_fractional_component(const MPNumber *x, MPNumber *z)
{
int i, shift;
@@ -695,7 +699,7 @@ mpexp(const MPNumber *x, MPNumber *z)
return;
}
- /* CHECK THAT ABS(X) < 1 */
+ /* Only defined for |x| < 1 */
if (x->exponent > 0) {
mperr("*** ABS(X) NOT LESS THAN 1 IN CALL TO MPEXP ***");
mp_set_from_integer(0, z);
@@ -751,13 +755,6 @@ mpexp(const MPNumber *x, MPNumber *z)
}
-/* RETURNS Z = EXP(X) FOR MP X AND Z.
- * EXP OF INTEGER AND FRACTIONAL PARTS OF X ARE COMPUTED
- * SEPARATELY. SEE ALSO COMMENTS IN MPEXP.
- * TIME IS O(SQRT(T)M(T)).
- * DIMENSION OF R MUST BE AT LEAST 4T+10 IN CALLING PROGRAM
- * CHECK LEGALITY OF B, T, M AND MXR
- */
void
mp_epowy(const MPNumber *x, MPNumber *z)
{
@@ -943,8 +940,6 @@ mp_is_less_equal(const MPNumber *x, const MPNumber *y)
* CONDITION ABS(X) < 1/B, ERROR OTHERWISE.
* USES NEWTONS METHOD TO SOLVE THE EQUATION
* EXP1(-Y) = X, THEN REVERSES SIGN OF Y.
- * TIME IS O(SQRT(T).M(T)) AS FOR MPEXP, SPACE = 5T+12.
- * CHECK LEGALITY OF B, T, M AND MXR
*/
static void
mplns(const MPNumber *x, MPNumber *z)
@@ -965,7 +960,7 @@ mplns(const MPNumber *x, MPNumber *z)
return;
}
- /* GET STARTING APPROXIMATION TO -LN(1+X) */
+ /* Get starting approximation -ln(1+x) ~= -x + x^2/2 - x^3/3 + x^4/4 */
mp_set_from_mp(x, &t2);
mp_divide_integer(x, 4, &t1);
mp_add_fraction(&t1, -1, 3, &t1);
@@ -1025,7 +1020,7 @@ mp_ln(const MPNumber *x, MPNumber *z)
float rx, rlx;
MPNumber t1, t2;
- /* ln(-x) -> error */
+ /* ln(-x) invalid */
if (x->sign <= 0) {
mperr("*** X NONPOSITIVE IN CALL TO MP_LN ***");
mp_set_from_integer(0, z);
@@ -1113,13 +1108,9 @@ mp_is_less_than(const MPNumber *x, const MPNumber *y)
void
mp_multiply(const MPNumber *x, const MPNumber *y, MPNumber *z)
{
- int c, i, j, i2, xi;
+ int c, i, j, xi;
MPNumber r;
- i2 = MP_T + 4;
-
- memset(&r, 0, sizeof(MPNumber));
-
/* x*0 = 0*y = 0 */
if (x->sign == 0 || y->sign == 0) {
mp_set_from_integer(0, z);
@@ -1128,6 +1119,7 @@ mp_multiply(const MPNumber *x, const MPNumber *y, MPNumber *z)
z->sign = x->sign * y->sign;
z->exponent = x->exponent + y->exponent;
+ memset(&r, 0, sizeof(MPNumber));
/* PERFORM MULTIPLICATION */
c = 8;
@@ -1139,7 +1131,7 @@ mp_multiply(const MPNumber *x, const MPNumber *y, MPNumber *z)
continue;
/* Computing MIN */
- for (j = 0; j < min(MP_T, i2 - i - 1); j++)
+ for (j = 0; j < min(MP_T, MP_T + 3 - i); j++)
r.fraction[i+j+1] += xi * y->fraction[j];
c--;
if (c > 0)
@@ -1155,7 +1147,7 @@ mp_multiply(const MPNumber *x, const MPNumber *y, MPNumber *z)
/* PROPAGATE CARRIES AT END AND EVERY EIGHTH TIME,
* FASTER THAN DOING IT EVERY TIME.
*/
- for (j = i2 - 1; j >= 0; j--) {
+ for (j = MP_T + 3; j >= 0; j--) {
int ri = r.fraction[j] + c;
if (ri < 0) {
mperr("*** INTEGER OVERFLOW IN MP_MULTIPLY, B TOO LARGE ***");
@@ -1181,7 +1173,7 @@ mp_multiply(const MPNumber *x, const MPNumber *y, MPNumber *z)
}
c = 0;
- for (j = i2 - 1; j >= 0; j--) {
+ for (j = MP_T + 3; j >= 0; j--) {
int ri = r.fraction[j] + c;
if (ri < 0) {
mperr("*** INTEGER OVERFLOW IN MP_MULTIPLY, B TOO LARGE ***");
@@ -1381,12 +1373,9 @@ mp_multiply_integer(const MPNumber *x, int y, MPNumber *z)
}
-/* MULTIPLIES MP X BY I/J, GIVING MP Y */
void
mp_multiply_fraction(const MPNumber *x, int numerator, int denominator, MPNumber *z)
{
- int is, js;
-
if (denominator == 0) {
mperr("*** ATTEMPTED DIVISION BY ZERO IN MP_MULTIPLY_FRACTION ***");
mp_set_from_integer(0, z);
@@ -1398,32 +1387,21 @@ mp_multiply_fraction(const MPNumber *x, int numerator, int denominator, MPNumber
return;
}
- /* REDUCE TO LOWEST TERMS */
- is = numerator;
- js = denominator;
- mpgcd(&is, &js);
- if (abs(is) == 1) {
- /* HERE IS = +-1 */
- mp_divide_integer(x, is * js, z);
- } else {
- mp_divide_integer(x, js, z);
- mp_multiply_integer(z, is, z);
- }
+ /* Reduce to lowest terms */
+ mpgcd(&numerator, &denominator);
+ mp_divide_integer(x, denominator, z);
+ mp_multiply_integer(z, numerator, z);
}
-/* SETS Y = -X FOR MP NUMBERS X AND Y */
void
-mp_invert_sign(const MPNumber *x, MPNumber *y)
+mp_invert_sign(const MPNumber *x, MPNumber *z)
{
- mp_set_from_mp(x, y);
- y->sign = -y->sign;
+ mp_set_from_mp(x, z);
+ z->sign = -z->sign;
}
-/* ASSUMES LONG (I.E. (T+4)-DIGIT) FRACTION IN R. NORMALIZES,
- * AND RETURNS MP RESULT IN Z. INTEGER ARGUMENTS REG_EXP IS
- * NOT PRESERVED. R*-ROUNDING IS USED IF TRUNC == 0
- */
+
// FIXME: Is r->fraction large enough? It seems to be in practise but it may be MP_T+4 instead of MP_T
// FIXME: There is some sort of stack corruption/use of unitialised variables here. Some functions are
// using stack variables as x otherwise there are corruption errors. e.g. "Cos(45) - 1/Sqrt(2) = -0"
@@ -1556,15 +1534,12 @@ mp_pwr(const MPNumber *x, const MPNumber *y, MPNumber *z)
void
mp_reciprocal(const MPNumber *x, MPNumber *z)
{
- /* Initialized data */
- static int it[9] = { 0, 8, 6, 5, 4, 4, 4, 4, 4 };
-
MPNumber tmp_x, t1, t2;
-
int ex, it0, t;
float rx;
+ static int it[9] = { 0, 8, 6, 5, 4, 4, 4, 4, 4 };
- /* MP_ADD_INTEGER REQUIRES 2T+6 WORDS. */
+ /* 1/x invalid */
if (x->sign == 0) {
mperr("*** ATTEMPTED DIVISION BY ZERO IN CALL TO MP_RECIPROCAL ***");
mp_set_from_integer(0, z);
@@ -1630,28 +1605,22 @@ mp_reciprocal(const MPNumber *x, MPNumber *z)
}
-/* RETURNS Z = X^(1/N) FOR INTEGER N, ABS(N) <= MAX (B, 64).
- * AND MP NUMBERS X AND Z,
- * USING NEWTONS METHOD WITHOUT DIVISIONS. SPACE = 4T+10
- * (BUT Z.EXP MAY BE R(3T+9))
- */
void
mp_root(const MPNumber *x, int n, MPNumber *z)
{
- /* Initialized data */
- static const int it[9] = { 0, 8, 6, 5, 4, 4, 4, 4, 4 };
-
float r__1;
-
int ex, np, it0, t;
float rx;
MPNumber t1, t2;
+ static const int it[9] = { 0, 8, 6, 5, 4, 4, 4, 4, 4 };
+ /* x^(1/1) = x */
if (n == 1) {
mp_set_from_mp(x, z);
return;
}
+ /* x^(1/0) invalid */
if (n == 0) {
mperr("*** N == 0 IN CALL TO MP_ROOT ***");
mp_set_from_integer(0, z);
@@ -1687,10 +1656,10 @@ mp_root(const MPNumber *x, int n, MPNumber *z)
/* REDUCE EXPONENT SO RX NOT TOO LARGE OR SMALL. */
{
- MPNumber tmp_x;
- mp_set_from_mp(x, &tmp_x);
- tmp_x.exponent = 0;
- rx = mp_cast_to_float(&tmp_x);
+ MPNumber tmp_x;
+ mp_set_from_mp(x, &tmp_x);
+ tmp_x.exponent = 0;
+ rx = mp_cast_to_float(&tmp_x);
}
/* USE SINGLE-PRECISION ROOT FOR FIRST APPROXIMATION */
@@ -1763,24 +1732,17 @@ mp_root(const MPNumber *x, int n, MPNumber *z)
}
-/* RETURNS Z = SQRT(X), USING SUBROUTINE MP_ROOT IF X > 0.
- * DIMENSION OF R IN CALLING PROGRAM MUST BE AT LEAST 4T+10
- * (BUT Z.EXP MAY BE R(3T+9)). X AND Z ARE MP NUMBERS.
- * CHECK LEGALITY OF B, T, M AND MXR
- */
void
mp_sqrt(const MPNumber *x, MPNumber *z)
{
- int i, i2;
- MPNumber t;
-
- /* MP_ROOT NEEDS 4T+10 WORDS, BUT CAN OVERLAP SLIGHTLY. */
- i2 = MP_T * 3 + 9;
- if (x->sign < 0) {
+ if (x->sign < 0)
mperr("*** X NEGATIVE IN CALL TO SUBROUTINE MP_SQRT ***");
- } else if (x->sign == 0) {
+ else if (x->sign == 0)
mp_set_from_integer(0, z);
- } else {
+ else {
+ int i;
+ MPNumber t;
+
mp_root(x, -2, &t);
i = t.fraction[0];
mp_multiply(x, &t, z);
@@ -1788,15 +1750,6 @@ mp_sqrt(const MPNumber *x, MPNumber *z)
}
}
-/* SUBTRACTS Y FROM X, FORMING RESULT IN Z, FOR MP X, Y AND Z.
- * FOUR GUARD DIGITS ARE USED, AND THEN R*-ROUNDING
- */
-void
-mp_subtract(const MPNumber *x, const MPNumber *y, MPNumber *z)
-{
- mp_add2(x, y, -y->sign, z);
-}
-
void
mp_factorial(const MPNumber *x, MPNumber *z)
@@ -1832,9 +1785,8 @@ mp_modulus_divide(const MPNumber *x, const MPNumber *y, MPNumber *z)
mp_subtract(x, &t2, z);
mp_set_from_integer(0, &t1);
- if ((mp_is_less_than(y, &t1) && mp_is_greater_than(z, &t1)) || mp_is_less_than(z, &t1)) {
+ if ((mp_is_less_than(y, &t1) && mp_is_greater_than(z, &t1)) || mp_is_less_than(z, &t1))
mp_add(z, y, z);
- }
}
diff --git a/src/unittest.c b/src/unittest.c
index bbf3bc5..b93b376 100644
--- a/src/unittest.c
+++ b/src/unittest.c
@@ -136,6 +136,10 @@ test_parser()
test("1½", "1.5", 0);
test("1.00", "1", 0);
test("1.01", "1.01", 0);
+
+ test("١٢٣٤٥٦٧٨٩٠", "1234567890", 0);
+ test("Û±Û²Û³Û´ÛµÛ¶Û·Û¸Û¹Û°", "1234567890", 0);
+
//test("2A", "2000000000000000", 0);
test("2T", "2000000000000", 0);
test("2G", "2000000000", 0);
@@ -164,9 +168,12 @@ test_parser()
//test("2n3", "0.0000000023", 0); // FIXME: Need to print out significant figures, not decimal places
//test("2p3", "0.0000000000023", 0); // FIXME: Need to print out significant figures, not decimal places
//test("2f3", "0.0000000000000023", 0); // FIXME: Need to print out significant figures, not decimal places
+
+ test("2Ã?10^3", "2000", 0);
+ test("2Ã?10^â??3", "0.002", 0);
+
test("Ï?", "3.141592654", 0);
test("e", "2.718281828", 0);
-
test("2Ï?", "6.283185307", 0);
test("2e", "5.436563657", 0);
//test("2Ï?²", "19.739208802", 0);
@@ -176,9 +183,6 @@ test_parser()
test("Ï?e", "8.539734223", 0);
test("eÏ?", "8.539734223", 0);
//test("2Ï?e", "17.079468445", 0);
-
- test("١٢٣٤٥٦٧٨٩٠", "1234567890", 0);
- test("Û±Û²Û³Û´ÛµÛ¶Û·Û¸Û¹Û°", "1234567890", 0);
test("0+0", "0", 0);
test("1+1", "2", 0);
@@ -189,39 +193,42 @@ test_parser()
test("2-3", "â??1", 0);
test("2â??3", "â??1", 0);
test("3â??2", "1", 0);
- test("1â??0.9â??0.1", "0", 0);
test("40000â??0.001", "39999.999", 0);
test("0.001â??40000", "â??39999.999", 0);
- test("40000000â??40000000", "0", 0);
test("2*3", "6", 0);
test("2Ã?3", "6", 0);
test("â??2Ã?3", "â??6", 0);
test("2Ã?â??3", "â??6", 0);
test("â??2Ã?â??3", "6", 0);
-
- test("2Ã?10^3", "2000", 0);
- test("2Ã?10^â??3", "0.002", 0);
-
test("6/3", "2", 0);
test("6÷3", "2", 0);
test("1÷2", "0.5", 0);
test("â??6÷3", "â??2", 0);
test("6÷â??3", "â??2", 0);
test("â??6÷â??3", "2", 0);
+ test("(â??3)÷(â??6)", "0.5", 0);
test("2÷2", "1", 0);
test("1203÷1", "1203", 0);
test("â??0÷32352.689", "0", 0);
test("1÷4", "0.25", 0);
- test("(â??3)÷(â??6)", "0.5", 0);
test("1÷3", "0.333333333", 0);
test("2÷3", "0.666666667", 0);
test("1÷0", "", -20001);
test("0÷0", "", -20001);
+
+ /* Precision */
+ test("1000000000000000â??1000000000000000", "0", 0);
+ test("1000000000000000÷1000000000000000", "1", 0);
+ test("1000000000000000Ã?0.000000000000001", "1", 0);
+ /* Order of operations */
+ test("1â??0.9â??0.1", "0", 0);
test("1+2Ã?3", "7", 0);
test("1+(2Ã?3)", "7", 0);
test("(1+2)Ã?3", "9", 0);
+ test("(1+2Ã?3)", "7", 0);
+ /* Percentage */
test("100%", "1", 0);
test("1%", "0.01", 0);
test("100+1%", "101", 0);
@@ -229,16 +236,17 @@ test_parser()
test("100Ã?1%", "1", 0);
test("100÷1%", "10000", 0);
+ /* Factorial */
test("0!", "1", 0);
test("1!", "1", 0);
test("5!", "120", 0);
test("69!", "171122452428141311372468338881272839092270544893520369393648040923257279754140647424000000000000000", 0);
test("0.1!", "", -20001);
- test("â??1!", "", -20001);
- test("0â??1!", "â??1", 0);
+ test("â??1!", "â??1", 0);
test("(â??1)!", "", -20001);
test("â??(1!)", "â??1", 0);
+ /* Powers */
test("2²", "4", 0);
test("2³", "8", 0);
test("2¹�", "1024", 0);
@@ -249,7 +257,7 @@ test_parser()
//test("2â?»", "", -20001); // FIXME: Maybe an error in bison?
test("2^â??1", "0.5", 0);
test("2^(â??1)", "0.5", 0);
- test("â??10^2", "100", 0);
+ test("â??10^2", "â??100", 0);
test("(â??10)^2", "100", 0);
test("â??(10^2)", "â??100", 0);
test("2^100", "1267650600228229401496703205376", 0);
@@ -270,8 +278,8 @@ test_parser()
test("Sqrt(2)", "1.414213562", 0);
test("4^0.5", "2", 0);
test("2^0.5", "1.414213562", 0);
- test("â??4^0.5", "", -20001);
- test("â??8^(1÷3)", "â??2", 0);
+ test("(â??4)^0.5", "", -20001);
+ test("(â??8)^(1÷3)", "â??2", 0);
test("0 mod 7", "0", 0);
test("6 mod 7", "6", 0);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]