Oxygen Basic

Programming => Example Code => Topic started by: Frankolinox on April 10, 2013, 01:49:06 AM

Title: rnd(a,b) command?
Post by: Frankolinox on April 10, 2013, 01:49:06 AM
hi, I am looking for a simple "rnd(a,b)" command or function.

thanks, frank
Title: Re: rnd(a,b) command?
Post by: Aurel on April 10, 2013, 02:15:11 AM
Frank..
Peter create this and work very well.. ;)
Rand(min,max)
Code: [Select]
Function Rand(byval z1 as long, byval z2 as long) as long
Long rnd
mov  eax,z2
sub  eax,z1
Inc  eax
imul edx,sys_Seed,0x8088405
Inc  edx
mov  sys_Seed,edx
mul  edx
add  edx,z1
mov  rnd,edx
Function = rnd
End Function
Title: Re: rnd(a,b) command?
Post by: Frankolinox on April 10, 2013, 05:11:40 AM
a) thanks for little rand() function, aurel, but it doesn't work here. have you more details about that example?

b) I am looking for a random function for using two parameters with "rnd(min,max)".
but it's not very urgent. I wanted only to use it for different "height" parameter for some cubes in my openGL fog example :) I can change the example for having different height values for the cubes, no problem, but it would be easier to have a random function here.

Code: [Select]
sys a,b,y
a=1
b=100
y=rnd(a,b)

function random(sys min, max) as long

end function


 for i = -25 to 25 step 10
      for j = -25 to 25 step 10
        height = Rand(5, 20)
        '...
 next
next

if anybody has an idea I am glad to see that one.

frank

X
Title: Re: rnd(a,b) command?
Post by: Emil_halim on April 10, 2013, 08:25:49 AM
Hi frank,

got this from Fasm and converted to Oxygen.
Code: [Select]

$ filename "rnd.exe"
#include "..\..\inc\RTL32.inc"


int Rnd(int max)
{
   int a;
 
      rdtsc          ; call read time-stamp counter instruction
                     ; returns timer value in edx:eax
      cdq            ; convert double word to quad word
                     ; edx:eax <-- sign extension of EAX
      idiv max       ; divide edx:eax by max integer
                     ; stores result in EAX <- Quotient, EDX <- Remainder
                     ; EDX = edx:eax % max
      cmp edx, 0     ; compare value to zero?
                    
      jge after      ; jump if not less than to after: label
      neg edx        ; otherwise, change sign to positive
.after:
      mov a, edx     ; store random number in a
 
   return a;      // return random number
}

macro RndA(min,max)
  rnd(max-min)+min
end macro

print Rnd(100)

print RndA(200,300)

Title: Re: rnd(a,b) command?
Post by: Emil_halim on April 10, 2013, 08:35:15 AM

Here is a copy in HighLevelAsm
Quote
int H_Rnd(int max)
{
   rdtsc
   cdq
   idiv max
   ^ .if eax<0
   ^     ~edx
   ^ .endif
   ^ eax><edx
   return eax
}
Title: Re: rnd(a,b) command?
Post by: Aurel on April 10, 2013, 08:36:05 AM
What... >:(
This time not work for me to...what a heck was heapend ???
Title: Re: rnd(a,b) command?
Post by: Aurel on April 10, 2013, 08:39:19 AM
Emil..
do you can show code without all this comments with
standard oxygen syntax without {} thingies ;)

Or maybe better to show us how create RND function with oxygen BASIC code?
Title: Re: rnd(a,b) command?
Post by: Emil_halim on April 10, 2013, 09:07:17 AM
Aurel ,

Quote
do you can show code without all this comments with
standard oxygen syntax without {} thingies

what is the problem with the comment , when coding in asm it is recommended to comment every step
you do for better understanding.
{} is prat of Oxygen , for example
Code: [Select]

function rnd(min as int, max as int) as int

equal to this

int rnd(int min,int max)
{

and
  
  function = val
End function

is equal to

  return val
}

so what is the problem here ??????

Quote
Or maybe better to show us how create RND function with oxygen BASIC code?

i think Oxygen basic still do not support quad value division so we cant make this with basic.
Title: Re: rnd(a,b) command?
Post by: Charles Pegge on April 10, 2013, 09:26:40 AM
32bit Oxygen uses the FPU for quad (64bit signed integer) arithmetic.
Title: Re: rnd(a,b) command?
Post by: Frankolinox on April 10, 2013, 09:49:51 AM
thank you emil for your example! :) I haven't checked it, but I will try next hours, looks good if that's working I am very glad!

here's my result of explorations about "rand" and "rnd()" by charles and peter's example shown:

Code: [Select]
'first random() ' rand(a,b) ' peter

Long seed=0x12345678 'initial seed value  

Function Rand(byval z1 as long, byval z2 as long) as long
long rnd
long sys_Seed=0x12345678
mov  eax,z2
sub  eax,z1
Inc  eax
imul edx,sys_Seed,0x8088405
Inc  edx
mov  sys_Seed,edx
mul  edx
add  edx,z1
mov  rnd,edx
Function = rnd
End Function

print Rand(64,255) /Log(10) '93.80760809
print Rand(64,255) '216

'second random() 'Rnd() ' charles

 '-----------------------  
 Function Rnd() as single 'sys
 '=======================  
 '  
 Static As Single f, d=1/0x7fffffff  
 mov eax,seed  
 rol eax,7  
 imul eax,eax,13  
 mov seed,eax  
 push eax  
 fild dWord [esp]  
 add esp,4  
 fmul dWord d  
 fstp dWord f  
 Function=f  
 End Function  

print rnd() '0.657777..

the rand() example from peter is good, but it's not working correct for different values for my openGL cubes (or I have done something wrong), I already tried it.
I suppose that's not working as usual rnd(min,max) function because there's a fixed value with the "seed", but I am not sure about that one.

Quote
got this from Fasm and converted to Oxygen.

@emil: little question just for my curiosity, because I didn't know Fasm: is that a heavy job to convert from Fasm to oxygen? thanks!

best regards, frank
Title: Re: rnd(a,b) command?
Post by: Emil_halim on April 10, 2013, 11:18:56 AM
Quote
@emil: little question just for my curiosity, because I didn't know Fasm: is that a heavy job to convert from Fasm to oxygen? thanks!

fasm  = flat assembler http://flatassembler.net/ (http://flatassembler.net/)
Title: Re: rnd(a,b) command?
Post by: Aurel on April 10, 2013, 01:33:26 PM
But Frank something is strange here:
Code: [Select]
Function Rand(byval z1 as INT, byval z2 as INT) as INT
INT rnd
INT sys_Seed=0x12345678
mov  eax,z2
sub  eax,z1
Inc  eax
imul edx,sys_Seed,0x8088405
Inc  edx
mov  sys_Seed,edx
mul  edx
add  edx,z1
mov  rnd,edx
Function = rnd
End Function

print Rand(1,100)

I always receive same result...what i do wrong  ???
Title: Re: rnd(a,b) command?
Post by: Aurel on April 10, 2013, 09:39:55 PM
Peter
First ..i see that your new function is litlle bit different then old which i have.
Ok i get it that i first need to randomize.
I will try... ;)

by the way ,is there a way to create this func without asm code?
and what will be difference ?
thanks
Title: Re: rnd(a,b) command?
Post by: Aurel on April 10, 2013, 11:11:27 PM
Peter
This looks like nightmare...
I receive now result 1  ???
What kind of problem is now?
here is my test code:
Code: [Select]
! GetTickCount Lib "kernel32.dll" () as sys
sys seed

Function Randomize() as sys
    seed = GetTickCount
End Function

Function Rand(sys z1,z2) as sys
    pushad
    sys  rnd
    mov  eax,z2
    sub  eax,z1
    inc  eax
    imul edx,seed,0x8088405
    inc  edx
    mov  seed,edx
    mul  edx
    add  edx,z1
    mov  rnd,edx
    popad
    Return rnd
End Function

print Rand(1,100)

I also found in from your old window.inc
this :
Code: [Select]
Declare Function timeGetTime Lib "winmm.dll" () As Long
sys sys_Seed

