Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

std.mathspecial: for 64-bit reals, provide MAXGAMMA, MAXLOG, and MINLOG #3045

Merged
merged 1 commit into from
Jul 30, 2015

Conversation

JohanEngelen
Copy link
Contributor

Because MAXGAMMA, MAXLOG, and MINLOG are only defined for 80-bit reals, gammafunction.d unittests fail for targets that have 64-bit reals (notably MSVC).

This PR conditionally defines the 64-bit equivalent constants. Also, it contains a fix for gammaStirling(x) in which a call to pow() would overflow for 64-bit reals for x > 143. This fixes several failing unittests. The changes should be a noop for 80-bit reals.
floatTraits from std.math is used to detect whether 80- or 64-bit reals are used; therefore there is a dependency on PR #3011.

The changes are tested using DMD 2.066.1 (Windows) and LDC2 (Windows, version 192583 based on DMD v2.066.1 and LLVM 3.7.0svn-r230699).

Comments are very welcome.

@yebblies
Copy link
Member

yebblies commented Mar 9, 2015

I've added you to the autotester whitelist: https://auto-tester.puremagic.com/pulls.ghtml?projectid=1

@JohanEngelen
Copy link
Contributor Author

Ah, great @yebblies , thanks!

@@ -231,7 +238,12 @@ real igammaTemmeLarge(real a, real x)

public:
/// The maximum value of x for which gamma(x) < real.infinity.
enum real MAXGAMMA = 1755.5483429L;
static if (real.mant_dig == 64) // 80-bit reals
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you use floatTraits from std.math ?
See also #3011

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed I tried, but floatTraits is still private. I agree it'd be better to use floatTraits.
When is #3011 going to be merged?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know about time, but DMD 2.068.

This PR can be good argument for #3011.
You may want to add dependency note in PR description: somebody from core team will add dependency label.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think now I screwed up this branch/PR while trying to update it to upstream master :'(

Edit: OK fixed it.

@JohanEngelen
Copy link
Contributor Author

Updated the PR using floatTraits from std.math. Depends on PR #3011.

@WalterBright
Copy link
Member

The DMC build for DMD uses 80 bit reals, even while supporting linking with MSVC libraries. Frankly, it's a bug in the MSVC generated build of DMD that 80 bit reals are not supported.
If the hardware supports 80 bits, then the D compiler ought to.

That doesn't affect this PR, though.

@quickfur
Copy link
Member

This PR requires PR #3011

@9il
Copy link
Member

9il commented May 1, 2015

@quickfur can you introduce math label?
#2991 #3011 #3045 #2548 #2862 #3186

@9il
Copy link
Member

9il commented Jul 16, 2015

PR #3011 was merged. Please remove trailing white spaces and rebase.

@JohanEngelen JohanEngelen force-pushed the gamma64bit branch 2 times, most recently from f6596f4 to 00fda8c Compare July 20, 2015 18:57
@JohanEngelen
Copy link
Contributor Author

@9il I've removed the excess whitespace and rebased.
Great that PR #3011 was merged.

@@ -111,7 +111,14 @@ real gammaStirling(real x)
}
else {
w = 1.0L + w * poly( w, SmallStirlingCoeffs);
y = pow( x, x - 0.5L ) / y;
if ( (floatTraits!(real).realFormat == RealFormat.ieeeDouble) && (x > 143.0L) ) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would the first condition be optimised at compile time?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You think it is better to do a static if on the first condition?
I think I chose against it, because of having to duplicate the y = pow( x, x - 0.5L ) / y;, but I have no preference. The alternative could be:

    else {
        w = 1.0L + w * poly( w, SmallStirlingCoeffs);
        static if (floatTraits!(real).realFormat == RealFormat.ieeeDouble) {
            // Avoid overflow in pow() for 64-bit reals
            if (x > 143.0L) ) {
                real v = pow( x, 0.5L * x - 0.25L );
                y = v * (v / y);
            }
            else {
                y = pow( x, x - 0.5L ) / y;
            }
        }
        else {
            y = pow( x, x - 0.5L ) / y;
        }
    }

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. This code looks better for math. Furthermore we would have this functions as template in the future, so please replace 0.5L for 64bit float with 0.5.

Inside gammaStirling(), fix a call to pow() that would overflow for 64-bit reals.
@JohanEngelen
Copy link
Contributor Author

@9il I've made some additional fixes and rebased again. Thank for the reviews.

At this point I have no further motivation to work on this (certainly not motivated to port CEPHES's double implementation). In the current state, it fixes a couple unittest failures for 64bit reals and gives plausible results.

}
else static if (floatTraits!(real).realFormat == RealFormat.ieeeDouble) {
enum real MAXLOG = 0x1.62e42fefa39efp+9L; // log(real.max)
enum real MINLOG = -0x1.74385446d71c3p+9L; // log(real.min_normal*real.epsilon) = log(smallest denormal)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please replace with this lines. The MINLOG was changed, the MAXLOG remains the same.

    enum real MAXLOG =  0x1.62e42fefa39efp+9; /// log(2^+1024) at Wolfram Alpha, 21.07.2015
    enum real MINLOG = -0x1.74910d52d3052p+9; /// log(2^-1075) at Wolfram Alpha, 21.07.2015

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@9il Are you sure your MINLOG is correct? I believe the smallest denormal is 2^-1074, according to Wikipedia. In that case, I think my value (the one calculated by DMD) is correct and is the same as calculated by Wolfram Alpha and then converted to hex (do you know how to have Wolfram Alpha do that conversion to 64-bit float hex?).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Smallest denormal is 2^-1074, however CEPHES uses 2^-1075 (probably because rounding rule?). Lets it be 2^-1074 ;)

CEPHES github fork fo reference (origin has the same constant).

Wolfram:

  1. Example
  2. D code example for transformation writefln("%a", 0x2e9.221aa5a60a3p+0);

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Current constant is OK

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Never believe what you read on Wikipedia. ;)

Just, kidding, this is fine.

@9il
Copy link
Member

9il commented Jul 22, 2015

LGTM

@DmitryOlshansky
Copy link
Member

Looks fine - anything else to review @ibuclaw?

@ibuclaw
Copy link
Member

ibuclaw commented Jul 30, 2015

Auto-merge toggled on

ibuclaw added a commit that referenced this pull request Jul 30, 2015
std.mathspecial: for 64-bit reals, provide MAXGAMMA, MAXLOG, and MINLOG
@ibuclaw ibuclaw merged commit 89f53cb into dlang:master Jul 30, 2015
@JohanEngelen JohanEngelen deleted the gamma64bit branch July 30, 2015 06:59
@JohanEngelen JohanEngelen restored the gamma64bit branch August 2, 2015 21:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants