Change order of two For loops

Just starting out? Need help? Post your questions and find answers here.
User avatar
Keya
Addict
Addict
Posts: 1891
Joined: Thu Jun 04, 2015 7:10 am

Change order of two For loops

Post by Keya »

does anyone know of a good way to change the order of two loops?

For example, a horizontal pass followed by a vertical pass of pixels in an image, both encompassing the same code - only the loop order is different:

Code: Select all

;Horizontal pass
For y = 1 to height
  For x = 1 to width
   ;process pixel (x,y)
  Next x
Next y

;Vertical pass
For x = 1 to width
  For y = 1 to height
   ;process pixel (x,y)
  Next y
Next x
So I would like to be able to combine the two into a single procedure.

While I was typing that example i realized perhaps simply "Swap(xcopy, ycopy)" might be one simple solution but im still curious about other options, and i'm thinking that might not actually work unless both width and height are the same size.

Of course another option is to have the two copies of the loop, just like in the previous example, and call a single ProcessPixel procedure, but then you don't easily have access to all the internal variables of that procedure without sending them all over as parameters, not always ideal!

i had came up with the following also but it's uh... yeah, lol

Code: Select all

swapped=0
xmax = 2 ;x = 0 to 2
ymax = 3 ;y = 0 to 3
Repeat  
  Debug "x="+Str(x) + "  y="+Str(y)  
  If swapped
    x + 1
    If x > xmax
      x = 0: y + 1
      If y > ymax: Break: EndIf
    EndIf    
  Else
    y + 1
    If y > ymax
      y = 0: x + 1
      If x > xmax: Break: EndIf
    EndIf
  EndIf  
ForEver
User avatar
Josh
Addict
Addict
Posts: 1183
Joined: Sat Feb 13, 2010 3:45 pm

Re: Change order of two For loops

Post by Josh »

Maybe like that:

Code: Select all

For y = 1 to height
  For x = 1 to width
    If HorizontalPass
      ProcessPixel (x,y)
    Else
      ProzessPixel (y,x)
    EndIf
  Next x
Next y
Don't know, what you really want to do
sorry for my bad english
User avatar
Keya
Addict
Addict
Posts: 1891
Joined: Thu Jun 04, 2015 7:10 am

Re: Change order of two For loops

Post by Keya »

im hoping to avoid calling another procedure so i can retain easy access to all the in-proc variables. A problem with your code is that it will only work if both width and height are the same size, otherwise youll send up sending a value out of array bounds
User avatar
Josh
Addict
Addict
Posts: 1183
Joined: Sat Feb 13, 2010 3:45 pm

Re: Change order of two For loops

Post by Josh »

Keya wrote:im hoping to avoid calling another procedure
Using your first code with the nasty GoTo in the loops?
sorry for my bad english
User avatar
Demivec
Addict
Addict
Posts: 4091
Joined: Mon Jul 25, 2005 3:51 pm
Location: Utah, USA

Re: Change order of two For loops

Post by Demivec »

What about something like this:

Code: Select all

Procedure doit(width, height, isVertical = #False)
  Protected *x.Integer, *y.Integer, lc_outer, lc_outer_max, lc_inner, lc_inner_max
  
  If isVertical
    ;Vertical pass
    lc_outer_max = width 
    lc_inner_max = height
    *y = @lc_inner
    *x = @lc_outer
  Else
    ;Horizontal pass
    lc_outer_max = height
    lc_inner_max = width
    *y = @lc_outer
    *x = @lc_inner
  EndIf
  
  For lc_outer = 1 To lc_outer_max
    For lc_inner = 1 To lc_inner_max
      ;process pixel(*x\i, *y\i)
      Debug "x: " + *x\i + ", y: " + *y\i
    Next lc_inner
  Next lc_outer
  
EndProcedure

Debug "----horizontal-----"
doit(3, 6, #False)
Debug "----vertical-------"
doit(3, 6, #True)
The setup for horizontal or vertical is inconsequential as most of the time will be spent in the loops themselves.

@Edit: made a small code correction
@Edit2: made another small code correction, code should actually work now :)
@Edit3: Reorganized code as a procedure and included some demo code.
Last edited by Demivec on Mon Mar 27, 2017 7:59 am, edited 3 times in total.
User avatar
Keya
Addict
Addict
Posts: 1891
Joined: Thu Jun 04, 2015 7:10 am

Re: Change order of two For loops

Post by Keya »

Josh wrote:
Keya wrote:im hoping to avoid calling another procedure
Using your first code with the nasty GoTo in the loops?
? I didn't use GoTo
User avatar
Fig
Enthusiast
Enthusiast
Posts: 351
Joined: Thu Apr 30, 2009 5:23 pm
Location: Côtes d'Azur, France

Re: Change order of two For loops

Post by Fig »

An other solution may be to keep 2 images instead of 1.
The first one is normal, the second would be rotated 90°.
There are 2 methods to program bugless.
But only the third works fine.

Win10, Pb x64 5.71 LTS
User avatar
Lunasole
Addict
Addict
Posts: 1091
Joined: Mon Oct 26, 2015 2:55 am
Location: UA
Contact:

Re: Change order of two For loops

Post by Lunasole »

Swap looks the simplest for such cases, in your example you probably can "Swap width, height" before first loop, + do the same with swap xMax/yMax or what else needed.

Or macro can be used also, it doesn't have procedure overhead etc, just bloats program size ^_^ I'm ofted adding macro right inside procedure with UndefineMacro following at procedure end, that's not a NASA coding standards but really nice and cleaner in some cases
Last edited by Lunasole on Sun Mar 26, 2017 3:19 pm, edited 1 time in total.
"W̷i̷s̷h̷i̷n̷g o̷n a s̷t̷a̷r"
User avatar
Keya
Addict
Addict
Posts: 1891
Joined: Thu Jun 04, 2015 7:10 am

Re: Change order of two For loops

Post by Keya »

ahh yes a double swap could be a winner, would solve the different-dimensions problem
User avatar
Fig
Enthusiast
Enthusiast
Posts: 351
Joined: Thu Apr 30, 2009 5:23 pm
Location: Côtes d'Azur, France

Re: Change order of two For loops

Post by Fig »

But it means 2 swaps before the nested loops (for sizes) and 2 conditionnal swaps inside the loops (one before the procedure and one after).
That seams not really efficient if you are looking for speed. (Demivec or even Josh's propositions look faster in compare)
There are 2 methods to program bugless.
But only the third works fine.

Win10, Pb x64 5.71 LTS
#NULL
Addict
Addict
Posts: 1440
Joined: Thu Aug 30, 2007 11:54 pm
Location: right here

Re: Change order of two For loops

Post by #NULL »

Demivec's solution is pretty nice.
here is another idea:

Code: Select all

EnableExplicit

Procedure doit(width, height, vertical = #False)
  Protected i, max, x, y
  i = 0
  max = (width * height) - 1
  For i=0 To max
    If vertical
      x = i / height
      y = i % height
    Else
      x = i % width
      y = i / width
    EndIf
    Debug "x: " + x + ", y: " + y
  Next
EndProcedure

Debug "----horizontal-----"
doit(3, 6, #False)
Debug "----vertical-------"
doit(3, 6, #True)
Post Reply