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

All times are UTC + 1 hour




Post new topic Reply to topic  [ 34 posts ]  Go to page 1, 2, 3  Next
Author Message
 Post subject: For Next Step
PostPosted: Wed Feb 15, 2012 5:15 am 
Offline
Addict
Addict

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
 Profile  
 
 Post subject: Re: For Next Step
PostPosted: Wed Feb 15, 2012 10:40 pm 
Offline
Enthusiast
Enthusiast
User avatar

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

STEP Variable !
For : Next : Step with decimals
Step in For loop to accept an expression
for-next
STEP Value.l
...

Image Search

_________________
Image


Top
 Profile  
 
 Post subject: Re: For Next Step
PostPosted: Wed Feb 15, 2012 10:42 pm 
Offline
Addict
Addict
User avatar

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


Already requested ... yes.

But SPAM ? :shock:

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


Top
 Profile  
 
 Post subject: Re: For Next Step
PostPosted: Sat Feb 18, 2012 8:13 am 
Offline
Enthusiast
Enthusiast
User avatar

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
 Profile  
 
 Post subject: Re: For Next Step
PostPosted: Sun Feb 19, 2012 1:29 am 
Offline
Enthusiast
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
 Profile  
 
 Post subject: Re: For Next Step
PostPosted: Sun Feb 19, 2012 4:11 pm 
Offline
Enthusiast
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
 Profile  
 
 Post subject: Re: For Next Step
PostPosted: Tue Feb 21, 2012 12:38 am 
Offline
Enthusiast
Enthusiast
User avatar

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
 Profile  
 
 Post subject: Re: For Next Step
PostPosted: Tue Feb 21, 2012 5:16 am 
Offline
Enthusiast
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
  ADD    esp,12
  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]
  FADD   qword [v_Incrementj]
  FADD   qword [D7]
  FSTP   qword [v_j]
  FLD    qword [v_Startingj]
  FLD    qword [v_Endingj]
  FSUB   qword [v_Startingj]
  FADD   qword [D7]
  FDIV   qword [v_Incrementj]
  FMUL   qword [v_Incrementj]
  FADDP  st1,st0
  FADD   qword [D7]
  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]
  FADD   qword [v_Incrementi]
  FADD   qword [D7]
  FSTP   qword [v_i]
  FLD    qword [v_Startingi]
  FLD    qword [v_Endingi]
  FSUB   qword [v_Startingi]
  FADD   qword [D7]
  FDIV   qword [v_Incrementi]
  FMUL   qword [v_Incrementi]
  FADDP  st1,st0
  FADD   qword [D7]
  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
;
;
section '.data' data readable writeable
;
_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
;
section '.bss' readable writeable
_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:
section '.data' data readable writeable
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]
  FADD   dword [F2]
  FSTP   dword [v_x]
  JMP   _While1
_Wend1:
;
; Debug "last x " + Str(x)


Top
 Profile  
 
 Post subject: Re: For Next Step
PostPosted: Tue Feb 21, 2012 5:15 pm 
Offline
Enthusiast
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
 Profile  
 
 Post subject: Re: For Next Step
PostPosted: Tue Feb 21, 2012 5:34 pm 
Offline
Addict
Addict
User avatar

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
 Profile  
 
 Post subject: Re: For Next Step
PostPosted: Tue Feb 21, 2012 6:21 pm 
Offline
Enthusiast
Enthusiast
User avatar

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
 Profile  
 
 Post subject: Re: For Next Step
PostPosted: Wed Feb 22, 2012 7:41 pm 
Offline
PureBasic Expert
PureBasic Expert
User avatar

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
 Profile  
 
 Post subject: Re: For Next Step
PostPosted: Wed Feb 22, 2012 9:55 pm 
Offline
Enthusiast
Enthusiast
User avatar

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. :twisted:

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
 Profile  
 
 Post subject: Re: For Next Step
PostPosted: Tue Feb 28, 2012 8:36 pm 
Offline
PureBasic Expert
PureBasic Expert
User avatar

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
 Profile  
 
 Post subject: Re: For Next Step
PostPosted: Tue Feb 28, 2012 9:31 pm 
Offline
Enthusiast
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
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 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 forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
Jump to:  

 


Powered by phpBB © 2008 phpBB Group
subSilver+ theme by Canver Software, sponsor Sanal Modifiye