Topic: why C/C++ have no reentrant functions ?


Author: sbnaran@fermi.ceg.uiuc.edu (Siemel Naran)
Date: 1998/09/09
Raw View
On 09 Sep 98 18:31:21 GMT, Zalman Stern <zalman@netcom.com> wrote:

>Doh! I forgot about that. How do people feel about having C++ move away
>from this in the future? Two obvious possibilities are using exceptions and
>overloading the math functions with versions that take an extra argument to
>return the exception info. Both are easy to make thread safe and should
>offer better optimization opportunities. Plus the existing calls could be
>easily written in terms of these new ones.

This sounds good.  The problem with sin,cos,sqrt is that they have
side effects -- setting ::errno in this case.  So if they throw
exceptions to express errors, it means that they no longer have side
effects.

One problem is that code will have to be rewritten to use exceptions.
No big deal though, because we (usually?) always check that x>=0.0
before calling sqrt(x) anyway.  If we don't do this check, then our
root finding problem or whatever it is that we're doing will not
converge, and we'll also do a bunch of unnecessary calculations.
In short, I'm not using ::errno, so why should I pay the price of
missed optimizations?

// function illustrating useless calculations
double func(double a)
{
     const double k1=sqrt(a);
     // more calculations
     return a*b;
}

If a<0.0, then we could simply return NaN without doing more
calculations, as follows:

double func(double a, double b)
{
     // do we have to set ::errno to zero here?
     const double k1=sqrt(a);
     if (::errno) return NaN;
     // more calculations
     return a*b;
}

But it's probably best to put the check for bad 'a' in the calling
code.  This actually helps with root finding and makes the code
clearer.

Besides, a single global variable ::errno doesn't hold up well
in multi-threading.  If we have N threads, then we need N
global ::errno's.

Besides, errno is an integer.  It should probably be a bool or
an enum for conceptual reasons.  Using int encourages people to
make up funny codes, like 3 means bad sqrt, etc.

Anyway, I checked my man page, and sin does not set ::errno.
Most of the other math funcs don't seem to set ::errno either.


Second, if we did this then the C math libraries will no longer
be compatible with the C++ math libraries.  No big deal here
either because library vendors would be only to happy to sell
us specialized C++ math libraries.  However, people using both
C and C++ would be screwed.

My suggestion is to make a namespace nonstd that has the C++
versions of the math functions.  If this works out good, we
can move it into namespace std.

--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: sjc@netcom.com (Steven Correll)
Date: 1998/09/10
Raw View
In article <35F0666C.794B@wizard.net>, James Kuyper  <kuyper@wizard.net> wrote:
>Zalman Stern wrote:
>Note, however, that sin() and cos() are not strictly "reentrant", in
>that they set the global variable errno in the case of a domain error.
>This interferes with some otherwise permissible optimizations, but only
>if the value of errno is checked somewhere.

The standard says that "errno" is a macro, not necessarily a global variable,
so that if the underlying system provides some method of accessing
thread-local-storage, that machinery might hide behind the macro. This would
certainly allow reentrancy relative to multiple threads; it might not allow
the optimizations you're thinking of.
--
Steven Correll == 1931 Palm Ave, San Mateo, CA 94403 == sjc@netcom.com


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: James Kuyper <kuyper@wizard.net>
Date: 1998/09/10
Raw View
Siemel Naran wrote:
...
> Anyway, I checked my man page, and sin does not set ::errno.
> Most of the other math funcs don't seem to set ::errno either.

The C++ standard doesn't cover this directly; it inherits the relevant
wording from the C standard. The C standard leaves it implementation
defined whether errno is set. Portable code has to assume that it might
be set; a specific implementation can do optimizations, based upon the
knowledge that sin() doesn't set errno in that implementation.

...
> My suggestion is to make a namespace nonstd that has the C++
> versions of the math functions.  If this works out good, we
> can move it into namespace std.

I like the idea of a 'math', or perhaps 'std::math' namespace better. It
would be a start toward compartmentalizing the standard library. Having
everything directly under std feels a bit crowded to me.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: 1998/09/10
Raw View
James Kuyper wrote:
>
> Steve Clamage wrote:
> ...
> > The only observable result of a call to the math routines is the
> > returned value, so the compiler is always free to cache results and
> > omit calls. No conforming program could tell the difference.
>
> One other observable effect: setting of errno.

Fortunately, if sin(x) sets errno once, it will set it every time, so
there is still no observable difference between, say, "sin(x) + sin(x)"
and "2*sin(x)".

--

