Skip to content

Commit f80b4fe

Browse files
🚴 perf(append): Skip one tree level.
1 parent e46cb3f commit f80b4fe

File tree

7 files changed

+137
-4
lines changed

7 files changed

+137
-4
lines changed

src/0-core/_fast/_fill_right.js

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import assert from 'assert';
2+
3+
import {One} from '../../1-digit/1-One.js';
4+
import {Two} from '../../1-digit/2-Two.js';
5+
import {Three} from '../../1-digit/3-Three.js';
6+
import {Four} from '../../1-digit/4-Four.js';
7+
import {node3} from '../../2-node/node3.js';
8+
import {Empty} from '../../3-tree/implementations/0-Empty.js';
9+
import {Single} from '../../3-tree/implementations/1-Single.js';
10+
import {Deep} from '../../3-tree/implementations/2-Deep.js';
11+
import {Lazy} from '../../4-lazy/0-Lazy.js';
12+
13+
/**
14+
* _fill_right.
15+
*
16+
* @param {any} M
17+
* @param {One|Two|Three|Four} left
18+
* @param {Empty|Single|Deep|Lazy} middle
19+
* @param {any} x1
20+
* @param {Iterator} iterator
21+
* @return {Deep}
22+
*/
23+
export default function _fill_right(M, left, middle, x1, iterator) {
24+
assert(
25+
left instanceof One ||
26+
left instanceof Two ||
27+
left instanceof Three ||
28+
left instanceof Four,
29+
);
30+
assert(
31+
middle instanceof Empty ||
32+
middle instanceof Single ||
33+
middle instanceof Deep ||
34+
middle instanceof Lazy,
35+
);
36+
let event;
37+
let x2;
38+
let x3;
39+
let y1;
40+
let y2;
41+
let y3;
42+
for (;;) {
43+
event = iterator.next();
44+
if (event.done) return new Deep(M, left, middle, new One(x1));
45+
x2 = event.value;
46+
47+
event = iterator.next();
48+
if (event.done) return new Deep(M, left, middle, new Two(x1, x2));
49+
x3 = event.value;
50+
51+
event = iterator.next();
52+
if (event.done) return new Deep(M, left, middle, new Three(x1, x2, x3));
53+
y1 = event.value;
54+
55+
middle = middle.push(node3(M, x1, x2, x3));
56+
57+
event = iterator.next();
58+
if (event.done) return new Deep(M, left, middle, new One(y1));
59+
y2 = event.value;
60+
61+
event = iterator.next();
62+
if (event.done) return new Deep(M, left, middle, new Two(y1, y2));
63+
y3 = event.value;
64+
65+
event = iterator.next();
66+
if (event.done) return new Deep(M, left, middle, new Three(y1, y2, y3));
67+
x1 = event.value;
68+
69+
middle = middle.push(node3(M, y1, y2, y3));
70+
}
71+
}

src/0-core/_fast/_from_by_filling.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import {One} from '../../1-digit/1-One.js';
2+
import {Empty} from '../../3-tree/implementations/0-Empty.js';
3+
import {Single} from '../../3-tree/implementations/1-Single.js';
4+
import {cache} from '../measure/cache.js';
5+
import _fill_right from './_fill_right.js';
6+
7+
export default function _form_by_filling(M, iterable) {
8+
const it = iterable[Symbol.iterator]();
9+
10+
let event = it.next();
11+
if (event.done) return new Empty(M);
12+
const a = event.value;
13+
14+
event = it.next();
15+
if (event.done) return new Single(M, a);
16+
const b = event.value;
17+
18+
const left = new One(a);
19+
const middle = new Empty(cache(M));
20+
21+
return _fill_right(M, left, middle, b, it);
22+
}

src/3-tree/base/Tree.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {append, prepend} from '../../0-core/index.js';
1+
import {prepend} from '../../0-core/index.js';
22

