line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Random::Skew::Test; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
72779
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
31
|
|
4
|
1
|
|
|
1
|
|
9
|
use warnings; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
37
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
our $VERSION = '0.02'; |
7
|
|
|
|
|
|
|
|
8
|
1
|
|
|
1
|
|
2711
|
use Random::Skew; |
|
1
|
|
|
|
|
1141
|
|
|
1
|
|
|
|
|
995
|
|
9
|
|
|
|
|
|
|
|
10
|
|
|
|
|
|
|
sub sample { |
11
|
|
|
|
|
|
|
|
12
|
2
|
|
|
2
|
0
|
1728
|
my $self = shift; |
13
|
2
|
|
|
|
|
11
|
my %params = @_; |
14
|
|
|
|
|
|
|
|
15
|
2
|
|
|
|
|
3
|
my @bad; |
16
|
|
|
|
|
|
|
|
17
|
2
|
50
|
|
|
|
8
|
my $iter = $params{iter} or push @bad,"Random::Skew::sample(iter=>?) parameter missing"; |
18
|
2
|
50
|
|
|
|
6
|
my $skew = $params{skew} or push @bad,"Random::Skew::sample(skew=>{}) parameter missing"; |
19
|
2
|
|
50
|
|
|
6
|
my $grain= $params{grain} // [ qw/25 250 1000/ ]; |
20
|
2
|
|
50
|
|
|
6
|
my $round= $params{round} // [ qw/0 .5/ ]; |
21
|
|
|
|
|
|
|
|
22
|
2
|
50
|
|
|
|
5
|
die @bad if @bad; |
23
|
|
|
|
|
|
|
|
24
|
2
|
|
|
|
|
5
|
my @output; |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
my $rs; |
27
|
|
|
|
|
|
|
|
28
|
2
|
|
|
|
|
5
|
my @grain = @$grain; |
29
|
2
|
|
|
|
|
4
|
my @round = @$round; |
30
|
|
|
|
|
|
|
|
31
|
2
|
|
|
|
|
5
|
foreach $grain ( @grain ) { |
32
|
|
|
|
|
|
|
|
33
|
3
|
|
|
|
|
5
|
$Random::Skew::GRAIN = $grain; |
34
|
3
|
|
|
|
|
7
|
my @r = @round; |
35
|
|
|
|
|
|
|
|
36
|
3
|
|
|
|
|
7
|
while ( @r ) { |
37
|
4
|
|
|
|
|
8
|
$round = shift @r; |
38
|
|
|
|
|
|
|
|
39
|
4
|
|
|
|
|
6
|
$Random::Skew::ROUNDING = $round; |
40
|
|
|
|
|
|
|
|
41
|
4
|
|
|
|
|
34
|
$rs = Random::Skew->new( %$skew ); |
42
|
4
|
|
|
|
|
490
|
my $pop = $rs->{_pop}; |
43
|
|
|
|
|
|
|
|
44
|
4
|
100
|
|
|
|
10
|
if ( $rs->{_tot} < $rs->{_grain} ) { |
45
|
2
|
|
|
|
|
4
|
$round = '[moot at this grain]'; |
46
|
2
|
|
|
|
|
5
|
@r = (); |
47
|
|
|
|
|
|
|
} |
48
|
|
|
|
|
|
|
|
49
|
4
|
|
|
|
|
19
|
push @output, "Grain=$Random::Skew::GRAIN (Rounding=+$round): -=-=-=-=-=-=-=-=-=-\n", |
50
|
|
|
|
|
|
|
&show( $rs ), |
51
|
|
|
|
|
|
|
&run( $rs, $iter ); |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
} |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
} |
56
|
|
|
|
|
|
|
|
57
|
2
|
|
|
|
|
27
|
return @output, |
58
|
|
|
|
|
|
|
"Typically you want the Ratio column to be close to 1.0 (0.9ish to 1.1ish).\n", |
59
|
|
|
|
|
|
|
"However, more iterations (>$iter) might smooth out the results.\n\n"; |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
} |
62
|
|
|
|
|
|
|
|
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
# To see the structure of a Random::Skew object |
66
|
|
|
|
|
|
|
sub show { |
67
|
6
|
|
|
6
|
0
|
11
|
my $set = shift; |
68
|
6
|
|
100
|
|
|
19
|
my $indent = shift || ''; |
69
|
|
|
|
|
|
|
|
70
|
6
|
|
|
|
|
14
|
my @output; |
71
|
|
|
|
|
|
|
|
72
|
|
|
|
|
|
|
my %v; |
73
|
6
|
|
|
|
|
0
|
my $v; |
74
|
6
|
|
|
|
|
9
|
foreach $v ( @{ $set->{_set} } ) { |
|
6
|
|
|
|
|
14
|
|
75
|
130
|
100
|
|
|
|
218
|
$v{ $v }++ unless ref $v; |
76
|
|
|
|
|
|
|
} |
77
|
6
|
50
|
|
|
|
47
|
foreach $v ( sort {$v{$b} <=> $v{$a} or $a cmp $b} keys %v ) { |
|
11
|
|
|
|
|
34
|
|
78
|
14
|
50
|
|
|
|
49
|
push @output, "$indent$v\t$v{$v}\n" |
79
|
|
|
|
|
|
|
if $v; # no need to show empties, _fraction handles those anyway |
80
|
|
|
|
|
|
|
} |
81
|
|
|
|
|
|
|
|
82
|
6
|
100
|
|
|
|
21
|
if ( $set->{_fraction} ) { |
83
|
|
|
|
|
|
|
push @output, |
84
|
|
|
|
|
|
|
"$indent...and smaller (when rand(0..$set->{_pop}) < $set->{_fraction}):\n", |
85
|
2
|
|
|
|
|
24
|
&show( $set->{_set}[0], "$indent " ); |
86
|
|
|
|
|
|
|
} |
87
|
|
|
|
|
|
|
|
88
|
6
|
|
|
|
|
26
|
return @output; |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
|
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
sub run { |
94
|
4
|
|
|
4
|
0
|
9
|
my $rs = shift; |
95
|
4
|
|
50
|
|
|
29
|
my $ct = shift // 1_000_000; |
96
|
|
|
|
|
|
|
|
97
|
4
|
|
|
|
|
10
|
my @output; |
98
|
|
|
|
|
|
|
|
99
|
4
|
|
|
|
|
11
|
push @output, "--${ct}x:\n", |
100
|
|
|
|
|
|
|
"Bucket\tReturned(%)\tRequested(%)\tRatio\n", |
101
|
|
|
|
|
|
|
"======\t========\t=========\t=====\n"; |
102
|
|
|
|
|
|
|
|
103
|
4
|
|
|
|
|
8
|
my %result; |
104
|
4
|
|
|
|
|
13
|
while ( $ct-- > 0 ) { |
105
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
# _/_/_/_/ _/_/_/_/ _/_/_/_/ _/_/_/_/ |
107
|
|
|
|
|
|
|
# _/ _/ _/ _/ |
108
|
|
|
|
|
|
|
# _/ _/_/_/ _/_/_/ _/ |
109
|
|
|
|
|
|
|
# _/ _/ _/ _/ |
110
|
|
|
|
|
|
|
#_/ _/_/_/_/ _/_/_/_/ _/ |
111
|
|
|
|
|
|
|
|
112
|
301
|
|
|
|
|
3957
|
$result{ $rs->item }++; # Here's where we iterate thru the tests |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
} |
115
|
|
|
|
|
|
|
|
116
|
4
|
|
|
|
|
51
|
my $overall_prd = 1.0; |
117
|
4
|
|
|
|
|
5
|
my $is_zero = 0; |
118
|
4
|
|
|
|
|
5
|
my $overall_avg = 0.0; |
119
|
|
|
|
|
|
|
|
120
|
4
|
|
|
|
|
8
|
my $p = $rs->{_params}; |
121
|
4
|
|
|
|
|
5
|
my $p_tot = 0; |
122
|
4
|
|
|
|
|
4
|
my $r_tot = 0; |
123
|
4
|
|
|
|
|
14
|
foreach my $item ( keys %$p ) { |
124
|
14
|
|
50
|
|
|
25
|
$p_tot += $p->{ $item } // 0; |
125
|
14
|
|
100
|
|
|
32
|
$r_tot += $result{ $item } // 0; |
126
|
|
|
|
|
|
|
} |
127
|
4
|
50
|
|
|
|
15
|
foreach my $item ( sort {$p->{$b} <=> $p->{$a} or $a cmp $b } keys %$p ) { |
|
13
|
|
|
|
|
31
|
|
128
|
14
|
|
|
|
|
27
|
my $p_pct = 100 * $p->{ $item } / $p_tot; |
129
|
14
|
|
100
|
|
|
41
|
my $r_pct = 100 * ($result{ $item } // 0) / $r_tot; |
130
|
14
|
|
|
|
|
28
|
my $ratio = $r_pct / $p_pct; |
131
|
14
|
100
|
|
|
|
28
|
$is_zero ++ unless defined( $result{ $item } ); |
132
|
|
|
|
|
|
|
|
133
|
14
|
|
|
|
|
19
|
my $ratio_alert = ''; |
134
|
14
|
100
|
|
|
|
28
|
$ratio_alert = ' <-- low?' if $ratio < 9/10; |
135
|
14
|
100
|
|
|
|
28
|
$ratio_alert = ' <-- LOW?' if $ratio < 8/10; |
136
|
14
|
100
|
|
|
|
24
|
$ratio_alert = ' <-- high?' if $ratio > 10/9; |
137
|
14
|
100
|
|
|
|
24
|
$ratio_alert = ' <-- HIGH?' if $ratio > 10/8; |
138
|
|
|
|
|
|
|
push @output, sprintf "%s:\t%s (%3.3g)\t%s (%3.3g)\t%.4f%s\n", |
139
|
|
|
|
|
|
|
$item, |
140
|
|
|
|
|
|
|
&h( $result{$item} // 0 ), $r_pct, |
141
|
14
|
|
100
|
|
|
36
|
&h( $p->{$item} ), $p_pct, |
142
|
|
|
|
|
|
|
$ratio, $ratio_alert, |
143
|
|
|
|
|
|
|
; |
144
|
14
|
|
|
|
|
28
|
$overall_prd *= $ratio; |
145
|
14
|
|
|
|
|
24
|
$overall_avg += $ratio; |
146
|
|
|
|
|
|
|
} |
147
|
4
|
|
|
|
|
10
|
$overall_avg /= scalar keys %$p; |
148
|
4
|
50
|
|
|
|
12
|
if ( $is_zero > 1 ) { |
|
|
100
|
|
|
|
|
|
149
|
0
|
|
|
|
|
0
|
push @output, "Note: there are $is_zero buckets not represented (which causes zero product).\n"; |
150
|
|
|
|
|
|
|
} elsif ( $is_zero > 0 ) { |
151
|
3
|
|
|
|
|
6
|
push @output, "Note: there is a bucket not represented (which causes zero product).\n"; |
152
|
|
|
|
|
|
|
} |
153
|
4
|
|
|
|
|
21
|
push @output, sprintf "Overall ratio product: %5.5g\nOverall ratio average: %5.5g\n\n", |
154
|
|
|
|
|
|
|
$overall_prd, |
155
|
|
|
|
|
|
|
$overall_avg; |
156
|
|
|
|
|
|
|
|
157
|
4
|
|
|
|
|
30
|
return @output; |
158
|
|
|
|
|
|
|
} |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
sub h { |
163
|
28
|
|
|
28
|
0
|
42
|
my $v = shift; |
164
|
28
|
|
|
|
|
36
|
my $unit = ''; |
165
|
28
|
|
|
|
|
33
|
my $div = 1; |
166
|
28
|
|
|
|
|
35
|
my $fmt = '%.0f'; # %f rounds, %d truncates |
167
|
28
|
50
|
|
|
|
84
|
if ( $v > 2_000_000_000 ) { |
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
168
|
0
|
|
|
|
|
0
|
$div = 1000 * 1000 * 1000; |
169
|
0
|
|
|
|
|
0
|
$unit = 'g'; |
170
|
|
|
|
|
|
|
} elsif ( $v > 9_999_999 ) { |
171
|
0
|
|
|
|
|
0
|
$div = 1000 * 1000; |
172
|
0
|
|
|
|
|
0
|
$unit = 'm'; |
173
|
|
|
|
|
|
|
} elsif ( $v > 2_000_000 ) { |
174
|
0
|
|
|
|
|
0
|
$div = 1000 * 1000; |
175
|
0
|
|
|
|
|
0
|
$unit = 'm'; |
176
|
0
|
|
|
|
|
0
|
$fmt = '%.1f'; |
177
|
|
|
|
|
|
|
} elsif ( $v > 9_999 ) { |
178
|
0
|
|
|
|
|
0
|
$div = 1000; |
179
|
0
|
|
|
|
|
0
|
$unit = 'k'; |
180
|
|
|
|
|
|
|
} elsif ( $v > 2_000 ) { |
181
|
0
|
|
|
|
|
0
|
$div = 1000; |
182
|
0
|
|
|
|
|
0
|
$unit = 'k'; |
183
|
0
|
|
|
|
|
0
|
$fmt = '%.1f'; |
184
|
|
|
|
|
|
|
} |
185
|
28
|
|
|
|
|
180
|
return sprintf "$fmt%s", $v/$div, $unit; |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
1; |
191
|
|
|
|
|
|
|
__END__ |