Sunday, June 30, 2019

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

G G <gdotone@gmail.com>: Jun 30 04:16PM -0700

casting:
 
double ( a_value ) or (double) a_value
 
vs.
 
static_cast<double>( a_value ) /* c++ 11 + */
Horizon68 <horizon@horizon.com>: Jun 30 01:26PM -0700

Hello,
 
Read this:
 
 
Read again, i correct a typo because i write fast...
 
More about computing and parallel computing..
 
The important guaranties of Memory Safety in Rust are:
 
1- No Null Pointer Dereferences
2- No Dangling Pointers
3- No Buffer Overruns
 
I think i have solved Null Pointer Dereferences and also solved Dangling
Pointers and also solved memory leaks for Delphi and Freepascal by
inventing my "scalable" reference counting with efficient support for
weak references and i have implemented it in Delphi and Freepascal, and
reference counting in Rust and C++ is "not" scalable.
 
About the (3) above that is Buffer Overruns, read here about Delphi
and Freepascal:
 
What's a buffer overflow and how to avoid it in Delphi?
 
http://delphi.cjcsoft.net/viewthread.php?tid=49495
 
 
About Deadlock and Race conditions in Delphi and Freepascal:
 
I have ported DelphiConcurrent to Freepascal, and i have
also extended them with the support of my scalable RWLocks for Windows
and Linux and with the support of my scalable lock called MLock for
Windows and Linux and i have also added the support for a Mutex for
Windows and Linux, please look inside the DelphiConcurrent.pas and
FreepascalConcurrent.pas files inside the zip file to understand more.
 
You can download DelphiConcurrent and FreepascalConcurrent for Delphi
and Freepascal from:
 
https://sites.google.com/site/scalable68/delphiconcurrent-and-freepascalconcurrent
 
DelphiConcurrent and FreepascalConcurrent by Moualek Adlene is a new way
to build Delphi applications which involve parallel executed code based
on threads like application servers. DelphiConcurrent provides to the
programmers the internal mechanisms to write safer multi-thread code
while taking a special care of performance and genericity.
 
In concurrent applications a DEADLOCK may occurs when two threads or
more try to lock two consecutive shared resources or more but in a
different order. With DelphiConcurrent and FreepascalConcurrent, a
DEADLOCK is detected and automatically skipped - before he occurs - and
the programmer has an explicit exception describing the multi-thread
problem instead of a blocking DEADLOCK which freeze the application with
no output log (and perhaps also the linked clients sessions if we talk
about an application server).
 
Amine Moulay Ramdane has extended them with the support of his scalable
RWLocks for Windows and Linux and with the support of his scalable lock
called MLock for Windows and Linux and he has also added the support for
a Mutex for Windows and Linux, please look inside the
DelphiConcurrent.pas and FreepascalConcurrent.pas files to understand more.
 
And please read the html file inside to learn more how to use it.
 
 
About race conditions now:
 
My scalable Adder is here..
 
As you have noticed i have just posted previously my modified versions
of DelphiConcurrent and FreepascalConcurrent to deal with deadlocks in
parallel programs.
 
But i have just read the following about how to avoid race conditions in
Parallel programming in most cases..
 
Here it is:
 
https://vitaliburkov.wordpress.com/2011/10/28/parallel-programming-with-delphi-part-ii-resolving-race-conditions/
 
This is why i have invented my following powerful scalable Adder to help
you do the same as the above, please take a look at its source code to
understand more, here it is:
 
https://sites.google.com/site/scalable68/scalable-adder-for-delphi-and-freepascal
 
Other than that, about composability of lock-based systems now:
 
Design your systems to be composable. Among the more galling claims of
the detractors of lock-based systems is the notion that they are somehow
uncomposable: "Locks and condition variables do not support modular
programming," reads one typically brazen claim, "building large programs
by gluing together smaller programs[:] locks make this impossible."9 The
claim, of course, is incorrect. For evidence one need only point at the
composition of lock-based systems such as databases and operating
systems into larger systems that remain entirely unaware of lower-level
locking.
 
There are two ways to make lock-based systems completely composable, and
each has its own place. First (and most obviously), one can make locking
entirely internal to the subsystem. For example, in concurrent operating
systems, control never returns to user level with in-kernel locks held;
the locks used to implement the system itself are entirely behind the
system call interface that constitutes the interface to the system. More
generally, this model can work whenever a crisp interface exists between
software components: as long as control flow is never returned to the
caller with locks held, the subsystem will remain composable.
 
Second (and perhaps counterintuitively), one can achieve concurrency and
composability by having no locks whatsoever. In this case, there must be
no global subsystem state—subsystem state must be captured in
per-instance state, and it must be up to consumers of the subsystem to
assure that they do not access their instance in parallel. By leaving
locking up to the client of the subsystem, the subsystem itself can be
used concurrently by different subsystems and in different contexts. A
concrete example of this is the AVL tree implementation used extensively
in the Solaris kernel. As with any balanced binary tree, the
implementation is sufficiently complex to merit componentization, but by
not having any global state, the implementation may be used concurrently
by disjoint subsystems—the only constraint is that manipulation of a
single AVL tree instance must be serialized.
 
Read more here:
 
https://queue.acm.org/detail.cfm?id=1454462
 
And about Message Passing Process Communication Model and Shared Memory
Process Communication Model:
 
An advantage of shared memory model is that memory communication is
faster as compared to the message passing model on the same machine.
 
However, shared memory model may create problems such as synchronization
and memory protection that need to be addressed.
 
Message passing's major flaw is the inversion of control–it is a moral
equivalent of gotos in un-structured programming (it's about time
somebody said that message passing is considered harmful).
 
Also some research shows that the total effort to write an MPI
application is significantly higher than that required to write a
shared-memory version of it.
 
And more about my scalable reference counting with efficient support
for weak references:
 
My invention that is my scalable reference counting with efficient
support for weak references version 1.35 is here..
 
Here i am again, i have just updated my scalable reference counting with
efficient support for weak references to version 1.35, I have just added
a TAMInterfacedPersistent that is a scalable reference counted version,
and now i think i have just made it complete and powerful.
 
Because I have just read the following web page:
 
https://www.codeproject.com/Articles/1252175/Fixing-Delphis-Interface-Limitations
 
But i don't agree with the writting of the guy of the above web page,
because i think you have to understand the "spirit" of Delphi, here is why:
 
A component is supposed to be owned and destroyed by something else,
"typically" a form (and "typically" means in english: in "most" cases,
and this is the most important thing to understand). In that scenario,
reference count is not used.
 
If you pass a component as an interface reference, it would be very
unfortunate if it was destroyed when the method returns.
 
Therefore, reference counting in TComponent has been removed.
 
Also because i have just added TAMInterfacedPersistent to my invention.
 
To use scalable reference counting with Delphi and FreePascal, just
replace TInterfacedObject with my TAMInterfacedObject that is the
scalable reference counted version, and just replace
TInterfacedPersistent with my TAMInterfacedPersistent that is the
scalable reference counted version, and you will find both my
TAMInterfacedObject and my TAMInterfacedPersistent inside the
AMInterfacedObject.pas file, and to know how to use weak references
please take a look at the demo that i have included called example.dpr
and look inside my zip file at the tutorial about weak references, and
to know how to use delegation take a look at the demo that i have
included called test_delegation.pas, and take a look inside my zip file
at the tutorial about delegation that learns you how to use delegation.
 
I think my Scalable reference counting with efficient support for weak
references is stable and fast, and it works on both Windows and Linux,
and my scalable reference counting scales on multicore and NUMA systems,
and you will not find it in C++ or Rust, and i don't think you will find
it anywhere, and you have to know that this invention of mine solves
the problem of dangling pointers and it solves the problem of memory
leaks and my scalable reference counting is "scalable".
 
And please read the readme file inside the zip file that i have just
extended to make you understand more.
 
You can download my new scalable reference counting with efficient
support for weak references version 1.35 from:
 
https://sites.google.com/site/scalable68/scalable-reference-counting-with-efficient-support-for-weak-references
 
 
Thank you,
Amine Moulay Ramdane.
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Jun 30 10:09PM +0100

On 30/06/2019 21:26, Horizon68 wrote:
> Hello,
 
> Read this:
 
> Read again, i correct a typo because i write fast...
 
Why would we read it again you demented loon?
 
/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," Bryne 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."
Jorgen Grahn <grahn+nntp@snipabacken.se>: Jun 30 05:58AM

On Sat, 2019-06-29, G G wrote:
 
[Attribution missing; I think David Brown wrote this]
 
> the code. But to ensure I'm not taking undue credit, the code is from a CERT
> website, www.securecoding.cert.org from a search INT32-CPP.
> At that site, they show many other concerns and suggestions how to mitigate.
 
