| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
package Crypt::IDA; |
|
2
|
|
|
|
|
|
|
|
|
3
|
2
|
|
|
2
|
|
30603
|
use 5.008008; |
|
|
2
|
|
|
|
|
12
|
|
|
|
2
|
|
|
|
|
88
|
|
|
4
|
2
|
|
|
2
|
|
12
|
use strict; |
|
|
2
|
|
|
|
|
4
|
|
|
|
2
|
|
|
|
|
69
|
|
|
5
|
2
|
|
|
2
|
|
11
|
use warnings; |
|
|
2
|
|
|
|
|
17
|
|
|
|
2
|
|
|
|
|
90
|
|
|
6
|
|
|
|
|
|
|
|
|
7
|
2
|
|
|
2
|
|
12
|
use Carp; |
|
|
2
|
|
|
|
|
3
|
|
|
|
2
|
|
|
|
|
186
|
|
|
8
|
2
|
|
|
2
|
|
11
|
use Fcntl qw(:DEFAULT :seek); |
|
|
2
|
|
|
|
|
5
|
|
|
|
2
|
|
|
|
|
1032
|
|
|
9
|
2
|
|
|
2
|
|
2171
|
use Math::FastGF2 qw(:ops); |
|
|
2
|
|
|
|
|
2428
|
|
|
|
2
|
|
|
|
|
293
|
|
|
10
|
2
|
|
|
2
|
|
2015
|
use Math::FastGF2::Matrix; |
|
|
2
|
|
|
|
|
40773
|
|
|
|
2
|
|
|
|
|
191
|
|
|
11
|
|
|
|
|
|
|
|
|
12
|
2
|
|
|
2
|
|
26
|
use vars qw(@ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION); |
|
|
2
|
|
|
|
|
6
|
|
|
|
2
|
|
|
|
|
25406
|
|
|
13
|
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
require Exporter; |
|
15
|
|
|
|
|
|
|
|
|
16
|
|
|
|
|
|
|
our @export_default = qw(fill_from_string fill_from_fh |
|
17
|
|
|
|
|
|
|
fill_from_file empty_to_string |
|
18
|
|
|
|
|
|
|
empty_to_fh empty_to_file |
|
19
|
|
|
|
|
|
|
ida_split ida_combine); |
|
20
|
|
|
|
|
|
|
our @export_extras = qw(ida_rng_init ida_fisher_yates_shuffle |
|
21
|
|
|
|
|
|
|
ida_generate_key ida_check_key |
|
22
|
|
|
|
|
|
|
ida_key_to_matrix ida_check_transform_opts |
|
23
|
|
|
|
|
|
|
ida_check_list); |
|
24
|
|
|
|
|
|
|
|
|
25
|
|
|
|
|
|
|
our @ISA = qw(Exporter); |
|
26
|
|
|
|
|
|
|
our %EXPORT_TAGS = ( 'default' => [ @export_default ], |
|
27
|
|
|
|
|
|
|
'extras' => [ @export_extras ], |
|
28
|
|
|
|
|
|
|
'all' => [ @export_extras, @export_default ] ); |
|
29
|
|
|
|
|
|
|
our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } ); |
|
30
|
|
|
|
|
|
|
our @EXPORT = qw( ); |
|
31
|
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
our $VERSION = '0.01'; |
|
33
|
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
# hard-coding module names is supposedly not good style, but at least |
|
35
|
|
|
|
|
|
|
# I'm up-front about breaking that "rule": |
|
36
|
|
|
|
|
|
|
our $classname="Crypt::IDA"; |
|
37
|
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
sub fill_from_string { |
|
39
|
|
|
|
|
|
|
# Allow calling as a regular sub call or as a method. This might not |
|
40
|
|
|
|
|
|
|
# be a good style to use, but it allows callers to use either the |
|
41
|
|
|
|
|
|
|
# exported name, as in $f=fill_from_string(...) or to avoid |
|
42
|
|
|
|
|
|
|
# exporting any method names and use the fully-qualified call |
|
43
|
|
|
|
|
|
|
# $f=Crypt::IDA::fill_from_string(...) without needing to worry |
|
44
|
|
|
|
|
|
|
# about the extra class name parameter. Of course, this means that |
|
45
|
|
|
|
|
|
|
# if the user wants to use the class name as the first input |
|
46
|
|
|
|
|
|
|
# parameter, they'll have to specify it twice. A similar pattern is |
|
47
|
|
|
|
|
|
|
# used in other routines in this module. |
|
48
|
16423
|
|
|
16423
|
0
|
11375962
|
my ($self, $class); |
|
49
|
16423
|
100
|
66
|
|
|
79386
|
if ($_[0] eq $classname or ref($_[0]) eq $classname) { |
|
50
|
2
|
|
|
|
|
4
|
$self = shift; |
|
51
|
2
|
|
33
|
|
|
13
|
$class = ref($self) || $self; |
|
52
|
|
|
|
|
|
|
} else { |
|
53
|
|
|
|
|
|
|
# we won't actually use the $self->method() style of calling, but |
|
54
|
|
|
|
|
|
|
# with this pattern we could if we wanted to. |
|
55
|
16421
|
|
|
|
|
19832
|
$self=$classname; |
|
56
|
16421
|
|
|
|
|
19644
|
$class=$classname; |
|
57
|
|
|
|
|
|
|
} |
|
58
|
16423
|
|
|
|
|
26226
|
my $s = shift; |
|
59
|
16423
|
|
100
|
|
|
47983
|
my $align = shift || 1; |
|
60
|
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
# There's a one-line (non-looping) way of doing the following, but |
|
62
|
|
|
|
|
|
|
# writing it as a loop is simpler to understand and hence less prone |
|
63
|
|
|
|
|
|
|
# to errors |
|
64
|
16423
|
|
|
|
|
37258
|
while ((length $s) % $align) { $s.="\0" } |
|
|
21027
|
|
|
|
|
39096
|
|
|
65
|
|
|
|
|
|
|
return { |
|
66
|
|
|
|
|
|
|
SUB => sub { |
|
67
|
34162
|
|
|
34162
|
|
44875
|
my $bytes=shift; |
|
68
|
|
|
|
|
|
|
# substr returns an empty string if input is empty |
|
69
|
34162
|
|
|
|
|
97182
|
return substr $s, 0, $bytes, ""; |
|
70
|
|
|
|
|
|
|
} |
|
71
|
16423
|
|
|
|
|
88823
|
}; |
|
72
|
|
|
|
|
|
|
} |
|
73
|
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
sub empty_to_string { |
|
75
|
24199
|
|
|
24199
|
1
|
2416248
|
my ($self, $class); |
|
76
|
24199
|
50
|
33
|
|
|
113206
|
if ($_[0] eq $classname or ref($_[0]) eq $classname) { |
|
77
|
0
|
|
|
|
|
0
|
$self = shift; |
|
78
|
0
|
|
0
|
|
|
0
|
$class = ref($self) || $self; |
|
79
|
|
|
|
|
|
|
} else { |
|
80
|
24199
|
|
|
|
|
30514
|
$self=$classname; |
|
81
|
24199
|
|
|
|
|
31415
|
$class=$classname; |
|
82
|
|
|
|
|
|
|
} |
|
83
|
24199
|
|
|
|
|
28899
|
my $strref=shift; |
|
84
|
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
return { |
|
86
|
|
|
|
|
|
|
SUB => sub { |
|
87
|
26778
|
|
|
26778
|
|
44450
|
my $str=shift; |
|
88
|
26778
|
|
|
|
|
46023
|
$$strref.=$str; |
|
89
|
26778
|
|
|
|
|
44503
|
return length $str; |
|
90
|
|
|
|
|
|
|
} |
|
91
|
24199
|
|
|
|
|
7397939
|
}; |
|
92
|
|
|
|
|
|
|
} |
|
93
|
|
|
|
|
|
|
|
|
94
|
|
|
|
|
|
|
sub fill_from_fh { |
|
95
|
15
|
|
|
15
|
0
|
16
|
my ($self, $class); |
|
96
|
15
|
50
|
33
|
|
|
89
|
if ($_[0] eq $classname or ref($_[0]) eq $classname) { |
|
97
|
0
|
|
|
|
|
0
|
$self = shift; |
|
98
|
0
|
|
0
|
|
|
0
|
$class = ref($self) || $self; |
|
99
|
|
|
|
|
|
|
} else { |
|
100
|
15
|
|
|
|
|
24
|
$self=$classname; |
|
101
|
15
|
|
|
|
|
17
|
$class=$classname; |
|
102
|
|
|
|
|
|
|
} |
|
103
|
15
|
|
|
|
|
19
|
my $fh=shift; |
|
104
|
15
|
|
100
|
|
|
35
|
my $align=shift || 0; |
|
105
|
15
|
|
100
|
|
|
42
|
my $offset=shift || 0; |
|
106
|
15
|
|
|
|
|
18
|
my $eof=0; |
|
107
|
15
|
|
|
|
|
56
|
my $bytes_read=0; |
|
108
|
|
|
|
|
|
|
|
|
109
|
15
|
100
|
|
|
|
34
|
if ($offset) { sysseek $fh, $offset, SEEK_SET; } |
|
|
9
|
|
|
|
|
32
|
|
|
110
|
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
return { |
|
112
|
|
|
|
|
|
|
SUB => sub { |
|
113
|
34
|
|
|
34
|
|
1236
|
my $bytes = shift; |
|
114
|
34
|
|
|
|
|
45
|
my $buf = ""; |
|
115
|
34
|
50
|
|
|
|
64
|
if ($bytes < 0) { |
|
116
|
0
|
|
|
|
|
0
|
carp "Asked to read $bytes bytes\n"; |
|
117
|
|
|
|
|
|
|
} |
|
118
|
34
|
|
|
|
|
242
|
my $rc = sysread $fh, $buf, $bytes; |
|
119
|
|
|
|
|
|
|
|
|
120
|
34
|
100
|
|
|
|
81
|
if ($rc == 0) { |
|
|
|
50
|
|
|
|
|
|
|
121
|
16
|
100
|
|
|
|
36
|
if ($align) { |
|
122
|
15
|
|
100
|
|
|
54
|
while ($bytes_read % $align and |
|
123
|
|
|
|
|
|
|
length($buf) < $bytes) { |
|
124
|
3
|
|
|
|
|
4
|
$buf.="\0"; |
|
125
|
3
|
|
|
|
|
12
|
++$bytes_read; |
|
126
|
|
|
|
|
|
|
} |
|
127
|
|
|
|
|
|
|
} |
|
128
|
|
|
|
|
|
|
} elsif ($rc < 0) { |
|
129
|
0
|
|
|
|
|
0
|
return undef; |
|
130
|
|
|
|
|
|
|
} else { |
|
131
|
18
|
|
|
|
|
21
|
$bytes_read+=$rc; |
|
132
|
|
|
|
|
|
|
} |
|
133
|
34
|
|
|
|
|
110
|
return $buf; |
|
134
|
|
|
|
|
|
|
} |
|
135
|
15
|
|
|
|
|
400
|
}; |
|
136
|
|
|
|
|
|
|
} |
|
137
|
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
sub fill_from_file { |
|
139
|
15
|
|
|
15
|
0
|
3322
|
my ($self, $class); |
|
140
|
15
|
50
|
33
|
|
|
91
|
if ($_[0] eq $classname or ref($_[0]) eq $classname) { |
|
141
|
0
|
|
|
|
|
0
|
$self = shift; |
|
142
|
0
|
|
0
|
|
|
0
|
$class = ref($self) || $self; |
|
143
|
|
|
|
|
|
|
} else { |
|
144
|
15
|
|
|
|
|
27
|
$self=$classname; |
|
145
|
15
|
|
|
|
|
21
|
$class=$classname; |
|
146
|
|
|
|
|
|
|
} |
|
147
|
15
|
|
|
|
|
20
|
my $filename = shift; |
|
148
|
15
|
|
100
|
|
|
40
|
my $align = shift || 0; |
|
149
|
15
|
|
100
|
|
|
46
|
my $offset = shift || 0; |
|
150
|
15
|
|
|
|
|
17
|
my $fh; |
|
151
|
|
|
|
|
|
|
|
|
152
|
15
|
50
|
|
|
|
556
|
return undef unless (sysopen $fh, $filename, O_RDONLY); |
|
153
|
15
|
|
|
|
|
55
|
return fill_from_fh($fh,$align,$offset); |
|
154
|
|
|
|
|
|
|
} |
|
155
|
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
sub empty_to_fh { |
|
157
|
12
|
|
|
12
|
0
|
16
|
my ($self, $class); |
|
158
|
12
|
100
|
66
|
|
|
63
|
if ($_[0] eq $classname or ref($_[0]) eq $classname) { |
|
159
|
3
|
|
|
|
|
6
|
$self = shift; |
|
160
|
3
|
|
33
|
|
|
15
|
$class = ref($self) || $self; |
|
161
|
|
|
|
|
|
|
} else { |
|
162
|
9
|
|
|
|
|
12
|
$self=$classname; |
|
163
|
9
|
|
|
|
|
11
|
$class=$classname; |
|
164
|
|
|
|
|
|
|
} |
|
165
|
12
|
|
|
|
|
15
|
my $fh = shift; |
|
166
|
12
|
|
100
|
|
|
36
|
my $offset = shift || 0; |
|
167
|
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
#warn "got fh=$fh; offset=$offset\n"; |
|
169
|
12
|
100
|
|
|
|
45
|
sysseek $fh, $offset, SEEK_SET if $offset; |
|
170
|
|
|
|
|
|
|
return { |
|
171
|
|
|
|
|
|
|
SUB => sub { |
|
172
|
12
|
|
|
12
|
|
19
|
my $str=shift; |
|
173
|
12
|
|
|
|
|
355
|
return syswrite $fh, $str; |
|
174
|
|
|
|
|
|
|
} |
|
175
|
12
|
|
|
|
|
87
|
}; |
|
176
|
|
|
|
|
|
|
} |
|
177
|
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
sub empty_to_file { |
|
179
|
3
|
|
|
3
|
1
|
4
|
my ($self, $class); |
|
180
|
3
|
50
|
33
|
|
|
21
|
if ($_[0] eq $classname or ref($_[0]) eq $classname) { |
|
181
|
0
|
|
|
|
|
0
|
$self = shift; |
|
182
|
0
|
|
0
|
|
|
0
|
$class = ref($self) || $self; |
|
183
|
|
|
|
|
|
|
} else { |
|
184
|
3
|
|
|
|
|
6
|
$self=$classname; |
|
185
|
3
|
|
|
|
|
21
|
$class=$classname; |
|
186
|
|
|
|
|
|
|
} |
|
187
|
3
|
|
|
|
|
6
|
my $filename = shift; |
|
188
|
3
|
|
50
|
|
|
15
|
my $perm = shift || 0644; |
|
189
|
3
|
|
50
|
|
|
19
|
my $offset = shift || 0; |
|
190
|
3
|
|
|
|
|
5
|
my $fh; |
|
191
|
|
|
|
|
|
|
|
|
192
|
|
|
|
|
|
|
return undef unless |
|
193
|
3
|
50
|
|
|
|
306
|
sysopen $fh, $filename, O_CREAT | O_WRONLY, $perm; |
|
194
|
3
|
|
|
|
|
19
|
return $self->empty_to_fh($fh, $offset); |
|
195
|
|
|
|
|
|
|
} |
|
196
|
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
# ida_process_streams is the heart of the module. It's called from |
|
198
|
|
|
|
|
|
|
# both ida_split and ida_combine, so it's capable of operating with |
|
199
|
|
|
|
|
|
|
# just one or several fillers/emptiers. Its main purpose is to manage |
|
200
|
|
|
|
|
|
|
# the input/output buffers, and it calls the external matrix multiply |
|
201
|
|
|
|
|
|
|
# code to actually transform blocks of data in large chunks. For |
|
202
|
|
|
|
|
|
|
# efficiency, it has some requirements on the organisation of |
|
203
|
|
|
|
|
|
|
# input/output buffer matrices. It also delegates the task of |
|
204
|
|
|
|
|
|
|
# reading/writing data to relatively simple user-supplied callbacks. |
|
205
|
|
|
|
|
|
|
# This module isn't intended to be called by users directly, though, |
|
206
|
|
|
|
|
|
|
# so it's not even documented in the POD section. Even though |
|
207
|
|
|
|
|
|
|
# technically this could be useful if the user wanted to specify their |
|
208
|
|
|
|
|
|
|
# own input/output matrices, there's so little error-checking of |
|
209
|
|
|
|
|
|
|
# parameters here that it's probably best not to mention its |
|
210
|
|
|
|
|
|
|
# existence/availability. |
|
211
|
|
|
|
|
|
|
sub ida_process_streams { |
|
212
|
6920
|
|
|
6920
|
0
|
7840
|
my ($self, $class); |
|
213
|
6920
|
50
|
33
|
|
|
39920
|
if ($_[0] eq $classname or ref($_[0]) eq $classname) { |
|
214
|
0
|
|
|
|
|
0
|
$self = shift; |
|
215
|
0
|
|
0
|
|
|
0
|
$class = ref($self) || $self; |
|
216
|
|
|
|
|
|
|
} else { |
|
217
|
6920
|
|
|
|
|
9271
|
$self=$classname; |
|
218
|
6920
|
|
|
|
|
8002
|
$class=$classname; |
|
219
|
|
|
|
|
|
|
} |
|
220
|
6920
|
|
|
|
|
25870
|
my ($xform, $in, $fillers, $out, $emptiers, $bytes_to_read, |
|
221
|
|
|
|
|
|
|
$inorder, $outorder)=@_; |
|
222
|
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
# default values are no byte-swapping, read bytes until eof |
|
224
|
6920
|
50
|
|
|
|
14605
|
$inorder=0 unless defined($inorder); |
|
225
|
6920
|
50
|
|
|
|
11443
|
$outorder=0 unless defined($outorder); |
|
226
|
6920
|
50
|
|
|
|
14108
|
$bytes_to_read = 0 unless defined($bytes_to_read); |
|
227
|
|
|
|
|
|
|
|
|
228
|
6920
|
|
|
|
|
8189
|
my $bytes_read=0; |
|
229
|
6920
|
|
|
|
|
11213
|
my ($IR, $OW); # input read, output write pointers |
|
230
|
0
|
|
|
|
|
0
|
my ($ILEN, $OLEN); |
|
231
|
0
|
|
|
|
|
0
|
my ($IFmin, $OFmax); # input and output buffer fill levels |
|
232
|
0
|
|
|
|
|
0
|
my ($want_in_size, $want_out_size); |
|
233
|
|
|
|
|
|
|
|
|
234
|
0
|
|
|
|
|
0
|
my ($eof, $rc, $str, $max_fill, $max_empty); |
|
235
|
6920
|
|
|
|
|
18067
|
my $width=$in->WIDTH; |
|
236
|
6920
|
|
|
|
|
7929
|
my $bits=$width << 3; |
|
237
|
6920
|
|
|
|
|
13478
|
my $rows=$in->ROWS; |
|
238
|
|
|
|
|
|
|
|
|
239
|
6920
|
|
|
|
|
8373
|
my $nfillers = scalar(@$fillers); |
|
240
|
6920
|
|
|
|
|
8263
|
my $nemptiers = scalar(@$emptiers); |
|
241
|
6920
|
|
|
|
|
17963
|
my ($idown,$odown); |
|
242
|
0
|
|
|
|
|
0
|
my ($iright,$oright); |
|
243
|
0
|
|
|
|
|
0
|
my ($rr,$cc); |
|
244
|
0
|
|
|
|
|
0
|
my ($i, $k); |
|
245
|
0
|
|
|
|
|
0
|
my ($start_in_col,$start_out_col); |
|
246
|
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
#warn "-------------------------------------\n"; |
|
248
|
|
|
|
|
|
|
#warn "Asked to process $bytes_to_read bytes\n"; |
|
249
|
|
|
|
|
|
|
#warn "Input cols is " .$in->COLS. ", Output cols is " . $out->COLS . "\n"; |
|
250
|
|
|
|
|
|
|
#warn "Inorder is $inorder, Outorder is $outorder\n"; |
|
251
|
|
|
|
|
|
|
#warn "There are $nfillers fillers, $nemptiers emptiers\n"; |
|
252
|
|
|
|
|
|
|
|
|
253
|
6920
|
50
|
|
|
|
23297
|
if ($bytes_to_read % ($width * $xform->COLS)) { |
|
254
|
0
|
|
|
|
|
0
|
carp "process_streams: bytes to read not a multiple of COLS * WIDTH"; |
|
255
|
0
|
|
|
|
|
0
|
return undef; |
|
256
|
|
|
|
|
|
|
} |
|
257
|
6920
|
50
|
66
|
|
|
23096
|
unless ($nfillers == 1 or $nfillers==$in->ROWS) { |
|
258
|
0
|
|
|
|
|
0
|
carp "Fillers must be 1 or number of input rows"; |
|
259
|
0
|
|
|
|
|
0
|
return undef; |
|
260
|
|
|
|
|
|
|
} |
|
261
|
6920
|
50
|
66
|
|
|
24822
|
unless ($nemptiers == 1 or $nemptiers == $out->ROWS) { |
|
262
|
0
|
|
|
|
|
0
|
carp "Emptiers must be 1 or number of output rows"; |
|
263
|
0
|
|
|
|
|
0
|
return undef; |
|
264
|
|
|
|
|
|
|
} |
|
265
|
|
|
|
|
|
|
|
|
266
|
|
|
|
|
|
|
|
|
267
|
6920
|
|
|
|
|
13320
|
($IFmin, $OFmax, $IR, $OW) = (0,0,0,0); |
|
268
|
6920
|
100
|
|
|
|
16553
|
if ($nfillers == 1) { |
|
269
|
4325
|
50
|
66
|
|
|
13262
|
if ($in->ORG ne "colwise" and $in->ROWS != 1) { |
|
270
|
0
|
|
|
|
|
0
|
carp "Need a 'colwise' input matrix with a single filler"; |
|
271
|
0
|
|
|
|
|
0
|
return undef; |
|
272
|
|
|
|
|
|
|
} |
|
273
|
4325
|
|
|
|
|
37102
|
$ILEN=$rows * $in->COLS * $width; |
|
274
|
4325
|
|
|
|
|
5773
|
$idown=$width; |
|
275
|
4325
|
|
|
|
|
7496
|
$iright=$in->ROWS * $width; |
|
276
|
4325
|
|
|
|
|
5397
|
$want_in_size = $width * $rows; |
|
277
|
|
|
|
|
|
|
} else { |
|
278
|
2595
|
50
|
33
|
|
|
7751
|
if ($in->ORG ne "rowwise" and $in->ROWS != 1) { |
|
279
|
0
|
|
|
|
|
0
|
carp "Need a 'rowwise' input matrix with multiple fillers"; |
|
280
|
0
|
|
|
|
|
0
|
return undef; |
|
281
|
|
|
|
|
|
|
} |
|
282
|
2595
|
|
|
|
|
21823
|
$ILEN=$in->COLS * $width; |
|
283
|
2595
|
|
|
|
|
4044
|
$idown=$ILEN; |
|
284
|
2595
|
|
|
|
|
3584
|
$iright=$width; |
|
285
|
2595
|
|
|
|
|
3370
|
$want_in_size = $width; |
|
286
|
|
|
|
|
|
|
} |
|
287
|
6920
|
|
|
|
|
13835
|
for my $i (0 .. $nfillers - 1) { |
|
288
|
16430
|
|
|
|
|
30113
|
$fillers->[$i]->{"IW" } = $i * $idown; |
|
289
|
16430
|
|
|
|
|
35251
|
$fillers->[$i]->{"END"} = $i * $idown + $ILEN - 1; |
|
290
|
16430
|
|
|
|
|
20587
|
$fillers->[$i]->{"BF"} = 0; |
|
291
|
16430
|
|
|
|
|
33672
|
$fillers->[$i]->{"PART"} = ""; # partial word |
|
292
|
|
|
|
|
|
|
} |
|
293
|
6920
|
100
|
|
|
|
16333
|
if ($nemptiers == 1) { |
|
294
|
3675
|
50
|
66
|
|
|
10943
|
if ($out->ORG ne "colwise" and $out->ROWS != 1) { |
|
295
|
0
|
|
|
|
|
0
|
carp "Need a 'colwise' output matrix with a single emptier"; |
|
296
|
0
|
|
|
|
|
0
|
return undef; |
|
297
|
|
|
|
|
|
|
} |
|
298
|
3675
|
|
|
|
|
33177
|
$OLEN=$out->ROWS * $out->COLS * $width; |
|
299
|
3675
|
|
|
|
|
5849
|
$odown=$width; |
|
300
|
3675
|
|
|
|
|
6936
|
$oright=$out->ROWS * $width; |
|
301
|
3675
|
|
|
|
|
6456
|
$want_out_size = $width * $out->ROWS; |
|
302
|
|
|
|
|
|
|
} else { |
|
303
|
3245
|
50
|
33
|
|
|
9578
|
if ($out->ORG ne "rowwise" and $out->ROWS != 1) { |
|
304
|
0
|
|
|
|
|
0
|
carp "Need a 'rowwise' output matrix with multiple emptiers"; |
|
305
|
0
|
|
|
|
|
0
|
return undef; |
|
306
|
|
|
|
|
|
|
} |
|
307
|
3245
|
|
|
|
|
22402
|
$OLEN = $out->COLS * $width; |
|
308
|
3245
|
|
|
|
|
4128
|
$odown = $OLEN; |
|
309
|
3245
|
|
|
|
|
4222
|
$oright = $width; |
|
310
|
3245
|
|
|
|
|
4662
|
$want_out_size = $width; |
|
311
|
|
|
|
|
|
|
} |
|
312
|
6920
|
|
|
|
|
13483
|
for my $i (0 .. $nemptiers - 1) { |
|
313
|
24210
|
|
|
|
|
37932
|
$emptiers->[$i]->{"OR"} = $i * $odown; |
|
314
|
24210
|
|
|
|
|
37470
|
$emptiers->[$i]->{"END"} = $i * $odown + $OLEN - 1; |
|
315
|
24210
|
|
|
|
|
30999
|
$emptiers->[$i]->{"BF"} = 0; |
|
316
|
24210
|
|
|
|
|
42161
|
$emptiers->[$i]->{"SKIP"} = 0; |
|
317
|
|
|
|
|
|
|
} |
|
318
|
|
|
|
|
|
|
|
|
319
|
6920
|
|
|
|
|
10959
|
do { |
|
320
|
|
|
|
|
|
|
# fill some of the input matrix |
|
321
|
|
|
|
|
|
|
#warn "Checking whether we need input (IFmin=$IFmin)\n"; |
|
322
|
14962
|
|
100
|
|
|
64940
|
while (!$eof and ($IFmin < $want_in_size)) { |
|
323
|
|
|
|
|
|
|
#warn "Seems like we need input\n"; |
|
324
|
14962
|
|
|
|
|
33429
|
for ($i = 0, $IFmin=$ILEN; $i < $nfillers ; ++$i) { |
|
325
|
|
|
|
|
|
|
#warn "IR is $IR, filler ${i}'s IW is " . $fillers->[$i]->{"IW"}. "\n"; |
|
326
|
34174
|
|
|
|
|
55857
|
$max_fill = $ILEN - $fillers->[$i]->{"BF"}; |
|
327
|
34174
|
50
|
|
|
|
74582
|
if ($fillers->[$i]->{"IW"} >= $IR + $i * $idown) { |
|
328
|
34174
|
50
|
|
|
|
83621
|
if ($fillers->[$i]->{"IW"} + $max_fill > |
|
329
|
|
|
|
|
|
|
$fillers->[$i]->{"END"}) { |
|
330
|
34174
|
|
|
|
|
64440
|
$max_fill = $fillers->[$i]->{"END"} - |
|
331
|
|
|
|
|
|
|
$fillers->[$i]->{"IW"} + 1; |
|
332
|
|
|
|
|
|
|
} |
|
333
|
|
|
|
|
|
|
} else { |
|
334
|
0
|
0
|
|
|
|
0
|
if ($fillers->[$i]->{"IW"} + $max_fill >= |
|
335
|
|
|
|
|
|
|
$IR + $i * $idown) { |
|
336
|
0
|
|
|
|
|
0
|
$max_fill = $IR + $i * $idown - $fillers->[$i]->{"IW"}; |
|
337
|
|
|
|
|
|
|
} |
|
338
|
|
|
|
|
|
|
} |
|
339
|
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
#warn "Before adjusting maxfill: $max_fill (bytes read $bytes_read)\n"; |
|
341
|
|
|
|
|
|
|
#warn "BF on filler $i is ". $fillers->[$i]->{"BF"} . "\n"; |
|
342
|
34174
|
100
|
100
|
|
|
101013
|
if ($bytes_to_read and |
|
343
|
|
|
|
|
|
|
($bytes_read + $max_fill > $bytes_to_read)) { |
|
344
|
12235
|
|
|
|
|
14771
|
$max_fill = $bytes_to_read - $bytes_read; |
|
345
|
|
|
|
|
|
|
} |
|
346
|
|
|
|
|
|
|
|
|
347
|
|
|
|
|
|
|
#next unless $max_fill; |
|
348
|
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
#warn "Calling fill handler, maxfill $max_fill\n"; |
|
350
|
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
# Subtract the length of any bytes from partial word read in |
|
352
|
|
|
|
|
|
|
# the last time around. |
|
353
|
34174
|
|
|
|
|
52860
|
$max_fill-=length $fillers->[$i]->{"PART"}; |
|
354
|
34174
|
50
|
|
|
|
60121
|
die "max fill: $max_fill < 0\n" unless $max_fill >= 0; |
|
355
|
|
|
|
|
|
|
|
|
356
|
34174
|
|
|
|
|
75462
|
$str=$fillers->[$i]->{"SUB"}->($max_fill); |
|
357
|
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
#warn "Got input '$str' on row $i, length ". length($str). "\n"; |
|
359
|
|
|
|
|
|
|
|
|
360
|
34174
|
50
|
|
|
|
99635
|
if (!defined($str)) { |
|
|
|
100
|
|
|
|
|
|
|
361
|
0
|
|
|
|
|
0
|
carp "Read error on input stream $!"; |
|
362
|
0
|
|
|
|
|
0
|
return undef; |
|
363
|
|
|
|
|
|
|
} elsif ($str eq "") { |
|
364
|
16430
|
|
|
|
|
20342
|
++$eof; |
|
365
|
|
|
|
|
|
|
} else { |
|
366
|
|
|
|
|
|
|
# setvals must be passed a string that's aligned to width |
|
367
|
|
|
|
|
|
|
# (mainly so that it can do byte-order manipulation). As a |
|
368
|
|
|
|
|
|
|
# result, we need to keep track of any bytes left over from |
|
369
|
|
|
|
|
|
|
# the last call to the fill handler and prepend them to the |
|
370
|
|
|
|
|
|
|
# string to be sent to setvals. We also need to chop off any |
|
371
|
|
|
|
|
|
|
# extra bytes at the end of the string and save them until |
|
372
|
|
|
|
|
|
|
# the next time around. |
|
373
|
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
#warn "Got string '$str' from filler $i\n"; |
|
375
|
|
|
|
|
|
|
#warn "length of str is " . (length($str)) . "\n"; |
|
376
|
|
|
|
|
|
|
|
|
377
|
17744
|
|
|
|
|
35047
|
my $aligned=$fillers->[$i]->{"PART"} . $str; |
|
378
|
17744
|
|
|
|
|
44609
|
$fillers->[$i]->{"PART"}= |
|
379
|
|
|
|
|
|
|
substr $aligned, |
|
380
|
|
|
|
|
|
|
(length($aligned) - (length($aligned) % $width)), |
|
381
|
|
|
|
|
|
|
(length($aligned) % $width), |
|
382
|
|
|
|
|
|
|
""; |
|
383
|
17744
|
50
|
|
|
|
38383
|
die "Alignment problem with filler $i\n" |
|
384
|
|
|
|
|
|
|
if length($aligned) % $width; |
|
385
|
17744
|
50
|
|
|
|
35523
|
die "Alignment problem with fill pointer $i\n" |
|
386
|
|
|
|
|
|
|
if $fillers->[$i]->{"IW"} % $width; |
|
387
|
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
#next unless length $aligned; |
|
389
|
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
#warn "Adding string '$aligned' to input buffer\n"; |
|
391
|
|
|
|
|
|
|
|
|
392
|
17744
|
|
|
|
|
68295
|
$in-> |
|
393
|
|
|
|
|
|
|
setvals($in-> |
|
394
|
|
|
|
|
|
|
offset_to_rowcol($fillers->[$i]->{"IW"}), |
|
395
|
|
|
|
|
|
|
$aligned, |
|
396
|
|
|
|
|
|
|
$inorder); |
|
397
|
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
# For the purpose of updating IW and BF variables, we |
|
399
|
|
|
|
|
|
|
# pretend we didn't see any bytes from partial words |
|
400
|
17744
|
|
|
|
|
678574
|
my $saw_bytes=(length $aligned) - (length($aligned) % $width) ; |
|
401
|
17744
|
|
|
|
|
22911
|
$bytes_read += $saw_bytes; |
|
402
|
17744
|
|
|
|
|
26912
|
$fillers->[$i]->{"BF"} += $saw_bytes; |
|
403
|
17744
|
|
|
|
|
21434
|
$fillers->[$i]->{"IW"} += $saw_bytes; |
|
404
|
17744
|
100
|
|
|
|
45833
|
if ($fillers->[$i]->{"IW"} > $fillers->[$i]->{"END"}) { |
|
405
|
7011
|
|
|
|
|
11693
|
$fillers->[$i]->{"IW"} -= $ILEN; |
|
406
|
|
|
|
|
|
|
} |
|
407
|
|
|
|
|
|
|
} |
|
408
|
34174
|
100
|
|
|
|
103514
|
if ($fillers->[$i]->{"BF"} < $IFmin) { |
|
409
|
11343
|
|
|
|
|
30175
|
$IFmin = $fillers->[$i]->{"BF"}; |
|
410
|
|
|
|
|
|
|
} |
|
411
|
|
|
|
|
|
|
} |
|
412
|
14962
|
100
|
|
|
|
52311
|
if ($eof) { |
|
413
|
6920
|
|
|
|
|
1186012
|
print "EOF detected in $eof stream(s)\n"; |
|
414
|
6920
|
50
|
|
|
|
39123
|
if ($eof % $nfillers) { |
|
415
|
0
|
|
|
|
|
0
|
carp "Not all input streams of same length"; |
|
416
|
0
|
|
|
|
|
0
|
return undef; |
|
417
|
|
|
|
|
|
|
} |
|
418
|
|
|
|
|
|
|
} |
|
419
|
|
|
|
|
|
|
} |
|
420
|
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
# flush some of the output matrix and do some processing |
|
422
|
14962
|
|
66
|
|
|
16492
|
do { |
|
423
|
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
#warn "Checking for output space; OFmax is $OFmax\n"; |
|
425
|
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
# flush output buffer if we need some space |
|
427
|
14962
|
|
100
|
|
|
78727
|
while (($eof && $OFmax) || ($OFmax + $want_out_size > $OLEN)) { |
|
|
|
|
100
|
|
|
|
|
|
428
|
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
#warn "Seems like we needed to flush\n"; |
|
430
|
|
|
|
|
|
|
|
|
431
|
8042
|
|
|
|
|
22376
|
for ($i=0, $OFmax=0; $i < $nemptiers; ++$i) { |
|
432
|
|
|
|
|
|
|
|
|
433
|
26788
|
|
|
|
|
46786
|
$max_empty = $emptiers->[$i]->{"BF"}; |
|
434
|
26788
|
100
|
|
|
|
81407
|
if ($emptiers->[$i]->{"OR"} >= $OW + $i * $odown) { |
|
435
|
11085
|
50
|
|
|
|
35163
|
if ($emptiers->[$i]->{"BF"} + $want_out_size > $OLEN) { |
|
436
|
11085
|
|
|
|
|
21727
|
$max_empty = $emptiers->[$i]->{"END"} - |
|
437
|
|
|
|
|
|
|
$emptiers->[$i]->{"OR"} + 1; |
|
438
|
|
|
|
|
|
|
#warn "Stopping overflow, max_empty is now $max_empty\n"; |
|
439
|
|
|
|
|
|
|
} |
|
440
|
|
|
|
|
|
|
} else { |
|
441
|
15703
|
50
|
|
|
|
41055
|
if ($emptiers->[$i]->{"OR"} + $want_out_size > |
|
442
|
|
|
|
|
|
|
$OW + $i * $odown) { |
|
443
|
|
|
|
|
|
|
#warn "Stopping tail overwrite, max_empty is now $max_empty\n"; |
|
444
|
0
|
|
|
|
|
0
|
$max_empty = |
|
445
|
|
|
|
|
|
|
$OW + $i * $odown - $emptiers->[$i]->{"OR"}; |
|
446
|
|
|
|
|
|
|
# printf ("Stopping tail overwrite, max_empty is now %Ld\n", |
|
447
|
|
|
|
|
|
|
# (long long) max_fill_or_empty); */ |
|
448
|
|
|
|
|
|
|
} |
|
449
|
|
|
|
|
|
|
} |
|
450
|
|
|
|
|
|
|
|
|
451
|
26788
|
50
|
33
|
|
|
115337
|
die "invalid max empty $max_empty\n" |
|
452
|
|
|
|
|
|
|
if $max_empty>0 and $max_empty<$width; |
|
453
|
|
|
|
|
|
|
#next unless $max_empty; |
|
454
|
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
# call handler to empty some data |
|
456
|
|
|
|
|
|
|
#warn "Emptying row $i, col ". |
|
457
|
|
|
|
|
|
|
# ($emptiers->[$i]->{"OR"} % ( $out->COLS * $width)) . |
|
458
|
|
|
|
|
|
|
# " with $max_empty bytes\n"; |
|
459
|
|
|
|
|
|
|
|
|
460
|
26788
|
50
|
|
|
|
65236
|
die "Alignment problem with OR emptier $i" if |
|
461
|
|
|
|
|
|
|
$emptiers->[$i]->{"OR"} % $width; |
|
462
|
26788
|
|
|
|
|
95773
|
($rr,$cc)=$out-> |
|
463
|
|
|
|
|
|
|
offset_to_rowcol($emptiers->[$i]->{"OR"}); |
|
464
|
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
#warn "got (row,col) ($rr,$cc) from OR#$i offset ". |
|
466
|
|
|
|
|
|
|
# $emptiers->[$i]->{"OR"}. "\n"; |
|
467
|
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
# When emptying, we have to check whether the emptier |
|
469
|
|
|
|
|
|
|
# emptied full words. If it emptied part of a word, we have |
|
470
|
|
|
|
|
|
|
# to prevent those bytes that were sent from being sent |
|
471
|
|
|
|
|
|
|
# again. To do this, we keep track of a SKIP variable for |
|
472
|
|
|
|
|
|
|
# each output buffer, which is the number of bytes to skip |
|
473
|
|
|
|
|
|
|
# at the start of the output string. |
|
474
|
|
|
|
|
|
|
|
|
475
|
26788
|
|
|
|
|
450068
|
$str=$out-> |
|
476
|
|
|
|
|
|
|
getvals($rr,$cc, |
|
477
|
|
|
|
|
|
|
$max_empty / $width, |
|
478
|
|
|
|
|
|
|
$outorder); |
|
479
|
|
|
|
|
|
|
#substr $str, 0, $emptiers->[$i]->{"SKIP"}, ""; |
|
480
|
26788
|
|
|
|
|
615122
|
$rc=$emptiers->[$i]->{"SUB"}->($str); |
|
481
|
|
|
|
|
|
|
|
|
482
|
26788
|
50
|
|
|
|
55628
|
unless (defined($rc)) { |
|
483
|
0
|
|
|
|
|
0
|
carp "ERROR: write error $!\n"; |
|
484
|
0
|
|
|
|
|
0
|
return undef; |
|
485
|
|
|
|
|
|
|
} |
|
486
|
|
|
|
|
|
|
#$emptiers->[$i]->{"SKIP"} = $rc % $width; |
|
487
|
|
|
|
|
|
|
#$rc -= $rc % $width; |
|
488
|
26788
|
|
|
|
|
40769
|
$emptiers->[$i]->{"BF"} -= $rc; |
|
489
|
26788
|
|
|
|
|
35388
|
$emptiers->[$i]->{"OR"} += $rc; |
|
490
|
26788
|
100
|
|
|
|
60219
|
if ($emptiers->[$i]->{"OR"} > $emptiers->[$i]->{"END"}) { |
|
491
|
11085
|
|
|
|
|
19843
|
$emptiers->[$i]->{"OR"} -= $OLEN; |
|
492
|
|
|
|
|
|
|
} |
|
493
|
26788
|
50
|
|
|
|
133077
|
if ($emptiers->[$i]->{"BF"} > $OFmax) { |
|
494
|
0
|
|
|
|
|
0
|
$OFmax = $emptiers->[$i]->{"BF"}; |
|
495
|
|
|
|
|
|
|
} |
|
496
|
|
|
|
|
|
|
} |
|
497
|
|
|
|
|
|
|
} |
|
498
|
|
|
|
|
|
|
|
|
499
|
|
|
|
|
|
|
# do some processing |
|
500
|
|
|
|
|
|
|
#warn "Processing: IR=$IR, OW=$OW, IFmin=$IFmin, OFmax=$OFmax\n"; |
|
501
|
14962
|
|
|
|
|
42272
|
($rr,$cc)=$in->offset_to_rowcol($IR); |
|
502
|
14962
|
|
|
|
|
1587456
|
$start_in_col = $cc; |
|
503
|
14962
|
|
|
|
|
44195
|
($rr,$cc)=$out->offset_to_rowcol($OW); |
|
504
|
14962
|
|
|
|
|
207486
|
$start_out_col = $cc; |
|
505
|
14962
|
|
|
|
|
21250
|
$k=int ($IFmin / $want_in_size); |
|
506
|
|
|
|
|
|
|
#warn "k=$k, start_in_col=$start_in_col, start_out_col=$start_out_col\n"; |
|
507
|
14962
|
50
|
|
|
|
42563
|
if ($k + $start_in_col > $in->COLS) { |
|
508
|
0
|
|
|
|
|
0
|
$k = $in->COLS - $start_in_col; |
|
509
|
|
|
|
|
|
|
} |
|
510
|
14962
|
50
|
|
|
|
42586
|
if ($k + $start_out_col > $out->COLS) { |
|
511
|
0
|
|
|
|
|
0
|
$k = $out->COLS - $start_out_col; |
|
512
|
|
|
|
|
|
|
} |
|
513
|
|
|
|
|
|
|
#warn "k is now $k\n"; |
|
514
|
|
|
|
|
|
|
Math::FastGF2::Matrix::multiply_submatrix_c |
|
515
|
14962
|
|
|
|
|
59072
|
($xform, $in, $out, |
|
516
|
|
|
|
|
|
|
0, 0, $xform->ROWS, |
|
517
|
|
|
|
|
|
|
$start_in_col, $start_out_col, $k); |
|
518
|
14962
|
|
|
|
|
19994
|
$IFmin -= $want_in_size * $k; |
|
519
|
14962
|
|
|
|
|
15691
|
$OFmax += $want_out_size * $k; |
|
520
|
14962
|
|
|
|
|
15216
|
$IR+=$iright * $k; |
|
521
|
14962
|
100
|
|
|
|
39870
|
if ($IR > $fillers->[0]->{"END"}) { |
|
522
|
3619
|
|
|
|
|
5147
|
$IR=0; |
|
523
|
|
|
|
|
|
|
} |
|
524
|
14962
|
|
|
|
|
20513
|
$OW+=$oright * $k; |
|
525
|
14962
|
100
|
|
|
|
31919
|
if ($OW > $emptiers->[0]->{"END"}) { |
|
526
|
3619
|
|
|
|
|
4295
|
$OW=0; |
|
527
|
|
|
|
|
|
|
} |
|
528
|
|
|
|
|
|
|
# printf ("Moving to next column: IFmin, OFmax are (%lld, %lld)\n", |
|
529
|
|
|
|
|
|
|
# (long long) IFmin, (long long) OFmax); */ |
|
530
|
|
|
|
|
|
|
|
|
531
|
|
|
|
|
|
|
#warn "Finished processing chunk of $k columns\n"; |
|
532
|
|
|
|
|
|
|
|
|
533
|
|
|
|
|
|
|
# we've been updating IFmin and OFmax, but not the real BF |
|
534
|
|
|
|
|
|
|
# variables in the gf2_streambuf_control structures. We do that |
|
535
|
|
|
|
|
|
|
# after the processing loop is finished. |
|
536
|
|
|
|
|
|
|
|
|
537
|
14962
|
100
|
|
|
|
60849
|
if ($k) { |
|
538
|
8042
|
|
|
|
|
17336
|
for ($i=0; $i < $nfillers; ++$i) { |
|
539
|
17744
|
|
|
|
|
48149
|
$fillers->[$i]->{"BF"} -= $k * $want_in_size; |
|
540
|
|
|
|
|
|
|
} |
|
541
|
8042
|
|
|
|
|
18685
|
for ($i=0; $i < $nemptiers; ++$i) { |
|
542
|
26788
|
|
|
|
|
82722
|
$emptiers->[$i]->{"BF"} += $k * $want_out_size; |
|
543
|
|
|
|
|
|
|
} |
|
544
|
|
|
|
|
|
|
} |
|
545
|
|
|
|
|
|
|
|
|
546
|
|
|
|
|
|
|
} while ($eof && $OFmax); |
|
547
|
|
|
|
|
|
|
} while (!$eof); |
|
548
|
|
|
|
|
|
|
|
|
549
|
6920
|
|
|
|
|
52070
|
return $bytes_read; |
|
550
|
|
|
|
|
|
|
} |
|
551
|
|
|
|
|
|
|
|
|
552
|
|
|
|
|
|
|
sub ida_rng_init { |
|
553
|
3458
|
|
|
3458
|
0
|
58837
|
my ($self, $class); |
|
554
|
3458
|
50
|
33
|
|
|
16526
|
if ($_[0] eq $classname or ref($_[0]) eq $classname) { |
|
555
|
0
|
|
|
|
|
0
|
$self = shift; |
|
556
|
0
|
|
0
|
|
|
0
|
$class = ref($self) || $self; |
|
557
|
|
|
|
|
|
|
} else { |
|
558
|
3458
|
|
|
|
|
3917
|
$self=$classname; |
|
559
|
3458
|
|
|
|
|
4439
|
$class=$classname; |
|
560
|
|
|
|
|
|
|
} |
|
561
|
3458
|
|
|
|
|
5766
|
my $bytes = shift; |
|
562
|
3458
|
|
100
|
|
|
8249
|
my $source = shift || "/dev/urandom"; |
|
563
|
3458
|
|
|
|
|
3304
|
my $fh; |
|
564
|
|
|
|
|
|
|
|
|
565
|
3458
|
50
|
100
|
|
|
16330
|
return undef unless ($bytes == 1 or $bytes == 2 or $bytes == 4); |
|
|
|
|
66
|
|
|
|
|
|
566
|
|
|
|
|
|
|
|
|
567
|
3458
|
50
|
|
|
|
7659
|
if ($source eq "rand") { |
|
568
|
0
|
|
|
|
|
0
|
my $max=256 ** $bytes; |
|
569
|
0
|
|
|
0
|
|
0
|
return sub { int rand $max }; |
|
|
0
|
|
|
|
|
0
|
|
|
570
|
|
|
|
|
|
|
} |
|
571
|
|
|
|
|
|
|
|
|
572
|
3458
|
50
|
|
|
|
222202
|
return undef unless sysopen $fh, $source, O_RDONLY; |
|
573
|
|
|
|
|
|
|
|
|
574
|
|
|
|
|
|
|
# Return an anonymous closure to act as an iterator. Calling the |
|
575
|
|
|
|
|
|
|
# iterator will return an integer in the range 0 .. 2^(8*bytes)-1 |
|
576
|
3458
|
|
|
|
|
6843
|
my $format; |
|
577
|
3458
|
100
|
|
|
|
10338
|
if ($bytes == 1) { |
|
|
|
100
|
|
|
|
|
|
|
578
|
1154
|
|
|
|
|
1786
|
$format="C"; |
|
579
|
|
|
|
|
|
|
} elsif ($bytes == 2) { |
|
580
|
1152
|
|
|
|
|
2021
|
$format="S"; |
|
581
|
|
|
|
|
|
|
} else { |
|
582
|
1152
|
|
|
|
|
2257
|
$format="L"; |
|
583
|
|
|
|
|
|
|
} |
|
584
|
|
|
|
|
|
|
return sub { |
|
585
|
22464
|
|
|
22464
|
|
26186
|
my $deinit=shift; # passing any args will close the |
|
586
|
22464
|
|
|
|
|
26439
|
my $buf; # file, allowing the calling program |
|
587
|
22464
|
50
|
|
|
|
36825
|
if (defined($deinit)) { # to deallocate the iterator without |
|
588
|
0
|
|
|
|
|
0
|
close $fh; # (possibly) leaving an open, but |
|
589
|
0
|
|
|
|
|
0
|
return undef; # inaccessible file handle |
|
590
|
|
|
|
|
|
|
} |
|
591
|
22464
|
50
|
|
|
|
151288
|
if ($bytes != sysread $fh,$buf,$bytes) { |
|
592
|
0
|
|
|
|
|
0
|
die "Fatal Error: not enough bytes in random source!\n"; |
|
593
|
|
|
|
|
|
|
} |
|
594
|
22464
|
|
|
|
|
47087
|
return unpack $format, $buf; |
|
595
|
3458
|
|
|
|
|
29345
|
}; |
|
596
|
|
|
|
|
|
|
}; |
|
597
|
|
|
|
|
|
|
|
|
598
|
|
|
|
|
|
|
sub ida_fisher_yates_shuffle { # based on recipe 4.15 from the |
|
599
|
|
|
|
|
|
|
# Perl Cookbook |
|
600
|
8068
|
|
|
8068
|
0
|
48643
|
my $array=shift; |
|
601
|
|
|
|
|
|
|
|
|
602
|
|
|
|
|
|
|
# Note that this uses plain old rand rather than our high-quality |
|
603
|
|
|
|
|
|
|
# RNG. If that is a problem, either replace this rand with a better |
|
604
|
|
|
|
|
|
|
# alternative or avoid having this function called by using more |
|
605
|
|
|
|
|
|
|
# than 1 byte-security. Since we're using the random variables to |
|
606
|
|
|
|
|
|
|
# generate a permutation, the actual numbers chosen won't be |
|
607
|
|
|
|
|
|
|
# revealed, so it should be a little more difficult for an attacker |
|
608
|
|
|
|
|
|
|
# to guess the sequence used (and hence make better guesses about |
|
609
|
|
|
|
|
|
|
# the random values for the other shares). I can't say either way |
|
610
|
|
|
|
|
|
|
# whether this will be a problem in practice, but it might be a good |
|
611
|
|
|
|
|
|
|
# idea to shuffle the array a second time if attacking rand is a |
|
612
|
|
|
|
|
|
|
# worry. Since an attacker won't have access to all the shares, |
|
613
|
|
|
|
|
|
|
# this should destroy or limit his ability to determine the order in |
|
614
|
|
|
|
|
|
|
# which the numbers were generated. Shuffling a list of high-quality |
|
615
|
|
|
|
|
|
|
# random numbers (such as from the rng_init function) with a |
|
616
|
|
|
|
|
|
|
# poor-quality rand-based shuffle should not leak any extra |
|
617
|
|
|
|
|
|
|
# information, while using two passes with the rand-based shuffler |
|
618
|
|
|
|
|
|
|
# (effectively one to select elements, the other to shuffle them) |
|
619
|
|
|
|
|
|
|
# seems like it should improve security. |
|
620
|
|
|
|
|
|
|
|
|
621
|
|
|
|
|
|
|
# Change recipe to allow picking a certain number of elements |
|
622
|
8068
|
|
|
|
|
10916
|
my $picks=shift; |
|
623
|
8068
|
100
|
66
|
|
|
44022
|
$picks=scalar(@$array) unless |
|
|
|
|
100
|
|
|
|
|
|
624
|
|
|
|
|
|
|
defined($picks) and $picks >=0 and $picks
|
|
625
|
|
|
|
|
|
|
|
|
626
|
8068
|
|
|
|
|
10433
|
my $i=scalar(@$array); |
|
627
|
8068
|
|
|
|
|
18204
|
while (--$i > $picks - scalar(@$array)) { |
|
628
|
633756
|
|
|
|
|
825445
|
my $j=int rand ($i + 1); # random int from [0,$i] |
|
629
|
633756
|
100
|
|
|
|
1048231
|
next if $i==$j; # don't swap element with itself |
|
630
|
613635
|
|
|
|
|
1518604
|
@$array[$i,$j]=@$array[$j,$i] |
|
631
|
|
|
|
|
|
|
} |
|
632
|
|
|
|
|
|
|
# If we want fewer picks than are in the full list, then truncate |
|
633
|
|
|
|
|
|
|
# the list by shifting off some elements from the front. This |
|
634
|
|
|
|
|
|
|
# destruction of the list may not be a good thing in general, but |
|
635
|
|
|
|
|
|
|
# it's fine for our purposes in this program. Note that this tail |
|
636
|
|
|
|
|
|
|
# processing effectively brings the algorithm up to O(n), where n is |
|
637
|
|
|
|
|
|
|
# the list length, but we still save out on the more expensive calls |
|
638
|
|
|
|
|
|
|
# to rand and the element-swapping for elements we'll never |
|
639
|
|
|
|
|
|
|
# select. Using mjd-permute might be a marginally better choice |
|
640
|
|
|
|
|
|
|
# where there are many unused elements, but since we're only |
|
641
|
|
|
|
|
|
|
# interested in using this with arrays of up to 256 elements, this |
|
642
|
|
|
|
|
|
|
# will be fine. |
|
643
|
|
|
|
|
|
|
# |
|
644
|
8068
|
|
|
|
|
20146
|
while (scalar(@$array) > $picks) { |
|
645
|
291956
|
|
|
|
|
488504
|
shift @$array; # using splice() is quicker! |
|
646
|
|
|
|
|
|
|
} |
|
647
|
|
|
|
|
|
|
# splice @$array, 0, scalar @$array - $picks; |
|
648
|
|
|
|
|
|
|
}; |
|
649
|
|
|
|
|
|
|
|
|
650
|
|
|
|
|
|
|
sub ida_check_key { |
|
651
|
1
|
|
|
1
|
0
|
2
|
my ($self, $class); |
|
652
|
1
|
50
|
33
|
|
|
9
|
if ($_[0] eq $classname or ref($_[0]) eq $classname) { |
|
653
|
0
|
|
|
|
|
0
|
$self = shift; |
|
654
|
0
|
|
0
|
|
|
0
|
$class = ref($self) || $self; |
|
655
|
|
|
|
|
|
|
} else { |
|
656
|
1
|
|
|
|
|
2
|
$self=$classname; |
|
657
|
1
|
|
|
|
|
3
|
$class=$classname; |
|
658
|
|
|
|
|
|
|
} |
|
659
|
1
|
|
|
|
|
3
|
my ($k,$n,$w,$key)=@_; |
|
660
|
|
|
|
|
|
|
|
|
661
|
|
|
|
|
|
|
# Check that key generated by the algorithm (or supplied by the |
|
662
|
|
|
|
|
|
|
# user) has the properties required for linear independence. |
|
663
|
|
|
|
|
|
|
# |
|
664
|
|
|
|
|
|
|
# The key supplied is a list of distinct numbers in the order |
|
665
|
|
|
|
|
|
|
# x1,...,xn,y1,...,yk |
|
666
|
|
|
|
|
|
|
|
|
667
|
1
|
50
|
|
|
|
4
|
die "No key elements to check\n" unless defined $key; |
|
668
|
|
|
|
|
|
|
|
|
669
|
1
|
50
|
|
|
|
11
|
die "Supplied key for generating matrix is of the wrong size" |
|
670
|
|
|
|
|
|
|
unless scalar(@$key) == $k + $n; |
|
671
|
|
|
|
|
|
|
|
|
672
|
1
|
|
|
|
|
3
|
my %values; |
|
673
|
|
|
|
|
|
|
|
|
674
|
|
|
|
|
|
|
# For integer values xi, yj mod a prime p, the conditons that must |
|
675
|
|
|
|
|
|
|
# be satisfied are... |
|
676
|
|
|
|
|
|
|
# xi + yj != 0 | |
|
677
|
|
|
|
|
|
|
# i != j -> xi != xj } for all i,j |
|
678
|
|
|
|
|
|
|
# i != j -> yi != yj | |
|
679
|
|
|
|
|
|
|
# |
|
680
|
|
|
|
|
|
|
# For calculations in GF_2, since each number is its own additive |
|
681
|
|
|
|
|
|
|
# inverse, these conditions can be achieved by stating that all |
|
682
|
|
|
|
|
|
|
# numbers must be distinct. |
|
683
|
1
|
|
|
|
|
4
|
foreach my $v (@$key) { |
|
684
|
6
|
50
|
|
|
|
61
|
return 1 if $v >= 256 ** $w; |
|
685
|
6
|
50
|
|
|
|
14
|
return 1 if exists($values{$v}); # failure; duplicate value |
|
686
|
6
|
|
|
|
|
19
|
$values{$v}=1; |
|
687
|
|
|
|
|
|
|
} |
|
688
|
1
|
|
|
|
|
9
|
return 0; # success; all values distinct |
|
689
|
|
|
|
|
|
|
}; |
|
690
|
|
|
|
|
|
|
|
|
691
|
|
|
|
|
|
|
sub ida_generate_key { |
|
692
|
3458
|
|
|
3458
|
0
|
4170
|
my ($self, $class); |
|
693
|
3458
|
50
|
33
|
|
|
17282
|
if ($_[0] eq $classname or ref($_[0]) eq $classname) { |
|
694
|
0
|
|
|
|
|
0
|
$self = shift; |
|
695
|
0
|
|
0
|
|
|
0
|
$class = ref($self) || $self; |
|
696
|
|
|
|
|
|
|
} else { |
|
697
|
3458
|
|
|
|
|
5092
|
$self=$classname; |
|
698
|
3458
|
|
|
|
|
4673
|
$class=$classname; |
|
699
|
|
|
|
|
|
|
} |
|
700
|
|
|
|
|
|
|
|
|
701
|
3458
|
|
|
|
|
6399
|
my ($k,$n,$w,$rng)=@_; |
|
702
|
3458
|
|
|
|
|
6312
|
my $key=[]; |
|
703
|
|
|
|
|
|
|
|
|
704
|
|
|
|
|
|
|
# Generate an array of $k + $n distinct random values, each in the |
|
705
|
|
|
|
|
|
|
# range [0..256**$w) |
|
706
|
|
|
|
|
|
|
|
|
707
|
|
|
|
|
|
|
# If the width is 1 byte, then we'll use the Fisher-Yates shuffle to |
|
708
|
|
|
|
|
|
|
# choose distinct numbers in the range [0,255]. This takes only |
|
709
|
|
|
|
|
|
|
# O($k+$n) steps and requires O(256) storage. If the width is 2 or |
|
710
|
|
|
|
|
|
|
# more bytes, the Fisher-Yates shuffle would require too much memory |
|
711
|
|
|
|
|
|
|
# (O(2**16), O(2**24), etc.), so we use a different algorithm which |
|
712
|
|
|
|
|
|
|
# uses the rng to generate the numbers directly, checking for |
|
713
|
|
|
|
|
|
|
# duplicates as it goes, and re-rolling whenever dups are found. |
|
714
|
3458
|
100
|
|
|
|
6661
|
if ($w == 1) { |
|
715
|
1154
|
|
|
|
|
311251
|
push @$key,(0..255); |
|
716
|
1154
|
|
|
|
|
3176
|
ida_fisher_yates_shuffle($key,$k + $n); |
|
717
|
|
|
|
|
|
|
} else { |
|
718
|
2304
|
|
|
|
|
2958
|
my (%rolled,$r); |
|
719
|
2304
|
|
|
|
|
3249
|
my $count=$k+$n; |
|
720
|
2304
|
|
|
|
|
5122
|
while ($count) { |
|
721
|
22464
|
|
|
|
|
35778
|
$r=$rng->(); |
|
722
|
22464
|
50
|
|
|
|
48330
|
next if exists($rolled{$r}); |
|
723
|
22464
|
|
|
|
|
42893
|
$rolled{$r}=1; |
|
724
|
22464
|
|
|
|
|
43885
|
push @$key,$r; |
|
725
|
22464
|
|
|
|
|
45283
|
--$count; |
|
726
|
|
|
|
|
|
|
} |
|
727
|
|
|
|
|
|
|
} |
|
728
|
|
|
|
|
|
|
|
|
729
|
|
|
|
|
|
|
# do a final shuffle of the elements. This should help guard against |
|
730
|
|
|
|
|
|
|
# exploiting weaknesses in either random generator, but particularly |
|
731
|
|
|
|
|
|
|
# the 1-byte version which uses the system's rand function. The |
|
732
|
|
|
|
|
|
|
# extra security derives from the fact that consecutively-generated |
|
733
|
|
|
|
|
|
|
# numbers will likely end up being distributed to different parties, |
|
734
|
|
|
|
|
|
|
# so it should no longer be possible for an attacker to determine |
|
735
|
|
|
|
|
|
|
# the order in which the rng generated them without actually |
|
736
|
|
|
|
|
|
|
# collecting all the shares (which would avoid the need to attack |
|
737
|
|
|
|
|
|
|
# the rng in the first place). |
|
738
|
3458
|
|
|
|
|
10298
|
ida_fisher_yates_shuffle($key); |
|
739
|
3458
|
|
|
|
|
8690
|
return $key; |
|
740
|
|
|
|
|
|
|
}; |
|
741
|
|
|
|
|
|
|
|
|
742
|
|
|
|
|
|
|
sub ida_check_list { |
|
743
|
|
|
|
|
|
|
|
|
744
|
|
|
|
|
|
|
# Check a given listref to make sure it has no dups and that all |
|
745
|
|
|
|
|
|
|
# values are within range. Returns the list less any deleted |
|
746
|
|
|
|
|
|
|
# elements, as well as doing an in-place delete on the passed |
|
747
|
|
|
|
|
|
|
# listref. |
|
748
|
|
|
|
|
|
|
|
|
749
|
3461
|
|
|
3461
|
0
|
6241
|
my ($list,$item,$min,$max)=@_; |
|
750
|
|
|
|
|
|
|
|
|
751
|
3461
|
|
|
|
|
6285
|
my $new_list=[]; # list without dups, invalid values |
|
752
|
3461
|
|
|
|
|
9882
|
my @saw_val=((0) x $max); |
|
753
|
3461
|
|
|
|
|
7093
|
for my $i (@$list) { |
|
754
|
20751
|
50
|
33
|
|
|
87843
|
if ($saw_val[$i]) { |
|
|
|
50
|
|
|
|
|
|
|
755
|
0
|
|
|
|
|
0
|
carp "Duplicate $item number $i in ${item}list; ignoring"; |
|
756
|
|
|
|
|
|
|
} elsif ($i < $min or $i > $max) { |
|
757
|
0
|
|
|
|
|
0
|
carp "$item number $i out of range in ${item}list; ignoring."; |
|
758
|
|
|
|
|
|
|
} else { |
|
759
|
20751
|
|
|
|
|
20502
|
++$saw_val[$i]; |
|
760
|
20751
|
|
|
|
|
37860
|
push @$new_list, $i; |
|
761
|
|
|
|
|
|
|
} |
|
762
|
|
|
|
|
|
|
} |
|
763
|
3461
|
|
|
|
|
11412
|
$list=$new_list; |
|
764
|
|
|
|
|
|
|
} |
|
765
|
|
|
|
|
|
|
|
|
766
|
|
|
|
|
|
|
sub ida_check_transform_opts { |
|
767
|
|
|
|
|
|
|
|
|
768
|
|
|
|
|
|
|
# Return 0 for success, or 1 otherwise. Fixes sharelist if it had |
|
769
|
|
|
|
|
|
|
# any duplicate or out-of-range vales |
|
770
|
|
|
|
|
|
|
|
|
771
|
10381
|
|
|
10381
|
0
|
14043
|
my ($self,$class); |
|
772
|
10381
|
50
|
33
|
|
|
43755
|
if ($_[0] eq $classname or ref($_[0]) eq $classname) { |
|
773
|
0
|
|
|
|
|
0
|
$self=shift; |
|
774
|
0
|
|
|
|
|
0
|
$class=ref($self); |
|
775
|
|
|
|
|
|
|
} else { |
|
776
|
10381
|
|
|
|
|
14339
|
$self=$classname; |
|
777
|
|
|
|
|
|
|
} |
|
778
|
10381
|
|
|
|
|
81877
|
my %o= ( |
|
779
|
|
|
|
|
|
|
"quorum" => undef, |
|
780
|
|
|
|
|
|
|
"shares" => undef, |
|
781
|
|
|
|
|
|
|
"width" => undef, |
|
782
|
|
|
|
|
|
|
"sharelist" => undef, |
|
783
|
|
|
|
|
|
|
"key" => undef, |
|
784
|
|
|
|
|
|
|
"matrix" => undef, |
|
785
|
|
|
|
|
|
|
@_); |
|
786
|
62286
|
50
|
|
|
|
164924
|
my ($k,$n,$w,$sharelist,$key,$mat) = |
|
787
|
|
|
|
|
|
|
map { |
|
788
|
10381
|
|
|
|
|
17441
|
exists($o{$_}) ? $o{$_} : undef; |
|
789
|
|
|
|
|
|
|
} qw(quorum shares width sharelist key matrix); |
|
790
|
|
|
|
|
|
|
|
|
791
|
10381
|
50
|
66
|
|
|
44381
|
if (defined($key) and defined($mat)) { |
|
792
|
0
|
|
|
|
|
0
|
carp "both key and matrix parameters supplied; use one only"; |
|
793
|
0
|
|
|
|
|
0
|
return 1; |
|
794
|
|
|
|
|
|
|
} |
|
795
|
10381
|
100
|
|
|
|
26818
|
if (defined($key)) { |
|
796
|
3459
|
50
|
33
|
|
|
21841
|
unless (defined ($n) and defined ($sharelist)) { |
|
797
|
0
|
|
|
|
|
0
|
carp "If a key is supplied, must specify shares and sharelist"; |
|
798
|
0
|
|
|
|
|
0
|
return 1; |
|
799
|
|
|
|
|
|
|
} |
|
800
|
3459
|
50
|
33
|
|
|
18277
|
unless (ref($key) and scalar(@$key) == $k + $n) { |
|
801
|
0
|
|
|
|
|
0
|
carp "key must be a reference to a list of $k + $n elements"; |
|
802
|
0
|
|
|
|
|
0
|
return 1; |
|
803
|
|
|
|
|
|
|
} |
|
804
|
|
|
|
|
|
|
} |
|
805
|
10381
|
100
|
|
|
|
20653
|
if (defined($mat)) { |
|
806
|
3465
|
50
|
|
|
|
8922
|
if ( ref($mat) ne "Math::FastGF2::Matrix") { |
|
807
|
0
|
|
|
|
|
0
|
carp "Matrix must be of type Math::FastGF2::Matrix"; |
|
808
|
0
|
|
|
|
|
0
|
return 1; |
|
809
|
|
|
|
|
|
|
} |
|
810
|
3465
|
50
|
|
|
|
10741
|
if ($mat->ORG ne "rowwise") { |
|
811
|
0
|
|
|
|
|
0
|
carp "supplied matrix must use 'rowwise' organisation"; |
|
812
|
0
|
|
|
|
|
0
|
return undef; |
|
813
|
|
|
|
|
|
|
} |
|
814
|
3465
|
50
|
33
|
|
|
37412
|
if (($mat->ROWS != $n or $mat->COLS != $k)) { |
|
815
|
0
|
|
|
|
|
0
|
carp "supplied matrix must be $n rows x $k cols"; |
|
816
|
0
|
|
|
|
|
0
|
return 1; |
|
817
|
|
|
|
|
|
|
} |
|
818
|
|
|
|
|
|
|
} |
|
819
|
10381
|
100
|
|
|
|
19288
|
if (defined($sharelist)) { |
|
820
|
3460
|
|
|
|
|
11491
|
ida_check_list($sharelist,"share",0,$n-1); |
|
821
|
3460
|
50
|
|
|
|
8825
|
unless (scalar(@$sharelist) > 0) { |
|
822
|
0
|
|
|
|
|
0
|
carp "sharelist does not contain any valid share numbers; aborting"; |
|
823
|
0
|
|
|
|
|
0
|
return 1; |
|
824
|
|
|
|
|
|
|
} |
|
825
|
|
|
|
|
|
|
} |
|
826
|
|
|
|
|
|
|
|
|
827
|
10381
|
|
|
|
|
62322
|
return 0; |
|
828
|
|
|
|
|
|
|
} |
|
829
|
|
|
|
|
|
|
|
|
830
|
|
|
|
|
|
|
sub ida_key_to_matrix { |
|
831
|
3458
|
|
|
3458
|
0
|
4786
|
my ($self,$class); |
|
832
|
3458
|
50
|
33
|
|
|
17991
|
if ($_[0] eq $classname or ref($_[0]) eq $classname) { |
|
833
|
0
|
|
|
|
|
0
|
$self=shift; |
|
834
|
0
|
|
|
|
|
0
|
$class=ref($self); |
|
835
|
|
|
|
|
|
|
} else { |
|
836
|
3458
|
|
|
|
|
5320
|
$self=$classname; |
|
837
|
|
|
|
|
|
|
} |
|
838
|
3458
|
|
|
|
|
43043
|
my %o= ( |
|
839
|
|
|
|
|
|
|
"quorum" => undef, |
|
840
|
|
|
|
|
|
|
"shares" => undef, |
|
841
|
|
|
|
|
|
|
"width" => undef, |
|
842
|
|
|
|
|
|
|
"sharelist" => undef, |
|
843
|
|
|
|
|
|
|
"key" => undef, |
|
844
|
|
|
|
|
|
|
"invert?" => 0, # want us to invert the matrix? |
|
845
|
|
|
|
|
|
|
"skipchecks?" => 0, # skip long checks on options? |
|
846
|
|
|
|
|
|
|
@_, |
|
847
|
|
|
|
|
|
|
); |
|
848
|
24206
|
50
|
|
|
|
66446
|
my ($k,$n,$w,$sharelist,$key,$invert,$skipchecks) = |
|
849
|
|
|
|
|
|
|
map { |
|
850
|
3458
|
|
|
|
|
6865
|
exists($o{$_}) ? $o{$_} : undef; |
|
851
|
|
|
|
|
|
|
} qw(quorum shares width sharelist key invert? skipchecks?); |
|
852
|
|
|
|
|
|
|
|
|
853
|
|
|
|
|
|
|
# skip error checking if the caller tells us it's OK |
|
854
|
3458
|
50
|
33
|
|
|
19274
|
unless (defined($skipchecks) and $skipchecks) { |
|
855
|
3458
|
50
|
|
|
|
14449
|
if (ida_check_transform_opts(%o)) { |
|
856
|
0
|
|
|
|
|
0
|
carp "Can't create matrix due to options problem"; |
|
857
|
0
|
|
|
|
|
0
|
return undef; |
|
858
|
|
|
|
|
|
|
} |
|
859
|
|
|
|
|
|
|
} |
|
860
|
|
|
|
|
|
|
|
|
861
|
3458
|
|
|
|
|
37564
|
my $mat=Math::FastGF2::Matrix -> |
|
862
|
|
|
|
|
|
|
new(rows => scalar(@$sharelist), |
|
863
|
|
|
|
|
|
|
cols => $k, |
|
864
|
|
|
|
|
|
|
width => $w, |
|
865
|
|
|
|
|
|
|
org => "rowwise"); |
|
866
|
3458
|
50
|
|
|
|
111359
|
unless (defined($mat)) { |
|
867
|
0
|
|
|
|
|
0
|
carp "Failed to create transform matrix"; |
|
868
|
0
|
|
|
|
|
0
|
return undef; |
|
869
|
|
|
|
|
|
|
} |
|
870
|
3458
|
|
|
|
|
4171
|
my $dest_row=0; |
|
871
|
3458
|
|
|
|
|
6399
|
for my $row (@$sharelist) { |
|
872
|
20742
|
|
|
|
|
32488
|
for my $col (0 .. $k-1) { |
|
873
|
97434
|
|
|
|
|
109148
|
my $x = $key->[$row]; |
|
874
|
97434
|
|
|
|
|
112366
|
my $y = $key->[$n+$col]; |
|
875
|
97434
|
|
|
|
|
103361
|
my $sum = $x ^ $y; |
|
876
|
97434
|
|
|
|
|
319041
|
$mat->setval($dest_row, $col, gf2_inv($w << 3,$sum)); |
|
877
|
|
|
|
|
|
|
} |
|
878
|
20742
|
|
|
|
|
44726
|
++$dest_row; |
|
879
|
|
|
|
|
|
|
} |
|
880
|
3458
|
50
|
33
|
|
|
15018
|
if (defined($invert) and $invert) { |
|
881
|
0
|
|
|
|
|
0
|
return $mat->invert; |
|
882
|
|
|
|
|
|
|
} else { |
|
883
|
3458
|
|
|
|
|
17032
|
return $mat; |
|
884
|
|
|
|
|
|
|
} |
|
885
|
|
|
|
|
|
|
} |
|
886
|
|
|
|
|
|
|
|
|
887
|
|
|
|
|
|
|
sub ida_split { |
|
888
|
3461
|
|
|
3461
|
0
|
19437
|
my ($self, $class); |
|
889
|
3461
|
50
|
33
|
|
|
16410
|
if ($_[0] eq $classname or ref($_[0]) eq $classname) { |
|
890
|
0
|
|
|
|
|
0
|
$self = shift; |
|
891
|
0
|
|
0
|
|
|
0
|
$class = ref($self) || $self; |
|
892
|
|
|
|
|
|
|
} else { |
|
893
|
3461
|
|
|
|
|
4401
|
$self=$classname; |
|
894
|
3461
|
|
|
|
|
5556
|
$class=$classname; |
|
895
|
|
|
|
|
|
|
} |
|
896
|
3461
|
|
|
|
|
49407
|
my %o= |
|
897
|
|
|
|
|
|
|
( |
|
898
|
|
|
|
|
|
|
quorum => undef, |
|
899
|
|
|
|
|
|
|
shares => undef, |
|
900
|
|
|
|
|
|
|
width => undef, |
|
901
|
|
|
|
|
|
|
# supply either a list of key parameters or a matrix |
|
902
|
|
|
|
|
|
|
key => undef, |
|
903
|
|
|
|
|
|
|
matrix => undef, |
|
904
|
|
|
|
|
|
|
sharelist => undef, |
|
905
|
|
|
|
|
|
|
# source, sinks |
|
906
|
|
|
|
|
|
|
filler => undef, |
|
907
|
|
|
|
|
|
|
emptiers => undef, |
|
908
|
|
|
|
|
|
|
# misc options |
|
909
|
|
|
|
|
|
|
rand => "/dev/urandom", |
|
910
|
|
|
|
|
|
|
bufsize => 4096, |
|
911
|
|
|
|
|
|
|
bytes => 0, |
|
912
|
|
|
|
|
|
|
# byte order flags |
|
913
|
|
|
|
|
|
|
inorder => 0, |
|
914
|
|
|
|
|
|
|
outorder => 0, |
|
915
|
|
|
|
|
|
|
@_, |
|
916
|
|
|
|
|
|
|
); |
|
917
|
|
|
|
|
|
|
|
|
918
|
|
|
|
|
|
|
# move all options into local variables |
|
919
|
44993
|
50
|
|
|
|
124776
|
my ($k,$n,$w,$key,$mat,$sharelist,$filler,$emptiers,$rng, |
|
920
|
|
|
|
|
|
|
$bufsize,$inorder,$outorder,$bytes_to_read) = |
|
921
|
|
|
|
|
|
|
map { |
|
922
|
3461
|
|
|
|
|
7299
|
exists($o{$_}) ? $o{$_} : undef; |
|
923
|
|
|
|
|
|
|
} qw(quorum shares width key matrix sharelist filler |
|
924
|
|
|
|
|
|
|
emptiers rand bufsize inorder outorder bytes); |
|
925
|
|
|
|
|
|
|
|
|
926
|
|
|
|
|
|
|
# validity checks |
|
927
|
3461
|
50
|
100
|
|
|
21278
|
unless ($w == 1 or $w == 2 or $w == 4) { |
|
|
|
|
66
|
|
|
|
|
|
928
|
0
|
|
|
|
|
0
|
carp "Width must be one of 1, 2, 4"; |
|
929
|
0
|
|
|
|
|
0
|
return undef; |
|
930
|
|
|
|
|
|
|
} |
|
931
|
3461
|
50
|
33
|
|
|
18232
|
unless ($k > 0 and $k < 256 ** $w) { |
|
932
|
0
|
|
|
|
|
0
|
carp "Quorum value out of range"; |
|
933
|
0
|
|
|
|
|
0
|
return undef; |
|
934
|
|
|
|
|
|
|
} |
|
935
|
3461
|
50
|
33
|
|
|
17077
|
unless ($n > 0 and $k + $n < 256 ** $w) { |
|
936
|
0
|
|
|
|
|
0
|
carp "Number of shares out of range"; |
|
937
|
0
|
|
|
|
|
0
|
return undef; |
|
938
|
|
|
|
|
|
|
} |
|
939
|
3461
|
50
|
|
|
|
8133
|
unless (defined ($filler)) { |
|
940
|
0
|
|
|
|
|
0
|
carp "Need a filler to provide data"; |
|
941
|
0
|
|
|
|
|
0
|
return undef; |
|
942
|
|
|
|
|
|
|
} |
|
943
|
3461
|
50
|
33
|
|
|
14487
|
unless (ref($emptiers) and scalar(@$emptiers) == $n) { |
|
944
|
0
|
|
|
|
|
0
|
carp "emptiers must be a list of $n items (one for each share)"; |
|
945
|
0
|
|
|
|
|
0
|
return undef; |
|
946
|
|
|
|
|
|
|
} |
|
947
|
3461
|
50
|
33
|
|
|
15380
|
unless (defined($bufsize) and $bufsize > 0) { |
|
948
|
0
|
|
|
|
|
0
|
carp "Bad bufsize ($bufsize)"; |
|
949
|
0
|
|
|
|
|
0
|
return undef; |
|
950
|
|
|
|
|
|
|
} |
|
951
|
3461
|
50
|
33
|
|
|
25170
|
unless (defined($inorder) and $inorder >= 0 and $inorder <= 2) { |
|
|
|
|
33
|
|
|
|
|
|
952
|
0
|
|
|
|
|
0
|
carp "inorder != 0 (native), 1 (little-endian) or 2 (big-endian)"; |
|
953
|
0
|
|
|
|
|
0
|
return undef; |
|
954
|
|
|
|
|
|
|
} |
|
955
|
3461
|
50
|
33
|
|
|
24702
|
unless (defined($outorder) and $outorder >= 0 and $outorder <= 2) { |
|
|
|
|
33
|
|
|
|
|
|
956
|
0
|
|
|
|
|
0
|
carp "outorder != 0 (native), 1 (little-endian) or 2 (big-endian)"; |
|
957
|
0
|
|
|
|
|
0
|
return undef; |
|
958
|
|
|
|
|
|
|
} |
|
959
|
|
|
|
|
|
|
# Move some checks to ida_check_transform_opts |
|
960
|
3461
|
50
|
|
|
|
18916
|
if (ida_check_transform_opts(%o)) { |
|
961
|
0
|
|
|
|
|
0
|
carp "Can't proceed due to problem with transform options"; |
|
962
|
0
|
|
|
|
|
0
|
return undef; |
|
963
|
|
|
|
|
|
|
} |
|
964
|
|
|
|
|
|
|
|
|
965
|
3461
|
50
|
33
|
|
|
18687
|
if (defined($bytes_to_read) and $bytes_to_read < 0) { |
|
966
|
0
|
|
|
|
|
0
|
carp "bytes parameter must be 0 (read until eof) or greater"; |
|
967
|
0
|
|
|
|
|
0
|
return undef; |
|
968
|
|
|
|
|
|
|
} |
|
969
|
|
|
|
|
|
|
|
|
970
|
3461
|
100
|
|
|
|
6738
|
if (defined($sharelist)) { |
|
971
|
|
|
|
|
|
|
|
|
972
|
|
|
|
|
|
|
# moved some checks to ida_check_transform_opts |
|
973
|
|
|
|
|
|
|
|
|
974
|
1
|
50
|
|
|
|
6
|
if (defined($mat)) { |
|
975
|
|
|
|
|
|
|
# copy only the listed rows into a new matrix |
|
976
|
1
|
|
|
|
|
9
|
my $m2=Math::FastGF2::Matrix->new(rows => scalar(@$sharelist), |
|
977
|
|
|
|
|
|
|
cols => $k, |
|
978
|
|
|
|
|
|
|
width => $w, |
|
979
|
|
|
|
|
|
|
org => "rowwise"); |
|
980
|
1
|
50
|
|
|
|
38
|
unless (defined($m2)) { |
|
981
|
0
|
|
|
|
|
0
|
carp "Problem creating submatrix with rows from sharelist"; |
|
982
|
0
|
|
|
|
|
0
|
return undef; |
|
983
|
|
|
|
|
|
|
} |
|
984
|
1
|
|
|
|
|
2
|
my $dest_row=0; |
|
985
|
1
|
|
|
|
|
3
|
for my $row (@$sharelist) { |
|
986
|
3
|
|
|
|
|
9
|
for my $col (0 .. $k-1) { |
|
987
|
9
|
|
|
|
|
35
|
$m2->setval($dest_row,$col, $mat->getval($row,$col)); |
|
988
|
|
|
|
|
|
|
} |
|
989
|
3
|
|
|
|
|
7
|
++$dest_row; |
|
990
|
|
|
|
|
|
|
} |
|
991
|
1
|
|
|
|
|
3
|
$mat=$m2; # replace matrix with reduced one |
|
992
|
|
|
|
|
|
|
} |
|
993
|
|
|
|
|
|
|
} else { |
|
994
|
3460
|
|
|
|
|
12448
|
$sharelist=[0..$n-1]; |
|
995
|
|
|
|
|
|
|
} |
|
996
|
|
|
|
|
|
|
|
|
997
|
3461
|
100
|
|
|
|
8668
|
unless (defined($mat)) { |
|
998
|
3456
|
50
|
|
|
|
7215
|
if (defined ($key)) { |
|
999
|
0
|
0
|
|
|
|
0
|
if (ida_check_key($k,$n,$w,$key)) { |
|
1000
|
0
|
|
|
|
|
0
|
carp "Problem with supplied key"; |
|
1001
|
0
|
|
|
|
|
0
|
return undef; |
|
1002
|
|
|
|
|
|
|
} |
|
1003
|
|
|
|
|
|
|
} else { |
|
1004
|
|
|
|
|
|
|
# no key and no matrix, so generate random key |
|
1005
|
3456
|
|
|
|
|
8926
|
$rng=ida_rng_init($w,$rng); |
|
1006
|
3456
|
50
|
|
|
|
7345
|
unless (defined($rng)) { |
|
1007
|
0
|
|
|
|
|
0
|
carp "Failed to initialise random number generator"; |
|
1008
|
0
|
|
|
|
|
0
|
return undef; |
|
1009
|
|
|
|
|
|
|
} |
|
1010
|
3456
|
|
|
|
|
8561
|
$key=ida_generate_key($k,$n,$w,$rng); |
|
1011
|
|
|
|
|
|
|
} |
|
1012
|
|
|
|
|
|
|
|
|
1013
|
|
|
|
|
|
|
# now generate matrix from key |
|
1014
|
3456
|
|
|
|
|
12413
|
$mat=ida_key_to_matrix( "quorum" => $k, |
|
1015
|
|
|
|
|
|
|
"shares" => $n, |
|
1016
|
|
|
|
|
|
|
"width" => $w, |
|
1017
|
|
|
|
|
|
|
"sharelist" => $sharelist, |
|
1018
|
|
|
|
|
|
|
"key" => $key, |
|
1019
|
|
|
|
|
|
|
"skipchecks?" => 0); |
|
1020
|
|
|
|
|
|
|
} |
|
1021
|
|
|
|
|
|
|
|
|
1022
|
|
|
|
|
|
|
# create the buffer matrices and start the transform |
|
1023
|
3461
|
|
|
|
|
14132
|
my $in = Math::FastGF2::Matrix->new(rows=>$k, |
|
1024
|
|
|
|
|
|
|
cols=>$bufsize, |
|
1025
|
|
|
|
|
|
|
width=>$w, |
|
1026
|
|
|
|
|
|
|
org => "colwise"); |
|
1027
|
3461
|
|
|
|
|
106313
|
my $out= Math::FastGF2::Matrix->new(rows=>scalar(@$sharelist), |
|
1028
|
|
|
|
|
|
|
cols=>$bufsize, |
|
1029
|
|
|
|
|
|
|
width=>$w, |
|
1030
|
|
|
|
|
|
|
org => "rowwise"); |
|
1031
|
3461
|
50
|
33
|
|
|
103684
|
unless (defined($in) and defined($out)) { |
|
1032
|
0
|
|
|
|
|
0
|
carp "failed to allocate input/output buffer matrices"; |
|
1033
|
0
|
|
|
|
|
0
|
return undef; |
|
1034
|
|
|
|
|
|
|
} |
|
1035
|
3461
|
|
|
|
|
13315
|
my $rc=ida_process_streams($mat, |
|
1036
|
|
|
|
|
|
|
$in, [$filler], |
|
1037
|
|
|
|
|
|
|
$out, $emptiers, |
|
1038
|
|
|
|
|
|
|
$bytes_to_read, |
|
1039
|
|
|
|
|
|
|
$inorder, $outorder); |
|
1040
|
3461
|
50
|
|
|
|
8815
|
if (defined ($rc)) { |
|
1041
|
3461
|
|
|
|
|
149118
|
return ($key,$mat,$rc); |
|
1042
|
|
|
|
|
|
|
} else { |
|
1043
|
0
|
|
|
|
|
0
|
return undef; |
|
1044
|
|
|
|
|
|
|
} |
|
1045
|
|
|
|
|
|
|
} |
|
1046
|
|
|
|
|
|
|
|
|
1047
|
|
|
|
|
|
|
sub ida_combine { |
|
1048
|
3459
|
|
|
3459
|
1
|
19066
|
my $self; |
|
1049
|
|
|
|
|
|
|
my $class; |
|
1050
|
3459
|
50
|
33
|
|
|
19726
|
if ($_[0] eq $classname or ref($_[0]) eq $classname) { |
|
1051
|
0
|
|
|
|
|
0
|
$self = shift; |
|
1052
|
0
|
|
0
|
|
|
0
|
$class = ref($self) || $self; |
|
1053
|
|
|
|
|
|
|
} else { |
|
1054
|
3459
|
|
|
|
|
4228
|
$self=$classname; |
|
1055
|
3459
|
|
|
|
|
4616
|
$class=$classname; |
|
1056
|
|
|
|
|
|
|
} |
|
1057
|
3459
|
|
|
|
|
50546
|
my %o= |
|
1058
|
|
|
|
|
|
|
( |
|
1059
|
|
|
|
|
|
|
quorum => undef, |
|
1060
|
|
|
|
|
|
|
shares => undef, # only needed if key supplied |
|
1061
|
|
|
|
|
|
|
width => undef, |
|
1062
|
|
|
|
|
|
|
# supply either a list of key parameters and a list of keys or a |
|
1063
|
|
|
|
|
|
|
# pre-inverted matrix generated from those key details |
|
1064
|
|
|
|
|
|
|
key => undef, |
|
1065
|
|
|
|
|
|
|
matrix => undef, |
|
1066
|
|
|
|
|
|
|
sharelist => undef, |
|
1067
|
|
|
|
|
|
|
# source, sinks |
|
1068
|
|
|
|
|
|
|
fillers => undef, |
|
1069
|
|
|
|
|
|
|
emptier => undef, |
|
1070
|
|
|
|
|
|
|
# misc options |
|
1071
|
|
|
|
|
|
|
bufsize => 4096, |
|
1072
|
|
|
|
|
|
|
bytes => 0, |
|
1073
|
|
|
|
|
|
|
# byte order flags |
|
1074
|
|
|
|
|
|
|
inorder => 0, |
|
1075
|
|
|
|
|
|
|
outorder => 0, |
|
1076
|
|
|
|
|
|
|
@_, |
|
1077
|
|
|
|
|
|
|
); |
|
1078
|
|
|
|
|
|
|
|
|
1079
|
|
|
|
|
|
|
# copy all options into local variables |
|
1080
|
41508
|
50
|
|
|
|
117939
|
my ($k,$n,$w,$key,$mat,$sharelist,$fillers,$emptier, |
|
1081
|
|
|
|
|
|
|
$bufsize,$inorder,$outorder,$bytes_to_read) = |
|
1082
|
|
|
|
|
|
|
map { |
|
1083
|
3459
|
|
|
|
|
8206
|
exists($o{$_}) ? $o{$_} : undef; |
|
1084
|
|
|
|
|
|
|
} qw(quorum shares width key matrix sharelist fillers |
|
1085
|
|
|
|
|
|
|
emptier bufsize inorder outorder bytes); |
|
1086
|
|
|
|
|
|
|
|
|
1087
|
|
|
|
|
|
|
# validity checks |
|
1088
|
3459
|
50
|
100
|
|
|
23986
|
unless ($w == 1 or $w == 2 or $w == 4) { |
|
|
|
|
66
|
|
|
|
|
|
1089
|
0
|
|
|
|
|
0
|
carp "Width must be one of 1, 2, 4"; |
|
1090
|
0
|
|
|
|
|
0
|
return undef; |
|
1091
|
|
|
|
|
|
|
} |
|
1092
|
3459
|
50
|
33
|
|
|
19254
|
unless ($k > 0 and $k < 256 ** $w) { |
|
1093
|
0
|
|
|
|
|
0
|
carp "Quorum value out of range"; |
|
1094
|
0
|
|
|
|
|
0
|
return undef; |
|
1095
|
|
|
|
|
|
|
} |
|
1096
|
3459
|
50
|
33
|
|
|
17337
|
unless (ref($fillers) and scalar(@$fillers) == $k) { |
|
1097
|
0
|
|
|
|
|
0
|
carp "fillers must be a list of $k items (one for each share)"; |
|
1098
|
0
|
|
|
|
|
0
|
return undef; |
|
1099
|
|
|
|
|
|
|
} |
|
1100
|
3459
|
50
|
|
|
|
9156
|
unless (defined($emptier)) { |
|
1101
|
0
|
|
|
|
|
0
|
carp "need an emptier to write data to"; |
|
1102
|
0
|
|
|
|
|
0
|
return undef; |
|
1103
|
|
|
|
|
|
|
} |
|
1104
|
3459
|
50
|
33
|
|
|
14828
|
unless (defined($bufsize) and $bufsize > 0) { |
|
1105
|
0
|
|
|
|
|
0
|
carp "Bad bufsize"; |
|
1106
|
0
|
|
|
|
|
0
|
return undef; |
|
1107
|
|
|
|
|
|
|
} |
|
1108
|
3459
|
50
|
33
|
|
|
21033
|
unless (defined($inorder) and $inorder >= 0 and $inorder <= 2) { |
|
|
|
|
33
|
|
|
|
|
|
1109
|
0
|
|
|
|
|
0
|
carp "inorder ($inorder) != 0 (native), ". |
|
1110
|
|
|
|
|
|
|
"1 (little-endian) or 2 (big-endian)"; |
|
1111
|
0
|
|
|
|
|
0
|
return undef; |
|
1112
|
|
|
|
|
|
|
} |
|
1113
|
3459
|
50
|
33
|
|
|
20693
|
unless (defined($outorder) and $outorder >= 0 and $outorder <= 2) { |
|
|
|
|
33
|
|
|
|
|
|
1114
|
0
|
|
|
|
|
0
|
carp "outorder ($outorder) != 0 (native), ". |
|
1115
|
|
|
|
|
|
|
"1 (little-endian) or 2 (big-endian)"; |
|
1116
|
0
|
|
|
|
|
0
|
return undef; |
|
1117
|
|
|
|
|
|
|
} |
|
1118
|
3459
|
50
|
|
|
|
6468
|
if (defined($key)) { |
|
1119
|
0
|
0
|
|
|
|
0
|
if (ida_check_key($k,$n,$w,$key)) { |
|
1120
|
0
|
|
|
|
|
0
|
carp "Invalid key supplied"; |
|
1121
|
0
|
|
|
|
|
0
|
return undef; |
|
1122
|
|
|
|
|
|
|
} |
|
1123
|
|
|
|
|
|
|
} else { |
|
1124
|
3459
|
|
|
|
|
8725
|
$o{"shares"}=$k; # needed for ida_check_transform_opts |
|
1125
|
3459
|
|
|
|
|
5012
|
$n=$k; |
|
1126
|
|
|
|
|
|
|
} |
|
1127
|
3459
|
50
|
|
|
|
19822
|
if (ida_check_transform_opts(%o)) { |
|
1128
|
0
|
|
|
|
|
0
|
carp "Can't continue due to problem with transform opts"; |
|
1129
|
0
|
|
|
|
|
0
|
return undef; |
|
1130
|
|
|
|
|
|
|
} |
|
1131
|
3459
|
50
|
33
|
|
|
18303
|
if (defined($bytes_to_read) and $bytes_to_read < 0) { |
|
1132
|
0
|
|
|
|
|
0
|
carp "bytes parameter must be 0 (read until eof) or greater"; |
|
1133
|
0
|
|
|
|
|
0
|
return undef; |
|
1134
|
|
|
|
|
|
|
} |
|
1135
|
|
|
|
|
|
|
|
|
1136
|
3459
|
50
|
|
|
|
6844
|
if (defined($key)) { |
|
1137
|
0
|
|
|
|
|
0
|
ida_check_list($sharelist,"share",0,$k-1); |
|
1138
|
0
|
0
|
|
|
|
0
|
unless (scalar(@$sharelist) == $k) { |
|
1139
|
0
|
|
|
|
|
0
|
carp "sharelist does not have k=$k elements"; |
|
1140
|
0
|
|
|
|
|
0
|
return undef; |
|
1141
|
|
|
|
|
|
|
} |
|
1142
|
|
|
|
|
|
|
#warn "Creating and inverting matrix from key\n"; |
|
1143
|
0
|
|
|
|
|
0
|
$mat=ida_key_to_matrix(%o, "skipchecks?" => 0, "invert?" => 1); |
|
1144
|
0
|
0
|
|
|
|
0
|
unless (defined($mat)) { |
|
1145
|
0
|
|
|
|
|
0
|
carp "Failed to invert transform matrix (this shouldn't happen)"; |
|
1146
|
0
|
|
|
|
|
0
|
return undef; |
|
1147
|
|
|
|
|
|
|
} |
|
1148
|
|
|
|
|
|
|
} |
|
1149
|
|
|
|
|
|
|
|
|
1150
|
|
|
|
|
|
|
# create the buffer matrices and start the transform |
|
1151
|
3459
|
|
|
|
|
21071
|
my $in = Math::FastGF2::Matrix->new(rows=>$k, |
|
1152
|
|
|
|
|
|
|
cols=>$bufsize, |
|
1153
|
|
|
|
|
|
|
width=>$w, |
|
1154
|
|
|
|
|
|
|
org => "rowwise"); |
|
1155
|
3459
|
|
|
|
|
104036
|
my $out= Math::FastGF2::Matrix->new(rows=>$k, |
|
1156
|
|
|
|
|
|
|
cols=>$bufsize, |
|
1157
|
|
|
|
|
|
|
width=>$w, |
|
1158
|
|
|
|
|
|
|
org => "colwise"); |
|
1159
|
3459
|
50
|
33
|
|
|
115615
|
unless (defined($in) and defined($out)) { |
|
1160
|
0
|
|
|
|
|
0
|
carp "failed to allocate input/output buffer matrices"; |
|
1161
|
0
|
|
|
|
|
0
|
return undef; |
|
1162
|
|
|
|
|
|
|
} |
|
1163
|
3459
|
|
|
|
|
12777
|
my @vals=$mat->getvals(0,0,$k * $n); |
|
1164
|
|
|
|
|
|
|
#warn "matrix is [" . (join ", ", map |
|
1165
|
|
|
|
|
|
|
# {sprintf("%02x",$_) } @vals) . "] (" . |
|
1166
|
|
|
|
|
|
|
# scalar(@vals) . " values)\n"; |
|
1167
|
|
|
|
|
|
|
|
|
1168
|
3459
|
|
|
|
|
3279985
|
return ida_process_streams($mat, |
|
1169
|
|
|
|
|
|
|
$in, $fillers, |
|
1170
|
|
|
|
|
|
|
$out, [$emptier], |
|
1171
|
|
|
|
|
|
|
$bytes_to_read, |
|
1172
|
|
|
|
|
|
|
$inorder, $outorder); |
|
1173
|
|
|
|
|
|
|
|
|
1174
|
|
|
|
|
|
|
} |
|
1175
|
|
|
|
|
|
|
|
|
1176
|
|
|
|
|
|
|
|
|
1177
|
|
|
|
|
|
|
1; |
|
1178
|
|
|
|
|
|
|
__END__ |