cisst-saw
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
nmrPolynomialTermPowerIndex.h
Go to the documentation of this file.
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ex: set filetype=cpp softtabstop=4 shiftwidth=4 tabstop=4 cindent expandtab: */
3 
4 /*
5 
6  Author(s): Ofri Sadowsky
7  Created on: 2001-10-21
8 
9  (C) Copyright 2001-2007 Johns Hopkins University (JHU), All Rights
10  Reserved.
11 
12 --- begin cisst license - do not edit ---
13 
14 This software is provided "as is" under an open source license, with
15 no warranty. The complete license can be found in license.txt and
16 http://www.cisst.org/cisst/license.txt.
17 
18 --- end cisst license ---
19 */
20 
27 #ifndef _nmrPolynomialTermPowerIndex_h
28 #define _nmrPolynomialTermPowerIndex_h
29 
30 #include <vector>
31 #include <stdexcept>
34 
35 class nmrPolynomialBase;
36 
41 #ifndef DEFINE_FORMATTED_OUTPUT
42 #define DEFINE_FORMATTED_OUTPUT 0
43 #endif
44 
90 {
91 public:
95  typedef int VariableIndexType;
98  typedef int PowerType;
101  typedef unsigned long MultinomialCoefficientType;
102 
103 
110  nmrPolynomialTermPowerIndex(VariableIndexType numVariables = 1, PowerType minDegree = 0, PowerType maxDegree = 4);
111 
116 
121  int GetDegree() const
122  {
123  return Degree;
124  }
125 
127  {
128  return MaxDegree;
129  }
130 
132  {
133  return MinDegree;
134  }
135 
136  void SetMaxDegree(PowerType newMax) throw(std::runtime_error)
137  {
138  if (newMax < this->Degree) {
139  throw std::runtime_error("nmrPolynomialTermPowerIndex: Attempt to set max degree below current degree");
140  }
141  if (newMax < this->MinDegree) {
142  throw std::runtime_error("nmrPolynomialTermPowerIndex: Attempt to set max degree below set minimum");
143  }
144  MaxDegree = newMax;
145  }
146 
147  void SetMinDegree(PowerType newMin) throw(std::runtime_error)
148  {
149  if (newMin > this->Degree) {
150  throw std::runtime_error("nmrPolynomialTermPowerIndex: Attempt to set min degree above current degree");
151  }
152  if (newMin > this->MaxDegree) {
153  throw std::runtime_error("nmrPolynomialTermPowerIndex: Attempt to set max degree above set maximum");
154  }
155  MinDegree = newMin;
156  }
157 
161  bool IsValid() const
162  {
163  return (MinDegree <= Degree) && (Degree <= MaxDegree);
164  }
165 
167  {
168  return Powers.size();
169  }
170 
176  {
177  return Powers[variable];
178  }
179 
181  const PowerType * GetPowers() const
182  {
183  return &(Powers[0]);
184  }
185 
187  const int * GetPowersAsSigned() const
188  {
189  return reinterpret_cast<const int *>(GetPowers());
190  }
191 
196  void SetPower(VariableIndexType variable, PowerType power)
197  {
198  Degree += power - Powers[variable];
199  Powers[variable] = power;
200  }
201 
203  void SetPowers(const PowerType powers[])
204  {
206  Degree = 0;
207  for (i = 0; i < GetNumVariables(); i++) {
208  Powers[i] = powers[i];
209  Degree += powers[i];
210  }
211  }
212 
217  void CopyPowers(const nmrPolynomialTermPowerIndex & other);
218 
221  void SetDegree(PowerType degree);
222 
224  void GoBegin();
226  void GoEnd();
227 
245  void Increment();
246 
256  void Decrement();
257 
259  bool IsBegin() const
260  {
261  return (GetDegree() == GetMinDegree()) && (GetPower(0) == GetMinDegree());
262  }
263 
265  bool IsEnd() const
266  {
267  return (GetDegree() == GetMaxDegree()) && (GetPower(GetNumVariables() - 1) == GetMaxDegree());
268  }
269 
284  int Compare(const nmrPolynomialTermPowerIndex & other) const;
285 
290  bool operator< (const nmrPolynomialTermPowerIndex& other) const
291  {
292  return (this->Compare(other) < 0);
293  }
294 
299  bool operator > (const nmrPolynomialTermPowerIndex& other) const
300  {
301  return (other < *this);
302  }
303 
304  bool operator<= (const nmrPolynomialTermPowerIndex & other) const
305  {
306  return (this->Compare(other) <= 0);
307  }
308 
309  bool operator>= (const nmrPolynomialTermPowerIndex & other) const
310  {
311  return (other <= *this);
312  }
313 
319  bool operator== (const nmrPolynomialTermPowerIndex& other) const;
320  // This is an incorrect definition of operator==
321  //{ return (this->Compare(other) == 0); }
322 
323 
324  // For a set of powers 'p1',...,'pn' whose sum is 'd', return
325  // d! / (p1! p2! ... pn!).
326  // In this function, d is given as an argument, so there is assumed to
327  // be an implicit (non-independent) variable in the polynomial.
328  static MultinomialCoefficientType
329  EvaluateMultinomialCoefficient(VariableIndexType numIndices,
330  PowerType chooseFrom, const PowerType indices[]);
331 
332  // For a set of powers 'p1',...,'pn' whose sum is 'd', return
333  // d! / (p1! p2! ... pn!).
334  // In this function, d is the sum of all the powers stored in 'indices'
335  static MultinomialCoefficientType
336  EvaluateMultinomialCoefficient(VariableIndexType numIndices,
337  const PowerType indices[]);
338 
339 
340  // For a set of powers 'p1',...,'pn' whose sum is 'd', return
341  // d! / (p1! p2! ... pn!).
342  // In this function, d is the sum of all the powers stored in this term.
344  {
345  return EvaluateMultinomialCoefficient(GetNumVariables(), GetPowers());
346  }
347 
348  // For a set of powers 'p1',...,'pn' whose sum is 'd', return
349  // d! / (p1! p2! ... pn!).
350  // In this function, d is given as an argument, so there is assumed to
351  // be an implicit (non-independent) variable in the polynomial.
353  {
354  return EvaluateMultinomialCoefficient(GetNumVariables(), d, GetPowers());
355  }
356 
357  // Return the combinatorial number of possible power sets for the term.
358  //
359  // For a fixed degree d, and n variables, the number of combinations
360  // is the number of multisets of size d over n elements.
361  // First we choose k = number of variables in the term. if d<n we can choose
362  // k=1..d, otherwise we can choose k=1..n . But for simplicity and arithmetic
363  // reasons we will assume k=1..d. We will see that it does not affect the
364  // final result. Next, we have to choose the variables in the term. We have
365  // \choose{n}{k} combinations. Finally we choose the power for each variable.
366  // We have \choose{d-1}{k-1} combinations. The entire expression is
367  //
368  // \sum_{k=1}^{d} \choose{n}{k} \choose{d-1}{k-1}
369  //
370  // Note that for any k>n, \choose{n}{k} = 0, so we don't need to worry about
371  // d>n.
372  // The entire sum can be simplified into \choose{n+d-1}{d}. However, for a term
373  // index of n variables, we have to sum over all possible degrees:
374  //
375  // \sum_{d=MinDegree}^{MaxDegree} \choose{n+d-1}{d}.
376  //
377  // \choose{n+d}{d+1} = (n+d)! / ( (d+1)! (n-1)! ) = ((n+d)(n+d-1)) / ((d+1) d! (n-1)!)
378  // = ((n+d)/(d+1)) * ( (n+d-1)! d! (n-1)! ) = ((n+d)/(d+1)) * \choose{n+d-1}{d}
379  //
380  // Therefore, we only need to make a long computation for the first element of the
381  // sum, and the rest are received incrementally.
382  MultinomialCoefficientType CountPowerCombinations() const;
383 
387  MultinomialCoefficientType CountLowerOrderTerms() const;
388 
389 #if DEFINE_FORMATTED_OUTPUT
390  // Print the powers of the term index in sprintf format into a character
391  // buffer. No assertion is made to ensure that the buffer has enough capacity
392  // to store the formatted message. All powers are printed, included zeroes.
393  // Parameters:
394  // buffer [i/o] -- destination buffer for the output
395  // widthFormat [i] -- a format specification to enable equal column width.
396  //
397  // Return: a pointer to the character immediately following the formatted output
398  char * FormatPowers(char * buffer, const char * widthFormat = "%d") const;
399 #endif
400 
401 
402 #if DEFINE_FORMATTED_OUTPUT
403  // Print the entire term index in formatted output. The format is:
404  // [numVariables minDegree maxDegree] powers...
405  // See FormatPowers for parameter and return value specification.
406  char * FormatTermIndex(char * buffer, const char * widthFormat = "%d") const;
407 #endif
408 
409 #if DEFINE_FORMATTED_OUTPUT
410  // Return the estimated number of characters required to store the formatted
411  // powers (from FormatPowers())
412  int CalculateFormatPowerLength(const char * widthFormat = "%d") const
413  {
414  char buff[10];
415  sprintf( buff, widthFormat, GetMaxDegree() );
416  int varLength = strlen(buff) + 1;
417  return varLength * GetNumVariables();
418  }
419 #endif
420 
426  void SerializeRaw(std::ostream & output) const;
427 
431  void DeserializeRaw(std::istream & input);
432 
438  void SerializeIndexRaw(std::ostream & output) const;
439 
442  void DeserializeIndexRaw(std::istream & input);
443 
444 protected:
445  std::vector<PowerType> Powers; // the powers of all the variables in the term
446  PowerType MinDegree; // the minimal possible degree of the term
447  PowerType MaxDegree; // the maximal possible degree of the term
448 
449  // the degree of the term. Note that it may be negative, in which case the term is
450  // invalid. This member should always be equal to the sum of all powers. It
451  // is therefore redundant information is only serves as a cache for sorting
452  // purposes. It is not serialized.
453  int Degree;
454 
455 };
456 
457 #endif // _nmrPolynomialTermPowerIndex_h
#define CISST_EXPORT
Definition: cmnExportMacros.h:50
int Degree
Definition: nmrPolynomialTermPowerIndex.h:453
MultinomialCoefficientType GetMultinomialCoefficient() const
Definition: nmrPolynomialTermPowerIndex.h:343
std::vector< PowerType > Powers
Definition: nmrPolynomialTermPowerIndex.h:445
Portability across compilers and operating systems tools.
MultinomialCoefficientType GetMultinomialCoefficient(PowerType d) const
Definition: nmrPolynomialTermPowerIndex.h:352
const int * GetPowersAsSigned() const
Definition: nmrPolynomialTermPowerIndex.h:187
PowerType MaxDegree
Definition: nmrPolynomialTermPowerIndex.h:447
void SetPower(VariableIndexType variable, PowerType power)
Definition: nmrPolynomialTermPowerIndex.h:196
int VariableIndexType
Definition: nmrPolynomialTermPowerIndex.h:95
PowerType MinDegree
Definition: nmrPolynomialTermPowerIndex.h:446
Definition: nmrPolynomialBase.h:51
PowerType GetMinDegree() const
Definition: nmrPolynomialTermPowerIndex.h:131
VariableIndexType GetNumVariables() const
Definition: nmrPolynomialTermPowerIndex.h:166
int PowerType
Definition: nmrPolynomialTermPowerIndex.h:98
bool IsEnd() const
Definition: nmrPolynomialTermPowerIndex.h:265
void SetPowers(const PowerType powers[])
Definition: nmrPolynomialTermPowerIndex.h:203
void SetMaxDegree(PowerType newMax)
Definition: nmrPolynomialTermPowerIndex.h:136
int GetDegree() const
Definition: nmrPolynomialTermPowerIndex.h:121
PowerType GetMaxDegree() const
Definition: nmrPolynomialTermPowerIndex.h:126
void SetMinDegree(PowerType newMin)
Definition: nmrPolynomialTermPowerIndex.h:147
PowerType GetPower(VariableIndexType variable) const
Definition: nmrPolynomialTermPowerIndex.h:175
bool IsValid() const
Definition: nmrPolynomialTermPowerIndex.h:161
bool IsBegin() const
Definition: nmrPolynomialTermPowerIndex.h:259
const PowerType * GetPowers() const
Definition: nmrPolynomialTermPowerIndex.h:181
unsigned long MultinomialCoefficientType
Definition: nmrPolynomialTermPowerIndex.h:101
Represents the power index of a single term in a multi-variable polynomial.
Definition: nmrPolynomialTermPowerIndex.h:89
Rules of exporting.