Added script front-end for primer-design code
[htsworkflow.git] / htswanalysis / MACS / lib / gsl / gsl-1.11 / randist / shuffle.c
1 /* randist/shuffle.c
2  * 
3  * Copyright (C) 1996, 1997, 1998, 1999, 2000, 2007 James Theiler, Brian Gough
4  * 
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 3 of the License, or (at
8  * your option) any later version.
9  * 
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  * 
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19
20 #include <config.h>
21 #include <stdlib.h>
22 #include <math.h>
23 #include <gsl/gsl_rng.h>
24 #include <gsl/gsl_randist.h>
25
26 /* Inline swap and copy functions for moving objects around */
27
28 static inline 
29 void swap (void * base, size_t size, size_t i, size_t j)
30 {
31   register char * a = size * i + (char *) base ;
32   register char * b = size * j + (char *) base ;
33   register size_t s = size ;
34
35   if (i == j)
36     return ;
37   
38   do                                            
39     {                                           
40       char tmp = *a;                            
41       *a++ = *b;                                
42       *b++ = tmp;                               
43     } 
44   while (--s > 0);                              
45 }
46
47 static inline void 
48 copy (void * dest, size_t i, void * src, size_t j, size_t size)
49 {
50   register char * a = size * i + (char *) dest ;
51   register char * b = size * j + (char *) src ;
52   register size_t s = size ;
53   
54   do                                            
55     {                                           
56       *a++ = *b++;                              
57     } 
58   while (--s > 0);                              
59 }
60
61 /* Randomly permute (shuffle) N indices
62
63    Supply an array x[N] with nmemb members, each of size size and on
64    return it will be shuffled into a random order.  The algorithm is
65    from Knuth, SemiNumerical Algorithms, v2, p139, who cites Moses and
66    Oakford, and Durstenfeld */
67
68 void
69 gsl_ran_shuffle (const gsl_rng * r, void * base, size_t n, size_t size)
70 {
71   size_t i ;
72
73   for (i = n - 1; i > 0; i--)
74     {
75       size_t j = gsl_rng_uniform_int(r, i+1); /* originally (i + 1) * gsl_rng_uniform (r) */
76
77       swap (base, size, i, j) ;
78     }
79 }
80
81 int
82 gsl_ran_choose (const gsl_rng * r, void * dest, size_t k, void * src, 
83                  size_t n, size_t size)
84 {
85   size_t i, j = 0;
86
87   /* Choose k out of n items, return an array x[] of the k items.
88      These items will prevserve the relative order of the original
89      input -- you can use shuffle() to randomize the output if you
90      wish */
91
92   if (k > n)
93     {
94       GSL_ERROR ("k is greater than n, cannot sample more than n items",
95                  GSL_EINVAL) ;
96     }
97
98   for (i = 0; i < n && j < k; i++)
99     {
100       if ((n - i) * gsl_rng_uniform (r) < k - j)
101         {
102           copy (dest, j, src, i, size) ;
103           j++ ;
104         }
105     }
106
107   return GSL_SUCCESS;
108 }
109
110 void
111 gsl_ran_sample (const gsl_rng * r, void * dest, size_t k, void * src, 
112                 size_t n, size_t size)
113 {
114   size_t i, j = 0;
115
116   /* Choose k out of n items, with replacement */
117
118   for (i = 0; i < k; i++)
119     {
120       j = gsl_rng_uniform_int (r, n);  /* originally n * gsl_rng_uniform (r) */
121
122       copy (dest, i, src, j, size) ;
123     }
124 }