]> granicus.if.org Git - postgresql/commitdiff
Improve our private implementation of cbrt() to give results of the
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 24 Apr 2006 20:36:41 +0000 (20:36 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 24 Apr 2006 20:36:41 +0000 (20:36 +0000)
accuracy expected by the regression tests.  Per suggestion from
Martijn van Oosterhout.

src/backend/utils/adt/float.c

index fb37e36624e6c5dfcddb021aefa1eb5bf7924119..d80b3d4ef49ac596a3df6aba47f045dd0286953a 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/utils/adt/float.c,v 1.115 2005/10/15 02:49:28 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/utils/adt/float.c,v 1.115.2.1 2006/04/24 20:36:41 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2321,11 +2321,22 @@ float84ge(PG_FUNCTION_ARGS)
 /* ========== PRIVATE ROUTINES ========== */
 
 #ifndef HAVE_CBRT
+
 static double
 cbrt(double x)
 {
        int                     isneg = (x < 0.0);
-       double          tmpres = pow(fabs(x), (double) 1.0 / (double) 3.0);
+       double          absx = fabs(x);
+       double          tmpres = pow(absx, (double) 1.0 / (double) 3.0);
+
+       /*
+        * The result is somewhat inaccurate --- not really pow()'s fault,
+        * as the exponent it's handed contains roundoff error.  We can improve
+        * the accuracy by doing one iteration of Newton's formula.  Beware of
+        * zero input however.
+        */
+       if (tmpres > 0.0)
+               tmpres -= (tmpres - absx/(tmpres*tmpres)) / (double) 3.0;
 
        return isneg ? -tmpres : tmpres;
 }