Passed
Push — main ( c73ca2...a94e44 )
by Dylan
03:37
created

src/SternBrocotTree.ts   A

Complexity

Total Complexity 11
Complexity/F 3.67

Size

Lines of Code 67
Function Count 3

Duplication

Duplicated Lines 0
Ratio 0 %

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 11
eloc 45
mnd 8
bc 8
fnc 3
dl 0
loc 67
ccs 39
cts 39
cp 1
rs 10
bpm 2.6666
cpm 3.6666
noi 0
c 0
b 0
f 0

3 Functions

Rating   Name   Duplication   Size   Complexity  
A SternBrocotTree.ts ➔ pathToValue 0 21 4
A SternBrocotTree.ts ➔ rationalApproximation 0 21 4
A SternBrocotTree.ts ➔ continuedFraction 0 15 3
1 3
import {MAX_LOOPS} from './config'
2 3
import {ZERO, ONE} from './bigint'
3 3
import {Rat} from './Rat'
4
5
/**
6
 * Traverse the tree, returning the rational number that best approximates the floating point number.
7
 */
8 3
export function rationalApproximation(n: number): Rat {
9 3
  const r = new Rat(ONE)
10 3
  const m = [ONE, ZERO, ZERO, ONE]
11 3
  for (let i=0; i<MAX_LOOPS; i++) {
12 36
    if (r.approximates(n)) break
13 33
    if (+r > n) {
14 18
      m[0] += m[1]
15 18
      m[2] += m[3]
16
    }
17
    else {
18 15
      m[1] += m[0]
19 15
      m[3] += m[2]
20
    }
21 33
    r.n = m[0] + m[1]
22 33
    r.d = m[2] + m[3]
23
  }
24 3
  return r
25
}
26
27
/**
28
 * Traverse the tree towards the float, yielding false for each left and true for each right.
29
 */
30 3
export function *pathToValue(n: number): Generator<boolean> {
31 7
  const r = new Rat(ONE)
32 7
  const m = [ONE, ZERO, ZERO, ONE]
33 7
  for (let i=0; i<MAX_LOOPS; i++) {
34 526
    if (r.approximates(n)) break
35 519
    if (+r > n) {
36 94
      yield false
37 94
      m[0] += m[1]
38 94
      m[2] += m[3]
39
    }
40
    else {
41 425
      yield true
42 425
      m[1] += m[0]
43 425
      m[3] += m[2]
44
    }
45 519
    r.n = m[0] + m[1]
46 519
    r.d = m[2] + m[3]
47
  }
48
}
49
50
/**
51
 * Traverse the tree towards the float, yielding the values of the continued fraction, ie. the length of runs left/right.
52
 */
53 3
export function *continuedFraction(n: number): Generator<number> {
54 5
  let last = true
55 5
  let run = 0
56 5
  for (const direction of pathToValue(n)) {
57 515
    if (direction === last) {
58 421
      run++
59
    }
60
    else {
61 94
      yield run
62 94
      run = 1
63 94
      last = direction
64
    }
65
  }
66
}
67