Prev: LM3478 design gets insanely hot
Next: 89C51ED2
From: Jan Panteltje on 14 Aug 2008 06:52 On a sunny day (14 Aug 2008 10:25:59 GMT) it happened nmm1(a)cus.cam.ac.uk (Nick Maclaren) wrote in <g8117n$af2$1(a)gemini.csx.cam.ac.uk>: > >In article <g810br$ou9$1(a)aioe.org>, >Jan Panteltje <pNaonStpealmtje(a)yahoo.com> writes: >|> > >|> >The length is passed around as uint32_t, but so are rather a lot of >|> >other fields. In a year or so, the program is upgraded to support >|> >another interface, which allows 48- or 64-bit file lengths. >|> >|> That is babble. >|> A new file specification will have an other header, or will be in >|> an extention field of the current header. >|> The whole program would be a different one, as all length calculations >|> and checks would change. >|> I have been there, done that. > >Precisely. And, if you would learn from the experience of the past, >all you would have to change is the interface code - the rest of the >program would not even need inspecting. > >Been there - done that. Many times, in many contexts. > > >Regards, >Nick Maclaren. I know we can go on, but probably mean the same thing in the end, but 'the program would not need inspecting (or changing)' sounds a bit, eh, daring, if not wrong. Take the example of a program that concatenates some wave files to one larger one. It will first read all headers, add the sizes, and then, if it finds the output exceeds 4GB say: 'myprogram: output exceeds 4GB, aborting.' So, the size check, and the reporting, would need to change, in any case. However there is much more, depending how really pedantic one was in reading the file headers, perhaps as length = byte + (byte * 256) + (byte * 65536) + etc. I do not claim to be the perfect coder, and you compiler writers know more about the specs then I do, but - I do try to learn from these discussions, and other similar ones in relevant newsgroups -. It has caused me on several occasions to rewrite my code. Will it ever be perfect? No, but usable, with no errors, yes. When I get an email (this happened when AMD 64 came out) saying: Your program always worked fine, but now I have an AMD 128, and it reports the wrong output file size', what do I do now?' it will be back to the source code for me, or somebody else.
From: Nick Maclaren on 14 Aug 2008 07:09 This is getting ridiculously off-topic, and this will be my last posting on this sub-thread. In article <g812p9$5nl$1(a)aioe.org>, Jan Panteltje <pNaonStpealmtje(a)yahoo.com> writes: |> |> I know we can go on, but probably mean the same thing in the end, |> but 'the program would not need inspecting (or changing)' sounds a |> bit, eh, daring, if not wrong. |> Take the example of a program that concatenates some wave files to |> one larger one. |> It will first read all headers, add the sizes, and then, if it finds the |> output exceeds 4GB say: 'myprogram: output exceeds 4GB, aborting.' |> So, the size check, and the reporting, would need to change, in any case. That is not how to approach such a problem. Inter alia, it prevents the program from concatenating files in a format with a 4 GB limit and writing them to one with a larger limit. You should write it like this: Each header is read and decodes, and the length is put in an internal format integer. The concatenation code adds the lengths, checking that they don't overflow, and giving a diagnostic if they do. It then writes the result to the output, checking that the file will fit, and diagnosing if it won't. Regards, Nick Maclaren.
From: Wilco Dijkstra on 14 Aug 2008 07:13 "Martin Brown" <|||newspam|||@nezumi.demon.co.uk> wrote in message news:66cf5$48a3fb0d$25237(a)news.teranews.com... > The worst pointer related faults I have ever had to find was as an outsider diagnosing faults in a customers large > software base. The crucial mode of failure was a local copy of a pointer to an object that was subsequently > deallocated but stayed around unmolested for long enough for the program to mostly still work except when it didn't. Those are very nasty indeed. However they aren't strictly pointer related - a language without pointers suffers from the same issue (even garbage collection doesn't solve this kind of problem). ValGrind is good at finding issues like this. Automatic checking tools have improved significantly over the last 10 years. The worst problem I've seen is a union of a pointer and an integer which was used as a set of booleans, which were confused by the code. So the last few bits of the pointer were sometimes being changed by setting or clearing the booleans. Similarly the value of the booleans were different on different systems or if you changed command-line options, compiled for debug etc. Wilco
From: Jan Panteltje on 14 Aug 2008 07:27 On a sunny day (14 Aug 2008 11:09:51 GMT) it happened nmm1(a)cus.cam.ac.uk (Nick Maclaren) wrote in <g813pv$h3c$1(a)gemini.csx.cam.ac.uk>: > >This is getting ridiculously off-topic, and this will be my last >posting on this sub-thread. OK. >In article <g812p9$5nl$1(a)aioe.org>, >Jan Panteltje <pNaonStpealmtje(a)yahoo.com> writes: >|> >|> I know we can go on, but probably mean the same thing in the end, >|> but 'the program would not need inspecting (or changing)' sounds a >|> bit, eh, daring, if not wrong. >|> Take the example of a program that concatenates some wave files to >|> one larger one. >|> It will first read all headers, add the sizes, and then, if it finds the >|> output exceeds 4GB say: 'myprogram: output exceeds 4GB, aborting.' >|> So, the size check, and the reporting, would need to change, in any case. > >That is not how to approach such a problem. Inter alia, it prevents >the program from concatenating files in a format with a 4 GB limit >and writing them to one with a larger limit. You should write it >like this: > >Each header is read and decodes, and the length is put in an internal >format integer. Yes this is what I do, so? >The concatenation code adds the lengths, checking that they don't >overflow, and giving a diagnostic if they do. Yes, and 'overflow' is set by the format it reads, in this case the wave format, and that is fixed at 4GB. >It then writes the result to the output, checking that the file will >fit, and diagnosing if it won't. No, it writes only output if it fits, and if it does not, then it switches to raw mode actually (actually it proposes a new command line). As raw mode has no file limit (other then OS and filesystem limitations). See, I *wrote* this program for real, you are only dreaming about one.
From: Terje Mathisen on 14 Aug 2008 08:46
Wilco Dijkstra wrote: > "Terje Mathisen" <terje.mathisen(a)hda.hydro.com> wrote in message news:V92dnbsbmsAAST7VRVnyvwA(a)giganews.com... >> How many ways can you define such a function? >> >> The only serious alternatives would be in the handling of negative-or-zero inputs or when rounding the actual fp >> result to integer: >> >> Do you want the Floor(), i.e. truncate, Ceil() or Round_to_nearest_or_even()? >> >> Using the latest alternative could make it harder to come up with a perfect implementation, but otherwise it should be >> trivial. > > It was a trivial routine, just floor(log2(x)), so just finding the top bit that is set. > The mistakes were things like not handling zero, using signed rather than > unsigned variables, looping forever for some inputs, returning the floor result + 1. > > Rather than just shifting the value right until it becomes zero, it created a mask > and shifted it left until it was *larger* than the input (which is not going to work > if you use a signed variable for it or if the input has bit 31 set etc). > > My version was something like: > > int log2_floor(unsigned x) > { > int n = -1; > for ( ; x != 0; x >>= 1) > n++; > return n; > } <BG> That is _identical_ to the code I originally wrote as part of my post, but then deleted as it didn't really add to my argument. :-) There are of course many possible alternative methods, including inline asm to use a hardware bitscan opcode. Here's a possibly faster version: int log2_floor(unsigned x) { int n = -1; while (x >= 0x10000) { n += 16; x >>= 16; } if (x >= 0x100) { n += 8; x >>= 8; } if (x >= 0x10) { n += 4; x >>= 4; } /* At this point x has been reduced to the 0-15 range, use a * register-internal lookup table: */ uint32_t lookup_table = 0xffffaa50; int lookup = (int) (lookup_table >> (x+x)) & 3; return n + lookup; } or to make it branchless: int log2_floor(unsigned x) { int n = -1; int gt = (x >= 0x10000) << 4; // 0 or 16 n += gt; x >>= gt; gt = (x >= 0x100) << 3; n += gt; x >>= gt; gt = (x >= 0x10) << 2; n += gt; x >>= gt; uint32_t lookup_table = 0xffffaa50; // 0011222233333333 int lookup = (int) (lookup_table >> (x+x)) & 3; return n + lookup; } Terje -- - <Terje.Mathisen(a)hda.hydro.com> "almost all programming can be viewed as an exercise in caching" |