diff --git a/src/builtin.cmod b/src/builtin.cmod index ba23cc5239eb49b4636fa05e0d6e91f964be2677..d3df7518dad14751fd889d3487d37fd259f88390 100644 --- a/src/builtin.cmod +++ b/src/builtin.cmod @@ -1,5 +1,5 @@ /* -*- c -*- - * $Id: builtin.cmod,v 1.30 2001/06/05 00:03:57 mast Exp $ + * $Id: builtin.cmod,v 1.31 2001/06/05 10:11:52 hubbe Exp $ */ #include "global.h" @@ -556,6 +556,115 @@ PIKEFUN object|program function_object(object|program|function func) +/*! @decl int random(int max) + *! + *! This function returns a random number in the range 0 - @[max]-1. + *! + *! @seealso + *! @[random_seed()] + */ +PIKEFUN mixed random(mixed arg) + efun; + optflags OPT_TRY_OPTIMIZE|OPT_EXTERNAL_DEPEND; + type function(int:int)|function(object:mixed)|function(array(1=mixed):1)|function(mapping(2=mixed:3=mixed):array(2|3))|function(multiset(4=mixed):4)|function(float:float); +{ + switch(arg->type) + { + case T_OBJECT: + pop_n_elems(args-1); + apply(Pike_sp[-1].u.object,"_random",0); + stack_swap(); + pop_stack(); + return; + + case T_INT: + { + INT_TYPE i=arg->u.integer; + pop_n_elems(args); + if(i <= 0) + { + push_int(0); + }else{ + push_int( my_rand() % i); + } + return; + } + + case T_FLOAT: + { + FLOAT_TYPE f=arg->u.float_number; + pop_n_elems(args); + if(f<=0.0) + { + push_float(0.0); + }else{ +#define N 1048576 + push_float(f * (my_rand()%N/((float)N)) + + f * (my_rand()%N/( ((float)N) * ((float)N) ))); + + } + return; + } + + case T_ARRAY: + { + struct array *a=arg->u.array; + if(!a->size) + SIMPLE_BAD_ARG_ERROR("random", 1, "array with elements in it"); + push_svalue(a->item + (my_rand() % a->size)); + stack_swap(); + pop_stack(); + return; + } + + case T_MULTISET: + { + struct multiset *m=arg->u.multiset; + if(!m->ind->size) + SIMPLE_BAD_ARG_ERROR("random", 1, "multiset with elements in it"); + push_svalue(m->ind->item + (my_rand() % m->ind->size)); + stack_swap(); + pop_stack(); + return; + } + + case T_MAPPING: + { + struct mapping *m=arg->u.mapping; + struct mapping_data *md=m->data; + size_t bucket, count; + struct keypair *k; + + if(!m_sizeof(m)) + SIMPLE_BAD_ARG_ERROR("random", 1, "mapping with elements in it"); + + /* Find a random, nonempty bucket */ + bucket=my_rand() % md->hashsize; + while(! md->hash[bucket] ) + if(++bucket > (size_t)md->hashsize) + bucket=0; + + /* Count entries in bucket */ + count=0; + for(k=md->hash[bucket];k;k=k->next) count++; + + /* Select a random entry in this bucket */ + count = my_rand() % count; + k=md->hash[bucket]; + while(count-- > 0) k=k->next; + + /* Push result and return */ + push_svalue(&k->ind); + push_svalue(&k->val); + f_aggregate(2); + stack_swap(); + pop_stack(); + return; + } + } +} + + void init_builtin(void) { INIT diff --git a/src/builtin_functions.c b/src/builtin_functions.c index ef654aedd5643dda13444b3b4787ffec37636a60..50172187dee3201a9d87a16185f53bbbe68cbf85 100644 --- a/src/builtin_functions.c +++ b/src/builtin_functions.c @@ -5,7 +5,7 @@ \*/ /**/ #include "global.h" -RCSID("$Id: builtin_functions.c,v 1.371 2001/06/05 00:01:40 mast Exp $"); +RCSID("$Id: builtin_functions.c,v 1.372 2001/06/05 10:11:52 hubbe Exp $"); #include "interpret.h" #include "svalue.h" #include "pike_macros.h" @@ -474,38 +474,6 @@ PMOD_EXPORT void f_upper_case(INT32 args) } } -/*! @decl int random(int max) - *! - *! This function returns a random number in the range 0 - @[max]-1. - *! - *! @seealso - *! @[random_seed()] - */ -PMOD_EXPORT void f_random(INT32 args) -{ - INT_TYPE i; - - if(args && (Pike_sp[-args].type == T_OBJECT)) - { - pop_n_elems(args-1); - apply(Pike_sp[-1].u.object,"_random",0); - stack_swap(); - pop_stack(); - return; - } - - get_all_args("random",args,"%i",&i); - - if(i <= 0) - { - i = 0; - }else{ - i = my_rand() % i; - } - pop_n_elems(args); - push_int(i); -} - /*! @decl string random_string(int len) *! *! Returns a string of random characters 0-255 with the length @[len]. @@ -7829,10 +7797,6 @@ void init_builtin_efuns(void) ADD_EFUN("query_num_arg",f_query_num_arg, tFunc(tNone,tInt),OPT_EXTERNAL_DEPEND); -/* function(int:int) */ - ADD_EFUN("random",f_random, - tFunc(tInt,tInt),OPT_EXTERNAL_DEPEND); - /* function(int:void) */ ADD_EFUN("random_seed",f_random_seed, tFunc(tInt,tVoid),OPT_SIDE_EFFECT);