Friday, September 30, 2022

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

Lynn McGuire <lynnmcguire5@gmail.com>: Sep 29 11:48PM -0500

Is this C++ statement using the comma operator ?
 
write(6, "(3(1x,i3),1x,f12.6,1x,f12.6)"), hkl(1, i), hkl(2, i),
hkl(3, i), f_calc(1, i), f_calc(2, i);
 
There is a large open source template library supporting this statement
from Fortran to C++ Fable software.
 
Thanks,
Lynn
Lynn McGuire <lynnmcguire5@gmail.com>: Sep 30 12:01AM -0500

On 9/29/2022 11:48 PM, Lynn McGuire wrote:
> from Fortran to C++ Fable software.
 
> Thanks,
> Lynn
 
If interested, you can see the Fable FEM (Fortran Emulation) code at:
https://cci.lbl.gov/fable/
 
Lynn
Lynn McGuire <lynnmcguire5@gmail.com>: Sep 30 12:03AM -0500

On 9/30/2022 12:01 AM, Lynn McGuire wrote:
 
> If interested, you can see the Fable FEM (Fortran Emulation) code at:
>    https://cci.lbl.gov/fable/
 
> Lynn
 
Specifically at:
https://cci.lbl.gov/fable/sources/fable/fem/
 
Lynn
James Kuyper <jameskuyper@alumni.caltech.edu>: Sep 30 01:05AM -0400

On 9/30/22 00:48, Lynn McGuire wrote:
> hkl(3, i), f_calc(1, i), f_calc(2, i);
 
> There is a large open source template library supporting this statement
> from Fortran to C++ Fable software.
 
 
 
If write, hkl, and f_calc are macros, you cannot be sure without
examining the macro definitions. However, if any of those three is an
ordinary function, it seems to me that this statement does unnecessarily
use the comma operator.
red floyd <no.spam.here@its.invalid>: Sep 29 10:45PM -0700

On 9/29/2022 10:05 PM, James Kuyper wrote:
> examining the macro definitions. However, if any of those three is an
> ordinary function, it seems to me that this statement does unnecessarily
> use the comma operator.
 
Not to mention that write() has an incorrect number of parameters,
assuming POSIX.
Gawr Gura <gawrgura@mail.hololive.com>: Sep 29 11:19PM -0700

> from Fortran to C++ Fable software.
 
> Thanks,
> Lynn
 
Assuming you're looking at the same example file on the fable web page
as I am (sf.cpp at line 113) then I think the answer is yes. I believe
this is a series of calls to fem::write_loop::operator,()
scott@slp53.sl.home (Scott Lurndal): Sep 30 03:16PM

>> use the comma operator.
 
>Not to mention that write() has an incorrect number of parameters,
>assuming POSIX.
 
The write here is an analog of the fortran write,
 
WRITE unit,format,iolist
 
And yes, it will conflict with the Unix (and POSIX) write function signature.
Lynn McGuire <lynnmcguire5@gmail.com>: Sep 30 01:31PM -0500

On 9/30/2022 1:19 AM, Gawr Gura wrote:
 
> Assuming you're looking at the same example file on the fable web page
> as I am (sf.cpp at line 113) then I think the answer is yes. I believe
> this is a series of calls to fem::write_loop::operator,()
 
Yes, that does seem to be true.
 
Thanks,
Lynn
David Brown <david.brown@hesbynett.no>: Sep 30 09:17AM +0200

On 29/09/2022 19:58, Kaz Kylheku wrote:
> ["Followup-To:" header set to comp.lang.c.]
 
Would you /please/ stop doing that? It messes up the threads, giving a
disjointed view in both groups with some posts missing and others
appearing from nowhere as people correct your inappropriate follow-up
groups.
 
If you want to talk about C specifically, start a thread in comp.lang.c.
 
If you want to talk about C++ specifically, start a thread in comp.lang.c++.
 
