Commit 812a9ec7 authored by Florent Jacquemard's avatar Florent Jacquemard
Browse files

revise fonction for sub interval to handle multiplicities

parent 71d76e6e
......@@ -32,8 +32,8 @@
struct PointedIntervalEq
{
bool operator () (IntervalTree const* lhs,
IntervalTree const* rhs) const
bool operator() (IntervalTree const* lhs,
IntervalTree const* rhs) const
{
return
lhs->rbegin() == rhs->rbegin() &&
......@@ -96,15 +96,13 @@ public:
/// @brief find or create (and push) a top interval
/// of real-time duration covering the whole length
/// of the given input segment s (root of interval tree) + the given extension.
///
/// - inside-bar interval (musical time duration of 1 bar) if flag bar is true
/// - multiple interval if flag bar is false (default).
/// @param mend end date in musical-time. must not be MTU::UNBOUNDED.
/// @param f_align flag says wether alignment is computed
/// for the interval.
/// @param f_align flag says wether alignment is computed for the interval.
/// if not, the next (first element of input segment after the
/// right bound of this interval) is set to out_of_range
/// (= size of segment), meaning that there is none.
/// right bound of this interval) is set to out_of_range (= size of segment),
/// meaning that there is none (no next element).
/// @warning the returned IntervalTree will be deleted with this Heap.
IntervalTree* const make(const InputSegment* s,
mtu_t mend = MTU::UNBOUNDED, // right open
......@@ -119,9 +117,7 @@ protected:
int _added;
int _found;
/// @brief get interval from heap,
/// build it if not present.
///
/// @brief get interval from heap, or build it if not present.
/// @param first must be the first element of input segment
/// after the left bound of this interval.
/// @param p pointer to the parent.
......
......@@ -213,7 +213,6 @@ IntervalTree* IntervalTree::sub(const InputSegment* s,
assert(! this->ropen());
assert(! this->mopen());
// creates an empty vector if it is not found
std::pair<std::map<size_t, std::vector<IntervalTree*>>::iterator, bool>
ret = _children.insert(std::pair<size_t,
......@@ -224,58 +223,7 @@ IntervalTree* IntervalTree::sub(const InputSegment* s,
// v is a newly created vector for a, fill it with aligned sub intervals
if (ret.second)
{
assert(v.size() == 0);
size_t b = this->first();
mtu_t mbeg = mbegin();
mtu_t mdur = (mend() - mbegin()) / MTU::make(a);
rtu_t rbeg = rbegin();
rtu_t rdur = (rend() - rbegin()) / ((rtu_t) a);
rtu_t rbeg_next;
IntervalTree* sibling = NULL;
IntervalTree* pt;
for (int j = 0; j < a; j++)
{
// last sub-interval
if (j == a-1)
{
rbeg_next = rend();
assert(mbeg + mdur == mend());
// not aligned
pt = ih->make(s,
rbeg, rbeg_next,
mbeg, mbeg+mdur,
b,
//this->next(),
this, sibling);
assert(pt);
assert(pt->aligned());
assert(pt->next() == this->next());
}
// sub-interval i < a-1
else
{
rbeg_next = rbeg + rdur;
pt = ih->make(s,
rbeg, rbeg_next,
mbeg, mbeg+mdur,
b,
this, sibling);
assert(pt);
if (pt->aligned())
b = pt->next();
else
b = pt->align(s, b);
}
TRACE("iTree.sub({}/{}) of {} = [{}, {}[ [{}, {}]",
j+1, a, *(this), mbeg, mbeg+mdur, rbeg, rbeg_next);
v.push_back(pt);
mbeg += mdur;
rbeg = rbeg_next;
sibling = pt;
}
fillSubtrees(s, ih, v, a);
}
// key a already present in tree
else
......@@ -287,6 +235,133 @@ IntervalTree* IntervalTree::sub(const InputSegment* s,
}
void IntervalTree::fillSubtrees(const InputSegment* s,
IntervalHeap* ih,
std::vector<IntervalTree*>& v,
size_t a)
{
assert(v.size() == 0);
size_t b = this->first();
mtu_t mbeg = mbegin();
mtu_t mdur = (mend() - mbegin()) / MTU::make(a);
rtu_t rbeg = rbegin();
rtu_t rdur = (rend() - rbegin()) / ((rtu_t) a);
rtu_t rbeg_next;
IntervalTree* sibling = NULL;
IntervalTree* pt;
for (int j = 0; j < a; j++)
{
// last sub-interval
if (j == a-1)
{
rbeg_next = rend();
assert(mbeg + mdur == mend());
// not aligned
pt = ih->make(s,
rbeg, rbeg_next,
mbeg, mbeg+mdur,
b,
//this->next(),
this, sibling);
assert(pt);
assert(pt->aligned());
assert(pt->next() == this->next());
}
// sub-interval i < a-1
else
{
rbeg_next = rbeg + rdur;
pt = ih->make(s,
rbeg, rbeg_next,
mbeg, mbeg+mdur,
b,
this, sibling);
assert(pt);
if (pt->aligned())
b = pt->next();
else
b = pt->align(s, b);
}
TRACE("iTree.sub({}/{}) of {} = [{}, {}[ [{}, {}]",
j+1, a, *(this), mbeg, mbeg+mdur, rbeg, rbeg_next);
v.push_back(pt);
mbeg += mdur;
rbeg = rbeg_next;
sibling = pt;
}
}
IntervalTree* IntervalTree::subm(const InputSegment* s,
IntervalHeap* ih,
size_t a, size_t i, size_t m)
{
assert (a > 1);
assert (1 <= i);
assert (i <= a);
assert(this->aligned());
assert(! this->ropen());
assert(! this->mopen());
if (m == 1)
{
return sub(s, ih, a, i);
}
// first child, of duration m times the normal dur.
if (i == 1)
{
size_t b = this->first();
rtu_t rbeg = rbegin();
rtu_t rdur = ((rtu_t) m) * (rend() - rbegin()) / ((rtu_t) a);
mtu_t mbeg = mbegin();
mtu_t mdur = MTU::make(m) * ((mend() - mbegin()) / MTU::make(a));
return ih->make(s,
rbeg, rbeg+rdur,
mbeg, mbeg+mdur,
b,
this, NULL);
}
else
{
// previous sibling. we complete the tree for arity a.
IntervalTree* prev = sub(s, ih, a, i-1);
assert(prev);
// immediately after the previous sibling and a duration m times more
return prev->nexti(s, ih, Rational(m));
}
}
IntervalTree* IntervalTree::nexti(const InputSegment* s,
IntervalHeap* ih,
const Rational& factor)
{
size_t b = this->next();
IntervalTree* sibling = this;
rtu_t rbeg = this->rend();
rtu_t rdur = RTU::mult(this->rduration(), factor);
mtu_t mbeg = mend();
mtu_t mdur = MTU::mult(this->mduration(), factor);
assert(ih);
// see Interval constructor next
// Interval::Interval(const InputSegment*, const Interval&, Rational):
IntervalTree* pt = ih->make(s,
rbeg, rbeg+rdur,
mbeg, mbeg+mdur,
b,
this->parent(), sibling);
assert(pt);
assert(pt->aligned());
// if (! pt->aligned()) pt->align(s, b);
return pt;
}
std::ostream& operator<<(std::ostream& o, const IntervalTree& p)
{
o << static_cast<const Interval&>(p);
......
......@@ -17,6 +17,8 @@
#include <unordered_map>
#include <map>
#include "trace.hpp"
#include "Rational.hpp"
#include "RTU.hpp"
#include "MTU.hpp"
#include "InputSegment.hpp"
......@@ -130,6 +132,31 @@ public:
IntervalHeap* h,
size_t a, size_t i);
/// @brief return the a sub-interval merging the (i-1)th to (i-1+m)th
/// sub-intervals of the division of this interval in ar equal parts.
/// @param ar total number of parts for division, must be > 1
/// @param i index of the part to return, must be in 1..a
/// @param m number of parts to merge (multiplicity)
/// @warning this interval must be aligned.
/// @warning this interval must not be open.
/// @warning the sub-interval returned is aligned.
IntervalTree* subm(const InputSegment* s,
IntervalHeap* h,
size_t ar, size_t i, size_t m);
/// interval starting just after this interval,
/// and of real-time (RTU) and musical-time (MTU) duration the factor of
/// the duration of this interval.
/// @param s input segment.
/// @param factor multiplicative factor to compute the duration of the
/// constructed interval from the duration of this interval.
/// @warning this interval must not be unbounded (MTU end).
/// @warning this interval must be inside given the given input segment.
/// The interval created is added to the interval heap. It is not added
/// to the tree.
IntervalTree* nexti(const InputSegment* s,
IntervalHeap* h,
const Rational& factor);
protected:
......@@ -147,7 +174,6 @@ protected:
std::map<size_t, std::vector<IntervalTree*>> _children;
/// @brief top interval (root of interval tree).
///
/// covering the whole length of the given input segment s
/// inside-bar interval of musical time duration of 1 bar if flag bar is true
/// multi-bar interval if flag bar is false.
......@@ -202,6 +228,13 @@ protected:
IntervalTree* p,
IntervalTree* ps);
private:
void fillSubtrees(const InputSegment* s,
IntervalHeap* ih,
std::vector<IntervalTree*>& v,
size_t a);
};
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment