# PureBasic Forum

 It is currently Thu May 23, 2013 10:45 am

 All times are UTC + 1 hour

 Page 1 of 3 [ 34 posts ] Go to page 1, 2, 3  Next
 Print view Previous topic | Next topic
Author Message
 Post subject: For Next StepPosted: Wed Feb 15, 2012 5:15 am

Joined: Fri Oct 23, 2009 2:33 am
Posts: 2862
Location: Wales, UK
The Step of a For Next loop is limited to an integer constant. There are occasions where an integer is required instead of a constant.

Edit: Yes, I am using another loop type instead but For Next is more elegant.

_________________
IdeasVacuum
If it sounds simple, you have not grasped the complexity.

Top

 Post subject: Re: For Next StepPosted: Wed Feb 15, 2012 10:40 pm
 Enthusiast

Joined: Thu Jan 10, 2008 1:30 pm
Posts: 711
Location: Germany, Glienicke

_________________

Top

 Post subject: Re: For Next StepPosted: Wed Feb 15, 2012 10:42 pm

Joined: Wed Aug 31, 2005 11:09 pm
Posts: 2240
Location: Italy
STARGÅTE wrote:
SPAM

But SPAM ?

_________________
[ Home ] [ My PC ] [ New to PB ? ]

Top

 Post subject: Re: For Next StepPosted: Sat Feb 18, 2012 8:13 am
 Enthusiast

Joined: Tue Sep 23, 2008 11:38 pm
Posts: 702
Location: Belgium (& Luxembourg)
Why not create a ForD, like we have StrD and ValD, for example?
This preserves the original For - Next statement, to maintain high speed.

I second the idea to create a For/Next statement that uses decimals (as well the Step), as it makes programming sometimes much easier.

_________________
- Future conversation forecasting not yet implemented.
- If the future had copied a program from now, they would have called it version -1.

Top

 Post subject: Re: For Next StepPosted: Sun Feb 19, 2012 1:29 am
 Enthusiast

Joined: Sat Aug 27, 2011 9:50 pm
Posts: 107
Location: Washington, USA
My reading of the original post is not for floating point steps, but variable steps.

for i = x to y step z where z is an actual expression, not a constant.

I can see how this could be useful in some circumstances.

Top

 Post subject: Re: For Next StepPosted: Sun Feb 19, 2012 4:11 pm
 Enthusiast

Joined: Tue Nov 09, 2010 10:15 pm
Posts: 794
Yes, very useful in many situations. While I haven't used it yet in PB, I'm surprised to see PB doesn't allow it.

Here are a couple macros that will work with any var type and any Step. They are the same as what For Next does, but without restriction. The only drawback is that since you can't put a block of code in a macro call, you have to reference the Var and Step in the ForEnd, not the ForStart.

Code:
Macro ForStart(Var, starting, ending)
Var = starting
While Var <= ending
EndMacro

Macro ForEnd(Var, increment)
Var = Var + increment
Wend
EndMacro

Macro ForStartDec(Var, starting, ending)
Var = starting
While Var >= ending
EndMacro

Macro ForEndDec(Var, increment)
Var = Var - increment
Wend
EndMacro

; Incrementing sample with Float:
x.f

ForStart(x, 1, 3.5)
Debug x
ForEnd(x, 0.5)

Debug "last x " + Str(x)

; Decrementing sample with variable Step:
i.f
a.i = 2

ForStartDec(i, 12, 2)
Debug i
ForEndDec(i, a)

Debug "last i " + Str(i)

Top

 Post subject: Re: For Next StepPosted: Tue Feb 21, 2012 12:38 am
 Enthusiast

Joined: Tue Sep 23, 2008 11:38 pm
Posts: 702
Location: Belgium (& Luxembourg)
@Tenaja,
I was very interested in your Macros in attempting to create a For-Next-Step with the same sequence and logic.
I have studied the drawback you mentioned.
Well, I have rewritten the Macros based on your idea.
I have tested it superficially, and it seems to work... Any bug or comment is welcome!
Code:
;==================================================================
Macro Loop(Var,Starting,Ending,Increment=1)
*Start#Var=AllocateMemory(9)
PokeD(*Start#Var,Starting)
*End#Var=AllocateMemory(9)
PokeD(*End#Var,Ending)
*Incr#Var=AllocateMemory(9)
PokeD(*Incr#Var,Increment)
Var=Starting
Repeat
EndMacro
;==================================================================
Macro EndLoop(Var)
Starting#Var.d=PeekD(*Start#Var)
Ending#Var.d=PeekD(*End#Var)
Increment#Var.d=PeekD(*Incr#Var)
Var+Increment#Var
Qend.d=Starting#Var+((Ending#Var-Starting#Var)/Increment#Var)*Increment#Var; calculate the number of steps to know the real destination value
a.d=Var : b.d=Qend
If Increment#Var<0; negative increment
a.d=Qend : b.d=Var; swap current var & real ending
EndIf
Until a>b; if increment was negative, we had to swap the variables, because we cannot swap the direction of Until
FreeMemory(*Incr#Var)
FreeMemory(*Start#Var)
FreeMemory(*End#Var)
EndMacro
;==================================================================
; Example
Loop(i.d,1,5.5,1.5)
Loop(j.d,16,4,-3.5)
Debug "("+StrD(i,2)+", "+StrD(j,2)+")"
EndLoop(j)
EndLoop(i)

Debug "last i = " + StrD(i)
Debug "last j = " + StrD(j)
;==================================================================

_________________
- Future conversation forecasting not yet implemented.
- If the future had copied a program from now, they would have called it version -1.

Top

 Post subject: Re: For Next StepPosted: Tue Feb 21, 2012 5:16 am
 Enthusiast

Joined: Tue Nov 09, 2010 10:15 pm
Posts: 794
Charvista, in general, I like your use of alloc to make them nestable. On the other hand, have you looked at the asm? It's LOOOOOOONG! So maybe not great for time sensitive code. This is your sample, with no edits:
Code:
;
; PureBasic 4.60 (Windows - x86) generated code
;
; (c) 2011 Fantaisie Software
;
; The header must remain intact for Re-Assembly
;
; Memory
; :System
; KERNEL32
; :Import
;
format MS COFF
;
;
extrn _PB_AllocateMemory@4
extrn _PB_FreeMemory@4
extrn _PB_FreeMemorys@0
extrn _PB_InitMemory@0
extrn _PB_PeekD@4
extrn _PB_PokeD@12
extrn _ExitProcess@4
extrn _GetModuleHandleA@4
extrn _HeapCreate@12
extrn _HeapDestroy@4
extrn _memset
public _PB_Instance
public _PB_ExecutableType
public _PB_OpenGLSubsystem
public _PB_MemoryBase
public PB_Instance
public PB_MemoryBase
public _PB_EndFunctions

macro pb_public symbol
{
public  _#symbol
public symbol
_#symbol:
symbol:
}

macro    pb_align value { rb (value-1) - (\$-_PB_DataSection + value-1) mod value }
macro pb_bssalign value { rb (value-1) - (\$-_PB_BSSSection  + value-1) mod value }
public PureBasicStart
;
section '.code' code readable executable align 8
;
;
PureBasicStart:
;
PUSH   dword I_BSSEnd-I_BSSStart
PUSH   dword 0
PUSH   dword I_BSSStart
CALL  _memset
PUSH   dword 0
CALL  _GetModuleHandleA@4
MOV    [_PB_Instance],eax
PUSH   dword 0
PUSH   dword 4096
PUSH   dword 0
CALL  _HeapCreate@12
MOV    [PB_MemoryBase],eax
CALL  _PB_InitMemory@0
;
;==================================================================
; Macro Loop(Var,Starting,Ending,Increment=1)
;==================================================================
; Macro EndLoop(Var)
;==================================================================
; Example
; Loop(i.d,1,5.5,1.5)
PUSH   dword 9
CALL  _PB_AllocateMemory@4
MOV    dword [p_Starti],eax
FLD    qword [D1]
SUB    esp,8
FSTP   qword [esp]
PUSH   dword [p_Starti]
CALL  _PB_PokeD@12
PUSH   dword 9
CALL  _PB_AllocateMemory@4
MOV    dword [p_Endi],eax
FLD    qword [D2]
SUB    esp,8
FSTP   qword [esp]
PUSH   dword [p_Endi]
CALL  _PB_PokeD@12
PUSH   dword 9
CALL  _PB_AllocateMemory@4
MOV    dword [p_Incri],eax
FLD    qword [D3]
SUB    esp,8
FSTP   qword [esp]
PUSH   dword [p_Incri]
CALL  _PB_PokeD@12
FLD    qword [D1]
FSTP   qword [v_i]
_Repeat1:
; Loop(j.d,16,4,-3.5)
PUSH   dword 9
CALL  _PB_AllocateMemory@4
MOV    dword [p_Startj],eax
FLD    qword [D4]
SUB    esp,8
FSTP   qword [esp]
PUSH   dword [p_Startj]
CALL  _PB_PokeD@12
PUSH   dword 9
CALL  _PB_AllocateMemory@4
MOV    dword [p_Endj],eax
FLD    qword [D5]
SUB    esp,8
FSTP   qword [esp]
PUSH   dword [p_Endj]
CALL  _PB_PokeD@12
PUSH   dword 9
CALL  _PB_AllocateMemory@4
MOV    dword [p_Incrj],eax
FLD    qword [D6]
SUB    esp,8
FSTP   qword [esp]
PUSH   dword [p_Incrj]
CALL  _PB_PokeD@12
FLD    qword [D4]
FSTP   qword [v_j]
_Repeat2:
; Debug "("+StrD(i,2)+", "+StrD(j,2)+")"
; EndLoop(j)
PUSH   dword [p_Startj]
CALL  _PB_PeekD@4
FSTP   qword [v_Startingj]
PUSH   dword [p_Endj]
CALL  _PB_PeekD@4
FSTP   qword [v_Endingj]
PUSH   dword [p_Incrj]
CALL  _PB_PeekD@4
FSTP   qword [v_Incrementj]
FLD    qword [v_j]
FSTP   qword [v_j]
FLD    qword [v_Startingj]
FLD    qword [v_Endingj]
FSUB   qword [v_Startingj]
FDIV   qword [v_Incrementj]
FMUL   qword [v_Incrementj]
FSTP   qword [v_Qend]
FLD    qword [v_j]
FSTP   qword [v_a]
FLD    qword [v_Qend]
FSTP   qword [v_b]
FLD    qword [v_Incrementj]
FCOMP  qword [D7]
FNSTSW ax
TEST   ah,1h
JE    _EndIf4
FLD    qword [v_Qend]
FSTP   qword [v_a]
FLD    qword [v_j]
FSTP   qword [v_b]
_EndIf4:
FLD    qword [v_a]
FLD    qword [v_b]
FCOMPP
FNSTSW ax
TEST   ah,1h
JE    _Repeat2
_Until2:
PUSH   dword [p_Incrj]
CALL  _PB_FreeMemory@4
PUSH   dword [p_Startj]
CALL  _PB_FreeMemory@4
PUSH   dword [p_Endj]
CALL  _PB_FreeMemory@4
; EndLoop(i)
PUSH   dword [p_Starti]
CALL  _PB_PeekD@4
FSTP   qword [v_Startingi]
PUSH   dword [p_Endi]
CALL  _PB_PeekD@4
FSTP   qword [v_Endingi]
PUSH   dword [p_Incri]
CALL  _PB_PeekD@4
FSTP   qword [v_Incrementi]
FLD    qword [v_i]
FSTP   qword [v_i]
FLD    qword [v_Startingi]
FLD    qword [v_Endingi]
FSUB   qword [v_Startingi]
FDIV   qword [v_Incrementi]
FMUL   qword [v_Incrementi]
FSTP   qword [v_Qend]
FLD    qword [v_i]
FSTP   qword [v_a]
FLD    qword [v_Qend]
FSTP   qword [v_b]
FLD    qword [v_Incrementi]
FCOMP  qword [D7]
FNSTSW ax
TEST   ah,1h
JE    _EndIf6
FLD    qword [v_Qend]
FSTP   qword [v_a]
FLD    qword [v_i]
FSTP   qword [v_b]
_EndIf6:
FLD    qword [v_a]
FLD    qword [v_b]
FCOMPP
FNSTSW ax
TEST   ah,1h
JE    _Repeat1
_Until1:
PUSH   dword [p_Incri]
CALL  _PB_FreeMemory@4
PUSH   dword [p_Starti]
CALL  _PB_FreeMemory@4
PUSH   dword [p_Endi]
CALL  _PB_FreeMemory@4
;
; Debug "last i = " + StrD(i)
; Debug "last j = " + StrD(j)
;==================================================================
_PB_EOP_NoValue:
PUSH   dword 0
_PB_EOP:
CALL  _PB_EndFunctions
PUSH   dword [PB_MemoryBase]
CALL  _HeapDestroy@4
CALL  _ExitProcess@4
_PB_EndFunctions:
CALL  _PB_FreeMemorys@0
RET
;
;
;
_PB_DataSection:
_PB_OpenGLSubsystem: db 0
pb_public PB_DEBUGGER_LineNumber
dd     -1
pb_public PB_DEBUGGER_IncludedFiles
dd     0
pb_public PB_DEBUGGER_FileName
db     0
_PB_ExecutableType: dd 0
align 4
D1: dd 0,1072693248
D2: dd 0,1075183616
D3: dd 0,1073217536
D4: dd 0,1076887552
D5: dd 0,1074790400
D6: dd 0,-1072955392
D7: dd 0,0
align 4
s_s:
dd     0
dd     -1
align 4
;
_PB_BSSSection:
align 4
;
I_BSSStart:
_PB_MemoryBase:
PB_MemoryBase: rd 1
_PB_Instance:
PB_Instance: rd 1
;
align 4
v_i rq 1
v_j rq 1
v_Startingj rq 1
v_Endingj rq 1
v_Incrementj rq 1
v_Qend rq 1
v_a rq 1
v_b rq 1
v_Startingi rq 1
v_Endingi rq 1
v_Incrementi rq 1
PB_DataPointer rd 1
p_Starti rd 1
p_Endi rd 1
p_Incri rd 1
p_Startj rd 1
p_Endj rd 1
p_Incrj rd 1
align 4
align 4
align 4
align 4
I_BSSEnd:
SYS_EndDataSection:

That's 25 instructions to get started, and 49 at the end (minus a few labels). That's a lot of overhead for a loop...mine is 10 instructions total (plus labels):
Code:
; ForStart(x, 1, 3.5)
MOV    dword [v_x],1065353216
_While1:
FLD    dword [v_x]
FCOMP  dword [F1]
FNSTSW ax
TEST   ah,41h
JE    _Wend1
; Debug x
; ForEnd(x, 0.5)
FLD    dword [v_x]
FSTP   dword [v_x]
JMP   _While1
_Wend1:
;
; Debug "last x " + Str(x)

Top

 Post subject: Re: For Next StepPosted: Tue Feb 21, 2012 5:15 pm
 Enthusiast

Joined: Tue Nov 09, 2010 10:15 pm
Posts: 794
I was thinking of your loops...the same thing can be accomplished with Push and Pop. That will save most of the code space.

Top

 Post subject: Re: For Next StepPosted: Tue Feb 21, 2012 5:34 pm

Joined: Sat Feb 19, 2005 2:46 pm
Posts: 1334
Location: Pas-de-Calais, France
Maybe like this...
Code:
Macro ForD(StartD)
StartD
!Loop@:
EndMacro

Macro NextD(StartD, StopD, StepD)
StartD + StepD
If StartD < StopD
!jmp Loop@
EndIf
EndMacro

ForD(i.d = 0)
Debug i.d
NextD(i, 8, 0.5)

_________________
The Shooting Crew ~> http://www.shootingcrew.com/
Bobble Puzzle, Purebreaker 3 ~> http://djes.free.fr

Last edited by djes on Thu Feb 23, 2012 3:51 pm, edited 2 times in total.

Top

 Post subject: Re: For Next StepPosted: Tue Feb 21, 2012 6:21 pm
 Enthusiast

Joined: Tue Sep 23, 2008 11:38 pm
Posts: 702
Location: Belgium (& Luxembourg)
@Tenaja & @djes & @All
The problem is that I have never learned Assembler, so I have no idea how to make it shorter. I am thinking purely in PureBasic. I can only understand that the complexity of my code can be time consuming at runtime, but I made some tests and I think that the speed is still high enough, as calculations with doubles are always slower than with integers.
@djes: the macro you made has a problem: in nested loops, it cannot be used again, because the symbol is already defined. (As this is asm, I have no clue what that means).
Code:
;==================================================================
Macro Loop(Var,Starting,Ending,Increment=1)
*Start#Var=AllocateMemory(9)
PokeD(*Start#Var,Starting)
*End#Var=AllocateMemory(9)
PokeD(*End#Var,Ending)
*Incr#Var=AllocateMemory(9)
PokeD(*Incr#Var,Increment)
Var=Starting
Repeat
EndMacro
;==================================================================
Macro EndLoop(Var)
Starting#Var.d=PeekD(*Start#Var)
Ending#Var.d=PeekD(*End#Var)
Increment#Var.d=PeekD(*Incr#Var)
Var+Increment#Var
Qend.d=Starting#Var+((Ending#Var-Starting#Var)/Increment#Var)*Increment#Var; calculate the number of steps to know the real destination value
a.d=Var : b.d=Qend
If Increment#Var<0; negative increment
a.d=Qend : b.d=Var; swap current var & real ending
EndIf
Until a>b; if increment was negative, we had to swap the variables, because we cannot swap the direction of Until
FreeMemory(*Incr#Var)
FreeMemory(*Start#Var)
FreeMemory(*End#Var)
EndMacro
;==================================================================
Macro ForD(StartD)
!Loop@:
EndMacro
;==================================================================
Macro NextD(StartD, StopD, StepD)
StartD + StepD
If StartD < StopD
!jmp Loop@
EndIf
EndMacro
;==================================================================
; Example

Debug "Please wait until loops are finished!............."
DisableDebugger

StartTime = ElapsedMilliseconds()
Loop(i.d,1,100000,0.75)
Loop(j.d,6000,-4000,-3.5)
;Debug "("+StrD(i,2)+", "+StrD(j,2)+")"
EndLoop(j)
EndLoop(i)
ElapsedTime1 = ElapsedMilliseconds()-StartTime

; StartTime = ElapsedMilliseconds()
; ForD(a.d = 1)
;     ForD(b.d = 6000)
;         ;...
;     NextD(b, -4000,-3.5)
; NextD(a, 100000, 0.75)
; ElapsedTime2 = ElapsedMilliseconds()-StartTime

StartTime = ElapsedMilliseconds()
For k=1 To 100000 Step 1
For l=6000 To -4000 Step -3
;Debug "("+StrD(k,2)+", "+StrD(l,2)+")"
Next l
Next k
ElapsedTime3 = ElapsedMilliseconds()-StartTime

EnableDebugger

Debug ElapsedTime1
;Debug ElapsedTime2
Debug ElapsedTime3

;==================================================================

_________________
- Future conversation forecasting not yet implemented.
- If the future had copied a program from now, they would have called it version -1.

Top

 Post subject: Re: For Next StepPosted: Wed Feb 22, 2012 7:41 pm
 PureBasic Expert

Joined: Sat May 17, 2003 11:31 am
Posts: 5808
I don't see any advantage of a for / next with variable step over a while / wend or repeat / until. In fact, a while / wend leaves IMHO better readable code.

Not being able to use a quad in a for / next is indeed a bit silly, though I've never need it thus far

_________________
( PB5.11 Win7 x64 Dell XPS710 Raid 0 VelociRaptor Intel Q6600 nForce 5 NVidia GTS450 )
( You have two options: psychotherapy, or the PureBasic Survival Guide... )

Top

 Post subject: Re: For Next StepPosted: Wed Feb 22, 2012 9:55 pm
 Enthusiast

Joined: Tue Sep 23, 2008 11:38 pm
Posts: 702
Location: Belgium (& Luxembourg)
@blueznl
Let's return the problem: What's the advantage of For/Next over While/Wend or Repeat/Until ?
If there is one, even a small one, then the same advantage may apply to the variable step (and doubles) as well.

To me, the big advantage is that I tell the program the fixed range and the step to the loop in one single line before it begins.

_________________
- Future conversation forecasting not yet implemented.
- If the future had copied a program from now, they would have called it version -1.

Top

 Post subject: Re: For Next StepPosted: Tue Feb 28, 2012 8:36 pm
 PureBasic Expert

Joined: Sat May 17, 2003 11:31 am
Posts: 5808
Yes, I can see that advantage of For / Next, and that does make sense. However, when doing fancy stuff (like changing the step parameter) it actually does make sense to switch to While / Wend, as you're no longer doing something simple and straightforward. In fact, you're changing the step parameter, something not obvious from the first For / Next call.

So, I beg to disagree with you

_________________
( PB5.11 Win7 x64 Dell XPS710 Raid 0 VelociRaptor Intel Q6600 nForce 5 NVidia GTS450 )
( You have two options: psychotherapy, or the PureBasic Survival Guide... )

Top

 Post subject: Re: For Next StepPosted: Tue Feb 28, 2012 9:31 pm
 Enthusiast

Joined: Tue Nov 09, 2010 10:15 pm
Posts: 794
charvista wrote:
To me, the big advantage is that I tell the program the fixed range and the step to the loop in one single line before it begins.

The way PB handles the For/Next loop, the ONLY advantage is readability. It compiles longer, and executes slower than a repeat/until or while/wend.

The reason is the same as what you like about it. PB parses the loop sequentially, and does NOT reorder anything. Therefore, the assignment is made, the test is performed, the increment is Jumped over (wasted time), the loop is run, then at Next, it Jumps to the increment, after which it Jumps to the test, and then it either jumps to the loop code or out of the loop.

All of those jumps make the For-Next loop the most inefficient loop you can use--both in code space and execution time. But it is easy to code and very readable, so if speed is not an issue, all is good.

Oh, yeah...only if your increment is a constant integer, you are good.

Top

 Display posts from previous: All posts1 day7 days2 weeks1 month3 months6 months1 year Sort by AuthorPost timeSubject AscendingDescending
 Page 1 of 3 [ 34 posts ] Go to page 1, 2, 3  Next

 All times are UTC + 1 hour

#### Who is online

Users browsing this forum: No registered users and 1 guest

 You cannot post new topics in this forumYou cannot reply to topics in this forumYou cannot edit your posts in this forumYou cannot delete your posts in this forum

Search for:
 Jump to:  Select a forum ------------------ PureBasic    Coding Questions    Game Programming    3D Programming    Assembly Programming    The PureBasic Editor    The PureBasic Form Designer    General Discussion    Feature Requests and Wishlists    Tricks 'n' Tips Bug Reports    Bugs - Windows    Bugs - Linux    Bugs - Mac OSX    Bugs - Documentation OS Specific    AmigaOS    Linux    Windows    Mac OSX Miscellaneous    Announcement    Off Topic Showcase    Applications - Feedback and Discussion    PureFORM & JaPBe    TailBite