Skip to content

Commit

Permalink
- Added better System.*Rand functions based on srandom() and random()
Browse files Browse the repository at this point in the history
git-svn-id: https://openmodelica.org/svn/OpenModelica/trunk@11836 f25d12d1-65f4-0310-ae8a-bbce733d8d8e
  • Loading branch information
sjoelund committed May 2, 2012
1 parent 731cb1b commit f9251d8
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 13 deletions.
19 changes: 13 additions & 6 deletions Compiler/Util/System.mo
Expand Up @@ -915,13 +915,20 @@ function snprintff "sprintf format string that takes one double as argument"
external "C" str=System_snprintff(format,maxlen,val) annotation(Library = {"omcruntime"});
end snprintff;

public function rand
"function: rand
author: Frenkel TUD 2012-04
"
public function realRand
"Returns a value in the intervals (0,1]"
output Real r;

external "C" r = System_rand();
end rand;
external "C" r = SystemImpl_realRand();
end realRand;

public function intRand
"Returns a integer value in the interval (0,n].
The number of possible values is n, the maximum value n-1."
input Integer n;
output Integer i;

external "C" i = SystemImpl_intRand(n);
end intRand;

end System;
5 changes: 0 additions & 5 deletions Compiler/runtime/System_omc.cpp
Expand Up @@ -691,9 +691,4 @@ extern const char* System_snprintff(const char *fmt, int len, double d)
return buf;
}

int System_rand()
{
return rand();
}

}
12 changes: 10 additions & 2 deletions Compiler/runtime/System_rml.c
Expand Up @@ -2058,9 +2058,17 @@ RML_BEGIN_LABEL(System__snprintff)
RML_END_LABEL


RML_BEGIN_LABEL(System__rand)
RML_BEGIN_LABEL(System__intRand)
{
rmlA0 = mk_icon(rand());
rmlA0 = mk_icon(SystemImpl__intRand(RML_UNTAGFIXNUM(rmlA0)));
RML_TAILCALLK(rmlSC);
}
RML_END_LABEL


RML_BEGIN_LABEL(System__realRand)
{
rmlA0 = mk_rcon(SystemImpl__realRand());
RML_TAILCALLK(rmlSC);
}
RML_END_LABEL
52 changes: 52 additions & 0 deletions Compiler/runtime/systemimpl.c
Expand Up @@ -1694,6 +1694,58 @@ extern char* SystemImpl__iconv(const char * str, const char *from, const char *t
return buf;
}

/* NOTES: Randomness provided by random() is guaranteed to be uniform
* (high and low bits are the same).
* rand() does not produce good results and should be avoided. */
static void seed(void)
{
static int init = 0;
if (!init) {
/* /dev/random is usually a good seed; abuse it! */
const char *devrandom = "/dev/random";
if (SystemImpl__regularFileExists(devrandom)) {
int seed=0;
FILE *f = fopen(devrandom, "r");
if (f && (sizeof(int)==fread(&seed,1,sizeof(int),f))) {
srandom(seed);
init = 1;
}
if (f) {
fclose(f);
}
}
if (!init) /* /dev/random failed; use crappy seed */ {
srandom(time(NULL));
init = 1;
}
}
}

/* Returns a value (0,1] */
double SystemImpl__realRand()
{
seed();
return random() / (((double)RAND_MAX)+1);
}

/* Returns an integer (0,n] (i.e. the highest value is n-1) */
int SystemImpl__intRand(int n)
{
unsigned int r;
int m = RAND_MAX % n;
if (n<0 || n>RAND_MAX) return -1 /* Garbage in, garbage out */;
seed();
/*
* Loop until we get something in a uniform range.
* Otherwise some values are more probable than others
*/
while (1) {
r = random();
if (RAND_MAX-(long)r >= m) break;
}
return r % n;
}

#ifdef __cplusplus
}
#endif
Expand Down

0 comments on commit f9251d8

Please sign in to comment.