[gcalctool] mend



commit 65a70a0856997c6852c747902068d07c0f460758
Author: Robert Ancell <robert ancell gmail com>
Date:   Fri May 15 13:50:50 2009 +1000

    mend
---
 src/calctool.c           |   58 +-----
 src/calctool.h           |   10 +-
 src/gtk.c                |   37 +++-
 src/mp-equation-lexer.l  |   20 +-
 src/mp-equation-parser.y |   56 +++---
 src/mp-equation.c        |   15 +-
 src/mp-equation.h        |   12 +
 src/mp-trigonometric.c   |  530 +++++++++++++++++++++++++---------------------
 src/mp.c                 |   13 +-
 src/mp.h                 |   14 +-
 src/ui.h                 |    2 +-
 src/unittest.c           |   10 +-
 12 files changed, 398 insertions(+), 379 deletions(-)

diff --git a/src/calctool.c b/src/calctool.c
index 661a3bd..f940777 100644
--- a/src/calctool.c
+++ b/src/calctool.c
@@ -45,58 +45,6 @@ int basevals[4] = { 2, 8, 10, 16 };
 static CalculatorVariables calc_state;
 CalculatorVariables *v;
 
-/* Change type to radian */
-void
-to_rad(const MPNumber *s1, MPNumber *t1)
-{
-    MPNumber MP1, MP2;
-
-    if (v->ttype == DEG) {
-        mp_get_pi(&MP1);
-        mp_multiply(s1, &MP1, &MP2);
-        mp_set_from_integer(180, &MP1);
-        mp_divide(&MP2, &MP1, t1);
-    } else if (v->ttype == GRAD) {
-        mp_get_pi(&MP1);
-        mp_multiply(s1, &MP1, &MP2);
-        mp_set_from_integer(200, &MP1);
-        mp_divide(&MP2, &MP1, t1);
-    } else {
-        mp_set_from_mp(s1, t1);
-    }
-}
-
-void
-do_trig_typeconv(TrigType ttype, const MPNumber *s1, MPNumber *t1)
-{
-    MPNumber MP1, MP2;
-  
-    switch (ttype) {
-
-        case DEG:
-            mp_set_from_integer(180, &MP1);
-            mp_multiply(s1, &MP1, &MP2);
-            mp_get_pi(&MP1);
-            mp_divide(&MP2, &MP1, t1);
-            break;
-
-        case RAD:
-            mp_set_from_mp(s1, t1);
-            break;
-
-        case GRAD:
-            mp_set_from_integer(200, &MP1);
-            mp_multiply(s1, &MP1, &MP2);
-            mp_get_pi(&MP1);
-            mp_divide(&MP2, &MP1, t1);
-            break;
-
-        default:
-            assert(0);
-            break;
-    }
-}
-
 /* Calctools' customised math library error-handling routine. */
 void
 doerr(char *errmes)
@@ -137,7 +85,7 @@ solve(const char *equation)
     char result_str[MAXLINE];
     
     v->base = DEC;
-    v->ttype = DEG;
+    v->ttype = MP_DEGREES;
     v->wordlen = 32;
     v->accuracy = 9;
     
@@ -282,9 +230,9 @@ init_state(void)
        v->base = DEC;
 
     if (get_enumerated_resource(R_TRIG, Rtstr, &i))
-       v->ttype = (TrigType) i;
+       v->ttype = (MPAngleUnit) i;
     else
-       v->ttype = DEG;  
+       v->ttype = MP_DEGREES;
 
     if (get_int_resource(R_WORDLEN, &i))
        v->wordlen = i;
diff --git a/src/calctool.h b/src/calctool.h
index 5240f51..eb32fe0 100644
--- a/src/calctool.h
+++ b/src/calctool.h
@@ -35,9 +35,6 @@
 /* Base definitions. */
 typedef enum { BIN, OCT, DEC, HEX, MAXBASES } BaseType;
 
-/* Trigonometric types. */
-typedef enum { DEG, GRAD, RAD, MAXTRIGMODES } TrigType;
-
 #define MAX_DIGITS     200         /* Maximum displayable number of digits. */
 #define MAX_LOCALIZED  (MAX_DIGITS * (1 + MB_LEN_MAX) + MB_LEN_MAX)
 
