You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by Gilles Sadowski <gi...@harfang.homelinux.org> on 2012/08/09 13:50:16 UTC

Re: svn commit: r1371082 - /commons/proper/math/trunk/src/main/java/org/apache/commons/math3/util/FastMath.java

Hi.

On Thu, Aug 09, 2012 at 08:07:25AM -0000, luc@apache.org wrote:
> Author: luc
> Date: Thu Aug  9 08:07:25 2012
> New Revision: 1371082
> 
> URL: http://svn.apache.org/viewvc?rev=1371082&view=rev
> Log:
> added a function to raise a double to an int power
> 
> Modified:
>     commons/proper/math/trunk/src/main/java/org/apache/commons/math3/util/FastMath.java
> 
> Modified: commons/proper/math/trunk/src/main/java/org/apache/commons/math3/util/FastMath.java
> URL: http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/util/FastMath.java?rev=1371082&r1=1371081&r2=1371082&view=diff
> ==============================================================================
> --- commons/proper/math/trunk/src/main/java/org/apache/commons/math3/util/FastMath.java (original)
> +++ commons/proper/math/trunk/src/main/java/org/apache/commons/math3/util/FastMath.java Thu Aug  9 08:07:25 2012
> @@ -1582,6 +1582,34 @@ public class FastMath {
>  
>  
>      /**
> +     * Raise a double to an int power.
> +     *
> +     * @param d Number to raise.
> +     * @param e Exponent.
> +     * @return d<sup>e</sup>
> +     */
> +    public static double pow(double d, int e) {
> +        if (e == 0) {
> +            return 1.0;
> +        } else if (e < 0) {
> +            e = -e;
> +            d = 1.0 / d;
> +        }
> +
> +        double result = 1;
> +        double d2p    = d;
> +        while (e != 0) {
> +            if ((e & 0x1) != 0) {
> +                result *= d2p;
> +            }
> +            d2p *= d2p;
> +            e = e >> 1;
> +        }
> +
> +        return result;
> +    }

I've added a unit test for this function. It shows that the result is not
the same as with "pow(double, double)" (cf. tolerance in "assertEquals").
I didn't check which one is more accurate, but I thought that we should be
aware of the discrepancy.


Regards,
Gilles

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org


Re: svn commit: r1371082 - /commons/proper/math/trunk/src/main/java/org/apache/commons/math3/util/FastMath.java

Posted by Gilles Sadowski <gi...@harfang.homelinux.org>.
Hello Luc.

> >> [...]
> >>+    public static double pow(double d, int e) {
> >>+        if (e == 0) {
> >>+            return 1.0;
> >>+        } else if (e < 0) {
> >>+            e = -e;
> >>+            d = 1.0 / d;
> >>+        }
> >>+
> >>+        double result = 1;
> >>+        double d2p    = d;
> >>+        while (e != 0) {
> >>+            if ((e & 0x1) != 0) {
> >>+                result *= d2p;
> >>+            }
> >>+            d2p *= d2p;
> >>+            e = e >> 1;
> >>+        }
> >>+
> >>+        return result;
> >>+    }
> >
> >I've added a unit test for this function. It shows that the result
> >is not
> >the same as with "pow(double, double)" (cf. tolerance in
> >"assertEquals").
> >I didn't check which one is more accurate, but I thought that we
> >should be
> >aware of the discrepancy.
> 
> I have checked this further. The pow(double, double) seems to be
> always slightly
> better than pow(double, int). I have used a comparison with Dfp set
> up at 60 digits
> and 100 digits too. I have also checked depending on the initial
> number being representable
> or not.
> 
> I expected the method to be slightly more accurate for small powers
> (say up to 20) and most
> importantly be much faster. The first part of my assumption is not
> true, so it is a major
> drawback. Even for very small powers I quickly have one ulp.
> 
> I'll take a further look at the current speed of pow(double,double)
> and if it is reasonable,
> I'll remove the new method. Adding a method that decreases accuracy
> is never good.

I had checked the performance too. ;-)
The "int" method is indeed about 8 times faster:
pow (calls per timed block: 200000, timed blocks: 100, time unit: ms)
         name      time/call      std error total time      ratio      difference
       double 2.92909569e-04 6.40278315e-05 5.8582e+03 1.0000e+00  0.00000000e+00
          int 3.72931144e-05 1.10545444e-05 7.4586e+02 1.2732e-01 -5.11232909e+03
