OME rand seq gen()
From Ingres Community Wiki
Contents |
Introduction
The function returns the next integer in the random sequence. All positive values in the range of the input integer type will be returned before the sequence repeats.
The function could be very useful in building random unique keys.
The rand_seq_gen() function is an implementation of a Linear Shift Register. Roy Hann showed it to me! I think the algorithm comes from E. J. Watson, Primitive Polynomials (Mod 2), Mathematics of Computation, v.16, 1962, p. 368--369.
Written by Martin Bowes.
Syntax
rand_seq_gen((integer1 | integer2 | integer4| integer8) n)
The input parameter may be any of the Ingres Integer types.
Return Value
The value returned will be of the same scale as the input. That is if an int2 item goes in, an int2 item comes out. If an int4 item goes in, an int4 item comes out.
Examples
- update control set next_id=rand_seq_gen(next_id);
- select rand_seq_gen(int1(1)) returns 64.
- select rand_seq_gen(int2(1)) returns 16384.
- select rand_seq_gen(int4(1)) returns 1073741824.
- select rand_seq_gen(int8(1)) returns 4611686018427387904.
FOD
You will need to install the definition UDF_RAND_SEQ_GEN in the fod_id enum set.
And then in the Function_Definitions array place the entry...
static IIADD_FO_DFN Function_Definitions[]={
...
{/* rand_seq_gen() */
II_O_OPERATION, /*fod_object_type*/
{"rand_seq_gen"}, /*fod_name*/
UDF_RAND_SEQ_GEN, /*fod_id*/
II_NORMAL /*fod_type*/
},
};
FIDs
You will need to install UDF_FI_RAND_SEQ_GEN in the fid_id enum set.
The FID also relies on the following array of datatypes...
static II_DT_ID UD_2_INT[] = {II_INTEGER, II_INTEGER};
The FIDs are...
static IIADD_FI_DFN Function_Instances[] = {
...
{
II_O_FUNCTION_INSTANCE, /* fid_object_type */
UDF_FI_RAND_SEQ_GEN, /* fid_id*/
II_NO_FI, /* fid_cmplmnt*/
UDF_RAND_SEQ_GEN, /* fid_opid=fod_id from function definition
** This is the minor sort field for this array
*/
II_NORMAL, /* fid_optype
** This is the major sort field for this array
*/
II_FID_F0_NOFLAGS, /* fid_attributes*/
0, /* fid_wslength*/
1, /* fid_numargs*/
UD_2_INT, /* fid_args, a pointer to an array of datatypes*/
II_INTEGER, /* fid_result, result is an integer*/
II_RES_FIRST, /* fid_rltype*/
II_LEN_UNKNOWN, /* fid_rlength */
0, /* fid_rprec */
rand_seq_gen, /* fid_routine */
0 /* lenspec_routine */
}, /* rand_seq_gen(int) */
Executor Code
II_STATUS
rand_seq_gen (
II_SCB *scb,
II_DATA_VALUE *p1,
II_DATA_VALUE *rdv
) {
int length_of_int;
long long int n;
char msg[256];
rdv->db_prec = 0; /* Set output precision */
/* Now do the deed! */
length_of_int=(int) p1->db_length;
if (p1->db_data) {
switch (length_of_int) {
case 1: n=*(char *) p1->db_data; break;
case 2: n=*(short *) p1->db_data; break;
case 4: n=*(int *) p1->db_data; break;
case 8: n=*(long *) p1->db_data; break;
default:
sprintf(msg,
"rand_seq_gen(): Unexpected integer length %d encountered",
length_of_int);
us_error(scb, 0x200000, msg);
return (II_ERROR);
};
if (n <= 0) {
sprintf(msg,
"rand_seq_gen(%d): Do not call with a negative or zero value",
n);
us_error(scb, 0x200000, msg);
return (II_ERROR);
};
/* I wonder if Roy's bullshitting me on this one! */
switch (length_of_int) {
case 1:
n=n>>1 | ((n^n>>1) & 1) << 6;
*(char *)rdv->db_data = n;
break;
case 2:
n=n>>1 | ((n^n>>2^n>>3^n>>5) & 1) << 14;
*(short *)rdv->db_data = n;
break;
case 4:
n=n>>1 | ((n^n>>3) & 1) << 30;
*(int *)rdv->db_data = n;
break;
case 8:
n=n>>1 | ((n^n>>1) & 1) << 62;
*(long *)rdv->db_data = n;
break;
};
};
return (II_OK);
} /*rand_seq_gen*/
