Hi Marc,
a few weeks ago I've reworked a SPL routine based on the Lehmer random number generator which also allows you to limit the random numbers to upper and lower bounds. If no parameters are used, calling rand() returns a random number between 0 and 1, otherwise you'll get a random value within the specified limits.
For initialization, either the srand() function can be called with a start value or is called implicitly to generate a seed which is being calculated using some dynamic values from the sysmaster database. These include session-id, user-id, process-id, thread-id, the time the engine has been running, the number of executed queries and memory blocks in use.
The code has been developed on Informix 14.10 but should probably also run on previous versions as well. Hope this helps.
Any comments are appreciated.
create procedure rand(_min integer default 0,
_max integer default 0,
_DEBUG boolean default "f")
returns float;
define global p_seed integer default 0;
define p_high integer;
define p_low integer;
define p_test integer;
define sessionid integer;
define sql_error integer;
define isam_error integer;
define error_string varchar(255);
on exception
set sql_error, isam_error, error_string
select dbinfo("sessionid")
into sessionid
from systables
where systables.tabname = "systables";
set debug file to "/tmp/" || sessionid || ".debug" with append;
trace "SPL: rand (" || current year to second || ")";
trace "User: " || user;
trace "sql_error = " || sql_error;
trace "isam_error = " || isam_error;
trace "error_string = " || error_string;
trace "_min = " || _min;
trace "_max = " || _max;
trace "p_seed = " || p_seed;
end exception with resume;
if _DEBUG
then set debug file to "/tmp/rand.debug" with append;
trace on;
set explain on;
end if;
if (p_seed = 0)
then call srand(0); -- initialize pseudo random number generator
end if;
let p_high = p_seed / (2147483647 / 48271);
let p_low = mod(p_seed, 2147483647 / 48271);
let p_test = 48271 * p_low - mod(2147483647, 48271) * p_high;
if (p_test > 0)
then let p_seed = p_test;
else let p_seed = p_test + 2147483647;
end if;
if ((_min < _max) and (_max > 0))
then return ((((p_seed / 2147483647) * ((_max - _min) + 1)) + _min)::integer);
else return (p_seed / 2147483647);
end if;
end procedure
create procedure srand(_seed integer default 0,
_DEBUG boolean default "f");
define global p_seed integer default 0;
define p_current integer; -- number of seconds since 1970-01-01 00:00:00
define p_sessionid integer; -- session id
define p_uid integer; -- user id
define p_pid integer; -- process id
define p_tid integer; -- thread id
define p_uptime integer; -- number of seconds since server instance startup
define p_isamtot integer; -- total number of calls
define p_blkused integer; -- number of blocks of used memory
define p_usercpu integer; -- total number of seconds of CPU user time
define sessionid integer;
define sql_error integer;
define isam_error integer;
define error_string varchar(255);
on exception
set sql_error, isam_error, error_string
select dbinfo("sessionid")
into sessionid
from systables
where systables.tabname = "systables";
set debug file to "/tmp/" || sessionid || ".debug" with append;
trace "SPL: srand (" || current year to second || ")";
trace "User: " || user;
trace "sql_error = " || sql_error;
trace "isam_error = " || isam_error;
trace "error_string = " || error_string;
trace "_seed = " || _seed;
trace "p_seed = " || p_seed;
end exception with resume;
if _DEBUG
then set debug file to "/tmp/srand.debug" with append;
trace on;
set explain on;
end if;
if ((_seed = 0) or (p_seed = 0))
then let p_current = nvl(dbinfo("utc_current"), 0);
let p_sessionid = nvl(dbinfo("sessionid"), 0);
let p_uid = nvl((select sysmaster:syssessions.uid
from sysmaster:syssessions
where sysmaster:syssessions.sid = dbinfo("sessionid")), 0);
let p_pid = nvl((select sysmaster:syssessions.pid
from sysmaster:syssessions
where sysmaster:syssessions.sid = dbinfo("sessionid")), 0);
let p_tid = nvl((select max(sysmaster:sysrstcb.tid)
from sysmaster:sysrstcb
where sysmaster:sysrstcb.sid = dbinfo("sessionid")), 0);
let p_uptime = nvl((select sysmaster:sysshmvals.sh_curtime - sysmaster:sysshmvals.sh_boottime
from sysmaster:sysshmvals), 0);
let p_isamtot = nvl((select mod(sysmaster:sysprofile.value, 2147483647)
from sysmaster:sysprofile
where sysmaster:sysprofile.name = "isamtot"), 0);
let p_blkused = nvl((select mod(sum(sysmaster:sysseglst.seg_blkused), 2147483647)
from sysmaster:sysseglst), 0);
let p_usercpu = nvl((select mod(round(sum(sysmaster:sysvpprof.usercpu), 0), 2147483647)
from sysmaster:sysvpprof), 0);
if (p_current > 0)
then if (p_sessionid > 0)
then let p_seed = mod(p_current * p_sessionid, 2147483647);
end if;
if (p_uid > 0)
then let p_seed = mod(mod(p_current * p_uid, 2147483647) * p_seed, 2147483647);
end if;
if (p_pid > 0)
then let p_seed = mod(mod(p_current * p_pid, 2147483647) * p_seed, 2147483647);
end if;
if (p_tid > 0)
then let p_seed = mod(mod(p_current * p_tid, 2147483647) * p_seed, 2147483647);
end if;
if (p_uptime > 0)
then let p_seed = mod(mod(p_current * p_uptime, 2147483647) * p_seed, 2147483647);
end if;
if (p_isamtot > 0)
then let p_seed = mod(mod(p_current * p_isamtot, 2147483647) * p_seed, 2147483647);
end if;
if (p_blkused > 0)
then let p_seed = mod(mod(p_current * p_blkused, 2147483647) * p_seed, 2147483647);
end if;
if (p_usercpu > 0)
then let p_seed = mod(mod(p_current * p_usercpu, 2147483647) * p_seed, 2147483647);
end if;
end if;
if (p_sessionid > 0)
then if (p_uid > 0)
then let p_seed = mod(mod(p_sessionid * p_uid, 2147483647) * p_seed, 2147483647);
end if;
if (p_pid > 0)
then let p_seed = mod(mod(p_sessionid * p_pid, 2147483647) * p_seed, 2147483647);
end if;
if (p_tid > 0)
then let p_seed = mod(mod(p_sessionid * p_tid, 2147483647) * p_seed, 2147483647);
end if;
if (p_uptime > 0)
then let p_seed = mod(mod(p_sessionid * p_uptime, 2147483647) * p_seed, 2147483647);
end if;
if (p_isamtot > 0)
then let p_seed = mod(mod(p_sessionid * p_isamtot, 2147483647) * p_seed, 2147483647);
end if;
if (p_blkused > 0)
then let p_seed = mod(mod(p_sessionid * p_blkused, 2147483647) * p_seed, 2147483647);
end if;
if (p_usercpu > 0)
then let p_seed = mod(mod(p_sessionid * p_usercpu, 2147483647) * p_seed, 2147483647);
end if;
end if;
if (p_uid > 0)
then if (p_pid > 0)
then let p_seed = mod(mod(p_uid * p_pid, 2147483647) * p_seed, 2147483647);
end if;
if (p_tid > 0)
then let p_seed = mod(mod(p_uid * p_tid, 2147483647) * p_seed, 2147483647);
end if;
if (p_uptime > 0)
then let p_seed = mod(mod(p_uid * p_uptime, 2147483647) * p_seed, 2147483647);
end if;
if (p_isamtot > 0)
then let p_seed = mod(mod(p_uid * p_isamtot, 2147483647) * p_seed, 2147483647);
end if;
if (p_blkused > 0)
then let p_seed = mod(mod(p_uid * p_blkused, 2147483647) * p_seed, 2147483647);
end if;
if (p_usercpu > 0)
then let p_seed = mod(mod(p_uid * p_usercpu, 2147483647) * p_seed, 2147483647);
end if;
end if;
if (p_pid > 0)
then if (p_tid > 0)
then let p_seed = mod(mod(p_pid * p_tid, 2147483647) * p_seed, 2147483647);
end if;
if (p_uptime > 0)
then let p_seed = mod(mod(p_pid * p_uptime, 2147483647) * p_seed, 2147483647);
end if;
if (p_isamtot > 0)
then let p_seed = mod(mod(p_pid * p_isamtot, 2147483647) * p_seed, 2147483647);
end if;
if (p_blkused > 0)
then let p_seed = mod(mod(p_pid * p_blkused, 2147483647) * p_seed, 2147483647);
end if;
if (p_usercpu > 0)
then let p_seed = mod(mod(p_pid * p_usercpu, 2147483647) * p_seed, 2147483647);
end if;
end if;
if (p_tid > 0)
then if (p_uptime > 0)
then let p_seed = mod(mod(p_tid * p_uptime, 2147483647) * p_seed, 2147483647);
end if;
if (p_isamtot > 0)
then let p_seed = mod(mod(p_tid * p_isamtot, 2147483647) * p_seed, 2147483647);
end if;
if (p_blkused > 0)
then let p_seed = mod(mod(p_tid * p_blkused, 2147483647) * p_seed, 2147483647);
end if;
if (p_usercpu > 0)
then let p_seed = mod(mod(p_tid * p_usercpu, 2147483647) * p_seed, 2147483647);
end if;
end if;
if (p_uptime > 0)
then if (p_isamtot > 0)
then let p_seed = mod(mod(p_uptime * p_isamtot, 2147483647) * p_seed, 2147483647);
end if;
if (p_blkused > 0)
then let p_seed = mod(mod(p_uptime * p_blkused, 2147483647) * p_seed, 2147483647);
end if;
if (p_usercpu > 0)
then let p_seed = mod(mod(p_uptime * p_usercpu, 2147483647) * p_seed, 2147483647);
end if;
end if;
if (p_isamtot > 0)
then if (p_blkused > 0)
then let p_seed = mod(mod(p_isamtot * p_blkused, 2147483647) * p_seed, 2147483647);
end if;
if (p_usercpu > 0)
then let p_seed = mod(mod(p_isamtot * p_usercpu, 2147483647) * p_seed, 2147483647);
end if;
end if;
if ((p_blkused > 0) and (p_usercpu > 0))
then if (p_usercpu > 0)
then let p_seed = mod(mod(p_blkused * p_usercpu, 2147483647) * p_seed, 2147483647);
end if;
end if;
else let p_seed = _seed;
end if;
end procedure
------------------------------
Roland Wintgen
DBA, Genero/4GL Developer
EVG Martens GmbH & Co. KG
Moenchengladbach
------------------------------
Original Message:
Sent: Tue July 14, 2020 04:11 AM
From: Marc Demhartner
Subject: alternative way to skip installation of DBMS_RANDOM package ?
Thanks for your feedback - i just noticed that DBMS_RANDOM requires to have logging enabled?
------------------------------
Marc Demhartner
Original Message:
Sent: Mon July 13, 2020 10:53 PM
From: SangGyu Jeong
Subject: alternative way to skip installation of DBMS_RANDOM package ?
Hello Marc,
Built-in function for generating random numbers are not provided, so you can write your own routine,
but wouldn't it be better to install and use the DBMS_RANDOM package?
------------------------------
SangGyu Jeong
Software Engineer
Infrasoft
Seoul Korea, Republic of
Original Message:
Sent: Mon July 13, 2020 10:21 AM
From: Marc Demhartner
Subject: alternative way to skip installation of DBMS_RANDOM package ?
Hello everyone,
i´d like ask if you know a good alterantive to install the DBMS_RANDOM package to get a "random" function in informix 14.10FC3
Is there any out of the box way to get a random integer ? How do you solve it ?
Thanks!
------------------------------
Marc Demhartner
------------------------------
#Informix