npstat is hosted by Hepforge, IPPP Durham
NPStat  5.10.0
Poly1D.hh
Go to the documentation of this file.
1 #ifndef NPSTAT_POLY1D_HH_
2 #define NPSTAT_POLY1D_HH_
3 
4 /*!
5 // \file Poly1D.hh
6 //
7 // \brief Basic 1-d polynomials in the monomial basis. Various operations
8 // with monomials are poorly conditioned, so we need long double.
9 //
10 // Author: I. Volobouev
11 //
12 // November 2020
13 */
14 
15 #include <vector>
16 
18 
19 namespace npstat {
20  class Poly1D : public Functor1<long double, long double>
21  {
22  public:
23  /*
24  // Default constructor creates a polynomial which is
25  // identically zero
26  */
27  inline Poly1D() : coeffs_(1, 0.0L) {}
28 
29  inline virtual ~Poly1D() {}
30 
31  //@{
32  /**
33  // The length of the array of coefficients should be at least
34  // degree+1. The highest degree coefficient is assumed to be
35  // the last one in the "coeffs" array (0th degree coefficient
36  // comes first).
37  */
38  Poly1D(const double* coeffs, unsigned degree);
39  Poly1D(const long double* coeffs, unsigned degree);
40  //@}
41 
42  //@{
43  /**
44  // The length of the vector of coefficients should be degree+1.
45  // The highest degree coefficient is assumed to be the last one
46  // in the vector (0th degree coefficient comes first).
47  */
48  explicit Poly1D(const std::vector<double>& c);
49  explicit Poly1D(const std::vector<long double>& c);
50  //@}
51 
52  /**
53  // Note that the constructor from a floating point number
54  // is not explicit. Implicit conversions from a floating
55  // point number into a Poly1D are useful, for example, with
56  // arithmetic operators.
57  */
58  inline Poly1D(const long double c0) : coeffs_(1, c0) {}
59 
60  /**
61  // Construct a monomial of the given degree and with
62  // the leading coefficient provided
63  */
64  Poly1D(unsigned degree, long double leadingCoeff);
65 
66  /**
67  // At times it makes sense to reserve the space
68  // for the polynomial coefficients (in particular,
69  // with operator *=, when you use it more than once
70  // and have some idea about the expected degree of
71  // the result).
72  */
73  inline void reserve(const unsigned degree)
74  {coeffs_.reserve(degree + 1U);}
75 
76  /**
77  // Truncate the highest degree coefficients. The resulting
78  // polynomial will be of degree "maxDegree" (or less, if the
79  // new leading coefficient is 0).
80  */
81  void truncate(const unsigned maxDegree);
82 
83  /**
84  // Explicitly truncate leading coefficients that are
85  // zeros. Normally, the application code should not
86  // use this function, as tracking and removal of leading
87  // zeros happens automatically. It might still be useful
88  // in certain difficult to anticipate underflow scenarios.
89  */
91 
92  /** Set coefficient for a particular degree */
93  void setCoefficient(unsigned degree, long double value);
94 
95  /** The degree of the polynomial */
96  inline unsigned deg() const {return coeffs_.size() - 1U;}
97 
98  /** Return the coefficient for the given degree */
99  inline long double operator[](const unsigned degree) const
100  {return degree < coeffs_.size() ? coeffs_[degree] : 0.0L;}
101 
102  /** Return all coefficients */
103  inline const std::vector<long double>& allCoefficients() const
104  {return coeffs_;}
105 
106  /** The coefficient of the maximum degree monomial */
107  long double leadingCoefficient() const;
108 
109  /** Number of roots on the interval (a, b] */
110  unsigned nRoots(long double a, long double b) const;
111 
112  /** Polynomial value at x */
113  virtual long double operator()(const long double& x) const;
114 
115  /**
116  // Check if all polynomial coefficients are within eps from
117  // those of another polynomial. eps must be non-negative.
118  */
119  bool isClose(const Poly1D& r, long double eps) const;
120 
121  /** Check if the polynomial value is identical zero */
122  inline bool isNull() const
123  {return coeffs_.size() == 1U && coeffs_[0] == 0.0L;}
124 
125  /** Derivative polynomial */
127 
128  /** Indefinite integral, with explicit additive constant */
129  Poly1D integral(long double c) const;
130 
131  //@{
132  /** Unary operator */
133  inline Poly1D operator+() const {return *this;}
134  Poly1D operator-() const;
135  //@}
136 
137  //@{
138  /**
139  // Binary operator on two polynomials or on a polynomial
140  // and a floating point number
141  */
142  Poly1D operator*(const Poly1D&) const;
143  Poly1D operator+(const Poly1D&) const;
144  Poly1D operator-(const Poly1D&) const;
145  //@}
146 
147  Poly1D& operator*=(const Poly1D&);
148  Poly1D& operator+=(const Poly1D&);
149  Poly1D& operator-=(const Poly1D&);
150 
151  /** Euclidean division of polynomials -- the ratio */
152  Poly1D operator/(const Poly1D&) const;
153 
154  /** Euclidean division of polynomials -- the remainder */
155  Poly1D operator%(const Poly1D&) const;
156 
157  inline bool operator==(const Poly1D& r) const
158  {return coeffs_ == r.coeffs_;}
159  inline bool operator!=(const Poly1D& r) const
160  {return coeffs_ != r.coeffs_;}
161 
162  /** Monic polynomial of 0th degree (just 1.0) */
163  inline static Poly1D monicDeg0() {return 1.0L;}
164 
165  /** Monic polynomial of degree 1, x + b */
166  static Poly1D monicDeg1(long double b);
167 
168  /** Monic polynomial of degree 2, x^2 + b x + c */
169  static Poly1D monicDeg2(long double b, long double c);
170 
171  private:
172  std::vector<long double> coeffs_;
173  };
174 
175  template<typename Real>
176  class Poly1DShifted : public Functor1<Real, Real>
177  {
178  public:
179  inline Poly1DShifted(const Poly1D& poly, const Real shift)
180  : poly_(poly), shift_(shift) {}
181 
182  inline virtual ~Poly1DShifted() {}
183 
184  inline virtual Real operator()(const Real& x) const
185  {return poly_(x - shift_);}
186 
187  private:
188  Poly1D poly_;
189  Real shift_;
190  };
191 }
192 
193 #endif // NPSTAT_POLY1D_HH_
Interface definitions and concrete simple functors for a variety of functor-based calculations.
Definition: Poly1D.hh:177
Definition: Poly1D.hh:21
unsigned nRoots(long double a, long double b) const
void truncateLeadingZeros()
static Poly1D monicDeg2(long double b, long double c)
bool isClose(const Poly1D &r, long double eps) const
virtual long double operator()(const long double &x) const
Poly1D operator/(const Poly1D &) const
Poly1D integral(long double c) const
Poly1D operator+() const
Definition: Poly1D.hh:133
long double operator[](const unsigned degree) const
Definition: Poly1D.hh:99
unsigned deg() const
Definition: Poly1D.hh:96
Poly1D(unsigned degree, long double leadingCoeff)
Poly1D(const long double c0)
Definition: Poly1D.hh:58
Poly1D operator*(const Poly1D &) const
static Poly1D monicDeg0()
Definition: Poly1D.hh:163
Poly1D operator%(const Poly1D &) const
Poly1D(const std::vector< double > &c)
bool isNull() const
Definition: Poly1D.hh:122
void setCoefficient(unsigned degree, long double value)
void reserve(const unsigned degree)
Definition: Poly1D.hh:73
static Poly1D monicDeg1(long double b)
const std::vector< long double > & allCoefficients() const
Definition: Poly1D.hh:103
Poly1D(const double *coeffs, unsigned degree)
Poly1D derivative() const
long double leadingCoefficient() const
void truncate(const unsigned maxDegree)
Definition: AbsArrayProjector.hh:14
Definition: SimpleFunctors.hh:58