Wednesday, November 14, 2018

Digest for comp.lang.c++@googlegroups.com - 25 updates in 3 topics

Juha Nieminen <nospam@thanks.invalid>: Nov 14 08:10AM

> __builtin_popcount is a viable solution for 99% of the code that
> needs it - portable "pure" C/C++ code is a myth.
 
Not only are you making your code non-standard and non-portable, and tied
to pretty much one single compiler, but ironically that very compiler uses
a lookup table for its fallback implementation of that function. Which is
the whole point I was making.
scott@slp53.sl.home (Scott Lurndal): Nov 14 01:46PM

>> __builtin_popcount is a viable solution for 99% of the code that
>> needs it - portable "pure" C/C++ code is a myth.
 
>Not only are you making your code non-standard and non-portable,
 
So what? My code relies heavily on POSIX interfaces anyway.
 
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.
 
Leaving aside classwork, of course.
"Öö Tiib" <ootiib@hot.ee>: Nov 14 07:02AM -0800

On Wednesday, 14 November 2018 15:46:24 UTC+2, Scott Lurndal wrote:
> real-world application. That's not to say they don't exist, but
> they're very rare.
 
> Leaving aside classwork, of course.
 
Exactly. Ultimately portable program can not exist in practice.
C and C++ just do not contain portable features to find out
implementation-specific details compile-time. So we have
to achieve portability with side-by-side platform-specific
code (like __popcnt, __builtin_popcount or fall-back to #error).

But (in practice) most of the most used software (starting
from web browsers) is written in C or C++. Lot of that runs
(again in practice) on majority of stuff that people actually
use.
bitrex <user@example.net>: Nov 13 07:27PM -0500

On 11/13/2018 04:56 PM, Stefan Ram wrote:
> contains the sentence:
 
> |The value returned for pow(0, 0) is implementation-defined.
 
> . Say what now?
 
std::pow from <cmath> returns 1 for std::pow(base, +0/-0) for any base
including NaN, is it okay to use that?
 
I can't really think of many mathematical contexts where it makes much
sense to define 0^0 as being something other than 1.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Nov 14 01:57AM +0100

On 14.11.2018 01:27, bitrex wrote:
> [snip]
> I can't really think of many mathematical contexts where it makes much
> sense to define 0^0 as being something other than 1.
 
If you consider x^n, then
 
* with x=0 and varying n down from infinity to 1, you get 0 all the way,
and would expect that also when you take n one step further down to 0,
 
* with n=0 and varying x down from infinity to 1, you get 1 all the way,
and would expect that also when you take x one step further down to 0.
 
So there are two natural choices for 0^0, namely 0 and 1.
 
Not sure exactly how x^n varies on the unit circle in the (x,n) plane,
but it must look pretty weird close to (0,0), with that sharp discontinuity.
 
 
Cheers!,
 
- Alf
bitrex <user@example.net>: Nov 14 12:26AM -0500

On 11/13/2018 07:57 PM, Alf P. Steinbach wrote:
> discontinuity.
 
> Cheers!,
 
> - Alf
 
From a set theory perspective the only choice that makes much sense for
0^0 is 1; the size of the set of all functions from the empty set to the
empty set is 1, the null function.
bitrex <user@example.net>: Nov 14 12:48AM -0500

On 11/13/2018 07:57 PM, Alf P. Steinbach wrote:
> discontinuity.
 
> Cheers!,
 
> - Alf
 
AFAIK the analytic _function_ z^n in the complex plane is a different
matter it has a removable singularity at 0^0 defined to be 0 at that
point because all the required directional limits allow it to be removed
a la Riemann's theorem.
 
<https://en.wikipedia.org/wiki/Removable_singularity>
 
z^n is holomorphic in C it is everywhere continuous and differentiable
(in C the former implies the latter, but not in R.)
 
std::pow is not the complex function z^n though it's C++'s equivalent of
the exponentiation operator.
bitrex <user@example.net>: Nov 14 01:00AM -0500

On 11/14/2018 12:48 AM, bitrex wrote:
 
> <https://en.wikipedia.org/wiki/Removable_singularity>
 
> z^n is holomorphic in C it is everywhere continuous and differentiable
> (in C the former implies the latter, but not in R.)
 
God created the complex numbers where everything works out very nicely
and all else is pathological edge-cases.
 
"ha ha I wonder when they'll notice that all non-trivial zeros of the
zeta function seem to have real part one half? LOL" God has a sense of humor
Siri Cruise <chine.bleu@yahoo.com>: Nov 13 10:37PM -0800


> > So there are two natural choices for 0^0, namely 0 and 1.
 
So average them: 0**0 = 1/2
 
--
:-<> Siri Seal of Disavowal #000-001. Disavowed. Denied. Deleted. @
'I desire mercy, not sacrifice.' /|\
An almond doesn't lactate. This post / \
Yet another supercilious snowflake for justice. insults Islam. Mohammed
Juha Nieminen <nospam@thanks.invalid>: Nov 14 08:33AM

> 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.
 
In limits, a result of 0^0 is undefined and needs further work to get
the actual answer, which may well be different from 1 (which is the reason
why 0^0 can *not* be said to be 1 even by convention. If you would do that,
you would get wrong answers for limit calculations.)
 
For example, if
 
f(x) = exp(-x^-4)
g(x) = x^2
 
then the limit when x->0 of f(x) is 0, and of g(x) is 0, which means that
the limit when x->0 of f(x)^g(x) is 0^0. Further calculations show that
the actual value of this limit is 0, not 1.
 
In fact, you can construct limit problems where f(x) and g(x) both
approach 0, and f(x)^g(x) approaches any value you want.
 
0^0 is not 1. It's undefined.
David Brown <david.brown@hesbynett.no>: Nov 14 09:54AM +0100

On 14/11/18 06:26, bitrex wrote:
 
>> Not sure exactly how x^n varies on the unit circle in the (x,n) plane,
>> but it must look pretty weird close to (0,0), with that sharp
>> discontinuity.
 
There is a picture on Wikipedia, as always:
 
<https://en.wikipedia.org/wiki/Zero_to_the_power_of_zero>
 
 
> From a set theory perspective the only choice that makes much sense for
> 0^0 is 1; the size of the set of all functions from the empty set to the
> empty set is 1, the null function.
 
That would be one way to define it that is consistent with the use of
power for considering the size of sets of functions. But there are
other ways to define it - such as the limit of 0^n as n tends to 0, that
give different values. Indeed, you can pick any non-negative real value
you want and find a continuous path to (0, 0) such that x^y tends
towards your target value.
 
So there is no choice for 0^0 that lets the power function be continuous
at 0.
 
However, defining it as 1 is often very useful - for most purposes, it
is either defined to 1 or left undefined.
David Brown <david.brown@hesbynett.no>: Nov 14 09:56AM +0100

On 14/11/18 07:00, bitrex wrote:
>> (in C the former implies the latter, but not in R.)
 
> God created the complex numbers where everything works out very nicely
> and all else is pathological edge-cases.
 
I thought God created the natural numbers, and all the rest is the work
of man?
 
Ralf Goertz <me@myprovider.invalid>: Nov 14 10:27AM +0100

Am Wed, 14 Nov 2018 08:33:35 -0000 (UTC)
 
> then the limit when x->0 of f(x) is 0, and of g(x) is 0, which means
> that the limit when x->0 of f(x)^g(x) is 0^0. Further calculations
> show that the actual value of this limit is 0, not 1.
 
Well, that is debatable, isn't it? f(x)^g(x) is the flat function
<https://en.wikipedia.org/wiki/Flat_function> which itself has to be
defined to be 0 at 0 to avoid a division by 0. I know that taking the
limit from both sides you also get 0 and that is infinitely often
differentiable in 0 but still. It is not analytical.
 
> In fact, you can construct limit problems where f(x) and g(x) both
> approach 0, and f(x)^g(x) approaches any value you want.
 
> 0^0 is not 1. It's undefined.
 
With that I agree…
bitrex <user@example.net>: Nov 14 04:30AM -0500

On 11/14/2018 03:33 AM, Juha Nieminen wrote:
>> 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.
 
Nonsense it's defined all the time. C++'s std::pow defines it to be 1.
"in mathematics" what's that mean? The One True Mathematics the one God
wrote the book on and handed down?
 
 
> In fact, you can construct limit problems where f(x) and g(x) both
> approach 0, and f(x)^g(x) approaches any value you want.
 
> 0^0 is not 1. It's undefined.
 
It's fascinating material for a real analysis course but defining it to
be "undefined" offers no practical advantages in the context of actually
performing mathematical calculations numerically in a computational
sense other than satisfying a pedant/calculus obsessive. How much real
analysis you do on the computer today?
bitrex <user@example.net>: Nov 14 04:38AM -0500

On 11/14/2018 04:27 AM, Ralf Goertz wrote:
>> approach 0, and f(x)^g(x) approaches any value you want.
 
>> 0^0 is not 1. It's undefined.
 
> With that I agree…
 
It's not undefined in set theory. It's not undefined in lambda calculus.
It's undefined in real analysis. The exponential operator is not real
analysis, intrinsically. As if every branch of mathematics is a serf
that somehow has to answer to the Throne of Real Analysis
Juha Nieminen <nospam@thanks.invalid>: Nov 14 10:04AM

>> In mathematics, 0^0 is undefined. Period. No ifs, buts or maybes.
 
> Nonsense it's defined all the time. C++'s std::pow defines it to be 1.
 
If it defines it to be 1, then it's wrong. The only "correct" value that
std::pow(0, 0) could ever return is NaN. Any other value is plain wrong.
 
You could just as well say that if C++ for some reason defines 0.0/0.0
to be 4.25, then that's how 0/0 is defined to be. Nonsense.
Paavo Helde <myfirstname@osa.pri.ee>: Nov 14 12:39PM +0200

On 14.11.2018 12:04, Juha Nieminen wrote:
 
>> Nonsense it's defined all the time. C++'s std::pow defines it to be 1.
 
> If it defines it to be 1, then it's wrong. The only "correct" value that
> std::pow(0, 0) could ever return is NaN. Any other value is plain wrong.
 
Unfortunately real compilers do not agree with this.
 
#include <iostream>
#include <cmath>
#include <complex>
 
int main() {
auto x = std::pow(0, 0);
auto y = std::pow(std::complex<double>(0, 0), std::complex<double>(0, 0));
std::cout << "x=" << x << ", y=" << y << "\n";
}
 
Output with MSVC++: x=1, y=(1,0)
Output with gcc: x=1, y=(0,0)
Manfred <noname@add.invalid>: Nov 14 01:48PM +0100

On 11/14/2018 11:39 AM, Paavo Helde wrote:
> }
 
> Output with MSVC++: x=1, y=(1,0)
> Output with gcc:    x=1, y=(0,0)
 
On my box gcc 8.2.1 yields the following:
std::pow(0., 0.) => 1.0;
std::pow(std::complex<double>(0,0), std::complex<double>(0,0)) =>
(nan,nan)
jameskuyper@alumni.caltech.edu: Nov 14 05:59AM -0800

On Wednesday, November 14, 2018 at 4:31:02 AM UTC-5, bitrex wrote:
> >> sense to define 0^0 as being something other than 1.
 
> > In mathematics, 0^0 is undefined. Period. No ifs, buts or maybes.
 
> Nonsense it's defined all the time. C++'s std::pow defines it to be 1.
 
Citation, please? The only relevant text I could find has already been
quoted by Stephen Ram, and says that the value is implementation-
defined.
jameskuyper@alumni.caltech.edu: Nov 14 06:28AM -0800

On Wednesday, November 14, 2018 at 5:04:54 AM UTC-5, Juha Nieminen wrote:
> bitrex <user@example.net> wrote:
> >> In mathematics, 0^0 is undefined. Period. No ifs, buts or maybes.
 
> > Nonsense it's defined all the time. C++'s std::pow defines it to be 1.
 
AFAICT, that's incorrect. The only thing that the C++ standard says
about it is that the value is implementation-defined, and it only says
that in the context of the complex version of it.
 