Ciao,
Paul
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: "Robert O'Dowd" <nospam@nonexistant.com>
Date: 1998/09/10
Raw View
Zalman Stern wrote:
>
> James Kuyper (kuyper@wizard.net) wrote:
> : Note, however, that sin() and cos() are not strictly "reentrant", in
> : that they set the global variable errno in the case of a domain error.
> : This interferes with some otherwise permissible optimizations, but only
> : if the value of errno is checked somewhere.
>
> Doh! I forgot about that. How do people feel about having C++ move away
> from this in the future? Two obvious possibilities are using exceptions and
> overloading the math functions with versions that take an extra argument to
> return the exception info. Both are easy to make thread safe and should
> offer better optimization opportunities. Plus the existing calls could be
> easily written in terms of these new ones.
>

I'm ambiguous in my opinions on this one.  A few thoughts.

sin() and cos() need have no side effects as they apply to all real
numbers (IEEE NaNs or similar things, not covered under standard C++,
possibly excepted).  A better example would be sqrt() which requires a
non-negative argument.

I never rely on errno in working code.  This is done by simply checking
arguments.  eg. ensuring sqrt() always receives a positive value.  That
means I could happily live without it.

I'm not really happy with the notion of either throwing exceptions from
math functions or returning info in an extra argument.  Both approaches
introduce overhead.  I still use FORTRAN for a lot of numerically
intensive code where run time speed is paramount.  The performance
hit that would be introduced by these approaches would mean me running
back to FORTRAN coding in cases where C++ is acceptable now but may
not be under exception handling schemes.  At the least, I'd have
to reassess a lot of code.



Author: Gabriel Dos Reis <dosreis@DPTMaths.ens-cachan.fr>
Date: 1998/09/10
Raw View
>>>>> =ABJames=BB, James Kuyper <kuyper@wizard.net> wrote:

James> Siemel Naran wrote:
James> ...
>> Anyway, I checked my man page, and sin does not set ::errno.
>> Most of the other math funcs don't seem to set ::errno either.

James> The C++ standard doesn't cover this directly; it inherits the relevant
James> wording from the C standard. The C standard leaves it implementation
James> defined whether errno is set. Portable code has to assume that it might
James> be set; a specific implementation can do optimizations, based upon the
James> knowledge that sin() doesn't set errno in that implementation.

James> ...
>> My suggestion is to make a namespace nonstd that has the C++
>> versions of the math functions.  If this works out good, we
>> can move it into namespace std.

James> I like the idea of a 'math', or perhaps 'std::math' namespace better. It
James> would be a start toward compartmentalizing the standard library. Having
James> everything directly under std feels a bit crowded to me.

I agree.

I would like to strongly second the idea of defining a namespace
std::math. One purpose of this namespace would be to provide a
complete rewrite/specification of some functions is <cmath> in light
of experience and benefits gained from exceptions uses. It would also
be an opportunity to provide a full support of IEEE aritmethic.

--
Gabriel Dos Reis                   |  Centre de Math=E9matiques et de
dosreis@cmla.ens-cachan.fr         |         Leurs Applications
Fax : (33) 01 47 40 21 69          |   ENS de Cachan -- CNRS (URA 1611)
               61, Avenue du Pdt Wilson, 94235 Cachan - Cedex


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: James Kuyper <kuyper@wizard.net>
Date: 1998/09/10
Raw View
Robert O'Dowd wrote:
>
> Zalman Stern wrote:
> >
> > James Kuyper (kuyper@wizard.net) wrote:
> > : Note, however, that sin() and cos() are not strictly "reentrant", in
> > : that they set the global variable errno in the case of a domain error.
> > : This interferes with some otherwise permissible optimizations, but only
> > : if the value of errno is checked somewhere.
...
> I'm ambiguous in my opinions on this one.  A few thoughts.
>
> sin() and cos() need have no side effects as they apply to all real
> numbers (IEEE NaNs or similar things, not covered under standard C++,
> possibly excepted).  A better example would be sqrt() which requires a
> non-negative argument.

On some implementations, sin(x) and cos(x) will set errno to EDOM, if x
is so large that x+pi == x, to machine precision. (I'm not sure that's
the exact criterion, but that's the basic idea). This is because the
argument cannot be given with sufficient precision to determine the
function value with a precision better that +/-2.

...
> My suggestion would be as follows.  Use three (!) namespaces
>
> The current math functions go into std namespace (I can't recall if
> they're in std or not).  The intent of this namespace is backward

The entire standard library is in std.


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: sbnaran@fermi.ceg.uiuc.edu (Siemel Naran)
Date: 1998/09/10
Raw View
On 10 Sep 98 07:50:21 GMT, Robert O'Dowd <nospam@nonexistant.com> wrote:

>My suggestion would be as follows.  Use three (!) namespaces

>The current math functions go into std namespace (I can't recall if
>A second complete set go into a mathdebug namespace.  The functions
>A third complete set go into a math namespace.  These functions do

Another idea.  The "namespace math" is good -- your second set.  These funcs
are complete with exception handling.  A compiler option turns exceptions
off just for this math namespace.  As an analogy, g++ has a -ffast-math option.


>       void foo() throw();

This still generates exception handling code.  Namely -- throw
bad_exception if some expression inside foo() throws anything.


--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Pete Becker <petebecker@acm.org>
Date: 1998/09/10
Raw View
Robert O'Dowd wrote:
>
>
> sin() and cos() need have no side effects as they apply to all real
> numbers (IEEE NaNs or similar things, not covered under standard C++,
> possibly excepted).

It's much worse than that, because we're not dealing with real numbers,
but floating point numbers. There are only a finite number of floating
point values that can be represented on a computer. (For example, if you
have 64-bit floats then there are at most 2^64 different values that can
be represented). In practice this means that for sufficiently large
values you cannot do meaningful computations of sin and cos, largely
because you reach a point where v + pi == v. This happens because v is
so much larger than pi that adding pi only affects the bits beyond those
that are actually stored. One consequence of this is that when you scale
the number down to the range -pi/2 to pi/2 in order to compute the sin
you no longer have a meaningful value.

--
Pete Becker
Dinkumware, Ltd.
http://www.dinkumware.com
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: James Kuyper <kuyper@wizard.net>
Date: 1998/09/10
Raw View
Paul D. DeRocco wrote:
>
> James Kuyper wrote:
> >
> > Steve Clamage wrote:
> > ...
> > > The only observable result of a call to the math routines is the
> > > returned value, so the compiler is always free to cache results and
> > > omit calls. No conforming program could tell the difference.
> >
> > One other observable effect: setting of errno.
>
> Fortunately, if sin(x) sets errno once, it will set it every time, so
> there is still no observable difference between, say, "sin(x) + sin(x)"
> and "2*sin(x)".

However, if your code changes the value of errno between two otherwise
identical calls to sin(), the compiler cannot store the value returned
by the first call, and skip the second one. A rare situation, but not an
impossible one.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: sbnaran@fermi.ceg.uiuc.edu (Siemel Naran)
Date: 1998/09/10
Raw View
On 10 Sep 98 07:48:31 GMT, Paul D. DeRocco <pderocco@ix.netcom.com> wrote:

>Fortunately, if sin(x) sets errno once, it will set it every time, so
>there is still no observable difference between, say, "sin(x) + sin(x)"
>and "2*sin(x)".

No, what if the expressions are seperated.

double func(double x)
{
     double y=sin(x); // might set ::errno
     for (int i=0; i<10; i++) y+=sqrt(double(i)); // might unset ::errno
     y*=sin(x); // might set ::errno again
     return y;
}


--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: miker3@ix.netcom.com (Michael Rubenstein)
Date: 1998/09/11
Raw View
On 10 Sep 1998 16:39:37 GMT, James Kuyper <kuyper@wizard.net> wrote:

>On some implementations, sin(x) and cos(x) will set errno to EDOM, if x
>is so large that x+pi == x, to machine precision. (I'm not sure that's
>the exact criterion, but that's the basic idea). This is because the
>argument cannot be given with sufficient precision to determine the
>function value with a precision better that +/-2.

That's misleading at best and, as I read the C standard,
nonconforming.

All references below are to the C standard.

A domain error is defined (7.5.1):

 For all functions [in <math.h>], a domain error occurs if an
 input argument is outside the domain over which the
 mathematical function is defined.  The description of each
 function lists any required domain errors; an implementation
 may define additional domain errors, provided that such errors
 are consistent with the mathematical definition of the
 function.  On a domain error, the function returns an
 implementation-defined value; the value of the macro EDOM is
 stored in errno.

Since sin and cos are mathemtically defined for all real values, there
should be no domain error.

7.5.1 also defines a range error (ERANGE), which also cannot occur for
sin and cos of a real argument.

However, 7.1.4 says

 The value of errno may be set to nonzero by a library function
 whether or not there is an error, provided the use of errno is
 not documented in the description of the function in this
 International Standard.

Does the description of sin and cos provide for using errno? If so,
then setting errno to EDOM is incorrect.

I would say that the description does provide for using errno even
though neither of the errors discussed can actually occur for the
functions.
--
Michael M Rubenstein


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: "Jim Cobban" <Jim.Cobban.jcobban@nt.com>
Date: 1998/09/11
Raw View
In article <v8vg1e08706.fsf@cor.dptmaths.ens-cachan.fr>,
Gabriel Dos Reis  <dosreis@DPTMaths.ens-cachan.fr> wrote:
>I would like to strongly second the idea of defining a namespace
>std::math. One purpose of this namespace would be to provide a
>complete rewrite/specification of some functions is <cmath> in light
>of experience and benefits gained from exceptions uses. It would also
>be an opportunity to provide a full support of IEEE aritmethic.

You will never get this approved as long as there are major computer vendors
who do not have IEEE 754 floating point.  That is every computer vendor
which was already in existence 15 years ago when the IEEE 754 specification
was published.  Whether you like it or not those companies are selling
BILLIONS of dollars worth of computers every year to people who don't give a
damn whether their floating point implements all of the features of 754.
--
Jim Cobban   |  jcobban@nortel.ca                   |  Phone: (613) 763-8013
Nortel (MCS) |                                      |  FAX:   (613) 763-5199


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: miker3@ix.netcom.com (Michael Rubenstein)
Date: 1998/09/11
Raw View
On 10 Sep 98 20:20:55 GMT, sbnaran@fermi.ceg.uiuc.edu (Siemel Naran)
wrote:

>On 10 Sep 98 07:48:31 GMT, Paul D. DeRocco <pderocco@ix.netcom.com> wrote:
>
>>Fortunately, if sin(x) sets errno once, it will set it every time, so
>>there is still no observable difference between, say, "sin(x) + sin(x)"
>>and "2*sin(x)".
>
>No, what if the expressions are seperated.
>
>double func(double x)
>{
>     double y=sin(x); // might set ::errno
>     for (int i=0; i<10; i++) y+=sqrt(double(i)); // might unset ::errno
>     y*=sin(x); // might set ::errno again
>     return y;
>}

Bad example.

No standard library function may "unset" errno.  Standard library
functions may not set errno to zero.

Second, sqrt cannot set errno unless the argument is negative.
--
Michael M Rubenstein


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Gabriel Dos Reis <dosreis@DPTMaths.ens-cachan.fr>
Date: 1998/09/11
Raw View
>>>>> =ABJim=BB, Jim Cobban <Jim.Cobban.jcobban@nt.com> wrote:

> In article <v8vg1e08706.fsf@cor.dptmaths.ens-cachan.fr>,
> Gabriel Dos Reis  <dosreis@DPTMaths.ens-cachan.fr> wrote:
>> I would like to strongly second the idea of defining a namespace
>> std::math. One purpose of this namespace would be to provide a
>> complete rewrite/specification of some functions is <cmath> in light
>> of experience and benefits gained from exceptions uses. It would also
>> be an opportunity to provide a full support of IEEE aritmethic.

> You will never get this approved as long as there are major computer vendors
> who do not have IEEE 754 floating point.  That is every computer vendor
> which was already in existence 15 years ago when the IEEE 754 specification
> was published.  Whether you like it or not those companies are selling
> BILLIONS of dollars worth of computers every year to people who don't give a
> damn whether their floating point implements all of the features of 754.

You're right but let me point out that C9x has adopted some features
to support IEEE arithmetics. I can reasonably think that they will be
included in the next revision.

I support the idea of  *separate* namespace std::math so that C math
functions still remain for compatibility for those who don't care for
IEEE arithmetic.

--
Gabriel Dos Reis                   |  Centre de Math=E9matiques et de
dosreis@cmla.ens-cachan.fr         |         Leurs Applications
Fax : (33) 01 47 40 21 69          |   ENS de Cachan -- CNRS (URA 1611)
               61, Avenue du Pdt Wilson, 94235 Cachan - Cedex


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: sbnaran@fermi.ceg.uiuc.edu (Siemel Naran)
Date: 1998/09/11
Raw View
On 11 Sep 1998 16:24:57 GMT, Michael Rubenstein <miker3@ix.netcom.com> wrote:

>Bad example.
>
>No standard library function may "unset" errno.  Standard library
>functions may not set errno to zero.

Oops.  I better read the man page more carefully next time.  :).


--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: James Kuyper <kuyper@wizard.net>
Date: 1998/09/12
Raw View
Siemel Naran wrote:
>
> On 10 Sep 98 07:48:31 GMT, Paul D. DeRocco <pderocco@ix.netcom.com> wrote:
>
> >Fortunately, if sin(x) sets errno once, it will set it every time, so
> >there is still no observable difference between, say, "sin(x) + sin(x)"
> >and "2*sin(x)".
>
> No, what if the expressions are seperated.
>
> double func(double x)
> {
>      double y=sin(x); // might set ::errno
>      for (int i=0; i<10; i++) y+=sqrt(double(i)); // might unset ::errno
>      y*=sin(x); // might set ::errno again
>      return y;
> }

If 'unset' means 'set to 0', that's not permitted for standard library
functions by the C standard. The relevant sections of the C standard are
incorporated by reference into the C++ standard.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: zalman@netcom.com (Zalman Stern)
Date: 1998/09/12
Raw View
Robert O'Dowd (nospam@nonexistant.com) wrote:
: I'm not really happy with the notion of either throwing exceptions from
: math functions or returning info in an extra argument.  Both approaches
: introduce overhead.

The idea was that to have two functions:
 math::sqrt(double x); // No overhead. Negative x returns garbage
 math::sqrt(double x, bool ok); // Does the check for you...
or whatever.

Also, the exception case need not have any extra overhead for correct
calls. (Assuming the processor raises a floating-point exception in the bad
argument case and the runtime has "zero speed overhead when not raised"
exceptions.)

[Multiple namespaces idea.]

Hmmmm... Interesting. I'll have to think about this technique.

-Z-
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: zalman@netcom.com (Zalman Stern)
Date: 1998/09/12
Raw View
Jim Cobban (Jim.Cobban.jcobban@nt.com) wrote:
: You will never get this approved as long as there are major computer vendors
: who do not have IEEE 754 floating point.  That is every computer vendor
: which was already in existence 15 years ago when the IEEE 754 specification
: was published.  Whether you like it or not those companies are selling
: BILLIONS of dollars worth of computers every year to people who don't give a
: damn whether their floating point implements all of the features of 754.

You overstate the case a little as due to other presures, many of these
vendors are adding IEEE floating-point to their new implementations. (E.g.
Cray and I think I heard somewhere that IBM is doing this for 390 class
hardware. DEC Alpha supported IEEE from day one. I don't know if they still
sell real VAXen.) So never may only be ten or 15 years.

-Z-
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: zalman@netcom.com (Zalman Stern)
Date: 1998/09/09
Raw View
James Kuyper (kuyper@wizard.net) wrote:
: Note, however, that sin() and cos() are not strictly "reentrant", in
: that they set the global variable errno in the case of a domain error.
: This interferes with some otherwise permissible optimizations, but only
: if the value of errno is checked somewhere.

Doh! I forgot about that. How do people feel about having C++ move away
from this in the future? Two obvious possibilities are using exceptions and
overloading the math functions with versions that take an extra argument to
return the exception info. Both are easy to make thread safe and should
offer better optimization opportunities. Plus the existing calls could be
easily written in terms of these new ones.

-Z-
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Paresh Adhia <adhia_paresh@jpmorgan.com.com>
Date: 1998/09/09
Raw View
Zalman Stern wrote:
>
> James Kuyper (kuyper@wizard.net) wrote:
> : Note, however, that sin() and cos() are not strictly "reentrant", in
> : that they set the global variable errno in the case of a domain error.
> : This interferes with some otherwise permissible optimizations, but only
> : if the value of errno is checked somewhere.
>
> Doh! I forgot about that. How do people feel about having C++ move away
> from this in the future? Two obvious possibilities are using exceptions and
> overloading the math functions with versions that take an extra argument to
> return the exception info. Both are easy to make thread safe and should
> offer better optimization opportunities. Plus the existing calls could be
> easily written in terms of these new ones.

Or may be now they can be put into separate namespace like math::sin, allowing older programs to continue
accessing std::sin and new ones can use math::sin, that way we don't need to pass extra argument just to be
able to overload existing definition. BTW, if function modifies one of the argument, possible thru' pointer,
then it wouldn't be reentrant.

I like the idea of throwing exceptions.

--
Please remove extra .com from my address to reply me directly.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: James Kuyper <kuyper@wizard.net>
Date: 1998/09/07
Raw View
Steve Clamage wrote:
...
> The only observable result of a call to the math routines is the
> returned value, so the compiler is always free to cache results and
> omit calls. No conforming program could tell the difference.

One other observable effect: setting of errno.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1998/09/04
Raw View
In article <35F02D0A.F9@jpmorgan.com.com>, Paresh Adhia <adhia_paresh@jp
morgan.com.com> writes
>y = sin(x) - cos(x);
>z = cos(x) + sin(x);
>
>PL/I compiler would not call sin(x) and cos(x) functions again to evaluate "z" -
>it would create temporaries to
>hold values returned by functions sin and cos while evaluating "y" and use them
>to evaluate "z". Of course,
>PL/I will do such optimization only for "built-in" functions. I don't see how
>even the most aggressive C/C++
>compiler can achieve this, unless it knows the function does not have side-
>effect (i.e. re-entrant, if input to
>function is same, the output is guaranteed to be same.).

I suspect that many C++ compilers would do likewise, but perhaps not in
strictly conforming mode.  Actually you raise a good point, it would be
helpful to have some way to declare that a compiler was at liberty to
optimise away calls to a function.

--
Francis Glassborow
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: sbnaran@fermi.ceg.uiuc.edu (Siemel Naran)
Date: 1998/09/04
Raw View
On 04 Sep 98 17:04:20 GMT, Paresh Adhia <adhia_paresh@jpmorgan.com.com> wrote:

>y = sin(x) - cos(x);
>z = cos(x) + sin(x);
>
>PL/I compiler would not call sin(x) and cos(x) functions again to evaluate "z" - it would create temporaries to
>hold values returned by functions sin and cos while evaluating "y" and use them to evaluate "z". Of course,
>PL/I will do such optimization only for "built-in" functions. I don't see how even the most aggressive C/C++
>compiler can achieve this, unless it knows the function does not have side-effect (i.e. re-entrant, if input to
>function is same, the output is guaranteed to be same.).

A conforming compiler is allowed to do this optimization.

First, it knows the standard library functions.  So through constant
folding, sin(30.0deg) will be a compile time constant.  Through
constant propogation, if the expression sin(x) is used in two places
and (x) is the same in both places, then sin(x) will be evaluated once
and cached in a register or whatever.

If the function is a user defined, non-inline function, the compiler
can do the following analysis.  If every sub-tree in the tree for
the function is re-entrant, the the whole function itself is
re-entrant.  Then the compiler stores this information the header's
object file.  Eg,

// file.h
double action(double, double);

// file.c
#include "file.h"
double action(double x, double y) { return x+y; }

Now type "CC -c file.c".
This generates a file "file.o" that contains the object file code.
It also generates a file "file.h.o" that contains the info that
function action(double,double) is re-entrant.

// main.c
#include "file.h" // implicitly includes file.h.o
int main() { std::cout<<action(1.0,2.0)+action(1.0,2.0)<<'\n'; }


This idea of the header's file object file seems a bit strange.
But if it can be worked out somehow, all sorts of optimizations
can be put into the header file.


--
----------------------------------
Siemel B. Naran (sbnaran@uiuc.edu)
----------------------------------
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: zalman@netcom.com (Zalman Stern)
Date: 1998/09/04
Raw View
Paresh Adhia (adhia_paresh@jpmorgan.com.com) wrote:
: [In PL/I sin and cos are "intrinsics", i.e. known to the compiler, and
   hence calls to them can be aggrssivley optimized.]

I believe the same is true in C++ . (It is certainly true in C89 and the
proposed C9X.) Many compilers do not take advantage of this, but that has
to do with "legacy practice" and implementor priorities, not limitations of
the standard.

-Z-


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1998/09/05
Raw View
Paresh Adhia <dont@mail.me.COM> writes:

>I always wondered why C/C++ don't have ability to declare functions as
>reentrant ?

C did not address reentrancy or threaded execution at all,
except for some caveats about signal handlers.

The C++ committee had more than enough work to do without
opening up that very messy can of worms. (The standard
does make a few statements about thread-safety of some
container classes.)

Some implementations of C and C++ provide libraries and
compilation modes that allow you to write reentrant and
multithreaded code. Those topics might become part of a future
C++ standard if there is enough interest and volunteers to do
the necessary work.

--
Steve Clamage, stephen.clamage@sun.com
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: James Kuyper <kuyper@wizard.net>
Date: 1998/09/05
Raw View
Zalman Stern wrote:
>
> Paresh Adhia (adhia_paresh@jpmorgan.com.com) wrote:
> : [In PL/I sin and cos are "intrinsics", i.e. known to the compiler, and
>    hence calls to them can be aggrssivley optimized.]
>
> I believe the same is true in C++ . (It is certainly true in C89 and the
> proposed C9X.) Many compilers do not take advantage of this, but that has
> to do with "legacy practice" and implementor priorities, not limitations of
> the standard.

Note, however, that sin() and cos() are not strictly "reentrant", in
that they set the global variable errno in the case of a domain error.
This interferes with some otherwise permissible optimizations, but only
if the value of errno is checked somewhere.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: jcoffin@taeus.com (Jerry Coffin)
Date: 1998/09/05
Raw View
In article <35F02D0A.F9@jpmorgan.com.com>,
adhia_paresh@jpmorgan.com.com says...

[ ... ]

> Thanks for responding. You are right about the example I quoted. May
> be I chose the wrong example. I really come from mainframe PL/I
> background, so let me refrain from C++ till I know more aboutit.
> Meanwhile, let me quote another example. PL/I compiler would optimize
> following code.
>
> y = sin(x) - cos(x);
> z = cos(x) + sin(x);
>
> PL/I compiler would not call sin(x) and cos(x) functions again to
> evaluate "z" - it would create temporaries to hold values returned by
> functions sin and cos while evaluating "y" and use them to evaluate
> "z". Of course, PL/I will do such optimization only for "built-in"
> functions. I don't see how even the most aggressive C/C++ compiler
> can achieve this, unless it knows the function does not have side-
> effect (i.e. re-entrant, if input to function is same, the output
> is guaranteed to be same.).

A C++ compiler is free to have special knowledge of library functions,
generate them inline, etc.  An aggressive compiler knows that sin and
cos don't have side-effects, and won't evaluate the expressions twice
to get the results above.  Just for example, I took your code, and
compiled with MS Visual C++ 5.0.  The first time around, the compiler
recognized that the results of the computations were never used so it
produced no code to produce the results at all.  After adding calls to
print out the results, it compiled main as follows:

_main PROC NEAR     ; COMDAT
; File mathopt.cpp
; Line 13
 fld QWORD PTR $T8407
 sub esp, 8
 fcos
 mov ecx, OFFSET
FLAT:?cout@std@@3V?$basic_ostream@DU?$char_traits@D@std@@@1@A
 fld QWORD PTR $T8407
 fsin
 fld ST(1)
 fadd ST(0), ST(1)
 fstp QWORD PTR [esp]
 push OFFSET FLAT:$SG6642
 fsub ST(0), ST(1)
 sub esp, 8
 fstp QWORD PTR [esp]
 fstp ST(0)
 call ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01
@N@Z ; std::basic_ostream<char,std::char_traits<char>>::operator<<
 push eax
 call ??6std@@YAAAV?$basic_ostream@DU?$char_traits@D@std@@@0@A
AV10@PBD@Z ; std::operator<<
 add esp, 8
 mov ecx, eax
 call ??6?$basic_ostream@DU?$char_traits@D@std@@@std@@QAEAAV01
@N@Z ; std::basic_ostream<char,std::char_traits<char>>::operator<<
; Line 14
 xor eax, eax
; Line 15
 ret 0
_main ENDP

Note that both sin and cos have been produced as in-line code rather
than using standard library functions at all.  Second, note that fsin
and fcos are each used exactly once.  This still isn't entirely
optimal, as a good assembly language coder could use the fsincos
instruction to produce both the sine and cosine, which is normally
faster than producing the two individually.  However, from the looks
of things, at least some compilers are already managing what you want
without the extra syntax you're asking for to help them accomplish it.

--
    Later,
    Jerry.

The Universe is a figment of its own imagination.
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 1998/09/06
Raw View
Francis Glassborow <francis@robinton.demon.co.uk> writes:

>In article <35F02D0A.F9@jpmorgan.com.com>, Paresh Adhia <adhia_paresh@jp
>morgan.com.com> writes
>>y = sin(x) - cos(x);
>>z = cos(x) + sin(x);

>>PL/I compiler would not call sin(x) and cos(x) functions again to evaluate "z" -
>>it would create temporaries to
>>hold values returned by functions sin and cos while evaluating "y" and use them
>>to evaluate "z". Of course,

>I suspect that many C++ compilers would do likewise, but perhaps not in
>strictly conforming mode.

The standard requires only that an implementation produce the
"observable results" specified. The standard library routine
names are reserved if the header is included, and reserved as
extenal identifiers in any event. Programmers are not permitted by
the standard to replace them. The compiler is always allowed to
assume that a call to ::sin or ::cos (with an appropriate signature)
is to the standard library routine.

The only observable result of a call to the math routines is the
returned value, so the compiler is always free to cache results and
omit calls. No conforming program could tell the difference.

Why don't more compilers make this optimization? All the compiler
implementors I know are overwhelmed by trying to meet the requirements
of the standard. Special-purpose optimizations take a back seat.

--
Steve Clamage, stephen.clamage@sun.com
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Paresh Adhia <dont@mail.me.COM>
Date: 1998/09/03
Raw View
I always wondered why C/C++ don't have ability to declare functions as
reentrant ? Compilers can perform quite a few optimizations based on this
additional knowldedge. More so in C++ because of objects. For example if
compiler knows if the constructors/destructor are reentrant then unused
objects which are wasted can be omptimized out, just like built-in types.

consider this,

myclass a;
myclass b(some parms);
a = b;

Here compiler can avoid calling default constructor and then destructor
for "a" and instead directly invoke the copy constructor with "b" as parm
- assumming myclass is defined appropriately. Of course this optimization
can be hand-coded, but think about code generators which generate C++
code without any optimizations.

There are other alternatives,

1) Allow #pragma. These are too compiler specific.
2) Let compiler be smart enough to recognize reentrant function if it
doesn't access static var.s or doesn't call any other non reentrant
functions. The problem with this is - it shifts omptimization to linker
and may not work with DLL's.

Thanks

Paresh


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]






Author: Francis Glassborow <francis@robinton.demon.co.uk>
Date: 1998/09/04
Raw View
In article <35EF0CB6.1CF@jpmorgan.com.com>, Paresh Adhia
<dont@mail.me.COM> writes
>myclass a;
>myclass b(some parms);
>a = b;
>
>Here compiler can avoid calling default constructor and then destructor
>for "a" and instead directly invoke the copy constructor with "b" as parm
>- assumming myclass is defined appropriately. Of course this optimization
>can be hand-coded, but think about code generators which generate C++
>code without any optimizations.

I think I would hate a compiler that did that.  If I chose to write my
code using copy assignment rather than copy constrction I presumably had
a reason (of course it might just be that I wasn't a very good coder:)

The problem with the idea is that it actually requires a very large
amount from the programmer.  Granted it would have the advantage that
the compiler could check that all functions called in the body of a re-
entrant function were themselves re-entrant.  Actually, that would be
the biggest advantage rather than potential for optimisation.
--
Francis Glassborow
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Paresh Adhia <adhia_paresh@jpmorgan.com.com>
Date: 1998/09/04
Raw View
Francis Glassborow wrote:
>
> In article <35EF0CB6.1CF@jpmorgan.com.com>, Paresh Adhia
> <dont@mail.me.COM> writes
> >myclass a;
> >myclass b(some parms);
> >a = b;
> >
> >Here compiler can avoid calling default constructor and then destructor
> >for "a" and instead directly invoke the copy constructor with "b" as parm
> >- assumming myclass is defined appropriately. Of course this optimization
> >can be hand-coded, but think about code generators which generate C++
> >code without any optimizations.
>
> I think I would hate a compiler that did that.  If I chose to write my
> code using copy assignment rather than copy constrction I presumably had
> a reason (of course it might just be that I wasn't a very good coder:)
>

Thanks for responding. You are right about the example I quoted. May be I chose the wrong example. I really
come from mainframe PL/I background, so let me refrain from C++ till I know more about it. Meanwhile, let me
quote another example. PL/I compiler would optimize following code.

y = sin(x) - cos(x);
z = cos(x) + sin(x);

PL/I compiler would not call sin(x) and cos(x) functions again to evaluate "z" - it would create temporaries to
hold values returned by functions sin and cos while evaluating "y" and use them to evaluate "z". Of course,
PL/I will do such optimization only for "built-in" functions. I don't see how even the most aggressive C/C++
compiler can achieve this, unless it knows the function does not have side-effect (i.e. re-entrant, if input to
function is same, the output is guaranteed to be same.).

I guess program would behave strangely, if programmer incorrectly labels a function "reentrant". (I remember
debugging a PL/I program that had time() function and would always return same time.)

Thanks

Paresh
---
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]





Author: Martin von Loewis <loewis@informatik.hu-berlin.de>
Date: 1998/09/04
Raw View
Paresh Adhia <dont@mail.me.COM> writes:

> myclass a;
> myclass b(some parms);
> a = b;
>
> Here compiler can avoid calling default constructor and then destructor
> for "a" and instead directly invoke the copy constructor with "b" as parm
> - assumming myclass is defined appropriately.

If the myclass constructors and assignment operators are inline, the
compiler can very well perform the optimizations you describe.

Regards,
Martin


[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@ncar.ucar.edu    ]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html              ]