@@ -75,7 +72,7 @@ typedef struct {
     int tsep_count;           /* Number of digits between separator. */
 
     BaseType base;            /* Numeric base (BIN, OCT, DEC or HEX). */
-    TrigType ttype;           /* Trigonometric type (DEG, GRAD or RAD). */
+    MPAngleUnit ttype;        /* Angle unit type */
     int wordlen;              /* Length of word for bitwise operations */
     int accuracy;             /* Number of digits precision. */
 
@@ -87,11 +84,6 @@ typedef struct {
 extern CalculatorVariables *v; /* Calctool variables and options. */
 extern int basevals[];         /* Supported arithmetic bases. */
 
-/* Change type to radian */
-void to_rad(const MPNumber *s1, MPNumber *t1);
-
-void do_trig_typeconv(TrigType ttype, const MPNumber *s1, MPNumber *t1);
-
 void doerr(char *);
 
 #endif /*CALCTOOL_H*/
diff --git a/src/gtk.c b/src/gtk.c
index 093f64b..f7a224b 100644
--- a/src/gtk.c
+++ b/src/gtk.c
@@ -512,7 +512,9 @@ typedef struct {
     GtkWidget *hyperbolic_toggle;      /* Hyperbolic mode. */
     GtkWidget *inverse_toggle;         /* Inverse mode. */
     GtkWidget *disp[MAXDISPMODES];     /* Numeric display mode. */
-    GtkWidget *trig[MAXTRIGMODES];     /* Trigonometric mode. */
+    GtkWidget *radian_radio;           /* Radian radio button. */
+    GtkWidget *degree_radio;           /* Degree radio button. */
+    GtkWidget *gradian_radio;          /* Gradian radio button. */
 
     /* Programming mode widgets */
     GtkWidget *base[MAXBASES];         /* Numeric base radio buttons. */
@@ -827,9 +829,22 @@ ui_update_modifier_mode()
 
 
 void
-ui_set_trigonometric_mode(TrigType mode)
+ui_set_trigonometric_mode(MPAngleUnit units)
 {
-    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(X.trig[mode]), 1);
+    GtkWidget *radio;
+    switch(units) {
+    default:
+    case MP_RADIANS:
+        radio = X.radian_radio;
+        break;
+    case MP_DEGREES:
+        radio = X.degree_radio;
+        break;
+    case MP_GRADIANS:
+        radio = X.gradian_radio;
+        break;
+    }
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(radio), 1);
 }
 
 
@@ -2545,11 +2560,11 @@ create_kframe()
     X.bit_panel    = GET_WIDGET("bit_panel");
     X.clear_buttons[0] = GET_WIDGET("calc_clear_simple_button");
     X.clear_buttons[1] = GET_WIDGET("calc_clear_advanced_button");   
-    X.sci_mode_panel = GET_WIDGET("scientific_mode_panel");
-    X.prog_mode_panel = GET_WIDGET("programming_mode_panel");
-    X.trig[0]      = GET_WIDGET("degrees_radio");
-    X.trig[1]      = GET_WIDGET("gradians_radio");
-    X.trig[2]      = GET_WIDGET("radians_radio");
+    X.sci_mode_panel   = GET_WIDGET("scientific_mode_panel");
+    X.prog_mode_panel  = GET_WIDGET("programming_mode_panel");
+    X.degree_radio     = GET_WIDGET("degrees_radio");
+    X.gradian_radio    = GET_WIDGET("gradians_radio");
+    X.radian_radio     = GET_WIDGET("radians_radio");
     X.base[0]      = GET_WIDGET("binary_radio");
     X.base[1]      = GET_WIDGET("octal_radio");
     X.base[2]      = GET_WIDGET("decimal_radio");
@@ -2731,9 +2746,9 @@ create_kframe()
     gtk_widget_realize(X.kframe);
     set_win_position();
 
-    for (i = 0; i < 3; i++)
-        g_object_set_data(G_OBJECT(X.trig[i]),
-                          "trig_mode", GINT_TO_POINTER(i));
+    g_object_set_data(G_OBJECT(X.radian_radio), "trig_mode", GINT_TO_POINTER(MP_RADIANS));
+    g_object_set_data(G_OBJECT(X.degree_radio), "trig_mode", GINT_TO_POINTER(MP_DEGREES));
+    g_object_set_data(G_OBJECT(X.gradian_radio), "trig_mode", GINT_TO_POINTER(MP_GRADIANS));
     for (i = 0; i < 4; i++)
         g_object_set_data(G_OBJECT(X.base[i]),
                           "base_mode", GINT_TO_POINTER(i));
diff --git a/src/mp-equation-lexer.l b/src/mp-equation-lexer.l
index f8fc4d2..6bc7971 100644
--- a/src/mp-equation-lexer.l
+++ b/src/mp-equation-lexer.l
@@ -97,37 +97,37 @@ return tREG;
 
 
 {DEC_NUM}{EXP}{DEC_NUM} {
-if (v->base == HEX) REJECT;
+if (_mp_equation_get_extra(yyscanner)->base == 16) REJECT;
 if (strlen(yytext) > MAX_DIGITS) yyextra->error = -PARSER_ERR_TOO_LONG_NUMBER;
-mp_set_from_string(yytext, basevals[v->base], &yylval->int_t);
+mp_set_from_string(yytext, _mp_equation_get_extra(yyscanner)->base, &yylval->int_t);
 return tNUMBER;
 }
 
 {BIN_NUM} {
-if (v->base != BIN) REJECT;
+if (_mp_equation_get_extra(yyscanner)->base != 2) REJECT;
 if (strlen(yytext) > MAX_DIGITS) yyextra->error = -PARSER_ERR_TOO_LONG_NUMBER;
-mp_set_from_string(yytext, basevals[v->base], &yylval->int_t);
+mp_set_from_string(yytext, _mp_equation_get_extra(yyscanner)->base, &yylval->int_t);
 return tNUMBER;
 }
 
 {OCT_NUM} {
-if (v->base != OCT) REJECT;
+if (_mp_equation_get_extra(yyscanner)->base != 8) REJECT;
 if (strlen(yytext) > MAX_DIGITS) yyextra->error = -PARSER_ERR_TOO_LONG_NUMBER;
-mp_set_from_string(yytext, basevals[v->base], &yylval->int_t);
+mp_set_from_string(yytext, _mp_equation_get_extra(yyscanner)->base, &yylval->int_t);
 return tNUMBER;
 }
 
 {DEC_NUM} {
-if (v->base != DEC) REJECT;
+if (_mp_equation_get_extra(yyscanner)->base != 10) REJECT;
 if (strlen(yytext) > MAX_DIGITS) yyextra->error = -PARSER_ERR_TOO_LONG_NUMBER;
-mp_set_from_string(yytext, basevals[v->base], &yylval->int_t);
+mp_set_from_string(yytext, _mp_equation_get_extra(yyscanner)->base, &yylval->int_t);
 return tNUMBER;
 }
 
 {HEX_NUM} {
-if (v->base != HEX) REJECT;
+if (_mp_equation_get_extra(yyscanner)->base != 16) REJECT;
 if (strlen(yytext) > MAX_DIGITS) yyextra->error = -PARSER_ERR_TOO_LONG_NUMBER;
-mp_set_from_string(yytext, basevals[v->base], &yylval->int_t);
+mp_set_from_string(yytext, _mp_equation_get_extra(yyscanner)->base, &yylval->int_t);
 return tNUMBER;
 }
 
diff --git a/src/mp-equation-parser.y b/src/mp-equation-parser.y
index 7f5ad70..81e2234 100644
--- a/src/mp-equation-parser.y
+++ b/src/mp-equation-parser.y
@@ -104,9 +104,9 @@
 
 statement: 
   seq
-| value { mp_set_from_mp(&$1, &((MPEquationParserState *)_mp_equation_get_extra(yyscanner))->ret); ((MPEquationParserState *)_mp_equation_get_extra(yyscanner))->flags |= ANS; }
+| value { mp_set_from_mp(&$1, &(_mp_equation_get_extra(yyscanner))->ret); (_mp_equation_get_extra(yyscanner))->flags |= ANS; }
 | error {
-  ((MPEquationParserState *)_mp_equation_get_extra(yyscanner))->error = -EINVAL; 
+  (_mp_equation_get_extra(yyscanner))->error = -EINVAL; 
   YYABORT;
 }
 ;
@@ -146,35 +146,35 @@ exp:
 
 | exp tMOD exp %prec MED {
     if (!mp_is_integer(&$1) || !mp_is_integer(&$3)) {
-	((MPEquationParserState *)_mp_equation_get_extra(yyscanner))->error = -PARSER_ERR_MODULUSOP;
+	(_mp_equation_get_extra(yyscanner))->error = -PARSER_ERR_MODULUSOP;
     } else {
       if (mp_modulus_divide(&$1, &$3, &$$)) {
-        ((MPEquationParserState *)_mp_equation_get_extra(yyscanner))->error = -EINVAL;
+        (_mp_equation_get_extra(yyscanner))->error = -EINVAL;
       }			   
     }
 }
 
 | exp tAND exp {
     if (!mp_is_natural(&$1) || !mp_is_natural(&$3)) {
-	((MPEquationParserState *)_mp_equation_get_extra(yyscanner))->error = -PARSER_ERR_BITWISEOP;
+	(_mp_equation_get_extra(yyscanner))->error = -PARSER_ERR_BITWISEOP;
     }
     mp_and(&$1, &$3, &$$);
 }
 | exp tOR exp {
     if (!mp_is_natural(&$1) || !mp_is_natural(&$3)) {
-	((MPEquationParserState *)_mp_equation_get_extra(yyscanner))->error = -PARSER_ERR_BITWISEOP;
+	(_mp_equation_get_extra(yyscanner))->error = -PARSER_ERR_BITWISEOP;
     }
     mp_or(&$1, &$3, &$$);
 }
 | exp tXNOR exp {
     if (!mp_is_natural(&$1) || !mp_is_natural(&$3)) {
-	((MPEquationParserState *)_mp_equation_get_extra(yyscanner))->error = -PARSER_ERR_BITWISEOP;
+	(_mp_equation_get_extra(yyscanner))->error = -PARSER_ERR_BITWISEOP;
     }
-    mp_xnor(&$1, &$3, v->wordlen, &$$);
+    mp_xnor(&$1, &$3, _mp_equation_get_extra(yyscanner)->wordlen, &$$);
 }
 | exp tXOR exp {
     if (!mp_is_natural(&$1) || !mp_is_natural(&$3)) {
-	((MPEquationParserState *)_mp_equation_get_extra(yyscanner))->error = -PARSER_ERR_BITWISEOP;
+	(_mp_equation_get_extra(yyscanner))->error = -PARSER_ERR_BITWISEOP;
     }
     mp_xor(&$1, &$3, &$$);
 }
@@ -191,11 +191,11 @@ term:
 | term '%' {mp_divide_integer(&$1, 100, &$$);}
 | '~' term %prec LNEG {
     if (!mp_is_natural(&$2)) {
-	((MPEquationParserState *)_mp_equation_get_extra(yyscanner))->error = -PARSER_ERR_BITWISEOP;
-    } else if (!mp_is_overflow(&$2, v->wordlen)) {
-	((MPEquationParserState *)_mp_equation_get_extra(yyscanner))->error = -PARSER_ERR_OVERFLOW;
+	(_mp_equation_get_extra(yyscanner))->error = -PARSER_ERR_BITWISEOP;
+    } else if (!mp_is_overflow(&$2, _mp_equation_get_extra(yyscanner)->wordlen)) {
+	(_mp_equation_get_extra(yyscanner))->error = -PARSER_ERR_OVERFLOW;
     }
-    mp_not(&$2, v->wordlen, &$$);
+    mp_not(&$2, _mp_equation_get_extra(yyscanner)->wordlen, &$$);
 }
 | '-' term %prec NEG {mp_invert_sign(&$2, &$$);}
 | '+' term %prec POS {mp_set_from_mp(&$2, &$$);}
@@ -226,12 +226,12 @@ func:
 | tINT term %prec HIGH {mp_integer_component(&$2, &$$);}
 | tCHS term %prec HIGH {mp_invert_sign(&$2, &$$);}
 
-| tSIN term %prec HIGH {to_rad(&$2, &$2); mp_sin(&$2, &$$);}
-| tCOS term %prec HIGH {to_rad(&$2, &$2); mp_cos(&$2, &$$);}
-| tTAN term %prec HIGH {to_rad(&$2, &$2); mp_tan(&$2, &$$);}
-| tASIN term %prec HIGH {mp_asin(&$2, &$$); do_trig_typeconv(v->ttype, &$$, &$$);}
-| tACOS term %prec HIGH {mp_acos(&$2, &$$); do_trig_typeconv(v->ttype, &$$, &$$);}
-| tATAN term %prec HIGH {mp_atan(&$2, &$$); do_trig_typeconv(v->ttype, &$$, &$$);}
+| tSIN term %prec HIGH {mp_sin(&$2, _mp_equation_get_extra(yyscanner)->angle_units, &$$);}
+| tCOS term %prec HIGH {mp_cos(&$2, _mp_equation_get_extra(yyscanner)->angle_units, &$$);}
+| tTAN term %prec HIGH {mp_tan(&$2, _mp_equation_get_extra(yyscanner)->angle_units, &$$);}
+| tASIN term %prec HIGH {mp_asin(&$2, _mp_equation_get_extra(yyscanner)->angle_units, &$$);}
+| tACOS term %prec HIGH {mp_acos(&$2, _mp_equation_get_extra(yyscanner)->angle_units, &$$);}
+| tATAN term %prec HIGH {mp_atan(&$2, _mp_equation_get_extra(yyscanner)->angle_units, &$$);}
 | tSINH term %prec HIGH {mp_sinh(&$2, &$$);}
 | tCOSH term %prec HIGH {mp_cosh(&$2, &$$);}
 | tTANH term %prec HIGH {mp_tanh(&$2, &$$);}
@@ -239,22 +239,22 @@ func:
 | tACOSH term %prec HIGH {mp_acosh(&$2, &$$);}
 | tATANH term %prec HIGH {mp_atanh(&$2, &$$);}
 
-| tTRUNC term %prec HIGH {mp_mask(&$2, v->wordlen, &$$);}
+| tTRUNC term %prec HIGH {mp_mask(&$2, _mp_equation_get_extra(yyscanner)->wordlen, &$$);}
 | t1S term %prec HIGH  {
     if (!mp_is_natural(&$2)) {
-	((MPEquationParserState *)_mp_equation_get_extra(yyscanner))->error = -PARSER_ERR_BITWISEOP;
-    } else if (!mp_is_overflow(&$2, v->wordlen)) {
-	((MPEquationParserState *)_mp_equation_get_extra(yyscanner))->error = -PARSER_ERR_OVERFLOW;
+	(_mp_equation_get_extra(yyscanner))->error = -PARSER_ERR_BITWISEOP;
+    } else if (!mp_is_overflow(&$2, _mp_equation_get_extra(yyscanner)->wordlen)) {
+	(_mp_equation_get_extra(yyscanner))->error = -PARSER_ERR_OVERFLOW;
     }
-    mp_1s_complement(&$2, v->wordlen, &$$);
+    mp_1s_complement(&$2, _mp_equation_get_extra(yyscanner)->wordlen, &$$);
 }
 | t2S term %prec HIGH {
     if (!mp_is_natural(&$2)) {
-	((MPEquationParserState *)_mp_equation_get_extra(yyscanner))->error = -PARSER_ERR_BITWISEOP;
-    } else if (!mp_is_overflow(&$2, v->wordlen)) {
-	((MPEquationParserState *)_mp_equation_get_extra(yyscanner))->error = -PARSER_ERR_OVERFLOW;
+	(_mp_equation_get_extra(yyscanner))->error = -PARSER_ERR_BITWISEOP;
+    } else if (!mp_is_overflow(&$2, _mp_equation_get_extra(yyscanner)->wordlen)) {
+	(_mp_equation_get_extra(yyscanner))->error = -PARSER_ERR_OVERFLOW;
     }
-    mp_2s_complement(&$2, v->wordlen, &$$);
+    mp_2s_complement(&$2, _mp_equation_get_extra(yyscanner)->wordlen, &$$);
 }
 ;
 
diff --git a/src/mp-equation.c b/src/mp-equation.c
index ad768f1..1c46b52 100644
--- a/src/mp-equation.c
+++ b/src/mp-equation.c
@@ -30,17 +30,20 @@ int
 mp_equation_parse_(const char *expression, MPNumber *result, int flags)
 {
     int ret = 0;
-    MPEquationParserState parser_state;
+    MPEquationParserState state;
     yyscan_t yyscanner;
     YY_BUFFER_STATE buffer;
 
     if (!(expression && result) || strlen(expression) == 0)
         return(-EINVAL);
 
-    memset(&parser_state, 0, sizeof(MPEquationParserState));
+    memset(&state, 0, sizeof(MPEquationParserState));
+    state.base = basevals[v->base];
+    state.wordlen = v->wordlen;
+    state.angle_units = v->ttype;
     v->math_error = 0;
         
-    _mp_equation_lex_init_extra(&parser_state, &yyscanner);
+    _mp_equation_lex_init_extra(&state, &yyscanner);
     buffer = _mp_equation__scan_string(expression, yyscanner);
 
     ret = _mp_equation_parse(yyscanner);
@@ -48,12 +51,12 @@ mp_equation_parse_(const char *expression, MPNumber *result, int flags)
     _mp_equation__delete_buffer(buffer, yyscanner);
     _mp_equation_lex_destroy(yyscanner);
 
-    ret = (parser_state.error) ? parser_state.error : ret;
+    ret = (state.error) ? state.error : ret;
 
     if (ret) {
         return(ret);
     } else {
-        if ((flags & ANS) != (parser_state.flags & ANS)) {
+        if ((flags & ANS) != (state.flags & ANS)) {
             return -EINVAL;
         }
 
@@ -62,7 +65,7 @@ mp_equation_parse_(const char *expression, MPNumber *result, int flags)
         }
 
         if (flags & ANS) {
-            mp_set_from_mp(&parser_state.ret, result);
+            mp_set_from_mp(&state.ret, result);
         }
 
         return 0;
diff --git a/src/mp-equation.h b/src/mp-equation.h
index a8f0aa1..cbc163c 100644
--- a/src/mp-equation.h
+++ b/src/mp-equation.h
@@ -39,11 +39,23 @@
 #define PARSER_ERR_MODULUSOP        10003
 #define PARSER_ERR_OVERFLOW         10004
 
+/* State for parser */
 typedef struct {
+    /* The numeric base (e.g 2, 8, 10, 16) */
+    int base;
+
+    /* The wordlength for binary operations in bits (e.g. 8, 16, 32) */
+    int wordlen;
+    
+    /* Units for angles (e.g. radians, degrees) */
+    MPAngleUnit angle_units;
+
     int flags;
 
+    /* Error returned from parser */
     int error;
 
+    /* Value returned from parser */
     MPNumber ret;
 } MPEquationParserState;
 
diff --git a/src/mp-trigonometric.c b/src/mp-trigonometric.c
index b103b17..5901f05 100644
--- a/src/mp-trigonometric.c
+++ b/src/mp-trigonometric.c
@@ -73,7 +73,7 @@ mpsin1(const MPNumber *x, MPNumber *z, int do_sin)
         return;
     }
 
-    b2 = max(MP.b,64) << 1;
+    b2 = max(MP.b, 64) << 1;
     mp_multiply(x, x, &t2);
     if (mp_compare_mp_to_int(&t2, 1) > 0) {
         mperr("*** ABS(X) > 1 IN CALL TO MPSIN1 ***");
@@ -81,7 +81,7 @@ mpsin1(const MPNumber *x, MPNumber *z, int do_sin)
 
     if (do_sin == 0)
         mp_set_from_integer(1, &t1);
-    if (do_sin != 0)
+    else
         mp_set_from_mp(x, &t1);
 
     z->sign = 0;
@@ -100,14 +100,12 @@ mpsin1(const MPNumber *x, MPNumber *z, int do_sin)
             break;
         t = min(t, MP.t);
 
-        /* PUT R(I3) FIRST IN CASE ITS DIGITS ARE MAINLY ZERO */
-        mp_multiply(&t2, &t1, &t1);
-
         /*  IF I*(I+1) IS NOT REPRESENTABLE AS AN INTEGER, THE FOLLOWING
          *  DIVISION BY I*(I+1) HAS TO BE SPLIT UP.
          */
         ts = MP.t;
         MP.t = t;
+        mp_multiply(&t2, &t1, &t1);
         if (i > b2) {
             mp_divide_integer(&t1, -i, &t1);
             mp_divide_integer(&t1, i + 1, &t1);
@@ -115,8 +113,8 @@ mpsin1(const MPNumber *x, MPNumber *z, int do_sin)
             mp_divide_integer(&t1, -i * (i + 1), &t1);
         }
         MP.t = ts;
-
         mp_add(&t1, z, z);
+
         if (t1.sign == 0)
             break;
     }
@@ -188,6 +186,58 @@ mp_atan1N(int n, MPNumber *z)
     }
 }
 
