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);