Thread overview
[phobos] Fixing std.math.pow(x, int.min)
Jun 21, 2010
Don Clugston
Jun 22, 2010
Don Clugston
June 21, 2010
Bug 3202 basically says that std.math.pow(someFloat, int.min) enters an infinite loop because int.min == -int.min.  Here's my suggestion for a fix:

--- std/math.d	(revision 1672)
+++ std/math.d	(working copy)
@@ -2904,6 +2904,12 @@
             return 1 / x;
         case -2:
             return 1 / (x * x);
+        static if (isSigned!G)
+        {
+        case G.min:
+            enum absGmin = cast(Unsigned!G)(-(G.min+1)) + 1;
+            return 1 / pow(x, absGmin);
+        }
         default:
         }

I'm wary of doing anything to std.math, since it's so fundamental and performance-critical.  So please, speak up if you see a problem with this patch.

-Lars

June 22, 2010
I think that actually m should be an unsigned type, then no special case is required. Line 2898.

-  G m = n;
+   Unsigned!(G) m = n;

Too late to test right now, but see if that works.


On 21 June 2010 21:28, Lars Tandle Kyllingstad <lars at kyllingen.net> wrote:
> Bug 3202 basically says that std.math.pow(someFloat, int.min) enters an infinite loop because int.min == -int.min. ?Here's my suggestion for a fix:
>
> --- std/math.d ?(revision 1672)
> +++ std/math.d ?(working copy)
> @@ -2904,6 +2904,12 @@
> ? ? ? ? ? ? return 1 / x;
> ? ? ? ? case -2:
> ? ? ? ? ? ? return 1 / (x * x);
> + ? ? ? ?static if (isSigned!G)
> + ? ? ? ?{
> + ? ? ? ?case G.min:
> + ? ? ? ? ? ?enum absGmin = cast(Unsigned!G)(-(G.min+1)) + 1;
> + ? ? ? ? ? ?return 1 / pow(x, absGmin);
> + ? ? ? ?}
> ? ? ? ? default:
> ? ? ? ? }
>
> I'm wary of doing anything to std.math, since it's so fundamental and performance-critical. ?So please, speak up if you see a problem with this patch.
>
> -Lars
>
> _______________________________________________
> phobos mailing list
> phobos at puremagic.com
> http://lists.puremagic.com/mailman/listinfo/phobos
>
June 22, 2010
You're right, that works.  Thanks!

But may I ask _why_ it works?  Consider:

    uint x = -int.min;

My first guess would be that the result of the negation is an int as well (and therefore == int.min), and that the cast to uint doesn't happen until the assignment.  Apparently this isn't the case.

I'll check the fix in, then.

-Lars


On Tue, 2010-06-22 at 00:01 +0200, Don Clugston wrote:
> I think that actually m should be an unsigned type, then no special case is required. Line 2898.
> 
> -  G m = n;
> +   Unsigned!(G) m = n;
> 
> Too late to test right now, but see if that works.
> 
> 
> On 21 June 2010 21:28, Lars Tandle Kyllingstad <lars at kyllingen.net> wrote:
> > Bug 3202 basically says that std.math.pow(someFloat, int.min) enters an infinite loop because int.min == -int.min.  Here's my suggestion for a fix:
> >
> > --- std/math.d  (revision 1672)
> > +++ std/math.d  (working copy)
> > @@ -2904,6 +2904,12 @@
> >             return 1 / x;
> >         case -2:
> >             return 1 / (x * x);
> > +        static if (isSigned!G)
> > +        {
> > +        case G.min:
> > +            enum absGmin = cast(Unsigned!G)(-(G.min+1)) + 1;
> > +            return 1 / pow(x, absGmin);
> > +        }
> >         default:
> >         }
> >
> > I'm wary of doing anything to std.math, since it's so fundamental and performance-critical.  So please, speak up if you see a problem with this patch.
> >
> > -Lars
> >
> > _______________________________________________
> > phobos mailing list
> > phobos at puremagic.com
> > http://lists.puremagic.com/mailman/listinfo/phobos
> >
> _______________________________________________
> phobos mailing list
> phobos at puremagic.com
> http://lists.puremagic.com/mailman/listinfo/phobos


June 22, 2010
On 22 June 2010 08:50, Lars Tandle Kyllingstad <lars at kyllingen.net> wrote:
> You're right, that works. ?Thanks!
>
> But may I ask _why_ it works? ?Consider:
>
> ? ?uint x = -int.min;
>
> My first guess would be that the result of the negation is an int as well (and therefore == int.min), and that the cast to uint doesn't happen until the assignment. ?Apparently this isn't the case.

-int.min is actually an unsigned result, that's why it wraps. Casting it to uint unwraps it.