+
+/* Convert x to radians */
+static void
+convert_to_radians(const MPNumber *x, MPAngleUnit unit, MPNumber *z)
+{
+    MPNumber t1, t2;
+
+    switch(unit) {
+    default:
+    case MP_RADIANS:
+        mp_set_from_mp(x, z);
+        break;
+
+    case MP_DEGREES:
+        mp_get_pi(&t1);
+        mp_multiply(x, &t1, &t2);
+        mp_divide_integer(&t2, 180, z);
+        break;
+
+    case MP_GRADIANS:        
+        mp_get_pi(&t1);
+        mp_multiply(x, &t1, &t2);
+        mp_divide_integer(&t2, 200, z);
+        break;
+    }
+}
+
+static void
+convert_from_radians(const MPNumber *x, MPAngleUnit unit, MPNumber *z)
+{
+    MPNumber t1, t2;
+    
+    switch (unit) {
+    default:
+    case MP_RADIANS:
+        mp_set_from_mp(x, z);
+        break;
+        
+    case MP_DEGREES:
+        mp_multiply_integer(x, 180, &t2);
+        mp_get_pi(&t1);
+        mp_divide(&t2, &t1, z);
+        break;
+        
+    case MP_GRADIANS:
+        mp_multiply_integer(x, 200, &t2);
+        mp_get_pi(&t1);
+        mp_divide(&t2, &t1, z);
+        break;
+    }
+}
+
 /*  SETS MP Z = PI TO THE AVAILABLE PRECISION.
  *  USES PI/4 = 4.ARCTAN(1/5) - ARCTAN(1/239).
  *  TIME IS O(T**2).
@@ -208,87 +258,163 @@ mp_get_pi(MPNumber *z)
     mp_subtract(&t, z, z);
     mp_multiply_integer(z, 4, z);
 
-    /* RETURN IF ERROR IS LESS THAN 0.01 */
-    prec = fabs(mp_cast_to_float(z) - 3.1416);
-    if (prec < 0.01) return;
-
     /* FOLLOWING MESSAGE MAY INDICATE THAT B**(T-1) IS TOO SMALL */
