Verilator

Форк
0
/
verilated_probdist.cpp 
240 строк · 7.3 Кб
1
// -*- mode: C++; c-file-style: "cc-mode" -*-
2
//*************************************************************************
3
//
4
// Code available from: https://verilator.org
5
//
6
// Copyright 2003-2024 by Wilson Snyder. This program is free software; you can
7
// redistribute it and/or modify it under the terms of either the GNU
8
// Lesser General Public License Version 3 or the Perl Artistic License
9
// Version 2.0.
10
// SPDX-License-Identifier: LGPL-3.0-only OR Artistic-2.0
11
//
12
//=========================================================================
13
///
14
/// \file
15
/// \brief Verilated probability distribution implementation code
16
///
17
/// Verilator always adds this file to the Makefile for the linker.
18
///
19
/// Those macro/function/variable starting or ending in _ are internal,
20
/// however many of the other function/macros here are also internal.
21
///
22
//=========================================================================
23

24
#include "verilated_config.h"
25
#include "verilatedos.h"
26

27
#include "verilated.h"
28

29
//===========================================================================
30
// Dist
31

32
static double _vl_dbase_uniform(IData& seedr, int32_t start, int32_t end) VL_MT_SAFE {
33
    union u_s {
34
        float s;
35
        unsigned stemp;
36
    } u;
37

38
    const double d = 0.00000011920928955078125;
39
    if (VL_UNLIKELY(seedr == 0)) seedr = 259341593;
40

41
    double a;
42
    double b;
43
    if (VL_UNCOVERABLE(start >= end)) {  // With current usage shound't occur
44
        a = 0.0;  // LCOV_EXCL_LINE
45
        b = 2147483647.0;  // LCOV_EXCL_LINE
46
    } else {
47
        a = static_cast<double>(start);
48
        b = static_cast<double>(end);
49
    }
50
    seedr = 69069 * seedr + 1;
51
    u.stemp = seedr;
52
    u.stemp = (u.stemp >> 9) | 0x3f800000;
53

54
    double c = static_cast<double>(u.s);
55
    c = c + (c * d);
56
    c = ((b - a) * (c - 1.0)) + a;
57
    return c;
58
}
59

60
static double _vl_dbase_normal(IData& seedr, int32_t mean, int32_t deviation) VL_MT_SAFE {
61
    double v1 = 0.0;
62
    double v2 = 0.0;
63
    double s = 1.0;
64
    while ((s >= 1.0) || (s == 0.0)) {
65
        v1 = _vl_dbase_uniform(seedr, -1, 1);
66
        v2 = _vl_dbase_uniform(seedr, -1, 1);
67
        s = v1 * v1 + v2 * v2;
68
    }
69
    s = v1 * std::sqrt(-2.0 * log(s) / s);
70
    v1 = static_cast<double>(deviation);
71
    v2 = static_cast<double>(mean);
72
    return (s * v1 + v2);
73
}
74

75
static double _vl_dbase_exponential(IData& seedr, int32_t mean) VL_MT_SAFE {
76
    double n = _vl_dbase_uniform(seedr, 0, 1);
77
    if (n != 0) n = -log(n) * mean;
78
    return n;
79
}
80

81
static double _vl_dbase_chi_square(IData& seedr, int32_t deg_of_free) VL_MT_SAFE {
82
    double x;
83
    if (deg_of_free % 2) {
84
        x = _vl_dbase_normal(seedr, 0, 1);
85
        x = x * x;
86
    } else {
87
        x = 0.0;
88
    }
89
    for (int32_t k = 2; k <= deg_of_free; k += 2) x = x + 2 * _vl_dbase_exponential(seedr, 1);
90
    return x;
91
}
92

93
IData VL_DIST_CHI_SQUARE(IData& seedr, IData udf) VL_MT_SAFE {
94
    const int32_t df = static_cast<int32_t>(udf);
95
    if (VL_UNLIKELY(df <= 0)) {
96
        // Chi_square distribution must have positive degree of freedom
97
        return 0;
98
    }
99
    double r = _vl_dbase_chi_square(seedr, df);
100
    int32_t i;
101
    if (r >= 0) {
102
        i = static_cast<int32_t>(r + 0.5);
103
    } else {
104
        r = -r;  // LCOV_EXCL_LINE
105
        i = static_cast<int32_t>(r + 0.5);  // LCOV_EXCL_LINE
106
        i = -i;  // LCOV_EXCL_LINE
107
    }
108
    return static_cast<IData>(i);
109
}
110

111
IData VL_DIST_ERLANG(IData& seedr, IData uk, IData umean) VL_MT_SAFE {
112
    const int32_t k = static_cast<int32_t>(uk);
113
    const int32_t mean = static_cast<int32_t>(umean);
114
    if (VL_UNLIKELY(k <= 0)) {
115
        // k-stage erlangian distribution must have positive k
116
        return 0;
117
    }
118
    double x = 1.0;
119
    for (int32_t i = 1; i <= k; i++) x = x * _vl_dbase_uniform(seedr, 0, 1);
120
    const double a = static_cast<double>(mean);
121
    const double b = static_cast<double>(k);
122
    double r = -a * log(x) / b;
123
    int32_t i;
124
    if (r >= 0) {
125
        i = static_cast<int32_t>(r + 0.5);
126
    } else {
127
        r = -r;
128
        i = static_cast<int32_t>(r + 0.5);
129
        i = -i;
130
    }
131
    return static_cast<IData>(i);
132
}
133

134
IData VL_DIST_EXPONENTIAL(IData& seedr, IData umean) VL_MT_SAFE {
135
    const int32_t mean = static_cast<int32_t>(umean);
136
    if (VL_UNLIKELY(mean <= 0)) {
137
        // Exponential distribution must have a positive mean
138
        return 0;
139
    }
140
    int32_t i;
141
    double r = _vl_dbase_exponential(seedr, mean);
142
    if (r >= 0) {
143
        i = static_cast<int32_t>(r + 0.5);
144
    } else {
145
        r = -r;  // LCOV_EXCL_LINE
146
        i = static_cast<int32_t>(r + 0.5);  // LCOV_EXCL_LINE
147
        i = -i;  // LCOV_EXCL_LINE
148
    }
149
    return static_cast<IData>(i);
150
}
151

152
IData VL_DIST_NORMAL(IData& seedr, IData umean, IData usd) VL_MT_SAFE {
153
    const int32_t mean = static_cast<int32_t>(umean);
154
    const int32_t sd = static_cast<int32_t>(usd);
155
    double r = _vl_dbase_normal(seedr, mean, sd);
156
    int32_t i;
157
    if (r >= 0) {
158
        i = static_cast<int32_t>(r + 0.5);
159
    } else {
160
        r = -r;
161
        i = static_cast<int32_t>(r + 0.5);
162
        i = -i;
163
    }
164
    return static_cast<IData>(i);
165
}
166

167
IData VL_DIST_POISSON(IData& seedr, IData umean) VL_MT_SAFE {
168
    const int32_t mean = static_cast<int32_t>(umean);
169
    if (VL_UNLIKELY(mean <= 0)) {
170
        // Poisson distribution must have a positive mean
171
        return 0;
172
    }
173
    int32_t i = 0;
174
    double q = -static_cast<double>(mean);
175
    double p = exp(q);
176
    q = _vl_dbase_uniform(seedr, 0, 1);
177
    while (p < q) {
178
        ++i;
179
        q = _vl_dbase_uniform(seedr, 0, 1) * q;
180
    }
181
    return static_cast<IData>(i);
182
}
183

184
IData VL_DIST_T(IData& seedr, IData udf) VL_MT_SAFE {
185
    const int32_t df = static_cast<int32_t>(udf);
186
    if (VL_UNLIKELY(df <= 0)) {
187
        // t distribution must have positive degree of freedom
188
        return 0;
189
    }
190
    const double chi2 = _vl_dbase_chi_square(seedr, df);
191
    const double div = chi2 / static_cast<double>(df);
192
    const double root = std::sqrt(div);
193
    double r = _vl_dbase_normal(seedr, 0, 1) / root;
194
    int32_t i;
195
    if (r >= 0) {
196
        i = static_cast<int32_t>(r + 0.5);
197
    } else {
198
        r = -r;
199
        i = static_cast<int32_t>(r + 0.5);
200
        i = -i;
201
    }
202
    return static_cast<IData>(i);
203
}
204

205
IData VL_DIST_UNIFORM(IData& seedr, IData ustart, IData uend) VL_MT_SAFE {
206
    int32_t start = static_cast<int32_t>(ustart);
207
    int32_t end = static_cast<int32_t>(uend);
208
    if (VL_UNLIKELY(start >= end)) return start;
209
    int32_t i;
210
    if (end != std::numeric_limits<int32_t>::max()) {
211
        ++end;
212
        const double r = _vl_dbase_uniform(seedr, start, end);
213
        if (r >= 0) {
214
            i = static_cast<int32_t>(r);
215
        } else {
216
            i = static_cast<int32_t>(r - 1);
217
        }
218
        if (i < start) i = start;
219
        if (i >= end) i = end - 1;
220
    } else if (start != std::numeric_limits<int32_t>::min()) {
221
        --start;
222
        const double r = _vl_dbase_uniform(seedr, start, end) + 1.0;
223
        if (r >= 0) {
224
            i = static_cast<int32_t>(r);
225
        } else {
226
            i = static_cast<int32_t>(r - 1);  // LCOV_EXCL_LINE
227
        }
228
        if (i <= start) i = start + 1;
229
        if (i > end) i = end;
230
    } else {
231
        double r = (_vl_dbase_uniform(seedr, start, end) + 2147483648.0) / 4294967295.0;
232
        r = r * 4294967296.0 - 2147483648.0;
233
        if (r >= 0) {
234
            i = static_cast<int32_t>(r);
235
        } else {
236
            i = static_cast<int32_t>(r - 1);
237
        }
238
    }
239
    return static_cast<IData>(i);
240
}
241

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.