double (Math) 3.52308890e-04 6.92417994e-05 7.0462e+03 1.2028e+00  1.18798641e+03

So, it's probably good to keep it, as long as people are aware of the
trade-off.


Best,
Gilles

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org


Re: svn commit: r1371082 - /commons/proper/math/trunk/src/main/java/org/apache/commons/math3/util/FastMath.java

Posted by luc <lu...@spaceroots.org>.
Le 2012-08-09 13:50, Gilles Sadowski a écrit :
> Hi.

Hi Gilles,

>
> On Thu, Aug 09, 2012 at 08:07:25AM -0000, luc@apache.org wrote:
>> Author: luc
>> Date: Thu Aug  9 08:07:25 2012
>> New Revision: 1371082
>>
>> URL: http://svn.apache.org/viewvc?rev=1371082&view=rev
>> Log:
>> added a function to raise a double to an int power
>>
>> Modified:
>>     
>> commons/proper/math/trunk/src/main/java/org/apache/commons/math3/util/FastMath.java
>>
>> Modified: 
>> commons/proper/math/trunk/src/main/java/org/apache/commons/math3/util/FastMath.java
>> URL: 
>> http://svn.apache.org/viewvc/commons/proper/math/trunk/src/main/java/org/apache/commons/math3/util/FastMath.java?rev=1371082&r1=1371081&r2=1371082&view=diff
>> 
>> ==============================================================================
>> --- 
>> commons/proper/math/trunk/src/main/java/org/apache/commons/math3/util/FastMath.java 
>> (original)
>> +++ 
>> commons/proper/math/trunk/src/main/java/org/apache/commons/math3/util/FastMath.java 
>> Thu Aug  9 08:07:25 2012
>> @@ -1582,6 +1582,34 @@ public class FastMath {
>>
>>
>>      /**
>> +     * Raise a double to an int power.
>> +     *
>> +     * @param d Number to raise.
>> +     * @param e Exponent.
>> +     * @return d<sup>e</sup>
>> +     */
>> +    public static double pow(double d, int e) {
>> +        if (e == 0) {
>> +            return 1.0;
>> +        } else if (e < 0) {
>> +            e = -e;
>> +            d = 1.0 / d;
>> +        }
>> +
>> +        double result = 1;
>> +        double d2p    = d;
>> +        while (e != 0) {
>> +            if ((e & 0x1) != 0) {
>> +                result *= d2p;
>> +            }
>> +            d2p *= d2p;
>> +            e = e >> 1;
>> +        }
>> +
>> +        return result;
>> +    }
>
> I've added a unit test for this function. It shows that the result is 
> not
> the same as with "pow(double, double)" (cf. tolerance in 
> "assertEquals").
> I didn't check which one is more accurate, but I thought that we 
> should be
> aware of the discrepancy.

I have checked this further. The pow(double, double) seems to be always 
slightly
better than pow(double, int). I have used a comparison with Dfp set up 
at 60 digits
and 100 digits too. I have also checked depending on the initial number 
being representable
or not.

I expected the method to be slightly more accurate for small powers 
(say up to 20) and most
importantly be much faster. The first part of my assumption is not 
true, so it is a major
drawback. Even for very small powers I quickly have one ulp.

I'll take a further look at the current speed of pow(double,double) and 
if it is reasonable,
I'll remove the new method. Adding a method that decreases accuracy is 
never good.

Thanks for having looked at this;

best regards,
Luc

>
>
> Regards,
> Gilles
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
> For additional commands, e-mail: dev-help@commons.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@commons.apache.org
For additional commands, e-mail: dev-help@commons.apache.org