Commit bfcbc6f5 authored by Manon Eugénie Voisin--Leprince's avatar Manon Eugénie Voisin--Leprince
Browse files

HW2

parent eaab2f6e
cmake_minimum_required(VERSION 2.6)
set(CMAKE_CXX_STANDARD 14)
add_subdirectory(src)
# Instructions to compile the code
Compilation:
mkdir build
cd build
ccmake ../
make
# Instructions to run the program:
In the build/src directory:
In order to get the help:
./compute_series --help
The arguments that can be provided are the following :
--series_type : pi/arithmetic/integral_cos/integral_sin/integral_cube (Default pi)
--dumper_type : print or write (Default print)
--output : cout or filename (Default cout)
--freq : int, output frequency of the serie value. (Default 10)
--maxiter: int, maximal series iteration. (Default 1000)
--precision: number of digits to use (Default 5)
--delimiter: separator to use for produced files (Default " ")
--integral_bound_inf: bound inf of integral
--integral_bound_sup: bound sup of integral
In order to run the program, at least one argument has to be provided.
Examples:
./compute_series --series_type arithmetic --dumper_type write
./compute_series --series_type integral_sin --dumper_type write --integral_bound_inf 0 --integral_bound_sup pi/2
add_executable(compute_series
main.cc
series.cc
compute_pi.cc
compute_arithmetic.cc
print_series.cc
write_series.cc
riemann_integral.cc
)
#include "compute_arithmetic.hh"
/* -------------------------------------------------------------------------- */
ComputeArithmetic::ComputeArithmetic() {
this->func = [](UInt i) { return 1. * i; };
}
/* -------------------------------------------------------------------------- */
double ComputeArithmetic::getAnalyticPrediction() {
return 1. * this->current_term * (this->current_term + 1) / 2.;
}
#ifndef __COMPUTE_ALGEBRAIC_HH__
#define __COMPUTE_ALGEBRAIC_HH__
/* -------------------------------------------------------------------------- */
#include "series.hh"
/* -------------------------------------------------------------------------- */
class ComputeArithmetic : public Series {
public:
ComputeArithmetic();
double getAnalyticPrediction() override;
};
#endif /* __COMPUTE_ALGEBRAIC_HH__ */
#include "compute_pi.hh"
#include <cmath>
/* -------------------------------------------------------------------------- */
ComputePi::ComputePi() {
func = [](UInt i) { return 1. / (1. * i * i); };
}
/* -------------------------------------------------------------------------- */
double ComputePi::compute(UInt N) {
Series::compute(N);
return sqrt(6. * current_value);
}
/* -------------------------------------------------------------------------- */
double ComputePi::getAnalyticPrediction() { return M_PI; }
/* -------------------------------------------------------------------------- */
#ifndef __COMPUTE_PI_HH__
#define __COMPUTE_PI_HH__
/* -------------------------------------------------------------------------- */
#include "series.hh"
/* -------------------------------------------------------------------------- */
class ComputePi : public Series {
public:
ComputePi();
double compute(UInt N) override;
double getAnalyticPrediction() override;
};
#endif /* __COMPUTE_PI_HH__ */
#ifndef __DUMPER_SERIES_HH__
#define __DUMPER_SERIES_HH__
/* -------------------------------------------------------------------------- */
#include "series.hh"
#include <iomanip>
/* -------------------------------------------------------------------------- */
class DumperSeries {
public:
DumperSeries(Series &series) : series(series){};
virtual void dump(std::ostream &os) = 0;
void setPrecision(UInt precision) { this->precision = precision; }
void setMaxIter(UInt maxiter) { this->maxiter = maxiter; }
protected:
Series &series;
UInt precision = 4;
UInt maxiter = 100;
};
inline std::ostream &operator<<(std::ostream &os, DumperSeries &dumper) {
dumper.dump(os);
return os;
}
#endif /* __DUMPER_SERIES_HH__ */
/* -------------------------------------------------------------------------- */
#include <algorithm>
#include <cstdlib>
#include <fstream>
#include <iostream>
#include <map>
#include <sstream>
#include <vector>
#include <math.h>
#include <cmath>
/* -------------------------------------------------------------------------- */
#include "compute_arithmetic.hh"
#include "compute_pi.hh"
#include "riemann_integral.hh"
#include "main.hh"
#include "print_series.hh"
#include "write_series.hh"
/* -------------------------------------------------------------------------- */
//********************************
// Definition of the options
//********************************
using ArgMap = std::map<std::string, std::string>;
ArgMap defaults{{"series_type", "pi"}, {"dumper_type", "print"},
{"output", "cout"}, {"freq", "10"},
{"maxiter", "1000"}, {"precision", "5"},
{"delimiter", " "}};
ArgMap options{{"series_type", "pi/arithmetic/integral_cube/integral_cos/integral_sin"},
{"integral_bound_inf", "bound inf of integral"},
{"integral_bound_sup", "bound sup of integral"},
{"dumper_type", "print/write"},
{"output", "cout/filename"},
{"freq", "Frequency to output series value"},
{"maxiter", "Maximal series iteration"},
{"precision", "number of digits to use"},
{"delimiter", "separator to use for produced files"}};
void printUsage(std::string prog_name);
ArgMap parseArgv(int argc, char **argv);
/* ---------------------------------------------------------------------- */
int main(int argc, char **argv) {
//********************************
// Parsing
//********************************
auto params = parseArgv(argc, argv);
auto series_type = params["series_type"];
auto dumper_type = params["dumper_type"];
auto max_iter = atoi(params["maxiter"].c_str());
auto precision = atoi(params["precision"].c_str());
auto delimiter = params["delimiter"];
auto freq = atoi(params["freq"].c_str());
auto output = params["output"];
auto bound_inf = atof(params["integral_bound_inf"].c_str());
auto bound_sup = atof(params["integral_bound_sup"].c_str());
if (params["integral_bound_inf"] == "pi")
bound_inf = M_PI;
if (params["integral_bound_inf"] == "pi/2")
bound_inf = M_PI/2;
if (params["integral_bound_sup"] == "pi")
bound_sup = M_PI;
if (params["integral_bound_sup"] == "pi/2")
bound_sup = M_PI/2;
//********************************
// Series object creation
//********************************
std::unique_ptr<Series> series = nullptr;
if (series_type == "pi")
series = std::make_unique<ComputePi>();
else if (series_type == "arithmetic")
series = std::make_unique<ComputeArithmetic>();
else if (series_type == "integral_cube"){
std::function<double(double)> func = [](double i) { return i * i * i; };
series = std::make_unique<RiemannIntegral>(func, bound_inf, bound_sup);
}
else if (series_type == "integral_cos"){
std::function<double(double)> func = [](double i) { return cos(i); };
series = std::make_unique<RiemannIntegral>(func, bound_inf, bound_sup);
}
else if (series_type == "integral_sin"){
std::function<double(double)> func = [](double i) { return sin(i); };
series = std::make_unique<RiemannIntegral>(func, bound_inf, bound_sup);
}
else
printUsage(argv[0]);
// Dumper object creation
//********************************
std::unique_ptr<DumperSeries> dumper = nullptr;
if (dumper_type == "print")
dumper = std::make_unique<PrintSeries>(*series, freq);
else if (dumper_type == "write")
dumper = std::make_unique<WriteSeries>(*series, delimiter);
else
printUsage(argv[0]);
//********************************
// File object creation
//********************************
std::ostream *file = nullptr;
if (output != "cout")
file = new std::ofstream(output);
else
file = &std::cout;
//********************************
// Do the polymorphic job
//********************************
dumper->setPrecision(precision);
dumper->setMaxIter(max_iter);
*file << *dumper << std::endl;
if (output != "cout")
delete file;
return EXIT_SUCCESS;
}
/* ---------------------------------------------------------------------- */
// argument parsing system
/* ---------------------------------------------------------------------- */
void printUsage(std::string prog_name) {
std::cerr << "Usage: " << prog_name << " --option value\n" << std::endl;
for (auto &&key_val : options) {
std::cerr << "\t--" << key_val.first << ": " << key_val.second << std::endl;
}
std::cerr << std::endl;
throw std::runtime_error("Wrong Usage");
}
/* ---------------------------------------------------------------------- */
ArgMap parseArgv(int argc, char **argv) {
if (argc == 1)
printUsage(argv[0]);
auto params = defaults;
std::vector<std::string> vec_options;
for (int i = 1; i < argc; ++i) {
vec_options.push_back(argv[i]);
}
if (vec_options.size() % 2 != 0)
printUsage(argv[0]);
UInt noptions = argc / 2;
for (int i = 0; i < noptions; ++i) {
auto key = vec_options[2 * i];
auto value = vec_options[2 * i + 1];
key = key.substr(2);
if (key == "help")
printUsage(argv[0]);
if (options.count(key) == 0)
printUsage(argv[0]);
params[key] = value;
}
std::cout << "Selected options:" << std::endl;
std::for_each(params.begin(), params.end(), [](auto &v) {
std::cout << "\t" << v.first << ": " << v.second << "\n";
});
return params;
}
#ifndef __MAIN_HH__
#define __MAIN_HH__
typedef double Real;
typedef unsigned long UInt;
#endif /* __MAIN_HH__ */
#include <cmath>
#include <iostream>
/* -------------------------------------------------------------------------- */
#include "print_series.hh"
/* -------------------------------------------------------------------------- */
PrintSeries::PrintSeries(Series &series, UInt freq)
: DumperSeries(series), freq(freq) {}
/* -------------------------------------------------------------------------- */
void PrintSeries::dump(std::ostream &os) {
for (UInt i = 1; i * this->freq < this->maxiter; ++i) {
double res = series.compute(i * this->freq - 1);
double res2 = series.compute(i * this->freq);
os << std::setprecision(this->precision);
os << std::scientific;
os << i * this->freq << " " << res << " " << res2 - res;
if (!std::isnan(series.getAnalyticPrediction())) {
os << " " << std::abs(res2 - series.getAnalyticPrediction());
}
os << std::endl;
}
}
/* -------------------------------------------------------------------------- */
#include "dumper_series.hh"
/* -------------------------------------------------------------------------- */
class PrintSeries : public DumperSeries {
public:
PrintSeries(Series &series, UInt freq);
void dump(std::ostream &os) override;
private:
UInt freq = 10;
};
#include "riemann_integral.hh"
/* -------------------------------------------------------------------------- */
RiemannIntegral::RiemannIntegral(std::function<double(double)> func, double inf, double sup) {
this->func = func;
this->inf = inf;
this->sup = sup;
}
/* -------------------------------------------------------------------------- */
double RiemannIntegral::compute(UInt N){
this->current_value = 0.;
this->current_term = 0.;
for (UInt k = 0; k < N; ++k) {
++current_term;
double a = current_term * (sup-inf);
double b = N;
double new_current_term = inf + (a/b);
current_value += (sup-inf)/N * func(new_current_term);
}
return current_value;
}
#ifndef __RIEMANN_INTEGRAL_HH__
#define __RIEMANN_INTEGRAL_HH__
/* -------------------------------------------------------------------------- */
#include "series.hh"
/* -------------------------------------------------------------------------- */
class RiemannIntegral : public Series {
public:
RiemannIntegral(std::function<double(double)> func, double inf, double sup);
double compute(UInt N) override;
std::function<double(double)> func;
double inf;
double sup;
};
#endif /* __RIEMANN_INTEGRAL_HH__ */
#include "series.hh"
#include <cmath>
/* -------------------------------------------------------------------------- */
Series::Series() {}
/* -------------------------------------------------------------------------- */
double Series::compute(UInt N) {
if (current_term <= N)
N -= this->current_term;
else {
this->current_value = 0.;
this->current_term = 0;
}
for (UInt k = 0; k < N; ++k) {
++current_term;
current_value += func(current_term);
}
return current_value;
}
/* -------------------------------------------------------------------------- */
double Series::getAnalyticPrediction() { return nan(""); }
#ifndef __SERIES_HH__
#define __SERIES_HH__
/* -------------------------------------------------------------------------- */
#include "main.hh"
#include <functional>
#include <ostream>
#include <cmath>
/* -------------------------------------------------------------------------- */
class Series {
public:
Series();
virtual double compute(UInt N);
virtual double getAnalyticPrediction();
protected:
std::function<Real(UInt)> func;
UInt current_term = 0;
double current_value = 0.;
};
#endif /* __SERIES_HH__ */
#include <cmath>
#include <iostream>
/* -------------------------------------------------------------------------- */
#include "write_series.hh"
#include <algorithm>
#include <fstream>
/* -------------------------------------------------------------------------- */
WriteSeries::WriteSeries(Series &series, const std::string &delimiter)
: DumperSeries(series), delimiter(delimiter) {}
/* -------------------------------------------------------------------------- */
void WriteSeries::dump(std::ostream &os) {
os << std::setprecision(this->precision);
os << std::scientific;
for (UInt i = 1; i < this->maxiter; ++i) {
double res = series.compute(i);
os << i << this->delimiter;
os << res << this->delimiter;
if (!std::isnan(series.getAnalyticPrediction())) {
os << series.getAnalyticPrediction();
}
os << std::endl;
}
}
/* -------------------------------------------------------------------------- */
void WriteSeries::dump() {
std::string namefile = "iterations";
std::string extension;
if (extensions.count(delimiter) == 0)
extension = ".txt";
else
extension = extensions[delimiter];
std::ofstream outfile(namefile + extension);
this->dump(outfile);
}
/* -------------------------------------------------------------------------- */
#include "dumper_series.hh"
#include <map>
/* -------------------------------------------------------------------------- */
class WriteSeries : public DumperSeries {
public:
WriteSeries(Series &series, const std::string &delimiter);
void dump(std::ostream &os) override;
void dump();
private:
std::string delimiter = ",";
std::map<std::string, std::string> extensions{
{",", ".csv"}, {"|", ".psv"}, {" ", ".txt"}};
};
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment