File: CDF.pm

package info (click to toggle)
ns2 2.35%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 78,796 kB
  • sloc: cpp: 172,923; tcl: 107,130; perl: 6,391; sh: 6,143; ansic: 5,846; makefile: 816; awk: 525; csh: 355
file content (119 lines) | stat: -rwxr-xr-x 2,134 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119

###############################################
#  A simple Perl module for using CDF files
#
#  Tim Buchheim,  25 September 2002
#
#  based on C++ code found in the ns project
#
# File format:
#
#  first column:  value
#  second column: cumulative number of occurances (ignored)
#  third column:  cumulative probability
#
###############################################

package CDF;

use strict;


# the constructor
#
#  $foo = new CDF($filename);
#

sub new {
    my $class = shift;
    my $i = 0;
    my $file = shift;
    my @table;

    open INPUT_FILE, $file or die "Unable to open file: $file";
    while (<INPUT_FILE>) {
        my ($value, $num, $prob) = split;
	$table[$i] = [$prob, $value];
	++$i;
    }
    close INPUT_FILE;
    return bless \@table, $class;
}




# public methods

#
#  $foo->value();
#
# looks up the value for a random number.  Does not do any interpolation.
sub value {
    my $self = shift;
    my @table = @$self;

    if (scalar(@table) <= 0) { return 0; }

    my $u = rand;
    my $mid = $self->lookup($u);

    return $table[$mid][1];
}


#
#  $foo->interpolated_value();
#
# looks up the value for a random number.  Interpolates between table
# entries.
sub interpolated_value {
    my $self = shift;
    my @table = @$self;

    if (scalar(@table) <= 0) { return 0; }

    my $u = rand;
    my $mid = $self->lookup($u);
    if ($mid and $u < $table[$mid][0]) {
        return interpolate($u, $table[$mid-1][0], $table[$mid-1][1],
	                   $table[$mid][0], $table[$mid][1]);
    }
    return $table[$mid][1];
}


# private method
sub lookup {
    my $self = shift;
    my @table = @$self;
    my $u = shift;
    if ($u <= $table[0][0]) {
    	return 0;
    }
    my ($lo, $hi, $mid);
    for ($lo = 1, $hi = scalar(@table) - 1; $lo < $hi; ) {
        $mid = ($lo + $hi) / 2;
	if ($u > $table[$mid][0]) {
	    $lo = $mid + 1;
	} else {
	    $hi = $mid;
	}
    }
    return $lo;
}

# private function
sub interpolate {
    my ($x, $x1, $y1, $x2, $y2) = @_;
    my $value = $y1 + ($x - $x1) * ($y2 - $y1) / ($x2 - $x1);
    return $value;
}





# a Perl package must return true
1;