## digitalmars.D - template bug?

- Denton Cockburn <diboss hotmail.com> Feb 28 2008
- "Koroskin Denis" <2korden+dmd gmail.com> Feb 29 2008
- Denton Cockburn <diboss hotmail.com> Feb 29 2008
- "Koroskin Denis" <2korden+dmd gmail.com> Feb 29 2008
- "Janice Caron" <caron800 googlemail.com> Feb 29 2008
- Marius Muja <mariusm cs.ubc.ca> Feb 29 2008
- Denton Cockburn <diboss hotmail.com> Feb 29 2008
- Bill Baxter <dnewsgroup billbaxter.com> Feb 29 2008

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=

output 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: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>(); }

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 Fri, 29 Feb 2008 18:15:18 +0300, Denton Cockburn <diboss hotmail.com> wrote:[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.

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 :)

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