> If it defines it to be 1, then it's wrong. The only "correct" value that
> std::pow(0, 0) could ever return is NaN. Any other value is plain wrong.
 
pow() is part of the C standard library that is inherited by C++, with
modifications listed in section C.6. None of the listed modifications
affects this issue. In general, the only thing the C standard says about
pow(0,0) is that "A domain error may occur if x is zero and y is zero."
(7.12.7.4p2). "On a domain error, the function returns an
implementation-defined value; if the integer expression
math_errhandling & MATH_ERRNO is nonzero, the integer expression errno
acquires the value EDOM; if the integer expression
math_errhandling & MATH_ERREXCEPT is nonzero, the ''invalid'' floating-
point exception is raised." (7.12.1p2)
 
However, an implementation that pre#defines __STDC_IEC_559__ is required
to also conform to the requirements of Annex F of the C standard, which
are derived from the requirements of ISO/IEC 60559 (== IEEE 754), which
includes, in particular, the requirement that "pow(x, ±0) returns 1 for
any x, even a NaN" (F.10.4.4). So the authors of ISO/IEC 60559
apparently disagree with you. Mathematically, it may be undefined, but
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().
Christiano <christiano@engineer.com>: Nov 14 12:44AM -0800

The following program enter in my placemente new function only when the type is X.
 
#include <iostream>
 
struct X
{
};
 
void *operator new(size_t sz, X *p)
{
std::cout << "It's here with size " << sz << std::endl;
return p;
}
 
int main()
{
X v[10];
 
X *test = new(v) X;
 
std::cout << "------------------------------" << std::endl;
 
test = new(v) X[10];
 
return 0;
}
 
I tried several ways but I could not make the program access my function when I use the X[10].
How can I do it?
Bo Persson <bop@gmb.dk>: Nov 14 11:55AM +0100

On 2018-11-14 09:44, Christiano wrote:
> }
 
> I tried several ways but I could not make the program access my function when I use the X[10].
> How can I do it?
 
You would need a separate overload for 'operator new[]', to be used for
the array allocation.
 
 
Bo Persson
Jorgen Grahn <grahn+nntp@snipabacken.se>: Nov 14 11:56AM

On Wed, 2018-11-14, Christiano wrote:
> }
 
> I tried several ways but I could not make the program access my
> function when I use the X[10]. How can I do it?
 
Note that this stuff is rarely useful for most people. Last time I
overloaded operator new was 17 years ago. If you find yourself doing
it often (after learning how) then you're probably doing something
wrong.
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
"Öö Tiib" <ootiib@hot.ee>: Nov 14 05:33AM -0800

On Wednesday, 14 November 2018 10:45:12 UTC+2, Christiano wrote:
 
> I tried several ways but I could not make the program access my function when I use the X[10].
> How can I do it?
 
That is next to never needed. What you try to actually do?
Something like that will work:
 
#include <iostream>
#include <vector>
 
struct X {};
 
void *operator new(size_t sz, X* p)
{
std::cout << "Placement new to X* for size " << sz << "\n";
return p;
}
 
void *operator new[](size_t sz, X* p)
{
std::cout << "Placement new[] to X* for size " << sz << "\n";
return p;
}
 
int main()
{
std::vector<X> x(7707);
 
new(&x.front()) char;
 
std::cout << "----------------------------------\n";
 
new(&x.front()) char[42];
 
std::cout << "-W-O-R-K-S------------------------" << std::endl;
}
 
Note that without knowing difference between new and new[]
(and delete and delete[]) there are chances that you don't
understand even most mundane points of dynamic memory
management correctly. Read up there. Tricks like placement
news and even overriding such are likely too early to study.
 
Better leave *all* memory management to standard library
containers and smart pointers and avoid writing any C++ code
that contains keywords "new" or "delete" whatsoever. With
such code it is easier to become employed currently than
with seriously confused code.
Manfred <noname@add.invalid>: Nov 14 03:26PM +0100

On 11/14/2018 2:33 PM, Öö Tiib wrote:
 
>> I tried several ways but I could not make the program access my function when I use the X[10].
>> How can I do it?
 
> That is next to never needed.
True.
 
What you try to actually do?
> {
> std::vector<X> x(7707);
 
> new(&x.front()) char;
Also note the most confusing call of placement new to X* when given a
type 'char'.
 
> that contains keywords "new" or "delete" whatsoever. With
> such code it is easier to become employed currently than
> with seriously confused code.
 
Also true.
In my experience I have (rarely) used placement new, but never had to
override it.
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: