Wednesday, November 14, 2018

Digest for comp.lang.c++@googlegroups.com - 21 updates in 7 topics

Nikki Locke <nikki@trumphurst.com>: Nov 14 11:23PM

Available C++ Libraries FAQ
 
URL: http://www.trumphurst.com/cpplibs/
 
This is a searchable list of libraries and utilities (both free
and commercial) available to C++ programmers.
 
If you know of a library which is not in the list, why not fill
in the form at http://www.trumphurst.com/cpplibs/cppsub.php
 
Maintainer: Nikki Locke - if you wish to contact me, please use the form on the website.
bitrex <user@example.net>: Nov 14 11:01AM -0500


> Citation, please? The only relevant text I could find has already been
> quoted by Stephen Ram, and says that the value is implementation-
> defined.
 
<https://en.cppreference.com/w/cpp/numeric/math/pow>
 
"pow(base, ±0) returns 1 for any base, even when base is NaN"
 
"If base is zero and exp is zero, a domain error may occur."
 
I assume this to mean that a domain error may or may not occur depending
on implementation, but the operation should still return 1 regardless.
Or that that particular reference is simply "wrong" as well.
 
It also shows that "pow(+1, NAN) = 1" what the hell does 1 to the power
of NaN even mean, mathematically speaking. But nobody appears to be
wigging out over that one.
bitrex <user@example.net>: Nov 14 11:06AM -0500

> computer math can't be perfectly in accord with the math of real
> numbers, and often isn't. I don't know how they chose that rule; one
> possibility is that it simplifies implementation of pow().
 
There's a bit of an abuse of terminology when we call things like
std::pow or pow "functions." In analysis x^n is a _function_.
Exponentiation is an _operator_.
 
The value of the _function_ is undefined at 0^0. The behavior of an
_operator_ may be defined as you like.
bitrex <user@example.net>: Nov 14 11:14AM -0500

On 11/14/2018 11:06 AM, bitrex wrote:
> Exponentiation is an _operator_.
 
> The value of the _function_ is undefined at 0^0. The behavior of an
> _operator_ may be defined as you like.
 
That is to say the reason why the function x^n at (0, 0) is undefined in
real analysis is because that's what makes the most sense for real
analysis for the exponentiation operator to return, for the reasons
already given. Of course it returns undefined in that situation "you"
set it up that way! Or else one believes in the One True Mathematics
handed down by God in which case I cannot argue anymore.
Ben Bacarisse <ben.usenet@bsb.me.uk>: Nov 14 04:29PM

>> I can't really think of many mathematical contexts where it makes much
>> sense to define 0^0 as being something other than 1.
 
> In mathematics, 0^0 is undefined. Period. No ifs, buts or maybes.
 
Them's fight'n words! There is a very clear exception when considering
integer powers. 0^0 must be 1 in those cases or almost every bit of
code you write to do combinatorics or symbolic mathematics involving
integer powers (polynomials, series and so one) would have to have
special cases. In fact, you'd fix the special case just once by
defining your own integer power function that gave 0^0 == 1 and you'd
use that instead of the broken built-in one.
 
This has nothing to do with C++ since C++ has only C's pow function and
its own complex ones. C++ has no integer exponentiation operator or
function to worry about, but I am sure that even you would make
 
int ipow(int x, int y);
 
return 1 for ipow(0, 0), wouldn't you?
 
<snip>
--
Ben.
bitrex <user@example.net>: Nov 14 12:06PM -0500

On 11/14/2018 11:29 AM, Ben Bacarisse wrote:
 
> int ipow(int x, int y);
 
> return 1 for ipow(0, 0), wouldn't you?
 
> <snip>
 
z^n @ (0, 0) is not undefined in complex analysis either it is 0; z^n
for n in the set of real numbers is a perfectly nice bijective mapping
from the set of complex numbers to the set of complex numbers,
continuous and infinitely differentiable everywhere.
 
the return value of ::std::complex::pow is unambiguously
implementation-defined however cuz ::std::complex::pow is not the
analytic function z^n.
bitrex <user@example.net>: Nov 14 12:14PM -0500

On 11/14/2018 03:56 AM, David Brown wrote:
>> and all else is pathological edge-cases.
 
> I thought God created the natural numbers, and all the rest is the work
> of man?
 
Nah, natural numbers are just the unit test for complex analysis. If the
result of some operation in complex analysis isn't in agreement with the
behavior of the natural numbers then the problem is in the operation not
elsewhere.
bitrex <user@example.net>: Nov 14 12:17PM -0500

On 11/14/2018 12:14 PM, bitrex wrote:
> result of some operation in complex analysis isn't in agreement with the
> behavior of the natural numbers then the problem is in the operation not
> elsewhere.
 
So should actually say they're the base case and the stuff in-between N
and C are the pathological cases.
jameskuyper@alumni.caltech.edu: Nov 14 10:08AM -0800

On Wednesday, November 14, 2018 at 11:06:23 AM UTC-5, bitrex wrote:
> On 11/14/2018 09:28 AM, jameskuyper@alumni.caltech.edu wrote:
...
> Exponentiation is an _operator_.
 
> The value of the _function_ is undefined at 0^0. The behavior of an
> _operator_ may be defined as you like.
 
The only use of "function" in the text you quoted was from the C++
standard, where the definitions of terms provided by that standard
overrule any other definitions. As a general rule, the reason why any
term is defined in the standard is that it is used there with a meaning
that might be at least subtly (and often not-so-subtly) different from
the meaning it would otherwise have. Such discrepancies are the norm,
not the exception.
 
C++ Functions are defined in 6.7.2p1, primarily by cross-referece to
9.2.3.5, which explains how to declare them. std::pow() is unambiguously
a C++ function (or more precisely, a family of overloaded functions,
some of them templated).
 
11.5p1 defines what constitutes a C++ operator; pow isn't on the list.
 
Still, I was curious to understand the distinction you were making.
While I've formally studied math at a fairly high level, it's been a
long time since I did so, so I reviewed the definitions (marked as
specifically for use in mathematics) provided by wikipedia:
 
"Formally, a function f from a set X to a set Y is defined by a set G of
ordered pairs (x, y) such that x ∈ X, y ∈ Y, and every element of X is
the first component of exactly one ordered pair in G."
<https://en.wikipedia.org/wiki/Function_(mathematics)#Definition>
 
"an operator is generally a mapping that acts on elements of a space to
produce other elements of the same space."
<https://en.wikipedia.org/wiki/Operator_(mathematics)>
 
Each overload of std::pow() has a set X consisting of the outer product
of the set of values represented by it's first parameter's type, and
the set of values representable by it's second parameter's type. It
maps each element of that set to one and only one element of the set Y,
consisting of all representable values of it's return type. Note that
this description applies to any particular implementation of the C/C++
standard library; different implementations might provide slightly
different mappings, due to permissible variations in the accuracy with
which they are implemented.
This seems an excellent match to the definition of a function.
 
However, X and Y are very different spaces, so it doesn't sound like a
particularly good match to that definition of an operator.
 
Possibly you're using different definitions for those terms? Nothing
would be more typical of mathematics than the use of different
definitions in different contexts - but by the same token, that should
lead you to respect C++'s decision to provide it's own, overriding
definitions for those terms.
jameskuyper@alumni.caltech.edu: Nov 14 10:18AM -0800

On Wednesday, November 14, 2018 at 11:01:55 AM UTC-5, bitrex wrote:
> On 11/14/2018 08:59 AM, jameskuyper@alumni.caltech.edu wrote:
> > On Wednesday, November 14, 2018 at 4:31:02 AM UTC-5, bitrex wrote:
...
> > defined.
 
> <https://en.cppreference.com/w/cpp/numeric/math/pow>
 
> "pow(base, ±0) returns 1 for any base, even when base is NaN"
 
That's a requirement stated in the C standard; it's inherited by the C++
standard, but not explicitly stated by it, and it applies only to
implementations which choose to pre#define __STDC_IEC_559__, and only to
the C standard library functions inherited by C++. Rather annoyingly, it
does not apply to the std::pow() overloads for complex types.
bitrex <user@example.net>: Nov 14 02:28PM -0500

> definitions in different contexts - but by the same token, that should
> lead you to respect C++'s decision to provide it's own, overriding
> definitions for those terms.
 
Essentially from the definition of a mathematical operation.
Exponentiation is an operation, like +, -, differentiation operator "D",
Laplace transform operator "L", etc. they are not functions.
 
<https://en.wikipedia.org/wiki/Exponentiation>
 
