Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #103588 > unrolled thread

Re: The required minimum omega for double

Started byBen Bacarisse <ben.usenet@bsb.me.uk>
First post2017-02-10 01:15 +0000
Last post2017-02-13 04:07 -0600
Articles 11 — 5 participants

Back to article view | Back to comp.lang.c

This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by below is the oldest one visible, not the original post.


Contents

  Re: The required minimum omega for double Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-02-10 01:15 +0000
    Re: The required minimum omega for double Robert Wessel <robertwessel2@yahoo.com> - 2017-02-09 23:58 -0600
      Re: The required minimum omega for double scott@slp53.sl.home (Scott Lurndal) - 2017-02-10 14:57 +0000
        Re: The required minimum omega for double Robert Wessel <robertwessel2@yahoo.com> - 2017-02-12 01:52 -0600
          Re: The required minimum omega for double scott@slp53.sl.home (Scott Lurndal) - 2017-02-14 13:39 +0000
            Re: The required minimum omega for double Robert Wessel <robertwessel2@yahoo.com> - 2017-02-14 08:02 -0600
              Re: The required minimum omega for double scott@slp53.sl.home (Scott Lurndal) - 2017-02-14 17:30 +0000
                Re: The required minimum omega for double Robert Wessel <robertwessel2@yahoo.com> - 2017-02-14 17:39 -0600
      Re: The required minimum omega for double Tim Rentsch <txr@alumni.caltech.edu> - 2017-02-12 10:16 -0800
    Re: The required minimum omega for double Juha Nieminen <nospam@thanks.invalid> - 2017-02-13 07:33 +0000
      Re: The required minimum omega for double Robert Wessel <robertwessel2@yahoo.com> - 2017-02-13 04:07 -0600

#103588 — Re: The required minimum omega for double

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2017-02-10 01:15 +0000
SubjectRe: The required minimum omega for double
Message-ID<87wpcy4zi1.fsf@bsb.me.uk>
ram@zedat.fu-berlin.de (Stefan Ram) writes:

> Newsgroups: comp.lang.c,comp.lang.c++
>
> #include <float.h>
>
>   Some implementations have this property:
>
>   A double has at least 14 significant digits (about 14-16) and 
>
> 9007199254740991.

I.e. 2^53 - 1  or, in most C implementations these days

  (1llu << DBL_MANT_DIG) - 1

This works when FLT_RADIX is 2, but it need not be.

>   is the largest double value that can be added to 1.0
>   giving the "next" double value
>
> 9007199254740992.
>
>   (when one adds 1.0 again, the value will not change
>   anymore).
>
>   I don't know whether there is a common name for such a
>   value. I will call it (just for this post) "omega".
>   (In the above example, the omega is 9007199254740991.)
>
>   Now, the standard does not require 14 significant
>   digits, but 10 (DBL_DIG).
>
>   I wonder whether one can somehow find the smallest
>   omega for the type double that is required by the
>   standard.

I don't think you can get more than an approximation to it and probably
quite a crude one at that.  The standard does not give minimum values
for DBL_MANT_DIG as you have no doubt found out already.

<snip>
-- 
Ben.

[toc] | [next] | [standalone]


#103593

FromRobert Wessel <robertwessel2@yahoo.com>
Date2017-02-09 23:58 -0600
Message-ID<agkq9c1bo5ltlbupebeo95o3b7ruip0gbm@4ax.com>
In reply to#103588
On Fri, 10 Feb 2017 01:15:50 +0000, Ben Bacarisse
<ben.usenet@bsb.me.uk> wrote:

>ram@zedat.fu-berlin.de (Stefan Ram) writes:
>
>> Newsgroups: comp.lang.c,comp.lang.c++
>>
>> #include <float.h>
>>
>>   Some implementations have this property:
>>
>>   A double has at least 14 significant digits (about 14-16) and 
>>
>> 9007199254740991.
>
>I.e. 2^53 - 1  or, in most C implementations these days
>
>  (1llu << DBL_MANT_DIG) - 1
>
>This works when FLT_RADIX is 2, but it need not be.


   (pow(FLT_RADIX, DBL_MANT_DIG) - 1)

Should get close.  That does have the disadvantage that it can't be
computed at compile time.  And resulting in a FP number.


>>   is the largest double value that can be added to 1.0
>>   giving the "next" double value
>>
>> 9007199254740992.
>>
>>   (when one adds 1.0 again, the value will not change
>>   anymore).
>>
>>   I don't know whether there is a common name for such a
>>   value. I will call it (just for this post) "omega".
>>   (In the above example, the omega is 9007199254740991.)
>>
>>   Now, the standard does not require 14 significant
>>   digits, but 10 (DBL_DIG).
>>
>>   I wonder whether one can somehow find the smallest
>>   omega for the type double that is required by the
>>   standard.
>
>I don't think you can get more than an approximation to it and probably
>quite a crude one at that.  The standard does not give minimum values
>for DBL_MANT_DIG as you have no doubt found out already.


I'm not sure what the OP is asking, but if it's about the minimum
possible "omega" on a conforming implementation (rather than the
actual omega of a particular implementation), then the answer would
appear to be approximately:

  (pow(10,DBL_DIG) - 1)

[toc] | [prev] | [next] | [standalone]


#103606

Fromscott@slp53.sl.home (Scott Lurndal)
Date2017-02-10 14:57 +0000
Message-ID<NxknA.31923$1w1.22568@fx35.iad>
In reply to#103593
Robert Wessel <robertwessel2@yahoo.com> writes:
>On Fri, 10 Feb 2017 01:15:50 +0000, Ben Bacarisse

>
>
>   (pow(FLT_RADIX, DBL_MANT_DIG) - 1)
>
>Should get close.  That does have the disadvantage that it can't be
>computed at compile time.  And resulting in a FP number.

With GCC you can do this as a compile time constexpr.

e.g., something similar to:

constexpr
unsigned int log2(uint64_t n) { return (n<=1) ? 0: (64-__builtin_clzll(n-1)); };

[toc] | [prev] | [next] | [standalone]


#103716

FromRobert Wessel <robertwessel2@yahoo.com>
Date2017-02-12 01:52 -0600
Message-ID<ah40acloeeg6kh7ldq6cgkuib1p0bv7arg@4ax.com>
In reply to#103606
On Fri, 10 Feb 2017 14:57:49 GMT, scott@slp53.sl.home (Scott Lurndal)
wrote:

>Robert Wessel <robertwessel2@yahoo.com> writes:
>>On Fri, 10 Feb 2017 01:15:50 +0000, Ben Bacarisse
>
>>
>>
>>   (pow(FLT_RADIX, DBL_MANT_DIG) - 1)
>>
>>Should get close.  That does have the disadvantage that it can't be
>>computed at compile time.  And resulting in a FP number.
>
>With GCC you can do this as a compile time constexpr.
>
>e.g., something similar to:
>
>constexpr
>unsigned int log2(uint64_t n) { return (n<=1) ? 0: (64-__builtin_clzll(n-1)); };


That's not the same thing - the above uses pow(), because FLT_RADIX
does not have to be 2.  And it's its an exponential function, not a
logarithm.

If you're implying that you could use a logarithm as a part of that
computation, assuming, something like:

  a**b  =  2 ** (a * lg(b))

and generating the logarithm with a clz, and then the exponentiation
with a left shit.

That doesn't work because no integer approximation of the lg will be
close enough to create anywhere near the correct value for the
exponentiation.  An exception being where (a) is a power of two.

Now while I suppose someone could define a pow() that is, itself, a
constexpr, I've never seen it done.

[toc] | [prev] | [next] | [standalone]


#103880

Fromscott@slp53.sl.home (Scott Lurndal)
Date2017-02-14 13:39 +0000
Message-ID<XLDoA.10876$ez.8333@fx17.iad>
In reply to#103716
Robert Wessel <robertwessel2@yahoo.com> writes:
>On Fri, 10 Feb 2017 14:57:49 GMT, scott@slp53.sl.home (Scott Lurndal)
>wrote:
>
>>Robert Wessel <robertwessel2@yahoo.com> writes:
>>>On Fri, 10 Feb 2017 01:15:50 +0000, Ben Bacarisse
>>
>>>
>>>
>>>   (pow(FLT_RADIX, DBL_MANT_DIG) - 1)
>>>
>>>Should get close.  That does have the disadvantage that it can't be
>>>computed at compile time.  And resulting in a FP number.
>>
>>With GCC you can do this as a compile time constexpr.
>>
>>e.g., something similar to:
>>
>>constexpr
>>unsigned int log2(uint64_t n) { return (n<=1) ? 0: (64-__builtin_clzll(n-1)); };
>
>
>That's not the same thing - the above uses pow(), because FLT_RADIX
>does not have to be 2.  And it's its an exponential function, not a
>logarithm.

"something like" in this case means call 'pow' directly in
a constexpr function.  It will be evaluated at compile time.

[toc] | [prev] | [next] | [standalone]


#103882

FromRobert Wessel <robertwessel2@yahoo.com>
Date2017-02-14 08:02 -0600
Message-ID<c536achi70d3hv8hrvc4p3pic33lh4lup3@4ax.com>
In reply to#103880
On Tue, 14 Feb 2017 13:39:03 GMT, scott@slp53.sl.home (Scott Lurndal)
wrote:

>Robert Wessel <robertwessel2@yahoo.com> writes:
>>On Fri, 10 Feb 2017 14:57:49 GMT, scott@slp53.sl.home (Scott Lurndal)
>>wrote:
>>
>>>Robert Wessel <robertwessel2@yahoo.com> writes:
>>>>On Fri, 10 Feb 2017 01:15:50 +0000, Ben Bacarisse
>>>
>>>>
>>>>
>>>>   (pow(FLT_RADIX, DBL_MANT_DIG) - 1)
>>>>
>>>>Should get close.  That does have the disadvantage that it can't be
>>>>computed at compile time.  And resulting in a FP number.
>>>
>>>With GCC you can do this as a compile time constexpr.
>>>
>>>e.g., something similar to:
>>>
>>>constexpr
>>>unsigned int log2(uint64_t n) { return (n<=1) ? 0: (64-__builtin_clzll(n-1)); };
>>
>>
>>That's not the same thing - the above uses pow(), because FLT_RADIX
>>does not have to be 2.  And it's its an exponential function, not a
>>logarithm.
>
>"something like" in this case means call 'pow' directly in
>a constexpr function.  It will be evaluated at compile time.


It would have to be an custom version of pow(), one presumably limited
to integer arguments, that would be implemented as a constexpr
function.  pow() itself, is not, AFAIK, valid in a constexpr function.

[toc] | [prev] | [next] | [standalone]


#103895

Fromscott@slp53.sl.home (Scott Lurndal)
Date2017-02-14 17:30 +0000
Message-ID<E8HoA.28800$824.16996@fx37.iad>
In reply to#103882
Robert Wessel <robertwessel2@yahoo.com> writes:
>On Tue, 14 Feb 2017 13:39:03 GMT, scott@slp53.sl.home (Scott Lurndal)
>wrote:
>
>>Robert Wessel <robertwessel2@yahoo.com> writes:
>>>On Fri, 10 Feb 2017 14:57:49 GMT, scott@slp53.sl.home (Scott Lurndal)
>>>wrote:
>>>
>>>>Robert Wessel <robertwessel2@yahoo.com> writes:
>>>>>On Fri, 10 Feb 2017 01:15:50 +0000, Ben Bacarisse
>>>>
>>>>>
>>>>>
>>>>>   (pow(FLT_RADIX, DBL_MANT_DIG) - 1)
>>>>>
>>>>>Should get close.  That does have the disadvantage that it can't be
>>>>>computed at compile time.  And resulting in a FP number.
>>>>
>>>>With GCC you can do this as a compile time constexpr.
>>>>
>>>>e.g., something similar to:
>>>>
>>>>constexpr
>>>>unsigned int log2(uint64_t n) { return (n<=1) ? 0: (64-__builtin_clzll(n-1)); };
>>>
>>>
>>>That's not the same thing - the above uses pow(), because FLT_RADIX
>>>does not have to be 2.  And it's its an exponential function, not a
>>>logarithm.
>>
>>"something like" in this case means call 'pow' directly in
>>a constexpr function.  It will be evaluated at compile time.
>
>
>It would have to be an custom version of pow(), one presumably limited
>to integer arguments, that would be implemented as a constexpr
>function.  pow() itself, is not, AFAIK, valid in a constexpr function.

$ cat /tmp/a.cpp
#include <float.h>
#include <math.h>

constexpr double omega(void) { return pow(FLT_RADIX, DBL_MANT_DIG) - 1; }

int
main(int argc, const char **argv, const char **envp)
{
    double o = omega();

    return (int)o;
}

$ g++ -std=c++11 -o /tmp/a /tmp/a.cpp
$

[toc] | [prev] | [next] | [standalone]


#103913

FromRobert Wessel <robertwessel2@yahoo.com>
Date2017-02-14 17:39 -0600
Message-ID<os47acl5h6qtcdc3vpfn0apjm1mji6n0tq@4ax.com>
In reply to#103895
On Tue, 14 Feb 2017 17:30:12 GMT, scott@slp53.sl.home (Scott Lurndal)
wrote:

>Robert Wessel <robertwessel2@yahoo.com> writes:
>>On Tue, 14 Feb 2017 13:39:03 GMT, scott@slp53.sl.home (Scott Lurndal)
>>wrote:
>>
>>>Robert Wessel <robertwessel2@yahoo.com> writes:
>>>>On Fri, 10 Feb 2017 14:57:49 GMT, scott@slp53.sl.home (Scott Lurndal)
>>>>wrote:
>>>>
>>>>>Robert Wessel <robertwessel2@yahoo.com> writes:
>>>>>>On Fri, 10 Feb 2017 01:15:50 +0000, Ben Bacarisse
>>>>>
>>>>>>
>>>>>>
>>>>>>   (pow(FLT_RADIX, DBL_MANT_DIG) - 1)
>>>>>>
>>>>>>Should get close.  That does have the disadvantage that it can't be
>>>>>>computed at compile time.  And resulting in a FP number.
>>>>>
>>>>>With GCC you can do this as a compile time constexpr.
>>>>>
>>>>>e.g., something similar to:
>>>>>
>>>>>constexpr
>>>>>unsigned int log2(uint64_t n) { return (n<=1) ? 0: (64-__builtin_clzll(n-1)); };
>>>>
>>>>
>>>>That's not the same thing - the above uses pow(), because FLT_RADIX
>>>>does not have to be 2.  And it's its an exponential function, not a
>>>>logarithm.
>>>
>>>"something like" in this case means call 'pow' directly in
>>>a constexpr function.  It will be evaluated at compile time.
>>
>>
>>It would have to be an custom version of pow(), one presumably limited
>>to integer arguments, that would be implemented as a constexpr
>>function.  pow() itself, is not, AFAIK, valid in a constexpr function.
>
>$ cat /tmp/a.cpp
>#include <float.h>
>#include <math.h>
>
>constexpr double omega(void) { return pow(FLT_RADIX, DBL_MANT_DIG) - 1; }
>
>int
>main(int argc, const char **argv, const char **envp)
>{
>    double o = omega();
>
>    return (int)o;
>}
>
>$ g++ -std=c++11 -o /tmp/a /tmp/a.cpp
>$


While GCC (6.3) does compile that (and with -O2, actually reduces it
to a constant), ICC (17) does not, and Clang (3.9.1) accepts it, but
appears to still generate a call to pow() (more specifically it
converts the tail call in main to a jump to pow).

My question is is this actually required by the standard?  GCC seems
to take a tour through some of the "promoted" stuff, which I really
don't understand.  Unless I've missed it, I really haven't seen
anything like a list of math.h functions that are required to be
constexpr (assuming appropriate inputs).  Obviously a compiler can
provide an extension providing an constexpr pow().

[toc] | [prev] | [next] | [standalone]


#103744

FromTim Rentsch <txr@alumni.caltech.edu>
Date2017-02-12 10:16 -0800
Message-ID<kfnfujj2s2e.fsf@x-alumni2.alumni.caltech.edu>
In reply to#103593
Robert Wessel <robertwessel2@yahoo.com> writes:

> On Fri, 10 Feb 2017 01:15:50 +0000, Ben Bacarisse
> <ben.usenet@bsb.me.uk> wrote:
>
>> ram@zedat.fu-berlin.de (Stefan Ram) writes:
>>
>>> Newsgroups: comp.lang.c,comp.lang.c++
>>>
>>> #include <float.h>
>>>
>>>   Some implementations have this property:
>>>
>>>   A double has at least 14 significant digits (about 14-16) and
>>>
>>> 9007199254740991.
>>
>> I.e. 2^53 - 1  or, in most C implementations these days
>>
>>  (1llu << DBL_MANT_DIG) - 1
>>
>> This works when FLT_RADIX is 2, but it need not be.
>
>    (pow(FLT_RADIX, DBL_MANT_DIG) - 1)
>
> Should get close.  That does have the disadvantage that it can't be
> computed at compile time.  And resulting in a FP number.

Since DBL_MANT_DIG is an integer, this expression can be computed
at compile time, assuming the value of DBL_MANT_DIG is within a
reasonable range (say, less than 1,000).  The resulting expansion
is usable (thank goodness!) as a constant expression.

>>>   is the largest double value that can be added to 1.0
>>>   giving the "next" double value
>>>
>>> 9007199254740992.
>>>
>>>   (when one adds 1.0 again, the value will not change
>>>   anymore).
>>>
>>>   I don't know whether there is a common name for such a
>>>   value.  I will call it (just for this post) "omega".
>>>   (In the above example, the omega is 9007199254740991.)
>>>
>>>   Now, the standard does not require 14 significant
>>>   digits, but 10 (DBL_DIG).
>>>
>>>   I wonder whether one can somehow find the smallest
>>>   omega for the type double that is required by the
>>>   standard.
>>
>> I don't think you can get more than an approximation to it and probably
>> quite a crude one at that.  The standard does not give minimum values
>> for DBL_MANT_DIG as you have no doubt found out already.
>
> I'm not sure what the OP is asking, but if it's about the minimum
> possible "omega" on a conforming implementation (rather than the
> actual omega of a particular implementation), then the answer would
> appear to be approximately:
>
>   (pow(10,DBL_DIG) - 1)

I believe this statement is correct, if we consider only those
implementations whose floating-point representations agree with
the model of section 5.2.4.2.2.

If we consider other possible representation schemes, then the
question gets more complicated, and I'm not sure what that means
for a minimal value for omega.  For example, I believe the
Standard allows, and is meant to allow, floating-point numbers to
be represented as logarithms.  I don't know what that implies for
omega, and probably it depends on the details of how omega is
formally defined.  I put together a short program that calculates
omega exactly in a way that I believe corresponds to what Stefan
was trying to get at.  (Note that this is omega for a particular
implementation, not a minimal omega.)  That program could be used
to define omega formally, but other plausible programs might give
different results, especially if, eg, a logarithm representation
is used.

[toc] | [prev] | [next] | [standalone]


#103772

FromJuha Nieminen <nospam@thanks.invalid>
Date2017-02-13 07:33 +0000
Message-ID<o7rngl$2kq$2@adenine.netfront.net>
In reply to#103588
In comp.lang.c++ Ben Bacarisse <ben.usenet@bsb.me.uk> wrote:
> This works when FLT_RADIX is 2, but it need not be.

In which practical system it isn't?

Of course for optimization you could use #if to use the integer
calculation, else the floating point one.

[toc] | [prev] | [next] | [standalone]


#103781

FromRobert Wessel <robertwessel2@yahoo.com>
Date2017-02-13 04:07 -0600
Message-ID<ce03acpg76a85224aveug7khmmlsvav7nh@4ax.com>
In reply to#103772
On Mon, 13 Feb 2017 07:33:44 +0000 (UTC), Juha Nieminen
<nospam@thanks.invalid> wrote:

>In comp.lang.c++ Ben Bacarisse <ben.usenet@bsb.me.uk> wrote:
>> This works when FLT_RADIX is 2, but it need not be.
>
>In which practical system it isn't?
>
>Of course for optimization you could use #if to use the integer
>calculation, else the floating point one.


On IBM mainframes, you can use either traditional hex FP or IEEE
binary FP for floats, doubles and long doubles (based on a compiler
option).  FLT_RADIX changes appropriately.

The system also supports IEEE decimal floating point, but I'm not
aware of any way you can make ordinary floats use decimal FP (you
actually do define such items with "_Decimal64", etc., and additional
constants are defined in decimal.h).

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.c


csiph-web