www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - handling T.min the right way

reply "Andrei Alexandrescu (See Website For Email)" <SeeWebsiteForEmail erdani.org> writes:
A while ago, C++ did the mistake of defining 
std::numeric_limits<T>::min() with a different semantics for 
floating-point types than for integral types. That hurt generic numeric 
code a lot.

D has taken over the same mistake: T.min means the smallest value of the 
type, except for floating-point types, where it means the smallest 
positive value.

The right way is to have T.min always return the minimum value (duh) and 
define a separate property T.min_positive.

The question is, would a lot of code be hurt by such a change?


Andrei
Mar 19 2007
next sibling parent reply Pragma <ericanderton yahoo.removeme.com> writes:
Andrei Alexandrescu (See Website For Email) wrote:
 A while ago, C++ did the mistake of defining 
 std::numeric_limits<T>::min() with a different semantics for 
 floating-point types than for integral types. That hurt generic numeric 
 code a lot.
 
 D has taken over the same mistake: T.min means the smallest value of the 
 type, except for floating-point types, where it means the smallest 
 positive value.
 
 The right way is to have T.min always return the minimum value (duh) and 
 define a separate property T.min_positive.
 
 The question is, would a lot of code be hurt by such a change?
 
 
 Andrei

No issue here. In fact, I've never used "double.min" for example - I'm suprised to hear that it's positive. As much as I'd like to see D embrace camelCase for multi-word things, "foreach_reverse" has pretty much decided that one for us - T.min_positive seems like a good addition to the language as any. I gather this means that we'll also see a t.max_negative to go along with it? -- - EricAnderton at yahoo
Mar 19 2007
parent Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Pragma wrote:
 I gather this means that we'll also see a t.max_negative to go along with it?

I was going to suggest this, but then considered that min_positive could also be defined for integer types, while max_negative has no good definition for the unsigned variants.
Mar 19 2007
prev sibling next sibling parent Pragma <ericanderton yahoo.removeme.com> writes:
Andrei Alexandrescu (See Website For Email) wrote:
 A while ago, C++ did the mistake of defining 
 std::numeric_limits<T>::min() with a different semantics for 
 floating-point types than for integral types. That hurt generic numeric 
 code a lot.
 
 D has taken over the same mistake: T.min means the smallest value of the 
 type, except for floating-point types, where it means the smallest 
 positive value.
 
 The right way is to have T.min always return the minimum value (duh) and 
 define a separate property T.min_positive.
 
 The question is, would a lot of code be hurt by such a change?
 
 
 Andrei

PS, the guy you really need to ask is Don. He seems to be the (if not one of a handful of) math/FP guru around here. ;) -- - EricAnderton at yahoo
Mar 19 2007
prev sibling next sibling parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Andrei Alexandrescu (See Website For Email) wrote:
 A while ago, C++ did the mistake of defining 
 std::numeric_limits<T>::min() with a different semantics for 
 floating-point types than for integral types. That hurt generic numeric 
 code a lot.
 
 D has taken over the same mistake: T.min means the smallest value of the 
 type, except for floating-point types, where it means the smallest 
 positive value.

??? This statement really surprised me. But it does seems to be what DMD does. The relevant line of the spec (http://www.digitalmars.com/d/property.html [section on floats]): --- .min smallest representable normalized value that's not 0 --- Does "normalized" imply non-negative? I guess I could have expected this behavior if I'd paid better attention to this line though, since it's '0' that is explicitly excluded instead of negative infinity. (Also, it uses "smallest" instead of something like "lowest")
 The right way is to have T.min always return the minimum value (duh) and 
 define a separate property T.min_positive.

Obviously. Since the minimum positive number would be a denormalized value (right?), perhaps a T.min_normalized as well? (or if "normalized" doesn't imply non-negative, min_normalized_positive, though that's getting a bit long...)
 The question is, would a lot of code be hurt by such a change?

I didn't even know this wasn't already how it worked...
Mar 19 2007
parent reply 0ffh <spam frankhirsch.net> writes:
Frits van Bommel wrote:
 Does "normalized" imply non-negative?

No, I think it just means the mantissa msb is 1. Happy hacking, 0ffh
Mar 20 2007
parent Daniel Keep <daniel.keep.lists gmail.com> writes:
0ffh wrote:
 Frits van Bommel wrote:
 Does "normalized" imply non-negative?

No, I think it just means the mantissa msb is 1. Happy hacking, 0ffh

If I remember correctly, there are two kinds of non-infinite, non-nan, non-zero IEEE floating point numbers: normalised and denormalised numbers. Normal numbers are ones where, like 0ffh said, the number starts with an implicit '1'. Basically, with IEEE, if you wanted to store the binary number 0b1.0101001, you would *actually* store the '0101001' part: every binary number must has a leading '1' at *some* point, otherwise it'd be zero :) Now, the other kind of number, a denormal, comes about when your number is so close to zero that IEEE runs out of full-precision numbers. So what happens here is that IEEE basically starts representing the number using less and less bits, trying to prevent underflow (or overflow if you're using negative numbers) to zero.[1] This is useful where you're doing a calculation with numbers very close to zero. The result might be a normalised number, but the intermediates are denormalised. With support for denormal numbers, you get (approximately) the correct, non-zero result. Without them, you get zero. IEEE is pretty interesting, in how much thought and care went into how we represent numbers. You can read more about Denormal numbers on Wikipedia[2]. There's a link to Kahan's site, but the server seems to be down atm. -- Daniel [1] Incidentally, some people working on the IEEE spec felt that the whole subnormal thing was a waste of time, that they couldn't be implemented efficiently and that these numbers should just automatically round to zero. Thankfully, Kahan and Intel convinced them otherwise :) [2] http://en.wikipedia.org/wiki/Denormal -- int getRandomNumber() { return 4; // chosen by fair dice roll. // guaranteed to be random. } http://xkcd.com/ v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
Mar 20 2007
prev sibling next sibling parent reply "Lionello Lunesu" <lionello lunesu.remove.com> writes:
"Andrei Alexandrescu (See Website For Email)" 
<SeeWebsiteForEmail erdani.org> wrote in message 
news:45FEE0BC.4000407 erdani.org...
A while ago, C++ did the mistake of defining std::numeric_limits<T>::min() 
with a different semantics for floating-point types than for integral 
types. That hurt generic numeric code a lot.

 D has taken over the same mistake: T.min means the smallest value of the 
 type, except for floating-point types, where it means the smallest 
 positive value.

 The right way is to have T.min always return the minimum value (duh) and 
 define a separate property T.min_positive.

Isn't this value sometimes also called "epsilon"? I think double.epsilon sounds quite nice :) L.
Mar 19 2007
next sibling parent =?ISO-8859-1?Q?Lu=EDs_Marques?= <luismarques+spam gmail.com> writes:
Lionello Lunesu wrote:
 Isn't this value sometimes also called "epsilon"? I think double.epsilon 
 sounds quite nice :)

quite charming :) Luis
Mar 19 2007
prev sibling parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Lionello Lunesu wrote:
 "Andrei Alexandrescu (See Website For Email)" 
 <SeeWebsiteForEmail erdani.org> wrote in message 
 news:45FEE0BC.4000407 erdani.org...
 The right way is to have T.min always return the minimum value (duh) and 
 define a separate property T.min_positive.

Isn't this value sometimes also called "epsilon"? I think double.epsilon sounds quite nice :)

Epsilon is already used for a related concept: ".epsilon -- smallest increment to the value 1" (http://www.digitalmars.com/d/property.html)
Mar 19 2007
parent reply Lionello Lunesu <lio lunesu.remove.com> writes:
Frits van Bommel wrote:
 Lionello Lunesu wrote:
 "Andrei Alexandrescu (See Website For Email)" 
 <SeeWebsiteForEmail erdani.org> wrote in message 
 news:45FEE0BC.4000407 erdani.org...
 The right way is to have T.min always return the minimum value (duh) 
 and define a separate property T.min_positive.

Isn't this value sometimes also called "epsilon"? I think double.epsilon sounds quite nice :)

Epsilon is already used for a related concept: ".epsilon -- smallest increment to the value 1" (http://www.digitalmars.com/d/property.html)

Huh, I thought it sounded familiar. So epsilon is such that 1.0+epsilon!=1.0, and the 'min' we're talking about is such that 0.0+min_positive!=0.0 ? I didn't know these were both useful values.... I wonder how they're actually being used. L.
Mar 19 2007
parent reply Lionello Lunesu <lio lunesu.remove.com> writes:
Lionello Lunesu wrote:
 Frits van Bommel wrote:
 Lionello Lunesu wrote:
 "Andrei Alexandrescu (See Website For Email)" 
 <SeeWebsiteForEmail erdani.org> wrote in message 
 news:45FEE0BC.4000407 erdani.org...
 The right way is to have T.min always return the minimum value (duh) 
 and define a separate property T.min_positive.

Isn't this value sometimes also called "epsilon"? I think double.epsilon sounds quite nice :)

Epsilon is already used for a related concept: ".epsilon -- smallest increment to the value 1" (http://www.digitalmars.com/d/property.html)

Huh, I thought it sounded familiar. So epsilon is such that 1.0+epsilon!=1.0, and the 'min' we're talking about is such that 0.0+min_positive!=0.0 ? I didn't know these were both useful values.... I wonder how they're actually being used. L.

Nevermind, I think I get it. epsilon reflects the smallest exponent, whereas min_positive represents the reflects the resolution of the mantissa. Both have bad names though. What terminology do mathematicians use for these 'constants'? L.
Mar 19 2007
parent reply BCS <BCS pathlink.com> writes:
Lionello Lunesu wrote:
 Lionello Lunesu wrote:
 
 Frits van Bommel wrote:

 Lionello Lunesu wrote:

 "Andrei Alexandrescu (See Website For Email)" 
 <SeeWebsiteForEmail erdani.org> wrote in message 
 news:45FEE0BC.4000407 erdani.org...

 The right way is to have T.min always return the minimum value 
 (duh) and define a separate property T.min_positive.

Isn't this value sometimes also called "epsilon"? I think double.epsilon sounds quite nice :)

Epsilon is already used for a related concept: ".epsilon -- smallest increment to the value 1" (http://www.digitalmars.com/d/property.html)

Huh, I thought it sounded familiar. So epsilon is such that 1.0+epsilon!=1.0, and the 'min' we're talking about is such that 0.0+min_positive!=0.0 ? I didn't know these were both useful values.... I wonder how they're actually being used. L.

Nevermind, I think I get it. epsilon reflects the smallest exponent, whereas min_positive represents the reflects the resolution of the mantissa.

Actually I think that is backwards. Epsilon reflects the number of bits in the mantissa and min_positive reflects the smallest exponent.
 
 Both have bad names though. What terminology do mathematicians use for 
 these 'constants'?
 
 L.

Mar 20 2007
parent Lionello Lunesu <lio lunesu.remove.com> writes:
BCS wrote:
 Lionello Lunesu wrote:
 Lionello Lunesu wrote:

 Frits van Bommel wrote:

 Lionello Lunesu wrote:

 "Andrei Alexandrescu (See Website For Email)" 
 <SeeWebsiteForEmail erdani.org> wrote in message 
 news:45FEE0BC.4000407 erdani.org...

 The right way is to have T.min always return the minimum value 
 (duh) and define a separate property T.min_positive.

Isn't this value sometimes also called "epsilon"? I think double.epsilon sounds quite nice :)

Epsilon is already used for a related concept: ".epsilon -- smallest increment to the value 1" (http://www.digitalmars.com/d/property.html)

Huh, I thought it sounded familiar. So epsilon is such that 1.0+epsilon!=1.0, and the 'min' we're talking about is such that 0.0+min_positive!=0.0 ? I didn't know these were both useful values.... I wonder how they're actually being used. L.

Nevermind, I think I get it. epsilon reflects the smallest exponent, whereas min_positive represents the reflects the resolution of the mantissa.

Actually I think that is backwards. Epsilon reflects the number of bits in the mantissa and min_positive reflects the smallest exponent.

I think you're right :) Goes to show how bad their names really are :) L.
Mar 20 2007
prev sibling next sibling parent mike <vertex gmx.at> writes:
Am 19.03.2007, 20:13 Uhr, schrieb Andrei Alexandrescu (See Website For  =

Email) <SeeWebsiteForEmail erdani.org>:

 The right way is to have T.min always return the minimum value (duh) a=

 define a separate property T.min_positive.

Maybe min could take an enum as parameter: ' T.min(positive); ' T.min(negative); with a default value so that T.min is still valid. Looks a lot more like= D = and less like PHP :) -mike -- = Erstellt mit Operas revolution=E4rem E-Mail-Modul: http://www.opera.com/= mail/
Mar 19 2007
prev sibling parent reply Don Clugston <dac nospam.com.au> writes:
Andrei Alexandrescu (See Website For Email) wrote:
 A while ago, C++ did the mistake of defining 
 std::numeric_limits<T>::min() with a different semantics for 
 floating-point types than for integral types. That hurt generic numeric 
 code a lot.
 
 D has taken over the same mistake: T.min means the smallest value of the 
 type, except for floating-point types, where it means the smallest 
 positive value.
 
 The right way is to have T.min always return the minimum value (duh) and 
 define a separate property T.min_positive.
 
 The question is, would a lot of code be hurt by such a change?
 
 
 Andrei

It probably wouldn't break a huge amount of D code, but I don't think there would be many cases where T.min for a floating point type would be useful. More significant is the problems involved in converting from C or Fortran code to D. On a more profound level... I'm not aware of many cases where it's possible to treat integer and floating-points generically. People often try, but usually the code is incorrect for the floating point types, since the semantics are completely different. (For example, I don't know why x++ is legal for floating point types; I think it's just a newbie trap; you have no guarantee that x++ is different to x). What type of generic numeric code did you have in mind? What are the benefits which would come by such a change?
Mar 20 2007
next sibling parent reply "Andrei Alexandrescu (See Website For Email)" <SeeWebsiteForEmail erdani.org> writes:
Don Clugston wrote:
 Andrei Alexandrescu (See Website For Email) wrote:
 A while ago, C++ did the mistake of defining 
 std::numeric_limits<T>::min() with a different semantics for 
 floating-point types than for integral types. That hurt generic 
 numeric code a lot.

 D has taken over the same mistake: T.min means the smallest value of 
 the type, except for floating-point types, where it means the smallest 
 positive value.

 The right way is to have T.min always return the minimum value (duh) 
 and define a separate property T.min_positive.

 The question is, would a lot of code be hurt by such a change?


 Andrei

It probably wouldn't break a huge amount of D code, but I don't think there would be many cases where T.min for a floating point type would be useful. More significant is the problems involved in converting from C or Fortran code to D.

I'm not even discussing the utility of min_positive. All I'm saying is that if you say "min", you should return "min", particularly when others do exactly that.
 On a more profound level...
 I'm not aware of many cases where it's possible to treat integer and 
 floating-points generically. People often try, but usually the code is 
 incorrect for the floating point types, since the semantics are 
 completely different. (For example, I don't know why x++ is legal for 
 floating point types; I think it's just a newbie trap; you have no 
 guarantee that x++ is different to x).
 
 What type of generic numeric code did you have in mind? What are the 
 benefits which would come by such a change?

Trivially simple: the min and max functions. For min, the code picks the type with the smallest .min. For max, the code picks the type with the largest .max. Andrei
Mar 20 2007
next sibling parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
Andrei Alexandrescu (See Website For Email) wrote:
 Don Clugston wrote:
 Andrei Alexandrescu (See Website For Email) wrote:
 A while ago, C++ did the mistake of defining 
 std::numeric_limits<T>::min() with a different semantics for 
 floating-point types than for integral types. That hurt generic 
 numeric code a lot.

 D has taken over the same mistake: T.min means the smallest value of 
 the type, except for floating-point types, where it means the 
 smallest positive value.

 The right way is to have T.min always return the minimum value (duh) 
 and define a separate property T.min_positive.

 The question is, would a lot of code be hurt by such a change?


 Andrei

It probably wouldn't break a huge amount of D code, but I don't think there would be many cases where T.min for a floating point type would be useful. More significant is the problems involved in converting from C or Fortran code to D.

I'm not even discussing the utility of min_positive. All I'm saying is that if you say "min", you should return "min", particularly when others do exactly that.
 On a more profound level...
 I'm not aware of many cases where it's possible to treat integer and 
 floating-points generically. People often try, but usually the code is 
 incorrect for the floating point types, since the semantics are 
 completely different. (For example, I don't know why x++ is legal for 
 floating point types; I think it's just a newbie trap; you have no 
 guarantee that x++ is different to x).

 What type of generic numeric code did you have in mind? What are the 
 benefits which would come by such a change?

Trivially simple: the min and max functions. For min, the code picks the type with the smallest .min. For max, the code picks the type with the largest .max. Andrei

Also when you're say trying to find the maximum of a set of numbers it can be handy to initialize the 'current_max' to the smallest number possible. float max_val = float.min; // want the new meaning here int max_idx = -1; foreach(i,x; bunch_o_floats) { if (x<max_val) { max_val=x; max_idx=i; } } --bb
Mar 20 2007
parent reply Daniel Keep <daniel.keep.lists gmail.com> writes:
Bill Baxter wrote:
 Andrei Alexandrescu (See Website For Email) wrote:
 Don Clugston wrote:
 Andrei Alexandrescu (See Website For Email) wrote:
 A while ago, C++ did the mistake of defining
 std::numeric_limits<T>::min() with a different semantics for
 floating-point types than for integral types. That hurt generic
 numeric code a lot.

 D has taken over the same mistake: T.min means the smallest value of
 the type, except for floating-point types, where it means the
 smallest positive value.

 The right way is to have T.min always return the minimum value (duh)
 and define a separate property T.min_positive.

 The question is, would a lot of code be hurt by such a change?


 Andrei

It probably wouldn't break a huge amount of D code, but I don't think there would be many cases where T.min for a floating point type would be useful. More significant is the problems involved in converting from C or Fortran code to D.

I'm not even discussing the utility of min_positive. All I'm saying is that if you say "min", you should return "min", particularly when others do exactly that.
 On a more profound level...
 I'm not aware of many cases where it's possible to treat integer and
 floating-points generically. People often try, but usually the code
 is incorrect for the floating point types, since the semantics are
 completely different. (For example, I don't know why x++ is legal for
 floating point types; I think it's just a newbie trap; you have no
 guarantee that x++ is different to x).

 What type of generic numeric code did you have in mind? What are the
 benefits which would come by such a change?

Trivially simple: the min and max functions. For min, the code picks the type with the smallest .min. For max, the code picks the type with the largest .max. Andrei

Also when you're say trying to find the maximum of a set of numbers it can be handy to initialize the 'current_max' to the smallest number possible. float max_val = float.min; // want the new meaning here int max_idx = -1; foreach(i,x; bunch_o_floats) { if (x<max_val) { max_val=x; max_idx=i; } } --bb

I usually cheat and use nan, then change the comparison so that it will succeed if 'x' is any real number :P That way, if I give it an empty list, I get nan back instead of float.min, which could be misleading. -- Daniel -- int getRandomNumber() { return 4; // chosen by fair dice roll. // guaranteed to be random. } http://xkcd.com/ v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP http://hackerkey.com/
Mar 20 2007
parent reply Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
Daniel Keep wrote:
 
 Bill Baxter wrote:
 Also when you're say trying to find the maximum of a set of numbers it
 can be handy to initialize the 'current_max' to the smallest number
 possible.

 float max_val = float.min; // want the new meaning here
 int max_idx = -1;
 foreach(i,x; bunch_o_floats) {
    if (x<max_val) {
        max_val=x;
        max_idx=i;
    }
 }

 --bb

I usually cheat and use nan, then change the comparison so that it will succeed if 'x' is any real number :P That way, if I give it an empty list, I get nan back instead of float.min, which could be misleading.

I'd use -float.infinity as the initial value. Empty quantifications should return the identity value[1]. At least, that's what I was taught in "Logic and Set Theory" (not sure if I translated that course name right) as well as several other courses I can't remember the names of right now. You'd still need to make sure your comparison does the right thing for NaNs, if that's important. (I'm pretty sure they didn't cover NaNs in any course :) ) [1]: The identity value of an operator <op> is the value e such that (for all x) e <op> x == x <op> e == x holds. (i.e. for '+' it's 0, for '*' it's 1, and for 'max' it's -infinity)
Mar 20 2007
parent Bill Baxter <dnewsgroup billbaxter.com> writes:
Frits van Bommel wrote:
 Daniel Keep wrote:
 Bill Baxter wrote:
 Also when you're say trying to find the maximum of a set of numbers it
 can be handy to initialize the 'current_max' to the smallest number
 possible.

 float max_val = float.min; // want the new meaning here
 int max_idx = -1;
 foreach(i,x; bunch_o_floats) {
    if (x<max_val) {
        max_val=x;
        max_idx=i;
    }
 }

 --bb

I usually cheat and use nan, then change the comparison so that it will succeed if 'x' is any real number :P That way, if I give it an empty list, I get nan back instead of float.min, which could be misleading.

I'd use -float.infinity as the initial value.

Yeh, I guess that's better. I've just gotten used to working with languages where there's no portable way to get at nan and infinity constants. But I guess D doesn't have that problem. Yay D! --bb
Mar 20 2007
prev sibling parent reply Don Clugston <dac nospam.com.au> writes:
Andrei Alexandrescu (See Website For Email) wrote:
 Don Clugston wrote:
 Andrei Alexandrescu (See Website For Email) wrote:
 A while ago, C++ did the mistake of defining 
 std::numeric_limits<T>::min() with a different semantics for 
 floating-point types than for integral types. That hurt generic 
 numeric code a lot.

 D has taken over the same mistake: T.min means the smallest value of 
 the type, except for floating-point types, where it means the 
 smallest positive value.

 The right way is to have T.min always return the minimum value (duh) 
 and define a separate property T.min_positive.

 The question is, would a lot of code be hurt by such a change?


 Andrei

It probably wouldn't break a huge amount of D code, but I don't think there would be many cases where T.min for a floating point type would be useful. More significant is the problems involved in converting from C or Fortran code to D.

I'm not even discussing the utility of min_positive. All I'm saying is that if you say "min", you should return "min", particularly when others do exactly that.
 On a more profound level...
 I'm not aware of many cases where it's possible to treat integer and 
 floating-points generically. People often try, but usually the code is 
 incorrect for the floating point types, since the semantics are 
 completely different. (For example, I don't know why x++ is legal for 
 floating point types; I think it's just a newbie trap; you have no 
 guarantee that x++ is different to x).

 What type of generic numeric code did you have in mind? What are the 
 benefits which would come by such a change?

Trivially simple: the min and max functions. For min, the code picks the type with the smallest .min. For max, the code picks the type with the largest .max.

Obviously, but are there many other functions like that? Also, you really should treat floating point as a special case, anyway, because of the possibility of a NaN. I'd be surprised if the total benefit amounted to more than a few dozen lines of library code. There's also the issue of complex types. Currently, this passes: static assert(creal.max == real.max+1i*real.max); -- which is a little strange.
Mar 21 2007
parent reply "Andrei Alexandrescu (See Website For Email)" <SeeWebsiteForEmail erdani.org> writes:
Don Clugston wrote:
 Andrei Alexandrescu (See Website For Email) wrote:
 Don Clugston wrote:
 Andrei Alexandrescu (See Website For Email) wrote:
 A while ago, C++ did the mistake of defining 
 std::numeric_limits<T>::min() with a different semantics for 
 floating-point types than for integral types. That hurt generic 
 numeric code a lot.

 D has taken over the same mistake: T.min means the smallest value of 
 the type, except for floating-point types, where it means the 
 smallest positive value.

 The right way is to have T.min always return the minimum value (duh) 
 and define a separate property T.min_positive.

 The question is, would a lot of code be hurt by such a change?


 Andrei

It probably wouldn't break a huge amount of D code, but I don't think there would be many cases where T.min for a floating point type would be useful. More significant is the problems involved in converting from C or Fortran code to D.

I'm not even discussing the utility of min_positive. All I'm saying is that if you say "min", you should return "min", particularly when others do exactly that.
 On a more profound level...
 I'm not aware of many cases where it's possible to treat integer and 
 floating-points generically. People often try, but usually the code 
 is incorrect for the floating point types, since the semantics are 
 completely different. (For example, I don't know why x++ is legal for 
 floating point types; I think it's just a newbie trap; you have no 
 guarantee that x++ is different to x).

 What type of generic numeric code did you have in mind? What are the 
 benefits which would come by such a change?

Trivially simple: the min and max functions. For min, the code picks the type with the smallest .min. For max, the code picks the type with the largest .max.

Obviously, but are there many other functions like that? Also, you really should treat floating point as a special case, anyway, because of the possibility of a NaN.

There was another example (computing the minimum of a nonempty collection). But to me the issue is a tad different: (1) the name is clearly misused; (2) it's easy to fix; (3) not fixing it sends the wrong message ("we carried over whatever was in C++ on numerics"). D takes pride in taking care of minutiae. It's odd to have the smorgasbord of floating-point operators that D has (how often did _you_ use !<>=?) yet at the same time say, "oh, min? that's not really min. I was kidding."
 I'd be surprised if the total benefit amounted to more than a few dozen 
 lines of library code.
 
 There's also the issue of complex types. Currently, this passes:
 
 static assert(creal.max == real.max+1i*real.max);

Ouch. Andrei
Mar 21 2007
next sibling parent Don Clugston <dac nospam.com.au> writes:
Andrei Alexandrescu (See Website For Email) wrote:
 Don Clugston wrote:
 Andrei Alexandrescu (See Website For Email) wrote:
 Don Clugston wrote:
 Andrei Alexandrescu (See Website For Email) wrote:
 A while ago, C++ did the mistake of defining 
 std::numeric_limits<T>::min() with a different semantics for 
 floating-point types than for integral types. That hurt generic 
 numeric code a lot.

 D has taken over the same mistake: T.min means the smallest value 
 of the type, except for floating-point types, where it means the 
 smallest positive value.

 The right way is to have T.min always return the minimum value 
 (duh) and define a separate property T.min_positive.

 The question is, would a lot of code be hurt by such a change?


 Andrei

It probably wouldn't break a huge amount of D code, but I don't think there would be many cases where T.min for a floating point type would be useful. More significant is the problems involved in converting from C or Fortran code to D.

I'm not even discussing the utility of min_positive. All I'm saying is that if you say "min", you should return "min", particularly when others do exactly that.
 On a more profound level...
 I'm not aware of many cases where it's possible to treat integer and 
 floating-points generically. People often try, but usually the code 
 is incorrect for the floating point types, since the semantics are 
 completely different. (For example, I don't know why x++ is legal 
 for floating point types; I think it's just a newbie trap; you have 
 no guarantee that x++ is different to x).

 What type of generic numeric code did you have in mind? What are the 
 benefits which would come by such a change?

Trivially simple: the min and max functions. For min, the code picks the type with the smallest .min. For max, the code picks the type with the largest .max.

Obviously, but are there many other functions like that? Also, you really should treat floating point as a special case, anyway, because of the possibility of a NaN.

There was another example (computing the minimum of a nonempty collection). But to me the issue is a tad different: (1) the name is clearly misused; (2) it's easy to fix; (3) not fixing it sends the wrong message ("we carried over whatever was in C++ on numerics"). D takes pride in taking care of minutiae. It's odd to have the smorgasbord of floating-point operators that D has (how often did _you_ use !<>=?) yet at the same time say, "oh, min? that's not really min. I was kidding.

Point taken. I'd support this if at the same time, the bizarre out-by-1 error in min_exp and max_exp was fixed. My code contains quite a few instances of (real.min_exp/2) because I actually wanted the genuine minimum exponent. Then we could say that all normalised numbers x satisfy pow(2, real.min_exp) <= x < pow(2, real.max_exp+1). Possibly even rename the current real.min to be real.min_normal, since it isn't even the smallest representable value > 0.
Mar 21 2007
prev sibling next sibling parent Lars Ivar Igesund <larsivar igesund.net> writes:
Andrei Alexandrescu (See Website For Email) wrote:

 Don Clugston wrote:
 Andrei Alexandrescu (See Website For Email) wrote:
 Don Clugston wrote:
 Andrei Alexandrescu (See Website For Email) wrote:
 A while ago, C++ did the mistake of defining
 std::numeric_limits<T>::min() with a different semantics for
 floating-point types than for integral types. That hurt generic
 numeric code a lot.

 D has taken over the same mistake: T.min means the smallest value of
 the type, except for floating-point types, where it means the
 smallest positive value.

 The right way is to have T.min always return the minimum value (duh)
 and define a separate property T.min_positive.

 The question is, would a lot of code be hurt by such a change?


 Andrei

It probably wouldn't break a huge amount of D code, but I don't think there would be many cases where T.min for a floating point type would be useful. More significant is the problems involved in converting from C or Fortran code to D.

I'm not even discussing the utility of min_positive. All I'm saying is that if you say "min", you should return "min", particularly when others do exactly that.
 On a more profound level...
 I'm not aware of many cases where it's possible to treat integer and
 floating-points generically. People often try, but usually the code
 is incorrect for the floating point types, since the semantics are
 completely different. (For example, I don't know why x++ is legal for
 floating point types; I think it's just a newbie trap; you have no
 guarantee that x++ is different to x).

 What type of generic numeric code did you have in mind? What are the
 benefits which would come by such a change?

Trivially simple: the min and max functions. For min, the code picks the type with the smallest .min. For max, the code picks the type with the largest .max.

Obviously, but are there many other functions like that? Also, you really should treat floating point as a special case, anyway, because of the possibility of a NaN.

There was another example (computing the minimum of a nonempty collection). But to me the issue is a tad different: (1) the name is clearly misused; (2) it's easy to fix; (3) not fixing it sends the wrong message ("we carried over whatever was in C++ on numerics").

And what about carrying over that const mess from C++? If const as a keyword is to stay - just let it mean constant - nothing else.
 D takes 
 pride in taking care of minutiae. It's odd to have the smorgasbord of
 floating-point operators that D has (how often did _you_ use !<>=?) yet
 at the same time say, "oh, min? that's not really min. I was kidding."

!<>= is in use in Tango as it seems to what is actually happening when looking for NaN :) -- Lars Ivar Igesund blog at http://larsivi.net DSource, #d.tango & #D: larsivi Dancing the Tango
Mar 21 2007
prev sibling parent reply Don Clugston <dac nospam.com.au> writes:
Andrei Alexandrescu (See Website For Email) wrote:
 It's odd to have the smorgasbord of 
 floating-point operators that D has (how often did _you_ use !<>=?) yet 

With a quick grep through 2 directories I found three uses, with <>= being used 12 times. But I'm not normal. <g>.
Mar 21 2007
next sibling parent "Andrei Alexandrescu (See Website For Email)" <SeeWebsiteForEmail erdani.org> writes:
Don Clugston wrote:
 Andrei Alexandrescu (See Website For Email) wrote:
 It's odd to have the smorgasbord of floating-point operators that D 
 has (how often did _you_ use !<>=?) yet 

With a quick grep through 2 directories I found three uses, with <>= being used 12 times. But I'm not normal. <g>.

Ok, now search for !>=. :o) Andrei
Mar 21 2007
prev sibling parent Walter Bright <newshound digitalmars.com> writes:
Don Clugston wrote:
 Andrei Alexandrescu (See Website For Email) wrote:
 It's odd to have the smorgasbord of floating-point operators that D 
 has (how often did _you_ use !<>=?) yet 

With a quick grep through 2 directories I found three uses, with <>= being used 12 times. But I'm not normal. <g>.

That's why your opinion on fp issues carries a lot of weight here - you're a professional numerics programmer, and those are unusual.
Mar 21 2007
prev sibling parent reply 0ffh <spam frankhirsch.net> writes:
Don Clugston wrote:
 completely different. (For example, I don't know why x++ is legal for 
 floating point types; I think it's just a newbie trap; you have no 
 guarantee that x++ is different to x).

Nope, not at all. Standard C defines that after "x++" x is incremented by one, exactly - *even for fp types* ! Happy hackimg, 0ffh
Mar 20 2007
next sibling parent reply 0ffh <spam frankhirsch.net> writes:
0ffh wrote:
 Standard C defines that after "x++" x is incremented by one, exactly -

Sorry for self-reply! Of course if you have a *very* big number, that might mean it's the same.... sometimes I do faster typing than thinking... :)
Mar 20 2007
parent reply Don Clugston <dac nospam.com.au> writes:
0ffh wrote:
 0ffh wrote:
 Standard C defines that after "x++" x is incremented by one, exactly -

Sorry for self-reply! Of course if you have a *very* big number, that might mean it's the same.... sometimes I do faster typing than thinking... :)

Exactly -- that's the trap. Also it's not reversible. x++; x--; changes the value of x in many cases: Old x New x real.max real.infinity // overflow 1.2345678e-10 1.2e-10 // loss of precision 1e-50 0 // catastrophic cancellation
Mar 21 2007
parent 0ffh <spam frankhirsch.net> writes:
Don Clugston wrote:
 0ffh wrote:
 [...]
 Of course if you have a *very* big number, that might mean it's the 
 same.... sometimes I do faster typing than thinking... :)


Faster typing than thinking? Sure! :-)))) (Sorry, couldn't resist!) Greetz, Frank
Mar 21 2007
prev sibling parent reply Walter Bright <newshound digitalmars.com> writes:
0ffh wrote:
 Don Clugston wrote:
 completely different. (For example, I don't know why x++ is legal for 
 floating point types; I think it's just a newbie trap; you have no 
 guarantee that x++ is different to x).

Nope, not at all. Standard C defines that after "x++" x is incremented by one, exactly - *even for fp types* !

For floating point types, if x happens to be +-infinity then x+1==x.
Mar 20 2007
next sibling parent reply James Dennett <jdennett acm.org> writes:
Walter Bright wrote:
 0ffh wrote:
 Don Clugston wrote:
 completely different. (For example, I don't know why x++ is legal for
 floating point types; I think it's just a newbie trap; you have no
 guarantee that x++ is different to x).

Nope, not at all. Standard C defines that after "x++" x is incremented by one, exactly - *even for fp types* !

For floating point types, if x happens to be +-infinity then x+1==x.

Or, most likely, even if x happens to be 1E100. I've not had the pleasure of working on hardware which supported floating point accurate enough to distinguish 1E100 from 1+1E100. -- James
Mar 20 2007
parent reply Bill Baxter <dnewsgroup billbaxter.com> writes:
James Dennett wrote:
 Walter Bright wrote:
 0ffh wrote:
 Don Clugston wrote:
 completely different. (For example, I don't know why x++ is legal for
 floating point types; I think it's just a newbie trap; you have no
 guarantee that x++ is different to x).

Standard C defines that after "x++" x is incremented by one, exactly - *even for fp types* !


Or, most likely, even if x happens to be 1E100. I've not had the pleasure of working on hardware which supported floating point accurate enough to distinguish 1E100 from 1+1E100. -- James

The cutoff is basically 2^{mantissa bits+1}. With floats: 2^23 + 1 == 2^23 With double: 2^53 + 1 == 2^53 So it happens for values much less than 1e100. More like 1e7 and 1e16. --bb
Mar 20 2007
parent Bill Baxter <dnewsgroup billbaxter.com> writes:
Bill Baxter wrote:
 James Dennett wrote:
 Walter Bright wrote:
 0ffh wrote:
 Don Clugston wrote:
 completely different. (For example, I don't know why x++ is legal for
 floating point types; I think it's just a newbie trap; you have no
 guarantee that x++ is different to x).

Standard C defines that after "x++" x is incremented by one, exactly - *even for fp types* !


Or, most likely, even if x happens to be 1E100. I've not had the pleasure of working on hardware which supported floating point accurate enough to distinguish 1E100 from 1+1E100. -- James

The cutoff is basically 2^{mantissa bits+1}. With floats: 2^23 + 1 == 2^23

doh! typo -- float has 23 mantissa bits so that should be 24.
 With double:  2^53 + 1 == 2^53
 
 So it happens for values much less than 1e100.  More like 1e7 and 1e16.

--bb
Mar 20 2007
prev sibling parent "David B. Held" <dheld codelogicconsulting.com> writes:
Walter Bright wrote:
 0ffh wrote:
 Don Clugston wrote:
 completely different. (For example, I don't know why x++ is legal for 
 floating point types; I think it's just a newbie trap; you have no 
 guarantee that x++ is different to x).

Nope, not at all. Standard C defines that after "x++" x is incremented by one, exactly - *even for fp types* !

For floating point types, if x happens to be +-infinity then x+1==x.

Wow, that's almost correct transfinite arithmetic. Technically speaking, 1 + oo == oo, but oo + 1 != oo. IEEE should really fix that. ;> Dave
Mar 21 2007