POV-Ray : Newsgroups : povray.advanced-users : Negative subscript in while loop Server Time
20 Apr 2024 03:33:44 EDT (-0400)
  Negative subscript in while loop (Message 1 to 4 of 4)  
From: Bald Eagle
Subject: Negative subscript in while loop
Date: 15 Jan 2023 18:15:00
Message: <web.63c487f2edb901151f9dae3025979125@news.povray.org>
So, I'm trying to convert some online code to SDL,

( https://github.com/xmdi/CAD-from-Scratch/blob/main/016/geom.c  )

and the conditions in the while statement
     #while( j >= 0 & bins[j] > key)
don't protect against j being negative.

"C:\Users\Mini\Documents\POV-Ray\v3.8-beta\scenes\DelaunayTriangulateTest1.pov"
line 226: Parse Error: Negative subscript

Render failed

Probably because they're collected in one line / statement and are therefore all
evaluated together, and the while loop doesn't terminate until that expression
is fully evaluated.

I managed to hacktastically bypass / protect against this with some additional
protective wrappers to the loop, but this doesn't seem like it ought to be
necessary, or else there ought to be a more elegant way to correct this in SDL.

Unless the while source code has a bug that I've triggered, and _I've broken
POV-Ray AGAIN_.   :\

 // sort points by proximity
 #local NbinRows = ceil(pow(numpoints, 0.25));
 #local bins = array [numpoints+1];

 #for (i, 0, numpoints)
  #local  p = (points[i][1] * NbinRows*0.999); // bin row
  #local  q = (points[i][0] * NbinRows*0.999); // bin column
  #if (mod(p, 2))
   #local bins[i] = (p+1) * NbinRows - q;
  #else
   #local bins[i] = p * NbinRows + q + 1;
  #end
 #end

 #for (i, 1, numpoints) // insertion sort
  #local key = bins[i];
  #local tempF = array {points[i][0], points[i][1]};
  #local  j = i - 1;
  #debug "------------------------------------------------\n"
  #debug concat ("      i = ", str (i, 0, 0), "\n")
  #debug concat ("bins[i] = ", str (bins[i], 0, 0), "\n")
  #debug concat ("bins[j] = ", str (bins[j], 0, 0), "\n")
  #if (j > 0)
  #while( j >= 0 & bins[j] > key)
   #local bins[j+1] = bins[j];
   #local points[j+1][0] = points[j][0];
   #local points[j+1][1] = points[j][1];
   #local j = j-1;

   #debug concat ("j = ", str (j, 0, 0), "\n")
   #debug concat ("bins[i] = ", str (bins[i], 0, 0), "\n")
   #if (j<0) #break #end
  #end // end while
  #end

  #local bins[j+1] = key;
  #local points[j+1][0] = tempF[0];
  #local points[j+1][1] = tempF[1];
 #end



Also, if anyone can tell me if this is C, C++, or C#, and how to properly
interpret and convert statements such as:

int* bins=malloc(numPoints*sizeof(int));
points=realloc(points,(3+numPoints)*2*sizeof(float));
int (*verts)[3]=malloc(3*sizeof(int));
int (*tris)[3]=malloc(3*sizeof(int));
int *triangleStack=malloc((numPoints-3)*sizeof(int));
tris=realloc(tris,(nT)*3*sizeof(int));
verts=realloc(verts,(nT)*3*sizeof(int));
int *renumberAdj=calloc(nT,sizeof(int));
bool *deadTris=calloc(nT,sizeof(bool));
int (*verts_final)[3]=malloc(3*nT_final*sizeof(int));
int (*tris_final)[3]=malloc(3*nT_final*sizeof(int));

that would be great.  I kinda get it, but a clear explanation from someone who
know the native language PLUS SDL, would help doing any such future conversions.

Maybe I could even write a small macro to make declaring such arrays a bit more
foolproof.


Post a reply to this message

From: Tor Olav Kristensen
Subject: Re: Negative subscript in while loop
Date: 15 Jan 2023 21:15:00
Message: <web.63c4b23631017364383c879289db30a9@news.povray.org>
"Bald Eagle" <cre### [at] netscapenet> wrote:
> So, I'm trying to convert some online code to SDL,
>
> ( https://github.com/xmdi/CAD-from-Scratch/blob/main/016/geom.c  )
>
> and the conditions in the while statement
>      #while( j >= 0 & bins[j] > key)
> don't protect against j being negative.
>
> "C:\Users\Mini\Documents\POV-Ray\v3.8-beta\scenes\DelaunayTriangulateTest1.pov"
> line 226: Parse Error: Negative subscript
>
> Render failed
>
> Probably because they're collected in one line / statement and are therefore all
> evaluated together, and the while loop doesn't terminate until that expression
> is fully evaluated.

You may want to have a look at these questions, answers and comments::

What is "short-circuiting" in C like languages?
https://softwareengineering.stackexchange.com/questions/201896/what-is-short-circuiting-in-c-like-languages

What is short-circuit evaluation in C?
https://stackoverflow.com/questions/45848858/what-is-short-circuit-evaluation-in-c

Is short-circuiting logical operators mandated? And evaluation order?
https://stackoverflow.com/questions/628526/is-short-circuiting-logical-operators-mandated-and-evaluation-order


My opinion is that writing code that depends on short circuiting is
bad practice (i.e. hard to understand and debug - and not so portable,
as you have now experienced).


> I managed to hacktastically bypass / protect against this with some additional
> protective wrappers to the loop, but this doesn't seem like it ought to be
> necessary, or else there ought to be a more elegant way to correct this in SDL.
>
> Unless the while source code has a bug that I've triggered, and _I've broken
> POV-Ray AGAIN_.   :\
>
>  // sort points by proximity
>  #local NbinRows = ceil(pow(numpoints, 0.25));
>  #local bins = array [numpoints+1];
>
>  #for (i, 0, numpoints)
>   #local  p = (points[i][1] * NbinRows*0.999); // bin row
>   #local  q = (points[i][0] * NbinRows*0.999); // bin column
>   #if (mod(p, 2))
>    #local bins[i] = (p+1) * NbinRows - q;
>   #else
>    #local bins[i] = p * NbinRows + q + 1;
>   #end
>  #end
>
>  #for (i, 1, numpoints) // insertion sort
>   #local key = bins[i];
>   #local tempF = array {points[i][0], points[i][1]};
>   #local  j = i - 1;
>   #debug "------------------------------------------------\n"
>   #debug concat ("      i = ", str (i, 0, 0), "\n")
>   #debug concat ("bins[i] = ", str (bins[i], 0, 0), "\n")
>   #debug concat ("bins[j] = ", str (bins[j], 0, 0), "\n")
>   #if (j > 0)
>   #while( j >= 0 & bins[j] > key)
>    #local bins[j+1] = bins[j];
>    #local points[j+1][0] = points[j][0];
>    #local points[j+1][1] = points[j][1];
>    #local j = j-1;
>
>    #debug concat ("j = ", str (j, 0, 0), "\n")
>    #debug concat ("bins[i] = ", str (bins[i], 0, 0), "\n")
>    #if (j<0) #break #end
>   #end // end while
>   #end
>
>   #local bins[j+1] = key;
>   #local points[j+1][0] = tempF[0];
>   #local points[j+1][1] = tempF[1];
>  #end
>...

You can try something like this:
(NB: Untested code)

// Sort points by proximity

#local NoOfBinRows = ceil(pow(NoOfPoints, 0.25));
#local Bins = array[NoOfPoints+1];

#for (I, 0, NoOfPoints)
    #local P = Points[I][1]*NoOfBinRows*0.999; // bin row
    #local Q = Points[I][0]*NoOfBinRows*0.999; // bin column
    #local Bins[I] = P*NoOfBinRows + (mod(P, 2) = 0 ? Q + 1 : NoOfBinRows - Q);
#end // for

// Insertion sort
#for (I, 1, NoOfPoints)
    #local Key = Bins[I];
    #local TempF_0 = Points[I][0];
    #local TempF_1 = Points[I][1];
    #local J = I - 1;
    #local Continue = (Bins[J] > Key);
    #while (Continue)
        #local Bins[J+1] = Bins[J];
        #local Points[J+1][0] = Points[J][0];
        #local Points[J+1][1] = Points[J][1];
        #local J = J - 1;
        #local Continue = (J >= 0);
        #if (Continue)
            #local Continue = (Bins[J] > Key);
        #end // if
    #end // while
    #local Bins[J+1] = Key;
    #local Points[J+1][0] = TempF_0;
    #local Points[J+1][1] = TempF_1;
#end // for


Btw.: I'm suspicious of the *0.999 calculations.

--
Tor Olav
http://subcube.com
https://github.com/t-o-k


Post a reply to this message

From: Tor Olav Kristensen
Subject: Re: Negative subscript in while loop
Date: 15 Jan 2023 21:35:00
Message: <web.63c4b7a931017364383c879289db30a9@news.povray.org>
"Tor Olav Kristensen" <tor### [at] TOBEREMOVEDgmailcom> wrote:
>...

> // Insertion sort
> #for (I, 1, NoOfPoints)
>     #local Key = Bins[I];
>     #local TempF_0 = Points[I][0];
>     #local TempF_1 = Points[I][1];
>     #local J = I - 1;
>     #local Continue = (Bins[J] > Key);
>     #while (Continue)
>         #local Bins[J+1] = Bins[J];
>         #local Points[J+1][0] = Points[J][0];
>         #local Points[J+1][1] = Points[J][1];
>         #local J = J - 1;
>         #local Continue = (J >= 0);
>         #if (Continue)
>             #local Continue = (Bins[J] > Key);
>         #end // if
>     #end // while
>     #local Bins[J+1] = Key;
>     #local Points[J+1][0] = TempF_0;
>     #local Points[J+1][1] = TempF_1;
> #end // for
>...

If the assignments after the while loop goes wrong, then you can try
to change lines at the end of the while loop like this:

        #local Continue = (J >= 1);
        #if (Continue)
            #local J = J - 1;
            #local Continue = (Bins[J] > Key);
        #end // if

--
Tor Olav
http://subcube.com
https://github.com/t-o-k


Post a reply to this message

From: Lars Rohwedder
Subject: rt_circuiting_is_veeeery_common_in_C=2e?
Date: 17 Jan 2023 01:40:27
Message: <63c642db@news.povray.org>
> You may want to have a look at these questions, answers and comments::
> 
> What is "short-circuiting" in C like languages?
>
https://softwareengineering.stackexchange.com/questions/201896/what-is-short-circuiting-in-c-like-languages
> 
> What is short-circuit evaluation in C?
> https://stackoverflow.com/questions/45848858/what-is-short-circuit-evaluation-in-c
> 
> Is short-circuiting logical operators mandated? And evaluation order?
>
https://stackoverflow.com/questions/628526/is-short-circuiting-logical-operators-mandated-and-evaluation-order
> 
> 
> My opinion is that writing code that depends on short circuiting is
> bad practice (i.e. hard to understand and debug - and not so portable,
> as you have now experienced).

But in C those expressions are a quite common idiome, like

#define IsNullOrEmpty(s)  ((s)==NULL || (s)[0]=='\0')

or – even more common - in expressions like this:

if( s && s->value )
{
    …
}

and a lot of C code rely on the short circui rule in these expressions.

And – IMHO – these expressions are not hard to debug, because 's' can be 
evaluated easily e.g. in a debugger.

But of course, PovRay scene files are not C. :-)

Lars R.


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.