Sub Randomize()
    sys_Seed = timeGetTime
End Sub

Function Rand(sys z1, z2) as sys
    sys    rnd
    mov    eax,z2
    sub    eax,z1
    inc    eax
    imul   edx,sys_Seed,0x8088405
    inc    edx
    mov    sys_Seed,edx
    mul    edx
    add    edx,z1
    mov    rnd,edx
    return rnd
End Function

print Rand(1,100)

And again result is always 1 ...
this is really weird...
because i know that this function work in the past  ::)
Title: Re: my random_asm example
Post by: Frankolinox on April 11, 2013, 12:18:22 AM
perhaps anybody can check this random() example I've done this morning with arrays:

Code: [Select]
basic

print "random test"

'-----------------------// test // ------------------
function rando(sys*max,sys*min) as long
    sys p=@max
    sys k=@min
        rdtsc
        cdq
        idiv max
        idiv min
        cmp edx, 0
        jge after
        neg edx
    .after:
        mov edx,p 'mov a, edx
        mov edx,k
    return [edx+4] 'p 'max '    
    
end function

print "ok"

indexbase 1

'sys aa[12]={50,52,53,54,55,56,57,58,59,60,61,62}
sys ab[21]={10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30}
print "test random function"
print "ok2"
'print rando ab[3] ,ab[5] 'result: 15
print rando ab[6] ,ab[7] 'result: 17
print "ok3"
'print rando aa[8] ,aa[9]  'result: 60

'print rnd(100)
'-----------------------// test end // ------------------

both results are correct, but I can only run one example

either

Code: [Select]
rando ab[3] ,ab[5]) OR

print rando aa[8] ,aa[9]  'result: 60

I've used emil's code (one page before) from fasm and convert it into oxygen.

b) thanks peter for code example with randomize+gettickcount :)

best regards, frank
Title: Re: rnd(a,b) command?
Post by: Aurel on April 11, 2013, 12:50:42 AM
I try..
compile Ok
but when i run program after few message boxes ,program just crush ???
Title: Re: rnd(a,b) command?
Post by: Aurel on April 11, 2013, 04:03:27 AM
Finally.. it work fine :)
i do what Peter say ,so i call Randomize() inside function Rand(min,max)
Code: [Select]
! GetTickCount Lib "kernel32.dll" () as sys
sys seed

Function Randomize() as sys
    seed = GetTickCount
End Function

Function Rand(sys z1,z2) as sys
Randomize
    pushad
    sys  rnd
    mov  eax,z2
    sub  eax,z1
    inc  eax
    imul edx,seed,0x8088405
    inc  edx
    mov  seed,edx
    mul  edx
    add  edx,z1
    mov  rnd,edx
    popad
    Return rnd
End Function

print Rand(1,100)

I am wondering is this posible to write without asm code?
Title: Re: random(a,b) with arrays :)
Post by: Frankolinox on April 11, 2013, 04:35:02 AM
1) here's my fixed version for random(a,b) with arrays :-)

that's only "one possible" approach for this task and this works fine here..

Code: [Select]
'
'random test with arrays by frankolinox for oxygenbasic, 11.april.2013
'

print "..new random(a,b) test follows.."
'-----------------------// test // ------------------
function rando(sys*max,sys*min) as long
    '------------- max    
    sys p=@max
        rdtsc
        cdq
        idiv max
        cmp edx, 0
        jge after
        neg edx
    .after:
        mov edx,p        
    return [edx+4] 'max    'that's I fixed ;)
    
    '------------- min    
    sys k=@min
        rdtsc
        cdq        
        idiv min
        cmp edx, 0
        jge after
        neg edx
    .after:        
        mov edx,k
    return [edx+4]
    
end function

indexbase 0

sys aa[12]={100,200,300,400,500,600,700,800,900,1000,1100,1200}
sys ab[31]={10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30}

print "test random function with arrays"
print "ok"
print rando aa[2] ,aa[4] 'result: 400 for indexbase 0
print "ok2"
print rando ab[3] ,ab[5] 'result: 14 for indexbase 0
print "ok3"


