0: use strict;
1: # This module provides a random numeric sequence generator and a simple
2: # smoothing filter for use in simulation. You can specify ranges and periods.
3: # I use it to simulate the output of
4: # physical sensors for data acquisition testing.
5: #
6: # As HyperZonk said, don't use this for crypto (you know
7: # better than that, right?)
8: #
9: package RandomSequence;
10: require Exporter;
11: @RandomSequence::ISA = 'Exporter';
12: @RandomSequence::EXPORT_OK = qw(randomSequenceGenerator filterGenerator);
13: %RandomSequence::EXPORT_TAGS = (
14: 'ALL' => [ qw(randomSequenceGenerator filterGenerator) ]
15: );
16:
17: # Generate a closure that will generate a value that will vary
18: # randomly per the specifications you give it while staying within
19: # a given range.
20: #
21: # my $sub = randomSequenceGenerator( $min, $max, $maxSamples, $maxSlope, $minSamples );
22: # my $sample = &$sub; # repeat
23: #
24: # $min and $max are the range of the output values.
25: # $maxSamples is how many samples a continuous run of the same slope will go
26: # $maxSlope is how much (absolute) the value can change sample to sample
27: # $minSamples (optional, default=1) is how short the shortest run will be
28: #
29: sub randomSequenceGenerator
30: {
31: my ($min, $max, $maxSamples, $maxSlope, $minSamples) = @_;
32: $minSamples ||= 1;
33: my ($lastOutput, $samplesLeft, $slope) = (($max+$min)/2, 0, 0);
34: return sub
35: {
36: if ($samplesLeft-- <= 0) # re-calculate slope and samplesLeft
37: {
38: $samplesLeft = int( rand( $maxSamples - $minSamples ) + $minSamples );
39: $slope = rand( $maxSlope * 2 ) - $maxSlope;
40: }
41: $slope = -$slope if ($lastOutput + $slope > $max)
42: or ($lastOutput + $slope < $min);
43: return $lastOutput += $slope;
44: }
45: }
46:
47: # generate a simple exponential filter as a closure
48: # my $sub = filterGenerator( $coefficient, $firstSample );
49: # my $filtered = &$sub( $value ); # repeat
50: # $coefficient is how many samples to average over
51: # $firstSample (optional, default=first sample) is the preset output
52: sub filterGenerator
53: {
54: my $coefficient = shift; # time period in samples, larger=slower
55: my $firstSample = shift;
56: my $lastValue = $firstSample;
57: return sub
58: {
59: my $newSample = shift;
60: return $lastValue = $newSample if !defined($lastValue);
61: $lastValue += $newSample/$coefficient;
62: $lastValue *= $coefficient/($coefficient+1);
63: return $lastValue;
64: }
65: }
66:
67: 1;
68: __END__
69: # test program:
70: use RandomSequence ':ALL';
71: my $sequenceGenerator = randomSequenceGenerator(0, 360.0, 30, 1.0);
72: my $filter = filterGenerator(8);
73: for my $i (1..10000)
74: {
75: my $sample = &$sequenceGenerator;
76: my $filtered = $filter->($sample);
77: print "$sample,$filtered\n";
78: } In reply to Random Sequence generation and Filtering by bikeNomad
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |