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(t1); } } 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/templatesrevisited.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(t1); } } 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/templatesrevisited.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 compiletime 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(n1)<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(n1)<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.49167e154. 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(n1)<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