• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

synesenom / ran / b979f73d-3ccf-45bd-b472-e57b53f0df9f

pending completion
b979f73d-3ccf-45bd-b472-e57b53f0df9f

Pull #63

circleci

Enys Mones
CodeScene badge updated
Pull Request #63: Docs improvements

1099 of 1141 branches covered (96.32%)

Branch coverage included in aggregate %.

4 of 4 new or added lines in 3 files covered. (100.0%)

2916 of 2936 relevant lines covered (99.32%)

665049.11 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.75
/src/dist/noncentral-beta.js
1
import recursiveSum from '../algorithms/recursive-sum'
2
import { regularizedBetaIncomplete, beta as fnBeta, logGamma } from '../special'
3
import chi2 from './_chi2'
4
import noncentralChi2 from './_noncentral-chi2'
5
import Distribution from './_distribution'
6

7
/**
8
 * Generator for the [non-central beta distribution]{@link https://en.wikipedia.org/wiki/Noncentral_beta_distribution}:
9
 *
10
 * $$f(x; \alpha, \beta, \lambda) = e^{-\frac{\lambda}{2}} \sum\_{k = 0}^\infty \frac{1}{k!} \bigg(\frac{\lambda}{2}\bigg)^k \frac{x^{\alpha + k - 1} (1 - x)^{\beta - 1}}{\mathrm{B}(\alpha + k, \beta)},$$
11
 *
12
 * where $\alpha, \beta > 0$ and $\lambda \ge 0$. Support: $x \in \[0, 1\]$.
13
 *
14
 * @class NoncentralBeta
15
 * @memberof ran.dist
16
 * @param {number=} alpha First shape parameter. Default value is 1.
17
 * @param {number=} beta Second shape parameter. Default value is 1.
18
 * @param {number=} lambda Non-centrality parameter. Default value is 1.
19
 * @constructor
20
 */
21
export default class extends Distribution {
22
  // TODO Use outward iteration
23
  constructor (alpha = 1, beta = 1, lambda = 1) {
84✔
24
    super('continuous', arguments.length)
112✔
25

26
    // Validate parameters.
27
    this.p = { alpha, beta, lambda }
112✔
28
    Distribution.validate({ alpha, beta, lambda }, [
112✔
29
      'alpha > 0',
30
      'beta > 0',
31
      'lambda >= 0'
32
    ])
33

34
    // Set support.
35
    this.s = [{
102✔
36
      value: 0,
37
      closed: true
38
    }, {
39
      value: 1,
40
      closed: true
41
    }]
42

43
    // Speed-up constants.
44
    this.c = [
102✔
45
      Math.exp(-lambda / 2),
46
      fnBeta(alpha, beta)
47
    ]
48
  }
49

50
  _generator () {
51
    // Direct sampling from non-central chi2 and chi2.
52
    const x = noncentralChi2(this.r, 2 * this.p.alpha, this.p.lambda)
75,080✔
53
    const y = chi2(this.r, 2 * this.p.beta)
75,080✔
54
    const z = x / (x + y)
75,080✔
55

56
    // Handle 1 - z << 1 case.
57
    if (Math.abs(1 - z) < Number.EPSILON) {
75,080!
58
      return 1 - y / x
×
59
    } else {
60
      return z
75,080✔
61
    }
62
  }
63

64
  _pdf (x) {
65
    // Speed-up variables.
66
    const l2 = this.p.lambda / 2
529✔
67
    const i0 = Math.round(l2)
529✔
68
    let iAlpha0 = this.p.alpha + i0
529✔
69

70
    // Init variables.
71
    const p0 = Math.exp(-l2 + i0 * Math.log(l2) - logGamma(i0 + 1))
529✔
72
    const xa0 = Math.pow(x, iAlpha0 - 1)
529✔
73
    const xb = Math.pow(1 - x, this.p.beta - 1)
529✔
74
    const b0 = fnBeta(iAlpha0, this.p.beta)
529✔
75

76
    // Forward sum.
77
    let z = recursiveSum({
529✔
78
      p: p0,
79
      xa: xa0,
80
      b: b0
81
    }, (t, i) => {
82
      t.p *= l2 / (i + i0)
7,793✔
83
      return t
7,793✔
84
    }, t => t.p * t.xa * xb / t.b, (t, i) => {
8,322✔
85
      const iAlpha = iAlpha0 + i
7,793✔
86
      t.xa *= x
7,793✔
87
      t.b *= iAlpha / (iAlpha + this.p.beta)
7,793✔
88
      return t
7,793✔
89
    })
90

91
    // Backward sum.
92
    if (i0 > 0) {
529✔
93
      iAlpha0--
431✔
94
      const xa = xa0 / x
431✔
95
      const b = b0 * (iAlpha0 + this.p.beta) / iAlpha0
431✔
96
      z += recursiveSum({
431✔
97
        p: p0 * i0 / l2,
98
        xa,
99
        b
100
      }, (t, i) => {
101
        const j = i0 - i - 1
464✔
102
        const iAlpha = iAlpha0 - i
464✔
103
        if (j >= 0) {
464✔
104
          t.p /= l2 / (j + 1)
33✔
105
          t.xa /= x
33✔
106
          t.b /= iAlpha / (iAlpha + this.p.beta)
33✔
107
        } else {
108
          t.p = 0
431✔
109
          t.ib = 0
431✔
110
        }
111
        return t
464✔
112
      }, t => t.p * t.xa * xb / t.b)
895✔
113
    }
114

115
    return z
529✔
116
  }
117

118
  _cdf (x) {
119
    // Speed-up variables
120
    const l2 = this.p.lambda / 2
67,121✔
121
    const i0 = Math.round(l2)
67,121✔
122
    let iAlpha0 = this.p.alpha + i0
67,121✔
123

124
    // Init variables
125
    const p0 = Math.exp(-l2 + i0 * Math.log(l2) - logGamma(i0 + 1))
67,121✔
126
    const xa0 = Math.pow(x, iAlpha0)
67,121✔
127
    const xb = Math.pow(1 - x, this.p.beta)
67,121✔
128
    const b0 = fnBeta(iAlpha0, this.p.beta)
67,121✔
129
    const ib0 = regularizedBetaIncomplete(iAlpha0, this.p.beta, x)
67,121✔
130

131
    // Forward sum.
132
    let z = recursiveSum({
67,121✔
133
      p: p0,
134
      xa: xa0,
135
      b: b0,
136
      ib: ib0
137
    }, (t, i) => {
138
      t.p *= l2 / (i + i0)
900,071✔
139
      return t
900,071✔
140
    }, t => t.p * t.ib, (t, i) => {
967,192✔
141
      const iAlpha = iAlpha0 + i
900,071✔
142
      t.ib -= t.xa * xb / (iAlpha * t.b)
900,071✔
143
      t.xa *= x
900,071✔
144
      t.b *= iAlpha / (iAlpha + this.p.beta)
900,071✔
145
      return t
900,071✔
146
    })
147

148
    // Backward sum.
149
    if (i0 > 0) {
67,121✔
150
      iAlpha0--
63,163✔
151
      const xa = xa0 / x
63,163✔
152
      const b = b0 * (iAlpha0 + this.p.beta) / iAlpha0
63,163✔
153
      z += recursiveSum({
63,163✔
154
        p: p0 * i0 / l2,
155
        xa,
156
        b,
157
        ib: ib0 + xa * xb / (iAlpha0 * b)
158
      }, (t, i) => {
159
        const j = i0 - i - 1
77,273✔
160
        const iAlpha = iAlpha0 - i
77,273✔
161
        if (j >= 0) {
77,273✔
162
          t.p /= l2 / (j + 1)
14,110✔
163
          t.xa /= x
14,110✔
164
          t.b /= iAlpha / (iAlpha + this.p.beta)
14,110✔
165
          t.ib += t.xa * xb / (iAlpha * t.b)
14,110✔
166
        } else {
167
          t.p = 0
63,163✔
168
          t.ib = 0
63,163✔
169
        }
170
        return t
77,273✔
171
      }, t => t.p * t.ib)
140,436✔
172
    }
173

174
    return Math.min(1, z)
67,121✔
175
  }
176
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc