76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński * @brief Polynomial in symmetric power basis (S-basis)
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen * Nathan Hurst <njh@mail.csse.monash.edu.au>
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen * Michael Sloan <mgsloan@gmail.com>
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen * Copyright (C) 2006-2007 authors
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen * This library is free software; you can redistribute it and/or
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen * modify it either under the terms of the GNU Lesser General Public
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen * License version 2.1 as published by the Free Software Foundation
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen * (the "LGPL") or, at your option, under the terms of the Mozilla
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen * Public License Version 1.1 (the "MPL"). If you do not alter this
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen * notice, a recipient may use your version of this file under either
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen * the MPL or the LGPL.
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen * You should have received a copy of the LGPL along with this library
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen * in the file COPYING-LGPL-2.1; if not, write to the Free Software
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen * You should have received a copy of the MPL along with this library
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen * in the file COPYING-MPL-1.1
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen * The contents of this file are subject to the Mozilla Public License
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen * Version 1.1 (the "License"); you may not use this file except in
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen * compliance with the License. You may obtain a copy of the License at
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen * OF ANY KIND, either express or implied. See the LGPL or the MPL for
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen * the specific language governing rights and limitations.
c3a8ad9235ff81909bd472707550aef5b91daf7bjohanengelen//#define USE_SBASISN 1
c3a8ad9235ff81909bd472707550aef5b91daf7bjohanengelen/*** An empty SBasis is identically 0. */
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński * @brief Polynomial in symmetric power basis
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński * @ingroup Fragments
c3a8ad9235ff81909bd472707550aef5b91daf7bjohanengelen void push_back(Linear const&l) { d.push_back(l); }
dc249e33217a0cf547f743fbc08fbce188911972johanengelen // As part of our migration away from SBasis isa vector we provide this minimal set of vector interface methods.
ddbfe2cbdba8be76e8d333b9ccfc35c2e83bcb19Johan B. C. Engelen typedef std::vector<Linear>::iterator iterator;
ddbfe2cbdba8be76e8d333b9ccfc35c2e83bcb19Johan B. C. Engelen typedef std::vector<Linear>::const_iterator const_iterator;
c3a8ad9235ff81909bd472707550aef5b91daf7bjohanengelen return d[i];
c3a8ad9235ff81909bd472707550aef5b91daf7bjohanengelen Linear& operator[](unsigned i) { return d.at(i); }
ddbfe2cbdba8be76e8d333b9ccfc35c2e83bcb19Johan B. C. Engelen const_iterator begin() const { return d.begin();}
ddbfe2cbdba8be76e8d333b9ccfc35c2e83bcb19Johan B. C. Engelen const_iterator end() const { return d.end();}
f055ef73fb003d7cfda819eb4cd73d3341893a14Krzysztof Kosiński bool empty() const { return d.size() == 1 && d[0][0] == 0 && d[0][1] == 0; }
f055ef73fb003d7cfda819eb4cd73d3341893a14Krzysztof Kosiński void resize(unsigned n) { d.resize(std::max<unsigned>(n, 1));}
f055ef73fb003d7cfda819eb4cd73d3341893a14Krzysztof Kosiński void resize(unsigned n, Linear const& l) { d.resize(std::max<unsigned>(n, 1), l);}
ddbfe2cbdba8be76e8d333b9ccfc35c2e83bcb19Johan B. C. Engelen void insert(iterator before, const_iterator src_begin, const_iterator src_end) { d.insert(before, src_begin, src_end);}
c3a8ad9235ff81909bd472707550aef5b91daf7bjohanengelen //void insert(Linear* before, int& n, Linear const &l) { d.insert(std::vector<Linear>::iterator(before), n, l);}
98a704c566ce5a750d76d5fc9675ccc804ac65f5johanengelen bool operator==(SBasis const&B) const { return d == B.d;}
98a704c566ce5a750d76d5fc9675ccc804ac65f5johanengelen bool operator!=(SBasis const&B) const { return d != B.d;}
c3a8ad9235ff81909bd472707550aef5b91daf7bjohanengelen explicit SBasis(size_t n, Linear const&l) : d(n, l) {}
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński SBasis(Coord c0, Coord c1, Coord c2, Coord c3)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński SBasis(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4, Coord c5)
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński SBasis(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4, Coord c5,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński SBasis(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4, Coord c5,
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński // construct from a sequence of coefficients
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński assert(std::distance(first, last) % 2 == 0);
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen //IMPL: FragmentConcept
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen typedef double output_type;
04d58df841d9eb087eb99074f5c99235b801189bJohan B. C. Engelen inline bool isZero(double eps=EPSILON) const {
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen for(unsigned i = 0; i < size(); i++) {
04d58df841d9eb087eb99074f5c99235b801189bJohan B. C. Engelen if(!(*this)[i].isZero(eps)) return false;
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen return true;
04d58df841d9eb087eb99074f5c99235b801189bJohan B. C. Engelen inline bool isConstant(double eps=EPSILON) const {
04d58df841d9eb087eb99074f5c99235b801189bJohan B. C. Engelen if(!(*this)[0].isConstant(eps)) return false;
04d58df841d9eb087eb99074f5c99235b801189bJohan B. C. Engelen if(!(*this)[i].isZero(eps)) return false;
bacf092e612ad1911c5a4db58261865e54953b34johanengelen return true;
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen bool isFinite() const;
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński inline Coord at0() const { return (*this)[0][0]; }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński inline Coord &at0() { return (*this)[0][0]; }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński inline Coord at1() const { return (*this)[0][1]; }
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosiński inline Coord &at1() { return (*this)[0][1]; }
c3a8ad9235ff81909bd472707550aef5b91daf7bjohanengelen int degreesOfFreedom() const { return size()*2;}
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen double valueAt(double t) const {
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen double s = t*(1-t);
d02f89424319afe28fe2cc6696c28108448de3acmcecchetti for(unsigned k = size(); k > 0; k--) {
d02f89424319afe28fe2cc6696c28108448de3acmcecchetti //double valueAndDerivative(double t, double &der) const {
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen double operator()(double t) const {
d8fa3c4faade9a5a8e7f79450544b1925e1ade41johanengelen std::vector<double> valueAndDerivatives(double t, unsigned n) const;
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen SBasis toSBasis() const { return SBasis(*this); }
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen// compute f(g)
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen//MUTATOR PRISON
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen //remove extra zeros
f055ef73fb003d7cfda819eb4cd73d3341893a14Krzysztof Kosiński void truncate(unsigned k) { if(k < size()) resize(std::max<size_t>(k, 1)); }
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen//TODO: figure out how to stick this in linear, while not adding an sbasis dep
981b809bc6ed10a21e89444d9447e5475801874fjohanengeleninline SBasis Linear::toSBasis() const { return SBasis(*this); }
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen//implemented in sbasis-roots.cpp
6c3e745a94ef6b25a4ef9f018d350a7535aa45afTed GouldOptInterval bounds_fast(SBasis const &a, int order = 0);
6c3e745a94ef6b25a4ef9f018d350a7535aa45afTed GouldOptInterval bounds_local(SBasis const &a, const OptInterval &t, int order = 0);
01d27eab5fca2dcb8e883011f8be77ae6b78a11cTed Gould/** Returns a function which reverses the domain of a.
01d27eab5fca2dcb8e883011f8be77ae6b78a11cTed Gould \param a sbasis function
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen \relates SBasis
01d27eab5fca2dcb8e883011f8be77ae6b78a11cTed Goulduseful for reversing a parameteric curve.
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen for(unsigned k = 0; k < a.size(); k++)
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen//IMPL: ScalableConcept
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen for(unsigned i = 0; i < p.size(); i++) {
981b809bc6ed10a21e89444d9447e5475801874fjohanengeleninline SBasis operator*(double k, SBasis const &a) { return a*k; }
981b809bc6ed10a21e89444d9447e5475801874fjohanengeleninline SBasis operator/(SBasis const &a, double k) { return a*(1./k); }
981b809bc6ed10a21e89444d9447e5475801874fjohanengeleninline SBasis& operator/=(SBasis& a, double b) { return (a*=(1./b)); }
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen//IMPL: AddableConcept
981b809bc6ed10a21e89444d9447e5475801874fjohanengelenSBasis operator+(const SBasis& a, const SBasis& b);
981b809bc6ed10a21e89444d9447e5475801874fjohanengelenSBasis operator-(const SBasis& a, const SBasis& b);
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen//TODO: remove?
c3a8ad9235ff81909bd472707550aef5b91daf7bjohanengelen/*inline SBasis operator+(const SBasis & a, Linear const & b) {
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen if(b.isZero()) return a;
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen if(a.isZero()) return b;
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen SBasis result(a);
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen result[0] += b;
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen return result;
981b809bc6ed10a21e89444d9447e5475801874fjohanengeleninline SBasis operator-(const SBasis & a, Linear const & b) {
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen if(b.isZero()) return a;
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen SBasis result(a);
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen result[0] -= b;
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen return result;
981b809bc6ed10a21e89444d9447e5475801874fjohanengeleninline SBasis& operator+=(SBasis& a, const Linear& b) {
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen if(a.isZero())
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen a.push_back(b);
981b809bc6ed10a21e89444d9447e5475801874fjohanengeleninline SBasis& operator-=(SBasis& a, const Linear& b) {
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen if(a.isZero())
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen a.push_back(-b);
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen//IMPL: OffsetableConcept
981b809bc6ed10a21e89444d9447e5475801874fjohanengeleninline SBasis operator+(const SBasis & a, double b) {
981b809bc6ed10a21e89444d9447e5475801874fjohanengeleninline SBasis operator-(const SBasis & a, double b) {
981b809bc6ed10a21e89444d9447e5475801874fjohanengeleninline SBasis& operator+=(SBasis& a, double b) {
981b809bc6ed10a21e89444d9447e5475801874fjohanengeleninline SBasis& operator-=(SBasis& a, double b) {
981b809bc6ed10a21e89444d9447e5475801874fjohanengeleninline SBasis truncate(SBasis const &a, unsigned terms) {
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen c.insert(c.begin(), a.begin(), a.begin() + std::min(terms, (unsigned)a.size()));
981b809bc6ed10a21e89444d9447e5475801874fjohanengelenSBasis multiply(SBasis const &a, SBasis const &b);
d02f89424319afe28fe2cc6696c28108448de3acmcecchetti// This performs a multiply and accumulate operation in about the same time as multiply. return a*b + c
d02f89424319afe28fe2cc6696c28108448de3acmcecchettiSBasis multiply_add(SBasis const &a, SBasis const &b, SBasis c);
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen// return a kth order approx to 1/a)
981b809bc6ed10a21e89444d9447e5475801874fjohanengelenSBasis divide(SBasis const &a, SBasis const &b, int k);
981b809bc6ed10a21e89444d9447e5475801874fjohanengeleninline SBasis operator*(SBasis const & a, SBasis const & b) {
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen return multiply(a, b);
981b809bc6ed10a21e89444d9447e5475801874fjohanengeleninline SBasis& operator*=(SBasis& a, SBasis const & b) {
01d27eab5fca2dcb8e883011f8be77ae6b78a11cTed Gould/** Returns the degree of the first non zero coefficient.
01d27eab5fca2dcb8e883011f8be77ae6b78a11cTed Gould \param a sbasis function
01d27eab5fca2dcb8e883011f8be77ae6b78a11cTed Gould \param tol largest abs val considered 0
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen \return first non zero coefficient
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen \relates SBasis
981b809bc6ed10a21e89444d9447e5475801874fjohanengeleninline unsigned
981b809bc6ed10a21e89444d9447e5475801874fjohanengelenSBasis compose(SBasis const &a, SBasis const &b);
981b809bc6ed10a21e89444d9447e5475801874fjohanengelenSBasis compose(SBasis const &a, SBasis const &b, unsigned k);
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen//compose_inverse(f,g)=compose(f,inverse(g)), but is numerically more stable in some good cases...
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen//TODO: requires g(0)=0 & g(1)=1 atm. generalization should be obvious.
981b809bc6ed10a21e89444d9447e5475801874fjohanengelenSBasis compose_inverse(SBasis const &f, SBasis const &g, unsigned order=2, double tol=1e-3);
01d27eab5fca2dcb8e883011f8be77ae6b78a11cTed Gould/** Returns the sbasis on domain [0,1] that was t on [from, to]
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen \param t sbasis function
01d27eab5fca2dcb8e883011f8be77ae6b78a11cTed Gould \param from,to interval
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen \return sbasis
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen \relates SBasis
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof KosińskiSBasis portion(const SBasis &t, double from, double to);
76addc201c409e81eaaa73fe27cc0f79c4db097cKrzysztof Kosińskiinline SBasis portion(const SBasis &t, Interval const &ivl) { return portion(t, ivl.min(), ivl.max()); }
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen// compute f(g)
981b809bc6ed10a21e89444d9447e5475801874fjohanengeleninline std::ostream &operator<< (std::ostream &out_file, const Linear &bo) {
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen out_file << "{" << bo[0] << ", " << bo[1] << "}";
981b809bc6ed10a21e89444d9447e5475801874fjohanengeleninline std::ostream &operator<< (std::ostream &out_file, const SBasis & p) {
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen for(unsigned i = 0; i < p.size(); i++) {
01d27eab5fca2dcb8e883011f8be77ae6b78a11cTed Gould// These are deprecated, use sbasis-math.h versions if possible
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelenstd::vector<double> roots(SBasis const & s, Interval const inside);
981b809bc6ed10a21e89444d9447e5475801874fjohanengelenstd::vector<std::vector<double> > multi_roots(SBasis const &f,
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen double b=1);
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen//--------- Levelset like functions -----------------------------------------------------
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen/** Solve f(t) = v +/- tolerance. The collection of intervals where
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen * v - vtol <= f(t) <= v+vtol
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen * is returned (with a precision tol on the boundaries).
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen \param f sbasis function
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen \param level the value of v.
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen \param vtol: error tolerance on v.
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen \param a, b limit search on domain [a,b]
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen \param tol: tolerance on the result bounds.
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen \returns a vector of intervals.
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelenstd::vector<Interval> level_set (SBasis const &f,
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen/** Solve f(t)\in I=[u,v], which defines a collection of intervals (J_k). More precisely,
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen * a collection (J'_k) is returned with J'_k = J_k up to a given tolerance.
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen \param f sbasis function
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen \param level: the given interval of deisred values for f.
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen \param a, b limit search on domain [a,b]
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen \param tol: tolerance on the bounds of the result.
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen \returns a vector of intervals.
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelenstd::vector<Interval> level_set (SBasis const &f,
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen/** 'Solve' f(t) = v +/- tolerance for several values of v at once.
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen \param f sbasis function
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen \param levels vector of values, that should be sorted.
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen \param vtol: error tolerance on v.
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen \param a, b limit search on domain [a,b]
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen \param tol: the bounds of the returned intervals are exact up to that tolerance.
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen \returns a vector of vectors of intervals.
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelenstd::vector<std::vector<Interval> > level_sets (SBasis const &f,
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen/** 'Solve' f(t)\in I=[u,v] for several intervals I at once.
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen \param f sbasis function
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen \param levels vector of 'y' intervals, that should be disjoints and sorted.
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen \param a, b limit search on domain [a,b]
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen \param tol: the bounds of the returned intervals are exact up to that tolerance.
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelen \returns a vector of vectors of intervals.
d37634d73670180f99a3e0ea583621373d90ec4fJohan Engelenstd::vector<std::vector<Interval> > level_sets (SBasis const &f,
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen Local Variables:
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen c-file-style:"stroustrup"
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen indent-tabs-mode:nil
981b809bc6ed10a21e89444d9447e5475801874fjohanengelen fill-column:99
a4030d5ca449e7e384bc699cd249ee704faaeab0Chris Morgan// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :