piecewise.h revision 7bec4f8084ba5b469390ba2b910f2146258eaff8
/**
* \file
* \brief Piecewise function class
*
* Copyright 2007 Michael Sloan <mgsloan@gmail.com>
*
* modify it either under the terms of the GNU Lesser General Public
* License version 2.1 as published by the Free Software Foundation
* (the "LGPL") or, at your option, under the terms of the Mozilla
* Public License Version 1.1 (the "MPL"). If you do not alter this
* notice, a recipient may use your version of this file under either
* the MPL or the LGPL.
*
* You should have received a copy of the LGPL along with this library
* in the file COPYING-LGPL-2.1; if not, output to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
* You should have received a copy of the MPL along with this library
* in the file COPYING-MPL-1.1
*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (the "License"); you may not use this file except in
* compliance with the License. You may obtain a copy of the License at
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
*
*/
#ifndef SEEN_GEOM_PW_SB_H
#define SEEN_GEOM_PW_SB_H
#include <vector>
#include <map>
#include <boost/concept_check.hpp>
/**
* %Piecewise function class.
* The Piecewise class manages a sequence of elements of a type as segments and
* the ’cuts’ between them. These cuts are time values which separate the pieces.
* This function representation allows for more interesting functions, as it provides
* a viable output for operations such as inversion, which may require multiple
* SBasis to properly invert the original.
* As for technical details, while the actual SBasis segments begin on the first
* cut and end on the last, the function is defined throughout all inputs by ex-
* tending the first and last segments. The exact switching between segments is
* arbitrarily such that beginnings (t=0) have preference over endings (t=1). This
* only matters if it is discontinuous at the location.
* \f[
* f(t) \rightarrow \left\{
* \begin{array}{cc}
* s_1,& t <= c_2 \\
* s_2,& c_2 <= t <= c_3\\
* \ldots \\
* s_n,& c_n <= t
* \end{array}\right.
* \f]
*/
//segs[i] stretches from cuts[i] to cuts[i+1].
Piecewise() {}
push_cut(0.);
push_seg(s);
push_cut(1.);
}
unsigned input_dim(){return 1;}
push_cut(0.);
push_seg(T(v));
push_cut(1.);
}
inline output_type valueAt(double t) const {
unsigned n = segN(t);
}
inline output_type firstValue() const {
}
inline output_type lastValue() const {
}
/**
* The size of the returned vector equals n_derivs+1.
*/
unsigned n = segN(t);
double mult = 1;
}
return ret;
}
//TODO: maybe it is not a good idea to have this?
inline void clear() {
}
/**Convenience/implementation hiding function to add segment/cut pairs.
* Asserts that basic size and order invariants are correct
*/
push_seg(s);
}
//Convenience/implementation hiding function to add cuts.
inline void push_cut(double c) {
}
//Convenience/implementation hiding function to add segments.
/**Returns the segment index which corresponds to a 'global' piecewise time.
*/
if(t < cuts[0]) return 0;
if(mv < t) {
} else if(t < mv) {
} else {
return mid;
}
}
return low;
}
/**Returns the time within a segment, given the 'global' piecewise time.
* Also takes an optional index parameter which may be used for efficiency or to find the time on a
* segment outside its range. If it is left to its default, -1, it will call segN to find the index.
*/
inline double segT(double t, int i = -1) const {
if(i == -1) i = segN(t);
assert(i >= 0);
}
inline double mapToDomain(double t, unsigned i) const {
}
//Offsets the piecewise domain
inline void offsetDomain(double o) {
if(o != 0)
for(unsigned i = 0; i <= size(); i++)
cuts[i] += o;
}
//Scales the domain of the function by a value. 0 will result in an empty Piecewise.
inline void scaleDomain(double s) {
assert(s > 0);
if(s == 0) {
return;
}
for(unsigned i = 0; i <= size(); i++)
cuts[i] *= s;
}
//Retrieves the domain in interval form
//Transforms the domain into another interval
if(empty()) return;
/* dom can not be empty
if(dom.isEmpty()) {
return;
}*/
for(unsigned i = 0; i <= size(); i++)
//fix floating point precision errors.
}
//Concatenates this Piecewise function with another, offseting time of the other to match the end.
if(empty()) {
return;
}
}
//Like concat, but ensures continuity.
}
//returns true if the Piecewise<T> meets some basic invariants.
inline bool invariants() const {
// segs between cuts
return false;
// cuts in order
return false;
return true;
}
};
for(unsigned i = 1; i < f.size(); i++)
return ret;
}
for(unsigned i = 1; i < f.size(); i++)
return ret;
}
inline typename FragmentConcept<T>::BoundsType bounds_local(const Piecewise<T> &f, const OptInterval &_m) {
return ret;
}
}
/**Piecewise<T> partition(const Piecewise<T> &pw, std::vector<double> const &c);
* Further subdivides the Piecewise<T> such that there is a cut at every value in c.
* Precondition: c sorted lower to higher.
*
* //Given Piecewise<T> a and b:
* Piecewise<T> ac = a.partition(b.cuts);
* Piecewise<T> bc = b.partition(a.cuts);
*/
for(unsigned i = 0; i < c.size() - 1; i++)
return ret;
}
//if the cuts have something earlier than the Piecewise<T>, add portions of the first segment
ci++;
}
//Loop which handles cuts within the Piecewise<T> domain
//Should have the cuts = segs + 1 invariant
return ret;
} else { //plain copy is fine
}
si++;
//Already finalized the seg with the code immediately above
ci++;
} else { //plain old subdivision
ci++;
}
}
//input cuts extend further than this Piecewise<T>, extend the last segment.
}
ci++;
}
return ret;
}
/**Piecewise<T> portion(const Piecewise<T> &pw, double from, double to);
* Returns a Piecewise<T> with a defined domain of [min(from, to), max(from, to)].
*/
return ret;
}
i++;
ret.invariants();
return ret;
}
//TODO: seems like these should be mutating
if(f.empty()) return f;
for(unsigned i=0; i<f.size(); i++){
}
}
return ret;
}
//TODO: seems like these should be mutating
if(f.empty()) return f;
for(unsigned i=0; i<f.size(); i++){
}
}
return ret;
}
for (unsigned j = 0; j < sr.size(); j++) ret.push_back(sr[j] * (pw.cuts[i + 1] - pw.cuts[i]) + pw.cuts[i]);
}
return ret;
}
//IMPL: OffsetableConcept
//TODO:empty
for(unsigned i = 0; i < a.size();i++)
return ret;
}
//TODO: empty
for(unsigned i = 0; i < a.size();i++)
return ret;
}
for(unsigned i = 0; i < a.size();i++)
a[i] += b;
return a;
}
for(unsigned i = 0;i < a.size();i++)
a[i] -= b;
return a;
}
//IMPL: ScalableConcept
for(unsigned i = 0; i < a.size();i++)
return ret;
}
for(unsigned i = 0; i < a.size();i++)
return ret;
}
for(unsigned i = 0; i < a.size();i++)
return ret;
}
//FIXME: b == 0?
for(unsigned i = 0; i < a.size();i++)
return ret;
}
for(unsigned i = 0; i < a.size();i++)
a[i] *= b;
return a;
}
//FIXME: b == 0?
for(unsigned i = 0; i < a.size();i++)
a[i] /= b;
return a;
}
//IMPL: AddableConcept
return ret;
}
return ret;
}
a = a+b;
return a;
}
a = a-b;
return a;
}
//function_requires<MultiplicableConcept<T1> >();
//function_requires<MultiplicableConcept<T2> >();
return ret;
}
a = a * b;
return a;
}
//TODO: replace divide(a,b,k) by divide(a,b,tol,k)?
//TODO: atm, relative error is ~(tol/a)%. Find a way to make it independant of a.
divide(Piecewise<SBasis> const &a, Piecewise<SBasis> const &b, double tol, unsigned k, double zero=1.e-3);
//Composition: functions called compose_* are pieces of compose that are factored out in pw.cpp.
SBasis const &g);
//TODO: add concept check
if (f.size()==1){
}
//first check bounds...
}
//TODO: use a std::vector<pairs<double,unsigned> > instead of a map<double,unsigned>.
//-- Compose each piece of g with the relevant seg of f.
//assert(std::abs(int((*cut).second-(*next).second))<1);
//TODO: find a way to recover from this error? the root finder missed some root;
// the levels/variations of f might be too close/fast...
cut++;
next++;
}
return(result);
}
//TODO: add concept check for following composition functions
}
return result;
}
/*
Piecewise<D2<SBasis> > compose(D2<SBasis2d> const &sb2d, Piecewise<D2<SBasis> > const &pwd2sb){
Piecewise<D2<SBasis> > result;
result.push_cut(0.);
for(unsigned i = 0; i < pwd2sb.size(); i++){
result.push(compose_each(sb2d,pwd2sb[i]),i+1);
}
return result;
}*/
}
return result;
}
}
return result;
}
std::vector<std::vector<double> >multi_roots(Piecewise<SBasis> const &f, std::vector<double> const &values);
}
return ret;
}
/**
* Interpolates between a and b.
* \return a if t = 0, b if t = 1, or an interpolation between a and b for t in [0,1]
* \relates Piecewise
*/
// Make sure both paths have the same number of segments and cuts at the same locations
}
}
#endif //SEEN_GEOM_PW_SB_H
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
fill-column:99
End:
*/
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :