MADNESS 0.10.1
polynomial.h
Go to the documentation of this file.
1/* This file is a part of Slymer, which is distributed under the Creative
2 Commons Attribution-NonCommercial 4.0 International Public License.
3
4 (c) 2017 Stony Brook University. */
5
6/**
7 * \file Basis/polynomial.h
8 * \brief API and helper functions for describing polynomial functions of
9 * three variables.
10 *
11 * The array is indexed by the polyIndex function. Each element of the array
12 * is a coefficient on the polynomial.
13 */
14
15#ifndef __Basis_polynomial_h__
16#define __Basis_polynomial_h__
17
18#include <array>
19#include <vector>
20
21namespace slymer {
22
23/**
24 * \brief Array for storing coefficients of a polynomial of three variables
25 * with specified degree.
26 *
27 * The general polynomial of three variables is written as
28 * \f[ \sum_{i,j,k} c_{i,j,k} x^i y^j z^k, \f]
29 * where \f$0\le i+j+k\le N\f$. This data structure stores the coefficients
30 * in a vector and provides access routines in terms of the exponents \f$i\f$,
31 * \f$j\f$, and \f$k\f$.
32 *
33 * \note This class is not designed for polynomials with a large degree.
34 */
36
37protected:
38 /// The degree of the polynomial.
39 unsigned degree;
40
41 /**
42 * \brief Array storing the coefficients.
43 *
44 * For a given degree n, there are \f$(n+1)(n+2)/2\f$ monomials. The total
45 * array thus has \f$(n+1)*(n+2)*(n+3)/6\f$ terms. The array stores all terms
46 * with degree 0, then degree 1, then degree 2, etc.
47 */
48 std::vector<double> coeffs;
49
50 /**
51 * \brief Gets the array index for the coefficient of a particular term.
52 *
53 * Terms of degree 0 are stored before those of degree 1, etc.
54 *
55 * Within a particular degree, think of the problem in the combinatorial "stars
56 * and bars" idea: there are n stars and two bars dividing them into three
57 * parts. (Each part corresponds to the number of x, y, or z factors.) The first
58 * array element will be bars in the 0 and 1 positions, then 0 and 2, ..., 0 and
59 * n+1, then 1 and 2, etc.
60 *
61 * \param[in] pows The powers of x, y, and z for this term.
62 * \return The array offset, as described above.
63 */
64 static inline unsigned polyIndex(const std::array<unsigned, 3> &pows) {
65 const unsigned n = pows[0] + pows[1] + pows[2];
66
67 // calculate the offset within the level of the degree...
68 // x-y offset. All terms with pows[0] == 0 are first; there are n+1 of them.
69 // Then pows[0] == 1; there are n, etc.
70 unsigned ret = (n+1)*pows[0] - (pows[0]-1)*pows[0] / 2;
71 // y-z offset. how many y factors are there? pows[1]. This value being 0
72 // comes first, then 1, then 2, etc.
73 ret += pows[1];
74
75 // calculate the offset for smaller degrees. There are (n+1)(n+2)/2 elements
76 // for degree n; add up all the smaller degrees.
77 ret += n*(n+1)*(n+2)/6;
78
79 return ret;
80 }
81
82public:
83 /**
84 * \brief Get the degree of the polynomial.
85 *
86 * \return The degree of the polynomial.
87 */
88 unsigned get_degree() const {
89 return degree;
90 }
91
92 PolynomialCoeffs() = delete;
93
94 /**
95 * \brief Create a linear function with the specified coefficients.
96 *
97 * \param[in] constant The constant term.
98 * \param[in] x The coefficient on x.
99 * \param[in] y The coefficient on y.
100 * \param[in] z The coefficient on z.
101 */
102 PolynomialCoeffs(const double constant, const double x, const double y,
103 const double z) : degree(1), coeffs(4) {
104
105 coeffs[polyIndex({{0,0,0}})] = constant;
106 coeffs[polyIndex({{1,0,0}})] = x;
107 coeffs[polyIndex({{0,1,0}})] = y;
108 coeffs[polyIndex({{0,0,1}})] = z;
109 }
110
111 /**
112 * \brief Create a polynomial of degree N.
113 *
114 * \param[in] N The degree of the polynomial.
115 */
116 PolynomialCoeffs(const unsigned N)
117 : degree(N), coeffs((N+1)*(N+2)*(N+3)/6) {
118
119 for(double &coeff : coeffs)
120 coeff = 0.;
121 }
122
123 /**
124 * \brief Access the coefficient for the specified term.
125 *
126 * \param[in] pows The powers of x, y, and z for this term.
127 * \return Reference to the array term.
128 */
129 double &operator[] (const std::array<unsigned, 3> &pows) {
130 return coeffs[polyIndex(pows)];
131 }
132
133 /**
134 * \brief Access the coefficient for the specified term.
135 *
136 * \param[in] pows The powers of x, y, and z for this term.
137 * \return The array term.
138 */
139 double operator[] (const std::array<unsigned, 3> &pows) const {
140 return coeffs[polyIndex(pows)];
141 }
142
143 /**
144 * \brief Evaluate the polynomial at the specified point.
145 *
146 * \note This implemention is a bit naive; it is not intended for
147 * polynomials with a large degree.
148 *
149 * \param[in] pt The point at which the polynomial is evaluated.
150 * \return The value of the polynomial at the point.
151 */
152 double operator() (const std::array<double, 3> &pt) const;
153
154 /**
155 * \brief Add two polynomials together.
156 *
157 * *this is one of the polynomials.
158 *
159 * \param[in] rhs The other polynomial.
160 * \return The sum of *this and rhs.
161 */
163
164 /**
165 * \brief Adds another polynomial to this one.
166 *
167 * \param[in] rhs The other polynomial.
168 * \return The sum of *this and rhs, in *this.
169 */
171
172 /**
173 * \brief Multiply a polynomial by a constant value.
174 *
175 * *this is one of the polynomials.
176 *
177 * \param[in] c The constant value.
178 * \return The product of c and the polynomial.
179 */
180 PolynomialCoeffs operator* (const double c) const;
181
182 /**
183 * \brief Scale the polynomial by a constant.
184 *
185 * \param[in] c The scale factor.
186 * \return The scaled polynomial (*this).
187 */
188 PolynomialCoeffs &operator*= (const double c);
189
190 /**
191 * \brief Multiply two polynomials together.
192 *
193 * *this is one of the polynomials.
194 *
195 * \param[in] rhs The other polynomial.
196 * \return The product of *this and rhs.
197 */
199
200 /**
201 * \brief Expands a linear polynomial raised to a power.
202 *
203 * Essentially expands the polynomial
204 * \f[ (coeffs[0] + coeffs[1]*x + coeffs[2]*y + coeffs[3]*z)^j \f]
205 * into a new PolynomialCoeffs object. That is, output[{{p,q,r}}] is the
206 * coefficient on the \f$x^p y^q z^r\f$ term.
207 *
208 * This function requires multinomial coefficients, which involve
209 * factorials. We assume that the arguments to the factorials will not
210 * be large and hard-code small values. An error will be thrown if
211 * the maximum value is exceeded.
212 *
213 * \throw std::runtime_error if the polynomial does not have degree 1.
214 *
215 * \param[in] j The exponent of the expansion.
216 * \return The polynomial, ordered using the polyIndex scheme.
217 */
218 PolynomialCoeffs pow(const unsigned j) const;
219
220}; // class PolynomialCoeffs
221
222/**
223 * \brief Multiply a polynomial by a constant value.
224 *
225 * \param[in] c The constant value.
226 * \param[in] poly The polynomial.
227 * \return The product of c and the polynomial.
228 */
229inline PolynomialCoeffs operator* (const double c, const PolynomialCoeffs &poly) {
230 return poly * c;
231}
232
233} // namespace slymer
234
235#endif
Array for storing coefficients of a polynomial of three variables with specified degree.
Definition polynomial.h:35
double operator()(const std::array< double, 3 > &pt) const
Evaluate the polynomial at the specified point.
Definition polynomial.cc:18
PolynomialCoeffs(const double constant, const double x, const double y, const double z)
Create a linear function with the specified coefficients.
Definition polynomial.h:102
PolynomialCoeffs & operator*=(const double c)
Scale the polynomial by a constant.
Definition polynomial.cc:90
PolynomialCoeffs operator*(const double c) const
Multiply a polynomial by a constant value.
Definition polynomial.cc:81
PolynomialCoeffs pow(const unsigned j) const
Expands a linear polynomial raised to a power.
Definition polynomial.cc:119
double & operator[](const std::array< unsigned, 3 > &pows)
Access the coefficient for the specified term.
Definition polynomial.h:129
static unsigned polyIndex(const std::array< unsigned, 3 > &pows)
Gets the array index for the coefficient of a particular term.
Definition polynomial.h:64
unsigned get_degree() const
Get the degree of the polynomial.
Definition polynomial.h:88
PolynomialCoeffs operator+(const PolynomialCoeffs &rhs) const
Add two polynomials together.
Definition polynomial.cc:30
std::vector< double > coeffs
Array storing the coefficients.
Definition polynomial.h:48
PolynomialCoeffs & operator+=(const PolynomialCoeffs &rhs)
Adds another polynomial to this one.
Definition polynomial.cc:58
unsigned degree
The degree of the polynomial.
Definition polynomial.h:39
PolynomialCoeffs(const unsigned N)
Create a polynomial of degree N.
Definition polynomial.h:116
Definition basis.h:22
GaussianFunction operator*(const double lhs, const GaussianFunction &rhs)
Multiply a GaussianFunction by a scalar.
Definition gaussian.h:372
static const double c
Definition relops.cc:10
#define N
Definition testconv.cc:37
double constant(const coordT &x)
Definition testper.cc:46