33
/**
44
* Base class for all implementations.
@@ -76,9 +76,9 @@ Tree.prototype.dropUntil = function (predicate) {
7676
*
7777
* @returns {Tree} The output tree.
7878
*/
79-
Tree.prototype.append = function (iterable) {
80-
return append(this, iterable);
81-
};
79+
// Tree.prototype.append = function (iterable) {
80+
// return append(this, iterable);
81+
// };
8282

8383
/**
8484
* Returns a tree that contains all values of the input iterable in-order

src/3-tree/implementations/0-Empty.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import {Tree} from '../base/index.js';
33
import {_EMPTY} from '../../0-core/index.js';
44
import {_from_medium_list} from '../../0-core/_fast/_from_medium_list.js';
55
import _append_small_list from '../../0-core/_fast/_append_small_list.js';
6+
import _from_by_filling from '../../0-core/_fast/_from_by_filling.js';
67
import {Single, Deep} from './index.js';
78

89
export function Empty(M) {
@@ -44,6 +45,10 @@ Empty.prototype.cons = function (value) {
4445
return new Single(this.M, value);
4546
};
4647

48+
Empty.prototype.append = function (iterable) {
49+
return _from_by_filling(this.M, iterable);
50+
};
51+
4752
Empty.prototype.concat = function (other) {
4853
return other;
4954
};

src/3-tree/implementations/1-Single.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {cache, Split} from '../../0-core/index.js';
44
import {One} from '../../1-digit/index.js';
55
import _append_small_list from '../../0-core/_fast/_append_small_list.js';
66
import {_from_medium_list} from '../../0-core/_fast/_from_medium_list.js';
7+
import _fill_right from '../../0-core/_fast/_fill_right.js';
78
import {Empty, Deep} from './index.js';
89

910
export function Single(M, value) {
@@ -56,6 +57,19 @@ Single.prototype.push = function (value) {
5657
);
5758
};
5859

60+
Single.prototype.append = function (iterable) {
61+
const it = iterable[Symbol.iterator]();
62+
63+
const event = it.next();
64+
if (event.done) return this;
65+
const x1 = event.value;
66+
67+
const left = new One(this.a);
68+
const middle = new Empty(cache(this.M));
69+
70+
return _fill_right(this.M, left, middle, x1, it);
71+
};
72+
5973
Single.prototype.concat = function (other) {
6074
return other.cons(this.a);
6175
};

src/3-tree/implementations/2-Deep.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
import {One, Two, Four} from '../../1-digit/index.js';
1212
import {delay, Lazy} from '../../4-lazy/index.js';
1313
import _prepend_small_list from '../../0-core/_fast/_prepend_small_list.js';
14+
import _fill_right from '../../0-core/_fast/_fill_right.js';
1415
import {Empty} from './index.js';
1516

1617
export function Deep(M, left, middle, right) {
@@ -109,6 +110,22 @@ Deep.prototype.push = function (value) {
109110
return new Deep(this.M, this.left, this.middle, this.right.push(value));
110111
};
111112

113+
Deep.prototype.append = function (iterable) {
114+
const it = iterable[Symbol.iterator]();
115+
116+
let event = it.next();
117+
if (event.done) return this;
118+
const a = event.value;
119+
120+
event = it.next();
121+
if (event.done) return this.push(a);
122+
const b = event.value;
123+
124+
const middle = this.middle.push(this.right._nodes(this.M, new One(a)));
125+
126+
return _fill_right(this.M, this.left, middle, b, it);
127+
};
128+
112129
Deep.prototype.concat = function (other) {
113130
return other._concat_with_deep(this);
114131
};

src/4-lazy/0-Lazy.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@ Lazy.prototype.split = function (p) {
5656
return this.force().split(p);
5757
};
5858

59+
Lazy.prototype.append = function (iterable) {
60+
return this.force().append(iterable);
61+
};
62+
5963
Lazy.prototype.concat = function (other) {
6064
return this.force().concat(other);
6165
};

0 commit comments

Comments
 (0)