Tizen 2.0 Release
[external/tizen-coreutils.git] / lib / randperm.c
1 /* Generate random permutations.
2
3    Copyright (C) 2006, 2007 Free Software Foundation, Inc.
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 2, or (at your option)
8    any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU 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 Foundation,
17    Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
18
19 /* Written by Paul Eggert.  */
20
21 #include <config.h>
22
23 #include "randperm.h"
24
25 #include <limits.h>
26
27 #include "xalloc.h"
28
29 /* Return the ceiling of the log base 2 of N.  If N is zero, return
30    an unspecified value.  */
31
32 static size_t
33 ceil_lg (size_t n)
34 {
35   size_t b = 0;
36   for (n--; n != 0; n /= 2)
37     b++;
38   return b;
39 }
40
41 /* Return an upper bound on the number of random bytes needed to
42    generate the first H elements of a random permutation of N
43    elements.  H must not exceed N.  */
44
45 size_t
46 randperm_bound (size_t h, size_t n)
47 {
48   /* Upper bound on number of bits needed to generate the first number
49      of the permutation.  */
50   size_t lg_n = ceil_lg (n);
51
52   /* Upper bound on number of bits needed to generated the first H elements.  */
53   size_t ar = lg_n * h;
54
55   /* Convert the bit count to a byte count.  */
56   size_t bound = (ar + CHAR_BIT - 1) / CHAR_BIT;
57
58   return bound;
59 }
60
61 /* From R, allocate and return a malloc'd array of the first H elements
62    of a random permutation of N elements.  H must not exceed N.
63    Return NULL if H is zero.  */
64
65 size_t *
66 randperm_new (struct randint_source *r, size_t h, size_t n)
67 {
68   size_t *v;
69
70   switch (h)
71     {
72     case 0:
73       v = NULL;
74       break;
75
76     case 1:
77       v = xmalloc (sizeof *v);
78       v[0] = randint_choose (r, n);
79       break;
80
81     default:
82       {
83         size_t i;
84
85         v = xnmalloc (n, sizeof *v);
86         for (i = 0; i < n; i++)
87           v[i] = i;
88
89         for (i = 0; i < h; i++)
90           {
91             size_t j = i + randint_choose (r, n - i);
92             size_t t = v[i];
93             v[i] = v[j];
94             v[j] = t;
95           }
96
97         v = xnrealloc (v, h, sizeof *v);
98       }
99       break;
100     }
101
102   return v;
103 }