Deutsch   English   Français   Italiano  
<vbl3am$228vv$1@dont-email.me>

View for Bookmarking (what is this?)
Look up another Usenet article

Path: ...!eternal-september.org!feeder3.eternal-september.org!news.eternal-september.org!.POSTED!not-for-mail
From: Bart <bc@freeuk.com>
Newsgroups: comp.lang.c
Subject: Re: Top 10 most common hard skills listed on resumes...
Date: Sun, 8 Sep 2024 22:01:10 +0100
Organization: A noiseless patient Spider
Lines: 165
Message-ID: <vbl3am$228vv$1@dont-email.me>
References: <vab101$3er$1@reader1.panix.com> <871q27weeh.fsf@bsb.me.uk>
 <20240829083200.195@kylheku.com> <87v7zjuyd8.fsf@bsb.me.uk>
 <20240829084851.962@kylheku.com> <87mskvuxe9.fsf@bsb.me.uk>
 <vaq9tu$1te8$1@dont-email.me> <vbci8r$1c9e8$1@paganini.bofh.team>
 <vbcs65$eabn$1@dont-email.me> <vbekut$1kd24$1@paganini.bofh.team>
 <vbepcb$q6p2$1@dont-email.me> <vbgb5q$1ruv8$1@paganini.bofh.team>
 <vbhbbb$1blt4$1@dont-email.me> <vbipp5$24kl5$1@paganini.bofh.team>
 <vbk0d9$1tajm$1@dont-email.me> <vbkpfc$27l2o$1@paganini.bofh.team>
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8; format=flowed
Content-Transfer-Encoding: 7bit
Injection-Date: Sun, 08 Sep 2024 23:01:11 +0200 (CEST)
Injection-Info: dont-email.me; posting-host="ad79b9a69b5377684053ea6685c7dbff";
	logging-data="2171903"; mail-complaints-to="abuse@eternal-september.org";	posting-account="U2FsdGVkX18ijpRPM2MKJJIPNBRih1W/"
User-Agent: Mozilla Thunderbird
Cancel-Lock: sha1:Su5PbQ8DjQimzKs1Zn8qit3I0V0=
Content-Language: en-GB
In-Reply-To: <vbkpfc$27l2o$1@paganini.bofh.team>
Bytes: 6841

On 08/09/2024 19:13, Waldek Hebisch wrote:
> Bart <bc@freeuk.com> wrote:

>> Like being able define anonymous structs always anywhere, or allowing
>> multiple declarations of the same module-level variables and functions.
> 
> Look at this C code:
> 
> void
> do_bgi_add(unsigned int * dst, int xlen, unsigned int * xp,
>       int ylen, unsigned int * yp) {
>      if (ylen < xlen) {
>          int tmp = xlen;
>          xlen = ylen;
>          ylen = tmp;
>          unsigned int * tmpp = xp;
>          xp = yp;
>          yp = tmpp;
>      }
>      unsigned int xext = (unsigned int)(((int)(xp[xlen - 1])) >> 31);
>      unsigned int yext = (unsigned int)(((int)(yp[ylen - 1])) >> 31);
>      unsigned int c = 0;
>      int i = 0;
>      while(i < xlen) {
>          unsigned long long pp = (unsigned long long)(xp[i])
>                                + (unsigned long long)(yp[i])
>                                + (unsigned long long)c;
>          dst[i] = pp;
>          c = (pp >> (32ULL));
>          i++;
>      }
>      while(i < ylen) {
>          unsigned long long pp = (unsigned long long)xext
>                                + (unsigned long long)(yp[i])
>                                + (unsigned long long)c;
>          dst[i] = pp;
>          c = (pp >> (32ULL));
>          i++;
>      }
>      {
>          unsigned long long pp = (unsigned long long)xext
>                                + (unsigned long long)yext
>                                + (unsigned long long)c;
>          dst[i] = pp;
>      }
> }
> 
> 
> I claim that is is better than what could be done in early Pascal.
> Temporary variables are declared exactly in scopes where they are
> needed, I reuse the same name for 'pp' but scoping makes clear
> that different 'pp' are different variables.  All variables
> are initialised at declaration time with sensible values.  Only
> parameters, 'i' and 'c' are common to various stages, they have
> to.  Note that 'xext' and 'yext' are declared at point where I
> can compute initial value.  Also note that among ordinary
> variables only 'i' and 'c' are reassigned (I need to swap parameters
> to simplify logic and 'dst' array entries are assigned as part of
> function contract).  Fact that variables are not reassigned could
> be made clearer by declaring them as 'const'.

I had a problem with this code because it was so verbose. The first 
thing I did was to define aliases u64 and u32 for those long types:

  typedef unsigned long long u64;
  typedef unsigned long u32;

Then I removed some casts that I thought were not necessary. The first 
result looks like this:

---------------------------
void do_bgi_add(u32 * dst, int xlen, u32 * xp, int ylen, u32 * yp) {
     u32 xext, yext, c;
     u64 pp;
     int i;

     if (ylen < xlen) {
         int tmp = xlen;
         xlen = ylen;
         ylen = tmp;
         u32 * tmpp = xp;
         xp = yp;
         yp = tmpp;
     }

     xext = ((int)(xp[xlen - 1])) >> 31;
     yext = ((int)(yp[ylen - 1])) >> 31;

     c = 0;
     i = 0;
     while(i < xlen) {
         pp = (u64)(xp[i]) + (u64)yp[i] + c;
         dst[i] = pp;
         c = pp >> 32;
         i++;
     }

    while(i < ylen) {
         pp = (u64)xext  + (u64)yp[i]  + c;
         dst[i] = pp;
         c = pp >> 32;
         i++;
     }
     pp = (u64)xext + (u64)yext + c;
     dst[i] = pp;
}
---------------------------

Things actually fit onto one line! It's easier now to grasp what's going 
on. There are still quite a few casts; it would be better if xext/yext/c 
were all u64 type instead of u32.

pp seems to used for the same purpose throughout, so I can't see the 
point in declaring three separate versions of the same thing.

I didn't take the C version further, but I did port it to my syntax to 
see what it might look like; that is shown below.

That uses 64-bits, but the arrays are still 32 bits (and here passed by 
reference and are actual arrays, not pointer). I rearranged the 
parameters for clarity.

This is now 20 non-blank lines vs 38 of your original, and has a 60% 
smaller character count. But this is more about keeping clutter away 
from the main body of the function.

Then it becomes easier to reason about it, something you also seem to 
claim. For example, I probably don't need 'c'; I can set pp := 0 then 
use pp.[32] as needed; two more lines gone. Now however, pp needs to 
have function-scope.

Now please post a version in Forth!

---------------------------
proc do_bgi_add(ref[]u32 dest, xp, yp, int xlen, ylen)=
     u64 xext, yext, c, pp, i

     if ylen < xlen then
         swap(xlen, ylen)
         swap(xp, yp)
     fi

     xext := xp[xlen].[31]
     yext := yp[ylen].[31]

     c := 0
     i := 1
     while i <= xlen, ++i do
         dst[i] := pp := xp[i] + yp[i] + c
         c := pp.[32]
     od

     while i <= ylen, ++i do
         dst[i] := pp := xext + yp[i] + c
         c := pp.[32]
     od

     dst[i] := xext + yext + c
end
---------------------------

(Special features: X.[i] is bit indexing. While-loops can have an option 
incremental (left over from a suggestion for C where 'for' was 
over-used); as written, the arrays are 1-based. 'swap' is a built-in op.)