Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #174243 > unrolled thread
| Started by | candycane@f172.n1.z21.fsxnet (candycane) |
|---|---|
| First post | 2023-09-06 19:53 +1300 |
| Last post | 2023-09-09 10:23 -0700 |
| Articles | 20 on this page of 129 — 12 participants |
Back to article view | Back to comp.lang.c
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 3 of 7 — ← Prev page 1 2 [3] 4 5 6 7 Next page →
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2023-09-11 14:55 +0100 |
| Message-ID | <udn68a$12tcm$1@dont-email.me> |
| In reply to | #175014 |
On 11/09/2023 13:58, 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.
It sounds like you wouldn't care if NaNs didn't exist and weren't
supported in hardware.
(I don't care much either, when using iee754.)
But it does make you wonder why they bothered supporting NaNs at all, if
all you have to do is take more care in writing your programs.
> No one said this was simple. Perhaps "check the data" is hard in your
> case. Sometimes programming /is/ hard.
And maybe NaNs were added to make it easier. Given a program like this:
#include <stdio.h>
#include <math.h>
int main(void) {
double x=-9.0;
printf("%f\n", sqrt(x));
printf("%d\n", (int)sqrt(x));
printf("%X\n", (int)sqrt(x));
}
what behaviour would you expect or prefer?
The output I got from on-line Clang was first that 'sqrt' was not
defined. That's due to that ******* stupid -lm thing (FFS just fix
instead of requiring millions to piss about with it).
With that out of the way, it produced:
-nan
-2147483648
80000000
(Not sure why it's -nan rather than nan)
Other compilers are similar; some show -1.#IND00 instead of 'nan'.
Let me guess: you'd rather it was unpredictable, or went haywire, or
just don't care because none of your programs would ever execute such
code. Since your software is NEVER buggy, not even experimental code
during development or throwaway programs of no consequence.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2023-09-11 16:42 +0200 |
| Message-ID | <udn8vu$13bqe$1@dont-email.me> |
| In reply to | #175026 |
On 11/09/2023 15:55, Bart wrote:
> On 11/09/2023 13:58, 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.
>
> It sounds like you wouldn't care if NaNs didn't exist and weren't
> supported in hardware.
>
For my own use, that is correct. But I do appreciate that other people
have other requirements.
Some of the hardware I use does not support NaNs, or at least not fully.
Support for all the corner cases of IEEE floats and doubles can be
costly in hardware terms, so some microcontroller implementations (and
especially vector varieties) either ignore them, or throw a hardware
exception and expect software to clean up the mess (which is obviously a
lot slower than hardware).
I invariable use the gcc "-ffast-math" switch - that lets it assume that
all values are finite, that arithmetic is commutative and associative,
that division can be done by multiplication with a reciprocal, and so
on. That also will not suit everyone, but on the kind of device I use,
it can make code very much more efficient and it works fine with the
values I have.
> (I don't care much either, when using iee754.)
>
> But it does make you wonder why they bothered supporting NaNs at all, if
> all you have to do is take more care in writing your programs.
>
Take Malcolm's examples of geometry calculations. Maybe you are doing
some matrix calculations and normalisation - you could have loops of,
say, 16 multiplications and additions then 4 divisions. Then you are
doing several similar transformations and normalisations on the data.
If you have to check at each point where you might get an infinity or a
divide by zero, you spoil the throughput of the calculations. Then it
is better to run them all with NaN-propagating code and check for NaN at
the end.
But you /do/ check for NaN at the end, and decide what to do about the
bad data - ignore that polygon, give an error message, or whatever. You
don't pass it on.
>
>> No one said this was simple. Perhaps "check the data" is hard in your
>> case. Sometimes programming /is/ hard.
>
> And maybe NaNs were added to make it easier. Given a program like this:
>
>
> #include <stdio.h>
> #include <math.h>
>
> int main(void) {
> double x=-9.0;
>
> printf("%f\n", sqrt(x));
> printf("%d\n", (int)sqrt(x));
> printf("%X\n", (int)sqrt(x));
> }
>
> what behaviour would you expect or prefer?
A compiler warning :-)
I won't expect anything. I don't use the <math.h> functions enough to
be familiar with their details - maybe there are specific guaranteed
behaviours here. But /I/ would not expect anything, because there is no
appropriate correct behaviour.
>
> The output I got from on-line Clang was first that 'sqrt' was not
> defined. That's due to that ******* stupid -lm thing (FFS just fix
> instead of requiring millions to piss about with it).
>
> With that out of the way, it produced:
>
> -nan
> -2147483648
> 80000000
>
> (Not sure why it's -nan rather than nan)
>
> Other compilers are similar; some show -1.#IND00 instead of 'nan'.
>
> Let me guess: you'd rather it was unpredictable, or went haywire, or
> just don't care because none of your programs would ever execute such
> code. Since your software is NEVER buggy, not even experimental code
> during development or throwaway programs of no consequence.
>
"""
On two occasions I have been asked, 'Pray, Mr. Babbage, if you put into
the machine wrong figures, will the right answers come out?' I am not
able rightly to apprehend the kind of confusion of ideas that could
provoke such a question.
"""
I am responsible for my own bugs. I am not responsible for people
calling my functions with values outside the specified acceptable domains.
It doesn't matter what I'd prefer, or what /you/ would prefer - "garbage
in, garbage out" is unavoidable, and is not a new or revolutionary idea.
[toc] | [prev] | [next] | [standalone]
| From | Kaz Kylheku <864-117-4973@kylheku.com> |
|---|---|
| Date | 2023-09-11 14:29 +0000 |
| Message-ID | <20230911071526.609@kylheku.com> |
| In reply to | #175014 |
On 2023-09-11, David Brown <david.brown@hesbynett.no> wrote:
> 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.
If you want performance, then you do neither.
NaN is a mechanism which opens the door to improved performance, by
moving many slow software checks into the hardware.
Without NaN, you have to perform difficult checks of the operands of any
function or operator. Before division, for instance, you must check not
only for zero, but for any small number near zero that has no
representable reciprocal.
Or else you have to handle CPU exceptions in the host system's manner,
like a POSIX SIGFPE.
NaN make the hardware do the checking and reporting, via in-band values
which are in the floating-point type, but distinguishable from numbers.
The intent is that you can let NaN propagate across complex calculations
and then just check the final result for NaN which indicates that
something went wrong somewhere.
The greaetest benefit of NaN is obtained when you *do* let NaNs be used
as operands of functions and operators.
But yes; you don't want those functions which you write yourself to be
doing wasteful checks for NaN either; they can just rely on the
operators and functions that they use to report NaN, and pass it up
to the caller.
The proposed int sign(double) funtion cannot pass a NaN to the
caller. However, as I wrote in another article, that doesn't mean
it has to check for NaN. It can return zero if the input is a NaN;
the caller can check the argument. This is better because the
caller can omit the check in some situations, like this:
switch (sign(x)) {
case 0: // could be NaN
case 1:
return x;
case -1:
return -x;
}
Since all branches of the code return x, if x is NaN, we return NaN.
So we have satisfied the protocol for error propagation, without
having had to call isnan(x).
In this example, we have to check:
switch (sign(x)) {
case 0:
if (isnan(x))
puts("x is NaN, and so neither positive nor negative");
else
puts("x is zero");
break;
case 1:
puts("x is positive");
break;
case -1:
puts("x is negative");
break;
}
We do not access x in the control flow branches, but print
information. So if we don't check for NaN, we risk printing
misinformatin in the form of "x is zero".
--
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]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2023-09-11 11:25 +0100 |
| Message-ID | <udmpuu$110jq$1@dont-email.me> |
| In reply to | #174963 |
On 11/09/2023 07:51, David Brown wrote:
> On 11/09/2023 06:36, Malcolm McLean wrote:
>> 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.
You seem to disagree.
> 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?
You can get them when writing calculators or interpreters, or anything
where values are not known until runtime.
Even just reading numbers from a file. Or writing a compiler when you
need to reduce a constant expression.
Then INF or IND (I can't seem to get NAN unless IND means NAN) can occur
when performing calculations between those numbers.
>>
>> 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.
Another situation where you can't control the inputs is in writing
library functions, then can be called from 1000 different applications
written by different people.
Then +/- INF/NAN/IND is a possible when writing a sign() function.
My bignum library which implements arbitrary precision floats
specifically has representations for infinity and nans. This is the
checking code needed for an add() operation:
switch (getbintype(a,b)) {
case nn_types:
break;
case zz_types:
bn_setzero(c);
return 1;
case nz_types:
bn_dupl(c,a);
return 1;
case zn_types:
bn_dupl(c,b);
return 1;
default:
bn_setnan(c);
return 0;
}
(An 'n' type is a normal number; a 'z' type is just zero, which here is
a special number.)
Since this is a library, I can't predict what inputs will be supplied.
>> 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.
You just haven't been writing the right programs. You don't always have
control over all the code that is running.
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.arthur.mclean@gmail.com> |
|---|---|
| Date | 2023-09-11 03:59 -0700 |
| Message-ID | <580ff51c-dcee-4ec0-a0d2-4bf0dae0b8f3n@googlegroups.com> |
| In reply to | #174987 |
On Monday, 11 September 2023 at 11:25:49 UTC+1, Bart wrote: > > > That is simply terrible programming practice. Seriously. You should > > know about the data that you are dealing with at any point in the code. > You just haven't been writing the right programs. You don't always have > control over all the code that is running. > Most code doesn't have to handle NaN specially, because the result of an operation on a NaN is usually NaN. So if we take the length squared of a vector which has a NaN member, we will obtain NaN, which is right. But sign() is an exception. Despite what Ben says, the sign of NaN is NaN (the fact that the sign bit doesn't physically disappear is irrelevant). So to handle NaN correctly you've got to catch it, because when you branch as the result of an operation on a NaN, you have to to either take or not take the branch. sign() written in a non-NaN aware fashion is an example of a function which might appear to have an unreachable closing brace, but in fact the brace is reachable, if the function is called with NaN. It's a mistake which could easily be made. If unreachable() behaves sensibly, then it's a seatbelt. We've made a mistake, but we get an error message or other behaviour which is as useful as it can be, given that the program is incorrect. And then as you say, often you don't have control over the person calling the code. So even if you check every call to sign() and somehow prove that it can never be NaN, you can't prevent a third party calling it with NaN, and the "unreachable" brace will be reached.
[toc] | [prev] | [next] | [standalone]
| From | Kaz Kylheku <864-117-4973@kylheku.com> |
|---|---|
| Date | 2023-09-11 13:57 +0000 |
| Message-ID | <20230911064035.380@kylheku.com> |
| In reply to | #174989 |
On 2023-09-11, Malcolm McLean <malcolm.arthur.mclean@gmail.com> wrote:
> On Monday, 11 September 2023 at 11:25:49 UTC+1, Bart wrote:
>>
>> > That is simply terrible programming practice. Seriously. You should
>> > know about the data that you are dealing with at any point in the code.
>> You just haven't been writing the right programs. You don't always have
>> control over all the code that is running.
>>
> Most code doesn't have to handle NaN specially, because the result of an
> operation on a NaN is usually NaN. So if we take the length squared of
> a vector which has a NaN member, we will obtain NaN, which is right.
>
> But sign() is an exception. Despite what Ben says, the sign of NaN is NaN
> (the fact that the sign bit doesn't physically disappear is irrelevant). So
> to handle NaN correctly you've got to catch it, because when you branch
> as the result of an operation on a NaN, you have to to either take or not
> take the branch.
NaN is a device which lets error propagate across calculations so that
we can efficiently catch it at some convenient point, rather than bog
down every calculation step wih checks that complicate/bloat the source
code and slow down the object code.
But you do have to check for NaN somewhere, otherwise the program
will report it as its output.
Yes; if you're converting the intermediate result to some other
representation which itself doesn't have anything analogous to NaN,
then you might want to check it at that point.
For instance if we convert an "a < b" comparison into two control flows
which no longer refer to a and b, and those operands could be NaN,
we should check for NaN. Otherwise the error could be swept under
the rug.
If all branches of the conditional use both input values to
continue the calculation, then you may be able to get away without
handling NaN at that point.
// ternary equivalent:
if (a < b) { return a + c; } else { return b + c; } // bad
Here although the a < b result will conceal NaN, because it's
not the case that both branches of the code refer to both operands,
a NaN could be swept under the rug.
if (a < b) { return b - a; } else { return a - b; }
Here we are okay.
Tt is the same with the proposed sign function.
> sign() written in a non-NaN aware fashion is an example of a function which
> might appear to have an unreachable closing brace, but in fact the brace is reachable,
> if the function is called with NaN.
If the function arbitrarily returned 0, it could work. The caller would
have to check the *operands* for NaN in the situations where that is
required, like when the result of sign() is used to select code paths,
not all of which pull all operands into the calculation.
> It's a mistake which could easily be made.
> If unreachable() behaves sensibly, then it's a seatbelt.
Nothing that invokes undefined behavior when the accident occurs
can be called a seatbelt.
You seem to be mistaking it for abort() or similar.
The unreachable() we have been discussing tells the compiler that the
code won't be reached. You've proven that somehow and the compiler can
optimize accordingly.
Given
a()
{
unreachable();
}
b()
{
puts("wut?");
}
It is possible for a call to a() to cause the puts to be called,
producing the "wut?" output.
That could happen if the functions are emitted, with only no-op
instructions between them and because of the unreachable assertion,
the compiler didn't emit the return sequence, for a, so that
effectively it tail calls into b by falling through.
> We've made a mistake,
> but we get an error message or other behaviour which is as useful as it
> can be, given that the program is incorrect.
If you want that, you have to reach for something other than
unreachable assertions.
--
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]
| From | Malcolm McLean <malcolm.arthur.mclean@gmail.com> |
|---|---|
| Date | 2023-09-11 09:52 -0700 |
| Message-ID | <b8fb1091-0b26-4fc9-a09b-530953c6d728n@googlegroups.com> |
| In reply to | #175027 |
On Monday, 11 September 2023 at 14:57:16 UTC+1, Kaz Kylheku wrote:
> On 2023-09-11, Malcolm McLean <malcolm.ar...@gmail.com> wrote:
> > On Monday, 11 September 2023 at 11:25:49 UTC+1, Bart wrote:
> >>
> >> > That is simply terrible programming practice. Seriously. You should
> >> > know about the data that you are dealing with at any point in the code.
> >> You just haven't been writing the right programs. You don't always have
> >> control over all the code that is running.
> >>
> > Most code doesn't have to handle NaN specially, because the result of an
> > operation on a NaN is usually NaN. So if we take the length squared of
> > a vector which has a NaN member, we will obtain NaN, which is right.
> >
> > But sign() is an exception. Despite what Ben says, the sign of NaN is NaN
> > (the fact that the sign bit doesn't physically disappear is irrelevant). So
> > to handle NaN correctly you've got to catch it, because when you branch
> > as the result of an operation on a NaN, you have to to either take or not
> > take the branch.
> NaN is a device which lets error propagate across calculations so that
> we can efficiently catch it at some convenient point, rather than bog
> down every calculation step wih checks that complicate/bloat the source
> code and slow down the object code.
>
> But you do have to check for NaN somewhere, otherwise the program
> will report it as its output.
>
That's true. However David Brown is also right that once a NaN is generated,
usually it is too late. The calculation is blown away. You do need to try to
stop NaNs from appearing in the first case, except in the rare case that
the high level code has no correct answer to return.
>
> Yes; if you're converting the intermediate result to some other
> representation which itself doesn't have anything analogous to NaN,
> then you might want to check it at that point.
>
> For instance if we convert an "a < b" comparison into two control flows
> which no longer refer to a and b, and those operands could be NaN,
> we should check for NaN. Otherwise the error could be swept under
> the rug.
>
> If all branches of the conditional use both input values to
> continue the calculation, then you may be able to get away without
> handling NaN at that point.
>
> // ternary equivalent:
>
> if (a < b) { return a + c; } else { return b + c; } // bad
>
> Here although the a < b result will conceal NaN, because it's
> not the case that both branches of the code refer to both operands,
> a NaN could be swept under the rug.
>
> if (a < b) { return b - a; } else { return a - b; }
>
> Here we are okay.
>
Yes, that's the problem. There's no easy way of saying "take neither branch".
Comparisons involving NaN return a boolean rather than an "unknown"
value.
>
> Tt is the same with the proposed sign function.
> > sign() written in a non-NaN aware fashion is an example of a function which
> > might appear to have an unreachable closing brace, but in fact the brace is reachable,
> > if the function is called with NaN.
> If the function arbitrarily returned 0, it could work. The caller would
> have to check the *operands* for NaN in the situations where that is
> required, like when the result of sign() is used to select code paths,
> not all of which pull all operands into the calculation.
>
That would be one solution. Zero is a sort of NaN - historically it caused all sorts
of problems, with highly educated mathematicians not really understanding what
it was. So it's not outrageous to say that the sign of NaN is 0.
>
> > It's a mistake which could easily be made.
> > If unreachable() behaves sensibly, then it's a seatbelt.
> Nothing that invokes undefined behavior when the accident occurs
> can be called a seatbelt.
>
> You seem to be mistaking it for abort() or similar.
>
> The unreachable() we have been discussing tells the compiler that the
> code won't be reached. You've proven that somehow and the compiler can
> optimize accordingly.
>
> Given
>
> a()
> {
> unreachable();
> }
>
> b()
> {
> puts("wut?");
> }
>
> It is possible for a call to a() to cause the puts to be called,
> producing the "wut?" output.
>
> That could happen if the functions are emitted, with only no-op
> instructions between them and because of the unreachable assertion,
> the compiler didn't emit the return sequence, for a, so that
> effectively it tail calls into b by falling through.
>
You haven't been following the thread. I was arguing for a defined behaviour
for "unrreachable()".
> > We've made a mistake,
> > but we get an error message or other behaviour which is as useful as it
> > can be, given that the program is incorrect.
> If you want that, you have to reach for something other than
> unreachable assertions.
>
Inherently you can't provide correct behaviour for a program which is incorrect.
However you can provide behaviour which is likely to be useful in uncovering
the errors, or to give the program a reasonable chance of recovering from the
error. There's a tension between the two, because if you recover from the error,
that reduces the motivation to fix it.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2023-09-11 16:07 +0200 |
| Message-ID | <udn6vo$1318q$1@dont-email.me> |
| In reply to | #174987 |
On 11/09/2023 12:25, Bart wrote:
> On 11/09/2023 07:51, David Brown wrote:
>> On 11/09/2023 06:36, Malcolm McLean wrote:
>
>>> 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.
>
> You seem to disagree.
:-)
>
>
>> 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?
>
> You can get them when writing calculators or interpreters, or anything
> where values are not known until runtime.
>
> Even just reading numbers from a file. Or writing a compiler when you
> need to reduce a constant expression.
>
Sure. These are all data from external sources, and need to be verified
and validated. And sometimes there is a possibility of a problem even
though the data is validated - that's okay, as long as you take it into
account. Floating point NaNs let you check for validity after the
calculation, and deal with problems appropriately (like printing an
error message).
And in other cases - such as the code I usually work with - there is no
possibility of NaNs getting into my code. I have no sources of external
data that could produce a NaN, and no external data that comes in
without checking. (I guess I am lucky there.)
> Then INF or IND (I can't seem to get NAN unless IND means NAN) can occur
> when performing calculations between those numbers.
>
Yes, if the numbers can be big enough (or otherwise poorly matched to
the calculations).
>>>
>>> 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.
>
> Another situation where you can't control the inputs is in writing
> library functions, then can be called from 1000 different applications
> written by different people.
Yes. Then you have perhaps three options:
1. Document the function, and insist that people use it correctly.
Those that don't, have themselves to blame - garbage in, garbage out.
This can be the right choice for small utility or calculation functions
or things that have to run efficiently, but would be a poor option for
something with security implications!
2. Document the requirements, then sanitize the inputs for safety and do
your best (which might mean doing nothing at all when the inputs are
invalid). Again, it's garbage in gives garbage out.
3. Document the function, providing some kind of clear error feedback in
the case of invalid inputs.
(Notice that documenting the function and its specification is a common
theme?)
Sometimes checking or sanitizing the inputs means trying to use them
identifying errors, such as NaNs, errno, or failure codes from other
functions.
>
> Then +/- INF/NAN/IND is a possible when writing a sign() function.
>
I disagree. Don't call the function when the input might be a NaN. I'd
consider "sign" to be a "type 1" function from the list above.
Remember, NaN's don't have a sign - they are unordered with respect to
0. So it makes no sense to call the "sign" function on a NaN - doing so
is a user error. There is no possibility of getting a correct answer
when the function is specified to return -1, 0 or 1, and it is given a
NaN. In computer science, there is a name sometimes given to a function
that will produce the correct output when given incorrect input -
"magic". It's great in specifications, but can't be implemented.
People who expect a library function to perform magic are usually
disappointed.
It's find to specify a different function that has a different
specification, and has a documented output for NaNs. It would be a
different function, with at least 4 possible output values - perhaps
given via an enumeration, or with an additional boolean "valid" flag, or
by setting errno.
> My bignum library which implements arbitrary precision floats
> specifically has representations for infinity and nans. This is the
> checking code needed for an add() operation:
>
> switch (getbintype(a,b)) {
> case nn_types:
> break;
> case zz_types:
> bn_setzero(c);
> return 1;
> case nz_types:
> bn_dupl(c,a);
> return 1;
> case zn_types:
> bn_dupl(c,b);
> return 1;
> default:
> bn_setnan(c);
> return 0;
> }
>
> (An 'n' type is a normal number; a 'z' type is just zero, which here is
> a special number.)
>
> Since this is a library, I can't predict what inputs will be supplied.
Agreed.
There had been no suggestion that "sign" was a library function when it
was described, or that it would be at the boundary of code sections.
>
>
>>> 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.
>
> You just haven't been writing the right programs. You don't always have
> control over all the code that is running.
>
Of course you do.
Your compiler has no control over what people type - maybe the source
code will have "int x = 1234567890123456789012345678901234567890;". So
when you are reading data from the source file, it's a string - you know
that. You check it for validity as a number - now you know it is a
string of decimal digits. Your code to turn that into an integer
constant will look at the length and value - now you know it is too
long. And so on.
At each stage, you know about the data you have.
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2023-09-11 16:26 +0100 |
| Message-ID | <8734zkspd5.fsf@bsb.me.uk> |
| In reply to | #174987 |
Bart <bc@freeuk.com> writes:
> On 11/09/2023 07:51, David Brown wrote:
>> 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?
>
> You can get them when writing calculators or interpreters, or anything
> where values are not known until runtime.
"... and not know perfectly well that they are a possibility in that
particular section of the code?"
They don't appear by magic. Is the user of the calculator allowed to
write them and use the deliberately? Then you know about them. And if
not, they only appear as a result of well-known calculations which should,
I contend, be reported to the user rather the be permitted to generate a
NaN.
To be honest, I have not been following closely enough to know what
position everyone is taking in the thread, but it feels like it has
spiralled into one of those where nothing interesting will come of it.
What's needed are actual detailed examples of situations where different
strategies are being proposed and/or criticised. I doubt that's going
to happen now.
Someone brought up the analogy with a safety belt, but it's no a good
one. Covering cases that "can't happen" (it used to be called defensive
programming in another bad analogy with defensive driving) is nothing
like a safety belt. All it usually does is push the error somewhere
else, since if the input was "unexpected" the contrived result will be
too.
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2023-09-11 16:47 +0100 |
| Message-ID | <udncqr$13vc2$1@dont-email.me> |
| In reply to | #175048 |
On 11/09/2023 16:26, Ben Bacarisse wrote: > Bart <bc@freeuk.com> writes: > >> On 11/09/2023 07:51, David Brown wrote: > >>> 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? >> >> You can get them when writing calculators or interpreters, or anything >> where values are not known until runtime. > > "... and not know perfectly well that they are a possibility in that > particular section of the code?" > > They don't appear by magic. Is the user of the calculator allowed to > write them and use the deliberately? Then you know about them. And if > not, they only appear as a result of well-known calculations which should, > I contend, be reported to the user rather the be permitted to generate a > NaN. Say both A are B are floating point numbers that are neither infinity nor NaNs (**). The next bit of code calculates A*B, which might not be representable. And A*B is one term of a bigger expression. So, does the user code perform extensive analysis of each term to determine if each operation will yield a valid result? It's easier and more efficient to try it, even the whole expression, and either test that result, or leave it for something further up the chain to report it. I was just surprised that DB was so confident of all the runtime values in his software that NaNs were never even a remote possibility. (** How actually do you test whether A and B have a valid value? They might come from text to float conversion, and that has the same problems as outlined above. Or maybe from strtod(), or from some input routine, or be parameters to a function. Unless you start getting into option types, the simplest way to determine this is to test for A or B being NaNs.)
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2023-09-11 19:14 +0200 |
| Message-ID | <udnhu0$14pa7$1@dont-email.me> |
| In reply to | #175055 |
On 11/09/2023 17:47, Bart wrote: > On 11/09/2023 16:26, Ben Bacarisse wrote: >> Bart <bc@freeuk.com> writes: >> >>> On 11/09/2023 07:51, David Brown wrote: >> >>>> 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? >>> >>> You can get them when writing calculators or interpreters, or anything >>> where values are not known until runtime. >> >> "... and not know perfectly well that they are a possibility in that >> particular section of the code?" >> >> They don't appear by magic. Is the user of the calculator allowed to >> write them and use the deliberately? Then you know about them. And if >> not, they only appear as a result of well-known calculations which >> should, >> I contend, be reported to the user rather the be permitted to generate a >> NaN. > > Say both A are B are floating point numbers that are neither infinity > nor NaNs (**). > > The next bit of code calculates A*B, which might not be representable. > And A*B is one term of a bigger expression. > > So, does the user code perform extensive analysis of each term to > determine if each operation will yield a valid result? It's easier and > more efficient to try it, even the whole expression, and either test > that result, or leave it for something further up the chain to report it. > > I was just surprised that DB was so confident of all the runtime values > in his software that NaNs were never even a remote possibility. What is the range of a single-precision float? Something like 10 ^ 37, IIRC. So to an overflow, you'd need A and B to be big enough that their product is a 37 digit number. The numbers in my code never do that. They represent real things - the voltage on a pin, the speed of a motor, the temperature on a sensor. If an analogue input on a card is rated for 24 V, it might be scaled so that 25 V is full range on the analogue to digital converter to ensure it is linear within the 24 V range, and to allow easy "out of range" detection. And maybe I will measure a current up to a maximum of 20 A, multiply them together and get 500 W peak. That multiplication is /not/ going to overflow - I could be accurately measuring a lightning strike or the Z Machine (look a that one up on youtube for some great videos), and I still would not be overflowing. Avoiding overflow is a matter of making sure your values are appropriate, and your types are appropriate. I've never had a problem being entirely sure that my integer arithmetic did not overflow - I certainly don't find it hard with floating point. (Again, it's quite reasonable to suggest that the type of coding I do makes this easier than something that has to deal with users feeding in bad data.) > > (** How actually do you test whether A and B have a valid value? They > might come from text to float conversion, and that has the same problems > as outlined above. Or maybe from strtod(), or from some input routine, > or be parameters to a function. > > Unless you start getting into option types, the simplest way to > determine this is to test for A or B being NaNs.) > If that is the simplest test, maybe it's appropriate for your code. But you might also have other limits or ranges to test against.
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2023-09-11 22:30 +0100 |
| Message-ID | <87r0n4qtwt.fsf@bsb.me.uk> |
| In reply to | #175055 |
Bart <bc@freeuk.com> writes: > On 11/09/2023 16:26, Ben Bacarisse wrote: >> Bart <bc@freeuk.com> writes: >> >>> On 11/09/2023 07:51, David Brown wrote: >> >>>> 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? >>> >>> You can get them when writing calculators or interpreters, or anything >>> where values are not known until runtime. >> "... and not know perfectly well that they are a possibility in that >> particular section of the code?" >> They don't appear by magic. Is the user of the calculator allowed to >> write them and use the deliberately? Then you know about them. And if >> not, they only appear as a result of well-known calculations which should, >> I contend, be reported to the user rather the be permitted to generate a >> NaN. > > Say both A are B are floating point numbers that are neither infinity > nor NaNs (**). The next bit of code calculates A*B, which might not > be representable. OK. I am already worried that you are going to pose a question without any context about the code. Is it to go in my pacemaker, or is it your personal ten-line program to print an estimate of your mortgage repayments? > And A*B is one term of a bigger expression. And we're off... The possibly interesting start (A and B being reasonably well specified) is now gone and A*B is essentially irrelevant because anything is possible in the "bigger expression". You should have started: "say we have some expression about which I will tell you absolutely nothing, in a program whose purpose is a mystery". > So, does the user code perform extensive analysis of each term to determine > if each operation will yield a valid result? The question can't be answered without knowing the purpose and/or the design of the code. > It's easier and more efficient > to try it, even the whole expression, and either test that result, or leave > it for something further up the chain to report it. That's often the case, yes. How does this relate to what I wrote? You appear to be just making vague remarks about unknown code in unknown programs with unknown requirements. > I was just surprised that DB was so confident of all the runtime values in > his software that NaNs were never even a remote possibility. I wasn't surprised, because I don't know the kind of code he writes and works with. Why were you surprised? Do you know the kind of he's talking about, or is surprise your default position when someone tells you something about their work with C? > (** How actually do you test whether A and B have a valid value? ! I am going to assume this is a rhetorical question for now. -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2023-09-11 23:07 +0100 |
| Message-ID | <udo32o$17c2v$1@dont-email.me> |
| In reply to | #175086 |
On 11/09/2023 22:30, Ben Bacarisse wrote: > Bart <bc@freeuk.com> writes: > >> On 11/09/2023 16:26, Ben Bacarisse wrote: >>> Bart <bc@freeuk.com> writes: >>> >>>> On 11/09/2023 07:51, David Brown wrote: >>> >>>>> 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? >>>> >>>> You can get them when writing calculators or interpreters, or anything >>>> where values are not known until runtime. >>> "... and not know perfectly well that they are a possibility in that >>> particular section of the code?" >>> They don't appear by magic. Is the user of the calculator allowed to >>> write them and use the deliberately? Then you know about them. And if >>> not, they only appear as a result of well-known calculations which should, >>> I contend, be reported to the user rather the be permitted to generate a >>> NaN. >> >> Say both A are B are floating point numbers that are neither infinity >> nor NaNs (**). The next bit of code calculates A*B, which might not >> be representable. > > OK. I am already worried that you are going to pose a question without > any context about the code. Is it to go in my pacemaker, or is it your > personal ten-line program to print an estimate of your mortgage > repayments? > >> And A*B is one term of a bigger expression. > > And we're off... The possibly interesting start (A and B being > reasonably well specified) is now gone and A*B is essentially irrelevant > because anything is possible in the "bigger expression". > > You should have started: "say we have some expression about which I will > tell you absolutely nothing, in a program whose purpose is a mystery". If you are implementing software which implements programs (such as compilers and interpreters) then this is pretty much it. The input is a program whose purpose and importance is unknown. The same can apply to a lesser extent to a calculator program, one of those where you can can enter a multi-term expression before pressing 'equals'. >> So, does the user code perform extensive analysis of each term to determine >> if each operation will yield a valid result? > > The question can't be answered without knowing the purpose and/or the > design of the code. I've given a scenario of writing code 'indirectly' so that that information is not available. Actually I've already made these points. You seem to want to customise approaches according to a specific task in hand. I'm looking at it more generally. >> It's easier and more efficient >> to try it, even the whole expression, and either test that result, or leave >> it for something further up the chain to report it. > > That's often the case, yes. How does this relate to what I wrote? You > appear to be just making vague remarks about unknown code in unknown > programs with unknown requirements. Yes, it can be that the programs and requirements are unknown, and your job is just to do the calculations or provide the means of doing so. Maybe you're writing a routine to go into library. >> I was just surprised that DB was so confident of all the runtime values in >> his software that NaNs were never even a remote possibility. > > I wasn't surprised, because I don't know the kind of code he writes and > works with. Why were you surprised? Do you know the kind of he's > talking about, or is surprise your default position when someone tells > you something about their work with C? >> (** How actually do you test whether A and B have a valid value? > > ! I am going to assume this is a rhetorical question for now. Not really. Why shouldn't you look at exactly how inputs are obtained? If they are supplied ready-formed into iee754 representations, that a NaN-check might be something you can look into. If you are involved in deriving those representations, then this just moves the discussion to that earlier stage.
[toc] | [prev] | [next] | [standalone]
| From | scott@slp53.sl.home (Scott Lurndal) |
|---|---|
| Date | 2023-09-11 23:31 +0000 |
| Message-ID | <PrNLM.5064$yQ_.903@fx47.iad> |
| In reply to | #175099 |
Bart <bc@freeuk.com> writes: >On 11/09/2023 22:30, Ben Bacarisse wrote: >> Bart <bc@freeuk.com> writes: >> >>> On 11/09/2023 16:26, Ben Bacarisse wrote: >>>> Bart <bc@freeuk.com> writes: >>>> >>>>> On 11/09/2023 07:51, David Brown wrote: >>>> >>>>>> 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? >>>>> >>>>> You can get them when writing calculators or interpreters, or anything >>>>> where values are not known until runtime. >>>> "... and not know perfectly well that they are a possibility in that >>>> particular section of the code?" >>>> They don't appear by magic. Is the user of the calculator allowed to >>>> write them and use the deliberately? Then you know about them. And if >>>> not, they only appear as a result of well-known calculations which should, >>>> I contend, be reported to the user rather the be permitted to generate a >>>> NaN. >>> >>> Say both A are B are floating point numbers that are neither infinity >>> nor NaNs (**). The next bit of code calculates A*B, which might not >>> be representable. >> >> OK. I am already worried that you are going to pose a question without >> any context about the code. Is it to go in my pacemaker, or is it your >> personal ten-line program to print an estimate of your mortgage >> repayments? >> >>> And A*B is one term of a bigger expression. >> >> And we're off... The possibly interesting start (A and B being >> reasonably well specified) is now gone and A*B is essentially irrelevant >> because anything is possible in the "bigger expression". >> >> You should have started: "say we have some expression about which I will >> tell you absolutely nothing, in a program whose purpose is a mystery". > >If you are implementing software which implements programs (such as >compilers and interpreters) then this is pretty much it. How many compilers use floating point arithmetic expressions internally?
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2023-09-12 09:18 +0200 |
| Message-ID | <udp3cn$1eviv$1@dont-email.me> |
| In reply to | #175104 |
On 12/09/2023 01:31, Scott Lurndal wrote: > Bart <bc@freeuk.com> writes: >> On 11/09/2023 22:30, Ben Bacarisse wrote: >>> You should have started: "say we have some expression about which I will >>> tell you absolutely nothing, in a program whose purpose is a mystery". >> >> If you are implementing software which implements programs (such as >> compilers and interpreters) then this is pretty much it. > > How many compilers use floating point arithmetic expressions internally? I'd assume that most compilers do so when dealing with constant floating point expressions (such as initialisers). The programmer could write "double x = 2e200 * 3e300;". (My understanding is that more advanced ones will emulate the floating point calculations in libraries designed to match the target devices bit-perfectly, so that they can pre-calculate things at compile time with /exactly/ the same results as the target platform would give at run time. But that is a very significant amount of effort - I believe the library gcc and clang uses for this is an order of magnitude bigger than Bart's entire compiler.)
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2023-09-12 03:01 +0100 |
| Message-ID | <87wmwwp2ub.fsf@bsb.me.uk> |
| In reply to | #175099 |
Bart <bc@freeuk.com> writes: > On 11/09/2023 22:30, Ben Bacarisse wrote: >> Bart <bc@freeuk.com> writes: >> >>> On 11/09/2023 16:26, Ben Bacarisse wrote: >>>> Bart <bc@freeuk.com> writes: >>>> >>>>> On 11/09/2023 07:51, David Brown wrote: >>>> >>>>>> 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? >>>>> >>>>> You can get them when writing calculators or interpreters, or anything >>>>> where values are not known until runtime. >>>> "... and not know perfectly well that they are a possibility in that >>>> particular section of the code?" >>>> They don't appear by magic. Is the user of the calculator allowed to >>>> write them and use the deliberately? Then you know about them. And if >>>> not, they only appear as a result of well-known calculations which should, >>>> I contend, be reported to the user rather the be permitted to generate a >>>> NaN. >>> >>> Say both A are B are floating point numbers that are neither infinity >>> nor NaNs (**). The next bit of code calculates A*B, which might not >>> be representable. >> OK. I am already worried that you are going to pose a question without >> any context about the code. Is it to go in my pacemaker, or is it your >> personal ten-line program to print an estimate of your mortgage >> repayments? >> >>> And A*B is one term of a bigger expression. >> And we're off... The possibly interesting start (A and B being >> reasonably well specified) is now gone and A*B is essentially irrelevant >> because anything is possible in the "bigger expression". >> You should have started: "say we have some expression about which I will >> tell you absolutely nothing, in a program whose purpose is a mystery". > > If you are implementing software which implements programs (such as > compilers and interpreters) then this is pretty much it. Nonsense. If you are implementing it, you have the code -- right there in front on you. I am not avoiding the question, I am avoiding the question without code. And you also have the context -- what sort of compiler and/or interpreter? What part? What are the language rules? Does it have IEEE 754 arithmetic? Does it have quiet or signalling NaNs? So, what are you asking and about what code? Give details. I just said "NaNs don't appear by magic", and you went off asking about A*B in some unknown larger expression. I have no idea what point you were trying to make. >>> So, does the user code perform extensive analysis of each term to determine >>> if each operation will yield a valid result? >> The question can't be answered without knowing the purpose and/or the >> design of the code. > > I've given a scenario of writing code 'indirectly' so that that information > is not available. You don't write code indirectly. You write the compiler. Or you write the interpreter. If you have a point, please get to it. Where in the writing of the compiler or interpreter are you concerned about NaNs and what is the point you are trying to make about them? > Actually I've already made these points. You seem to want to customise > approaches according to a specific task in hand. I'm looking at it more > generally. > >>> It's easier and more efficient >>> to try it, even the whole expression, and either test that result, or leave >>> it for something further up the chain to report it. >> That's often the case, yes. How does this relate to what I wrote? You >> appear to be just making vague remarks about unknown code in unknown >> programs with unknown requirements. > > Yes, it can be that the programs and requirements are unknown, and your job > is just to do the calculations or provide the means of doing so. Maybe > you're writing a routine to go into library. If the requirements are unknown, my job is easy. Every arithmetic operation will return zero. But if you give me a minimal spec: "do actual arithmetic", I'll map the operations to the simplest implementation I can imagine since apparently no one cares what happens for 1/0 or 0/0. If you tell me what you want, then I will know how to implement it. This is pretty close to the silliest discussion I've even been involved in. >>> (** How actually do you test whether A and B have a valid value? >> ! I am going to assume this is a rhetorical question for now. > > Not really. You wrote a C implementation and you don't know how to check if a floating point value is valid (by which I suppose you mean, not a NaN, not an infinity and not subnormal)? -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.arthur.mclean@gmail.com> |
|---|---|
| Date | 2023-09-11 10:08 -0700 |
| Message-ID | <f7077ac4-908c-41e9-96a0-58cf9df4d494n@googlegroups.com> |
| In reply to | #175048 |
On Monday, 11 September 2023 at 16:26:30 UTC+1, Ben Bacarisse wrote: > > Someone brought up the analogy with a safety belt, but it's no a good > one. Covering cases that "can't happen" (it used to be called defensive > programming in another bad analogy with defensive driving) is nothing > like a safety belt. All it usually does is push the error somewhere > else, since if the input was "unexpected" the contrived result will be > too. > That analogy was because David Brown was making out that, because I consider the possibility that there might be errors in my code, I'm therefore a bad programmer. You're right that when a program is incorrect, it's hard to provide correct behaviour. But things which are liley to be helpful and things which are likely not to be. Bascially programs fall into two categories. Life support systems, where the worst thing you can do is return wrong results. And video games, where the worst thing you can do is return no results. If the life support system returns the wrong value for the oxygen, then the patient suffocates to death. If it crashes out, the alarm goes off, the nurse comes running, and the patient is administered emergency manual oxygen whilst a new machine is brought. If a video game returns a wrong result, then anything could happen to the game (infinite levels, etc), but most likely the screen will flash a mess for a single frame, then the game will recover. The player will just notice a glitch. If it returns no results, the game is dead. The player will likely ask for his money back. So you have to know which type of program you are writing before you decide your error strategy.
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2023-09-11 23:18 +0100 |
| Message-ID | <87ledcqrp0.fsf@bsb.me.uk> |
| In reply to | #175059 |
Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes: > On Monday, 11 September 2023 at 16:26:30 UTC+1, Ben Bacarisse wrote: >> >> Someone brought up the analogy with a safety belt, but it's no a good >> one. Covering cases that "can't happen" (it used to be called defensive >> programming in another bad analogy with defensive driving) is nothing >> like a safety belt. All it usually does is push the error somewhere >> else, since if the input was "unexpected" the contrived result will be >> too. >> > That analogy was because David Brown was making out that, because I > consider the possibility that there might be errors in my code, I'm > therefore a bad programmer. That seems very unlikely. Do you have a citation? > You're right that when a program is incorrect, it's hard to provide correct > behaviour. But things which are liley to be helpful and things which are > likely not to be. Bascially programs fall into two categories. Oh, here we go... > Life support > systems, where the worst thing you can do is return wrong results. And > video games, where the worst thing you can do is return no results. I am sure you can shoe-horn any other possibility into what you imagine these two categories contain. I will, however note that one is often designing code not programs. The authors of the C library don't know where it will be linked. > If the life support system returns the wrong value for the oxygen, then > the patient suffocates to death. If it crashes out, the alarm goes off, the > nurse comes running, and the patient is administered emergency manual > oxygen whilst a new machine is brought. Is it "crashing out" because a result was wrong or because there was no result? I'm just curious where this case lies in your arbitrary divide. > If a video game returns a wrong result, then anything could happen So the effect could be just the same as whatever you mean by "no result". > to the game (infinite levels, etc), but most likely the screen will > flash a mess for a single frame, then the game will recover. The > player will just notice a glitch. If it returns no results, the game > is dead. The player will likely ask for his money back. And if "no result" is returned, everything might be well again by the next frame cycle, just as returning the wrong result from some function might kill the game. > So you have to know which type of program you are writing before you decide > your error strategy. No. You can design code, and even whole programs, without ever making that decision. I don't think I've ever written a program that comes down on one side or the other of this curious divide. Anyway, none of this helps move the discussion forward. To do that someone must propose an actual example (simplified of course but with enough detail to be able to consider the options properly) and we can all then consider how we'd try to ameliorate the effect of possible programming errors. -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2023-09-11 23:37 +0100 |
| Message-ID | <udo4s3$17hu7$1@dont-email.me> |
| In reply to | #175100 |
On 11/09/2023 23:18, Ben Bacarisse wrote: > Malcolm McLean <malcolm.arthur.mclean@gmail.com> writes: > >> On Monday, 11 September 2023 at 16:26:30 UTC+1, Ben Bacarisse wrote: >>> >>> Someone brought up the analogy with a safety belt, but it's no a good >>> one. Covering cases that "can't happen" (it used to be called defensive >>> programming in another bad analogy with defensive driving) is nothing >>> like a safety belt. All it usually does is push the error somewhere >>> else, since if the input was "unexpected" the contrived result will be >>> too. >>> >> That analogy was because David Brown was making out that, because I >> consider the possibility that there might be errors in my code, I'm >> therefore a bad programmer. > > That seems very unlikely. Do you have a citation? > >> You're right that when a program is incorrect, it's hard to provide correct >> behaviour. But things which are liley to be helpful and things which are >> likely not to be. Bascially programs fall into two categories. > > Oh, here we go... > >> Life support >> systems, where the worst thing you can do is return wrong results. And >> video games, where the worst thing you can do is return no results. > > I am sure you can shoe-horn any other possibility into what you imagine > these two categories contain. You also gave two extreme examples of applications. Is that good or bad? As you seem to be criticising that here. (But I've lost track of the discussion. To backtrack a little, I think it was the possibility of NaNs in floating-point values that would have caused an example non-void function to unexpectedly hit the closing '}'.)
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.arthur.mclean@gmail.com> |
|---|---|
| Date | 2023-09-11 15:46 -0700 |
| Message-ID | <08ac58d7-8c26-4dff-9916-92790b078d81n@googlegroups.com> |
| In reply to | #175101 |
On Monday, 11 September 2023 at 23:38:08 UTC+1, Bart wrote: > On 11/09/2023 23:18, Ben Bacarisse wrote: > > Malcolm McLean <malcolm.ar...@gmail.com> writes: > > > >> On Monday, 11 September 2023 at 16:26:30 UTC+1, Ben Bacarisse wrote: > >>> > >>> Someone brought up the analogy with a safety belt, but it's no a good > >>> one. Covering cases that "can't happen" (it used to be called defensive > >>> programming in another bad analogy with defensive driving) is nothing > >>> like a safety belt. All it usually does is push the error somewhere > >>> else, since if the input was "unexpected" the contrived result will be > >>> too. > >>> > >> That analogy was because David Brown was making out that, because I > >> consider the possibility that there might be errors in my code, I'm > >> therefore a bad programmer. > > > > That seems very unlikely. Do you have a citation? > > > >> You're right that when a program is incorrect, it's hard to provide correct > >> behaviour. But things which are liley to be helpful and things which are > >> likely not to be. Bascially programs fall into two categories. > > > > Oh, here we go... > > > >> Life support > >> systems, where the worst thing you can do is return wrong results. And > >> video games, where the worst thing you can do is return no results. > > > > I am sure you can shoe-horn any other possibility into what you imagine > > these two categories contain. > You also gave two extreme examples of applications. > > Is that good or bad? As you seem to be criticising that here. > > (But I've lost track of the discussion. To backtrack a little, I think > it was the possibility of NaNs in floating-point values that would have > caused an example non-void function to unexpectedly hit the closing '}'.) > Yes. Sign() is an example of a function which a programmer might erroneously consider to have a closing brace which is unreachable, because he has forgotten that NaN always compares false.When we realise that this is a very real possibility, what are the implications for how an unreachable() statement should behave? However the discussion was derailed by someone sniping that, in his code, unexpected NaNs never occur.
[toc] | [prev] | [next] | [standalone]
Page 3 of 7 — ← Prev page 1 2 [3] 4 5 6 7 Next page →
Back to top | Article view | comp.lang.c
csiph-web