I'm not very happy with the do {} while() statement in C

Discussion of chess software programming and technical issues.

Moderators: hgm, Harvey Williamson, bob

Forum rules
This textbox is used to restore diagrams posted with the [d] tag before the upgrade.
Michael Sherwin
Posts: 2822
Joined: Fri May 26, 2006 1:00 am
Location: OH, USA

Re: I'm not very happy with the do {} while() statement in C

Post by Michael Sherwin » Sun Feb 18, 2018 1:56 pm

Thanks everyone for your help. This is what I have so far and it seems to be correct now that I corrected the knight offsets. However, I'm up 8 hours past my bedtime so I'll check it more thoroughly later.

Code: Select all

#define FALSE  0
#define TRUE   1

#define QUIT   0
#define THINK  1
#define GETCMD 2

#define s32 signed   __int32
#define u64 unsigned __int64

#define SQUARE64&#40;x&#41; ((((&#40;x&#41; / 10&#41; - 2&#41; << 3&#41; + (&#40;x&#41; - (&#40;x&#41; / 10 * 10&#41; - 1&#41;)
#define SQUARE120&#40;x&#41; ((((&#40;x&#41; >> 3&#41; + 2&#41; * 10&#41; + ((&#40;x&#41; & 7&#41; + 1&#41;)

void Think&#40;void&#41;;
void Initialize&#40;void&#41;;
void GetCmd&#40;void&#41;;
s32 main&#40;void&#41;;

u64 dir7p&#91;64&#93;;
u64 dir9p&#91;64&#93;;
u64 dir7m&#91;64&#93;;
u64 dir9m&#91;64&#93;;
u64 dir1p&#91;64&#93;;
u64 dir8p&#91;64&#93;;
u64 dir1m&#91;64&#93;;
u64 dir8m&#91;64&#93;;
u64 dirKn&#91;64&#93;;
u64 dirKi&#91;64&#93;;

s32 mode = GETCMD;

u64 *dirPtr&#91;8&#93; = &#123; dir7p, dir9p, dir7m, dir9m, dir1p, dir8p, dir1m, dir8m &#125;;

void Think&#40;) &#123;

&#125;

void GetCmd&#40;) &#123;
  mode = QUIT;
&#125;

void Initialize&#40;) &#123;
  s32 i, fs120, ts120, fs64, ts64;
  s32 dir&#91;8&#93; = &#123; 9, 11, -9, -11, 1, 10, -1, -10 &#125;;
  s32 din&#91;8&#93; = &#123; 8, 12, 19, 21, -8, -12, -19, -21 &#125;;
  s32 initBoard&#91;120&#93; = &#123;
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 1, 1, 1, 1, 1, 1, 1, 1, 0,
    0, 1, 1, 1, 1, 1, 1, 1, 1, 0,
    0, 1, 1, 1, 1, 1, 1, 1, 1, 0,
    0, 1, 1, 1, 1, 1, 1, 1, 1, 0,
    0, 1, 1, 1, 1, 1, 1, 1, 1, 0,
    0, 1, 1, 1, 1, 1, 1, 1, 1, 0,
    0, 1, 1, 1, 1, 1, 1, 1, 1, 0,
    0, 1, 1, 1, 1, 1, 1, 1, 1, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0 &#125;;

  for &#40;fs64 = 63; fs64 >= 0; fs64--) &#123;
    fs120 = SQUARE120&#40;fs64&#41;;
    dirKi&#91;fs64&#93; = 0;
    dirKn&#91;fs64&#93; = 0;
    for &#40;i = 7; i >= 0; i--) &#123;
      ts120 = fs120 + din&#91;i&#93;;
      if &#40;initBoard&#91;ts120&#93;) &#123;
        dirKn&#91;fs64&#93; |= &#40;u64&#41;1 << SQUARE64&#40;ts120&#41;;
      &#125;
      dirPtr&#91;i&#93;&#91;fs64&#93; = 0;
      ts120 = fs120 + dir&#91;i&#93;;
      if &#40;initBoard&#91;ts120&#93;)  &#123;
        ts64 = SQUARE64&#40;ts120&#41;;
        dirKi&#91;fs64&#93; |= &#40;u64&#41;1 << ts64;
        while&#40;1&#41; &#123;
          dirPtr&#91;i&#93;&#91;fs64&#93; |= &#40;u64&#41;1 << ts64;
          ts120 += dir&#91;i&#93;;
          if (!initBoard&#91;ts120&#93;) break;
          ts64 = SQUARE64&#40;ts120&#41;;
        &#125; 
      &#125;
    &#125;
  &#125;
&#125;

s32 main&#40;)
&#123;
  Initialize&#40;);

  while &#40;mode&#41; &#123;
    if &#40;mode == THINK&#41; Think&#40;);
    GetCmd&#40;);
  &#125;
  return 0;
&#125;
Regards,
Mike

syzygy
Posts: 4318
Joined: Tue Feb 28, 2012 10:56 pm

Re: I'm not very happy with the do {} while() statement in C

Post by syzygy » Sun Feb 18, 2018 2:34 pm

Michael Sherwin wrote:

Code: Select all

#define FALSE  0
#define TRUE   1

#define QUIT   0
#define THINK  1
#define GETCMD 2

#define s32 signed   __int32
#define u64 unsigned __int64
Just to be picky, I would replace the last two #defines with typedefs:

Code: Select all

typedef signed __int32 s32;
typedef unsigned __int64 u64;
Optionally, you could also do this:

Code: Select all

enum &#123; FALSE, TRUE &#125;;

enum &#123; QUIT, THINK, GETCMD &#125;;

mar
Posts: 1866
Joined: Fri Nov 26, 2010 1:00 pm
Full name: Martin Sedlak

Re: I'm not very happy with the do {} while() statement in C

Post by mar » Sun Feb 18, 2018 5:39 pm

Michael Sherwin wrote:In the do while loop I have to execute instructions that at some point will not need to be executed. It is not really a problem in this simple initiation example. But still it seems like a poor design. It would be perfect if the do while worked like this.

Code: Select all

         k = i + dir&#91;j&#93;;
        if &#40;initBoard&#91;k&#93;)  &#123;
          y = k / 10; x = k - y * 10 - 1; y -= 2;
          ts = y * 8 + x;
          dirKi&#91;sq&#93; |= &#40;u64&#41;1 << ts;
          do &#123;
            dirPtr&#91;j&#93;&#91;sq&#93; |= (&#40;u64&#41;1 << ts&#41;;
            k += dir&#91;j&#93;;
          &#125; while &#40;initBoard&#91;k&#93;) &#123;
            y = k / 10; x = k - y * 10 - 1; y -= 2;
            ts = y * 8 + x;
          &#125;
        &#125;
 
If it would execute the code in the braces before looping back to the do statement. Maybe there is away around this minor dilemma. I just do not know what it is?
What "poor design" are you talking about? If you want early exit, just use break inside infinite loop. What you propose is beyond ugly.

Code: Select all

         for&#40;;;)
         &#123; 
            dirPtr&#91;j&#93;&#91;sq&#93; |= (&#40;u64&#41;1 << ts&#41;; 
            k += dir&#91;j&#93;; 

            if (!initBoard&#91;k&#93;)
              break;

            y = k / 10; x = k - y * 10 - 1; y -= 2; 
            ts = y * 8 + x; 
          &#125; 

Michael Sherwin
Posts: 2822
Joined: Fri May 26, 2006 1:00 am
Location: OH, USA

Re: I'm not very happy with the do {} while() statement in C

Post by Michael Sherwin » Sun Feb 18, 2018 5:59 pm

mar wrote:
Michael Sherwin wrote:In the do while loop I have to execute instructions that at some point will not need to be executed. It is not really a problem in this simple initiation example. But still it seems like a poor design. It would be perfect if the do while worked like this.

Code: Select all

         k = i + dir&#91;j&#93;;
        if &#40;initBoard&#91;k&#93;)  &#123;
          y = k / 10; x = k - y * 10 - 1; y -= 2;
          ts = y * 8 + x;
          dirKi&#91;sq&#93; |= &#40;u64&#41;1 << ts;
          do &#123;
            dirPtr&#91;j&#93;&#91;sq&#93; |= (&#40;u64&#41;1 << ts&#41;;
            k += dir&#91;j&#93;;
          &#125; while &#40;initBoard&#91;k&#93;) &#123;
            y = k / 10; x = k - y * 10 - 1; y -= 2;
            ts = y * 8 + x;
          &#125;
        &#125;
 
If it would execute the code in the braces before looping back to the do statement. Maybe there is away around this minor dilemma. I just do not know what it is?
What "poor design" are you talking about? If you want early exit, just use break inside infinite loop. What you propose is beyond ugly.

Code: Select all

         for&#40;;;)
         &#123; 
            dirPtr&#91;j&#93;&#91;sq&#93; |= (&#40;u64&#41;1 << ts&#41;; 
            k += dir&#91;j&#93;; 

            if (!initBoard&#91;k&#93;)
              break;

            y = k / 10; x = k - y * 10 - 1; y -= 2; 
            ts = y * 8 + x; 
          &#125; 
Beauty is in the eye of the beholder. Break while an efficient solution is nothing more than a goto. And any goto is considered poor design by some. It is considered unfortunate by some that we must resort to using goto in some situations. The ugliness that you are referring to I think is that it looks like a regular while loop. I thought of that so I am now thinking do {} while () first {}

But it is just an idea.
Regards,
Mike

mar
Posts: 1866
Joined: Fri Nov 26, 2010 1:00 pm
Full name: Martin Sedlak

Re: I'm not very happy with the do {} while() statement in C

Post by mar » Sun Feb 18, 2018 6:40 pm

Michael Sherwin wrote:Beauty is in the eye of the beholder. Break while an efficient solution is nothing more than a goto. And any goto is considered poor design by some. It is considered unfortunate by some that we must resort to using goto in some situations. The ugliness that you are referring to I think is that it looks like a regular while loop. I thought of that so I am now thinking do {} while () first {}

But it is just an idea.
Well if you consider goto be a simple jump instruction, then even end of loop would be a goto as well.
Also, break/continue may not be a simple jump instruction (the same applies to goto) as you may need to clean up stack (RAII-based languages):

Code: Select all

while&#40;...)
&#123;
  string x;
  break;
  string z;
&#125;
Here the end of loop cleans up z and x, while break cleans up x and chains to the start of the loop.

I'd trade deep nesting (which I consider bad) for early break/continue anytime. I certainly don't consider break/continue harmful - this must be simply another myth.
They are not as tricky as goto and in the case of a switch statement, you can't really escape without break, only some switches can be converted to table lookups
and if sequences are only good for small number of cases.

Goto is actually tricky to implement and it may not even be possible in all cases:

Code: Select all

goto L1;
string s = "abc";
L1&#58;;
print&#40;s&#41;;
Here goto would skip over initialization of s, which should be considered illegal (similar problem with backward goto).

Also labels (jump targets) produce new optimization frontiers as they break control flow (to be fair, break/continue may as well).

Sorry but I have the feeling you're trying to solve a non-issue.

If you feel jumps are bad, you can try movfuscator https://github.com/xoreaxeaxeax/movfuscator which is able to compile C programs
into a sequence of mov instructions (spectre/meltdown proof :), branchless (and also not very fast).

Ras
Posts: 1015
Joined: Tue Aug 30, 2016 6:19 pm
Contact:

Re: I'm not very happy with the do {} while() statement in C

Post by Ras » Sun Feb 18, 2018 7:04 pm

Goto is a perfectly fine tool - and like any tool, it can be misused. The goto aversion stems from a Dijkstra article in the 1960s, but that referred to the goto in Basic. That was another beast because it was using fixed line numbers as jump targets, which quickly could become a maintenance nightmare once you inserted additional instructions somewhere.

Goto usually should not be used in regular control flow, and it should only be forward goto. For error handling in C, goto is much nicer than nested ifs. As soon as you have more than one thing to clean up, nested ifs also entail code duplication. That's why goto is used in the Linux kernel.

The mathematical idea is to first rule out any error cases so that the rest of the algorithm is reduced to the error free case. That way, the algorithm is not cluttered by the error handling.

Oh, and for break, that is also neat. I've seen code in Pascal dialects without break, and it works usually by maintaining some helper flag variable that gets checked in the loop condition. Not only that this is cluttered, it is also inefficient.

Michael Sherwin
Posts: 2822
Joined: Fri May 26, 2006 1:00 am
Location: OH, USA

Re: I'm not very happy with the do {} while() statement in C

Post by Michael Sherwin » Sun Feb 18, 2018 7:16 pm

I do not have a single thing against break/continue or the use of goto's forward or backwards as I use all in RomiChess without any problems. My point is that beauty is in the eye of the beholder. I find my suggestion to be eloquent and you think it is ugly. End of story!
Regards,
Mike

syzygy
Posts: 4318
Joined: Tue Feb 28, 2012 10:56 pm

Re: I'm not very happy with the do {} while() statement in C

Post by syzygy » Sun Feb 18, 2018 8:39 pm

mar wrote:I certainly don't consider break/continue harmful - this must be simply another myth.
But not an existing myth. (Unless there is a myth condemning the use of all high-level loop constructs, which ultimately all compile to branch instructions... ignoring the movfuscator for a moment.)

syzygy
Posts: 4318
Joined: Tue Feb 28, 2012 10:56 pm

Re: I'm not very happy with the do {} while() statement in C

Post by syzygy » Sun Feb 18, 2018 9:12 pm

Ras wrote:Goto is a perfectly fine tool - and like any tool, it can be misused. The goto aversion stems from a Dijkstra article in the 1960s, but that referred to the goto in Basic. That was another beast because it was using fixed line numbers as jump targets, which quickly could become a maintenance nightmare once you inserted additional instructions somewhere.
I fully agree that Dijkstra's article has to be understood against the background of the coding practices of that time (1968). But he was probably not thinking very much about BASIC (which is from 1964 and was probably hardly used for serious programming).
Goto usually should not be used in regular control flow, and it should only be forward goto. For error handling in C, goto is much nicer than nested ifs. As soon as you have more than one thing to clean up, nested ifs also entail code duplication. That's why goto is used in the Linux kernel.
http://koblents.com/Ches/Links/Month-Ma ... rnel-Code/

(The guy who started that thread also suggested that the Linux code was of questionable quality given the many patches coming in.)

mar
Posts: 1866
Joined: Fri Nov 26, 2010 1:00 pm
Full name: Martin Sedlak

Re: I'm not very happy with the do {} while() statement in C

Post by mar » Sun Feb 18, 2018 9:33 pm

mar wrote:Here the end of loop cleans up z and x, while break cleans up x and chains to the start of the loop.
Correction: end of the loop (actually out of the loop).

I agree with Ras that goto can be useful now and then. I'd personally prefer to be able to break say n loop scopes with "break n" or "continue n", but this won't happen and I'm ok to code around it.

@Ronald: fully agreed, but this is not the first time I've read that break or continue are "as bad as goto", this is why I called it a myth.

Post Reply