Added MACS source
[htsworkflow.git] / htswanalysis / MACS / lib / gsl / gsl-1.11 / rng / schrage.c
1 /* rng/schrage.c
2  * Copyright (C) 2003 Carlo Perassi and Heiko Bauke.
3  * 
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 3 of the License, or (at
7  * your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18
19 static inline unsigned long int
20 schrage (unsigned long int a, unsigned long int b, unsigned long int m)
21 {
22   /* This is a modified version of Schrage's method. It ensures that no
23    * overflow or underflow occurs even if a=ceil(sqrt(m)). Usual 
24    * Schrage's method works only until a=floor(sqrt(m)).
25    */
26   unsigned long int q, t;
27   if (a == 0UL)
28     return 0UL;
29   q = m / a;
30   t = 2 * m - (m % a) * (b / q);
31   if (t >= m)
32     t -= m;
33   t += a * (b % q);
34   return (t >= m) ? (t - m) : t;
35 }
36
37 static inline unsigned long int
38 schrage_mult (unsigned long int a, unsigned long int b,
39               unsigned long int m,
40               unsigned long int sqrtm)
41 {
42   /* To multiply a and b use Schrage's method 3 times.
43    * represent a in base ceil(sqrt(m))  a = a1*ceil(sqrt(m)) + a0  
44    * a*b = (a1*ceil(sqrt(m)) + a0)*b = a1*ceil(sqrt(m))*b + a0*b   
45    */
46   unsigned long int t0 = schrage (sqrtm, b, m);
47   unsigned long int t1 = schrage (a / sqrtm, t0, m);
48   unsigned long int t2 = schrage (a % sqrtm, b, m);
49   unsigned long int t = t1 + t2;
50   return (t >= m) ? (t - m) : t;
51 }