156 lines
3.5 KiB
C
156 lines
3.5 KiB
C
|
/* $Id$
|
||
|
|
||
|
Part of SWI-Prolog
|
||
|
|
||
|
Author: L.Damas, V.S.Costa, Jan Wielemaker
|
||
|
E-mail: wielemak@science.uva.nl
|
||
|
WWW: http://www.swi-prolog.org
|
||
|
Copyright (C): Universidade do Porto, University of Amsterdam
|
||
|
|
||
|
Original code create for YAP under Artistic license. As this
|
||
|
license is compatible (but less restrictive than) the SWI-Prolog
|
||
|
license we keep the Artistic license.
|
||
|
*/
|
||
|
|
||
|
|
||
|
/*************************************************************************
|
||
|
* *
|
||
|
* YAP Prolog *
|
||
|
* *
|
||
|
* Yap Prolog was developed at NCCUP - Universidade do Porto *
|
||
|
* *
|
||
|
* Copyright L.Damas, V.S.Costa and Universidade do Porto 1985-1997 *
|
||
|
* *
|
||
|
**************************************************************************
|
||
|
* *
|
||
|
* File: random.c *
|
||
|
* Last rev: *
|
||
|
* mods: *
|
||
|
* comments: Random number generation *
|
||
|
* *
|
||
|
*************************************************************************/
|
||
|
|
||
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||
|
Ported to SWI-Prolog by Jan Wielemaker
|
||
|
|
||
|
To compile:
|
||
|
|
||
|
plld -o random -shared -fpic random.c
|
||
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||
|
|
||
|
#include <SWI-Prolog.h>
|
||
|
#include <math.h>
|
||
|
#include <limits.h>
|
||
|
|
||
|
static functor_t FUNCTOR_rand3;
|
||
|
|
||
|
static short a1 = 27314, b1 = 9213, c1 = 17773;
|
||
|
|
||
|
static int
|
||
|
type_error(term_t actual, const char *expected)
|
||
|
{ term_t ex;
|
||
|
|
||
|
if ( (ex = PL_new_term_ref()) &&
|
||
|
PL_unify_term(ex,
|
||
|
PL_FUNCTOR_CHARS, "error", 2,
|
||
|
PL_FUNCTOR_CHARS, "type_error", 2,
|
||
|
PL_CHARS, expected,
|
||
|
PL_TERM, actual,
|
||
|
PL_VARIABLE) )
|
||
|
return PL_raise_exception(ex);
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
static int
|
||
|
domain_error(term_t actual, const char *expected)
|
||
|
{ term_t ex;
|
||
|
|
||
|
if ( (ex = PL_new_term_ref()) &&
|
||
|
PL_unify_term(ex,
|
||
|
PL_FUNCTOR_CHARS, "error", 2,
|
||
|
PL_FUNCTOR_CHARS, "domain_error", 2,
|
||
|
PL_CHARS, expected,
|
||
|
PL_TERM, actual,
|
||
|
PL_VARIABLE) )
|
||
|
return PL_raise_exception(ex);
|
||
|
|
||
|
return FALSE;
|
||
|
}
|
||
|
|
||
|
|
||
|
static int
|
||
|
get_short_ex(term_t t, short *p)
|
||
|
{ long v;
|
||
|
|
||
|
if ( !PL_get_long(t, &v) )
|
||
|
return type_error(t, "integer");
|
||
|
if ( v < SHRT_MIN || v > SHRT_MAX )
|
||
|
return domain_error(t, "short integer");
|
||
|
|
||
|
*p = (short)v;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
|
||
|
static int
|
||
|
get_short_arg_ex(int a, term_t state, short *p)
|
||
|
{ term_t arg = PL_new_term_ref();
|
||
|
|
||
|
_PL_get_arg(a, state, arg);
|
||
|
return get_short_ex(arg, p);
|
||
|
}
|
||
|
|
||
|
|
||
|
static foreign_t
|
||
|
p_random(term_t rnd)
|
||
|
{
|
||
|
double fli;
|
||
|
long int t1, t2, t3;
|
||
|
|
||
|
t1 = (a1 * 171) % 30269;
|
||
|
t2 = (b1 * 172) % 30307;
|
||
|
t3 = (c1 * 170) % 30323;
|
||
|
fli = (t1/30269.0) + (t2/30307.0) + (t3/30323.0);
|
||
|
a1 = (short)t1;
|
||
|
b1 = (short)t2;
|
||
|
c1 = (short)t3;
|
||
|
|
||
|
return PL_unify_float(rnd, fli-(int)(fli));
|
||
|
}
|
||
|
|
||
|
static foreign_t
|
||
|
p_setrand(term_t state)
|
||
|
{ if ( !PL_is_functor(state, FUNCTOR_rand3) )
|
||
|
return type_error(state, "rand_state");
|
||
|
|
||
|
if ( !get_short_arg_ex(1, state, &a1) ||
|
||
|
!get_short_arg_ex(2, state, &b1) ||
|
||
|
!get_short_arg_ex(3, state, &c1) )
|
||
|
return FALSE;
|
||
|
|
||
|
return TRUE;
|
||
|
}
|
||
|
|
||
|
static foreign_t
|
||
|
p_getrand(term_t state)
|
||
|
{ return PL_unify_term(state,
|
||
|
PL_FUNCTOR, FUNCTOR_rand3,
|
||
|
PL_INTEGER, a1,
|
||
|
PL_INTEGER, b1,
|
||
|
PL_INTEGER, c1);
|
||
|
}
|
||
|
|
||
|
|
||
|
install_t
|
||
|
install_random()
|
||
|
{ FUNCTOR_rand3 = PL_new_functor(PL_new_atom("rand"), 3);
|
||
|
|
||
|
PL_register_foreign("random", 1, p_random, 0);
|
||
|
PL_register_foreign("setrand", 1, p_setrand, 0);
|
||
|
PL_register_foreign("getrand", 1, p_getrand, 0);
|
||
|
}
|
||
|
|