When a thread is discussing both languages, such as this one (look at
the subject), and everyone else is keeping both newsgroups in the
followups, then you should do that too.
 
 
There are only two good reasons why you should consider setting
followups. One is if a branch is clearly diverging to a side-topic that
is applicable to one group only, and is of no interest to people in the
other group. This will normally be accompanied by a subject change.
 
The other is when someone posts to the wrong group, and you are
informing them of where they ought to be.
 
Neither applies here.
 
Note that "I only follow the one group comp.lang.c" is /not/ a relevant
reason. Your follow-up settings mess up things particularly badly for
those that happen to follow only comp.lang.c++.
 
 
Your posts in this thread are as topical, relevant and interesting in
both groups.
Kaz Kylheku <864-117-4973@kylheku.com>: Sep 30 04:39PM

> disjointed view in both groups with some posts missing and others
> appearing from nowhere as people correct your inappropriate follow-up
> groups.
 
The question is, why do I do that? It's a bad idea in most cases.
 
The workflow is that SLRN, in the cross-posting situation, brings up a a
prompt like this:
 
Crosspost using: (F)ollowup-To, (A)ll groups, (T)his group, (C)ancel
 
There are times when I hit 'f' by mistake. (Could it be because 'f' is also
the command for initiating the follow-up in the first place?)
Among those times, there are times when I subsequently neglect to edit out the
header associated body line. Maybe I jump to the bottom too fast,
that being the fundamental race in Usenet, and all.
 
Drilling into it now, I see that if the configuration option
netiquette_warnings is set to 0, the prompt goes away, and the (A)ll
behavior prevails.
 
It's unfortunate that the warnings are lumped together under one
option like that. I'd like to be warned if there is too much quoted
material, or long lines and such.
 
It can be solved in another way: Vim can easily be programmed to
dispatch an action when a file named .followup is opened; that
can be used to make some automatic edits.
 
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Kaz Kylheku <864-117-4973@kylheku.com>: Sep 30 05:20PM

[ Apologies for having had diverted this subthread to comp.lang.c ]
>> correct code is by by developing tools, and using them.
 
> Sure. In particular, they are responsible for learning the tools and
> using them properly to maximal effect for the task in hand.
 
This is a basic principle in the field and pretty much any other
professional field; as such, it doesn't really inform.
 
It's true whether you're toggling switches on a panel to produce
a binary program directly in memory, or whether you're using OCaml
or Prolog.
 
Yet it is empirically valid that those diverse alternatives
don't have the same safety, and we evolve things accordingly.
 
Speaking of returning the cross-posting to comp.lang.c++, that language
as of C++17 has chosen to define some evaluation orders.
 
The evaluation order of function arguments is not yet defined, but
now there is a sequence point between the argument expressions.
 
That is obviouslly super important, because now the unspecified behavior
stays unspecified when there are side effects like:
 
f(i++, i++);
 
it doesn't help with the situation
 
f(g(), h())
 
because those calls are sequenced. However, it helps in the
argument space: with just the classic sequencing of function calls not
being interleaved, this is still undefined:
 
f(g(i++), h(i++))
 
whereas by my understanding C++17 leaves it unspecified in which order g
and h will be called, and which one will have receive the original value
of i. But, I think, we can infer that that function which is called
first receives the original value of i, and i is reliably incremented
twice. Baby steps in the right direction, in any case.
 
I don't understand the rationale for sequencing A before B in A << B
(what is so special about shifting); there must be some motivating
example where you have a side effect in A that B depends on. What I'm
likely missing that it's probably not the built-in arithmetic << that is
of concern, but overloads.
 
> It is not the language that is at fault if someone writes code that
> relies on execution order that is left unspecified by the standards -
> it's the programmers' fault.
 
It's not a game of blame, but of reducing the unfortunate situations in
which someone has a reason to look for something to blame.
 
I can't look at a large body of code (that I perhaps didn't write: so no
responsibility of mine) and easily know whether there is a problem due
to eval order. If I'm charged with the responsibility of finding out,
I could just give a quick answer "almost certainly no, modulo compiler
bugs" if eval order is defined by the language, without any effort. (On
the other hand, that leaves money on the table, doesn't it! Now I have
to find alternative ways to get paid for the saved hours.)
 
Scrambled eval orders in a language in which side effects are the
principal means of getting anything done is a poor technical situation.
 
--
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Paavo Helde <eesnimi@osa.pri.ee>: Sep 30 08:59PM +0300

30.09.2022 20:20 Kaz Kylheku kirjutas:
 
> Scrambled eval orders in a language in which side effects are the
> principal means of getting anything done is a poor technical situation.
 
That must be some other language. I have never written any C++ code
where side effects were the principal means of getting something done.
 
If anything, C++ in general has moved towards more functional style over
the years, with fewer mutable objects, not to speak about objects
mutated by side effects.
Juha Nieminen <nospam@thanks.invalid>: Sep 30 07:12AM

> It is interesting that problem occurs only when debugging. Program run
> from prompt works fine, without the problem.
 
That's completely normal. Just because it seems to "work fine" that
doesn't mean there isn't a problem (it just so happens that it isn't
crashing in that particular situation).
 
You should still create the minimal complete program that demonstrates
the problem.
Juha Nieminen <nospam@thanks.invalid>: Sep 30 07:13AM

>> from prompt works fine, without the problem.
 
> Ah, you mean there is no bug, just the debugger is displaying some
> misleading messages? In that case, welcome to the club!
 
Are you being sarcastic?
 
Rather obviously just because a release build of the program doesn't
happen to crash in a particular situation doesn't mean there is no bug.
"Alf P. Steinbach" <alf.p.steinbach@gmail.com>: Sep 30 10:36AM +0200

On 28 Sept 2022 13:53, Jivanmukta wrote:
> ...
> for (auto dir = vendor_frameworks_dirs.begin(); dir !=
> vendor_frameworks_dirs.end(); ++dir)
 
Post a complete but minimal example that demonstrates the problem.
 
Alan Turing professed to believe in ESP, but we don't.
 
- Alf
Paavo Helde <eesnimi@osa.pri.ee>: Sep 30 03:56PM +0300

30.09.2022 10:13 Juha Nieminen kirjutas:
 
>> Ah, you mean there is no bug, just the debugger is displaying some
>> misleading messages? In that case, welcome to the club!
 
> Are you being sarcastic?
 
No, I had got an impression he is complaining about something which he
sees in his debugger only. The debuggers are known to sometimes display
invalid or misleading information. I might be wrong, it is hard to say
what OP meant by the phrase "while debugging".
 
 
> Rather obviously just because a release build of the program doesn't
> happen to crash in a particular situation doesn't mean there is no bug.
 
The reported "crash" is basically an assert failure in a debug feature,
so a proper Release build would obviously not have it. However, the OP
did not talk anything about running a Release build, he just said
"Program run from prompt works fine". I assumed that was the same Debug
build, but I might be mistaken.
Muttley@dastardlyhq.com: Sep 30 01:50PM

On Thu, 29 Sep 2022 22:19:05 +0300
>> The error described by me makes debugging problematic.
 
>Well, use a better debugger then. My debugger (Visual Studio) does not
>display such error messages.
 
It just randomly skips lines during stepping depending on the optimisation
level. Very helpful.
Paavo Helde <eesnimi@osa.pri.ee>: Sep 30 05:04PM +0300

>> display such error messages.
 
> It just randomly skips lines during stepping depending on the optimisation
> level. Very helpful.
 
If the line has been optimized away or moved to another place, it cannot
be really stepped into.
 
Debugging optimized code is a dark art anyway. Hopefully the compiler
vendors will not listen to the advocates for applying some optimizations
always, regardless of the optimization level.
 
With gdb I have the opposite problem, it dutifully steps into std code
like string contstructors. It's basically impossible to step into my own
function if there are any non-trivial arguments in the function call.
Jivanmukta <jivanmukta@poczta.onet.pl>: Sep 30 04:21PM +0200

W dniu 30.09.2022 o 14:56, Paavo Helde pisze:
> sees in his debugger only. The debuggers are known to sometimes display
> invalid or misleading information. I might be wrong, it is hard to say
> what OP meant by the phrase "while debugging".
 
When I debug my program in Codium the programs stops and I receive
mentioned error.
> did not talk anything about running a Release build, he just said
> "Program run from prompt works fine". I assumed that was the same Debug
> build, but I might be mistaken.
 
I run debug build from prompt. I don't compile to release.
Muttley@dastardlyhq.com: Sep 30 03:03PM

On Fri, 30 Sep 2022 17:04:07 +0300
>> level. Very helpful.
 
>If the line has been optimized away or moved to another place, it cannot
>be really stepped into.
 
Thats fair enough, but since it knows the code isn't there it should flag up
in the code window that its been optimised away rather than just jumping
ahead.
 
 
>With gdb I have the opposite problem, it dutifully steps into std code
>like string contstructors. It's basically impossible to step into my own
>function if there are any non-trivial arguments in the function call.
 
There is a way to avoid that but I can't remember how off the top of my head.
You'll have to google.
scott@slp53.sl.home (Scott Lurndal): Sep 30 03:19PM


>Debugging optimized code is a dark art anyway. Hopefully the compiler
>vendors will not listen to the advocates for applying some optimizations
>always, regardless of the optimization level.
 
I suspect that most compilers always do simple optimizations
such as constant folding or peephole optimizations such as
replacing multiply/divide with shifts regardless of the optimization level.
Juha Nieminen <nospam@thanks.invalid>: Sep 30 04:09PM

> When I debug my program in Codium the programs stops and I receive
> mentioned error.
 
Just create the minimal complete program that exhibits the problem, so
we can put this to rest.
Louis Krupp <lkrupp@invalid.pssw.com.invalid>: Sep 30 11:01AM -0600

> Thats fair enough, but since it knows the code isn't there it should flag up
> in the code window that its been optimised away rather than just jumping
> ahead.
 
The debugger might not know that the code was optimized away. If it's
not there, it's not there.
 
Louis
Bonita Montero <Bonita.Montero@gmail.com>: Sep 30 06:51PM +0200

double myFmod( double divisor, double dividend )
{
auto bin = []( double d ) -> uint64_t { return bit_cast<uint64_t>( d ); };
auto dbl = []( uint64_t u ) -> double { return bit_cast<double>( u ); };
uint64_t
bDivisor = bin( divisor ),
bDividend = bin( dividend );
constexpr uint64_t
SIGN_BIT = (uint64_t)1 << 63,
EXP_MASK = (uint64_t)0x7FF << 52,
IMPLCIT_BIT = (uint64_t)1 << 52,
MANT_MASK = IMPLCIT_BIT - 1,
QNAN_BIT = IMPLCIT_BIT >> 1;
uint64_t sign = (bDivisor ^ bDividend) & SIGN_BIT;
if( (bDividend & EXP_MASK) == EXP_MASK ) [[unlikely]]
// ... % +/-[Inf|QNan|SNaN]
if( !(bDividend & MANT_MASK) ) [[likely]]
// ... % +/-Inf
if( (bDivisor & EXP_MASK) != EXP_MASK ) [[unlikely]]
// +/-x % +/-Inf = -/+x
return dbl( sign | bDivisor & ~SIGN_BIT );
else if( !(bDivisor & MANT_MASK) ) [[likely]]
// +/-Inf % +/-Inf = -QNaN
return dbl( SIGN_BIT | EXP_MASK | QNAN_BIT );
else
{
// +/-[QNaN|SNaN] % +/-Inf = -[QNaN|SNaN]
if( !(bDivisor & QNAN_BIT) )
feraiseexcept( FE_INVALID );
return dbl( SIGN_BIT | bDivisor );
}
else if( bDividend & QNAN_BIT ) [[likely]]
// ... % +/-QNaN
if( (bDivisor & EXP_MASK) != EXP_MASK ) [[likely]]
// +/-x % +/-QNaN = -QNaN
return dbl( SIGN_BIT | bDivisor | bDividend );
else if( !(bDivisor & MANT_MASK) ) [[likely]]
// +/-Inf % +/-QNaN = -QNaN
return dbl( SIGN_BIT | bDivisor | bDividend );
else
{
// +/-[QNaN|SNaN] % +/-QNaN = -[QNaN|SNaN]
if( ~bDivisor & QNAN_BIT ) [[unlikely]]
feraiseexcept( FE_INVALID );
return dbl( SIGN_BIT | (bDivisor | bDividend) & ~(~bDivisor &
QNAN_BIT) );
}
else
{
// ... % +/-SNaN = -SNaN
feraiseexcept( FE_INVALID );
return dbl( (SIGN_BIT | bDivisor | bDividend) & ~QNAN_BIT );
}
if( (bDivisor & EXP_MASK) == EXP_MASK ) [[unlikely]]
// +/-[Inf|QNan|SNaN] / +/-x
if( !(bDivisor & MANT_MASK) ) [[likely]]
// +/-Inf % +/-x = -QNaN
return dbl( SIGN_BIT | EXP_MASK | QNAN_BIT );
else if( bDivisor & QNAN_BIT ) [[likely]]
// +/-QNaN % +/-x = -QNaN
return dbl( SIGN_BIT | bDivisor | bDividend );
else
{
// +/-SNaN % +/-x = -SNaN
feraiseexcept( FE_INVALID );
return dbl( SIGN_BIT | (bDivisor | bDividend) & ~QNAN_BIT );
}
int
divisorExp = (bDivisor & EXP_MASK) >> 52,
dividendExp = (bDividend & EXP_MASK) >> 52;
uint64_t
divisorMant = IMPLCIT_BIT | bDivisor & MANT_MASK,
dividendMant = IMPLCIT_BIT | bDividend & MANT_MASK;
auto normalize = []( uint64_t &mant, int &exp )
{
mant &= MANT_MASK;
unsigned shift = countl_zero( mant ) - 11;
mant <<= shift;
exp -= shift - 1;
};
if( !divisorExp ) [[unlikely]]
if( !(bDivisor & MANT_MASK) ) [[likely]]
// +/-0.0 % +/-x = -/+0.0
return dbl( sign );
else
// divisor is +/-denorm -> normalize
normalize( divisorMant, divisorExp );
if( !dividendExp ) [[unlikely]]
if( !(bDividend & MANT_MASK) ) [[likely]]
// +/-x % +/-0.0 = -/+QNaN
return dbl( sign | EXP_MASK | QNAN_BIT );
else
// dividend is +/-denorm -> normalize
normalize( dividendMant, dividendExp );
int exp = divisorExp;
uint64_t remainderMant = divisorMant;
for( ; ; )
{
int below = remainderMant < dividendMant;
if( exp - below < dividendExp ) [[unlikely]]
break;
exp -= below;
remainderMant <<= below;
if( !(remainderMant -= dividendMant) ) [[unlikely]]
return dbl( sign );
unsigned shift = (unsigned)countl_zero( remainderMant ) - 11;
remainderMant <<= shift;
exp -= shift;
}
if( exp <= 0 ) [[unlikely]]
// denormal result
remainderMant >>= -exp + 1,
exp = 0;
return dbl( sign | (uint64_t)exp << 52 | remainderMant & MANT_MASK );
}
Frederick Virchanza Gotham <cauldwell.thomas@gmail.com>: Sep 30 03:46AM -0700

Let's say you have a linker invocation as follows:
 
g++ -o prog *.o -lmonkey -lcow -lfish -ldog
 
I've written a program that parses your linker command and tries it without each of the libraries. If the linking succeeds, then it tells you that the library in question isn't needed.
 
Sample invocation:
 
./linker_reducer "g++ -o prog *.o -pthread -lwx_gtk3u_xrc-3.1 -lwx_gtk3u_html-3.1 -lwx_gtk3u_qa-3.1 -lwx_gtk3u_core-3.1 -lwx_baseu_xml-3.1 -lwx_baseu_net-3.1 -lwx_baseu-3.1 -lpcap -lpthread -ldl"
 
Sample output:
 
Trying without '-lwx_gtk3u_xrc-3.1' [SUCCESS]
Trying without '-lwx_gtk3u_html-3.1' [SUCCESS]
Trying without '-lwx_gtk3u_qa-3.1' [SUCCESS]
Trying without '-lwx_gtk3u_core-3.1' [FAILURE]
Trying without '-lwx_baseu_xml-3.1' [SUCCESS]
Trying without '-lwx_baseu_net-3.1' [SUCCESS]
Trying without '-lwx_baseu-3.1' [FAILURE]
Trying without '-lpcap' [SUCCESS]
Trying without '-lpthread' [SUCCESS]
Trying without '-ldl' [SUCCESS]
 
Not needed:
-lwx_gtk3u_xrc-3.1
-lwx_gtk3u_html-3.1
-lwx_gtk3u_qa-3.1
-lwx_baseu_xml-3.1
-lwx_baseu_net-3.1
-lpcap
-lpthread
-ldl
 
Revised Linker invocation command:
 
g++ -o prog *.o -pthread -lwx_gtk3u_core-3.1 -lwx_baseu-3.1
 
Here's the source code. Tested and working on Linux. Probably works on MS-Windows.
 
#include <cstddef> // size_t
#include <cstdlib> // system, EXIT_FAILURE
#include <algorithm> // max
#include <tuple> // tuple, std::get<>
#include <vector> // vector
#include <string> // string
#include <string_view> // string_view
#include <regex> // regex
#include <iostream> // cout, endl
 
using std::size_t;
using std::string;
using std::sregex_iterator;
using std::cout;
using std::endl;
 
// The vector on the next line works as follows:
// { true /* is_required */, char_index_of_library_in_string, "library_string" };
std::vector< std::tuple<bool, size_t, string> > g_libs;
 
string Remove_Library(std::string_view const sv, size_t const index)
{
string s(sv);
 
std::tuple<bool, size_t, string> const &x = g_libs.at(index);
 
s.erase( std::get<1u>(x), std::get<2u>(x).size() );
 
return s;
}
 
int main(int const argc, char **const argv)
{
if ( argc < 2u || argc > 3u )
{
cout << "This program takes two command line arguments.\n"
"The first is the full linker invocation command, and\n"
"the second is the regex to match a library. For example:\n\n"
" " << argv[0u] << " \"g++ -o prog *.cpp -lmonkey -lcow\" -l[^\\s]+" << "\n\n";
 
return EXIT_FAILURE;
}
 
string linker_command{ argv[1u] };
 
std::regex const my_regex{ (3u == argc) ? argv[2u] : "-l[^\\s]+" };
 
size_t longest_library_name = 0u;
 
for ( sregex_iterator it = sregex_iterator(linker_command.begin(), linker_command.end(), my_regex);
it != sregex_iterator();
++it )
{
std::smatch const m{ *it };
 
//cout << m.str() << " at position " << m.position() << " with length " << m.str().size() << '\n';
 
g_libs.emplace_back(std::tuple<bool, size_t, string>(true, m.position(), m.str()));
 
longest_library_name = std::max(longest_library_name, m.str().size());
}
 
size_t i = -1;
for ( auto &e : g_libs )
{
++i;
 
string revised_linker_command( Remove_Library(linker_command,i) );
 
cout << "Trying without '" << std::get<2u>(e) << "' ";
 
for ( size_t i = 0u; i < (longest_library_name - std::get<2u>(e).size()); ++i ) cout << " ";
 
cout << std::flush;
 
#if defined(_WIN32) || defined(_WIN64)
revised_linker_command += " > NUL 2> NUL";
#else
revised_linker_command += " > /dev/null 2> /dev/null";

No comments: