package fj.data.fingertrees;
import fj.*;
import fj.data.Option;
import fj.data.Stream;
import fj.data.vector.V2;
import fj.data.vector.V3;
import fj.data.vector.V4;
import static fj.Function.constant;
import static fj.data.List.list;
import static fj.Function.flip;
import static fj.data.Stream.nil;
/**
* A finger tree with 1-4-digits on the left and right, and a finger tree of 2-3-nodes in the middle.
*/
public final class Deep<V, A> extends FingerTree<V, A> {
private final V v;
private final Digit<V, A> prefix;
private final FingerTree<V, Node<V, A>> middle;
private final Digit<V, A> suffix;
Deep(final Measured<V, A> m, final V v, final Digit<V, A> prefix,
final FingerTree<V, Node<V, A>> middle,
final Digit<V, A> suffix) {
super(m);
this.v = v;
this.prefix = prefix;
this.middle = middle;
this.suffix = suffix;
}
/**
* Returns the first few elements of this tree.
*
* @return the first few elements of this tree.
*/
public Digit<V, A> prefix() {
return prefix;
}
/**
* Returns a finger tree of the inner nodes of this tree.
*
* @return a finger tree of the inner nodes of this tree.
*/
public FingerTree<V, Node<V, A>> middle() {
return middle;
}
/**
* Returns the last few elements of this tree.
*
* @return the last few elements of this tree.
*/
public Digit<V, A> suffix() {
return suffix;
}
@Override public <B> B foldRight(final F<A, F<B, B>> aff, final B z) {
return prefix.foldRight(aff, middle.foldRight(flip(Node.foldRight_(aff)), suffix.foldRight(aff, z)));
}
@Override public A reduceRight(final F<A, F<A, A>> aff) {
return prefix.foldRight(aff, middle.foldRight(flip(Node.foldRight_(aff)), suffix.reduceRight(aff)));
}
@Override public <B> B foldLeft(final F<B, F<A, B>> bff, final B z) {
return suffix.foldLeft(bff, middle.foldLeft(Node.foldLeft_(bff), prefix.foldLeft(bff, z)));
}
@Override public A reduceLeft(final F<A, F<A, A>> aff) {
return suffix.foldLeft(aff, middle.foldLeft(Node.foldLeft_(aff), prefix.reduceLeft(aff)));
}
@Override public <B> FingerTree<V, B> map(final F<A, B> abf, final Measured<V, B> m) {
return new Deep<>(m, v, prefix.map(abf, m), middle.map(Node.liftM(abf, m), m.nodeMeasured()),
suffix.map(abf, m));
}
/**
* Returns the sum of the measurements of this tree's elements, according to the monoid.
*
* @return the sum of the measurements of this tree's elements, according to the monoid.
*/
public V measure() {
return v;
}
/**
* Pattern matching on the tree. Matches the function on the Deep tree.
*/
@Override public <B> B match(final F<Empty<V, A>, B> empty, final F<Single<V, A>, B> single,
final F<Deep<V, A>, B> deep) {
return deep.f(this);
}
@Override public FingerTree<V, A> cons(final A a) {
final Measured<V, A> m = measured();
final V measure = m.sum(m.measure(a), v);
final MakeTree<V, A> mk = mkTree(m);
return prefix.match(
one -> new Deep<>(m, measure, mk.two(a, one.value()), middle, suffix),
two -> new Deep<>(m, measure, mk.three(a, two.values()._1(), two.values()._2()), middle, suffix),
three -> new Deep<>(m, measure, mk.four(a, three.values()._1(), three.values()._2(), three.values()._3()), middle, suffix),
four -> new Deep<>(m, measure, mk.two(a, four.values()._1()), middle.cons(mk.node3(four.values()._2(), four.values()._3(), four.values()._4())), suffix));
}
public FingerTree<V, A> snoc(final A a) {
final Measured<V, A> m = measured();
final V measure = m.sum(m.measure(a), v);
final MakeTree<V, A> mk = mkTree(m);
return suffix.match(
one -> new Deep<>(m, measure, prefix, middle, mk.two(one.value(), a)),
two -> new Deep<>(m, measure, prefix, middle, mk.three(two.values()._1(), two.values()._2(), a)),
three -> new Deep<>(m, measure, prefix, middle, mk.four(three.values()._1(), three.values()._2(), three.values()._3(), a)),
four -> new Deep<>(m, measure, prefix, middle.snoc(mk.node3(four.values()._1(), four.values()._2(), four.values()._3())), mk.two(four.values()._4(), a)));
}
@Override public A head() {
return prefix.match(
One::value,
two -> two.values()._1(),
three -> three.values()._1(),
four -> four.values()._1());
}
@Override public A last() {
return suffix.match(
One::value,
two -> two.values()._2(),
three -> three.values()._3(),
four -> four.values()._4());
}
private static <V, A> FingerTree<V, A> deepL(final Measured<V, A> measured, final Option<Digit<V, A>> lOpt, final FingerTree<V, Node<V, A>> m, final Digit<V, A> r) {
return lOpt.option(
P.lazy(() -> m.isEmpty() ? r.toTree() : mkTree(measured).deep(m.head().toDigit(), m.tail(), r)),
(F<Digit<V, A>, FingerTree<V, A>>) l -> mkTree(measured).deep(l, m, r)
);
}
private static <V, A> FingerTree<V, A> deepR(final Measured<V, A> measured, final Option<Digit<V, A>> rOpt, final FingerTree<V, Node<V, A>> m, final Digit<V, A> l) {
return rOpt.option(
P.lazy(() -> m.isEmpty() ? l.toTree() : mkTree(measured).deep(l, m.init(), m.last().toDigit())),
(F<Digit<V, A>, FingerTree<V, A>>) r -> mkTree(measured).deep(l, m, r)
);
}
@Override public FingerTree<V, A> tail() { return deepL(measured(), prefix.tail(), middle, suffix); }
@Override public FingerTree<V, A> init() { return deepR(measured(), suffix.init(), middle, prefix); }
@Override public FingerTree<V, A> append(final FingerTree<V, A> t) {
final Measured<V, A> m = measured();
return t.match(
constant(this),
single -> snoc(single.value()),
deep -> new Deep<>(m, m.sum(measure(), deep.measure()), prefix,
addDigits0(m, middle, suffix, deep.prefix, deep.middle), deep.suffix));
}
@Override P3<FingerTree<V, A>, A, FingerTree<V, A>> split1(final F<V, Boolean> predicate, final V acc) {
final Measured<V, A> m = measured();
final V accL = m.sum(acc, prefix.measure());
if (predicate.f(accL)) {
final P3<Option<Digit<V, A>>, A, Option<Digit<V, A>>> lxr = prefix.split1(predicate, acc);
return P.p(lxr._1().option(new Empty<>(m), Digit::toTree), lxr._2(), deepL(m, lxr._3(), middle, suffix));
} else {
final V accM = m.sum(accL, middle.measure());
if (predicate.f(accM)) {
final P3<FingerTree<V, Node<V, A>>, Node<V, A>, FingerTree<V, Node<V, A>>> mlXsMr = middle.split1(predicate, accL);
final P3<Option<Digit<V, A>>, A, Option<Digit<V, A>>> lxr = mlXsMr._2().split1(predicate, m.sum(accL, mlXsMr._1().measure()));
return P.p(deepR(m, lxr._1(), mlXsMr._1(), prefix), lxr._2(), deepL(m, lxr._3(), mlXsMr._3(), suffix));
} else {
final P3<Option<Digit<V, A>>, A, Option<Digit<V, A>>> lxr = suffix.split1(predicate, accM);
return P.p(deepR(m, lxr._1(), middle, prefix), lxr._2(), lxr._3().option(new Empty<>(m), Digit::toTree));
}
}
}
@Override public P2<Integer, A> lookup(final F<V, Integer> o, final int i) {
final int spr = o.f(prefix.measure());
if (i < spr) {
return prefix.lookup(o, i);
} else {
final int spm = spr + o.f(middle.measure());
if (i < spm) {
final P2<Integer, Node<V, A>> p = middle.lookup(o, i - spr);
return p._2().lookup(o, p._1());
} else {
return suffix.lookup(o, i - spm);
}
}
}
@Override
public int length() {
int midSize = middle.foldLeft((acc, n) -> acc + n.length(), 0);
return prefix.length() + midSize + suffix.length();
}
private static <V, A> FingerTree<V, Node<V, A>> addDigits0(
final Measured<V, A> m, final FingerTree<V, Node<V, A>> m1,
final Digit<V, A> s1, final Digit<V, A> p2,
final FingerTree<V, Node<V, A>> m2) {
final MakeTree<V, A> mk = mkTree(m);
return s1.match(
one1 -> p2.match(
one2 -> append1(m, m1, mk.node2(one1.value(), one2.value()), m2),
two2 -> {
final V2<A> vs = two2.values();
return append1(m, m1, mk.node3(one1.value(), vs._1(), vs._2()), m2);
},
three -> {
final V3<A> vs = three.values();
return append2(m, m1, mk.node2(one1.value(), vs._1()), mk.node2(vs._2(), vs._3()), m2);
},
four -> {
final V4<A> vs = four.values();
return append2(m, m1, mk.node3(one1.value(), vs._1(), vs._2()), mk.node2(vs._3(), vs._4()), m2);
}
),
two1 -> {
final V2<A> v1 = two1.values();
return p2.match(
one -> append1(m, m1, mk.node3(v1._1(), v1._2(), one.value()), m2),
two2 -> {
final V2<A> v2 = two2.values();
return append2(m, m1, mk.node2(v1._1(), v1._2()), mk.node2(v2._1(), v2._2()), m2);
},
three -> {
final V3<A> v2 = three.values();
return append2(m, m1, mk.node3(v1._1(), v1._2(), v2._1()), mk.node2(v2._2(), v2._3()), m2);
},
four -> {
final V4<A> v2 = four.values();
return append2(m, m1, mk.node3(v1._1(), v1._2(), v2._1()), mk.node3(v2._2(), v2._3(), v2._4()), m2);
}
);
},
three1 -> {
final V3<A> v1 = three1.values();
return p2.match(
one -> append2(m, m1, mk.node2(v1._1(), v1._2()), mk.node2(v1._3(), one.value()), m2),
two -> {
final V2<A> v2 = two.values();
return append2(m, m1, mk.node3(v1), mk.node2(v2), m2);
},
three2 -> append2(m, m1, mk.node3(v1), mk.node3(three2.values()), m2),
four -> append3(m, m1, mk.node3(v1),
mk.node2(four.values()._1(), four.values()._2()),
mk.node2(four.values()._3(), four.values()._4()), m2
)
);
},
four1 -> {
final V4<A> v1 = four1.values();
return p2.match(
one -> append2(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node2(v1._4(), one.value()), m2),
two -> {
final V2<A> v2 = two.values();
return append2(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), v2._1(), v2._2()), m2);
},
three -> {
final V3<A> v2 = three.values();
return append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node2(v1._4(), v2._1()), mk.node2(v2._2(), v2._3()), m2);
},
four2 -> {
final V4<A> v2 = four2.values();
return append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), v2._1(), v2._2()), mk.node2(v2._3(), v2._4()), m2);
}
);
}
);
}
private static <V, A> FingerTree<V, Node<V, A>> append1(final Measured<V, A> m, final FingerTree<V, Node<V, A>> xs,
final Node<V, A> a, final FingerTree<V, Node<V, A>> ys) {
return xs.match(empty -> ys.cons(a), single -> ys.cons(a).cons(single.value()), deep1 -> ys.match(empty -> xs.snoc(a), single -> xs.snoc(a).snoc(single.value()), deep2 -> {
final Measured<V, Node<V, A>> nm = m.nodeMeasured();
return new Deep<>(nm, m.sum(m.sum(deep1.v, nm.measure(a)), deep2.v), deep1.prefix,
addDigits1(nm, deep1.middle, deep1.suffix, a, deep2.prefix, deep2.middle),
deep2.suffix);
}));
}
private static <V, A> FingerTree<V, Node<V, Node<V, A>>> addDigits1(final Measured<V, Node<V, A>> m,
final FingerTree<V, Node<V, Node<V, A>>> m1,
final Digit<V, Node<V, A>> x, final Node<V, A> n,
final Digit<V, Node<V, A>> y,
final FingerTree<V, Node<V, Node<V, A>>> m2) {
final MakeTree<V, Node<V, A>> mk = mkTree(m);
return x.match(one1 -> y.match(one2 -> append1(m, m1, mk.node3(one1.value(), n, one2.value()), m2), two -> append2(m, m1, mk.node2(one1.value(), n), mk.node2(two.values()), m2), three -> {
final V3<Node<V, A>> v2 = three.values();
return append2(m, m1, mk.node3(one1.value(), n, v2._1()), mk.node2(v2._2(), v2._3()), m2);
}, four -> {
final V4<Node<V, A>> v2 = four.values();
return append2(m, m1, mk.node3(one1.value(), n, v2._1()), mk.node3(v2._2(), v2._3(), v2._4()), m2);
}), two1 -> {
final V2<Node<V, A>> v1 = two1.values();
return y.match(one -> append2(m, m1, mk.node2(v1), mk.node2(n, one.value()), m2), two -> append2(m, m1, mk.node3(v1._1(), v1._2(), n), mk.node2(two.values()), m2), three -> append2(m, m1, mk.node3(v1._1(), v1._2(), n), mk.node3(three.values()), m2), four -> {
final V4<Node<V, A>> v2 = four.values();
return append3(m, m1, mk.node3(v1._1(), v1._2(), n), mk.node2(v2._1(), v2._2()), mk.node2(v2._3(), v2._4()),
m2);
});
}, three -> {
final V3<Node<V, A>> v1 = three.values();
return y.match(one -> append2(m, m1, mk.node3(v1), mk.node2(n, one.value()), m2), two -> {
final V2<Node<V, A>> v2 = two.values();
return append2(m, m1, mk.node3(v1), mk.node3(n, v2._1(), v2._2()), m2);
}, three1 -> {
final V3<Node<V, A>> v2 = three1.values();
return append3(m, m1, mk.node3(v1), mk.node2(n, v2._1()), mk.node2(v2._2(), v2._3()), m2);
}, four -> {
final V4<Node<V, A>> v2 = four.values();
return append3(m, m1, mk.node3(v1), mk.node3(n, v2._1(), v2._2()), mk.node2(v2._3(), v2._4()), m2);
});
}, four -> {
final V4<Node<V, A>> v1 = four.values();
return y.match(one -> append2(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n, one.value()), m2), two -> append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node2(v1._4(), n), mk.node2(two.values()),
m2), three -> {
final V3<Node<V, A>> v2 = three.values();
return append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n, v2._1()),
mk.node2(v2._2(), v2._3()), m2);
}, four1 -> {
final V4<Node<V, A>> v2 = four1.values();
return append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n, v2._1()),
mk.node3(v2._2(), v2._3(), v2._4()), m2);
});
});
}
private static <V, A> FingerTree<V, Node<V, A>> append2(final Measured<V, A> m, final FingerTree<V, Node<V, A>> t1,
final Node<V, A> n1, final Node<V, A> n2,
final FingerTree<V, Node<V, A>> t2) {
return t1.match(empty -> t2.cons(n2).cons(n1), single -> t2.cons(n2).cons(n1).cons(single.value()), deep -> t2.match(empty -> deep.snoc(n1).snoc(n2), single -> deep.snoc(n1).snoc(n2).snoc(single.value()), deep2 -> new Deep<>(m.nodeMeasured(),
m.sum(m.sum(m.sum(deep.measure(), n1.measure()), n2.measure()),
deep2.measure()), deep.prefix,
addDigits2(m.nodeMeasured(), deep.middle, deep.suffix, n1, n2, deep2.prefix,
deep2.middle), deep2.suffix)));
}
private static <V, A> FingerTree<V, Node<V, Node<V, A>>> addDigits2(final Measured<V, Node<V, A>> m,
final FingerTree<V, Node<V, Node<V, A>>> m1,
final Digit<V, Node<V, A>> suffix,
final Node<V, A> n1, final Node<V, A> n2,
final Digit<V, Node<V, A>> prefix,
final FingerTree<V, Node<V, Node<V, A>>> m2) {
final MakeTree<V, Node<V, A>> mk = mkTree(m);
return suffix.match(one -> prefix.match(one2 -> append2(m, m1, mk.node2(one.value(), n1), mk.node2(n2, one2.value()), m2), two -> append2(m, m1, mk.node3(one.value(), n1, n2), mk.node2(two.values()), m2), three -> append2(m, m1, mk.node3(one.value(), n1, n2), mk.node3(three.values()), m2), four -> {
final V4<Node<V, A>> v2 = four.values();
return append3(m, m1, mk.node3(one.value(), n1, n2), mk.node2(v2._1(), v2._2()), mk.node2(v2._3(), v2._4()),
m2);
}), two -> {
final V2<Node<V, A>> v1 = two.values();
return prefix.match(one -> append2(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node2(n2, one.value()), m2), two2 -> {
final V2<Node<V, A>> v2 = two2.values();
return append2(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node3(n2, v2._1(), v2._2()), m2);
}, three -> {
final V3<Node<V, A>> v2 = three.values();
return append3(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node2(n2, v2._1()), mk.node2(v2._2(), v2._3()),
m2);
}, four -> {
final V4<Node<V, A>> v2 = four.values();
return append3(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node3(n2, v2._1(), v2._2()),
mk.node2(v2._3(), v2._4()), m2);
});
}, three -> {
final V3<Node<V, A>> v1 = three.values();
return prefix.match(one -> append2(m, m1, mk.node3(v1), mk.node3(n1, n2, one.value()), m2), two -> append3(m, m1, mk.node3(v1), mk.node2(n1, n2), mk.node2(two.values()), m2), three2 -> {
final V3<Node<V, A>> v2 = three2.values();
return append3(m, m1, mk.node3(v1), mk.node3(n1, n2, v2._1()), mk.node2(v2._2(), v2._3()), m2);
}, four -> {
final V4<Node<V, A>> v2 = four.values();
return append3(m, m1, mk.node3(v1), mk.node3(n1, n2, v2._1()), mk.node3(v2._2(), v2._3(), v2._4()), m2);
});
}, four -> {
final V4<Node<V, A>> v1 = four.values();
return prefix.match(one -> append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node2(v1._4(), n1), mk.node2(n2, one.value()),
m2), two -> append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2),
mk.node2(two.values()), m2), three -> append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2),
mk.node3(three.values()), m2), four2 -> {
final V4<Node<V, A>> v2 = four2.values();
return append4(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2),
mk.node2(v2._1(), v2._2()), mk.node2(v2._3(), v2._4()), m2);
});
});
}
@SuppressWarnings("unchecked")
private static <V, A> FingerTree<V, Node<V, A>> append3(final Measured<V, A> m, final FingerTree<V, Node<V, A>> t1,
final Node<V, A> n1, final Node<V, A> n2, final Node<V, A> n3,
final FingerTree<V, Node<V, A>> t2) {
final Measured<V, Node<V, A>> nm = m.nodeMeasured();
return t1.match(empty -> t2.cons(n3).cons(n2).cons(n1), single -> t2.cons(n3).cons(n2).cons(n1).cons(single.value()), deep -> t2.match(empty -> deep.snoc(n1).snoc(n2).snoc(n3), single -> deep.snoc(n1).snoc(n2).snoc(n3).snoc(single.value()), deep2 -> new Deep<>(nm, nm.monoid().sumLeft(
list(deep.v, n1.measure(), n2.measure(), n3.measure(), deep2.v)), deep.prefix,
addDigits3(nm, deep.middle, deep.suffix, n1, n2, n3, deep2.prefix,
deep2.middle), deep2.suffix)));
}
private static <V, A> FingerTree<V, Node<V, Node<V, A>>> addDigits3(final Measured<V, Node<V, A>> m,
final FingerTree<V, Node<V, Node<V, A>>> m1,
final Digit<V, Node<V, A>> suffix,
final Node<V, A> n1, final Node<V, A> n2,
final Node<V, A> n3,
final Digit<V, Node<V, A>> prefix,
final FingerTree<V, Node<V, Node<V, A>>> m2) {
final MakeTree<V, Node<V, A>> mk = mkTree(m);
return suffix.match(one -> prefix.match(one2 -> append2(m, m1, mk.node3(one.value(), n1, n2), mk.node2(n3, one2.value()), m2), two -> {
final V2<Node<V, A>> v2 = two.values();
return append2(m, m1, mk.node3(one.value(), n1, n2), mk.node3(n3, v2._1(), v2._2()), m2);
}, three -> {
final V3<Node<V, A>> v2 = three.values();
return append3(m, m1, mk.node3(one.value(), n1, n2), mk.node2(n3, v2._1()), mk.node2(v2._2(), v2._3()), m2);
}, four -> {
final V4<Node<V, A>> v2 = four.values();
return append3(m, m1, mk.node3(one.value(), n1, n2), mk.node3(n3, v2._1(), v2._2()),
mk.node2(v2._3(), v2._4()), m2);
}), two -> {
final V2<Node<V, A>> v1 = two.values();
return prefix.match(one -> append2(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node3(n2, n3, one.value()), m2), two1 -> append3(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node2(n2, n3), mk.node2(two1.values()), m2), three -> {
final V3<Node<V, A>> v2 = three.values();
return append3(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node3(n2, n3, v2._1()), mk.node2(v2._2(), v2._3()),
m2);
}, four -> {
final V4<Node<V, A>> v2 = four.values();
return append3(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node3(n2, n3, v2._1()),
mk.node3(v2._2(), v2._3(), v2._4()), m2);
});
}, three -> prefix.match(one -> append3(m, m1, mk.node3(three.values()), mk.node2(n1, n2), mk.node2(n3, one.value()), m2), two -> append3(m, m1, mk.node3(three.values()), mk.node3(n1, n2, n3), mk.node2(two.values()), m2), three2 -> append3(m, m1, mk.node3(three.values()), mk.node3(n1, n2, n3), mk.node3(three2.values()), m2), four -> {
final V4<Node<V, A>> v2 = four.values();
return append4(m, m1, mk.node3(three.values()), mk.node3(n1, n2, n3), mk.node2(v2._1(), v2._2()),
mk.node2(v2._3(), v2._4()), m2);
}), four -> {
final V4<Node<V, A>> v1 = four.values();
return prefix.match(one -> append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2),
mk.node2(n3, one.value()), m2), two -> {
final V2<Node<V, A>> v2 = two.values();
return append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2),
mk.node3(n3, v2._1(), v2._2()), m2);
}, three -> {
final V3<Node<V, A>> v2 = three.values();
return append4(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2), mk.node2(n3, v2._1()),
mk.node2(v2._2(), v2._3()), m2);
}, four2 -> {
final V4<Node<V, A>> v2 = four2.values();
return append4(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2),
mk.node3(n3, v2._1(), v2._2()), mk.node2(v2._3(), v2._4()), m2);
});
});
}
@SuppressWarnings("unchecked")
private static <V, A> FingerTree<V, Node<V, A>> append4(final Measured<V, A> m,
final FingerTree<V, Node<V, A>> t1,
final Node<V, A> n1,
final Node<V, A> n2,
final Node<V, A> n3,
final Node<V, A> n4,
final FingerTree<V, Node<V, A>> t2) {
final Measured<V, Node<V, A>> nm = m.nodeMeasured();
return t1.match(empty -> t2.cons(n4).cons(n3).cons(n2).cons(n1), single -> t2.cons(n4).cons(n3).cons(n2).cons(n1).cons(single.value()), deep -> t2.match(empty -> t1.snoc(n1).snoc(n2).snoc(n3).snoc(n4), single -> t1.snoc(n1).snoc(n2).snoc(n3).snoc(n4).snoc(single.value()), deep2 -> new Deep<>(nm, m.monoid().sumLeft(
list(deep.v, n1.measure(), n2.measure(), n3.measure(), n4.measure(), deep2.v)), deep.prefix,
addDigits4(nm, deep.middle, deep.suffix, n1, n2, n3, n4, deep2.prefix,
deep2.middle), deep2.suffix)));
}
private static <V, A> FingerTree<V, Node<V, Node<V, A>>> addDigits4(final Measured<V, Node<V, A>> m,
final FingerTree<V, Node<V, Node<V, A>>> m1,
final Digit<V, Node<V, A>> suffix,
final Node<V, A> n1, final Node<V, A> n2,
final Node<V, A> n3, final Node<V, A> n4,
final Digit<V, Node<V, A>> prefix,
final FingerTree<V, Node<V, Node<V, A>>> m2) {
final MakeTree<V, Node<V, A>> mk = mkTree(m);
return suffix.match(one -> prefix.match(one2 -> append2(m, m1, mk.node3(one.value(), n1, n2), mk.node3(n3, n4, one2.value()), m2), two -> append3(m, m1, mk.node3(one.value(), n1, n2), mk.node2(n3, n4), mk.node2(two.values()), m2), three -> {
final V3<Node<V, A>> v2 = three.values();
return append3(m, m1, mk.node3(one.value(), n1, n2), mk.node3(n3, n4, v2._1()), mk.node2(v2._2(), v2._3()),
m2);
}, four -> {
final V4<Node<V, A>> v2 = four.values();
return append3(m, m1, mk.node3(one.value(), n1, n2), mk.node3(n3, n4, v2._1()),
mk.node3(v2._2(), v2._3(), v2._4()), m2);
}), two -> {
final V2<Node<V, A>> v1 = two.values();
return prefix.match(one -> append3(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node2(n2, n3), mk.node2(n4, one.value()), m2), two2 -> append3(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node3(n2, n3, n4), mk.node2(two2.values()), m2), three -> append3(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node3(n2, n3, n4), mk.node3(three.values()), m2), four -> {
final V4<Node<V, A>> v2 = four.values();
return append4(m, m1, mk.node3(v1._1(), v1._2(), n1), mk.node3(n2, n3, n4), mk.node2(v2._1(), v2._2()),
mk.node2(v2._3(), v2._4()), m2);
});
}, three -> {
final V3<Node<V, A>> v1 = three.values();
return prefix.match(one -> append3(m, m1, mk.node3(v1), mk.node3(n1, n2, n3), mk.node2(n4, one.value()), m2), two -> {
final V2<Node<V, A>> v2 = two.values();
return append3(m, m1, mk.node3(v1), mk.node3(n1, n2, n3), mk.node3(n4, v2._1(), v2._2()), m2);
}, three1 -> {
final V3<Node<V, A>> v2 = three1.values();
return append4(m, m1, mk.node3(v1), mk.node3(n1, n2, n3), mk.node2(n4, v2._1()), mk.node2(v2._2(), v2._3()),
m2);
}, four -> {
final V4<Node<V, A>> v2 = four.values();
return append4(m, m1, mk.node3(v1), mk.node3(n1, n2, n3), mk.node3(n4, v2._1(), v2._2()),
mk.node2(v2._3(), v2._4()), m2);
});
}, four -> {
final V4<Node<V, A>> v1 = four.values();
return prefix.match(one -> append3(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2),
mk.node3(n3, n4, one.value()), m2), two -> append4(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2),
mk.node2(n3, n4), mk.node2(two.values()), m2), three -> {
final V3<Node<V, A>> v2 = three.values();
return append4(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2),
mk.node3(n3, n4, v2._1()), mk.node2(v2._2(), v2._3()), m2);
}, four1 -> {
final V4<Node<V, A>> v2 = four1.values();
return append4(m, m1, mk.node3(v1._1(), v1._2(), v1._3()), mk.node3(v1._4(), n1, n2),
mk.node3(n3, n4, v2._1()), mk.node3(v2._2(), v2._3(), v2._4()), m2);
});
});
}
public String toString() {
return Show.fingerTreeShow(Show.<V>anyShow(), Show.<A>anyShow()).showS(this);
}
public Stream<A> toStream() {
return prefix().toStream().append(() ->
middle().match(
e -> Stream.<A>nil(),
s -> s.value().toStream(),
d -> d.toStream().bind(p -> p.toStream())
)
).append(() -> suffix.toStream());
}
}