2) I am not sure, but I think that's peter example serves with no different values as random function should do. output gives in that example only first parameter back and not different (random) values.

best regards, frank
Title: Re: rnd(a,b) command?
Post by: Emil_halim on April 11, 2013, 07:08:51 AM
Hi Frank,

My i ask you a question .

why you do the job towis , one for max value and other one for min.

for the sake of speed , you can do only one time for a value (max-min) then add min to the result.

here is the example again
Code: [Select]
int Rnd(int max)
{
   int a;
 
      rdtsc          ; call read time-stamp counter instruction
                     ; returns timer value in edx:eax
      cdq            ; convert double word to quad word
                     ; edx:eax <-- sign extension of EAX
      idiv max       ; divide edx:eax by max integer
                     ; stores result in EAX <- Quotient, EDX <- Remainder
                     ; EDX = edx:eax % max
      cmp edx, 0     ; compare value to zero?
                     
      jge after      ; jump if not less than to after: label
      neg edx        ; otherwise, change sign to positive
.after:
      mov a, edx     ; store random number in a
 
   return a;      // return random number
}

macro RndA(min,max)
  rnd(max-min)+min
end macro
       
Title: Re: rnd(a,b) command?
Post by: Emil_halim on April 11, 2013, 07:56:44 AM
Hi Peter,

yes , jge is equal to jnl.

but Oxygen did not support jnl and many of jn... and i have told Mr Charles.

he will complete it.  
Title: Re: rnd(a,b) command?
Post by: Frankolinox on April 11, 2013, 10:25:38 AM
@emil: the macro didn't work here this morning, I don't know why. therefore I tried another way. in this example I adept little for oxygen everything is working fine, I used instead of macro a function. your example didn't work for me at all, so I was searching for another way. now I have installed newer oxygen update and everything is going well and much better. the little devil hides in some details how so often ;)

Code: [Select]
$ filename "rnd2a.exe"
#include "inc\RTL32.inc" '#include "..\..\inc\RTL32.inc"

function rnd(int max) 
   int a
   rdtsc
   cdq
   idiv max
   cmp edx, 0
   jge after
   neg edx
.after:     
   mov a, edx 
return a        '[edx+4]
end function
'------------------- macro doesnt work here correctly ----- //
macro RndAll(min,max) 
rnd(max-min)+min
end macro

'print RndAll(200,300) 'unidentified array or procedure error message!

'------------------- macro doesnt work here correctly ----- //

print "ok"


function rndAllgo(int min,max) 'function works fine!
   return rnd(max-min)+min
end function

print "randomFunction 200-300: " +str(RndAllgo(200,300))

print "first: "+str(Rnd(100))
print "second: "+str(Rnd(500))

print "end of random example"

I am glad that's all working.

@peter: your example is working for me too. don't ask me why, I suppose it's belonging to an old oxygen.dll or my notebook has got a cold ;)

frank
Title: Re: rnd(a,b) command?
Post by: Aurel on April 11, 2013, 12:58:14 PM
Yeah Peter , Randomize ONCE -> work whole day.. ;D

Emil...
Because you like to add comments ,do you can comment this Peter code
for laics like me that will be interesting..
Code: [Select]
Function Rand(sys z1, z2) as sys
    sys    rnd
    mov    eax,z2   ; move z2 to eax
    sub    eax,z1    ; subtract eax - z1
    inc    eax         ; increase eax
    imul   edx,sys_Seed,0x8088405  ; i(what? multiply / you can kill me if i know what is this /)
    inc    edx
    mov    sys_Seed,edx
    mul    edx
    add    edx,z1
    mov    rnd,edx
    return rnd
End Function


Heh ...i just try.. :-\
Title: Re: rnd(a,b) command?
Post by: Charles Pegge on April 11, 2013, 08:05:05 PM
I don't understand exactly how this algorithm works, except that the edx register is overwritten when a 32 bit multiply is performed.  edx takes the upper 32 bits of the product (bits 32..63). so it is rather specific to x86 processors. Very clever though.

http://www.illmob.org/Sources/RobinHood.html
Title: Re: rnd(a,b) command?
Post by: Emil_halim on April 12, 2013, 03:46:29 AM
Aurel ,

here is the comments

first i will demonstrate it then adding the comments.
Quote
we have a Sys_seed variable that holds the returned value of Randomize function , it get a semi random value because it return the timer at any time.

we subtract min value from max value and add 1 to  result . then we multiply this result by 0x8088405
then increasing it by 1 , we store it for next calling, add it to min value and return the rand value.     
 
this is the concept of this code
   

here is the comments
Code: [Select]
Function Rand(sys z1, z2) as sys
    sys    rnd
    mov    eax,z2   ;  Eax = max value
    sub    eax,z1    ;  Eax = eax - min value
    inc    eax         ;  Eax = Eax + 1
    imul   edx,sys_Seed,0x8088405 ; edx = Sys_seed * 0x8088405
    inc    edx
    mov    sys_Seed,edx ; Sys_seed = EDX
    mul    edx                ; Eax = Eax * edx 
    add    edx,z1            ; eax = eax + min value
    mov    rnd,edx         ; rnd = eax
    return rnd               
End Function


Title: Re: rnd(a,b) command?
Post by: Charles Pegge on April 12, 2013, 04:51:25 AM
What I don't understand is how the result is confined within the upper range. Any ideas Emil, Peter?
Title: Re: rnd(a,b) command?
Post by: Emil_halim on April 12, 2013, 05:15:11 AM
hi Charles,

consider the following
Quote
 
    imul op1 , op2 , imm 
eg.
    imul edx , ecx , 100   
will be
   (32 bit) edx  = (32 bit) ecx * 100

that is deffer from this
   mul op
eg.
   mul ebx
will be
   Edx:Eax = Eax * Ebx         ------------ here edx is the upper result.   

Title: Re: rnd(a,b) command?
Post by: Emil_halim on April 12, 2013, 05:21:41 AM
Aurel ,

here is Peter's code with High Level asm , may be better to understand
Code: [Select]
===============================
' Peter's function with HLA
===============================
Function H_Rand(sys z1,z2) as sys
    ^  eax =  z2
    ^  eax -= z1
    ^  eax++
    ^  edx = seed * 0x8088405
    ^  edx++
    ^  seed =  edx
    ^  eax *=  edx
    ^  edx +=  z1
    ^  eax >< edx
    Return eax
End Function

BTW i have made a litle change
Title: Re: rnd(a,b) command?
Post by: Emil_halim on April 12, 2013, 06:23:06 AM

Hi Peter

Quote
machine code isn't that easy, but for an Engineer is it easy.

BTW , I am Engineer , but civil Engineer .  :)

 
Title: Re: rnd(a,b) command?
Post by: Aurel on April 12, 2013, 08:22:47 AM
Heh ..i try to convert Emil comments to pure Basic code
but it looks that i mess up ::)
Code: [Select]
'random basic
! GetTickCount Lib "kernel32.dll" () as sys
sys sys_Seed

Sub Randomize()
    sys_Seed = GetTickCount
End Sub

Function Rand(sys z1, z2) as sys
Randomize()
sys rnd,ex,ed
  ex = z2
  ex = ex-z1
  ex = ex+1
  ed = sys_Seed * 0x8088405
  ed = ed+1
  sys_Seed = ed
  ex = ex * ed
  ex = ex + z1
  rnd = ex
    return rnd
End Function

print Rand(1,100)

Emil do you can fix this..?
Title: Re: rnd(a,b) command?
Post by: Emil_halim on April 12, 2013, 08:55:08 AM
Aurel ,

the problem is here
Quote

^  eax *=  edx

this translated to that

Mul edx

so this asm instruction is better to presented like that

 (64 bits) Edx:Eax = Eax * edx

then edx is the high Dowrd of the quad multiplication 


in your basic code you took the lower Dword of  quad multiplication.

really i do not know how to make it by basic 
Title: Re: rnd(a,b) command?
Post by: Emil_halim on April 12, 2013, 09:25:05 AM
Aurel ,

here it is with basic and small asm code
Code: [Select]
===============================
' Aurel's function with basic
===============================
Function B_Rand(sys z1, z2) as sys
  int Lex,Led
  Lex = z2
  Lex = Lex - z1
  Lex = Lex + 1
  Led = seed * 0x8088405
  Led = Led + 1
  seed = Led
  mov eax , Lex
  mul edx
  Lex = edx + z1
  return Lex
End Function

 
Title: Re: rnd(a,b) command?
Post by: Charles Pegge on April 12, 2013, 07:38:46 PM
We can get close to an equivalent  Basic rand :)

Peter's Orginal:


sys seed

Function Rnd(sys z1,z2) as sys
    pushad
    sys  rand
    mov  eax,z2
    sub  eax,z1
    inc  eax
    imul edx,seed,0x8088405
    inc  edx
    mov  seed,edx
    mul  edx
    add  edx,z1
    mov  rand,edx
    popad
    Return rand
End Function

Intermediate:

function rand(sys z1,z2) as sys
mov eax,z2
sub eax,z1
inc eax
imul edx,seed,0x8088405
inc edx
mov seed,edx
mul edx
add edx,z1
return edx
end function



Basic:

function brnd(sys z1,z2) as sys
seed*=0x8088405+1
eax=z2-z1+1 : mul seed
return edx+z1
end function


seed=12345 : print rnd  1,100 '39
seed=12345 : print rand 1,100 '39
seed=12345 : print brnd 1,100 '39

Charles


Title: Re: rnd(a,b) command?
Post by: Aurel on April 12, 2013, 11:18:05 PM
But Charles...
your code always return 1

Code: [Select]
function brnd(sys z1,z2) as sys
sys seed
seed*=0x8088405+1
eax=z2-z1+1 : mul seed
return edx+z1
end function

print brnd(1,100)
Title: Re: rnd(a,b) command?
Post by: Aurel on April 13, 2013, 12:14:43 AM
Charles did you ever see something like this :
Quote
This isn't asm, but works fine in vb. You get the idea.

Dim startIndex As New String("1234567890")
Dim random As New Random
Dim startIndex1 As New String("0987654321")
Dim random1 As New Random
startIndex = random.Next(startIndex)
startIndex1 = random1.Next(startIndex1)
Dim str1 As String = startIndex
Dim str2 As String = startIndex1
Dim str3 As String = (str1 + str2).Substring(0, 10)
TextBox2.Text = str3
End SubEnd Class
Title: Re: rnd(a,b) command?
Post by: Charles Pegge on April 13, 2013, 01:01:43 AM
Hi Aurel, seed has to be global, not defined inside the brnd function. (sys seed)
Title: Re: rnd(a,b) command?
Post by: Aurel on April 13, 2013, 02:41:24 AM
Quote
Hi Aurel, seed has to be global,
Ok ...
But still return 1

Code: [Select]
sys seed

function brnd(sys z1,z2) as sys
seed*=0x8088405+1
eax=z2-z1+1 : mul seed
return edx+z1
end function

print brnd(1,100)
Title: Re: rnd(a,b) command?
Post by: Charles Pegge on April 13, 2013, 02:48:00 AM
A seed of 0 wont work. You need to start with a large seed to saturate eax.
Title: Re: rnd(a,b) command?
Post by: Frankolinox on April 13, 2013, 02:51:22 AM
aurel take some simple values for seed and try the example again with for example

seed=12345
Code: [Select]
sys seed=12345

function brnd(sys z1,z2) as sys
seed*=0x8088405+1
eax=z2-z1+1 : mul seed
return edx+z1
end function

print brnd(1,100)
print brnd(1,100)

so you will get different values.

@charles: very good your short rnd code example ;) for my openGL fog test I've used longer rand() function and that's working very fine there.

frank
Title: Re: rnd(a,b) command?
Post by: Aurel on April 13, 2013, 02:53:34 AM
Ahhh..oh my i see now..
this work...
Code: [Select]
Declare Function GetTickCount   Lib "kernel32.dll" () As Int
sys seed
seed = GetTickCount
function brnd(sys z1,z2) as sys
seed*=0x8088405+1
eax=z2-z1+1 : mul seed
return edx+z1
end function

print brnd(1,100)