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