Skip to content

Instantly share code, notes, and snippets.

@pacmancoder
Created January 21, 2018 21:37
Show Gist options
  • Save pacmancoder/4ecf15365086456adfeca0a3ec2b6ea2 to your computer and use it in GitHub Desktop.
Save pacmancoder/4ecf15365086456adfeca0a3ec2b6ea2 to your computer and use it in GitHub Desktop.
Polynomial
#include <iostream>
#include <Polynomial.h>
#include <string>
#include <vector>
#include <fstream>
#include <ios>
using namespace Calculus;
namespace
{
const char* DEFAULT_VARIABLES_FILE("variables.bin");
void ClearCin()
{
size_t MAX_IGNORE_CHARS(10000);
std::cin.clear();
std::cin.ignore(MAX_IGNORE_CHARS, '\n');
}
char SelectOption()
{
std::cout << "option > ";
char option = 0;
std::cin >> option;
ClearCin();
return option;
}
size_t SelectVariable()
{
char index = 0;
for(;;)
{
std::cout << "variable index > ";
std::cin >> index;
if (index < '0' || index > '9')
{
std::cout << "Please provide value from 0 to 9" << std::endl;
ClearCin();
continue;
}
ClearCin();
return static_cast<size_t >(index - '0');
}
}
Polynomial::Exponent SelectExponent()
{
Polynomial::Exponent exponent = 0;
for (;;)
{
std::cout << "exponent (order) > ";
if (std::cin >> exponent)
{
ClearCin();
return exponent;
}
std::cout << "Please provide valid integer!" << std::endl;
ClearCin();
}
}
Polynomial::Scale SelectScale()
{
Polynomial::Scale scale = 0;
for (;;)
{
std::cout << "scale (coefficient) > ";
if (std::cin >> scale)
{
ClearCin();
return scale;
}
std::cout << "Please provide valid float!" << std::endl;
ClearCin();
}
}
void DisplayVariables(const std::vector<Polynomial>& variables)
{
for (size_t i = 0; i < variables.size(); ++i)
{
std::cout << "[" << i << "] : " << variables[i].toString() << std::endl;
}
}
void AddMemberToPolynomial(std::vector<Polynomial>& variables)
{
auto variable = SelectVariable();
Polynomial::Exponent exponent = SelectExponent();
Polynomial::Scale scale = SelectScale();
variables[variable][exponent] = scale;
}
void CopyVariable(std::vector<Polynomial>& variables)
{
std::cout << "Form:" << std::endl;
auto from = SelectVariable();
std::cout << "To:" << std::endl;
auto to = SelectVariable();
variables[to] = variables[from];
}
void MultiplyByConst(std::vector<Polynomial>& variables)
{
auto variable = SelectVariable();
std::cout << "Scale:" << std::endl;
auto scale = SelectScale();
variables[variable] = variables[variable] * scale;
}
void DivideByConst(std::vector<Polynomial>& variables)
{
auto variable = SelectVariable();
std::cout << "Divisor:" << std::endl;
auto scale = SelectScale();
variables[variable] = variables[variable] / scale;
}
void Multiply(std::vector<Polynomial>& variables)
{
std::cout << "Variable 1:" << std::endl;
auto variable1 = SelectVariable();
std::cout << "Variable 2:" << std::endl;
auto variable2 = SelectVariable();
std::cout << "Resulting variable:" << std::endl;
auto result = SelectVariable();
variables[result] = variables[variable1] * variables[variable2];
}
void Add(std::vector<Polynomial>& variables)
{
std::cout << "Variable 1:" << std::endl;
auto variable1 = SelectVariable();
std::cout << "Variable 2:" << std::endl;
auto variable2 = SelectVariable();
std::cout << "Resulting variable:" << std::endl;
auto result = SelectVariable();
variables[result] = variables[variable1] + variables[variable2];
}
void PowerOfPolynomial(std::vector<Polynomial>& variables)
{
auto variable = SelectVariable();
std::cout << "Exponent:" << std::endl;
auto exp = SelectExponent();
variables[variable] = variables[variable] ^ exp;
}
void SetScaleForRange(std::vector<Polynomial>& variables)
{
auto variable = SelectVariable();
std::cout << "Lowest exponent:" << std::endl;
auto from = SelectExponent();
std::cout << "Highest exponent:" << std::endl;
auto to = SelectExponent();
std::cout << "Scale:" << std::endl;
auto scale = SelectScale();
variables[variable](from, to) = scale;
}
void LoadVariables(std::vector<Polynomial>& variables)
{
std::ifstream file(DEFAULT_VARIABLES_FILE, std::ios::binary | std::ios::in);
for (auto& v : variables)
{
file >> v;
}
}
void SaveVariables(const std::vector<Polynomial>& variables)
{
std::ofstream file(DEFAULT_VARIABLES_FILE, std::ios::binary | std::ios::out | std::ios::trunc);
for (const auto& v : variables)
{
file << v;
}
}
void Evaluate(const std::vector<Polynomial>& variables)
{
auto variable = SelectVariable();
std::cout << "Enter value for variable:" << std::endl;
auto value = SelectScale();
std::cout << "Result: " << variables[variable].toString() << " = " << variables[variable](value) << std::endl;
}
void ChangeIdentifier(std::vector<Polynomial>& variables)
{
auto variable = SelectVariable();
std::string identifier;
std::cout << "Enter identifier (one char):" << std::endl;
identifier.push_back(SelectOption());
variables[variable].setVariableName(identifier);
}
void ShowMenu()
{
std::cout << "=== Select action with key ===" << std::endl;
std::cout << "d - Display current variables" << std::endl;
std::cout << "a - Set single member of polynomial" << std::endl;
std::cout << "c - Copy variable" << std::endl;
std::cout << "q - Exit from application" << std::endl;
std::cout << "r - Set scale for the range of the members" << std::endl;
std::cout << "u - Multiply on constant" << std::endl;
std::cout << "l - Divide on constant" << std::endl;
std::cout << "p - Raise polynomial to power" << std::endl;
std::cout << "m - Multiply 2 polynomials" << std::endl;
std::cout << "s - Sum 2 polynomials" << std::endl;
std::cout << "o - Save variables to file" << std::endl;
std::cout << "i - Load variables from file" << std::endl;
std::cout << "e - Evaluate polynomial in point" << std::endl;
std::cout << "v - Change default variable identifier" << std::endl;
}
}
int main(int argc, char* argv[])
{
std::vector<Polynomial> variables(10);
bool exitRequested = false;
for(;;)
{
ShowMenu();
auto option = SelectOption();
switch (option)
{
case 'd': DisplayVariables(variables); break;
case 'a': AddMemberToPolynomial(variables); break;
case 'c': CopyVariable(variables); break;
case 'r': SetScaleForRange(variables); break;
case 'u': MultiplyByConst(variables); break;
case 'l': DivideByConst(variables); break;
case 'p': PowerOfPolynomial(variables); break;
case 'm': Multiply(variables); break;
case 's': Add(variables); break;
case 'o': SaveVariables(variables); break;
case 'i': LoadVariables(variables); break;
case 'e': Evaluate(variables); break;
case 'v': ChangeIdentifier(variables); break;
case 'q': exitRequested = true; break;
default: break;
}
if (exitRequested)
{
break;
}
std::cout << std::endl;
}
return 0;
}
#include <Polynomial.h>
#include <sstream>
#include <cmath>
using namespace Calculus;
Polynomial::Polynomial() :
Polynomial(PolynomialMap()) {}
Polynomial::Polynomial(const Polynomial::PolynomialMap& polyMap) :
variableName_("x"), poly_(polyMap) {}
Polynomial::Polynomial(const Polynomial& rhs) :
variableName_(rhs.variableName_), poly_(rhs.poly_) {}
Polynomial::Polynomial(std::istream& stream)
{
deserialize(stream);
}
Polynomial& Polynomial::operator=(const Polynomial& rhs)
{
variableName_ = rhs.variableName_;
poly_ = rhs.poly_;
return *this;
}
Polynomial::Scale& Polynomial::operator[](size_t order)
{
// operator [] for map will always construct default value (in our case - scale which equals 0)
return poly_[order];
}
Polynomial::PolynomialMap &Polynomial::operator->()
{
return poly_;
}
std::string Polynomial::toString() const
{
std::stringstream stringStream;
bool isFirst = true;
for (const auto& f : poly_)
{
if (!isFirst)
{
stringStream << " ";
}
// scale is zero -- shouldn't be displayed
if (f.second == 0)
{
continue;
}
// display sign
if (f.second < 0)
{
stringStream << "- ";
}
else if (f.second > 0 && !isFirst)
{
stringStream << "+ ";
}
// display scale
if (std::fabs(f.second) != 1 || f.first == 0)
{
stringStream << std::fabs(f.second);
}
// display variable
if (f.first != 0)
{
stringStream << variableName_;
if (f.first != 1)
{
stringStream << "^" << f.first;
}
}
isFirst = false;
}
return stringStream.str();
}
void Polynomial::deserialize(std::istream &stream)
{
poly_.clear();
size_t mapSize = 0;
Exponent exponent = 0;
Scale scale = 0;
stream.read(reinterpret_cast<char*>(&mapSize), sizeof(mapSize));
for (auto i = 0; i < mapSize; ++i)
{
stream.read(reinterpret_cast<char*>(&exponent), sizeof(exponent));
stream.read(reinterpret_cast<char*>(&scale), sizeof(scale));
poly_[exponent] = scale;
}
}
void Polynomial::serialize(std::ostream &stream) const
{
size_t mapSize = poly_.size();
stream.write(reinterpret_cast<char*>(&mapSize), sizeof(mapSize));
for (const auto& f : poly_)
{
stream.write(reinterpret_cast<const char*>(&(f.first)), sizeof(f.first));
stream.write(reinterpret_cast<const char*>(&(f.second)), sizeof(f.second));
}
}
Real Polynomial::operator()(Real arg) const
{
Real acc(0);
for (const auto& f : poly_)
{
acc += std::pow(arg * f.second, f.first);
}
return acc;
}
Polynomial::ScaleHandle Polynomial::operator()(size_t first, size_t last)
{
return Polynomial::ScaleHandle(*this, first, last);
}
Polynomial Polynomial::operator*(Real rhs) const
{
Polynomial poly(*this);
for (const auto& f : poly_)
{
poly[f.first] *= rhs;
}
return poly;
}
Polynomial Polynomial::operator+(const Polynomial& rhs) const
{
Polynomial poly(*this);
for (const auto& f : rhs.poly_)
{
poly[f.first] += f.second;
}
return poly;
}
Polynomial Polynomial::operator/(Real rhs) const
{
return (*this) * (1 / rhs);
}
Polynomial Polynomial::operator*(const Polynomial &rhs) const
{
Polynomial poly;
poly.setVariableName(variableName_);
for (const auto& f1 : poly_)
{
for (const auto& f2 : rhs.poly_)
{
poly[f1.first + f2.first] += f1.second * f2.second;
}
}
return poly;
}
Polynomial Polynomial::operator^(Exponent rhs) const
{
Polynomial poly(*this);
for (Exponent i = 1; i < rhs; ++i)
{
poly = poly * (*this);
}
return poly;
}
std::ostream& operator<<(std::ostream &stream, const Polynomial& poly)
{
poly.serialize(stream);
return stream;
}
std::istream& operator>>(std::istream &stream, Polynomial& poly)
{
poly.deserialize(stream);
return stream;
}
void Polynomial::setVariableName(const std::string& variableName)
{
variableName_ = variableName;
}
// Pseudo-variable implementation
Polynomial::ScaleHandle::ScaleHandle(Polynomial &parent, size_t first, size_t last) :
parent_(parent), first_(first), last_(last) {}
Polynomial::ScaleHandle::ScaleHandle(const Polynomial::ScaleHandle& rhs) :
parent_(rhs.parent_), first_(rhs.first_), last_(rhs.last_) {}
Polynomial::ScaleHandle &Polynomial::ScaleHandle::operator=(Real scale)
{
for (auto i = first_; i <= last_; ++i)
{
parent_[i] = scale;
}
return *this;
}
#pragma once
#include <map>
#include <functional>
namespace Calculus
{
typedef float Real;
struct PowerFunction
{
Real scale;
Real exponent;
};
class Polynomial
{
public:
typedef size_t Exponent;
typedef Real Scale;
typedef std::map<Exponent, Scale, std::greater<Exponent>> PolynomialMap;
public:
class ScaleHandle
{
public:
ScaleHandle(Polynomial& parent, Exponent first, Exponent last);
ScaleHandle(const ScaleHandle& rhs);
ScaleHandle& operator=(const ScaleHandle&) = delete;
ScaleHandle& operator=(Real scale);
private:
Polynomial& parent_;
Exponent first_;
Exponent last_;
};
public:
Polynomial();
explicit Polynomial(std::istream& stream);
explicit Polynomial(const PolynomialMap& polyMap);
Polynomial(const Polynomial& poly);
Polynomial& operator =(const Polynomial& rhs);
Scale& operator[](Exponent order);
PolynomialMap& operator->();
std::string toString() const;
void deserialize(std::istream& stream);
void serialize(std::ostream& stream) const;
Real operator()(Real arg) const;
ScaleHandle operator()(Exponent first, Exponent last);
Polynomial operator*(Real rhs) const;
Polynomial operator/(Real rhs) const;
Polynomial operator^(Exponent rhs) const;
Polynomial operator*(const Polynomial& rhs) const;
Polynomial operator+(const Polynomial& rhs) const;
void setVariableName(const std::string& variableName);
private:
PolynomialMap poly_;
std::string variableName_;
};
}
std::ostream& operator<<(std::ostream& stream, const Calculus::Polynomial& poly);
std::istream& operator>>(std::istream& stream, Calculus::Polynomial& poly);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment