Tuesday, December 17, 2019

Digest for comp.lang.c++@googlegroups.com - 25 updates in 1 topic

Bart <bc@freeuk.com>: Dec 17 01:06AM

On 16/12/2019 15:21, David Brown wrote:
>> means, there is already X(uint64_t). There is not a totally new feature
>> or concept to add.
 
> <https://en.cppreference.com/w/cpp/language/user_literal>
 
I didn't follow most of that (C++ has a knack of making what should be
simple things, complicated). But I did recognise these examples:
 
"1-4) user-defined integer literals, such as 12_km"
"5-6) user-defined floating-point literals, such as 0.5_Pa"
 
"double x = 90.0_deg;"
 
These are numeric suffixes like the ones I first introduced around 30
years ago. However I managed to do it without needing the "_"; just a space:
 
5 km
6 m
7 mm
 
(These ones represented 5000000.0, 6000.0 and 7.0. Actually, at the time
I didn't even need the space, and could write 5mm, but know I require it.)
 
This was achieved without the km, m, mm etc infringing on any other
name-spaces (they can still be used as identifiers).
 
The degree one could also be written as:
 
90°
 
In my scheme, these were just suffixes for numeric constants that
applied a scale-factor; they didn't result in any new user-type, or
prevent units being mixed (a full treatment requires a language like
Frink (frinklang.org)).
 
Creating true new literal types for user-defined types, even if limited
to numeric types, is difficult. But probably not as difficult as that
C++ link is making it.
Daniel <danielaparker@gmail.com>: Dec 16 06:53PM -0800

On Monday, December 16, 2019 at 7:44:38 AM UTC-5, James Kuyper wrote:
> optional - but per 7.20.1p4, the relevant identifiers cannot be used for
> any conflicting purpose by the implementation - and that is the sense in
> which I say that it has been standardized.
 
Thanks, appreciate the references.
 
Daniel
James Kuyper <jameskuyper@alumni.caltech.edu>: Dec 16 10:40PM -0500

On 12/16/19 10:32 AM, David Brown wrote:
...> I suspect that at the time, no one really thought about the possibility
> of 128-bit integers. After all, 64-bit integers were new, and 64 bits
> should be enough for anybody!
I can assure you that the possibility of people wanting, and
implementations providing, 128 bit integers was fairly heavily discussed
during the lead-up to C99's approval. If there had been an implicit
belief that there would never be any types larger than int64_t, there'd
have been no point in specifying intmax_t - int64_t would have served
the purpose that intmax_t was designed to serve.
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Dec 16 07:42PM -0800

On 12/16/2019 8:54 AM, Robert Wessel wrote:
 
> Personally I think both 128-bit types and arbitrary precision
> arithmetic should be part of the language (whether in the language
> proper or the library).
 
I would not object to C/C++ supporting a standard bignum lib.
Ben Bacarisse <ben.usenet@bsb.me.uk>: Dec 17 04:07AM


> gcc supports 128-bit types even with "-std=c11 -pedantic" (or other C
> or C++ standards), but requires "__extension__" to avoid a warning:
 
> __extension__ typedef __int128 int128;
 
Right, but that amounts to something very similar. It's not standard C.
 
 
> __int128 is a gcc extension, and is treated as an "integer scalar
> type", but it is /not/ an "extended integer type" as defined by the C
> standards. That applies whether you are in conforming modes or not.
 
If you need __extension__ or a non-conforming mode I don't see that it
matters what gcc calls it.
 
Is it your contention that gcc /could/ provide __int128 in conforming
mode (with no extra syntax) and, just by declaring it so, not have it be
considered and extended integer type? You may be right about that, but
then what is the __extension__ there for? gcc could do without it,
declare __int128 not an extended type, and all would be fine.
 
> """
> GCC does not support any extended integer types.
> """
 
I can see how they can say that! There are none in conforming mode
without a special extension, and in other modes the language is not C so
that can say anything they like about it! In that sense I was wrong to
say that gcc "implements extended integer types but not in conforming
mode". In non-C mode everything it's up to the gcc authors to say what
these types are called.
 
>> integer type.
 
> Yes, Keith mentioned that use, which I had not thought about (it's not
> something that turns up in my kind of coding).
 
Yes, noise on my part because I'd not refreshed the thread before
replying.
 
--
Ben.
Robert Wessel <robertwessel2@yahoo.com>: Dec 16 11:20PM -0600

On Mon, 16 Dec 2019 21:45:47 +0000, Vir Campestris
 
>32 bit numbers are quite big enough for my financial needs, and the
>world GDP is only about 40 bits (in USD). What currency work have you
>done where 64 bit currency wasn't enough?
 
 
Currency calculations are often performed in pennies or mills for
dollars, sometimes even with finer divisions. Exxon's revenue, for
example, requires 45 bits to store in pennies. Even global GDP in
dollars requires 47 bits (about 85 *trillion* dollars). Toss in some
of the badly inflated currencies, and things get worse (before it was
reformed, the Turkish Lira was my go-to example - a less dramatic
current example is the Iranian Rial, worth less than a thousandth of a
penny each).
 
That being said, it's not that 64-bit type are inadequate for stored
formats - for the most part they are. Cobol, where if nothing else,
they care about handling currency, for decades only required 18
decimal* digits for stored formats, although the more recent standards
have doubled that. Some folks have recommended IEEE doubles as a
storage format, as that nets you about 53 bits - that's tight for
not-that-crazy scenarios (global GDP in pennies) - and that not an
attempt to actually store currency in floats (which tends to be
*really* problematic) - just to use a double as a fairly wide integer.
 
In any event, 64 bits are usually enough to store currency related
values. The problem is intermediate results. Multiply Exxon's
revenue by a couple of percentages, and you'll overflow a 64-bit
number (even with fairly "short" percentages - tell that you some
states that have five digit percentages in their tax rates). So
currency calculations really require something bigger than a 64-bit
intermediate, in order to compute the exact (correctly rounded)
result, since people get funny when you lop off bits of their bank
balance. Again, Cobol usually requires longer intermediates in order
to produce exact results (and they've understood that since about
1959).
 
32-bit numbers aren't actually good enough to manage *your* bank
account - interest rates are commonly four digits, factor in pennies,
and the bank's calculations for your account goes tilt at less than
$4300. Again, it might be adequate for *storing* your bank balance
(how many of us actually have more than $42 million in an account?),
but the bank needs to perform operations on those balances.
 
 
 
 
*Regardless of the actual stored representation, binary, decimal, or
something else. In binary 18 decimal digits happens to fit neatly in
a 64-bit int.
Robert Wessel <robertwessel2@yahoo.com>: Dec 16 11:23PM -0600

On Mon, 16 Dec 2019 10:47:41 -0800, Keith Thompson
>given the difficulty (and questionable usefulness) of providing
>them on small embedded systems. Note that gcc supports __int128,
>but not on all targets.
 
 
I don't really buy it. On systems that small, the operations would
almost certainly be RTL functions. If you don't define any large
types, those routes won't get linked. The way floats are handled on
many small systems is a parallel. And the RTL functions for the basic
operations aren't actually going to be that large.
"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>: Dec 16 10:06PM -0800

On 12/16/2019 1:45 PM, Vir Campestris wrote:
 
> I started in PCs when a pointer and an int were both 16 bit, and people
> misused int. A few years later they were both 32 bit... now they're
> generally a different size, and _still_ I see int x = sizeof(...)
 
64 bits are not even close to what is needed to take a very deep zoom of
a fractal.
Keith Thompson <Keith.S.Thompson+u@gmail.com>: Dec 16 10:23PM -0800

David Brown <david.brown@hesbynett.no> writes:
[...]
> 128-bit integer types without increasing intmax_t. I don't think
> there would be a need to make them mandatory - compilers would support
> them where they are practical and useful.
 
I'd greatly prefer to see the *existing* standard way to have 128-bit
integer types *along with* a redefinition of intmax_t as appropriate.
 
Because **that's what intmax_t means**.
 
I know that ABIs and existing libraries make that difficult, but
understanding the reasons does not lessen my annoyance.
 
On the other hand, 64 bits really are enough to count just about
anything. For example, we're not going to see files bigger than
2**64 bytes any time soon. Some standardized way of handling huge
integer-like entities without calling them "integer types" would
probably give us most of the benefits of 128-bit integer types,
and C++ has enough features that it's feasible to do that in the
library rather than in the language.
 
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
[Note updated email address]
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */
Keith Thompson <Keith.S.Thompson+u@gmail.com>: Dec 16 10:29PM -0800

Ben Bacarisse <ben.usenet@bsb.me.uk> writes:
[...]
> intmax_t is useful, in part because it solves the printf problem. You
> can portably print any integer i using
 
> printf("%ld\n", (intmax_t)i);
 
You mean "%jd\n".
 
> whether i is an extended type like __int128 or even some weird 99-bit
> integer type.
 
To be completely sure, you need to use either intmax_t or uintmax_t
depending on whether the argument is signed or unsigned. If you
have a name for the type, you can do something like
 
big_type i = some_value;
if ((big_type)-1 > (big_type)0) {
printf("%ju\n", (uintmax_t)i);
}
else {
printf("%jd\n", (intmax_t)i);
}
 
But quite often you'll know from context whether the type is signed or
unsigned, even if you don't know which type it is.
 
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
[Note updated email address]
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */
David Brown <david.brown@hesbynett.no>: Dec 17 09:31AM +0100

On 17/12/2019 07:23, Keith Thompson wrote:
>> them where they are practical and useful.
 
> I'd greatly prefer to see the *existing* standard way to have 128-bit
> integer types *along with* a redefinition of intmax_t as appropriate.
 
I'd be fine with that too.
 
> Because **that's what intmax_t means**.
 
> I know that ABIs and existing libraries make that difficult, but
> understanding the reasons does not lessen my annoyance.
 
Fair enough.
 
 
It is certainly easy to see that mistakes were made in the way intmax_t
has been handled (without necessarily doing the blamestorming) and that
this has restricted the way possibilities for bigger standard integer
types in C and C++.
 
The question is, where is it possible to go from here? If it is too
late to fix maxint_t usage, then we must accept that maxint_t is
effectively long long int, and 64-bit on modern "big" processors (as
distinct from small embedded devices). Is it possible to get something
that works at least as well as gcc's __int128 today, but can be
supported with the same name in other compilers, along with appropriate
limit macros (and C++ equivalents) ?
 
 
Also, while it could be nice to have a 128-bit type and make maxint_t
use this, I think that would limit the possibilities of 256-bit or
512-bit types in the future. (I am not sure what the usage of these
would be - perhaps for sha512 checksums - but let's avoid saying that
128 bits should be big enough for anyone.) If a compiler has int128_t,
int256_t and int512_t, do we really want intmax_t to be 512 bits? Do we
want to have to use 512 bit arithmetic with imaxdiv when we actually
want to divide 128 bit numbers?
 
I think a better solution would be to phase out intmax_t entirely, and
move to an explicit sized system. Have printf support explicit sizes
for the integers, rather than an endless series of arbitrary letters or
a single inefficient huge size. Have the functions named "abs32",
"abs64", etc., rather than "imaxabs", and with a type-generic version.
 
> probably give us most of the benefits of 128-bit integer types,
> and C++ has enough features that it's feasible to do that in the
> library rather than in the language.
 
That's it, yes. For C++, a standard library should be practical - with
the size being a template parameter. For C, it would need to be part of
the language. But if we had a new term rather than "integer type", the
intmax_t problem could be circumvented.
Jorgen Grahn <grahn+nntp@snipabacken.se>: Dec 17 09:14AM

> On Sun, 15 Dec 2019 15:41:18 -0800 (PST)
> =?UTF-8?B?w5bDtiBUaWli?= <ootiib@hot.ee> wrote:
>>On Monday, 16 December 2019 01:28:14 UTC+2, Melzzzzz wrote:
...
 
> Optional and variant are both solutions looking for a problem. Just
> more noise added to the language to keep a tiny number of purists
> happy.
 
As far as I can tell, they're useful for solving some kinds of
problems in a specific way -- but not all programs need them.
 
To have a concrete example, optional<T> is good for representing "zero
or one" and is an alternative to conventions like
 
- "zero means absent"
- "-1 means absent"
- "default-constructed means absent"
- "T::invalid() means absent"
- keeping T by pointer, just to get "nullptr means absent"
 
This way you don't have to complicate T itself; it doesn't have to
be aware of its own possible absense.
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
boltar@nowhere.co.uk: Dec 17 09:37AM

On Mon, 16 Dec 2019 10:21:20 -0800 (PST)
>noise
>> added to the language to keep a tiny number of purists happy.
 
>Nonsense. The problems are usual. Performance and reliability. Union is
 
Rubbish. Optional is just a lazy inefficient way of checking valid return
object values. Any decently designed class thats going to have many instances
thrown around should have a valid flag or some other marker showing whether it
can be used so optional not required. And if you're dealing with pointers just
return NULL.
 
>rather good performance optimization in decent hands, variant is a easy
>to use reliable union, and optional is a variant between value and
 
Non POD types should never be unioned unless memory space is so critical that
there is no other option. In which case why are you using C++ in the first
place? And a standard union is fine for PODs and in all sane use cases for
a union you HAVE to know what types you're dealing with as you're probably
dealing with very low level operations so leaving it to the compiler makes
no sense.
 
>nothing. So "purist" who can wield such trivial tools typically
>wins such a sorry "latitudinarians" who can't.
 
Uh huh.
boltar@nowhere.co.uk: Dec 17 09:38AM

On Mon, 16 Dec 2019 21:13:18 +0000
>noise
>> added to the language to keep a tiny number of purists happy.
 
>Wrong! You really are an ignorant twit.
 
Oh hello. Is playtime over already?
Paavo Helde <myfirstname@osa.pri.ee>: Dec 17 03:13PM +0200


> Non POD types should never be unioned unless memory space is so critical that
> there is no other option.
 
What? Trying to start another Luddite upraise or something?
 
> In which case why are you using C++ in the first
> place?
 
To have non-POD types, obviously! And for speed, of course.
 
> a union you HAVE to know what types you're dealing with as you're probably
> dealing with very low level operations so leaving it to the compiler makes
> no sense.
 
Of course I have to know which type is active in an union. This is not
specific to POD or non-POD. And one can still use a simple integer
discriminator tag and switch() on it at will, no need to use heavy
templating a la std::variant if it does not suit the task.
David Brown <david.brown@hesbynett.no>: Dec 17 02:51PM +0100

On 17/12/2019 02:06, Bart wrote:
 
> "1-4) user-defined integer literals, such as 12_km"
> "5-6) user-defined floating-point literals, such as 0.5_Pa"
 
> "double x = 90.0_deg;"
 
The real benefit of these is when you can write:
 
distance x = 2210_m;
distance y = 3_km;
time t = 300_sec;
 
and then you c compile-time error when you try:
 
speed v = (x + t) + y;
 
but are allowed to write:
 
seed v = (x + y) / t;
 
 
> name-spaces (they can still be used as identifiers).
 
> The degree one could also be written as:
 
>  90°
 
Unicode symbols sound nice, until you have to distinguish between 90°
and 90˚ or 90⁰, or between 90℃ and 90°C. And it looks great being able
to write π = 3.14 and y = x², until the next programmer is using Windows
instead of *nix and can't type those symbols without a character map applet.
 
 
> Creating true new literal types for user-defined types, even if limited
> to numeric types, is difficult. But probably not as difficult as that
> C++ link is making it.
 
Nah, it's easy in C++.
 
And it's the user-defined types that are the real feature here.
Otherwise, it's almost nothing more than you could have in C with:
 
#define km *1000.0
#define m *1.0
#define mm *0.001
 
double x = 5 km;
double y = 5 mm;
 
Your language apparently lets you make these context sensitive in some
way, which is nice.
David Brown <david.brown@hesbynett.no>: Dec 17 03:00PM +0100

On 17/12/2019 05:07, Ben Bacarisse wrote:
>> standards. That applies whether you are in conforming modes or not.
 
> If you need __extension__ or a non-conforming mode I don't see that it
> matters what gcc calls it.
 
It doesn't really matter what /we/ call it - it matters what /gcc/ calls
it. And they say it is not an extended integer type, regardless of the
compiler flags, precisely because they can't have an extended integer
type that is bigger than maxint_t.
 
> Is it your contention that gcc /could/ provide __int128 in conforming
> mode (with no extra syntax) and, just by declaring it so, not have it be
> considered and extended integer type?
 
Yes.
 
__int128 is in a reserved namespace - they can put whatever types they
want there, even in conforming modes. They can't make an "extended
integer type" that is bigger than maxint_t while remaining conforming,
and it would be ridiculous to say it is an extended integer type with
"-std=gnu11" and a different name (but identical functionality) with
"-std=c11".
 
It is an implementation-specific type that handles 128-bit integers, but
it is not an "integer type" as defined by the C standards.
 
> You may be right about that, but
> then what is the __extension__ there for? gcc could do without it,
> declare __int128 not an extended type, and all would be fine.
 
It could, yes. You only need the "__extension__" marker if you are
specifying "-pedantic", and even then it is just to avoid getting a
warning. __int128 is supported in the most standards-compliant and
pedantic warning modes gcc has. But the "-pedantic" warnings don't just
ensure that gcc emits all required diagnostics, it also gives warnings
on gcc extensions that would limit portability another compilers.
"__extensions__" tells the compiler that you know this thing is a gcc
extension, and you know you asked for warnings about gcc-specific
features, but you want to hide the warning in this particular case.
 
>> something that turns up in my kind of coding).
 