I'm sure his advice was for you, me, and everyone, including the CERT
people. There are different schools of thought here, and has been for
as long as I can remember.
 
BTW, the code left out the most interesting part. It said:
 
/* Handle error */
 
If aborting isn't an option, it's really hard to fill in that part of
the function, and it's often impossible to get test coverage for it
in a full system test.
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
G G <gdotone@gmail.com>: Jun 30 02:43AM -0700


> I'm sure his advice was for you, me, and everyone, including the CERT
> people.
 
I'm sure too.
I thank him, you, and everyone who helps me learn.
"Chris M. Thomasson" <invalid_chris_thomasson_invalid@invalid.com>: Jun 30 03:00AM -0700

On 6/28/2019 7:46 PM, G G wrote:
 
> are these checks still necessary or is there another way?
[...]
 
Its been a while since I read the following, cannot remember if it goes
into overflows:
 
http://www.stroustrup.com/JSF-AV-rules.pdf
"Öö Tiib" <ootiib@hot.ee>: Jun 30 07:19AM -0700

On Saturday, 29 June 2019 05:46:54 UTC+3, G G wrote:
> are these checks still necessary or is there another way?
 
> https://wiki.sei.cmu.edu/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow
 
Yes, quarter of possible signed addition or subtraction
operations are undefined behavior by standard.
 
There may be are non-standard compiler intrinsics that
help us to deal with overflows more simply or we can use
a type for result where every resulting value fits.
 
For example we can detect if distance between every two
signed longs fits into unsigned long with a compile-time
check:
 
static_assert(ULONG_MAX/2 >= LONG_MAX);
 
So we can luckily write a distance function that can never
fail if it compiles:
 
#include <iostream>
#include <limits.h>
 
unsigned long distance(long x, long y)
{
static_assert(ULONG_MAX/2 >= LONG_MAX);
return (x > y) ? (unsigned long)x - (unsigned long)y
: (unsigned long)y - (unsigned long)x;
}
 
int main()
{
std::cout << "Distance between 3 and -42 is "
<< distance(3, -42) << std::endl;
}
 
I prefer to use int64_t and uint64_t that guarantee that
UINT64_MAX/2 >= INT64_MAX so I don't need that
static_assert.

However quite common is that meaningful limits for a
number are rather different from what the integer type
of processor has.
 
For example we need to have variable that represents
reasonably reachable temperatures with accuracy of
one centi degree of Celsius.
 
The int32_t that we might want to use has range
-2147483648 to 2147483647 so most of that range will
be erroneous values.
 
Absolute zero is −273.15°C, can't go below that.
Temperatures within stars can reach millions of degrees
(thanks to pressure) but at surface of Sun we have "only"
5505°C. Therefore we should check limits like
-27315 to 600000 (far under INT32_MIN and INT32_MAX)
to figure if our values are outside of sanity limits or not.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jun 30 04:44PM +0200

On 30.06.2019 16:19, Öö Tiib wrote:
> signed longs fits into unsigned long with a compile-time
> check:
 
> static_assert(ULONG_MAX/2 >= LONG_MAX);
 
Will always be true for two's complement form, by definition. floor(
(2^n)-1)/2 ) = floor( 2^(n-1) - 1/2 ) = 2^(n-1)-1, which is LONG_MAX.
 
 
> return (x > y) ? (unsigned long)x - (unsigned long)y
> : (unsigned long)y - (unsigned long)x;
> }
 
Yes, but the assertion isn't necessary. ;-)
 
The distance between two numbers in a 2^n range can never be 2^n or higher.
 
 
> 5505°C. Therefore we should check limits like
> -27315 to 600000 (far under INT32_MIN and INT32_MAX)
> to figure if our values are outside of sanity limits or not.
 
And always think of Ariane 5.
 
 
Cheers!,
 
- Alf
"Öö Tiib" <ootiib@hot.ee>: Jun 30 08:18AM -0700

On Sunday, 30 June 2019 17:44:53 UTC+3, Alf P. Steinbach wrote:
 
> > static_assert(ULONG_MAX/2 >= LONG_MAX);
 
> Will always be true for two's complement form, by definition. floor(
> (2^n)-1)/2 ) = floor( 2^(n-1) - 1/2 ) = 2^(n-1)-1, which is LONG_MAX.
 
Yes but two's complement is not guaranteed for long.
Basically if we assume two's complement then we better
use types that guarantee it like I said later:

> > UINT64_MAX/2 >= INT64_MAX so I don't need that
> > static_assert.
 
> And always think of Ariane 5.
 
You mean partially failed launch 25 January 2018? I
wasn't involved. :D Incorrect value in specifications.
That is hard to avoid in practice because infallible and
omnipotent humans are impossible to hire for whatever
money.
 
For example if to take and to let three separate teams to
write same software and then let the resulting programs to
vote each decision ... if the specs were defective then
these would likely suggest same, incorrect decision
unanimously.
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jun 30 06:22PM +0200

On 30.06.2019 17:18, Öö Tiib wrote:
 
>> Will always be true for two's complement form, by definition. floor(
>> (2^n)-1)/2 ) = floor( 2^(n-1) - 1/2 ) = 2^(n-1)-1, which is LONG_MAX.
 
> Yes but two's complement is not guaranteed for long.
 
Oh it is.
 
No extant compiler uses anything else, and next year you get it
guaranteed from the standard too.
 
 
> vote each decision ... if the specs were defective then
> these would likely suggest same, incorrect decision
> unanimously.
 
Cheers!
 
- Alf
David Brown <david.brown@hesbynett.no>: Jun 30 10:22PM +0200

On 30/06/2019 01:02, G G wrote:
> the code. But to ensure I'm not taking undue credit, the code is from a CERT
> website, www.securecoding.cert.org from a search INT32-CPP.
> At that site, they show many other concerns and suggestions how to mitigate.
 
Yes, I meant "you" in general, not just you personally.
 
I've seen that page. The sample code is silly and pointless, because it
solves a problem that doesn't exist while failing to address the problem
that /does/ exist.
 
Overflows (including unsigned overflows, which are also usually errors)
occur because people don't do a good enough job of checking data coming
in from outside, and don't check that their calculations will work over
the full range of the data they are using. Checking specifically over
the range of "int" is pointless.
David Brown <david.brown@hesbynett.no>: Jun 30 10:24PM +0200

On 30/06/2019 11:43, G G wrote:
>> people.
 
> I'm sure too.
> I thank him, you, and everyone who helps me learn.
 
(/Please/ use appropriate attributions. Even if you have to use the
appalling google groups interface instead of a proper newsreader and
newsserver, you should make the effort to keep attributions.)
David Brown <david.brown@hesbynett.no>: Jun 30 10:25PM +0200

On 30/06/2019 07:58, Jorgen Grahn wrote:
> the function, and it's often impossible to get test coverage for it
> in a full system test.NoNoNo
 
> /Jorgen
 
