xref: /aosp_15_r20/external/icu/icu4j/perf-tests/perldriver/Dataset.pm (revision 0e209d3975ff4a8c132096b14b0e9364a753506e)
1*0e209d39SAndroid Build Coastguard Worker#!/usr/local/bin/perl
2*0e209d39SAndroid Build Coastguard Worker#  ********************************************************************
3*0e209d39SAndroid Build Coastguard Worker#  * COPYRIGHT:
4*0e209d39SAndroid Build Coastguard Worker#  * © 2016 and later: Unicode, Inc. and others.
5*0e209d39SAndroid Build Coastguard Worker#  * License & terms of use: http://www.unicode.org/copyright.html
6*0e209d39SAndroid Build Coastguard Worker#  * Copyright (c) 2006, International Business Machines Corporation and
7*0e209d39SAndroid Build Coastguard Worker#  * others. All Rights Reserved.
8*0e209d39SAndroid Build Coastguard Worker#  ********************************************************************
9*0e209d39SAndroid Build Coastguard Worker
10*0e209d39SAndroid Build Coastguard Workerpackage Dataset;
11*0e209d39SAndroid Build Coastguard Workeruse Statistics::Descriptive;
12*0e209d39SAndroid Build Coastguard Workeruse Statistics::Distributions;
13*0e209d39SAndroid Build Coastguard Workeruse strict;
14*0e209d39SAndroid Build Coastguard Worker
15*0e209d39SAndroid Build Coastguard Worker# Create a new Dataset with the given data.
16*0e209d39SAndroid Build Coastguard Workersub new {
17*0e209d39SAndroid Build Coastguard Worker    my ($class) = shift;
18*0e209d39SAndroid Build Coastguard Worker    my $self = bless {
19*0e209d39SAndroid Build Coastguard Worker        _data => \@_,
20*0e209d39SAndroid Build Coastguard Worker        _scale => 1.0,
21*0e209d39SAndroid Build Coastguard Worker        _mean => 0.0,
22*0e209d39SAndroid Build Coastguard Worker        _error => 0.0,
23*0e209d39SAndroid Build Coastguard Worker    }, $class;
24*0e209d39SAndroid Build Coastguard Worker
25*0e209d39SAndroid Build Coastguard Worker    my $n = @_;
26*0e209d39SAndroid Build Coastguard Worker
27*0e209d39SAndroid Build Coastguard Worker    if ($n >= 1) {
28*0e209d39SAndroid Build Coastguard Worker        my $stats = Statistics::Descriptive::Full->new();
29*0e209d39SAndroid Build Coastguard Worker        $stats->add_data(@{$self->{_data}});
30*0e209d39SAndroid Build Coastguard Worker        $self->{_mean} = $stats->mean();
31*0e209d39SAndroid Build Coastguard Worker
32*0e209d39SAndroid Build Coastguard Worker        if ($n >= 2) {
33*0e209d39SAndroid Build Coastguard Worker            # Use a t distribution rather than Gaussian because (a) we
34*0e209d39SAndroid Build Coastguard Worker            # assume an underlying normal dist, (b) we do not know the
35*0e209d39SAndroid Build Coastguard Worker            # standard deviation -- we estimate it from the data, and (c)
36*0e209d39SAndroid Build Coastguard Worker            # we MAY have a small sample size (also works for large n).
37*0e209d39SAndroid Build Coastguard Worker            my $t = Statistics::Distributions::tdistr($n-1, 0.005);
38*0e209d39SAndroid Build Coastguard Worker            $self->{_error} = $t * $stats->standard_deviation();
39*0e209d39SAndroid Build Coastguard Worker        }
40*0e209d39SAndroid Build Coastguard Worker    }
41*0e209d39SAndroid Build Coastguard Worker
42*0e209d39SAndroid Build Coastguard Worker    $self;
43*0e209d39SAndroid Build Coastguard Worker}
44*0e209d39SAndroid Build Coastguard Worker
45*0e209d39SAndroid Build Coastguard Worker# Set a scaling factor for all data; 1.0 means no scaling.
46*0e209d39SAndroid Build Coastguard Worker# Scale must be > 0.
47*0e209d39SAndroid Build Coastguard Workersub setScale {
48*0e209d39SAndroid Build Coastguard Worker    my ($self, $scale) = @_;
49*0e209d39SAndroid Build Coastguard Worker    $self->{_scale} = $scale;
50*0e209d39SAndroid Build Coastguard Worker}
51*0e209d39SAndroid Build Coastguard Worker
52*0e209d39SAndroid Build Coastguard Worker# Multiply the scaling factor by a value.
53*0e209d39SAndroid Build Coastguard Workersub scaleBy {
54*0e209d39SAndroid Build Coastguard Worker    my ($self, $a) = @_;
55*0e209d39SAndroid Build Coastguard Worker    $self->{_scale} *= $a;
56*0e209d39SAndroid Build Coastguard Worker}
57*0e209d39SAndroid Build Coastguard Worker
58*0e209d39SAndroid Build Coastguard Worker# Return the mean.
59*0e209d39SAndroid Build Coastguard Workersub getMean {
60*0e209d39SAndroid Build Coastguard Worker    my $self = shift;
61*0e209d39SAndroid Build Coastguard Worker    return $self->{_mean} * $self->{_scale};
62*0e209d39SAndroid Build Coastguard Worker}
63*0e209d39SAndroid Build Coastguard Worker
64*0e209d39SAndroid Build Coastguard Worker# Return a 99% error based on the t distribution.  The dataset
65*0e209d39SAndroid Build Coastguard Worker# is described as getMean() +/- getError().
66*0e209d39SAndroid Build Coastguard Workersub getError {
67*0e209d39SAndroid Build Coastguard Worker    my $self = shift;
68*0e209d39SAndroid Build Coastguard Worker    return $self->{_error} * $self->{_scale};
69*0e209d39SAndroid Build Coastguard Worker}
70*0e209d39SAndroid Build Coastguard Worker
71*0e209d39SAndroid Build Coastguard Worker# Divide two Datasets and return a new one, maintaining the
72*0e209d39SAndroid Build Coastguard Worker# mean+/-error.  The new Dataset has no data points.
73*0e209d39SAndroid Build Coastguard Workersub divide {
74*0e209d39SAndroid Build Coastguard Worker    my $self = shift;
75*0e209d39SAndroid Build Coastguard Worker    my $rhs = shift;
76*0e209d39SAndroid Build Coastguard Worker
77*0e209d39SAndroid Build Coastguard Worker    my $minratio = ($self->{_mean} - $self->{_error}) /
78*0e209d39SAndroid Build Coastguard Worker                   ($rhs->{_mean} + $rhs->{_error});
79*0e209d39SAndroid Build Coastguard Worker    my $maxratio = ($self->{_mean} + $self->{_error}) /
80*0e209d39SAndroid Build Coastguard Worker                   ($rhs->{_mean} - $rhs->{_error});
81*0e209d39SAndroid Build Coastguard Worker
82*0e209d39SAndroid Build Coastguard Worker    my $result = Dataset->new();
83*0e209d39SAndroid Build Coastguard Worker    $result->{_mean} = ($minratio + $maxratio) / 2;
84*0e209d39SAndroid Build Coastguard Worker    $result->{_error} = $result->{_mean} - $minratio;
85*0e209d39SAndroid Build Coastguard Worker    $result->{_scale} = $self->{_scale} / $rhs->{_scale};
86*0e209d39SAndroid Build Coastguard Worker    $result;
87*0e209d39SAndroid Build Coastguard Worker}
88*0e209d39SAndroid Build Coastguard Worker
89*0e209d39SAndroid Build Coastguard Worker# subtracts two Datasets and return a new one, maintaining the
90*0e209d39SAndroid Build Coastguard Worker# mean+/-error.  The new Dataset has no data points.
91*0e209d39SAndroid Build Coastguard Workersub subtract {
92*0e209d39SAndroid Build Coastguard Worker    my $self = shift;
93*0e209d39SAndroid Build Coastguard Worker    my $rhs = shift;
94*0e209d39SAndroid Build Coastguard Worker
95*0e209d39SAndroid Build Coastguard Worker    my $result = Dataset->new();
96*0e209d39SAndroid Build Coastguard Worker    $result->{_mean} = $self->{_mean} - $rhs->{_mean};
97*0e209d39SAndroid Build Coastguard Worker    $result->{_error} = $self->{_error} + $rhs->{_error};
98*0e209d39SAndroid Build Coastguard Worker    $result->{_scale} = $self->{_scale};
99*0e209d39SAndroid Build Coastguard Worker    $result;
100*0e209d39SAndroid Build Coastguard Worker}
101*0e209d39SAndroid Build Coastguard Worker
102*0e209d39SAndroid Build Coastguard Worker# adds two Datasets and return a new one, maintaining the
103*0e209d39SAndroid Build Coastguard Worker# mean+/-error.  The new Dataset has no data points.
104*0e209d39SAndroid Build Coastguard Workersub add {
105*0e209d39SAndroid Build Coastguard Worker    my $self = shift;
106*0e209d39SAndroid Build Coastguard Worker    my $rhs = shift;
107*0e209d39SAndroid Build Coastguard Worker
108*0e209d39SAndroid Build Coastguard Worker    my $result = Dataset->new();
109*0e209d39SAndroid Build Coastguard Worker    $result->{_mean} = $self->{_mean} + $rhs->{_mean};
110*0e209d39SAndroid Build Coastguard Worker    $result->{_error} = $self->{_error} + $rhs->{_error};
111*0e209d39SAndroid Build Coastguard Worker    $result->{_scale} = $self->{_scale};
112*0e209d39SAndroid Build Coastguard Worker    $result;
113*0e209d39SAndroid Build Coastguard Worker}
114*0e209d39SAndroid Build Coastguard Worker
115*0e209d39SAndroid Build Coastguard Worker# Divides a dataset by a scalar.
116*0e209d39SAndroid Build Coastguard Worker# The new Dataset has no data points.
117*0e209d39SAndroid Build Coastguard Workersub divideByScalar {
118*0e209d39SAndroid Build Coastguard Worker    my $self = shift;
119*0e209d39SAndroid Build Coastguard Worker    my $s = shift;
120*0e209d39SAndroid Build Coastguard Worker
121*0e209d39SAndroid Build Coastguard Worker    my $result = Dataset->new();
122*0e209d39SAndroid Build Coastguard Worker    $result->{_mean} = $self->{_mean}/$s;
123*0e209d39SAndroid Build Coastguard Worker    $result->{_error} = $self->{_error}/$s;
124*0e209d39SAndroid Build Coastguard Worker    $result->{_scale} = $self->{_scale};
125*0e209d39SAndroid Build Coastguard Worker    $result;
126*0e209d39SAndroid Build Coastguard Worker}
127*0e209d39SAndroid Build Coastguard Worker
128*0e209d39SAndroid Build Coastguard Worker# Divides a dataset by a scalar.
129*0e209d39SAndroid Build Coastguard Worker# The new Dataset has no data points.
130*0e209d39SAndroid Build Coastguard Workersub multiplyByScalar {
131*0e209d39SAndroid Build Coastguard Worker    my $self = shift;
132*0e209d39SAndroid Build Coastguard Worker    my $s = shift;
133*0e209d39SAndroid Build Coastguard Worker
134*0e209d39SAndroid Build Coastguard Worker    my $result = Dataset->new();
135*0e209d39SAndroid Build Coastguard Worker    $result->{_mean} = $self->{_mean}*$s;
136*0e209d39SAndroid Build Coastguard Worker    $result->{_error} = $self->{_error}*$s;
137*0e209d39SAndroid Build Coastguard Worker    $result->{_scale} = $self->{_scale};
138*0e209d39SAndroid Build Coastguard Worker    $result;
139*0e209d39SAndroid Build Coastguard Worker}
140*0e209d39SAndroid Build Coastguard Worker
141*0e209d39SAndroid Build Coastguard Worker1;
142