[grisbi-cvs] grisbi/src gsb_real.c,1.39,1.40

Mickaƫl Remars mykeul at users.sourceforge.net
Wed May 20 22:27:33 CEST 2009


Update of /cvsroot/grisbi/grisbi/src
In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv26499/src

Modified Files:
	gsb_real.c 
Log Message:
New version of gsb_real_normalize() to make its unit-tests passing

Index: gsb_real.c
===================================================================
RCS file: /cvsroot/grisbi/grisbi/src/gsb_real.c,v
retrieving revision 1.39
retrieving revision 1.40
diff -u -d -r1.39 -r1.40
--- gsb_real.c	20 May 2009 19:49:29 -0000	1.39
+++ gsb_real.c	20 May 2009 20:27:31 -0000	1.40
@@ -32,6 +32,7 @@
 
 
 #include "include.h"
+#include <assert.h>
 
 /*START_INCLUDE*/
 #include "gsb_real.h"
@@ -409,61 +410,71 @@
 }
 
 /**
- * normalize the 2 numbers to be able to work with them later
+ * reduce the exponent to its smallest possible value,
+ * without losing any precision
+ *
+ * \param num a pointer to the number to be reduced
+ **/
+void gsb_real_minimize_exponent ( gsb_real *num )
+{
+    while ( num->exponent > 0 )
+    {
+        ldiv_t d = ldiv ( num->mantissa, 10 );
+        if ( d.rem != 0 )
+            return;
+        num->mantissa = d.quot;
+        --num->exponent;
+    }
+}
+
+/**
+ * grow the exponent up to target_exponent
+ * (only if possible without losing precision)
+ *
+ * \param num a pointer to the number
+ * \param target_exponent the desired exponent
+ **/
+void gsb_real_grow_exponent( gsb_real *num, guint target_exponent )
+{
+    assert ( target_exponent > num->exponent );
+    gint64 mantissa = num->mantissa;
+    gint exponent = num->exponent;
+    while ( exponent < target_exponent )
+    {
+        gint64 new_mantissa = mantissa * 10;
+        if ( ( new_mantissa > G_MAXLONG ) || ( new_mantissa < G_MINLONG ) )
+            break;
+        mantissa = new_mantissa;
+        ++exponent;
+    }
+    num->mantissa = mantissa;
+    num->exponent = exponent;
+}
+
+/**
+ * normalize the 2 numbers to be able to add/substract/compare them later
  * for that transform the 2 numbers to have the same exponent
  * and after that we can work on the mantissa
  *
  * \param number_1 a pointer to gsb_real wich contains the number_1 to transform
  * \param number_2 a pointer to gsb_real wich contains the number_2 to transform
  *
- * \return TRUE
+ * \return TRUE if normalization occured
+ * FALSE if exponents can't be the same without loss of precision
  * */
-gboolean gsb_real_normalize ( gsb_real *number_1,
-                        gsb_real *number_2 )
+gboolean gsb_real_normalize ( gsb_real *a, gsb_real *b )
 {
-    glong limit_number;
-    gboolean invert = FALSE;
-
-    limit_number = G_MAXLONG / 10;
-
-    while ( number_1 -> exponent != number_2 -> exponent )
+    gsb_real_minimize_exponent ( a );
+    gsb_real_minimize_exponent ( b );
+    if ( a->exponent < b->exponent )
     {
-	/* if we go over the upper limit we change the sense */
-	if ( !invert
-	     &&
-	     ( labs (number_1 -> mantissa) > limit_number
-	      ||
-	      labs (number_2 -> mantissa) > limit_number ))
-	    invert = TRUE;
-
-	if (number_1 -> exponent > number_2 -> exponent)
-	{
-	    if (invert)
-	    {
-		number_1 -> exponent--;
-		number_1 -> mantissa = number_1 -> mantissa / 10;
-	    }
-	    else
-	    {
-		number_2 -> exponent++;
-		number_2 -> mantissa = number_2 -> mantissa * 10;
-	    }
-	}
-	else
-	{
-	    if (invert)
-	    {
-		number_2 -> exponent--;
-		number_2 -> mantissa = number_2 -> mantissa / 10;
-	    }
-	    else
-	    {
-		number_1 -> exponent++;
-		number_1 -> mantissa = number_1 -> mantissa * 10;
-	    }
-	}
+        gsb_real_grow_exponent ( a, b->exponent );
     }
-    return TRUE;
+    else if ( b->exponent < a->exponent )
+    {
+        gsb_real_grow_exponent ( b, a->exponent );
+    }
+    return ( a->exponent == b->exponent );
 }
 
 /**



More information about the cvs mailing list