digitalmars.D - template bug?
- Denton Cockburn (18/18) Feb 28 2008 In DMD 2.011
-
Koroskin Denis
(34/52)
Feb 29 2008
On Fri, 29 Feb 2008 08:35:02 +0300, Denton Cockburn
... - Denton Cockburn (10/75) Feb 29 2008 D template parameters can be:
- Koroskin Denis (5/15) Feb 29 2008 I din't say a thing about (in)correctness of this code. In fact, I was
- Janice Caron (5/6) Feb 29 2008 Forgive me, but factorial is not defined for real numbers. The domain
- Marius Muja (5/30) Feb 29 2008 Because of the nature of floating point numbers, you shouldn't use
- Denton Cockburn (19/25) Feb 29 2008 That wouldn't explain why it works in 1.027 and not 2.011.
- Bill Baxter (6/11) Feb 29 2008 It's true generally, but integers (up to a point) have an exact
In DMD 2.011 import std.stdio; template factorial(real n) { static if (n == 1) const factorial = 1; else const factorial = n * factorial!(n - 1); } void main() { writefln(factorial!(5)); } produces: -3.10504e+231 when the template is changed to accept an int instead of a real, it produces the right output: 120 What's the cause of this? Note: in 1.027, the version accepting a real still produces the correct output of 120.
Feb 28 2008
On Fri, 29 Feb 2008 08:35:02 +0300, Denton Cockburn <diboss hotmail.com>= = wrote:In DMD 2.011 import std.stdio; template factorial(real n) { static if (n =3D=3D 1) const factorial =3D 1; else const factorial =3D n * factorial!(n - 1); } void main() { writefln(factorial!(5)); } produces: -3.10504e+231 when the template is changed to accept an int instead of a real, it produces the right output: 120 What's the cause of this? Note: in 1.027, the version accepting a real still produces the correc=toutput of 120.Seems like a bug to mee, too. This produces incorrect output as well: template factorial(real n) { const real factorial =3D 1; } void main() { writefln(factorial!(5)); } In C++, one cannot use real as a template parameter. The following code = = won't compile, although the code looks harmless :) template<float t> class SomeClass { static const float someValue =3D t; } void main() { float value =3D SomeClass<5.0f>::someValue; // 5.0f expected } However this one can easily instanciate as much templates, at it wishes = = because of rounding error on floating point arithmetics: template<float t> float factorial() { if (t =3D=3D 1) { ///< this condition might never be satisfied return 1; } else { return t*factorial(t-1); } } int main() { float t1 =3D factorial<5.0f>(); float t2 =3D factorial<5.1f>(); }
Feb 29 2008
On Fri, 29 Feb 2008 12:58:26 +0300, Koroskin Denis wrote:On Fri, 29 Feb 2008 08:35:02 +0300, Denton Cockburn <diboss hotmail.com> wrote:D template parameters can be: * types * integral values * floating point values * string literals * templates * or any symbol http://www.digitalmars.com/d/2.0/templates-revisited.html I guess this is a bug.In DMD 2.011 import std.stdio; template factorial(real n) { static if (n == 1) const factorial = 1; else const factorial = n * factorial!(n - 1); } void main() { writefln(factorial!(5)); } produces: -3.10504e+231 when the template is changed to accept an int instead of a real, it produces the right output: 120 What's the cause of this? Note: in 1.027, the version accepting a real still produces the correct output of 120.Seems like a bug to mee, too. This produces incorrect output as well: template factorial(real n) { const real factorial = 1; } void main() { writefln(factorial!(5)); } In C++, one cannot use real as a template parameter. The following code won't compile, although the code looks harmless :) template<float t> class SomeClass { static const float someValue = t; } void main() { float value = SomeClass<5.0f>::someValue; // 5.0f expected } However this one can easily instanciate as much templates, at it wishes because of rounding error on floating point arithmetics: template<float t> float factorial() { if (t == 1) { ///< this condition might never be satisfied return 1; } else { return t*factorial(t-1); } } int main() { float t1 = factorial<5.0f>(); float t2 = factorial<5.1f>(); }
Feb 29 2008
On Fri, 29 Feb 2008 18:15:18 +0300, Denton Cockburn <diboss hotmail.com> wrote:I din't say a thing about (in)correctness of this code. In fact, I was talking about C++! However, you should use this feature with care :)[snip]D template parameters can be: * types * integral values * floating point values * string literals * templates * or any symbol http://www.digitalmars.com/d/2.0/templates-revisited.html I guess this is a bug.
Feb 29 2008
On 29/02/2008, Denton Cockburn <diboss hotmail.com> wrote:template factorial(real n)Forgive me, but factorial is not defined for real numbers. The domain of factorial is the positive integers only. Of course, if you want to write a compile-time gamma function! ... :-) (I know, I know - it's a bug report, not a math lesson. I'll shut up now).
Feb 29 2008
Because of the nature of floating point numbers, you shouldn't use equality(==) to compare floating point numbers. Instead of n==1 you should write something like abs(n-1)<eps (where eps is a small number) Denton Cockburn wrote:In DMD 2.011 import std.stdio; template factorial(real n) { static if (n == 1) const factorial = 1; else const factorial = n * factorial!(n - 1); } void main() { writefln(factorial!(5)); } produces: -3.10504e+231 when the template is changed to accept an int instead of a real, it produces the right output: 120 What's the cause of this? Note: in 1.027, the version accepting a real still produces the correct output of 120.
Feb 29 2008
On Fri, 29 Feb 2008 10:46:23 -0800, Marius Muja wrote:Because of the nature of floating point numbers, you shouldn't use equality(==) to compare floating point numbers. Instead of n==1 you should write something like abs(n-1)<eps (where eps is a small number)That wouldn't explain why it works in 1.027 and not 2.011. The next thing, it doesn't explain why: template factorial(real n) { static if (n == 1.0L) const real factorial = 1.0L; else const real factorial = 5.0L; } void main() { writefln(factorial!(5.0L)); } which is using full real comparisons, and in either case should execute the else even if it doesn't equate, produces an output of -1.49167e-154. 1.027 produces the correct output of 5 again. P.S. Isn't that how == is defined for floating point numbers already? If not, shouldn't it be that way?
Feb 29 2008
Marius Muja wrote:Because of the nature of floating point numbers, you shouldn't use equality(==) to compare floating point numbers. Instead of n==1 you should write something like abs(n-1)<eps (where eps is a small number)It's true generally, but integers (up to a point) have an exact representation in floating point. Multiplying exact real integers by exact real integers will yield exact real integers as long as you don't overlflow the mantissa. -bb
Feb 29 2008