1#############################################################################
2##
3##  realrandom.gi           IO package
4##                                                        by Max Neunhoeffer
5##
6##  Copyright (C) 2006-2010 by Max Neunhoeffer
7##  This file is free software, see license information at the end.
8##
9##  Code for "real" random sources using /dev/random
10##
11#############################################################################
12
13InstallMethod( Init, "for a real random source",
14  [IsRealRandomSource,IsString], 1,
15  function( r, type )
16    local f;
17    if type <> "random" and type <> "urandom" then
18        Error("seed must be \"random\" or \"urandom\"");
19    fi;
20    if type = "random" then
21        f := IO_File("/dev/random",128);  # Use smaller buffer size
22    else
23        f := IO_File("/dev/urandom",1024);  # Use medium buffer size
24    fi;
25    if f = fail then return fail; fi;
26    r!.file := f;
27    r!.type := type;
28    return r;
29  end );
30
31InstallMethod( State, "for a real random source",
32  [IsRealRandomSource],
33  function(r)
34    return fail;
35  end );
36
37InstallMethod( Reset, "for a real random source",
38  [IsRealRandomSource],
39  function(r)
40    return;
41  end );
42
43InstallMethod( Reset, "for a real random source and an object",
44  [IsRealRandomSource,IsObject],
45  function(r,o)
46    return;
47  end );
48
49InstallMethod( Random, "for a real random source and two integers",
50  [ IsRealRandomSource, IsInt, IsInt ],
51  function( r, f, t )
52    local c,d,h,i,l,q,s;
53    d := t-f;   # we need d+1 different outcomes from [0..d]
54    if d <= 0 then return fail; fi;
55    l := (Log2Int(d)+1);      # now 2^l >= d
56    l := (l+7) - (l+7) mod 8; # this rounds up to a multiple of 8, still 2^l>=d
57    q := QuoInt(2^l,d+1);     # now q*(d+1) <= 2^l < (q+1)*(d+1)
58                              # thus for 0 <= x   < 2^l
59                              # we have  0 <= x/q <= d+1 <= 2^l/q
60                              # Thus if we do QuoInt(x,q) we get something
61                              # between 0 and d inclusively, and if x is
62                              # evenly distributed in [0..2^l-1], all values
63                              # between 0 and d occur equally often
64    repeat
65        s := IO_ReadBlock(r!.file,l/8); # note that l is divisible by 8
66        h := "";
67        for c in s do Append(h,HexStringInt(INT_CHAR(c))); od;
68        i := IntHexString(h);  # this is now between 0 and 2^l-1 inclusively
69        i := QuoInt(i,q);
70    until i <= d;
71    return f+i;
72  end );
73
74InstallMethod( Random, "for a real random source and a list",
75  [ IsRealRandomSource, IsList ],
76  function( r, l )
77    local nr;
78    repeat
79        nr := Random(r,1,Length(l));
80    until IsBound(l[nr]);
81    return l[nr];
82  end );
83
84InstallMethod( ViewObj, "for a real random source",
85  [IsRealRandomSource],
86  function(rs)
87    Print("<a real random source>");
88  end );
89
90InstallMethod( IO_Pickle, "for a real random source",
91  [IsFile, IsRealRandomSource],
92  function(f,rs)
93    if IO_Write(f,"RSRE") = fail then return IO_Error; fi;
94    if IO_Pickle(f,rs!.type) = IO_Error then return IO_Error; fi;
95    return IO_OK;
96  end );
97
98IO_Unpicklers.RSRE := function(f)
99  local t;
100  t := IO_Unpickle(f);
101  if t = IO_Error then return IO_Error; fi;
102  return RandomSource(IsRealRandomSource,t);
103end;
104
105
106##
107##  This program is free software: you can redistribute it and/or modify
108##  it under the terms of the GNU General Public License as published by
109##  the Free Software Foundation, either version 3 of the License, or
110##  (at your option) any later version.
111##
112##  This program is distributed in the hope that it will be useful,
113##  but WITHOUT ANY WARRANTY; without even the implied warranty of
114##  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
115##  GNU General Public License for more details.
116##
117##  You should have received a copy of the GNU General Public License
118##  along with this program.  If not, see <http://www.gnu.org/licenses/>.
119##
120