That is a very important point - thanks for bringing it up. You (yous,
or y'all) should not include code that can't be tested.
Horizon68 <horizon@horizon.com>: Jun 30 12:05PM -0700

Hello..
 
 
More about computing and parallel computing..
 
The important guaranties of Memory Safety in Rust are:
 
1- No Null Pointer Dereferences
2- No Dangling Pointers
3- No Buffer Overruns
 
I think i have solved Pointer Dereferences and also solved Dangling
Pointers and also solved memory leaks for Delphi and Freepascal by
inventing my "scalable" reference counting with efficient support for
weak references and i have implemented it in Delphi and Freepascal, and
reference counting in Rust and C++ is "not" scalable.
 
About the (3) above that is Buffer Overruns, read here about Delphi
and Freepascal:
 
What's a buffer overflow and how to avoid it in Delphi?
 
http://delphi.cjcsoft.net/viewthread.php?tid=49495
 
 
About Deadlock and Race conditions in Delphi and Freepascal:
 
I have ported DelphiConcurrent to Freepascal, and i have
also extended them with the support of my scalable RWLocks for Windows
and Linux and with the support of my scalable lock called MLock for
Windows and Linux and i have also added the support for a Mutex for
Windows and Linux, please look inside the DelphiConcurrent.pas and
FreepascalConcurrent.pas files inside the zip file to understand more.
 
You can download DelphiConcurrent and FreepascalConcurrent for Delphi
and Freepascal from:
 
https://sites.google.com/site/scalable68/delphiconcurrent-and-freepascalconcurrent
 
DelphiConcurrent and FreepascalConcurrent by Moualek Adlene is a new way
to build Delphi applications which involve parallel executed code based
on threads like application servers. DelphiConcurrent provides to the
programmers the internal mechanisms to write safer multi-thread code
while taking a special care of performance and genericity.
 
In concurrent applications a DEADLOCK may occurs when two threads or
more try to lock two consecutive shared resources or more but in a
different order. With DelphiConcurrent and FreepascalConcurrent, a
DEADLOCK is detected and automatically skipped - before he occurs - and
the programmer has an explicit exception describing the multi-thread
problem instead of a blocking DEADLOCK which freeze the application with
no output log (and perhaps also the linked clients sessions if we talk
about an application server).
 
Amine Moulay Ramdane has extended them with the support of his scalable
RWLocks for Windows and Linux and with the support of his scalable lock
called MLock for Windows and Linux and he has also added the support for
a Mutex for Windows and Linux, please look inside the
DelphiConcurrent.pas and FreepascalConcurrent.pas files to understand more.
 
And please read the html file inside to learn more how to use it.
 
 
About race conditions now:
 
My scalable Adder is here..
 
As you have noticed i have just posted previously my modified versions
of DelphiConcurrent and FreepascalConcurrent to deal with deadlocks in
parallel programs.
 
But i have just read the following about how to avoid race conditions in
Parallel programming in most cases..
 
Here it is:
 
https://vitaliburkov.wordpress.com/2011/10/28/parallel-programming-with-delphi-part-ii-resolving-race-conditions/
 
This is why i have invented my following powerful scalable Adder to help
you do the same as the above, please take a look at its source code to
understand more, here it is:
 
https://sites.google.com/site/scalable68/scalable-adder-for-delphi-and-freepascal
 
Other than that, about composability of lock-based systems now:
 
Design your systems to be composable. Among the more galling claims of
the detractors of lock-based systems is the notion that they are somehow
uncomposable: "Locks and condition variables do not support modular
programming," reads one typically brazen claim, "building large programs
by gluing together smaller programs[:] locks make this impossible."9 The
claim, of course, is incorrect. For evidence one need only point at the
composition of lock-based systems such as databases and operating
systems into larger systems that remain entirely unaware of lower-level
locking.
 
There are two ways to make lock-based systems completely composable, and
each has its own place. First (and most obviously), one can make locking
entirely internal to the subsystem. For example, in concurrent operating
systems, control never returns to user level with in-kernel locks held;
the locks used to implement the system itself are entirely behind the
system call interface that constitutes the interface to the system. More
generally, this model can work whenever a crisp interface exists between
software components: as long as control flow is never returned to the
caller with locks held, the subsystem will remain composable.
 
Second (and perhaps counterintuitively), one can achieve concurrency and
composability by having no locks whatsoever. In this case, there must be
no global subsystem state—subsystem state must be captured in
per-instance state, and it must be up to consumers of the subsystem to
assure that they do not access their instance in parallel. By leaving
locking up to the client of the subsystem, the subsystem itself can be
used concurrently by different subsystems and in different contexts. A
concrete example of this is the AVL tree implementation used extensively
in the Solaris kernel. As with any balanced binary tree, the
implementation is sufficiently complex to merit componentization, but by
not having any global state, the implementation may be used concurrently
by disjoint subsystems—the only constraint is that manipulation of a
single AVL tree instance must be serialized.
 
Read more here:
 
https://queue.acm.org/detail.cfm?id=1454462
 
And about Message Passing Process Communication Model and Shared Memory
Process Communication Model:
 
An advantage of shared memory model is that memory communication is
faster as compared to the message passing model on the same machine.
 
However, shared memory model may create problems such as synchronization
and memory protection that need to be addressed.
 
Message passing's major flaw is the inversion of control–it is a moral
equivalent of gotos in un-structured programming (it's about time
somebody said that message passing is considered harmful).
 
Also some research shows that the total effort to write an MPI
application is significantly higher than that required to write a
shared-memory version of it.
 
And more about my scalable reference counting with efficient support
for weak references:
 
My invention that is my scalable reference counting with efficient
support for weak references version 1.35 is here..
 
Here i am again, i have just updated my scalable reference counting with
efficient support for weak references to version 1.35, I have just added
a TAMInterfacedPersistent that is a scalable reference counted version,
and now i think i have just made it complete and powerful.
 
Because I have just read the following web page:
 
https://www.codeproject.com/Articles/1252175/Fixing-Delphis-Interface-Limitations
 
But i don't agree with the writting of the guy of the above web page,
because i think you have to understand the "spirit" of Delphi, here is why:
 
A component is supposed to be owned and destroyed by something else,
"typically" a form (and "typically" means in english: in "most" cases,
and this is the most important thing to understand). In that scenario,
reference count is not used.
 
If you pass a component as an interface reference, it would be very
unfortunate if it was destroyed when the method returns.
 
Therefore, reference counting in TComponent has been removed.
 
Also because i have just added TAMInterfacedPersistent to my invention.
 
To use scalable reference counting with Delphi and FreePascal, just
replace TInterfacedObject with my TAMInterfacedObject that is the
scalable reference counted version, and just replace
TInterfacedPersistent with my TAMInterfacedPersistent that is the
scalable reference counted version, and you will find both my
TAMInterfacedObject and my TAMInterfacedPersistent inside the
AMInterfacedObject.pas file, and to know how to use weak references
please take a look at the demo that i have included called example.dpr
and look inside my zip file at the tutorial about weak references, and
to know how to use delegation take a look at the demo that i have
included called test_delegation.pas, and take a look inside my zip file
at the tutorial about delegation that learns you how to use delegation.
 
I think my Scalable reference counting with efficient support for weak
references is stable and fast, and it works on both Windows and Linux,
and my scalable reference counting scales on multicore and NUMA systems,
and you will not find it in C++ or Rust, and i don't think you will find
it anywhere, and you have to know that this invention of mine solves
the problem of dangling pointers and it solves the problem of memory
leaks and my scalable reference counting is "scalable".
 
And please read the readme file inside the zip file that i have just
extended to make you understand more.
 
You can download my new scalable reference counting with efficient
support for weak references version 1.35 from:
 
https://sites.google.com/site/scalable68/scalable-reference-counting-with-efficient-support-for-weak-references
 
 
Thank you,
Amine Moulay Ramdane.
alexo <alelvb@inwind.it>: Jun 30 06:43PM +0200

Il 30/06/19 16:04, Stefan Ram ha scritto:
 
Hi Stefan, your parser works correctly. I checked with other formulas
{'such as
 
[Fe(CO)6][Sb2F11]2
 
1 * [ 1 * Fe + 6 * ( 1 * C + 1 * O ) ] + 2 * [ 2 * Sb + 11 * F ]
 
and
 
HRh(CO)[P[CH2CH2(CF2)5CF]3]3
 
for which the output is:
 
1 * H + 1 * Rh + 1 * ( 1 * C + 1 * O ) + 3 * [ 1 * P + 3 * [ 1 * C + 2 *
H + 1 * C + 2 * H + 5 * ( 1 * C + 2 * F ) + 1 * C + 1 * F ] ]
 
 
To say it all, the text from which I took this formula reports it as:
 
HRh(CO)[P{CH2CH2(CF2)5CF}3]3
 
i.e with another kind of parentheses '{' and '}
 
I added that to your parser.
You did a great job.
 
But to be perfect it should handle even the molecules of crystallization
that are written in this way (but I didn't talk about them in my post:
 
 
CuSO4*5H2O
 
here there are 5 molecules of H2O in the composition of the molecule.
The '*' character is the one I use because it should be used the
'central dot' character but I don't know how to type it.
 
 
 
here is your program purged by all those ::std that made the text hard
to read:
 
 
#include <cctype>
#include <iostream>
#include <istream>
#include <memory>
#include <ostream>
#include <sstream>
#include <string>
#include <vector>
 
using namespace ::std::literals;
 
using std::string;
using std::move;
using std::cout;
using std::istringstream;
 
template< typename source >struct scanner
{ source s;
 
string peek_value;
 
typename source::int_type eof { source::traits_type::eof() };
 
scanner( source && s )noexcept : s{ move( s )}, peek_value{ ""s } {}
 
scanner( scanner && s )noexcept : s{ static_cast<source&&>(s.s)},
peek_value{static_cast<string&&>(s.peek_value)} { }
 
string name( char c )
{ string result;
if( isalpha( c ))
{ int pos {};
while( isalpha( c )&&( pos == 0 || islower( c )))
{ pos = 1;
c = static_cast< char >( s.get() );
result += c;
auto const i = s.peek();
if( i == eof )return result;
c = static_cast< char >( i ); }}
return result; }
 
string number( char c )
{ string result;
if( isdigit( c ))
{ while( isdigit( c ))
{ c = static_cast< char >( s.get() );
result += c;
auto const i = s.peek();
if( i == eof )return result;
c = static_cast< char >( i ); }}
return result; }
 
string special( char c )
{ string result;
if( c == '(' || c == ')' || c == '[' || c == ']' || c == '{' || c
== '}')
{ c = static_cast< char >( s.get() );
result += c;
return result; }
return result; }
 
string do_get()
{ string result;
auto const i = s.peek();
if( i == eof )return result;
else
{ auto c { static_cast< char >( i )};
result = name( c ); if( result != ""s )return result;
result = number( c ); if( result != ""s )return result;
result = special( c ); if( result != ""s )return result;
return result; }
return result; }
 
string get()
{ if( peek_value != ""s )
{ string const result{ peek_value };
peek_value = ""s;
return result; }
else return do_get(); }
 
string peek()
{ if( peek_value == ""s )peek_value = do_get();
return peek_value; }};
 
 
struct parse_type
{ virtual string surface() const = 0;
virtual string description() const = 0;
parse_type()= default;
parse_type( const parse_type & )= default;
parse_type( parse_type && )= default;
parse_type & operator=( const parse_type & )= default;
parse_type & operator=( parse_type && )noexcept = default;
virtual ~parse_type() = default; };
 
struct primary_parse_type final : public parse_type
{ parse_type const * primary;
primary_parse_type( const primary_parse_type & )= default;
primary_parse_type& operator=(const primary_parse_type&)= default;
primary_parse_type( parse_type const * primary ):
primary{ primary } {}
string surface() const override { return primary->surface(); }
string description() const override
{ return primary->description(); }};
 
struct name_parse_type;
 
struct name_parse_type final : public parse_type
{ string surface_;
name_parse_type( string surface ):surface_{ move(surface) } {}
string surface() const override { return surface_; }
string description() const override { return surface_; }};
 
struct number_parse_type final : public parse_type
{ string surface_;
number_parse_type( string surface ):surface_{ move(surface) } {}
string surface() const override { return surface_; }
string description() const override { return "number "s + surface_; }};
 
struct product_parse_type final : public parse_type
{ string surface_;
primary_parse_type * component;
string multiplicity;
product_parse_type(const product_parse_type&)=default;
product_parse_type& operator=(const product_parse_type&)=default;
product_parse_type( string surface, primary_parse_type * component,
string multiplicity ):
surface_{ move(surface) }, component{ component }, multiplicity{
move(multiplicity) } {}
string surface() const override { return surface_; }
string description() const override { return multiplicity + " * " +
component->description(); }};
 
struct sum_parse_type final : public parse_type
{ string surface_;
::std::vector< product_parse_type >vector;
sum_parse_type( string surface, ::std::vector< product_parse_type >
vector ):
surface_{ move(surface) }, vector{ move(vector) } {}
string const plus = " + "s;
void append_surface( string const & s ){ surface_ += s; }
void append_addend( product_parse_type const & s ){ vector.push_back(
s ); }
string surface() const override { return surface_; }
string description() const override
{ string result;
bool first = true;
for( auto & entry: vector )
if( first ){ result = entry.description(); first = false; }
else result = result + plus + entry.description();
return result; }};
 
struct paren_parse_type final : public parse_type
{ string surface_;
string lpar;
string rpar;
sum_parse_type sum;
paren_parse_type( string surface, string lpar, string rpar,
sum_parse_type sum ):
surface_{ move(surface) }, lpar{ move(lpar) }, rpar{ move(rpar) },
sum{ move(sum) } {}
string const space{ " "s };
string surface() const override { return surface_; }
string description() const override
{ return lpar + space + sum.description() + space + rpar; }};
 
 
template< typename scanner >struct parser_type
{ scanner sc;
explicit parser_type( scanner && sc ): sc{ move( sc )} {}
 
name_parse_type get_name()
{ string t;
t = sc.get(); return name_parse_type{ t }; }
 
number_parse_type get_number()
{ string t; t = sc.get(); return number_parse_type{ t }; }
 
product_parse_type get_product()
{ primary_parse_type const component { get_primary() };
string preview { sc.peek() };
bool const is_product { preview.length() > 0 && isdigit(
preview.at( 0 )) };
string const multiplicity { is_product ? sc.get(): "1"s };
return product_parse_type{ component.surface() +( is_product ?
preview : ""s ), new primary_parse_type { component }, multiplicity }; }
 
sum_parse_type get_sum()
{ auto result { sum_parse_type{ ""s, {} }};
product_parse_type component { get_product() };
if( component.surface() == ""s )return result;
result.append_surface( component.surface() );
result.append_addend( component );
string preview;
while( true )
{ preview = sc.peek();
bool const is_sum { preview.length() > 0 &&( isalpha(
preview.front() ) || preview.front() == '(' || preview.front() == '[' ||
preview.front() == '{') };
if( !is_sum )return result;
component = get_product();
result.append_surface( component.surface() );
result.append_addend( component ); }
return sum_parse_type{ ""s, {} }; }
 
paren_parse_type get_paren()
{ string const lpar { sc.get() };
sum_parse_type const sum { get_sum() };
string const rpar { sc.get() };
return paren_parse_type
{ lpar + sum.surface() + rpar, lpar, rpar, sum }; }
 
primary_parse_type get_primary()
{ auto next { sc.peek() };
if( isalpha( next.front() ))
{ name_parse_type name = get_name();
return new name_parse_type{ name }; }
if( next.front() == '(' || next.front() == '[' || next.front() == '{')
{ paren_parse_type paren = get_paren();
return new paren_parse_type{ paren }; }
return nullptr; }};
 
int main()
{ istringstream s{ "HRh(CO)[P{CH2CH2(CF2)5CF}3]3" };
scanner< istringstream >sc{ move( s )};
parser_type< scanner< istringstream > >parser{ move( sc )};
sum_parse_type sum_value = parser.get_sum();
cout << sum_value.surface() << '\n';
cout << sum_value.description() << '\n'; }
"Heinz Müller" <Heinz.Mueller69@gmail.com>: Jun 30 07:07PM +0200

> sum_parse_type sum_value = parser.get_sum();
> ::std::cout << sum_value.surface() << '\n';
> ::std::cout << sum_value.description() << '\n'; }
 
You've won the 2019 obfuscated code contest!
Mr Flibble <flibbleREMOVETHISBIT@i42.co.uk>: Jun 30 07:54PM +0100

On 30/06/2019 15:04, Stefan Ram wrote:
> sum_parse_type sum_value = parser.get_sum();
> ::std::cout << sum_value.surface() << '\n';
> ::std::cout << sum_value.description() << '\n'; }
 
What's with all the `::std::`? `std::` is fine. Your code is nearly as
bad as Alf's.
 
/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," Bryne 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."
"Öö Tiib" <ootiib@hot.ee>: Jun 30 09:16AM -0700

On Friday, 28 June 2019 09:24:00 UTC+3, Tim Rentsch wrote:
 
> (Direct is not the same as short here. My viewpoint has more
> than a few different aspects, which is to say too many to be
> conveyed in only one or two sentences, so please be thorough.)
 
My impression, (but I may be wrong there) is that you consider
"undefined behavior" to be synonymous with "behavior caused
by programming error". For me these two things overlap a lot
but also have differences. Some clear constraint violations
result with defined behavior but some flawless programs
may end with undefined behavior.
 
For some of those situations we have signals like SIGILL
and SIGSEGV. There are no defined behaviors that cause
those.
 
In running system it is impossible to figure if these signals
were caused by programming error in some program, defect
in hardware, defect in compiler, defect in operating system,
misconfiguration of any of those, external attackers or cosmic
rays. So as a programmer of software it is not what I have
to deal with. Instead my software needs to give up any control
it has and to notify possible backup systems about it as fast
as possible.
 
Same with exceeding automatic storage limits. I would be lot
happier if C++ did provide me some runtime way to check
how lot of automatic storage is left or at least guarantee
that SIGSEGV when automatic storage is exhausted.
But unfortunately C++ neither provides nor guarantees
anything and so it is undefined behavior.
ram@zedat.fu-berlin.de (Stefan Ram): Jun 30 02:04PM

>but not the following:
>[Be(N(CH3)2)2]3
 
Here is a quick attempt to write a parser for it.
 
However, this is just a "quick and dirty" solution,
it is a first draft, a kind of "compilable pseudo code",
it contains some some unnecessary lines.
 
It can parse the above formula, but has not been
tested with other formulas, and it allocates memory
with "new" that never is freed (it is leaking memory).
 
Maybe better memory management can be achieved by
overwriting the destructors?
 
input (see "main"):
 
[Be(N(CH3)2)2]3
 
output (written to stdout):
 
3 * [ 1 * Be + 2 * ( 1 * N + 2 * ( 1 * C + 3 * H ) ) ]
 
source code (wide lines!):
 
#include <cctype>
#include <iostream>
#include <istream>
#include <memory>
#include <ostream>
#include <sstream>
#include <string>
#include <vector>
 
using namespace ::std::literals;
 
template< typename source >struct scanner
{ source s;
 
::std::string peek_value;
 
typename source::int_type eof { source::traits_type::eof() };
 
scanner( source && s )noexcept : s{ ::std::move( s )}, peek_value{ ""s } {}
 
scanner( scanner && s )noexcept : s{ static_cast<source&&>(s.s)}, peek_value{static_cast<::std::string&&>(s.peek_value)} { }
 
::std::string name( char c )
{ ::std::string result;
if( isalpha( c ))
{ int pos {};
while( isalpha( c )&&( pos == 0 || islower( c )))
{ pos = 1;
c = static_cast< char >( s.get() );
result += c;
auto const i = s.peek();
if( i == eof )return result;
c = static_cast< char >( i ); }}
return result; }
 
::std::string number( char c )
{ ::std::string result;
if( isdigit( c ))
{ while( isdigit( c ))
{ c = static_cast< char >( s.get() );
result += c;
auto const i = s.peek();
if( i == eof )return result;
c = static_cast< char >( i ); }}
return result; }
 
::std::string special( char c )
{ ::std::string result;
if( c == '(' || c == ')' || c == '[' || c == ']' )
{ c = static_cast< char >( s.get() );
result += c;
return result; }
return result; }
 
::std::string do_get()
{ ::std::string result;
auto const i = s.peek();
if( i == eof )return result;
else
{ auto c { static_cast< char >( i )};
result = name( c ); if( result != ""s )return result;
result = number( c ); if( result != ""s )return result;
result = special( c ); if( result != ""s )return result;
return result; }
return result; }
 
::std::string get()
{ if( peek_value != ""s )
{ ::std::string const result{ peek_value };
peek_value = ""s;
return result; }
else return do_get(); }
 
::std::string peek()
{ if( peek_value == ""s )peek_value = do_get();
return peek_value; }};
 
 
struct parse_type
{ virtual ::std::string surface() const = 0;
virtual ::std::string description() const = 0;
parse_type()= default;
parse_type( const parse_type & )= default;
parse_type( parse_type && )= default;
parse_type & operator=( const parse_type & )= default;
parse_type & operator=( parse_type && )noexcept = default;
virtual ~parse_type() = default; };
 
struct primary_parse_type final : public parse_type
{ parse_type const * primary;
primary_parse_type( const primary_parse_type & )= default;
primary_parse_type& operator=(const primary_parse_type&)= default;
primary_parse_type( parse_type const * primary ):
primary{ primary } {}
::std::string surface() const override { return primary->surface(); }
::std::string description() const override
{ return primary->description(); }};
 
struct name_parse_type;
 
struct name_parse_type final : public parse_type
{ ::std::string surface_;
name_parse_type( ::std::string surface ):surface_{ ::std::move(surface) } {}
::std::string surface() const override { return surface_; }
::std::string description() const override { return surface_; }};
 
struct number_parse_type final : public parse_type
{ ::std::string surface_;
number_parse_type( ::std::string surface ):surface_{ ::std::move(surface) } {}
::std::string surface() const override { return surface_; }
::std::string description() const override { return "number "s + surface_; }};
 
struct product_parse_type final : public parse_type
{ ::std::string surface_;
primary_parse_type * component;
::std::string multiplicity;
product_parse_type(const product_parse_type&)=default;
product_parse_type& operator=(const product_parse_type&)=default;
product_parse_type( ::std::string surface, primary_parse_type * component, ::std::string multiplicity ):
surface_{ ::std::move(surface) }, component{ component }, multiplicity{ ::std::move(multiplicity) } {}
::std::string surface() const override { return surface_; }
::std::string description() const override { return multiplicity + " * " + component->description(); }};
 
struct sum_parse_type final : public parse_type
{ ::std::string surface_;
::std::vector< product_parse_type >vector;
sum_parse_type( ::std::string surface, ::std::vector< product_parse_type > vector ):
surface_{ ::std::move(surface) }, vector{ ::std::move(vector) } {}
::std::string const plus = " + "s;
void append_surface( ::std::string const & s ){ surface_ += s; }
void append_addend( product_parse_type const & s ){ vector.push_back( s ); }
::std::string surface() const override { return surface_; }
::std::string description() const override
{ ::std::string result;
bool first = true;
for( auto & entry: vector )
if( first ){ result = entry.description(); first = false; }
else result = result + plus + entry.description();
return result; }};
 
struct paren_parse_type final : public parse_type
{ ::std::string surface_;
::std::string lpar;
::std::string rpar;
sum_parse_type sum;
paren_parse_type( ::std::string surface, ::std::string lpar, ::std::string rpar, sum_parse_type sum ):
surface_{ ::std::move(surface) }, lpar{ ::std::move(lpar) }, rpar{ ::std::move(rpar) }, sum{ ::std::move(sum) } {}
::std::string const space{ " "s };
::std::string surface() const override { return surface_; }
::std::string description() const override
{ return lpar + space + sum.description() + space + rpar; }};
 
 
template< typename scanner >struct parser_type
{ scanner sc;
explicit parser_type( scanner && sc ): sc{ ::std::move( sc )} {}
 
name_parse_type get_name()
{ ::std::string t;
t = sc.get(); return name_parse_type{ t }; }
 
number_parse_type get_number()
{ ::std::string t; t = sc.get(); return number_parse_type{ t }; }
 
product_parse_type get_product()
{ primary_parse_type const component { get_primary() };
::std::string preview { sc.peek() };
bool const is_product { preview.length() > 0 && isdigit( preview.at( 0 )) };
::std::string const multiplicity { is_product ? sc.get(): "1"s };
return product_parse_type{ component.surface() +( is_product ? preview : ""s ), new primary_parse_type { component }, multiplicity }; }
 
sum_parse_type get_sum()
{ auto result { sum_parse_type{ ""s, {} }};
product_parse_type component { get_product() };
if( component.surface() == ""s )return result;
result.append_surface( component.surface() );
result.append_addend( component );
::std::string preview;
while( true )
{ preview = sc.peek();
bool const is_sum { preview.length() > 0 &&( isalpha( preview.front() )|| preview.front() == '(' || preview.front() == '[' )};
if( !is_sum )return result;
component = get_product();
result.append_surface( component.surface() );
result.append_addend( component ); }
return sum_parse_type{ ""s, {} }; }
 
paren_parse_type get_paren()
{ ::std::string const lpar { sc.get() };
sum_parse_type const sum { get_sum() };
::std::string const rpar { sc.get() };
return paren_parse_type
{ lpar + sum.surface() + rpar, lpar, rpar, sum }; }
 
primary_parse_type get_primary()
{ auto next { sc.peek() };
if( isalpha( next.front() ))
{ name_parse_type name = get_name();
return new name_parse_type{ name }; }
if( next.front() == '(' || next.front() == '[' )
{ paren_parse_type paren = get_paren();
return new paren_parse_type{ paren }; }
return nullptr; }};
 
int main()
{ ::std::istringstream s{ "[Be(N(CH3)2)2]3" };
scanner< ::std::istringstream >sc{ ::std::move( s )};
parser_type< scanner< ::std::istringstream > >parser{ ::std::move( sc )};
sum_parse_type sum_value = parser.get_sum();
::std::cout << sum_value.surface() << '\n';
::std::cout << sum_value.description() << '\n'; }
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.

Saturday, June 29, 2019

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

Jorgen Grahn <grahn+nntp@snipabacken.se>: Jun 29 02:55PM

On Sat, 2019-06-29, Stefan Ram wrote:
...
 
Lots of things are more important than C++, but they are still
offtopic here.
 
/Jorgen
 
--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .
Keith Thompson <kst-u@mib.org>: Jun 29 02:23PM -0700

> Subject: Re: What does C++ say about climate change?
 
Nothing.
 
> »"Goodbye, " << "Planet!"«
 
> n4800, 28.10.3.4 Member functions [syncstream.osyncstream.members]
 
In context, it's simply a phrase in contrast to "Hello, World!".
 
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Will write code for food.
void Void(void) { Void(); } /* The recursive call of the void */
Chris Vine <chris@cvine--nospam--.freeserve.co.uk>: Jun 29 10:36PM +0100

On 29 Jun 2019 12:09:08 GMT
 
> n4800, 28.10.3.4 Member functions [syncstream.osyncstream.members]
 
> (It might sound cynical, but when people are driving
> 90 miles an hour down a dead-end road what else is left?)
 
I think that by mistake you posted to the wrong group. C++ says nothing
about climate change. C++ is a programming language.
 
Evidence indicates beyond reasonable dispute that global temperatures
are rising, partly because of human intervention. Sea levels are about
2cm higher than 200 years ago. They are about 130 metres higher than
at the end of the last glaciation maximum, mainly because of natural
temperature and climate variation because we are now in an inter-glacial
period of an ice age. Sea levels are still over 200 metres lower than
they were 100 million years ago (a blink of the eye geologically
speaking). 250 million years ago Antartica was forested even though it
was only somewhat further north than now, because the joining of the
North and South American continents had not then occured so
extinguishing trans-global currents. For the larger part of earth's
history there has been no permanent ice on both poles: ice ages such as
the present one are typically unusual (plate techtonics have been a big
driver of climate variation): in earth's history there have been at
least 5 of them. One of them (the Cryogenian) may have produced a
"snowball earth" with ice sheats to the equator.
 
Carbon dioxide absorption by silicate weathering will in due course
become a threat to bio-diversity (100 to 500 million years ahead) by
reducing carbon dioxide below the level required for the main form of
photosynthesis to occur (but new forms of vegetation will adapt).
Increased solar radiation is a bigger long term threat as nuclear fuel
is slowly expended, which at some point (approx 1 billon years ahead)
will cause thermal runaway and evaporation of the oceans, long before
the sun turns into a red giant. If technology is sufficiently existent
at that time, then it may possibly be averted technologically be
reflecting the radiation back into space. Nothing is likely to defend
when the sun becomes a red giant in some 5 billion years time, and
nothing at all will defend the subsequent extinguishment of solar
radiation.
 
As Private Fraser would say, "we are all doomed". We are all on your
dead-end road. (The universe is also, by virtue of the 2nd law of
thermodynamics - the universe has an arrow of time.)
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jun 30 01:21AM +0200

On 29.06.2019 23:36, Chris Vine wrote:
 
> As Private Fraser would say, "we are all doomed". We are all on your
> dead-end road. (The universe is also, by virtue of the 2nd law of
> thermodynamics - the universe has an arrow of time.)
 
Since we're off-topic and it's, well now it's Sunday already. Since it's
Sunday.
 
The last parenthetical remark, short as it is, contains a number of errors.
 
First, the application of a statistical law that applies to inert gases,
to the universe at large, is at best invalid. It's not the case that a
system of more interestingly interacting parts than inert atoms, is
necessarily likely to evolve towards an uninteresting homogeneous state.
Of course it depends on what one means by interesting, but. It's easy to
construct artificial systems, systems with less than totally inert
parts, that evolve in interesting ways without ever going into a
homogeneous state. If such a system is started in an apparently
homogeneous state it can/will evolve away from it, towards complexity.
 
To wit, the current generally accepted cosmological hypothesis, called
the Big Bang, has it that the universe started in a nearly completely
homogeneous state, and evolved to the interesting complex structure we
see around us.
 
Sad observation of the kind of science going on: the cosmological
principle is the idea that at a sufficiently large scale the universe is
still homogeneous. But every proposed and at the time accepted scale,
has been contradicted by observations, and this has happened many times.
Every time the idea, alleged fact, is refuted by observations of larger
structures, say roughly once a decade, it's relaunched with just an
adjustment of the scale, and worse, scientists then forget the history.
 
Secondly, the remark seems to equate increase of entropy with time.
 
For a sufficiently simple system, like the mentioned inert gas, a time's
arrow causes entropy increase. Necessarily, logically, because the
uninteresting gas-everywhere states are in the zillions compared to
those states that can be identified as not-gas-everywhere, and there's
no structuring process going on. So with a random walk to nearest states
it rapidly gets to gas-everywhere. But even in such a simple system it's
the time's arrow that drives the system evolution, not opposite. They're
not on equal terms, as one can readily see by implementing a simulation.
 
It pains me that the scientific community is at odds with both logic and
observations about this matter. I think it's like religion, or some
kinds of politics, or war. Everybody adopts or pretends to adopt the
belief that they see that everybody else, in particular authorities, say
they have. And so we had 2000 years of crystal spheres. And now a
hundred years at least of Big Bang and predicted entropic death of the
universe. Happily sooner or later there will be observations that
shatter the current variation of belief, like Tycho Brahe's comet
shattered the crystal spheres (or rather didn't), but as the repetitive
history of the cosmological principle shows, that may not be enough:
with a strong enough social force the theory is just amended.
 
Cheers!,
 
- Alf
G G <gdotone@gmail.com>: Jun 28 07:46PM -0700

are these checks still necessary or is there another way?
 
https://wiki.sei.cmu.edu/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow
 
Like:
 
#include <limits.h>

void f(signed int si_a, signed int si_b)
{
signed int sum;
 
if (((si_b > 0) && (si_a > (INT_MAX - si_b))) ||
((si_b < 0) && (si_a < (INT_MIN - si_b))))
{
/* Handle error */
}
else
{
sum = si_a + si_b;
}
 
/* ... */
}
 
to protect against over flow like: (that may happen)
 
void func(signed int si_a, signed int si_b)
{
signed int sum = si_a + si_b;
/* ... */
}
 
the code above is taken from:
 
https://wiki.sei.cmu.edu/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jun 29 05:54AM +0200

On 29.06.2019 04:46, G G wrote:
> }
 
> the code above is taken from:
 
> https://wiki.sei.cmu.edu/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow
 
Checks are still necessary when there is a possibility of overflow that
one wishes to handle. C++ has not gained any support for overflow
handling of integer arithmetic.
 
However, the checking can be simplified, possibly more efficient, and
modulo late-late-night + full-of-painkillers I think this doesn't rely
on C++20 requirement of two's complement form:
 
inline auto sign( const int x ) -> bool { return x < 0; }
 
void func( const int a, const int b )
{
const int sum = static_cast<int>( 0u + a + b );
const bool overflow =
(sign( a ) == sign( b ) and sign( sum ) != sign( a );
// ...
}
 
Disclaimer: off the cuff code.
 
Also, formally the `static_cast` here has implementation defined
behavior, IIRC. But hey.
 
An alternative can be to use floating point and rely on NaN. But there
is danger in there. The standard library's facilities for checking NaN
are not good enough to deal with GCC and MSVC fast float optimizations.
 
Cheers!,
 
- Alf
David Brown <david.brown@hesbynett.no>: Jun 29 11:56PM +0200

On 29/06/2019 04:46, G G wrote:
> }
 
> the code above is taken from:
 
> https://wiki.sei.cmu.edu/confluence/display/c/INT32-C.+Ensure+that+operations+on+signed+integers+do+not+result+in+overflow
 
Signed integer overflow is undefined behaviour in C++ (and C). There
are many ways to avoid overflowing, depending on the circumstances, the
operations you are doing, the target compiler (if portability is not a
concern), etc. In most cases, signed integer overflow is an error -
it's a case of garbage in, garbage out. And in most cases, a check like
you have made above is meaningless and inefficient because all it does
is check if the addition can be done with those types, without
overflowing. It is rare that you are adding two integers with unknown
origins, and unknown usage, and that adding them is all you are doing -
and thus rare that it makes sense to make a check like that. It is far
better to check for the validity of data when it comes in from the
outside, checking against sensible limits. And then make your
calculations valid for all sensible data (use bigger types if necessary).
G G <gdotone@gmail.com>: Jun 29 04:02PM -0700

> better to check for the validity of data when it comes in from the
> outside, checking against sensible limits. And then make your
> calculations valid for all sensible data (use bigger types if necessary).
 
I'm sure you don't mean me per se , but only cause I'm asking and showing
the code. But to ensure I'm not taking undue credit, the code is from a CERT
website, www.securecoding.cert.org from a search INT32-CPP.
At that site, they show many other concerns and suggestions how to mitigate.
Horizon68 <horizon@horizon.com>: Jun 29 02:52PM -0700

Hello,
 
 
My Universal Scalability Law for Delphi and FreePascal was updated to
version 3.22
 
I have implemented and enhanced this powerful tool.
 
I have included a 32 bit and 64 bit windows and linux executables called
usl.exe and usl_graph.exe inside the zip, please read the readme file
to know how to use it, it is a very powerful tool.
 
Now about the Beta and Alpha coefficients of USL:
 
Coefficient Alpha is: the contention
 
And
 
Coefficient Beta is: the coherency.
 
Contention and coherency are measured as the fraction of the sequential
execution time. A value of 0 means that there is no effect on
performance. A contention factor of 0.2, for instance, means that 20% of
the sequential execution time cannot be parallelized. A coherency factor
of 0.01 means that the time spent in the synchronization between each
pair of processes is 1% of the sequential execution time.
 
 
Also there is something very important to know, and here it is:
 
So to optimize more the criterion of the cost for a better QoS, you have
to choose a good delta(y)/delta(x) to optimize the criterion of the cost
of your system and you have to balance better between the performance
and the cost. You can read about my powerful tool and download it from:
 
https://sites.google.com/site/scalable68/universal-scalability-law-for-delphi-and-freepascal
 
 
Thank you,
Amine Moulay Ramdane.
woodbrian77@gmail.com: Jun 29 12:30PM -0700

On Thursday, August 30, 2018 at 11:50:04 AM UTC-5, Jorgen Grahn wrote:
> > So I guess this is still a problem for poll().
 
> Yes, and also for epoll(7). The problem/feature is in the kernel code
> that's underlying for all these functions.
 
It looks like this may finally be fixed. What I wrote last
year was about Linux 4.14. Now I have 4.19 installed and I
can't find any mention of this problem in the docs for poll,
(p)select or epoll. Am I missing something? Maybe my
perseverance is starting to pay off. Thanks.
 
 
 
Brian
Ebenezer Enterprises - In G-d we trust.
https://github.com/Ebenezer-group/onwards
alexo <alelvb@inwind.it>: Jun 29 05:18AM +0200

Il 29/06/19 00:53, Alf P. Steinbach ha scritto:
> formula, using that function. Because it discards the delimiter it stops
> at. Which means, in any way I think of using it, that it discards the
> parentheses.
 
What I wrote doesn't use the strok function. I analyzed the formula from
left to right skipping invalid letter combinations and analyzing
numerical coefficients.
I wrongly supposed that strok function could help me in the job, but it
is not so.
 
 
> whether there can be multi-digit integers in there. From what I remember
> of chemistry and quantum mechanics I guess the maximum number would be 7
> or less, maybe just 4? But guesswork doesn't make up for a clear spec.
 
The numerical coefficient theorically can be of any lenght, but usually
are not greater than, say, 15.
 
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jun 29 06:08AM +0200

On 29.06.2019 05:18, alexo wrote:
>> clear spec.
 
> The numerical coefficient theorically can be of any lenght, but usually
> are not greater than, say, 15.
 
OK. The following is a manual approach to lexing such formulas. I've
assumed that they can contain whitespace.
 
 
-------------------------------------- chemical-elements.hpp
#pragma once
#include <string_view>
 
namespace chemical
{
using std::string_view;
 
struct Element
{
int number;
string_view symbol;
string_view name;
};
 
constexpr Element elements[] =
{
{ 1, "H", "Hydrogen" },
{ 2, "He", "Helium" },
{ 3, "Li", "Lithium" },
{ 4, "Be", "Beryllium" },
{ 5, "B", "Boron" },
{ 6, "C", "Carbon" },
{ 7, "N", "Nitrogen" },
{ 8, "O", "Oxygen" },
{ 9, "F", "Fluorine" },
{ 10, "Ne", "Neon" },
{ 11, "Na", "Sodium" },
{ 12, "Mg", "Magnesium" },
{ 13, "Al", "Aluminium" },
{ 14, "Si", "Silicon" },
{ 15, "P", "Phosphorus" },
{ 16, "S", "Sulfur" },
{ 17, "Cl", "Chlorine" },
{ 18, "Ar", "Argon" },
{ 19, "K", "Potassium" },
{ 20, "Ca", "Calcium" },
{ 21, "Sc", "Scandium" },
{ 22, "Ti", "Titanium" },
{ 23, "V", "Vanadium" },
{ 24, "Cr", "Chromium" },
{ 25, "Mn", "Manganese" },
{ 26, "Fe", "Iron" },
{ 27, "Co", "Cobalt" },
{ 28, "Ni", "Nickel" },
{ 29, "Cu", "Copper" },
{ 30, "Zn", "Zinc" },
{ 31, "Ga", "Gallium" },
{ 32, "Ge", "Germanium" },
{ 33, "As", "Arsenic" },
{ 34, "Se", "Selenium" },
{ 35, "Br", "Bromine" },
{ 36, "Kr", "Krypton" },
{ 37, "Rb", "Rubidium" },
{ 38, "Sr", "Strontium" },
{ 39, "Y", "Yttrium" },
{ 40, "Zr", "Zirconium" },
{ 41, "Nb", "Niobium" },
{ 42, "Mo", "Molybdenum" },
{ 43, "Tc", "Technetium" },
{ 44, "Ru", "Ruthenium" },
{ 45, "Rh", "Rhodium" },
{ 46, "Pd", "Palladium" },
{ 47, "Ag", "Silver" },
{ 48, "Cd", "Cadmium" },
{ 49, "In", "Indium" },
{ 50, "Sn", "Tin" },
{ 51, "Sb", "Antimony" },
{ 52, "Te", "Tellurium" },
{ 53, "I", "Iodine" },
{ 54, "Xe", "Xenon" },
{ 55, "Cs", "Caesium" },
{ 56, "Ba", "Barium" },
{ 57, "La", "Lanthanum" },
{ 58, "Ce", "Cerium" },
{ 59, "Pr", "Praseodymium" },
{ 60, "Nd", "Neodymium" },
{ 61, "Pm", "Promethium" },
{ 62, "Sm", "Samarium" },
{ 63, "Eu", "Europium" },
{ 64, "Gd", "Gadolinium" },
{ 65, "Tb", "Terbium" },
{ 66, "Dy", "Dysprosium" },
{ 67, "Ho", "Holmium" },
{ 68, "Er", "Erbium" },
{ 69, "Tm", "Thulium" },
{ 70, "Yb", "Ytterbium" },
{ 71, "Lu", "Lutetium" },
{ 72, "Hf", "Hafnium" },
{ 73, "Ta", "Tantalum" },
{ 74, "W", "Tungsten" },
{ 75, "Re", "Rhenium" },
{ 76, "Os", "Osmium" },
{ 77, "Ir", "Iridium" },
{ 78, "Pt", "Platinum" },
{ 79, "Au", "Gold" },
{ 80, "Hg", "Mercury" },
{ 81, "Tl", "Thallium" },
{ 82, "Pb", "Lead" },
{ 83, "Bi", "Bismuth" },
{ 84, "Po", "Polonium" },
{ 85, "At", "Astatine" },
{ 86, "Rn", "Radon" },
{ 87, "Fr", "Francium" },
{ 88, "Ra", "Radium" },
{ 89, "Ac", "Actinium" },
{ 90, "Th", "Thorium" },
{ 91, "Pa", "Protactinium" },
{ 92, "U", "Uranium" },
{ 93, "Np", "Neptunium" },
{ 94, "Pu", "Plutonium" },
{ 95, "Am", "Americium" },
{ 96, "Cm", "Curium" },
{ 97, "Bk", "Berkelium" },
{ 98, "Cf", "Californium" },
{ 99, "Es", "Einsteinium" },
{ 100, "Fm", "Fermium" },
{ 101, "Md", "Mendelevium" },
{ 102, "No", "Nobelium" },
{ 103, "Lr", "Lawrencium" },
{ 104, "Rf", "Rutherfordium" },
{ 105, "Db", "Dubnium" },
{ 106, "Sg", "Seaborgium" },
{ 107, "Bh", "Bohrium" },
{ 108, "Hs", "Hassium" },
{ 109, "Mt", "Meitnerium" },
{ 110, "Ds", "Darmstadtium" },
{ 111, "Rg", "Roentgenium" },
{ 112, "Cn", "Copernicium" },
{ 113, "Nh", "Nihonium" },
{ 114, "Fl", "Flerovium" },
{ 115, "Mc", "Moscovium" },
{ 116, "Lv", "Livermorium" },
{ 117, "Ts", "Tennessine" },
{ 118, "Og", "Oganesson" }
};
} // namespace chemical
 
 
-------------------------------------- chemical_formula-Tokenizer.hpp
#pragma once
#include "chemical-elements.hpp" // chemical::(Element, elements)
#include <cppx-core/all.hpp> // <url:
https://github.com/alf-p-steinbach/cppx-core>
 
namespace chemical_formula
{
$use_std(
stoi, string_view
);
$use_cppx(
Map_, // A std::unordered_map with [] indexing of
const instance.
P_, // P_<T> is an alias for T*. It supports prefix
const.
p_first_of, p_beyond_of
);
namespace ascii = cppx::ascii; // ascii::is_*
 
struct Token
{
struct Kind{ enum Enum {
none,
element,
number,
left_parens = '(', right_parens = ')',
left_bracket = '[', right_bracket = ']'
}; };
 
Kind::Enum kind;
string_view text;
int n; // Only used for `element` and
`number`.
};
 
class Tokenizer
{
const string_view m_formula;
const P_<const char> m_p_beyond_formula;
 
Token m_current;
 
struct Symbols_to_elements_map:
Map_<string_view, P_<const chemical::Element>>
{
Symbols_to_elements_map()
{
auto& self = *this;
for( const chemical::Element& elem : chemical::elements ) {
self[elem.symbol] = &elem;
}
}
};
 
auto is_in_formula( const P_<const char> p )
-> bool
{ return p != m_p_beyond_formula; }
 
void find_token_that_starts_at( const P_<const char> p_start )
{
static const auto symbols = Symbols_to_elements_map();
 
const char first_char = *p_start;
if( ascii::is_digit( first_char ) ) {
P_<const char> p_beyond = p_start + 1;
while( is_in_formula( p_beyond ) and ascii::is_digit(
*p_beyond ) ) {
++p_beyond;
}
const auto text = string_view( p_start, p_beyond -
p_start );
try {
m_current = { Token::Kind::number, text, stoi(
p_start ) };
} catch( ... ) {
m_current = { Token::Kind::none, text, -1 };
}
} else if( ascii::is_uppercase( first_char ) ) {
P_<const char> p_beyond = p_start + 1;
while( is_in_formula( p_beyond ) and
ascii::is_lowercase( *p_beyond ) ) {
++p_beyond;
}
const auto text = string_view( p_start, p_beyond -
p_start );
try {
m_current = { Token::Kind::element, text,
symbols[text]->number };
} catch( ... ) {
m_current = { Token::Kind::none, text, -1 };
}
} else {
const auto text = string_view( p_start, 1 );
switch( first_char ) {
case '(': [[fallthrough]];
case ')': [[fallthrough]];
case '[': [[fallthrough]];
case ']': {
m_current = { Token::Kind::Enum( first_char ),
text, -1 };
break;
}
default: {
m_current = { Token::Kind::none, text, -1 };
}
}
}
}
 
void find_next_remaining_token()
{
P_<const char> p_start = p_beyond_of( m_current.text );
while( is_in_formula( p_start ) and ascii::is_whitespace(
*p_start ) ) {
++p_start;
}
if( p_start == m_p_beyond_formula ) {
m_current = { Token::Kind::none, string_view( p_start,
0 ), -1 };
return;
}
find_token_that_starts_at( p_start );
}
 
public:
auto current() const
-> Token
{ return m_current; }
 
auto is_at_end() const
-> bool
{ return p_first_of( m_current.text ) == p_beyond_of( m_formula
); }
 
void advance()
{
find_next_remaining_token();
}
 
Tokenizer( const string_view& formula ):
m_formula( formula ),
m_p_beyond_formula( p_beyond_of( formula ) ),
m_current{ Token::Kind::none, string_view( formula.data(),
0 ), -1 }
{
assert( m_current.text.data() == formula.data() );
find_next_remaining_token();
}
};
} // namespace chemical_formula
 
 
-------------------------------------- main.cpp
#include "chemical_formula-Tokenizer.hpp"
#include <cppx-core/all.hpp>
 
auto main() -> int
{
$use_std( cout, endl );
 
const auto& formula = "[Be(N(CH3)24)255555555555555555555]3";
 
cout << "Tokens:" << endl;
for( auto tokens = chemical_formula::Tokenizer( formula );
not tokens.is_at_end();
tokens.advance() )
{
const chemical_formula::Token tok = tokens.current();
cout << "* ";
if( tok.kind == chemical_formula::Token::Kind::none ) {
cout << "<invalid> ";
}
cout << "\"" << tok.text << "\"" << endl;
}
}
 
 
Output:
 
Tokens:
* "["
* "Be"
* "("
* "N"
* "("
* "C"
* "H"
* "3"
* ")"
* "24"
* ")"
* <invalid> "255555555555555555555"
* "]"
* "3"
 
 
Cheers & hth.,
 
- Alf
alexo <alelvb@inwind.it>: Jun 29 06:21AM +0200

Il 29/06/19 05:18, alexo ha scritto:
>> clear spec.
 
> The numerical coefficient theorically can be of any lenght, but usually
> are not greater than, say, 15.
 
For a single central atom the coordination number can be higher than 7,
but the coefficient can be very high in organic chemistry formulas,
where there is not a limit to the number of carbon atoms that can be
chained together. They are usually reported grouping methyl or methylene
groups as this:
 
CH3(CH2)10CH(CH3)(CH2)3CH3
 
5-methyl-hexadecane.
 
For the parentheses, formulas usually involve a pair of square brackets
inside of which there are round parentheses.
 
The example I reported earlier, namely, [Be(N(CH3)2)2]3 even if simple,
fails to be recognized by my parser.
 
2(3HC)-N-N-(CH3)2 being the 1,1,2,2 tetramethyl-hydrazine group
alexo <alelvb@inwind.it>: Jun 29 06:31AM +0200

Il 29/06/19 06:08, Alf P. Steinbach ha scritto:
>>>>> On 28.06.2019 19:14, alexo wrote:
 
> OK. The following is a manual approach to lexing such formulas. I've
> assumed that they can contain whitespace.
 
No Alf, chemical formulas don't have spaces inside them. They are a list
of the atoms, or group of atoms the molecule contains.
"Chris M. Thomasson" <invalid_chris_thomasson_invalid@invalid.com>: Jun 28 09:49PM -0700

On 6/28/2019 9:08 PM, Alf P. Steinbach wrote:
>         string_view     name;
>     };
 
>     constexpr Element elements[]    =
[...]
>         { 116, "Lv", "Livermorium" },
>         { 117, "Ts", "Tennessine" },
>         { 118, "Og", "Oganesson" }
[...]
 
Where 115 = ununpentium or Lazarium? lol. ;^)
 
Just having some fun.
Bonita Montero <Bonita.Montero@gmail.com>: Jun 29 08:40AM +0200

>> -versions with internal buffers which are thread-local?
 
> Because it makes much more sense for the caller to provide the
> storage for the metadata, as POSIX realized two decades ago:
 
I think storing the saveptr yourself is less convenient than a
strtok() with internal thread-local buffers. And even more this
solution with be fully backward-compatible.
Manfred <noname@invalid.add>: Jun 29 04:47PM +0200

On 6/28/19 11:57 PM, Keith Thompson wrote:
 
> http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf
 
> Annex K is normative but optional. An implementation that supports it
> must pre#define __STDC_WANT_EXT1__.
 
Just an extra bit of practical info: glibc, as diffuse as it is, does
_not_ support annex K, on purpose.
 
[...]
Bonita Montero <Bonita.Montero@gmail.com>: Jun 29 04:51PM +0200

> * Microsoft submitted their silly *_s bounds checking functions for
> standardization in C.
 
They aren't silly! If you don't use C++-strings but stick with C
char-arrays the make sense.
Manfred <noname@add.invalid>: Jun 29 06:59PM +0200

On 6/29/2019 4:51 PM, Bonita Montero wrote:
>> standardization in C.
 
> They aren't silly! If you don't use C++-strings but stick with C
> char-arrays the make sense.
 
Except that they are poorly designed, i.e., in human language, silly.
 
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1969.htm
ram@zedat.fu-berlin.de (Stefan Ram): Jun 29 12:09PM

»"Goodbye, " << "Planet!"«
 
n4800, 28.10.3.4 Member functions [syncstream.osyncstream.members]
 
(It might sound cynical, but when people are driving
90 miles an hour down a dead-end road what else is left?)
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jun 29 01:39AM +0200

On 29.06.2019 01:16, Mr Flibble wrote:
> egregious will it take for you to stop posting fucking egregious code?
 
> Please when posting snippets that are answers to questions:
> 1) DO NOT use your personal non-standard fucktarded library
 
There's nothing non-standard about the library, other than purely
formally some macro names that you can trivially transform to formally
conforming.
 
You have been so informed numerous times.
 
You keep forgetting.
 
 
> that flings
> dollar sign shit all over the walls of the room;
 
Reiterating what you've been told several times before:
 
You can trivially replace each macro name's dollar sign with prefix
`CPPX_`, and just uppercase the rest, to avoid the /emotional/ affront
to you.
 
You can even do that in your head, no editing effort involved, since
examples posted in clc++ are seldom posted for their output but for
understanding things.
 
When you don't that means you're lazy, or trolling, or both.
 
 
> it;
> 3) DO NOT write auto main() ... (see (2)) as it makes you look like a
> trolling cunt fuckwomble who just wants to irritate everyone.
 
Well, the swearing and strong reaction to modern C++ syntax says it all.
 
 
Cheers & hth.,
 
- Alf
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.