x^n is a function. So the question would be what is std::pow supposed to
represent. The formal function x^n as it is used in real analysis, or
the more general mathematical operator of exponentiation, but a
constrained variant of it which operates only on the types it does
simply due to practical limitations of the intrinsic language types i.e.
you're not working with pen and paper
 
Since the value of the formal function x^n is undefined at (0, 0) as any
real analysis text would say, if that's what they were trying to
represent why would the designers of the language standard allow any
different, in any implementation? it would be wrong! It should just
throw a domain exception no ifs-ands-or-buts. But since they did in fact
do something different that would imply to me that wasn't what they were
trying to make, rather a pragmatically-constrained exponentiation
operator. and " ^ " was already taken.
jameskuyper@alumni.caltech.edu: Nov 14 12:53PM -0800

On Wednesday, November 14, 2018 at 2:29:10 PM UTC-5, bitrex wrote:
> On 11/14/2018 01:08 PM, jameskuyper@alumni.caltech.edu wrote:
...
> Exponentiation is an operation, like +, -, differentiation operator "D",
> Laplace transform operator "L", etc. they are not functions.
 
> <https://en.wikipedia.org/wiki/Exponentiation>
 
That describes Exponentiation as a mathematical operation, cross-referencing
<https://en.wikipedia.org/wiki/Operation_(mathematics)>, which says "An operation ω is a function of the form ω : V → Y, where V ⊂ X1 × ... × Xk.". Do you agree with that definition? If so, operations are functions, and there's nothing wrong with using the term "function" to refer to an operation.
 
...
> real analysis text would say, if that's what they were trying to
> represent why would the designers of the language standard allow any
> different, in any implementation?
 
The answer for the C++ standard is that they were just incorporating the
C standard library by reference. The answer for the C standard is that
they were just following the lead of ISO/IEC 60559. I don't have a copy
of that standard, and even if I did, it wouldn't necessarily explain why
that decision was made. But I do know that in many cases ISO/IEC 60559
just codified existing practice, which often meant following the lead of
Fortran. I'm not sure whether this is one of those cases, but if it is,
you might want to ask why Fortran made that decision. As a general rule,
if there's a discrepancy between the mathematical definition of a
function, and the corresponding computer implementation of that
function, it's generally because it was found to be acceptable in most
cases, and more convenient for at least some cases. That's the best
answer I can give you - I wasn't involved in any of the relevant
decision making.
 
> it would be wrong! It should just
> throw a domain exception no ifs-ands-or-buts. But since they did in fact
 
The specification was derived from C, which doesn't have exceptions to
be thrown. C's floating point exceptions (which are incorporated by
reference into C++ - see section 24.4) are very different from C++
exceptions - they don't interrupt the flow of execution, they merely set
flags which can be tested after execution is complete.
In the context of high-performance numerical calculations, it would
often be unacceptable to interrupt the flow of execution with a C++
exception.
 
> do something different that would imply to me that wasn't what they were
> trying to make, rather a pragmatically-constrained exponentiation
> operator.
 
That seems extremely plausible. Pragmatism usually plays a big role in the development of standards.
bitrex <user@example.net>: Nov 14 05:36PM -0500

>> trying to make, rather a pragmatically-constrained exponentiation
>> operator.
 
> That seems extremely plausible. Pragmatism usually plays a big role in the development of standards.
 
I believe what I should have said is that std::pow(x, y) should probably
be understood to represent the exponential operator, not the operation
of exponentiation itself, and not the real-valued function x^n. Like "^"
but in the development of C++ "^" was already taken for xor and they
didn't give it a new thing. "+" could have been say add(1, 2), okay sure
add(1, 2) will be a function call but "+" operator is not a function. In
say Mathematica "^" means the exponential operator and what it does is
context-dependent on what its operands are.
 
If it had been given its own symbol in C++ it would've been
over-loadable like any other operator I suppose; that would make sense
as while the concept of "exponentiation" is easy to visualize with
natural numbers as repeated multiplication exponent-number-of-times the
exponentiation operator "^" is used in other contexts where what the
operation it actually performs is is not really at all intuitive, like
you can write A^B where both A and B are matrices.
 
What does it "mean" to multiply matrix A with itself B times where B is
a rank 47 matrix? I'm not sure I could tell you that from an intuitive
perspective but it can definitely be defined to produce something, as a
valid _operation_, all the way back to the Peano axioms I suppose.
 
So it's my contention that because of the intrinsic limitations "pow"
while seems to behave a lot like the plain ol' function x^n for floating
point real numbers there's no mathematical law or reason it has to
confirm to the analysis textbook behavior of x^n because that's not
really what it "is."
 
Just because std::pow can accept floating point real numbers like you're
doing real analysis doesn't mean you have to use it that way, could also
use it to strictly exponentiate values from the set of natural numbers
to do set theory problems, in set theory it's perfectly natural to
define 0^0 = 1 and 0^0 = undefined makes no sense, how come set theory
should get the shaft in deference to what analysis says it should be?
 
'bout the best argument I can make. :)
"Chris M. Thomasson" <invalid_chris_thomasson@invalid.invalid>: Nov 14 02:35PM -0800

On 11/13/2018 1:04 PM, Rick C. Hodgin wrote:
> On Tuesday, November 13, 2018 at 3:56:51 PM UTC-5, Chris M. Thomasson wrote:
>> Have you ever read about the Giants, or Hybrids in the Bible?
 
> The Nephilim.
 
Indeed. I have a sneaking suspicion that the Nephilim happen to be hyper
smart rebellious alien scientists. God told them not to mess around with
the natural process on Earth. The Nephilim said, "FU%^&&^%%% YOU", and
experimented away at full steam ahead... God basically had to destroy
their abominations of desolation, their hybrid strange creations, with
the: Flood...^^...^^^^...^^
 
Ascii art for little waves. ;^)
ram@zedat.fu-berlin.de (Stefan Ram): Nov 14 09:39PM

><https://en.wikipedia.org/wiki/Operation_(mathematics)>, which says "An ope=
>ration =CF=89 is a function of the form =CF=89 : V =E2=86=92 Y, where V =E2=
 
(Sorry for the bad quotation
- There's a problem with the newsreader.)
 
C already uses a term "operation".
 
For example:
 
|7.17.7 Operations on atomic types
 
|7.21.4 Operations on files
 
|3.19.5
|perform a trap
|interrupt execution of the program such that no further
|operations are performed
 
|A volatile access to an object, modifying a file, or calling
|a function that does any of those operations are all side
|effects, which are changes in the state of the execution
|environment.
 
|Floating-point operations implicitly set the status flags
 
|Much of this section is motivated by the desire to support
|atomic operations with explicit and detailed visibility
|constraints.
 
..
 
But what is this, an operation?
 
I am not sure there is a definition in ISO/IEC 9899!
 
Maybe in the normative reference ISO/IEC 2382:2015? Yes:
 
|operation
|A well-defined action that, when applied to any permissible
|combination of known entities, produces a new entity.
 
This leads only to more questions: What is an action?
When is it well-defined? Is something that does not
produce new entities but changes existing entities not
an operation?
 
The definition I would personally prefer would be to define
the term "operation" a the execution of a specific
incarnation of an operator or of a function. For example,
during the evaluation of »2+3*4«, there are two operations:
»3*4« and »2+7«. For another example, the evaluation of
»pow(2,3*4)« has »3*4« and »pow(2,7)«. Sometimes it might
be helpful to allow "internal operations" of the implementation
which do not directly correspond to a C operator or function,
but on "internal operators" or "internal functions". E.e.,
the behavior of the evaluation of »2|3« in C might be explained
based on internal operations on bits.
 
With regard to mathematics: I sometimes find the term
operation from universal algebra helpful: It also allows
for operations with zero operands. This better corresponds to
C functions like »rand()« than mathematical function,
which do not allow for a function with zero parameters.
 
|An n-ary operation on A is a function that takes n
|elements of A and returns a single element of A.
en.wikipedia.org/wiki/Universal_algebra
woodbrian77@gmail.com: Nov 14 12:41PM -0800

On Tuesday, November 13, 2018 at 3:41:44 PM UTC-6, Lynn McGuire wrote:
> effort – this wouldn't be possible without all of your help. So, thank
> you, and apologies for not being able to acknowledge everyone by name."
 
> Wow, that is a lot of new features.
 
I'm wondering if there will be a new C that is
based on 2011 C++ and that adds some of the things
from 2014, 2017 and 2020 C++. A less frenzied
language.
 
> Lynn
 
 
Brian
Ebenezer Enterprises - In G-d we trust.
https://github.com/Ebenezer-group/onwards
David Brown <david.brown@hesbynett.no>: Nov 14 09:52PM +0100

> based on 2011 C++ and that adds some of the things
> from 2014, 2017 and 2020 C++. A less frenzied
> language.
 
There is a C17, with draft standard available. It doesn't change much
compared to C11, but incorporates a whole bunch of defect reports and
has nicer (IMHO) typesetting.
 
C2x is underway, with a few new features. It is not yet solidified, but
you can find some information about proposals and likely features.
Don't expect it to have too much new - C is intentionally a slow-moving
language, unlike C++.
Ian Collins <ian-news@hotmail.com>: Nov 15 10:27AM +1300

On 15/11/18 09:52, David Brown wrote:
>> On Tuesday, November 13, 2018 at 3:41:44 PM UTC-6, Lynn McGuire wrote:
>>> "Trip report: Fall ISO C++ standards meeting (San Diego)" by Herb Sutter
 
>>> https://herbsutter.com/2018/11/13/trip-report-fall-iso-c-standards-meeting-san-diego/
 
<snip>
> you can find some information about proposals and likely features.
> Don't expect it to have too much new - C is intentionally a slow-moving
> language, unlike C++.
 
I liked this quote from origin link:
 
"Signed integers are two's complement (JF Bastien) is the result of a
courtroom drama in both WG21 (C++) and WG14 (C). After intense
prosecutorial cross-examination, the witness finally admitted in both
courts that, yes, all known modern computers are two's complement
machines, and, no, we don't really care about using C++ (or C) on the
ones that aren't. The C standard is likely to adopt the same change."
 
About time!
 
This one should hopefully be in the next C:
 
"assume_aligned (Timur Doumler, Chandler Carruth) enables portable code
to express an alignment optimization hint to the compiler."
 
--
Ian
"Öö Tiib" <ootiib@hot.ee>: Nov 14 08:50AM -0800

On Wednesday, 14 November 2018 16:27:02 UTC+2, Manfred wrote:
 
> > new(&x.front()) char;
> Also note the most confusing call of placement new to X* when given a
> type 'char'.
 
That was my extension. OP code did placement new 'X' not 'char'.
I did it for to show that only the type of arguments inside () matters
to what placement new is picked by overload resolution and that
there won't be any diagnostics.
 
 
> Also true.
> In my experience I have (rarely) used placement new, but never had to
> override it.
 
I have seen it been overload for passing whatever other things
but the pointer for example for to instrument the buffer
somehow:
 
void* operator new [](size_t n, char c)
{
char* p = new char[n];
std::fill(p, p+n, c);
return p;
}
 
Such code always seems like deliberate obfuscation.
One likely has to read [expr.new] of standard to figure out
what is going on there and if and to what extent it is valid.
Manfred <noname@add.invalid>: Nov 14 08:20PM +0100

On 11/14/2018 5:50 PM, Öö Tiib wrote:
> On Wednesday, 14 November 2018 16:27:02 UTC+2, Manfred wrote:
>> On 11/14/2018 2:33 PM, Öö Tiib wrote:
[...]
>>> std::cout << "Placement new to X* for size " << sz << "\n";
>>> return p;
>>> }
[...]
> I did it for to show that only the type of arguments inside () matters
> to what placement new is picked by overload resolution and that
> there won't be any diagnostics.
 
And, in fact the type of the arguments (X*) is used to resolve
overloading of the operator, and 'char' to deduce the size arg 'sz'
passed to the overloaded operator.
As I said, most confusing.
 
[...]
David Brown <david.brown@hesbynett.no>: Nov 14 04:22PM +0100

On 14/11/18 14:46, Scott Lurndal wrote:
 
> Really, I've never seen a useful "portable" "standard" C or C++
> real-world application. That's not to say they don't exist, but
> they're very rare.
 
There is a distinction between portable code, and portable programs. I
doubt if there are many fully portable C or C++ programs. But there is
a good deal of portable C and C++ code. It is not at all uncommon to
have most of the C implementation files and headers written in portable
code, with only a few specific parts written in an
implementation-specific or non-portable manner.
 
So you could have a header file that contained:
 
static inline int popcount(unsigned int x) {
return __builtin_popcount(x);
}
 
That would be non-standard and non-portable.
 
The C file that used the code, #include'ing the header and calling the
function "popcount", would be portable.
 
So the program as a whole would be non-portable, but the C code that
called the popcount function would be portable.
 
 
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page.
To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com.

No comments: