A four level stack allows 4 subroutines plus the main routine, or eight plus main for the current PICAXE ...in PICAXE parlance up to 3 sub-routines can be called from the main one (4 in total)
#Picaxe 08M2
#Terminal 4800
Do
SerTxd( CR, LF, "Start:" )
Gosub Level1
Loop
Level1: SerTxd( "1" ) : Gosub level2 : Return
Level2: SerTxd( "2" ) : Gosub level3 : Return
Level3: SerTxd( "3" ) : Gosub level4 : Return
Level4: SerTxd( "4" ) : Gosub level5 : Return
Level5: SerTxd( "5" ) : Gosub level6 : Return
Level6: SerTxd( "6" ) : Gosub level7 : Return
Level7: SerTxd( "7" ) : Gosub level8 : Return
level8: SerTxd( "8" ) : Return
I just implemented exp function as recursive gosub... I have a level counter to know the recursivity depth. Furtunately, the function is converging before level 5, so there are few levels to call the function. But 8 levels are not to much !... 4 levels of stack are all that is required to work, so the PICAXE 8 limit is more than generous and rarely if ever will be met in practice.
#picaxe 40X2
#no_table
#simspeed 1
Do
SerTxd( CR, LF, "Start:" )
Gosub Level1
Loop
Level1: SerTxd( ">1 " ) : Gosub level2 : SerTxd( "1< " ): Return
Level2: SerTxd( ">2 " ) : Gosub level3 : SerTxd( "2< " ): Return
Level3: SerTxd( ">3 " ) : Gosub level4 : SerTxd( "3< " ): Return
Level4: SerTxd( ">4 " ) : Gosub level5 : SerTxd( "4< " ): Return
Level5: SerTxd( ">5 " ) : Gosub level6 : SerTxd( "5< " ): Return
Level6: SerTxd( ">6 " ) : Gosub level7 : SerTxd( "6< " ): Return
Level7: SerTxd( ">7 " ) : Gosub level8 : SerTxd( "7< " ): Return
Level8: SerTxd( ">8 " ) : Gosub level9 : SerTxd( "8< " ): Return
Level9: SerTxd( ">9 " ) : Gosub level10 : SerTxd( "9< " ): Return
Level10: SerTxd( ">10 " ) : Gosub level11 : SerTxd( "10< " ): Return
level11: SerTxd( ">11 " ) : Return
#picaxe 40X2
#no_table
#simspeed 1
Do
SerTxd( CR, LF, "Start:" )
b0=0
Gosub Level
Loop
Level:
inc b0
SerTxd( ">",#b0," " )
if b0<8 then gosub Level
SerTxd( #b0,"< " )
dec b0
Return
YESInteresting. So I would do power(base x exp) and stop the recursion when exp=1
#picaxe 40X2
#no_table
#simspeed 1
symbol EE=b0
symbol EEbit0=bit0
symbol WL=b2
symbol WH=b3
symbol WW=w1
symbol E_2=b4
symbol E10=b5
symbol Nb =b6
symbol BT=b7
symbol Reste=b8
symbol FL_ZM=w21
Symbol FL_TM=w22
symbol FL_ZE2=b46
symbol FL_TE2=b47
symbol WT=w24
symbol WTL=B48
symbol WTH=B49
symbol FL_XM=w25
symbol FL_XL=b50
symbol FL_XH=b51
symbol FL_YM=w26
symbol FL_YL=b52
symbol FL_YH=b53
symbol FL_XE2=b54
symbol FL_YE2=b55
#macro FL_Exp(Flott,E2,E)
Nb=0
FL_XM=Flott
FL_XE2=E2
EE=E
gosub FLexp
#endmacro
#macro Expo2(E)
E_2=E
gosub Exp2
#endmacro
#macro ToFloat(F,E)
WW=F
E10=E
gosub ToFlo
#endmacro
#macro FL_Add(Flott,E2)
FL_YM=FL_XM : FL_YE2=FL_XE2
FL_XM=Flott
FL_XE2=E2
gosub FLadd
#endmacro
#macro FL_Div(Flott,E2)
FL_YM=FL_XM : FL_YE2=FL_XE2
FL_XM=Flott
FL_XE2=E2
gosub FLdiv
#endmacro
#rem
FL_XM=40002 : FL_XE2=1
FL_YM=50000 : FL_YE2=1
gosub FLdiv
FL_XM=50000 : FL_XE2=1
FL_YM=40002 : FL_YE2=1
gosub FLdiv
FL_XM=40002 : FL_XE2=1
FL_YM=50000 : FL_YE2=3
gosub FLdiv
#endrem
#rem
sertxd(13,10)
FL_XM=32768
FL_XE2=0
FL_YM=32768
FL_YE2=0
gosub FL_Sertxd
gosub FL_Sertyd
sertxd ("FLmulti",13,10)
gosub FLmulti
gosub FL_Sertxd
sertxd(13,10)
FL_XM=50000
FL_XE2=0
FL_YM=12000
FL_YE2=0
gosub FL_Sertxd
gosub FL_Sertyd
sertxd ("FLmulti",13,10)
gosub FLmulti
gosub FL_Sertxd
sertxd(13,10)
FL_XM=50000
FL_XE2=1
FL_YM=12000
FL_YE2=-2
gosub FL_Sertxd
gosub FL_Sertyd
sertxd ("FLmulti",13,10)
gosub FLmulti
gosub FL_Sertxd
FL_XM=33000:FL_XE2=0
FL_Div(32768,-13)
FL_Add(22000,4)
gosub FL_sertxd
#endrem
sertxd(13,10,"FL_Exp 2 0 15",13,10)
FL_Exp(2,0,15)
gosub FL_sertxd
sertxd(13,10,"FL_Exp 3 0 3",13,10)
FL_Exp(3,0,3)
gosub FL_sertxd
FL_ZM=FL_XM : FL_ZE2=FL_XE2
sertxd(13,10,"FL_Exp 10 0 4",13,10)
FL_Exp(10,0,4)
FL_YM=FL_ZM : FL_YE2=FL_ZE2
gosub FLmulti
gosub FL_sertxd
#rem
FL_YM=32768
FL_YE2=-30
gosub FLmul
sertxd ("X=")
gosub FL_sertxd
sertxd (13,10)
FL_Exp(3,0,5)
sertxd ("3^5=",#FL_XM,"*2^",#FL_XE2,13,10,13,10)
FL_Exp(2,12)
sertxd ("2^12=",#WW,13,10,13,10)
FL_Exp(2,-5)
sertxd ("2^-5=",#WW,13,10,13,10)
Expo2(0)
sertxd ("2^0=",#WW," E" , #E_2,13,10)
Expo2(4)
sertxd ("2^4=",#WW," E" , #E_2,13,10)
for nb=15 to 64
Expo2(nb)
sertxd ("2^",#nb,"=",#WW," E" , #E10,13,10)
next nb
#endrem
#rem
toFloat(1000,3)
sertxd( #WW," E" , #E_2,13,10)
toFloat(100,4)
sertxd( #WW," E" , #E_2,13,10)
#endrem
end
FL_sertXd:
if FL_XE2<128 then
sertxd ("X=",#FL_XM,"*2^",#FL_XE2,13,10)
else
BT=-FL_XE2
sertxd ("X=",#FL_XM,"*2^-",#BT,13,10)
endif
return
FL_sertYd:
if FL_YE2<128 then
sertxd ("Y=",#FL_YM,"*2^",#FL_YE2,13,10)
else
BT=-FL_YE2
sertxd ("Y=",#FL_YM,"*2^-",#BT,13,10)
endif
return
ToFlo:
sertxd(13,10,"Float(",#ww,",",#E10,")=")
E_2=ncd WW
E_2=16-E_2
WW=WW<<E_2
return
Exp2:
E10=0
Reste=0
if E_2=0 then
WW=1
elseif E_2 < 16 then
WW=dcd E_2
elseif E_2<128 then
WW=32768 ' ww=dcd 16
EE=15
b0=E_2-3
do while EE<b0
gosub Div10
loop
do while EE<E_2
if WW<32768 then
WW=WW<<1
Reste=Reste<<1
inc EE
else
gosub Div10
endif
loop
WW=Reste+5/10+WW
else
endif
return
Div10:
b0=ncd WW
b0=16-b0
Reste=Reste<<b0+5/10
WW=WW<<b0+reste
Reste=WW//5*2
WW=WW/5
EE=EE+b0+1
' sertxd("WW=",#WW," EE=",#EE," R=", #Reste,13,10)
inc E10
return
FLexp:
sertxd ("FLexp Level=",#Nb," E=",#EE," ")
GOSUB FL_sertxd
inc Nb
If EE = 0 Then
FL_XM=1
' ElseIf EE = 1 Then ' answer is FL_XM
ElseIf EE <128 Then
FL_YM=FL_XM : FL_YE2=FL_XE2
gosub FLmulti
sertxd ("X*X =>")
gosub FL_sertxd
If EEbit0 = 0 Then ' BT est pair
' Expon = Expon(X * X, Exp / 2)
EE=EE/2
if EE<>1 then gosub FLexp
Else
' Expon = X * Expon(X * X, (Exp - 1) / 2)
EE=EE-1/2
push FL_YL,FL_YH,FL_YE2
if EE<>1 then gosub FLexp
pop FL_YE2,FL_YH,FL_YL
GOSUB FL_sertxd
GOSUB FL_sertyd
sertxd("X * Y",13,10)
gosub FLmulti
End If
Else
' Expon = Expon(1 / X, -Exp)
EE=-EE
FL_YM=32768 : FL_YE2=-15
gosub FLdiv
gosub FLexp
End If
return
' Effectue X=Y/X (Y est perdu dans l'op?ration)
FLdiv:
#rem
wt=FL_YM/FL_XH-1
sertxd (#FL_YM,"/",#FL_XH,"=",#Wt,13,10)
w2=wt*/FL_XM
sertxd ("W2=",#w2,13,10)
w4=FL_YM-w2<<8/FL_XH>>1
sertxd (#FL_YM,"-",#w2,"<<8/",#FL_XH,"=",#w4,13,10)
FL_XM=wt<<7+w4
sertxd ("WT=",#WT," X=",#FL_XM,13,10)
#endrem
sertxd (#FL_YM," E2:",#FL_YE2,"/",#FL_XM," E2:",#FL_XE2,13,10)
FL_XE2=FL_YE2-FL_XE2 ' on lib?re FL_YE2
WT=FL_YM/FL_XH-1 ' 8 ou 9 premiers bits du dividande
BT=ncd WT-8 ' Combien de bits au dividande ?
sertxd (#FL_YM,"/",#FL_XH,"=",#WT," E2=",#BT,13,10)
FL_YE2=FL_XH ' On sauvegarde FL_XH
FL_XM=WT*/FL_XM
FL_YM=FL_YM-FL_XM<<8/FL_YE2>>BT ' En fait, on divise par FL_XM
BT=8-BT
FL_XM=WT<<BT+FL_YM
FL_XE2=FL_XE2-BT-8
gosub FL_sertxd
return
FLmul:
FL_XM=FL_XM**FL_YM
FL_XE2=FL_XE2+FL_YE2
return
FLmulti: ' X=X*Y et Y inchange
' Accepte les flottants non normalis?s
sertxd("FL_XM=",#FL_XM," * FL_YM=",#FL_YM,13,10)
WT=FL_XM*FL_YM
FL_XM=FL_XM**FL_YM
sertxd("FL_XM**FL_YM=",#FL_XM,13,10)
BT=ncd FL_XM
FL_XE2=FL_XE2+FL_YE2
sertxd("BT(**)=",#BT,13,10)
if BT=0 then
BT=ncd WT
sertxd("BT(*)=" , #BT,13,10)
BT=16-BT
FL_XM=WT<<BT
FL_XE2=FL_XE2-BT
else
WT=WT>>BT
BT=16-BT
FL_XM=FL_XM<<BT+WT
FL_XE2=FL_XE2-BT+16
endif
return
FLadd: ' X=X+Y et Y inchange
' Accepte les flottants non normalises
sertxd(13,10,"ADD",13,10)
gosub FL_sertxd
gosub FL_sertyd
BT=FL_XE2-FL_YE2
if BT<128 then
FL_XM=FL_YM>>BT+FL_XM
else
BT=-BT
FL_XM=FL_XM>>BT+FL_YM
endif
return
Yes you are wrong : only 8 levels are possible.Am i wrong in thinking a GOSUB of 256 can be coded,
And yes : any recursive program can also be written without recursivity.and why would you need more then a few levels on gosub depth then a few for average code. i can only expect your code can be better written to work better. rather than your current method of many layers of gosub depths.
PrintHexWord:
b10 = w0 / $0100 : Gosub PrintHexByte
b10 = w0 & $00FF : Gosub PrintHexByte
Return
PrintHexByte:
b11 = b10 / $10 : Gosub PrintHexNibble
b11 = b10 & $0F : Gosub PrintHexNibble
Return
PrintHexNibble:
b11 = b11 & $0F + "0"
If b11 > "9" Then : b11 = b11 + 7 : End If
Gosub PrintChar
Return
PrintChar:
If flgDebug Then
SerTxd( b11 )
End If
HSerOut 0, ( b11 )
Return
Not sure that is correct. There used to be a limit of 16 GOSUB's in a program in total, and that was raised from 16 to 256. The stack depth was originally 4 but raised to 8.Somewhere there was a switch from 8 to 16 levels. Is that method as old as I am?
Recursion when watched as it is working looks like programatic ballet! As one routine calls itself repeatedly it is like seeing an infinite number of Russian dolls being opened, only to find yet another doll inside. As the recursion reaches it's climax, the dolls slowly start being put back inside one another, one by one, eventually closing the last doll as the routine finally exits. Truly wonderful.And yes : any recursive program can also be written without recursivity.
Recursive style is more compact and work well if you don't reach the GOSUB depth limit.
Linear coding of same algorithm imply using of a stack, and fortunately Picaxe have Push and Pull commands.
So it is doable.
Recursive style is not "my method" !
It is a well documented and known computer programming tactic : Recursion_(computer_science)
Here is a very classical implementation of N! (as illustration)Recursion when watched as it is working looks like programatic ballet! As one routine calls itself repeatedly it is like seeing an infinite number of Russian dolls being opened...
#picaxe 40X2
#no_table
#simspeed 1
#macro Fact(N)
w1=1
b1=N
gosub Factorielle
#endmacro
Do
for b0=2 to 6
Fact(b0)
SerTxd( "Fact(",#b0,")=",#w1,13,10 )
next b0
sertxd(13,10)
Loop
Factorielle:
w1=w1+1*w1
dec b1
if b1>1 then gosub Factorielle
Return
This isn't the result I got with a 08M2...I tried two different over-flow programs (including yours from post 5)...Here is the answer for first code in #5 :
Start:>1 >2 >3 >4 >5 >6 >7 >8 >9 >10 >11 10< 9< 8< 7< 6< 5< 4< 3< 3< 3< 3< 3< 3< 3< 3< 3< 3< 3< 3< 3< 3< 3< 3< 3< 3< 3< 3< 3< 3
So, a real Picaxe go back everlastingly to the last GOSUB on his stack, in our case the one in Level3:
Thanks. It is clear now. I haven't nested any of my subroutines even once.That's fine, you can gosub like that all day long as many times as you want, the nesting limit is when you gosub another subroutine from within a subroutine and do it several times, such as:
ProcOne:
Gosub ProcTwo
Return
ProcTwo:
Gosub ProcThree
Return
ProcThree:
Gosub ProcFour
Return
etc.
So you can only do that sort of nested gosub 8 levels deep, though I can't recall ever having to nest beyond once or twice so it's not a problem unless you get into some really complex programming.
I think Hippy just confirmed you can go to 256 levels in gosubs, as it use to be less and you needed to select 256 in setup options, i think now its no setup required.Yes you are wrong : only 8 levels are possible.
Not 256 levels in gosubs but 256 gosub commands.I think Hippy just confirmed you can go to 256 levels in gosubs, as it use to be less and you needed to select 256 in setup options, i think now its no setup required.