> Yes, noise on my part because I'd not refreshed the thread before
> replying.
 
No problem - it is useful to know that such uses are not just a
peculiarity of a single person.
boltar@nowhere.co.uk: Dec 17 02:12PM

On Tue, 17 Dec 2019 15:13:14 +0200
 
>> In which case why are you using C++ in the first
>> place?
 
>To have non-POD types, obviously! And for speed, of course.
 
You've never done any embedded development have you.
 
No, thats not a question.
Ben Bacarisse <ben.usenet@bsb.me.uk>: Dec 17 02:44PM

>> David Brown <david.brown@hesbynett.no> writes:
 
>>> On 16/12/2019 21:45, Ben Bacarisse wrote:
>>>> David Brown <david.brown@hesbynett.no> writes:
<cut>
> "-std=c11".
 
> It is an implementation-specific type that handles 128-bit integers, but
> it is not an "integer type" as defined by the C standards.
 
(I think you mean "signed integer type" -- the C standard does not
define the term "integer type" as far as I can see.)
 
The only way that it can not be a signed integer type is by a decree
from gcc. I am not saying this is wrong -- maybe that was the intent of
the committee -- but then I'm not sure why gcc uses the __extension__
keyword. Maybe, as you say below, that's all about managing diagnostics
for portability.
 
>> then what is the __extension__ there for? gcc could do without it,
>> declare __int128 not an extended type, and all would be fine.
 
> It could, yes.
 
And it turns out clang decided to do just that. __int128 is there in
conforming modes, but sizeof (intmax_t) is 8. Presumably they too have
decreed that __int128 is not a signed integer type, despite meeting all
the technical requirements to be one!
 
<cut>
--
Ben.
David Brown <david.brown@hesbynett.no>: Dec 17 03:54PM +0100

On 17/12/2019 15:44, Ben Bacarisse wrote:
>> it is not an "integer type" as defined by the C standards.
 
> (I think you mean "signed integer type" -- the C standard does not
> define the term "integer type" as far as I can see.)
 
It does (C11 6.2.5p17) - "integer types" cover "char, the signed and
unsigned integer types, and the enumerated types". The "signed integer
types" covers the "standard signed integer types" and "extended signed
integer types".
 
> conforming modes, but sizeof (intmax_t) is 8. Presumably they too have
> decreed that __int128 is not a signed integer type, despite meeting all
> the technical requirements to be one!
 
__int128 meets almost all the technical requirements to be a signed
integer type - the only missing one is the classification, as that would
mean maxint_t would have to be (at least) 128 bits.
 
It is a strange situation indeed.
Ben Bacarisse <ben.usenet@bsb.me.uk>: Dec 17 03:52PM


> On 17/12/2019 15:44, Ben Bacarisse wrote:
>> David Brown <david.brown@hesbynett.no> writes:
<cut>
> unsigned integer types, and the enumerated types". The "signed integer
> types" covers the "standard signed integer types" and "extended signed
> integer types".
 
So it does. Thanks.
 
--
Ben.
"Öö Tiib" <ootiib@hot.ee>: Dec 17 08:32AM -0800

> object values. Any decently designed class thats going to have many instances
> thrown around should have a valid flag or some other marker showing whether it
> can be used so optional not required.
 
"Invalid"/"Incomplete"/"Half-received"/"Erred" states of objects are the common
source of errors. You are rare fan of iostreams failbit-badbit garbage it seems?

> And if you're dealing with pointers just
> return NULL.
 
Per-object dynamic memory management is common source of inefficiency.
 
 
> Non POD types should never be unioned unless memory space is so critical that
> there is no other option. In which case why are you using C++ in the first
> place?
 
Because C++ is often more efficient than alternatives and can union non-pod
types in variant. If C++ can't do it then there are no chance to do better job
with your Perl ... or what you program there.
 
> a union you HAVE to know what types you're dealing with as you're probably
> dealing with very low level operations so leaving it to the compiler makes
> no sense.
 
PODs are useful only for dealing with those low level operations. Most
embedded controllers have tens of kilobytes of RAM (since it just costs
nothing) and so are often expected to be quite smart these days.
 
