mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-11-04 05:50:31 -05:00 
			
		
		
		
	
		
			
				
	
	
		
			238 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			238 lines
		
	
	
		
			7.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
// Use, modification and distribution are subject to the
 | 
						|
// Boost Software License, Version 1.0.
 | 
						|
// (See accompanying file LICENSE_1_0.txt
 | 
						|
// or copy at http://www.boost.org/LICENSE_1_0.txt)
 | 
						|
 | 
						|
// Copyright Jeremy W. Murphy 2015.
 | 
						|
 | 
						|
// This file is written to be included from a Quickbook .qbk document.
 | 
						|
// It can be compiled by the C++ compiler, and run. Any output can
 | 
						|
// also be added here as comment or included or pasted in elsewhere.
 | 
						|
// Caution: this file contains Quickbook markup as well as code
 | 
						|
// and comments: don't change any of the special comment markups!
 | 
						|
 | 
						|
//[polynomial_arithmetic_0
 | 
						|
/*`First include the essential polynomial header (and others) to make the example:
 | 
						|
*/
 | 
						|
#include <boost/math/tools/polynomial.hpp>
 | 
						|
//] [polynomial_arithmetic_0
 | 
						|
 | 
						|
#include <boost/array.hpp>
 | 
						|
#include <boost/lexical_cast.hpp>
 | 
						|
#include <boost/assert.hpp>
 | 
						|
 | 
						|
#include <iostream>
 | 
						|
#include <stdexcept>
 | 
						|
#include <cmath>
 | 
						|
#include <string>
 | 
						|
#include <utility>
 | 
						|
 | 
						|
//[polynomial_arithmetic_1
 | 
						|
/*`and some using statements are convenient:
 | 
						|
*/
 | 
						|
 | 
						|
using std::string;
 | 
						|
using std::exception;
 | 
						|
using std::cout;
 | 
						|
using std::abs;
 | 
						|
using std::pair;
 | 
						|
 | 
						|
using namespace boost::math;
 | 
						|
using namespace boost::math::tools; // for polynomial
 | 
						|
using boost::lexical_cast;
 | 
						|
 | 
						|
//] [/polynomial_arithmetic_1]
 | 
						|
 | 
						|
template <typename T>
 | 
						|
string sign_str(T const &x)
 | 
						|
{
 | 
						|
  return x < 0 ? "-" : "+";
 | 
						|
}
 | 
						|
 | 
						|
template <typename T>
 | 
						|
string inner_coefficient(T const &x)
 | 
						|
{
 | 
						|
  string result(" " + sign_str(x) + " ");
 | 
						|
  if (abs(x) != T(1))
 | 
						|
      result += lexical_cast<string>(abs(x));
 | 
						|
  return result;
 | 
						|
}
 | 
						|
 | 
						|
/*! Output in formula format.
 | 
						|
For example: from a polynomial in Boost container storage  [ 10, -6, -4, 3 ]
 | 
						|
show as human-friendly formula notation: 3x^3 - 4x^2 - 6x + 10.
 | 
						|
*/
 | 
						|
template <typename T>
 | 
						|
string formula_format(polynomial<T> const &a)
 | 
						|
{
 | 
						|
  string result;
 | 
						|
  if (a.size() == 0)
 | 
						|
      result += lexical_cast<string>(T(0));
 | 
						|
  else
 | 
						|
  {
 | 
						|
    // First one is a special case as it may need unary negate.
 | 
						|
    unsigned i = a.size() - 1;
 | 
						|
    if (a[i] < 0)
 | 
						|
        result += "-";
 | 
						|
    if (abs(a[i]) != T(1))
 | 
						|
        result += lexical_cast<string>(abs(a[i]));
 | 
						|
 | 
						|
    if (i > 0)
 | 
						|
    {
 | 
						|
      result += "x";
 | 
						|
      if (i > 1)
 | 
						|
      {
 | 
						|
          result += "^" + lexical_cast<string>(i);
 | 
						|
          i--;
 | 
						|
          for (; i != 1; i--)
 | 
						|
              if (a[i])
 | 
						|
                result += inner_coefficient(a[i]) + "x^" + lexical_cast<string>(i);
 | 
						|
 | 
						|
          if (a[i])
 | 
						|
            result += inner_coefficient(a[i]) + "x";
 | 
						|
      }
 | 
						|
      i--;
 | 
						|
 | 
						|
      if (a[i])
 | 
						|
        result += " " + sign_str(a[i]) + " " + lexical_cast<string>(abs(a[i]));
 | 
						|
    }
 | 
						|
  }
 | 
						|
  return result;
 | 
						|
} // string formula_format(polynomial<T> const &a)
 | 
						|
 | 
						|
 | 
						|
int main()
 | 
						|
{
 | 
						|
  cout << "Example: Polynomial arithmetic.\n\n";
 | 
						|
 | 
						|
  try
 | 
						|
  {
 | 
						|
//[polynomial_arithmetic_2
 | 
						|
/*`Store the coefficients in a convenient way to access them,
 | 
						|
then create some polynomials using construction from an iterator range,
 | 
						|
and finally output in a 'pretty' formula format.
 | 
						|
 | 
						|
[tip Although we might conventionally write a polynomial from left to right
 | 
						|
in descending order of degree, Boost.Math stores in [*ascending order of degree].]
 | 
						|
 | 
						|
  Read/write for humans:    3x^3 - 4x^2 - 6x + 10
 | 
						|
  Boost polynomial storage: [ 10, -6, -4, 3 ]
 | 
						|
*/
 | 
						|
  boost::array<double, 4> const d3a = {{10, -6, -4, 3}};
 | 
						|
  polynomial<double> const a(d3a.begin(), d3a.end());
 | 
						|
 | 
						|
  // With C++11 and later, you can also use initializer_list construction.
 | 
						|
  polynomial<double> const b{{-2.0, 1.0}};
 | 
						|
 | 
						|
  // formula_format() converts from Boost storage to human notation.
 | 
						|
  cout << "a = " << formula_format(a)
 | 
						|
  << "\nb = " << formula_format(b) << "\n\n";
 | 
						|
 | 
						|
//] [/polynomial_arithmetic_2]
 | 
						|
 | 
						|
//[polynomial_arithmetic_3
 | 
						|
  // Now we can do arithmetic with the usual infix operators: + - * / and %.
 | 
						|
  polynomial<double> s = a + b;
 | 
						|
  cout << "a + b = " << formula_format(s) << "\n";
 | 
						|
  polynomial<double> d = a - b;
 | 
						|
  cout << "a - b = " << formula_format(d) << "\n";
 | 
						|
  polynomial<double> p = a * b;
 | 
						|
  cout << "a * b = " << formula_format(p) << "\n";
 | 
						|
  polynomial<double> q = a / b;
 | 
						|
  cout << "a / b = " << formula_format(q) << "\n";
 | 
						|
  polynomial<double> r = a % b;
 | 
						|
  cout << "a % b = " << formula_format(r) << "\n";
 | 
						|
//] [/polynomial_arithmetic_3]
 | 
						|
 | 
						|
//[polynomial_arithmetic_4
 | 
						|
/*`
 | 
						|
Division is a special case where you can calculate two for the price of one.
 | 
						|
 | 
						|
Actually, quotient and remainder are always calculated together due to the nature
 | 
						|
of the algorithm: the infix operators return one result and throw the other
 | 
						|
away.
 | 
						|
 | 
						|
If you are doing a lot of division and want both the quotient and remainder, then
 | 
						|
you don't want to do twice the work necessary.
 | 
						|
 | 
						|
In that case you can call the underlying function, [^quotient_remainder],
 | 
						|
to get both results together as a pair.
 | 
						|
*/
 | 
						|
  pair< polynomial<double>, polynomial<double> > result;
 | 
						|
  result = quotient_remainder(a, b);
 | 
						|
// Reassure ourselves that the result is the same.
 | 
						|
  BOOST_ASSERT(result.first == q);
 | 
						|
  BOOST_ASSERT(result.second == r);
 | 
						|
//] [/polynomial_arithmetic_4]
 | 
						|
//[polynomial_arithmetic_5
 | 
						|
  /* 
 | 
						|
We can use the right and left shift operators to add and remove a factor of x.
 | 
						|
This has the same semantics as left and right shift for integers where it is a 
 | 
						|
factor of 2. x is the smallest prime factor of a polynomial as is 2 for integers.
 | 
						|
*/
 | 
						|
    cout << "Right and left shift operators.\n";
 | 
						|
    cout << "\n" << formula_format(p) << "\n";
 | 
						|
    cout << "... right shift by 1 ...\n";
 | 
						|
    p >>= 1;
 | 
						|
    cout << formula_format(p) << "\n";
 | 
						|
    cout << "... left shift by 2 ...\n";
 | 
						|
    p <<= 2;
 | 
						|
    cout << formula_format(p) << "\n";    
 | 
						|
  
 | 
						|
/*
 | 
						|
We can also give a meaning to odd and even for a polynomial that is consistent
 | 
						|
with these operations: a polynomial is odd if it has a non-zero constant value, 
 | 
						|
even otherwise. That is:
 | 
						|
    x^2 + 1     odd
 | 
						|
    x^2         even    
 | 
						|
   */
 | 
						|
    cout << std::boolalpha;
 | 
						|
    cout << "\nPrint whether a polynomial is odd.\n";
 | 
						|
    cout << formula_format(s) << "   odd? " << odd(s) << "\n";
 | 
						|
    // We cheekily use the internal details to subtract the constant, making it even.
 | 
						|
    s -= s.data().front();
 | 
						|
    cout << formula_format(s) << "   odd? " << odd(s) << "\n";
 | 
						|
    // And of course you can check if it is even:
 | 
						|
    cout << formula_format(s) << "   even? " << even(s) << "\n";
 | 
						|
    
 | 
						|
    
 | 
						|
    //] [/polynomial_arithmetic_5]
 | 
						|
    //[polynomial_arithmetic_6]
 | 
						|
    /* For performance and convenience, we can test whether a polynomial is zero 
 | 
						|
     * by implicitly converting to bool with the same semantics as int.    */
 | 
						|
    polynomial<double> zero; // Default construction is 0.
 | 
						|
    cout << "zero: " << (zero ? "not zero" : "zero") << "\n";
 | 
						|
    cout << "r: " << (r ? "not zero" : "zero") << "\n";
 | 
						|
    /* We can also set a polynomial to zero without needing a another zero 
 | 
						|
     * polynomial to assign to it. */
 | 
						|
    r.set_zero();
 | 
						|
    cout << "r: " << (r ? "not zero" : "zero") << "\n";    
 | 
						|
    //] [/polynomial_arithmetic_6]
 | 
						|
}
 | 
						|
catch (exception const &e)
 | 
						|
{
 | 
						|
  cout << "\nMessage from thrown exception was:\n   " << e.what() << "\n";
 | 
						|
}
 | 
						|
} // int main()
 | 
						|
 | 
						|
/*
 | 
						|
//[polynomial_output_1
 | 
						|
 | 
						|
a = 3x^3 - 4x^2 - 6x + 10
 | 
						|
b = x - 2
 | 
						|
 | 
						|
//] [/polynomial_output_1]
 | 
						|
 | 
						|
 | 
						|
//[polynomial_output_2
 | 
						|
 | 
						|
a + b = 3x^3 - 4x^2 - 5x + 8
 | 
						|
a - b = 3x^3 - 4x^2 - 7x + 12
 | 
						|
a * b = 3x^4 - 10x^3 + 2x^2 + 22x - 20
 | 
						|
a / b = 3x^2 + 2x - 2
 | 
						|
a % b = 6
 | 
						|
 | 
						|
//] [/polynomial_output_2]
 | 
						|
 | 
						|
*/
 |