Computer Chess Club Archives


Search

Terms

Messages

Subject: Re: One (silly) question about "C"

Author: Dann Corbit

Date: 12:31:25 02/05/02

Go up one level in this thread


On February 05, 2002 at 13:13:09, Miguel A. Ballicora wrote:
[snip]
>>>    register int n=(count+7)/8;
>>>
>>>    switch(count & 7){
>>>        case 0: do { *to++ = *from++;
>>>        case 7:      *to++ = *from++;
>>>        case 6:      *to++ = *from++;
>>>        case 5:      *to++ = *from++;
>>>        case 4:      *to++ = *from++;
>>>        case 3:      *to++ = *from++;
>>>        case 2:      *to++ = *from++;
>>>        case 1:      *to++ = *from++;
>>>                } while(--n > 0);
>>>    }
>>>
>>
>>Nice -:(
>>
>>The "do ... while" in the switch statement is really driving me crazy.
>>
>>Regards, Uli
>
>I will check K&RII later but IIRC case 0: can be understood as a label
>and I just figure that the same will be with "do"
>and  "while ()" would be the same as "if () goto".
>You can jump right into the middle of this loop, crazy isn'it?

It's found in the C FAQ:
20.35:  What is "Duff's Device"?

A:      It's a devastatingly deviously unrolled byte-copying loop,
        devised by Tom Duff while he was at Lucasfilm.  In its "classic"
        form, it looks like:

                register n = (count + 7) / 8;   /* count > 0 assumed */
                switch (count % 8)
                {
                case 0:    do { *to = *from++;
                case 7:         *to = *from++;
                case 6:         *to = *from++;
                case 5:         *to = *from++;
                case 4:         *to = *from++;
                case 3:         *to = *from++;
                case 2:         *to = *from++;
                case 1:         *to = *from++;
                              } while (--n > 0);
                }

        where count bytes are to be copied from the array pointed to by
        from to the memory location pointed to by to (which is a memory-
        mapped device output register, which is why to isn't
        incremented).  It solves the problem of handling the leftover
        bytes (when count isn't a multiple of 8) by interleaving a
        switch statement with the loop which copies bytes 8 at a time.
        (Believe it or not, it *is* legal to have case labels buried
        within blocks nested in a switch statement like this.  In his
        announcement of the technique to C's developers and the world,
        Duff noted that C's switch syntax, in particular its "fall
        through" behavior, had long been controversial, and that "This
        code forms some sort of argument in that debate, but I'm not
        sure whether it's for or against.")

From my benchmarking, memcpy() is faster.  Duff's device can be worthwhile in a
few rare circumstances (e.g. compiler does not know how to unroll and the data
objects in the array are large).  It can also cause large problems on vector
machines (e.g. an enormous slowdown rather than a speedup).

For the most part, the day for Duff's device as a useful computing tool are
past.  All the compilers I use know how to unroll anyway.



This page took 0.01 seconds to execute

Last modified: Thu, 15 Apr 21 08:11:13 -0700

Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.