Paavo Helde <myfirstname@osa.pri.ee>: Dec 17 07:35PM +0200

>>> place?
 
>> To have non-POD types, obviously! And for speed, of course.
 
> You've never done any embedded development have you.
 
Ah, trying to change the topic and ad hominem in a single line. Well done!
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Dec 17 05:50PM

On 17/12/2019 09:14, Jorgen Grahn wrote:
> - keeping T by pointer, just to get "nullptr means absent"
 
> This way you don't have to complicate T itself; it doesn't have to
> be aware of its own possible absense.
 
Why are you trying to teach a brick wall something? He is an obtuse fucktarded troll, nothing more.
 
/Flibble
 
--
"Snakes didn't evolve, instead talking snakes with legs changed into snakes." - Rick C. Hodgin
 
"You won't burn in hell. But be nice anyway." – Ricky Gervais
 
"I see Atheists are fighting and killing each other again, over who doesn't believe in any God the most. Oh, no..wait.. that never happens." – Ricky Gervais
 
"Suppose it's all true, and you walk up to the pearly gates, and are confronted by God," Byrne asked on his show The Meaning of Life. "What will Stephen Fry say to him, her, or it?"
"I'd say, bone cancer in children? What's that about?" Fry replied.
"How dare you? How dare you create a world to which there is such misery that is not our fault. It's not right, it's utterly, utterly evil."
"Why should I respect a capricious, mean-minded, stupid God who creates a world that is so full of injustice and pain. That's what I would say."
Keith Thompson <Keith.S.Thompson+u@gmail.com>: Dec 17 11:51AM -0800

David Brown <david.brown@hesbynett.no> writes:
[...]
> __int128 meets almost all the technical requirements to be a signed
> integer type - the only missing one is the classification, as that would
> mean maxint_t would have to be (at least) 128 bits.
 
It doesn't meet *all* the requirements. N1570 6.4.4.1p6 (Integer
constants):
 
If an integer constant cannot be represented by any type in its
list, it may have an extended integer type, if the extended integer
type can represent its value.
 
In gcc, there are no constants of type __int128.
 
(The word "may" is a bit ambiguous, and it could be argued that an
implementation isn't required to support constants of type int128_t
even if it's an extended integer type.)
 
--
Keith Thompson (The_Other_Keith) Keith.S.Thompson+u@gmail.com
[Note updated email address]
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */
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: