Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #174243 > unrolled thread

Re: bart again (UCX64)

Started bycandycane@f172.n1.z21.fsxnet (candycane)
First post2023-09-06 19:53 +1300
Last post2023-09-09 10:23 -0700
Articles 20 on this page of 129 — 12 participants

Back to article view | Back to comp.lang.c


Contents

  Re: bart again (UCX64) candycane@f172.n1.z21.fsxnet (candycane) - 2023-09-06 19:53 +1300
    Re: bart again (UCX64) Richard Damon <Richard@Damon-Family.org> - 2023-09-07 12:00 -0700
      Re: bart again (UCX64) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-09-07 16:33 -0700
        Re: bart again (UCX64) Richard Damon <Richard@Damon-Family.org> - 2023-09-07 20:55 -0700
          Re: bart again (UCX64) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-09-07 22:16 -0700
            Re: bart again (UCX64) Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-08 07:09 +0000
              Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-08 10:10 +0200
                Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-08 01:30 -0700
                  Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-08 11:26 +0200
                    Re: bart again (UCX64) Bart <bc@freeuk.com> - 2023-09-08 10:44 +0100
                      Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-08 13:26 +0200
                        Re: bart again (UCX64) Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-09 01:57 +0000
                          Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-09 18:36 +0200
                            Re: bart again (UCX64) Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-09 18:19 +0000
                              Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-10 13:28 +0200
                                Re: bart again (UCX64) Bart <bc@freeuk.com> - 2023-09-10 13:20 +0100
                                  Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-10 15:19 +0200
                                    Re: bart again (UCX64) Bart <bc@freeuk.com> - 2023-09-10 16:07 +0100
                                      Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-10 18:33 +0200
                                Re: bart again (UCX64) Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-10 15:44 +0000
                                  Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-10 18:36 +0200
                      Re: bart again (UCX64) Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-09 01:48 +0000
                        Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-09 19:04 +0200
                    Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-08 02:47 -0700
                      Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-08 16:03 +0200
                        Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-08 16:06 -0700
                          Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-09 01:52 +0100
                            Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-08 18:16 -0700
                              Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-09 21:31 +0100
                          Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-10 12:03 +0200
                            Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-10 21:36 -0700
                              Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-11 08:51 +0200
                                Re: bart again (UCX64) "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2023-09-10 23:59 -0700
                                Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-11 01:01 -0700
                                  Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-11 11:17 +0200
                                    Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-11 03:16 -0700
                                      Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-11 14:58 +0200
                                        Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-11 06:35 -0700
                                          Re: bart again (UCX64) Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-11 14:13 +0000
                                          Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-11 16:24 +0200
                                        Re: bart again (UCX64) Bart <bc@freeuk.com> - 2023-09-11 14:55 +0100
                                          Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-11 16:42 +0200
                                        Re: bart again (UCX64) Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-11 14:29 +0000
                                Re: bart again (UCX64) Bart <bc@freeuk.com> - 2023-09-11 11:25 +0100
                                  Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-11 03:59 -0700
                                    Re: bart again (UCX64) Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-11 13:57 +0000
                                      Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-11 09:52 -0700
                                  Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-11 16:07 +0200
                                  Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-11 16:26 +0100
                                    Re: bart again (UCX64) Bart <bc@freeuk.com> - 2023-09-11 16:47 +0100
                                      Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-11 19:14 +0200
                                      Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-11 22:30 +0100
                                        Re: bart again (UCX64) Bart <bc@freeuk.com> - 2023-09-11 23:07 +0100
                                          Re: bart again (UCX64) scott@slp53.sl.home (Scott Lurndal) - 2023-09-11 23:31 +0000
                                            Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-12 09:18 +0200
                                          Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-12 03:01 +0100
                                    Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-11 10:08 -0700
                                      Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-11 23:18 +0100
                                        Re: bart again (UCX64) Bart <bc@freeuk.com> - 2023-09-11 23:37 +0100
                                          Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-11 15:46 -0700
                                            Re: bart again (UCX64) scott@slp53.sl.home (Scott Lurndal) - 2023-09-11 23:40 +0000
                                              Re: bart again (UCX64) Bart <bc@freeuk.com> - 2023-09-12 01:50 +0100
                                                Re: bart again (UCX64) Richard Damon <Richard@Damon-Family.org> - 2023-09-11 17:59 -0700
                                                Re: bart again (UCX64) scott@slp53.sl.home (Scott Lurndal) - 2023-09-12 01:03 +0000
                                                Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-12 02:39 +0100
                                                  Re: bart again (UCX64) Bart <bc@freeuk.com> - 2023-09-12 11:28 +0100
                                                    Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-12 14:49 +0100
                                                      Re: bart again (UCX64) Bart <bc@freeuk.com> - 2023-09-12 15:18 +0100
                                          Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-12 03:58 +0100
                                            Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-12 02:25 -0700
                                              Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-12 16:17 +0100
                                                Re: bart again (UCX64) Bart <bc@freeuk.com> - 2023-09-12 17:28 +0100
                                                  Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-12 21:07 +0200
                                                    Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-13 03:01 +0100
                                                      Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-13 09:38 +0200
                                                        Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-13 10:00 +0200
                                                      Re: bart again (UCX64) Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-09-19 05:22 -0700
                                                        Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-19 14:29 +0100
                                                  Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-13 13:35 +0100
                                                    Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-13 20:48 +0100
                                                    Re: bart again (UCX64) Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-09-19 05:53 -0700
                                                Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-12 09:33 -0700
                                                  Re: bart again (UCX64) scott@slp53.sl.home (Scott Lurndal) - 2023-09-12 16:48 +0000
                                                    Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-12 10:57 -0700
                                                      Re: bart again (UCX64) scott@slp53.sl.home (Scott Lurndal) - 2023-09-12 18:07 +0000
                                                        Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-12 21:23 +0200
                                                          Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-13 02:07 -0700
                                                            Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-13 12:43 +0200
                                                              Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-13 04:04 -0700
                                                                Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-13 14:07 +0200
                                                        Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-13 01:47 -0700
                                                          Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-13 13:02 +0200
                                                            Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-13 04:45 -0700
                                                              Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-13 14:36 +0200
                                                                Re: bart again (UCX64) scott@slp53.sl.home (Scott Lurndal) - 2023-09-13 13:43 +0000
                                                                  Re: bart again (UCX64) James Kuyper <jameskuyper@alumni.caltech.edu> - 2023-09-13 11:10 -0400
                                                                    Re: bart again (UCX64) Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-13 17:12 +0000
                                                                      [meta] spam in thread Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-13 11:22 -0700
                                                                        Re: [meta] spam in thread Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-13 18:40 +0000
                                                                          Re: [meta] spam in thread Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-13 11:48 -0700
                                                                        Re: [meta] spam in thread David Brown <david.brown@hesbynett.no> - 2023-09-13 21:01 +0200
                                                                      Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-13 19:58 +0100
                                                                  Re: bart again (UCX64) Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-09-18 12:36 -0700
                                                                    Re: bart again (UCX64) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-09-18 13:40 -0700
                                                                      Re: bart again (UCX64) Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-09-20 19:43 -0700
                                                                        Re: bart again (UCX64) "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2023-09-20 20:14 -0700
                                                                        Re: bart again (UCX64) Keith Thompson <Keith.S.Thompson+u@gmail.com> - 2023-09-20 22:10 -0700
                                                                          Re: bart again (UCX64) Tim Rentsch <tr.17687@z991.linuxsc.com> - 2023-10-01 11:03 -0700
                                                                Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-13 07:39 -0700
                                                                  Re: bart again (UCX64) scott@slp53.sl.home (Scott Lurndal) - 2023-09-13 15:18 +0000
                                                                  Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-13 18:39 +0200
                                                  Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-13 15:44 +0100
                                                    Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-13 08:42 -0700
                                                      Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-13 22:35 +0100
                                                    Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-13 18:49 +0200
                                        Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-11 15:40 -0700
                                          Re: bart again (UCX64) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2023-09-12 03:36 +0100
                                          Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-12 12:58 +0200
                                      Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-12 12:49 +0200
                                        Re: bart again (UCX64) Bart <bc@freeuk.com> - 2023-09-12 12:52 +0100
                                          Re: bart again (UCX64) Malcolm McLean <malcolm.arthur.mclean@gmail.com> - 2023-09-12 05:22 -0700
                                          Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-12 15:05 +0200
                    Re: bart again (UCX64) Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-09 02:17 +0000
                      Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-10 14:44 +0200
                  Re: bart again (UCX64) scott@slp53.sl.home (Scott Lurndal) - 2023-09-08 14:36 +0000
                    Re: bart again (UCX64) Kaz Kylheku <864-117-4973@kylheku.com> - 2023-09-09 01:50 +0000
                      Re: bart again (UCX64) scott@slp53.sl.home (Scott Lurndal) - 2023-09-09 15:40 +0000
            Re: bart again (UCX64) David Brown <david.brown@hesbynett.no> - 2023-09-08 09:57 +0200
            Re: bart again (UCX64) Richard Damon <Richard@Damon-Family.org> - 2023-09-09 10:23 -0700

Page 2 of 7 — ← Prev page 1 [2] 3 4 5 6 7  Next page →


#174847

FromDavid Brown <david.brown@hesbynett.no>
Date2023-09-10 18:36 +0200
Message-ID<udkrau$kuso$2@dont-email.me>
In reply to#174844
On 10/09/2023 17:44, Kaz Kylheku wrote:
> On 2023-09-10, David Brown <david.brown@hesbynett.no> wrote:

>> I don't see "unreachable()" as saying "insert UB here".
> 
> But you must think of it that way, if it is specified that way
> in its documentation. E.g. the GCC one:
> 
>    Built-in Function: void __builtin_unreachable (void)
> 
>      If control flow reaches the point of the __builtin_unreachable, the
>      program is undefined. It is useful in situations where the compiler
>      cannot deduce the unreachability of the code.
> 

I know how it works (I have read most of the gcc manual, and I read that 
description before first using __builtin_unreachable).  But if you read 
that sentence, it is a conditional - "/if/ control flow reaches the 
point...".  Control flow will /not/ reach the point in my code that has 
"unreachable()", thus no undefined behaviour is introduced.

[toc] | [prev] | [next] | [standalone]


#174664

FromKaz Kylheku <864-117-4973@kylheku.com>
Date2023-09-09 01:48 +0000
Message-ID<20230908184633.897@kylheku.com>
In reply to#174517
On 2023-09-08, Bart <bc@freeuk.com> wrote:
> It's funny that some people don't want the bother of writing 'return 0;' 
> in a path they know will never be reached, while others are prepared to 
> write 'unreachable();', which is both longer and uses shifted characters.

What is worse, the original program with a missing "return 0;" might
well be correct. If the caller doesn't extract the return value,
everything is copacetic.

Whereas unreachable() is a gizmo whose only meaning is that it invokes
undefined behavior if executed!

It's like you have a pepper shaker on your programing table labeled
"UB", and you sprinkle that on your program.

-- 
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @Kazinator@mstdn.ca
NOTE: If you use Google Groups, I don't see you, unless you're whitelisted.

[toc] | [prev] | [next] | [standalone]


#174735

FromDavid Brown <david.brown@hesbynett.no>
Date2023-09-09 19:04 +0200
Message-ID<udi8i5$52sl$4@dont-email.me>
In reply to#174664
On 09/09/2023 03:48, Kaz Kylheku wrote:
> On 2023-09-08, Bart <bc@freeuk.com> wrote:
>> It's funny that some people don't want the bother of writing 'return 0;'
>> in a path they know will never be reached, while others are prepared to
>> write 'unreachable();', which is both longer and uses shifted characters.
> 
> What is worse, the original program with a missing "return 0;" might
> well be correct. If the caller doesn't extract the return value,
> everything is copacetic.
> 
> Whereas unreachable() is a gizmo whose only meaning is that it invokes
> undefined behavior if executed!
> 
> It's like you have a pepper shaker on your programing table labeled
> "UB", and you sprinkle that on your program.
> 

That's the joy of undefined behaviour :-)

Several years back, I had to deal with finding bugs in a code base where 
the programmer had regularly muddled up function parameters and return 
types.  Most people like to have global functions declared in a header, 
and include that header in the C file that defines the function and any 
C files that use the function - then they get everything nice and 
consistent.  The code base that this programmer had started with, before 
he screwed around with it, was organised like that.  (I know - I wrote 
it, and my gcc setup will complain loudly if there are any missing or 
mismatched declarations.)  But this guy frequently didn't bother 
including headers, or declaring his global functions in headers. 
Sometimes he had an extern declaration in the C file, sometimes he 
relied on ancient implicit function declaration.  And he got it wrong - 
a lot.  Functions would be defined with one set of parameters, and 
called from different C files with a different number or different type 
of parameters.  Return types were equally random.

But you can't just replace a missing "return x;" with "return 0;", even 
though the behaviour is defined.  Sometimes the code without the return 
statement works by sheer luck, which the "return 0;" is a guaranteed and 
consistent failure.

It had one feature I've never seen before, tying in with another thread 
here - it called main() recursively.  From within an interrupt handler.


[toc] | [prev] | [next] | [standalone]


#174518

FromMalcolm McLean <malcolm.arthur.mclean@gmail.com>
Date2023-09-08 02:47 -0700
Message-ID<543b9acc-de99-425c-bb1d-485e9f98889dn@googlegroups.com>
In reply to#174513
On Friday, 8 September 2023 at 10:27:12 UTC+1, David Brown wrote:
> On 08/09/2023 10:30, Malcolm McLean wrote: 
> > On Friday, 8 September 2023 at 09:10:20 UTC+1, David Brown wrote: 
> >> 
> >> Note that since trying to execute "unreachable()" (as the C23 function 
> >> is called) is undefined behaviour, compilers can freely add debugging 
> >> and fault-finding options to give a run-time diagnostic if the code is 
> >> actually reached. But if the standard had defined the behaviour of 
> >> "unreachable()" to be somewhat like "abort()", compilers would not be 
> >> free to use it for efficient optimisation, or to aid static analysis. 
> >> 
> > The difference is that the programmer might want to deliberately call 
> > abort() as part of the expected runtime behaviour of the program. Whilst 
> > unreachable() can only be called if he has made a programming error. 
> > However he might want to fall back to defined behaviour in the case of 
> > such an error.
> If a programmer wants such behaviour, then he or she should know how to 
> write it.
> > However compilers can run unreachable code tests which would otherwise 
> > be too expensive if they encounter an unreachable() statement. What 
> > they can't do is use the unreachable() statement as a proof that the 
> > code is in fact unreachable.
> Compilers can, and do, do exactly that. C is very much a "trust the 
> programmer" language, not a hand-holding language. If I write 
> "unreachable();", I expect my compiler to believe me and trust that the 
> code cannot ever be reached (or that I don't care what happens if it 
> /is/ reached). I don't want it to add extra code to check if the code 
> is reached, or to call abort() if it is reached. What I want is for the 
> compiler to use that extra information to make other code more 
> efficient, and to allow more compile-time warnings and static error 
> checking. 
> 
> That's the deal with C - the compiler believes the programmer, and the 
> programmer is careful not to lie to the compiler. If you don't like 
> that, pick a different programming language. 
> 
> So if you are not sure the code point is unreachable, don't "call" 
> unreachable(). It's very simple.
>
This is a basic misunderstanding you have shown before.

In your world, you should never wear a seatbelt, because if you are at
risk of crashing into the car in front, you shouldn't be driving.
Of course that's nonsense. Experienced driver will occasionally have
moment of inattention. Very rarely, this will produce an accident,
and then the seatbelt is a life saver. Of course most seatbelts are 
never used for their intended purpose. But it's still worth having.

Similarly, if you know that code cannot be reached, then unreachable()
can have undefined behaviour. But even experienced programmer make
mistakes. Less so maybe in the sort of programming you do. In
the sort of programming other people do, you often do have termination
conditions which depend on various mathematically proven properties
like convergence being correct. But of course threre could be a subtle
programming error which means that the mathematical property isn't
always met. 
 
So a defined behaviour fallback is potentially useful. "This can't happen, 
but if it does, give me this diagnostic".

[toc] | [prev] | [next] | [standalone]


#174578

FromDavid Brown <david.brown@hesbynett.no>
Date2023-09-08 16:03 +0200
Message-ID<udf9jn$3fta8$1@dont-email.me>
In reply to#174518
On 08/09/2023 11:47, Malcolm McLean wrote:
> On Friday, 8 September 2023 at 10:27:12 UTC+1, David Brown wrote:
>> On 08/09/2023 10:30, Malcolm McLean wrote:
>>> On Friday, 8 September 2023 at 09:10:20 UTC+1, David Brown wrote:
>>>>
>>>> Note that since trying to execute "unreachable()" (as the C23 function
>>>> is called) is undefined behaviour, compilers can freely add debugging
>>>> and fault-finding options to give a run-time diagnostic if the code is
>>>> actually reached. But if the standard had defined the behaviour of
>>>> "unreachable()" to be somewhat like "abort()", compilers would not be
>>>> free to use it for efficient optimisation, or to aid static analysis.
>>>>
>>> The difference is that the programmer might want to deliberately call
>>> abort() as part of the expected runtime behaviour of the program. Whilst
>>> unreachable() can only be called if he has made a programming error.
>>> However he might want to fall back to defined behaviour in the case of
>>> such an error.
>> If a programmer wants such behaviour, then he or she should know how to
>> write it.
>>> However compilers can run unreachable code tests which would otherwise
>>> be too expensive if they encounter an unreachable() statement. What
>>> they can't do is use the unreachable() statement as a proof that the
>>> code is in fact unreachable.
>> Compilers can, and do, do exactly that. C is very much a "trust the
>> programmer" language, not a hand-holding language. If I write
>> "unreachable();", I expect my compiler to believe me and trust that the
>> code cannot ever be reached (or that I don't care what happens if it
>> /is/ reached). I don't want it to add extra code to check if the code
>> is reached, or to call abort() if it is reached. What I want is for the
>> compiler to use that extra information to make other code more
>> efficient, and to allow more compile-time warnings and static error
>> checking.
>>
>> That's the deal with C - the compiler believes the programmer, and the
>> programmer is careful not to lie to the compiler. If you don't like
>> that, pick a different programming language.
>>
>> So if you are not sure the code point is unreachable, don't "call"
>> unreachable(). It's very simple.
>>
> This is a basic misunderstanding you have shown before.

No, I am not misunderstanding anything - but I think /you/ are greatly 
misunderstanding /me/.

> 
> In your world, you should never wear a seatbelt, because if you are at
> risk of crashing into the car in front, you shouldn't be driving.

Not at all - that is not even remotely equivalent.  I am surprised that 
someone as experience in programming as yourself does not see it 
immediately.

The risks when driving are unknowns - other people on the road, icy 
patches, kids jumping out in front of the car, etc.  Some things you 
have partial control over, such as how well you have learned to drive, 
others you don't - such as an unexpected sneeze.  These are all inputs - 
and your code should always check and sanitize input data from unknown 
sources.

Compile-time information is about the car and/or driver, not the trip. 
You check the seat is in the right position once, before starting, not 
every time you want to press a pedal.  You trust that the experts do 
their job - you don't open up the wheel mountings to see if the brakes 
are in order, but trust the mechanic at the workshop.  When you turn the 
steering wheel, the car's wheels turn - because the car "trusts" that 
the driver knows what he or she is doing.


And more relevantly, when writing software, you check the code at many 
stages - you check it when writing it, you test it at run-time, you have 
other people check it in code reviews, you have your static error 
checking software check what it can.  You don't whip together a bunch of 
code and deploy it on the basis of "it compiles, so it must be right - 
any serious issue would have given an error on compilation, not just a 
warning."  /That/ would be more akin to driving without a seat belt.



So - back to reality and programming.  I write "unreachable()" for parts 
of the code that I know can never be reached, because that is useful 
information to readers and the compiler.  I expect the compiler to trust 
me, and to make use of that information to optimise the code.  That's 
the compiler's job - I write in clear, high-level C code, and it turns 
that into efficient object code.

If I see someone has written code such as :

	abort();	// Can never reach this

I know that something in the development process is broken or 
untrustworthy.  Perhaps the programmer can't trust the compiler - there 
are occasions when people have no choice but to use poor quality tools, 
and even the best tools are not bug-free.  Perhaps the programmer is 
inexperienced, and thinks this is a good idea.  Perhaps the warnings 
used in the compiler complain if there is nothing there (such as if you 
use Bart's compiler in the examples discussed).  Perhaps the project 
manager is inexperienced, and thinks this is a case of being "doubly 
safe".  Certainly something is wrong.


> Of course that's nonsense. 

Yes, I agree - your analogy was utter nonsense.

> 
> Similarly, if you know that code cannot be reached, then unreachable()
> can have undefined behaviour. 

No.

We are talking here about run-time undefined behaviour.  Since the code 
line will never be reached when running the program, there cannot be 
undefined behaviour from it (or defined behaviour, for that matter - 
there is /no/ behaviour as it does not run).

> But even experienced programmer make
> mistakes. Less so maybe in the sort of programming you do. In
> the sort of programming other people do, you often do have termination
> conditions which depend on various mathematically proven properties
> like convergence being correct. But of course threre could be a subtle
> programming error which means that the mathematical property isn't
> always met.

If there is a possibility of the code reaching that point, 
"unreachable()" would not be appropriate.

It's a bit like noting that if you don't want to write some output to 
the terminal, writing "printf" is not appropriate.

What is so difficult about writing what you mean when programming?

Sure, programmers make mistakes.  That's why you have code reviews, and 
testing.  That's why you use a debugger, and sanitizers, and other 
tools.  That's why it is important to write code that you mean, and not 
nonsense that you don't mean.  And you don't write code that is 
untestable such as lines that cannot be reached, or code that makes no 
sense to a reviewer claiming to do something in impossible situations.

>   
> So a defined behaviour fallback is potentially useful. "This can't happen,
> but if it does, give me this diagnostic".

Where did you learn about logic?  From watching Monty Python?

Things that can't happen, can't happen.  If the thing /might/ happen, 
then it /can/ happen.

Do you think I write my code by guesswork?  Do you think I say to 
myself, "I guess this is unlikely, and I don't want to consider it - 
we'll pretend it it's impossible and tell the compiler its unreachable. 
I'm sure no one will notice" ?

[toc] | [prev] | [next] | [standalone]


#174644

FromMalcolm McLean <malcolm.arthur.mclean@gmail.com>
Date2023-09-08 16:06 -0700
Message-ID<7cf7b6bd-39d9-4e22-baee-e128cfb2f214n@googlegroups.com>
In reply to#174578
On Friday, 8 September 2023 at 15:03:51 UTC+1, David Brown wrote:
> On 08/09/2023 11:47, Malcolm McLean wrote: 
> 
> > So a defined behaviour fallback is potentially useful. "This can't happen, 
> > but if it does, give me this diagnostic".
> Where did you learn about logic? From watching Monty Python? 
> 
> Things that can't happen, can't happen. If the thing /might/ happen, 
> then it /can/ happen. 
> 
> Do you think I write my code by guesswork? Do you think I say to 
> myself, "I guess this is unlikely, and I don't want to consider it - 
> we'll pretend it it's impossible and tell the compiler its unreachable. 
> I'm sure no one will notice" ?
>
OK so

int sign(double x)
{
    if (x < 0) return -1;
    if (x == 0) retun 0;
    if (x > 0) return 1;
    /* unreachable */
}

Yes? 
No. In David Brown world, no-one would ever make that mistake. In reality,
it's the sort of thing that is quite likely to slip through. In fact sign() needs
to return a double to handle the corner case properly.

It's NaN of course. The sign of NaN is NaN.
Or you could say that NaN isn't in the domain of the function and either catch
it, or just ignore it and accept any garbage - the real bug will be upstream.
Or you could say that the code is unreachable because we always filter
out NaN. But how would you prove that?

[toc] | [prev] | [next] | [standalone]


#174657

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2023-09-09 01:52 +0100
Message-ID<874jk4mam8.fsf@bsb.me.uk>
In reply to#174644
Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:

> int sign(double x)
> {
>     if (x < 0) return -1;
>     if (x == 0) retun 0;
>     if (x > 0) return 1;
>     /* unreachable */
> }

Just for information...

> In fact sign() needs to return a double to handle the corner case properly.
>
> It's NaN of course. The sign of NaN is NaN.

In IEEE floating point (almost universal these days) NaNs (and
infinities) are signed, and the sign often carries useful information.
You can't just state that "the sign of NaN is NaN" as if it's a plain
fact.  One might want, for example, something more like:

  return x == 0 ? 0 : 1 - 2*signbit(x);

The information alluded to above being that some readers may not know
that C has a signbit macro.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#174663

FromMalcolm McLean <malcolm.arthur.mclean@gmail.com>
Date2023-09-08 18:16 -0700
Message-ID<14ea840a-b27e-49c3-99b0-edebbb020662n@googlegroups.com>
In reply to#174657
On Saturday, 9 September 2023 at 01:52:30 UTC+1, Ben Bacarisse wrote:
> Malcolm McLean <malcolm.ar...@gmail.com> writes: 
> 
> > int sign(double x) 
> > { 
> > if (x < 0) return -1; 
> > if (x == 0) retun 0; 
> > if (x > 0) return 1; 
> > /* unreachable */ 
> > }
> Just for information...
> > In fact sign() needs to return a double to handle the corner case properly. 
> > 
> > It's NaN of course. The sign of NaN is NaN.
> In IEEE floating point (almost universal these days) NaNs (and 
> infinities) are signed, and the sign often carries useful information. 
> You can't just state that "the sign of NaN is NaN" as if it's a plain 
> fact. One might want, for example, something more like: 
> 
> return x == 0 ? 0 : 1 - 2*signbit(x); 
> 
> The information alluded to above being that some readers may not know 
> that C has a signbit macro. 
> 
IEEE also allows for signed zero. But the sign of zero is zero. Certainly for
positive zero. I suppose you might argue that for the rare negative zeroes
you should return -1.

[toc] | [prev] | [next] | [standalone]


#174758

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2023-09-09 21:31 +0100
Message-ID<87y1hfks06.fsf@bsb.me.uk>
In reply to#174663
Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes:

> On Saturday, 9 September 2023 at 01:52:30 UTC+1, Ben Bacarisse wrote:
>> Malcolm McLean <malcolm.ar...@gmail.com> writes: 
>> 
>> > int sign(double x) 
>> > { 
>> > if (x < 0) return -1; 
>> > if (x == 0) retun 0; 
>> > if (x > 0) return 1; 
>> > /* unreachable */ 
>> > }
>> Just for information...
>> > In fact sign() needs to return a double to handle the corner case properly. 
>> > 
>> > It's NaN of course. The sign of NaN is NaN.
>> In IEEE floating point (almost universal these days) NaNs (and 
>> infinities) are signed, and the sign often carries useful information. 
>> You can't just state that "the sign of NaN is NaN" as if it's a plain 
>> fact. One might want, for example, something more like: 
>> 
>> return x == 0 ? 0 : 1 - 2*signbit(x); 
>> 
>> The information alluded to above being that some readers may not know 
>> that C has a signbit macro. 
>> 
> IEEE also allows for signed zero. But the sign of zero is zero. Certainly for
> positive zero. I suppose you might argue that for the rare negative zeroes
> you should return -1.

One might argue that, yes.  But I decided to try to make minimal changes
to the behaviour of the posted code.  The hypothetical author appears to
want positive and negative zeros to have sign(...) == 0.

-- 
Ben.

[toc] | [prev] | [next] | [standalone]


#174821

FromDavid Brown <david.brown@hesbynett.no>
Date2023-09-10 12:03 +0200
Message-ID<udk4a5$hkp5$1@dont-email.me>
In reply to#174644
On 09/09/2023 01:06, Malcolm McLean wrote:
> On Friday, 8 September 2023 at 15:03:51 UTC+1, David Brown wrote:
>> On 08/09/2023 11:47, Malcolm McLean wrote:
>>
>>> So a defined behaviour fallback is potentially useful. "This can't happen,
>>> but if it does, give me this diagnostic".
>> Where did you learn about logic? From watching Monty Python?
>>
>> Things that can't happen, can't happen. If the thing /might/ happen,
>> then it /can/ happen.
>>
>> Do you think I write my code by guesswork? Do you think I say to
>> myself, "I guess this is unlikely, and I don't want to consider it -
>> we'll pretend it it's impossible and tell the compiler its unreachable.
>> I'm sure no one will notice" ?
>>
> OK so
> 
> int sign(double x)
> {
>      if (x < 0) return -1;
>      if (x == 0) retun 0;
>      if (x > 0) return 1;
>      /* unreachable */
> }
> 
> Yes?

No :


// Precondition - "x" is a finite real-value double
// Postcondition - the return value is an integer -1, 0 or 1
//     matching the sign of "x".
int sign(double x)
{
      if (x < 0) return -1;
      if (x == 0) return 0;
      if (x > 0) return 1;
      unreachable();
}


> No. In David Brown world, no-one would ever make that mistake. 

I assume you are talking about double values that are unordered with 
respect to 0, rather than your typo.  Most people /do/ make typos like 
this on occasion, but their editor or IDE would pick up on it 
immediately - and their compiler would certainly spot it.  I recommend 
that you get a spell-checker for your Usenet client - it would pick up 
on your regular typos.  (I would make many more mistakes without a 
spell-checker.)

You should write "unreachable();" to show that the line cannot be 
reached by your code, as used in your program.  If it might be reached, 
don't write "unreachable();" - write the correct code to handle the 
situation.

You seem to be under the strange misconception that some kind of omitted 
or default behaviour is acceptable here.  If "sign" is called with a NaN 
or other value that is unordered with 0, then there is no plausible 
correct value to return.  A default "return 0;" would be wrong.  Having 
no return statement, so that in practice an unspecified value is 
returned, is also wrong.

Writing "unreachable();" does not give a correct answer if someone fails 
to follow the precondition for calling this function - but it makes it 
clear to the reader and to the compiler that this line cannot be reached 
when the function is used correctly.  That is better than leaving a 
mysterious and uninformed incorrect behaviour if the function is used 
incorrectly.

> In reality,
> it's the sort of thing that is quite likely to slip through. 

Not in my world, no.  To me, programming is about specifying behaviour 
and writing implementations of those specifications.  It is certainly 
the case that some specifications and details are never properly 
documented, but they exist nonetheless.  It seems entirely clear to me 
that the function "sign" will be specified to work on real numbers, not 
NaNs, because they do not have a sign.

> In fact sign() needs
> to return a double to handle the corner case properly.

No, it does not.

If you want to specify a function that takes a double and returns -1, 0, 
1 or NaN if the argument does not have a sign, then you can do that - 
calling the function "sign" would be a very bad name.

> 
> It's NaN of course. The sign of NaN is NaN.
> Or you could say that NaN isn't in the domain of the function and either catch
> it, or just ignore it and accept any garbage - the real bug will be upstream.

You are beginning, slowly, to understand a little about the fundamentals 
of programming.  A function needs a specification.  It has 
pre-conditions, saying what must be true before the function starts.  It 
has post-conditions, saying what the function establishes when it is 
finished.  It has invariants, which are things that are true before it 
starts, and remain true when it is finished.  This gives you the 
specification of the function.

Specifications are contracts - as the caller of the function, you 
promise to fulfil the pre-conditions.  The implementer of the function 
then promises to fulfil the post-conditions.  Stick to the contract, and 
everyone is happy - lie and break the contract, and you have no reason 
to expect anything.

Now, no one has given a clear specification of this "sign" function - we 
have the name, and we can guess the specification from the name and the 
original implementation.  The pre-condition is that the argument is a 
value that is ordered with respect to 0.  The post-condition is an 
integer -1, 0, or 1 representing that order with 0.

If that is the correct specification, then the implementation is 
correct.  The final line can be "unreachable();", "return 42;", omitted 
entirely, or anything else - it's all fine.  The sensible choice that is 
clearest to the reader and gives the compiler the best chance for 
optimisation and static error checking is "unreachable();".

If you want to change the specification and have a different function, 
that's fine - and then you have a different implementation.

> Or you could say that the code is unreachable because we always filter
> out NaN. But how would you prove that?
> 

Don't give the function a NaN in the first place.

None of my programs ever generate NaNs, and never have to deal with 
them.  I realise that some kinds of coding find NaNs, infinities, and 
other non-real floating point values to be useful, but I don't.  You are 
only going to see them in some pretty odd and unusual calculations, so 
take them into consideration at that point in your code.


[toc] | [prev] | [next] | [standalone]


#174949

FromMalcolm McLean <malcolm.arthur.mclean@gmail.com>
Date2023-09-10 21:36 -0700
Message-ID<8238a0d7-aeb2-4b26-8b1d-611caa37049an@googlegroups.com>
In reply to#174821
On Sunday, 10 September 2023 at 11:04:05 UTC+1, David Brown wrote:
> On 09/09/2023 01:06, Malcolm McLean wrote: 
> > Or you could say that the code is unreachable because we always filter 
> > out NaN. But how would you prove that? 
> > 
> 
> Don't give the function a NaN in the first place. 
> 
> None of my programs ever generate NaNs, and never have to deal with 
> them. I realise that some kinds of coding find NaNs, infinities, and 
> other non-real floating point values to be useful, but I don't. You are 
> only going to see them in some pretty odd and unusual calculations, so 
> take them into consideration at that point in your code.
>
You see this is the typical "I don't need a seatbelt because I would
never crash, and if you want a seatbelt then that means you
shouldn't be driving" David Brown.

Of course it's almost certainly a programming error to pass a NaN to
sign(). And of course in simple programs, you can often easily show
that NaNs will never occur. In a program which isn't simple, you would
have to go through every call to sign(), and prove that a NaN can't be
passed to it. Which isn't going to be practical.

NaNs may well be passed to sign(), and the unreachable() statement
may be executed. Now of course if we realise this, we shouldn't use 
"unreachable()". We should handle it. If maybe we don't realise this,
unreachable() should be our seatbelt.

You need methods which are as robust as possible to the errors which
inevitably occur. 

[toc] | [prev] | [next] | [standalone]


#174963

FromDavid Brown <david.brown@hesbynett.no>
Date2023-09-11 08:51 +0200
Message-ID<udmddn$v4e7$1@dont-email.me>
In reply to#174949
On 11/09/2023 06:36, Malcolm McLean wrote:
> On Sunday, 10 September 2023 at 11:04:05 UTC+1, David Brown wrote:
>> On 09/09/2023 01:06, Malcolm McLean wrote:
>>> Or you could say that the code is unreachable because we always filter
>>> out NaN. But how would you prove that?
>>>
>>
>> Don't give the function a NaN in the first place.
>>
>> None of my programs ever generate NaNs, and never have to deal with
>> them. I realise that some kinds of coding find NaNs, infinities, and
>> other non-real floating point values to be useful, but I don't. You are
>> only going to see them in some pretty odd and unusual calculations, so
>> take them into consideration at that point in your code.
>>
> You see this is the typical "I don't need a seatbelt because I would
> never crash, and if you want a seatbelt then that means you
> shouldn't be driving" David Brown.

Bollocks.  I mean, complete and under drivel.

Maybe this is news to you, but some programmers know what they are 
doing.  Some of us understand good software development practices, and 
apply them appropriately.


It is /peanuts/ to write floating point code that does not have NaNs. 
You simply don't get them in straightforward code.  And you don't get 
them in complicated code either, unless you specifically choose to write 
code that lets error conditions build up because it is more efficient to 
do lots of calculations and check for oddities (NaNs, infinities, etc.) 
afterwards.

You are the one that is always telling people that floating point 
numbers represent real quantities - distances, times, weights, whatever. 
  These don't have NaNs, and anything you do with them is not going to 
give you a NaN.

And in /my/ code, specifically, floating point types always represent 
real quantities.  And NaNs, infinities, and other special cases do not 
ever occur.

Would you like to explain where you get NaNs in your code, or think you 
might get them, and not know perfectly well that they are a possibility 
in that particular section of the code?

> 
> Of course it's almost certainly a programming error to pass a NaN to
> sign().

Yes.

If you want a "sign_or_NaN" function, write that and use it when you 
need it.  It's a different function, with a different domain, and a 
different specification.

> And of course in simple programs, you can often easily show
> that NaNs will never occur. In a program which isn't simple, you would
> have to go through every call to sign(), and prove that a NaN can't be
> passed to it. Which isn't going to be practical.

That is simply terrible programming practice.  Seriously.  You should 
know about the data that you are dealing with at any point in the code. 
NaNs represent errors - they can be a practical error management method 
for some code (especially looped or vectored calculations where 
throughput per clock cycle is important), but like any other error, they 
should be contained to a small and manageable part of the code - not 
leaked everywhere.

So you know when your floating point data could be a NaN or not - and if 
it could be, you don't call sign() with it.  In fact, you usually don't 
do much for it except check it for validity before moving on.


> 
> NaNs may well be passed to sign(), and the unreachable() statement
> may be executed. Now of course if we realise this, we shouldn't use
> "unreachable()". We should handle it. If maybe we don't realise this,
> unreachable() should be our seatbelt.

No, what you are describing there is a drunk driver in a Ferrari driving 
at 200 mph on a busy mountain road, wondering if a seatbelt is a good 
idea.  To get in the situation you describe, you have to make a whole 
range of appallingly bad design, specification and coding issues.  This 
is not the result of bugs in coding (these happen to everyone, and as 
has been discussed, there are ways to help find bugs).  This is the 
result of bad project leadership or bad management.

> 
> You need methods which are as robust as possible to the errors which
> inevitably occur.

You need methods to find and fix bugs that occur - programmers make 
mistakes, and these bugs need to be found.  That I agree on.

What you don't need, is ways that cover up bugs and pass them on down 
the line.  You don't want programmers to have the attitude that it 
doesn't really matter if your function is wrong and gives the wrong 
answers, as the caller function expects wrong answers and will pass the 
buck elsewhere.  Take some responsibility for writing /correct/ code!


[toc] | [prev] | [next] | [standalone]


#174964

From"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>
Date2023-09-10 23:59 -0700
Message-ID<udmdte$uh79$10@dont-email.me>
In reply to#174963
On 9/10/2023 11:51 PM, David Brown wrote:
> On 11/09/2023 06:36, Malcolm McLean wrote:
>> On Sunday, 10 September 2023 at 11:04:05 UTC+1, David Brown wrote:
>>> On 09/09/2023 01:06, Malcolm McLean wrote:
>>>> Or you could say that the code is unreachable because we always filter
>>>> out NaN. But how would you prove that?
>>>>
>>>
>>> Don't give the function a NaN in the first place.
>>>
>>> None of my programs ever generate NaNs, and never have to deal with
>>> them. I realise that some kinds of coding find NaNs, infinities, and
>>> other non-real floating point values to be useful, but I don't. You are
>>> only going to see them in some pretty odd and unusual calculations, so
>>> take them into consideration at that point in your code.
>>>
>> You see this is the typical "I don't need a seatbelt because I would
>> never crash, and if you want a seatbelt then that means you
>> shouldn't be driving" David Brown.
> 
> Bollocks.  I mean, complete and under drivel.
> 
> Maybe this is news to you, but some programmers know what they are 
> doing.  Some of us understand good software development practices, and 
> apply them appropriately.[...]

:^) C and C++ allows us to eat without putting corks on the forks... 
This scene in dirty rotten scoundrels still cracks me up:

https://youtu.be/SKDX-qJaJ08

Why is the cork on the fork? To prevent him from hurting himself. This 
reminds me of people saying that C and/or C++ are to dangerous.

Still makes me giggle.

[toc] | [prev] | [next] | [standalone]


#174965

FromMalcolm McLean <malcolm.arthur.mclean@gmail.com>
Date2023-09-11 01:01 -0700
Message-ID<2ead0d9a-bc68-48c6-8fba-f10756997a6an@googlegroups.com>
In reply to#174963
On Monday, 11 September 2023 at 07:51:50 UTC+1, David Brown wrote:
> On 11/09/2023 06:36, Malcolm McLean wrote: 
> 
> It is /peanuts/ to write floating point code that does not have NaNs. 
> You simply don't get them in straightforward code. And you don't get 
> them in complicated code either, unless you specifically choose to write 
> code that lets error conditions build up because it is more efficient to 
> do lots of calculations and check for oddities (NaNs, infinities, etc.) 
> afterwards. 
>
For your code, maybe.  
>
> You are the one that is always telling people that floating point 
> numbers represent real quantities - distances, times, weights, whatever. 
> These don't have NaNs, and anything you do with them is not going to 
> give you a NaN. 
>
Vaild data shouldn't have NaNs. However sometimes you have missing values.
Sometimes it is incorrectly assumed that that data will not have missing values,
which is one way you can get a NaN.
Of course you'll say that you shouldn't incorrectly assume that data which can
have missing values can't have missing values. In your world.
>
> And in /my/ code, specifically, floating point types always represent 
> real quantities. And NaNs, infinities, and other special cases do not 
> ever occur. 
> 
> Would you like to explain where you get NaNs in your code, or think you 
> might get them, and not know perfectly well that they are a possibility 
> in that particular section of the code?
>
Degenerate geometry, bascially. An example of degenerate geometry is a
quad which is actually a triangle because one of its sides is of zero length.
But there are many, many possible degeneracies. Because the calculations
and done with finite precision, there are also near-degeneracies which 
cause the same problems.
Its virtually inevitable that occasionally a check for a degeneracy will be
either missed or set to a too low an episilon. And because the degeneracies are
often rare, it can take a long time for the error to actually manifest itself.

That's the main. way that NaNs crop up unexpectly in my code.

You seem to think that your own, highly supervised, highly controlled
environment which deals only with understood problems, is the way everyone
has to work.
In my case, the costs of errors aren't very high (the worst thing that can happen
is that someone's drawing gets ruined, which is embarrassing for the company,
but it's not like we'll be hit with lawsuit for killing a baby). And a lot of the algorithms
are novel - no one has ever written a function to achieve a the same transformation
before. And the criteria for acceptability are often "does it look OK?" and hard to
specify mathematically. 

So bascially what I want is a system that is robust to the inevitable programming
errors.  It should return incorrect results rather than crashing out, because usually
the user can simply press "undo" an an operation hasn't worked, but his work is
still there. But it should also ideally tell me what has gone wrong and where. 
 

[toc] | [prev] | [next] | [standalone]


#174976

FromDavid Brown <david.brown@hesbynett.no>
Date2023-09-11 11:17 +0200
Message-ID<udmlvm$10ckq$1@dont-email.me>
In reply to#174965
On 11/09/2023 10:01, Malcolm McLean wrote:
> On Monday, 11 September 2023 at 07:51:50 UTC+1, David Brown wrote:
>> On 11/09/2023 06:36, Malcolm McLean wrote:
>>
>> It is /peanuts/ to write floating point code that does not have NaNs.
>> You simply don't get them in straightforward code. And you don't get
>> them in complicated code either, unless you specifically choose to write
>> code that lets error conditions build up because it is more efficient to
>> do lots of calculations and check for oddities (NaNs, infinities, etc.)
>> afterwards.
>>
> For your code, maybe.

I don't believe there is anything special about my code in this respect.

>>
>> You are the one that is always telling people that floating point
>> numbers represent real quantities - distances, times, weights, whatever.
>> These don't have NaNs, and anything you do with them is not going to
>> give you a NaN.
>>
> Vaild data shouldn't have NaNs. 

Correct.  And you should not be using potentially invalid data without 
knowing that it is potentially invalid.

> However sometimes you have missing values.

That may be the case.  But you don't fill in the missing values with 
random bits - you deal with them appropriately (which will depend on the 
application).  So missing values are not a source of NaNs, unless the 
application and algorithms mean it is sensible to use NaNs to fill in 
the missing values.  And if that's the case, you know it is the case.

> Sometimes it is incorrectly assumed that that data will not have missing values,
> which is one way you can get a NaN.

And there's the root of your problem - incorrect assumptions.  I don't 
know where you'd get such incorrect assumptions - perhaps from poor 
specifications, or poor names for your functions, or poor testing, or 
poor code reviews.

> Of course you'll say that you shouldn't incorrectly assume that data which can
> have missing values can't have missing values. In your world.

If programmers are making incorrect assumptions about the data, and the 
code, then they have a far bigger problem than just an odd 
"unreachable()" statement.  I appreciate that some software is written 
by incompetent programmers (from lack of training, lack of experience, 
lack of leadership, lack of time, whatever).  And you have to deal with 
that in some way.  But strangling good software is not the way to do it.

Data comes in two forms.  Verified data, that you know is correct 
(valid, in range, free from SQL injection attacks, etc.), and unverified 
data that comes from unknown or untrusted outside sources.  The boundary 
between these can be data read from files or received from networks, or 
it can be a public API for a library, or different modules of a program 
written by different programming groups.  Sometimes you put in temporary 
boundaries and verifications, for debugging, testing and fault-finding. 
Sometimes security concerns mean you have to add extra internal 
boundaries and checks.

But in general, once data is verified and moved "inside" your code, 
/you/ have full control and full responsibility.  It doesn't go missing. 
  It doesn't acquire NaNs mysteriously.  If functions are not well 
specified, it is /your/ fault.  If functions are not used according to 
specification, it is /your/ fault.  (Specifications don't have to be 
formally written to be important.)

And if you've made a mistake - such as data not been fully verified - 
you have to fix that mistake.  Crippling internal functions so that they 
are inefficient and functionally useless is not the answer.  Nor is 
intentionally going out of your way to pass the errors around.

>>
>> And in /my/ code, specifically, floating point types always represent
>> real quantities. And NaNs, infinities, and other special cases do not
>> ever occur.
>>
>> Would you like to explain where you get NaNs in your code, or think you
>> might get them, and not know perfectly well that they are a possibility
>> in that particular section of the code?
>>
> Degenerate geometry, bascially. An example of degenerate geometry is a
> quad which is actually a triangle because one of its sides is of zero length.

So check for it.

> But there are many, many possible degeneracies. Because the calculations
> and done with finite precision, there are also near-degeneracies which
> cause the same problems.

So do the calculations, then check for NaN or other problems, then deal 
with those issues.  Don't pass on crap data to the rest of the code.

And if you are getting these kinds of issues, you need to look a lot 
harder at your algorithms.  Making good numerical algorithms that are 
stable in face of awkward data like this is not easy.  If you are not 
qualified to do it, find someone who is (or more likely, find an 
existing library that does the job right).

> Its virtually inevitable that occasionally a check for a degeneracy will be
> either missed or set to a too low an episilon. And because the degeneracies are
> often rare, it can take a long time for the error to actually manifest itself.
> 
> That's the main. way that NaNs crop up unexpectly in my code.

If you know they can crop up, they are not unexpected - and you should 
deal with them at the time.

> 
> You seem to think that your own, highly supervised, highly controlled
> environment which deals only with understood problems, is the way everyone
> has to work.

Have you ever heard of "divide and conquer" ?  Break up your problems 
until you have something small enough that it can be controlled and 
understood.  I appreciate that NaNs can turn up in some kinds of code - 
I said that several times already.  The flaw is letting them escape 
thoughtlessly.

> In my case, the costs of errors aren't very high (the worst thing that can happen
> is that someone's drawing gets ruined, which is embarrassing for the company,
> but it's not like we'll be hit with lawsuit for killing a baby). And a lot of the algorithms
> are novel - no one has ever written a function to achieve a the same transformation
> before. And the criteria for acceptability are often "does it look OK?" and hard to
> specify mathematically.
> 
> So bascially what I want is a system that is robust to the inevitable programming
> errors.  It should return incorrect results rather than crashing out, because usually
> the user can simply press "undo" an an operation hasn't worked, but his work is
> still there. But it should also ideally tell me what has gone wrong and where.
>   

All I am saying is that you take responsibility of your code, and its 
results.  If you consider NaN an appropriate result, fair enough - deal 
with it.  Don't expect other code that handles finite values to be 
changed to give meaningless results just because you want to pass in 
meaningless arguments.

[toc] | [prev] | [next] | [standalone]


#174980

FromMalcolm McLean <malcolm.arthur.mclean@gmail.com>
Date2023-09-11 03:16 -0700
Message-ID<0cea903b-f004-4fb5-aae4-b6263e553e74n@googlegroups.com>
In reply to#174976
On Monday, 11 September 2023 at 10:17:58 UTC+1, David Brown wrote:
> On 11/09/2023 10:01, Malcolm McLean wrote: 
> 
> > Degenerate geometry, bascially. An example of degenerate geometry is a 
> > quad which is actually a triangle because one of its sides is of zero length.
> So check for it.
>
You are just mouthing platitudes as if they were great insights, and arrogantly
presenting them as your superior wisdom.
So you seriously think that if it was as simple as "check for it" I wouldn't have
thought of that? Seriously?
. 

[toc] | [prev] | [next] | [standalone]


#175014

FromDavid Brown <david.brown@hesbynett.no>
Date2023-09-11 14:58 +0200
Message-ID<udn2u8$12b7a$1@dont-email.me>
In reply to#174980
On 11/09/2023 12:16, Malcolm McLean wrote:
> On Monday, 11 September 2023 at 10:17:58 UTC+1, David Brown wrote:
>> On 11/09/2023 10:01, Malcolm McLean wrote:
>>
>>> Degenerate geometry, bascially. An example of degenerate geometry is a
>>> quad which is actually a triangle because one of its sides is of zero length.
>> So check for it.
>>
> You are just mouthing platitudes as if they were great insights, and arrogantly
> presenting them as your superior wisdom.
> So you seriously think that if it was as simple as "check for it" I wouldn't have
> thought of that? Seriously?
> .

 From what you are saying, yes.  Seriously.

 From what you have said before about matrix determinants, I know you 
don't have a lot of knowledge or experience in numerical methods and 
algorithms.  (There's nothing wrong with that - no one can be 
experienced in everything.)  So do I think you might have a geometry 
algorithm in your code that is numerically unstable?  Absolutely - 
certainly if your application can tolerate some visual glitches (in such 
cases, an occasionally unstable algorithm might be better than a more 
complex stable algorithm).  And do I think you are lax about checking? 
Yes - you've said as much.

I know different kinds of software require different levels of 
development quality.  You need to put a lot more effort into ensuring 
the correctness of code that will be in a card buried in a oil well head 
at the bottom of the ocean than you need for a computer game that can be 
easily updated online.  But I like to believe that most programmers are 
interested in writing correct code.

So if your data might be invalid, you check it.  If your data might not 
fit within the domain of the function you want to call, you check it. 
If your function might not be able to return correct results, your 
function needs to return error indicators in some way, so that the 
caller function knows what it is getting.  And then the caller function 
handles the errors.

What you don't do is leave the problem data wandering around your 
program, ready to cause more trouble.  You don't cripple the performance 
by writing all functions so that they handle NaNs in some predictable 
way - you make sure they are not called with NaNs.  You specify your 
functions - including whether they can accept NaNs and what range of 
valid data they accept, and what range of valid data and/or NaNs they 
return.  That all makes your code easier to write, lets you have more 
efficient functions, keeps it cleaner, makes it easier to analyse (so 
that you know when your data is valid), and makes it easier to debug.

No one said this was simple.  Perhaps "check the data" is hard in your 
case.  Sometimes programming /is/ hard.

[toc] | [prev] | [next] | [standalone]


#175022

FromMalcolm McLean <malcolm.arthur.mclean@gmail.com>
Date2023-09-11 06:35 -0700
Message-ID<120791af-c99c-4fd8-8017-016f19038d8fn@googlegroups.com>
In reply to#175014
On Monday, 11 September 2023 at 13:59:03 UTC+1, David Brown wrote:
> On 11/09/2023 12:16, Malcolm McLean wrote: 
> > On Monday, 11 September 2023 at 10:17:58 UTC+1, David Brown wrote: 
> >> On 11/09/2023 10:01, Malcolm McLean wrote: 
> >> 
> >>> Degenerate geometry, bascially. An example of degenerate geometry is a 
> >>> quad which is actually a triangle because one of its sides is of zero length. 
> >> So check for it. 
> >> 
> > You are just mouthing platitudes as if they were great insights, and arrogantly 
> > presenting them as your superior wisdom. 
> > So you seriously think that if it was as simple as "check for it" I wouldn't have 
> > thought of that? Seriously? 
> > .
> From what you are saying, yes. Seriously. 
> 
> From what you have said before about matrix determinants, I know you 
> don't have a lot of knowledge or experience in numerical methods and 
> algorithms. (There's nothing wrong with that - no one can be 
> experienced in everything.) So do I think you might have a geometry 
> algorithm in your code that is numerically unstable? Absolutely - 
> certainly if your application can tolerate some visual glitches (in such 
> cases, an occasionally unstable algorithm might be better than a more 
> complex stable algorithm). And do I think you are lax about checking? 
> Yes - you've said as much. 
> 
> I know different kinds of software require different levels of 
> development quality. You need to put a lot more effort into ensuring 
> the correctness of code that will be in a card buried in a oil well head 
> at the bottom of the ocean than you need for a computer game that can be 
> easily updated online. But I like to believe that most programmers are 
> interested in writing correct code. 
> 
> So if your data might be invalid, you check it. If your data might not 
> fit within the domain of the function you want to call, you check it. 
> If your function might not be able to return correct results, your 
> function needs to return error indicators in some way, so that the 
> caller function knows what it is getting. And then the caller function 
> handles the errors. 
> 
> What you don't do is leave the problem data wandering around your 
> program, ready to cause more trouble. You don't cripple the performance 
> by writing all functions so that they handle NaNs in some predictable 
> way - you make sure they are not called with NaNs. You specify your 
> functions - including whether they can accept NaNs and what range of 
> valid data they accept, and what range of valid data and/or NaNs they 
> return. That all makes your code easier to write, lets you have more 
> efficient functions, keeps it cleaner, makes it easier to analyse (so 
> that you know when your data is valid), and makes it easier to debug. 
> 
> No one said this was simple. Perhaps "check the data" is hard in your 
> case. Sometimes programming /is/ hard.
>
No. But the point is that this function

double lengthSQ(Vector *v)
{
    return v->x *v->x + v->y *v->y;
}

will return NaN if v has a NaN member. And it might well be the case that
the person who wrote it is completely ignorant that IEEE floating points have
a NaN representation. 
And that's typical. Most operations on NaN return NaN, so most functions are 
correct within the domain of NaN.

Now this function

int sign(double x)
{
   if (x < 0) return -1;
   if (x == 0) return 0;
   if (x > 0) return 1;
}

is an exception. Control will fall off the end if we pass NaN. And because we've returned the
sign as an int, we have no NaN representation. So it's not correct for NaN. And that's a bit
unusual.

Now if we make it double valued and "return x" instead of falling off the brace, we won't "cripple
performance". But there might be a slight perfomance impact. Is it worthwhile? Hard to
say. But there's definitely a case for it. It just depends what the consequences of getting things
incorrect are. And, as you say, probably if you are passing NaN to sign() that indicates a 
programming error upstream anyway. 

But checking for every possible degeneracy that could cause a NaN in geometrical algorithms
is hard, and sometimes unacceptably expensive. And degenerate doesn't always mean "invalid".
For instance a quad with a zero-length side is still clockwise or anti-clockwise. However you
can't tell which by taking a wedge product of two adjacent sides, if one of them is the zero
length side.



 


[toc] | [prev] | [next] | [standalone]


#175034

FromKaz Kylheku <864-117-4973@kylheku.com>
Date2023-09-11 14:13 +0000
Message-ID<20230911070056.703@kylheku.com>
In reply to#175022
On 2023-09-11, Malcolm McLean <malcolm.arthur.mclean@gmail.com> wrote:
> Now this function
>
> int sign(double x)
> {
>    if (x < 0) return -1;
>    if (x == 0) return 0;
>    if (x > 0) return 1;
> }
>
> is an exception. Control will fall off the end if we pass NaN. And because we've returned the
> sign as an int, we have no NaN representation. So it's not correct for NaN.

We could write it like this:

  {
    if (x < 0) return -1;
    if (x > 0) return 1;
    return 0;
  }

Then in the reference manual we add the admonishment: "If the input is
NaN, then sign returns 0; a NaN input is not converted to a NaN output,
since the return type has no such representation. The application should
check the argument for NaN in situations where that is necessary."

The zero return is correct for NaN because we defined it that way;
it means that the input is neither positive nor negative, not
that it's a number.

This is the same like defining pow(0, 0) to be 1, etc.

-- 
TXR Programming Language: http://nongnu.org/txr
Cygnal: Cygwin Native Application Library: http://kylheku.com/cygnal
Mastodon: @Kazinator@mstdn.ca
NOTE: If you use Google Groups, I don't see you, unless you're whitelisted.

[toc] | [prev] | [next] | [standalone]


#175035

FromDavid Brown <david.brown@hesbynett.no>
Date2023-09-11 16:24 +0200
Message-ID<udn7vg$136e1$1@dont-email.me>
In reply to#175022
On 11/09/2023 15:35, Malcolm McLean wrote:
> On Monday, 11 September 2023 at 13:59:03 UTC+1, David Brown wrote:
>> On 11/09/2023 12:16, Malcolm McLean wrote:
>>> On Monday, 11 September 2023 at 10:17:58 UTC+1, David Brown wrote:
>>>> On 11/09/2023 10:01, Malcolm McLean wrote:
>>>>
>>>>> Degenerate geometry, bascially. An example of degenerate geometry is a
>>>>> quad which is actually a triangle because one of its sides is of zero length.
>>>> So check for it.
>>>>
>>> You are just mouthing platitudes as if they were great insights, and arrogantly
>>> presenting them as your superior wisdom.
>>> So you seriously think that if it was as simple as "check for it" I wouldn't have
>>> thought of that? Seriously?
>>> .
>>  From what you are saying, yes. Seriously.
>>
>>  From what you have said before about matrix determinants, I know you
>> don't have a lot of knowledge or experience in numerical methods and
>> algorithms. (There's nothing wrong with that - no one can be
>> experienced in everything.) So do I think you might have a geometry
>> algorithm in your code that is numerically unstable? Absolutely -
>> certainly if your application can tolerate some visual glitches (in such
>> cases, an occasionally unstable algorithm might be better than a more
>> complex stable algorithm). And do I think you are lax about checking?
>> Yes - you've said as much.
>>
>> I know different kinds of software require different levels of
>> development quality. You need to put a lot more effort into ensuring
>> the correctness of code that will be in a card buried in a oil well head
>> at the bottom of the ocean than you need for a computer game that can be
>> easily updated online. But I like to believe that most programmers are
>> interested in writing correct code.
>>
>> So if your data might be invalid, you check it. If your data might not
>> fit within the domain of the function you want to call, you check it.
>> If your function might not be able to return correct results, your
>> function needs to return error indicators in some way, so that the
>> caller function knows what it is getting. And then the caller function
>> handles the errors.
>>
>> What you don't do is leave the problem data wandering around your
>> program, ready to cause more trouble. You don't cripple the performance
>> by writing all functions so that they handle NaNs in some predictable
>> way - you make sure they are not called with NaNs. You specify your
>> functions - including whether they can accept NaNs and what range of
>> valid data they accept, and what range of valid data and/or NaNs they
>> return. That all makes your code easier to write, lets you have more
>> efficient functions, keeps it cleaner, makes it easier to analyse (so
>> that you know when your data is valid), and makes it easier to debug.
>>
>> No one said this was simple. Perhaps "check the data" is hard in your
>> case. Sometimes programming /is/ hard.
>>
> No. But the point is that this function
> 
> double lengthSQ(Vector *v)
> {
>      return v->x *v->x + v->y *v->y;
> }
> 
> will return NaN if v has a NaN member. And it might well be the case that
> the person who wrote it is completely ignorant that IEEE floating points have
> a NaN representation.
> And that's typical. Most operations on NaN return NaN, so most functions are
> correct within the domain of NaN.

Okay.  So that function is "NaN propagating" - that's common for 
functions that operate on real numbers and return real numbers.

> 
> Now this function
> 
> int sign(double x)
> {
>     if (x < 0) return -1;
>     if (x == 0) return 0;
>     if (x > 0) return 1;
> }
> 
> is an exception. Control will fall off the end if we pass NaN. And because we've returned the
> sign as an int, we have no NaN representation. So it's not correct for NaN. And that's a bit
> unusual.

It is not at all unusual.  This is not a calculation function, it is a 
classification function, operating on finite numbers and returning an 
integer.

If that's not what you want, use or write a different function.

> 
> Now if we make it double valued and "return x" instead of falling off the brace, we won't "cripple
> performance". But there might be a slight perfomance impact. 

The impact on the performance is dependent on the way the code is used - 
a function like this will typically be inlined.  "Cripple" may be too 
strong a word - it may also be too weak.

> Is it worthwhile? Hard to
> say. 

Agreed.

But it won't give you the sign of the argument when passed a NaN, and so 
the name would be wrong.

> But there's definitely a case for it. It just depends what the consequences of getting things
> incorrect are.

I am usually much more interested in encouraging correct coding than 
worrying about the consequences of incorrect coding.  Sometimes the 
consequences of incorrect coding need to be the focus, such as in 
security-critical code.  But most often, you are better off spending the 
effort getting the code right than minimising the consequences of 
getting it wrong.

And code that does not do what it says, or does not say what it does, is 
encouraging incorrect coding.

> And, as you say, probably if you are passing NaN to sign() that indicates a
> programming error upstream anyway.

Yes.  So concentrate on that, not on the function that is correct.

> 
> But checking for every possible degeneracy that could cause a NaN in geometrical algorithms
> is hard, and sometimes unacceptably expensive. And degenerate doesn't always mean "invalid".
> For instance a quad with a zero-length side is still clockwise or anti-clockwise. However you
> can't tell which by taking a wedge product of two adjacent sides, if one of them is the zero
> length side.
> 

If that is an issue, then perhaps you have the wrong data structure. 
Maybe you should store additional information (such as the orientation) 
along with the points.  Maybe you should be using different formats for 
your points, such as quaternions instead of three real dimensions. 
Maybe you should take care to order your quads so that any zero-length 
sides come last, or split one side in two so that your sides all have 
non-zero length.  Or change your orientation function's algorithm to 
find the most numerically stable choice of sides and use that for 
determining the orientation.

There are many possibilities, and the "best" will of course be a 
trade-off, and of course depend on how you are using the data.




[toc] | [prev] | [next] | [standalone]


Page 2 of 7 — ← Prev page 1 [2] 3 4 5 6 7  Next page →

Back to top | Article view | comp.lang.c


csiph-web