summaryrefslogtreecommitdiff
path: root/Build/source/texk/web2c/mplibdir/mpmathdouble.w
diff options
context:
space:
mode:
authorAkira Kakuto <kakuto@fuk.kindai.ac.jp>2015-10-07 01:43:37 +0000
committerAkira Kakuto <kakuto@fuk.kindai.ac.jp>2015-10-07 01:43:37 +0000
commit4ca2692153042a0c2f7db8d681e190b867ae2faf (patch)
tree5ce3f1b1d2b21911766b40bb856a8279cec96fed /Build/source/texk/web2c/mplibdir/mpmathdouble.w
parent357d78ed0c02ea3e4c41bac6c13f2cdb7c50784c (diff)
web2c/mplibdir: Sync with the upstream.
git-svn-id: svn://tug.org/texlive/trunk@38574 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/web2c/mplibdir/mpmathdouble.w')
-rw-r--r--Build/source/texk/web2c/mplibdir/mpmathdouble.w132
1 files changed, 131 insertions, 1 deletions
diff --git a/Build/source/texk/web2c/mplibdir/mpmathdouble.w b/Build/source/texk/web2c/mplibdir/mpmathdouble.w
index 7a6d99a4aa7..d5663b2df97 100644
--- a/Build/source/texk/web2c/mplibdir/mpmathdouble.w
+++ b/Build/source/texk/web2c/mplibdir/mpmathdouble.w
@@ -1,4 +1,4 @@
-% $Id: mpmathdouble.w 2057 2015-03-20 01:33:59Z luigi $
+% $Id: mpmathdouble.w 2070 2015-10-06 10:35:23Z luigi $
%
% This file is part of MetaPost;
% the MetaPost program is in the public domain.
@@ -64,6 +64,7 @@ static void mp_number_angle_to_scaled (mp_number *A);
static void mp_number_fraction_to_scaled (mp_number *A);
static void mp_number_scaled_to_fraction (mp_number *A);
static void mp_number_scaled_to_angle (mp_number *A);
+static void mp_double_m_unif_rand (MP mp, mp_number *ret, mp_number x_orig);
static void mp_double_m_norm_rand (MP mp, mp_number *ret);
static void mp_double_m_exp (MP mp, mp_number *ret, mp_number x_orig);
static void mp_double_m_log (MP mp, mp_number *ret, mp_number x_orig);
@@ -262,6 +263,7 @@ void * mp_initialize_double_math (MP mp) {
math->n_arg = mp_double_n_arg;
math->m_log = mp_double_m_log;
math->m_exp = mp_double_m_exp;
+ math->m_unif_rand = mp_double_m_unif_rand;
math->m_norm_rand = mp_double_m_norm_rand;
math->pyth_add = mp_double_pyth_add;
math->pyth_sub = mp_double_pyth_sub;
@@ -1215,6 +1217,81 @@ mp_number_to_double(*n_cos), mp_number_to_double(*n_sin));
#endif
}
+@ This is the http://www-cs-faculty.stanford.edu/~uno/programs/rng.c
+with small cosmetic modifications.
+
+@c
+#define KK 100 /* the long lag */
+#define LL 37 /* the short lag */
+#define MM (1L<<30) /* the modulus */
+#define mod_diff(x,y) (((x)-(y))&(MM-1)) /* subtraction mod MM */
+/* */
+static long ran_x[KK]; /* the generator state */
+/* */
+static void ran_array(long aa[],int n) /* put n new random numbers in aa */
+ /* long aa[] destination */
+ /* int n array length (must be at least KK) */
+{
+ register int i,j;
+ for (j=0;j<KK;j++) aa[j]=ran_x[j];
+ for (;j<n;j++) aa[j]=mod_diff(aa[j-KK],aa[j-LL]);
+ for (i=0;i<LL;i++,j++) ran_x[i]=mod_diff(aa[j-KK],aa[j-LL]);
+ for (;i<KK;i++,j++) ran_x[i]=mod_diff(aa[j-KK],ran_x[i-LL]);
+}
+/* */
+/* the following routines are from exercise 3.6--15 */
+/* after calling ran_start, get new randoms by, e.g., "x=ran_arr_next()" */
+/* */
+#define QUALITY 1009 /* recommended quality level for high-res use */
+static long ran_arr_buf[QUALITY];
+static long ran_arr_dummy=-1, ran_arr_started=-1;
+static long *ran_arr_ptr=&ran_arr_dummy; /* the next random number, or -1 */
+/* */
+#define TT 70 /* guaranteed separation between streams */
+#define is_odd(x) ((x)&1) /* units bit of x */
+/* */
+static void ran_start(long seed) /* do this before using ran_array */
+ /* long seed selector for different streams */
+{
+ register int t,j;
+ long x[KK+KK-1]; /* the preparation buffer */
+ register long ss=(seed+2)&(MM-2);
+ for (j=0;j<KK;j++) {
+ x[j]=ss; /* bootstrap the buffer */
+ ss<<=1; if (ss>=MM) ss-=MM-2; /* cyclic shift 29 bits */
+ }
+ x[1]++; /* make x[1] (and only x[1]) odd */
+ for (ss=seed&(MM-1),t=TT-1; t; ) {
+ for (j=KK-1;j>0;j--) x[j+j]=x[j], x[j+j-1]=0; /* "square" */
+ for (j=KK+KK-2;j>=KK;j--)
+ x[j-(KK-LL)]=mod_diff(x[j-(KK-LL)],x[j]),
+ x[j-KK]=mod_diff(x[j-KK],x[j]);
+ if (is_odd(ss)) { /* "multiply by z" */
+ for (j=KK;j>0;j--) x[j]=x[j-1];
+ x[0]=x[KK]; /* shift the buffer cyclically */
+ x[LL]=mod_diff(x[LL],x[KK]);
+ }
+ if (ss) ss>>=1; else t--;
+ }
+ for (j=0;j<LL;j++) ran_x[j+KK-LL]=x[j];
+ for (;j<KK;j++) ran_x[j-LL]=x[j];
+ for (j=0;j<10;j++) ran_array(x,KK+KK-1); /* warm things up */
+ ran_arr_ptr=&ran_arr_started;
+}
+/* */
+#define ran_arr_next() (*ran_arr_ptr>=0? *ran_arr_ptr++: ran_arr_cycle())
+static long ran_arr_cycle(void)
+{
+ if (ran_arr_ptr==&ran_arr_dummy)
+ ran_start(314159L); /* the user forgot to initialize */
+ ran_array(ran_arr_buf,QUALITY);
+ ran_arr_buf[KK]=-1;
+ ran_arr_ptr=ran_arr_buf+1;
+ return ran_arr_buf[0];
+}
+
+
+
@ To initialize the |randoms| table, we call the following routine.
@c
@@ -1237,6 +1314,10 @@ void mp_init_randoms (MP mp, int seed) {
mp_new_randoms (mp);
mp_new_randoms (mp);
mp_new_randoms (mp); /* ``warm up'' the array */
+
+ ran_start((unsigned long) seed);
+
+
}
@ @c
@@ -1255,6 +1336,18 @@ void mp_number_modulo (mp_number *a, mp_number b) {
+@ To consume a random integer for the uniform generator, the program below will say `|next_unif_random|'.
+
+@c
+static void mp_next_unif_random (MP mp, mp_number *ret) {
+ double a;
+ unsigned long int op;
+ (void)mp;
+ op = (unsigned)ran_arr_next();
+ a = op/(MM*1.0);
+ ret->data.dval = a;
+}
+
@ To consume a random fraction, the program below will say `|next_random|'.
@@ -1269,6 +1362,43 @@ static void mp_next_random (MP mp, mp_number *ret) {
}
+@ To produce a uniform random number in the range |0<=u<x| or |0>=u>x|
+or |0=u=x|, given a |scaled| value~|x|, we proceed as shown here.
+
+Note that the call of |take_fraction| will produce the values 0 and~|x|
+with about half the probability that it will produce any other particular
+values between 0 and~|x|, because it rounds its answers.
+
+@c
+static void mp_double_m_unif_rand (MP mp, mp_number *ret, mp_number x_orig) {
+ mp_number y; /* trial value */
+ mp_number x, abs_x;
+ mp_number u;
+ new_fraction (y);
+ new_number (x);
+ new_number (abs_x);
+ new_number (u);
+ mp_number_clone (&x, x_orig);
+ mp_number_clone (&abs_x, x);
+ mp_double_abs (&abs_x);
+ mp_next_unif_random(mp, &u);
+ y.data.dval = abs_x.data.dval * u.data.dval;
+ free_number (u);
+ if (mp_number_equal(y, abs_x)) {
+ mp_number_clone (ret, ((math_data *)mp->math)->zero_t);
+ } else if (mp_number_greater(x, ((math_data *)mp->math)->zero_t)) {
+ mp_number_clone (ret, y);
+ } else {
+ mp_number_clone (ret, y);
+ mp_number_negate (ret);
+ }
+ free_number (abs_x);
+ free_number (x);
+ free_number (y);
+}
+
+
+
@ Finally, a normal deviate with mean zero and unit standard deviation
can readily be obtained with the ratio method (Algorithm 3.4.1R in
{\sl The Art of Computer Programming\/}).