-    mperr("*** ERROR OCCURRED IN MP_GET_PI, RESULT INCORRECT ***");
+    prec = fabs(mp_cast_to_float(z) - 3.1416);
+    if (prec >= 0.01)
+        mperr("*** ERROR OCCURRED IN MP_GET_PI, RESULT INCORRECT ***");
 }
 
-/*  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
+
+/*  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_acos(const MPNumber *x, MPNumber *z)
+mp_sin(const MPNumber *x, MPAngleUnit unit, MPNumber *z)
 {
-    MPNumber MP1, MP2;
-    MPNumber MPn1, MPpi, MPy;
-
-    mp_get_pi(&MPpi);
-    mp_set_from_integer(1, &MP1);
-    mp_set_from_integer(-1, &MPn1);
+    int ie, xs;
+    float rx = 0.0;
+    MPNumber t1, t2;
 
-    if (mp_is_greater_than(x, &MP1) || mp_is_less_than(x, &MPn1)) {
-        mperr("Error");
-        z->sign = 0;
-    } else if (x->sign == 0) {
-        mp_divide_integer(&MPpi, 2, z);
-    } else if (mp_is_equal(x, &MP1)) {
+    mpchk();
+    
+    convert_to_radians(x, unit, &t1);
+    
+    if (t1.sign == 0) {
         z->sign = 0;
-    } else if (mp_is_equal(x, &MPn1)) {
-        mp_set_from_mp(&MPpi, z);
-    } else { 
-        mp_multiply(x, x, &MP2);
-        mp_subtract(&MP1, &MP2, &MP2);
-        mp_sqrt(&MP2, &MP2);
-        mp_divide(&MP2, x, &MP2);
-        mp_atan(&MP2, &MPy);
-        if (x->sign > 0) {
-            mp_set_from_mp(&MPy, z);
+        return;
+    }
+
+    xs = t1.sign;
+    ie = abs(t1.exponent);
+    if (ie <= 2)
+        rx = mp_cast_to_float(&t1);
+
+    mp_abs(&t1, &t1);
+
+    /* USE MPSIN1 IF ABS(X) <= 1 */
+    if (mp_compare_mp_to_int(&t1, 1) <= 0)
+    {
+        mpsin1(&t1, z, 1);
+    }
+    /*  FIND ABS(X) MODULO 2PI (IT WOULD SAVE TIME IF PI WERE
+     *  PRECOMPUTED AND SAVED IN COMMON).
+     *  FOR INCREASED ACCURACY COMPUTE PI/4 USING MP_ATAN1N
+     */
+    else {
+        mp_atan1N(5, &t2);
+        mp_multiply_integer(&t2, 4, &t2);
+        mp_atan1N(239, z);
+        mp_subtract(&t2, z, z);
+        mp_divide(&t1, z, &t1);
+        mp_divide_integer(&t1, 8, &t1);
+        mp_fractional_component(&t1, &t1);
+
+        /* SUBTRACT 1/2, SAVE SIGN AND TAKE ABS */
+        mp_add_fraction(&t1, -1, 2, &t1);
+        xs = -xs * t1.sign;
+        if (xs == 0) {
+            z->sign = 0;
+            return;
+        }
+
+        t1.sign = 1;
+        mp_multiply_integer(&t1, 4, &t1);
+
+        /* IF NOT LESS THAN 1, SUBTRACT FROM 2 */
+        if (t1.exponent > 0)
+            mp_add_integer(&t1, -2, &t1);
+
+        if (t1.sign == 0) {
+            z->sign = 0;
+            return;
+        }        
+
+        t1.sign = 1;
+        mp_multiply_integer(&t1, 2, &t1);
+
+        /*  NOW REDUCED TO FIRST QUADRANT, IF LESS THAN PI/4 USE
+         *  POWER SERIES, ELSE COMPUTE COS OF COMPLEMENT
+         */
+        if (t1.exponent > 0) {
+            mp_add_integer(&t1, -2, &t1);
+            mp_multiply(&t1, z, &t1);
+            mpsin1(&t1, z, 0);
         } else {
-            mp_add(&MPy, &MPpi, z);
+            mp_multiply(&t1, z, &t1);
+            mpsin1(&t1, z, 1);
         }
     }
+
+    z->sign = xs;
+
+    /*  CHECK THAT ABSOLUTE ERROR LESS THAN 0.01 IF ABS(X) <= 100
+     *  (IF ABS(X) IS LARGE THEN SINGLE-PRECISION SIN INACCURATE)
+     */
+    if (ie <= 2 && fabs(rx) <= 100.0) {
+        float ry = mp_cast_to_float(z);
+        /*  THE FOLLOWING MESSAGE MAY INDICATE THAT B**(T-1) IS TOO SMALL. */
+        if (fabs(ry - sin(rx)) >= 0.01)
+            mperr("*** ERROR OCCURRED IN MPSIN, RESULT INCORRECT ***");
+    }
 }
 
 
-/*  MP precision hyperbolic arc cosine.
- *
- *  1. If (x < 1) then report DOMAIN error and return 0.
- *
- *  2. acosh(x) = log(x + sqrt(x^2 - 1))
+/*  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_acosh(const MPNumber *x, MPNumber *z)
+mp_cos(const MPNumber *xi, MPAngleUnit unit, MPNumber *z)
 {
-    MPNumber MP1;
+    MPNumber t;
 
-    mp_set_from_integer(1, &MP1);
-    if (mp_is_less_than(x, &MP1)) {
-        mperr("Error");
-        mp_set_from_integer(0, z);
+    /* COS(0) = 1 */    
+    if (xi->sign == 0) {
+        mp_set_from_integer(1, z);
+        return;
+    }
+
+    /* CHECK LEGALITY OF B, T, M AND MXR */
+    mpchk();
+
+    convert_to_radians(xi, unit, z);
+
+    /* SEE IF ABS(X) <= 1 */
+    mp_abs(z, z);
+    if (mp_compare_mp_to_int(z, 1) <= 0) {
+        /* HERE ABS(X) <= 1 SO USE POWER SERIES */
+        mpsin1(z, z, 0);
     } else {
-        mp_multiply(x, x, &MP1);
-        mp_add_integer(&MP1, -1, &MP1);
-        mp_sqrt(&MP1, &MP1);
-        mp_add(x, &MP1, &MP1);
-        mp_ln(&MP1, z);
+        /*  HERE ABS(X) > 1 SO USE COS(X) = SIN(PI/2 - ABS(X)),
+         *  COMPUTING PI/2 WITH ONE GUARD DIGIT.
+         */
+        mp_get_pi(&t);
+        mp_divide_integer(&t, 2, &t);
+        mp_subtract(&t, z, z);
+        mp_sin(z, MP_RADIANS, z);
     }
 }
 
 
+void 
+mp_tan(const MPNumber *x, MPAngleUnit unit, MPNumber *z)
+{
+    MPNumber cos_x, sin_x;
+
+    mp_sin(x, unit, &sin_x);
+    mp_cos(x, unit, &cos_x);
+    /* Check if COS(x) == 0 */
+    if (mp_is_zero(&cos_x)) {
+        /* Translators: Error displayed when tangent value is undefined */
+        mperr(_("Tangent is infinite"));
+        return;
+    }
+    mp_divide(&sin_x, &cos_x, 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.
@@ -297,7 +423,7 @@ mp_acosh(const MPNumber *x, MPNumber *z)
  *  CHECK LEGALITY OF B, T, M AND MXR
  */
 void
-mp_asin(const MPNumber *x, MPNumber *z)
+mp_asin(const MPNumber *x, MPAngleUnit unit, MPNumber *z)
 {
     MPNumber t1, t2;
 
@@ -316,36 +442,70 @@ mp_asin(const MPNumber *x, MPNumber *z)
         mp_multiply(&t1, &t2, &t2);
         mp_root(&t2, -2, &t2);
         mp_multiply(x, &t2, z);
-        mp_atan(z, z);
+        mp_atan(z, unit, z);
         return;
     }
 
     /* HERE ABS(X) >= 1.  SEE IF X == +-1 */
     mp_set_from_integer(x->sign, &t2);
-    if (!mp_is_equal(x, &t2)) {
+    if (!mp_is_equal(x, &t2))
         mperr("*** ABS(X) > 1 IN CALL TO MP_ASIN ***");
-    }
 
     /* X == +-1 SO RETURN +-PI/2 */
     mp_get_pi(z);
     mp_divide_integer(z, t2.sign << 1, z);
+    
+    convert_from_radians(z, unit, z);
 }
 
 
-/*  MP precision hyperbolic arc sine.
+/*  MP precision arc cosine.
  *
- *  1. asinh(x) = log(x + sqrt(x^2 + 1))
+ *  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_asinh(const MPNumber *x, MPNumber *z)
+mp_acos(const MPNumber *x, MPAngleUnit unit, MPNumber *z)
 {
-    MPNumber MP1;
- 
-    mp_multiply(x, x, &MP1);
-    mp_add_integer(&MP1, 1, &MP1);
-    mp_sqrt(&MP1, &MP1);
-    mp_add(x, &MP1, &MP1);
-    mp_ln(&MP1, z);
+    MPNumber MP1, MP2;
+    MPNumber MPn1, MPpi, MPy;
+
+    mp_get_pi(&MPpi);
+    mp_set_from_integer(1, &MP1);
+    mp_set_from_integer(-1, &MPn1);
+
+    if (mp_is_greater_than(x, &MP1) || mp_is_less_than(x, &MPn1)) {
+        mperr("Error");
+        z->sign = 0;
+    } else if (x->sign == 0) {
+        mp_divide_integer(&MPpi, 2, z);
+    } else if (mp_is_equal(x, &MP1)) {
+        z->sign = 0;
+    } else if (mp_is_equal(x, &MPn1)) {
+        mp_set_from_mp(&MPpi, z);
+    } else { 
+        mp_multiply(x, x, &MP2);
+        mp_subtract(&MP1, &MP2, &MP2);
+        mp_sqrt(&MP2, &MP2);
+        mp_divide(&MP2, x, &MP2);
+        mp_atan(&MP2, MP_RADIANS, &MPy);
+        if (x->sign > 0) {
+            mp_set_from_mp(&MPy, z);
+        } else {
+            mp_add(&MPy, &MPpi, z);
+        }
+    }
+    
+    convert_from_radians(z, unit, z);
 }
 
 
@@ -360,10 +520,10 @@ mp_asinh(const MPNumber *x, MPNumber *z)
  *  CHECK LEGALITY OF B, T, M AND MXR
  */
 void
-mp_atan(const MPNumber *x, MPNumber *z)
+mp_atan(const MPNumber *x, MPAngleUnit unit, MPNumber *z)
 {
     int i, q;
-    float rx = 0.0, ry;
+    float rx = 0.0;
     MPNumber t1, t2;
 
     mpchk();
@@ -421,15 +581,56 @@ mp_atan(const MPNumber *x, MPNumber *z)
     /*  CHECK THAT RELATIVE ERROR LESS THAN 0.01 UNLESS EXPONENT
      *  OF X IS LARGE (WHEN ATAN MIGHT NOT WORK)
      */
-    if (abs(x->exponent) > 2)
-        return;
+    if (abs(x->exponent) <= 2) {
+        float ry = mp_cast_to_float(z);
+        /* THE FOLLOWING MESSAGE MAY INDICATE THAT B**(T-1) IS TOO SMALL. */
+        if (fabs(ry - atan(rx)) >= fabs(ry) * 0.01)
+            mperr("*** ERROR OCCURRED IN MP_ATAN, RESULT INCORRECT ***");
+    }
 
-    ry = mp_cast_to_float(z);
-    if (fabs(ry - atan(rx)) < fabs(ry) * (float).01)
-        return;
+    convert_from_radians(z, unit, z);
+}
+
+
+/*  MP precision hyperbolic arc cosine.
+ *
+ *  1. If (x < 1) then report DOMAIN error and return 0.
+ *
+ *  2. acosh(x) = log(x + sqrt(x^2 - 1))
+ */
+void
+mp_acosh(const MPNumber *x, MPNumber *z)
+{
+    MPNumber MP1;
 
-    /* THE FOLLOWING MESSAGE MAY INDICATE THAT B**(T-1) IS TOO SMALL. */
-    mperr("*** ERROR OCCURRED IN MP_ATAN, RESULT INCORRECT ***");
+    mp_set_from_integer(1, &MP1);
+    if (mp_is_less_than(x, &MP1)) {
+        mperr("Error");
+        mp_set_from_integer(0, z);
+    } else {
+        mp_multiply(x, x, &MP1);
+        mp_add_integer(&MP1, -1, &MP1);
+        mp_sqrt(&MP1, &MP1);
+        mp_add(x, &MP1, &MP1);
+        mp_ln(&MP1, z);
+    }
+}
+
+
+/*  MP precision hyperbolic arc sine.
+ *
+ *  1. asinh(x) = log(x + sqrt(x^2 + 1))
+ */
+void
+mp_asinh(const MPNumber *x, MPNumber *z)
+{
+    MPNumber MP1;
+
+    mp_multiply(x, x, &MP1);
+    mp_add_integer(&MP1, 1, &MP1);
+    mp_sqrt(&MP1, &MP1);
+    mp_add(x, &MP1, &MP1);
+    mp_ln(&MP1, z);
 }
 
 
@@ -462,40 +663,6 @@ mp_atanh(const MPNumber *x, 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 *x, MPNumber *z)
-{
-    MPNumber t;
-
-    /* COS(0) = 1 */    
-    if (x->sign == 0) {
-        mp_set_from_integer(1, z);
-        return;
-    }
-
-    /* CHECK LEGALITY OF B, T, M AND MXR */
-    mpchk();
-
-    /* SEE IF ABS(X) <= 1 */
-    mp_abs(x, z);
-    if (mp_compare_mp_to_int(z, 1) <= 0) {
-        /* HERE ABS(X) <= 1 SO USE POWER SERIES */
-        mpsin1(z, z, 0);
-    } else {
-        /*  HERE ABS(X) > 1 SO USE COS(X) = SIN(PI/2 - ABS(X)),
-         *  COMPUTING PI/2 WITH ONE GUARD DIGIT.
-         */
-        mp_get_pi(&t);
-        mp_divide_integer(&t, 2, &t);
-        mp_subtract(&t, z, z);
-        mp_sin(z, z);
-    }
-}
-
-
 /*  RETURNS Z = COSH(X) FOR MP NUMBERS X AND Z, X NOT TOO LARGE.
  *  USES MP_EPOWY, DIMENSION OF R IN COMMON AT LEAST 5T+12
  */
@@ -530,108 +697,6 @@ mp_cosh(const MPNumber *x, MPNumber *z)
 }
 
 
-/*  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, MPNumber *z)
-{
-    int ie, xs;
-    float rx = 0.0, ry;
-    MPNumber t1, t2;
-
-    mpchk();
-    
-    if (x->sign == 0) {
-        z->sign = 0;
-        return;
-    }
-
-    xs = x->sign;
-    ie = abs(x->exponent);
-    if (ie <= 2)
-        rx = mp_cast_to_float(x);
-
-    mp_abs(x, &t1);
-
-    /* USE MPSIN1 IF ABS(X) <= 1 */
-    if (mp_compare_mp_to_int(&t1, 1) <= 0)
-    {
-        mpsin1(&t1, z, 1);
-    }
-    /*  FIND ABS(X) MODULO 2PI (IT WOULD SAVE TIME IF PI WERE
-     *  PRECOMPUTED AND SAVED IN COMMON).
-     *  FOR INCREASED ACCURACY COMPUTE PI/4 USING MP_ATAN1N
-     */
-    else {
-        mp_atan1N(5, &t2);
-        mp_multiply_integer(&t2, 4, &t2);
-        mp_atan1N(239, z);
-        mp_subtract(&t2, z, z);
-        mp_divide(&t1, z, &t1);
-        mp_divide_integer(&t1, 8, &t1);
-        mp_fractional_component(&t1, &t1);
-
-        /* SUBTRACT 1/2, SAVE SIGN AND TAKE ABS */
-        mp_add_fraction(&t1, -1, 2, &t1);
-        xs = -xs * t1.sign;
-        if (xs == 0) {
-            z->sign = 0;
-            return;
-        }
-
-        t1.sign = 1;
-        mp_multiply_integer(&t1, 4, &t1);
-
-        /* IF NOT LESS THAN 1, SUBTRACT FROM 2 */
-        if (t1.exponent > 0)
-            mp_add_integer(&t1, -2, &t1);
-
-        if (t1.sign == 0) {
-            z->sign = 0;
-            return;
-        }        
-
-        t1.sign = 1;
-        mp_multiply_integer(&t1, 2, &t1);
-
-        /*  NOW REDUCED TO FIRST QUADRANT, IF LESS THAN PI/4 USE
-         *  POWER SERIES, ELSE COMPUTE COS OF COMPLEMENT
-         */
-        if (t1.exponent > 0) {
-            mp_add_integer(&t1, -2, &t1);
-            mp_multiply(&t1, z, &t1);
-            mpsin1(&t1, z, 0);
-        } else {
-            mp_multiply(&t1, z, &t1);
-            mpsin1(&t1, z, 1);
-        }
-    }
-
-    z->sign = xs;
-    if (ie > 2)
-        return;
-
-    /*  CHECK THAT ABSOLUTE ERROR LESS THAN 0.01 IF ABS(X) <= 100
-     *  (IF ABS(X) IS LARGE THEN SINGLE-PRECISION SIN INACCURATE)
-     */
-    if (fabs(rx) > (float)100.)
-        return;
-
-    ry = mp_cast_to_float(z);
-    if (fabs(ry - sin(rx)) < (float) 0.01)
-        return;
-
-    /*  THE FOLLOWING MESSAGE MAY INDICATE THAT
-     *  B**(T-1) IS TOO SMALL.
-     */
-    mperr("*** ERROR OCCURRED IN MPSIN, RESULT INCORRECT ***");
-}
-
-
 /*  RETURNS Z = SINH(X) FOR MP NUMBERS X AND Z, X NOT TOO LARGE.
  *  METHOD IS TO USE MP_EPOWY OR MPEXP1, SPACE = 5T+12
  *  SAVE SIGN OF X AND CHECK FOR ZERO, SINH(0) = 0
@@ -682,23 +747,6 @@ mp_sinh(const MPNumber *x, MPNumber *z)
 }
 
 
-void 
-mp_tan(const MPNumber *x, MPNumber *z)
-{
-    MPNumber MPcos, MPsin;
-
-    mp_sin(x, &MPsin);
-    mp_cos(x, &MPcos);
-    /* Check if COS(x) == 0 */
-    if (mp_is_zero(&MPcos)) {
-        /* Translators: Error displayed when tangent value is undefined */
-        mperr(_("Tangent is infinite"));
-        return;
-    }
-    mp_divide(&MPsin, &MPcos, z);
-}
-
-
 /*  RETURNS Z = TANH(X) FOR MP NUMBERS X AND Z,
  *  USING MP_EPOWY OR MPEXP1, SPACE = 5T+12
  */
@@ -723,7 +771,7 @@ mp_tanh(const MPNumber *x, MPNumber *z)
     mp_abs(x, &t);
 
     /* SEE IF ABS(X) SO LARGE THAT RESULT IS +-1 */
-    r__1 = (float) MP.t * (float).5 * log((float) MP.b);
+    r__1 = (float) MP.t * 0.5 * log((float) MP.b);
     mp_set_from_float(r__1, z);
     if (mp_compare_mp_to_mp(&t, z) > 0) {
         /* HERE ABS(X) IS VERY LARGE */
diff --git a/src/mp.c b/src/mp.c
index e94d218..356d274 100644
--- a/src/mp.c
+++ b/src/mp.c
@@ -121,10 +121,11 @@ mp_init(int accuracy)
 
 /* SETS Y = ABS(X) FOR MP NUMBERS X AND Y */
 void
-mp_abs(const MPNumber *x, MPNumber *y)
+mp_abs(const MPNumber *x, MPNumber *z)
 {
-    mp_set_from_mp(x, y);
-    y->sign = abs(y->sign);
+    mp_set_from_mp(x, z);
+    if (z->sign < 0)
+        z->sign = -z->sign;
 }
 
 /*  ADDS X AND Y, FORMING RESULT IN Z, WHERE X, Y AND Z ARE MP
@@ -1954,10 +1955,8 @@ mp_reciprocal(const MPNumber *x, MPNumber *z)
 
     /* RESTORE M AND CHECK FOR OVERFLOW (UNDERFLOW IMPOSSIBLE) */
     MP.m += -2;
-    if (z->exponent <= MP.m)
-        return;
-
-    mpovfl(z, "*** OVERFLOW OCCURRED IN MP_RECIPROCAL ***");
+    if (z->exponent > MP.m)
+        mpovfl(z, "*** OVERFLOW OCCURRED IN MP_RECIPROCAL ***");
 }
 
 
diff --git a/src/mp.h b/src/mp.h
index 39240d3..2e01645 100644
--- a/src/mp.h
+++ b/src/mp.h
@@ -56,6 +56,8 @@ typedef struct
    int fraction[MP_SIZE]; // Size MP.t?
 } MPNumber;
 
+typedef enum { MP_RADIANS, MP_DEGREES, MP_GRADIANS } MPAngleUnit;
+
 /* Initialise the MP state.  Must be called only once and before any other MP function
  * 'accuracy' is the requested accuracy required.
  */
@@ -206,22 +208,22 @@ int    mp_cast_to_int(const MPNumber *x);
 void   mp_cast_to_string(const MPNumber *x, int base, int max_digits, char *buffer, int buffer_length);
 
 /* Sets z = sin(x) */
-void   mp_sin(const MPNumber *x, MPNumber *z);
+void   mp_sin(const MPNumber *x, MPAngleUnit unit, MPNumber *z);
 
 /* Sets z = cos(x) */
-void   mp_cos(const MPNumber *x, MPNumber *z);
+void   mp_cos(const MPNumber *x, MPAngleUnit unit, MPNumber *z);
 
 /* Sets z = tan(x) */
-void   mp_tan(const MPNumber *x, MPNumber *z);
+void   mp_tan(const MPNumber *x, MPAngleUnit unit, MPNumber *z);
 
 /* Sets z = asin(x) */
-void   mp_asin(const MPNumber *x, MPNumber *z);
+void   mp_asin(const MPNumber *x, MPAngleUnit unit, MPNumber *z);
 
 /* Sets z = acos(x) */
-void   mp_acos(const MPNumber *x, MPNumber *z);
+void   mp_acos(const MPNumber *x, MPAngleUnit unit, MPNumber *z);
 
 /* Sets z = atan(x) */
-void   mp_atan(const MPNumber *x, MPNumber *z);
+void   mp_atan(const MPNumber *x, MPAngleUnit unit, MPNumber *z);
 
 /* Sets z = sinh(x) */
 void   mp_sinh(const MPNumber *x, MPNumber *z);
diff --git a/src/ui.h b/src/ui.h
index f008231..ce22e75 100644
--- a/src/ui.h
+++ b/src/ui.h
@@ -49,7 +49,7 @@ void ui_set_registers_visible(gboolean);
 void ui_set_accuracy(int);
 void ui_set_mode(ModeType);
 void ui_set_base(BaseType);
-void ui_set_trigonometric_mode(TrigType);
+void ui_set_trigonometric_mode(MPAngleUnit unit);
 void ui_set_numeric_mode(BaseType);
 void ui_set_show_thousands_separator(gboolean);
 void ui_set_show_trailing_zeroes(gboolean);
diff --git a/src/unittest.c b/src/unittest.c
index 24da065..2e0a68e 100644
--- a/src/unittest.c
+++ b/src/unittest.c
@@ -93,7 +93,7 @@ void
 test_parser()
 {
     v->base = DEC;
-    v->ttype = DEG;
+    v->ttype = MP_DEGREES;
     v->wordlen = 32;
     v->accuracy = 9;
 
@@ -191,7 +191,7 @@ test_parser()
     
     test("Ln(e^1)", "1", 0);
 
-    v->ttype = DEG;    
+    v->ttype = MP_DEGREES;
     test("Sin(0)", "0", 0);
     test("Sin(45) - 1/Sqrt(2)", "0", 0);
     test("Sin(20) + Sin(-20)", "0", 0);
@@ -232,13 +232,13 @@ test_parser()
     test("Atanh(0)", "0", 0);
     test("Atanh(1/10) - 1/2*Ln(11/9)", "0", 0);
 
-    v->ttype = DEG;
+    v->ttype = MP_DEGREES;
     test("Sin(90)", "1", 0);
     
-    v->ttype = RAD;
+    v->ttype = MP_RADIANS;
     test("Sin(3.14159/2)", "1", 0);
     
-    v->ttype = GRAD;
+    v->ttype = MP_GRADIANS;
     test("Sin(100)", "1", 0);
 
     v->base = HEX;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]