Skip to content
Snippets Groups Projects
Commit f91c0303 authored by Sandipan Mohanty's avatar Sandipan Mohanty
Browse files

Add missing polymorphic directory

parent f614821f
No related branches found
No related tags found
No related merge requests found
Showing
with 649 additions and 0 deletions
cmake_minimum_required(VERSION 3.10)
project(polymorphic_w_virtual CXX)
set(CMAKE_CXX_EXTENSIONS OFF)
set (CMAKE_CXX_STANDARD 17)
set (CMAKE_CXX_STANDARD_REQUIRED ON)
set(Headers Point.hh Shape.hh Polygon.hh Triangle.hh Circle.hh)
add_executable(${PROJECT_NAME} Point.cc Triangle.cc Circle.cc main.cc ${Headers})
#include "Circle.hh"
constexpr double pi = 3.141592653589793;
Circle::Circle(double rad, const Point& p)
: r{ rad }
, c{ p }
{
}
std::string Circle::name() const
{
return "Circle";
}
double Circle::area() const
{
return pi * r * r;
}
double Circle::perimeter() const
{
return 2 * pi * r;
}
void Circle::rotate(double phi) { phi = 0; }
void Circle::translate(Point p)
{
c += p;
}
#ifndef Circle_HH
#define Circle_HH
#include "Point.hh"
#include "Shape.hh"
#include <string>
class Circle : public Shape {
public:
Circle() = default;
Circle(double rad, const Point& p);
Circle(const Circle& cir) = default;
Circle(Circle&& cir) = default;
Circle& operator=(const Circle& cir) = default;
Circle& operator=(Circle&& cir) = default;
void rotate(double phi) override;
void translate(Point p) override;
double area() const override;
double perimeter() const override;
inline double circumference() const { return perimeter(); }
std::string name() const override;
private:
double r{ 1.0 };
Point c{}; // Use default constructor of class Point to create c
};
#endif
#include "Point.hh"
#include <iostream>
Point::Point(double x, double y)
: X{ x }
, Y{ y }
{
}
Point& Point::operator+=(const Point& p)
{
X += p.X;
Y += p.Y;
return *this;
}
Point& Point::operator-=(const Point& p)
{
X -= p.X;
Y -= p.Y;
return *this;
}
Point Point::operator+(const Point& p) const
{
return { X + p.X, Y + p.Y };
}
Point Point::operator-(const Point& p) const
{
return { X - p.X, Y - p.Y };
}
double Point::operator*(const Point& p) const
{
return (X * p.X + Y * p.Y);
}
Point Point::operator*(double f) const
{
return { f * X, f * Y };
}
Point operator*(double f, const Point& p)
{
return { f * p.X, f * p.Y };
}
std::ostream& operator<<(std::ostream& os, const Point& p)
{
os << "(" << p.X << ", " << p.Y << ")";
return os;
}
#ifndef Point_HH
#define Point_HH
class ostream;
struct Point {
double X = 0, Y = 0;
Point() = default;
Point(const Point&) = default;
Point(Point&&) = default;
Point& operator=(const Point& p) = default;
Point& operator=(Point&& p) = default;
Point(double x, double y);
Point& operator+=(const Point& p);
Point& operator-=(const Point& p);
Point operator+(const Point& p) const;
Point operator-(const Point& p) const;
double operator*(const Point& p) const;
Point operator*(double f) const;
};
Point operator*(double f, const Point& p);
ostream& operator<<(ostream& os, const Point& p);
#endif
#ifndef Polygon_HH
#define Polygon_HH
#include <array>
#include <cmath>
#include "Shape.hh"
template <unsigned int NV>
class Polygon : public Shape {
static_assert(NV > 2, "Can't have polygon with less than 3 sides");
public:
Polygon() = default;
Polygon(const Polygon&) = default;
Polygon(Polygon&&) = default;
Polygon& operator=(const Polygon& pg) = default;
Polygon& operator=(Polygon&&) = default;
constexpr auto n_vertexes() const { return NV; }
std::string name() const override { return "Polygon<" +std::to_string(NV)+">"; }
double perimeter() const override {
double ans = 0;
for (size_t i = 1; i < vertex.size(); ++i) {
ans += sqrt((vertex[i] - vertex[i - 1]) * (vertex[i] - vertex[i - 1]));
}
ans += sqrt((vertex.front() - vertex.back()) * (vertex.front() - vertex.back()));
return ans;
}
void translate(Point p) override {
for (auto& pt : vertex)
pt += p;
}
void rotate(double phi) override{
Point center;
for (auto pt : vertex)
center += pt;
center = (1.0 / NV) * center;
double ct = cos(phi), st = sin(phi);
for (auto& pt : vertex) {
auto rel = pt - center;
pt = center + Point(ct * rel.X + st * rel.Y, -st * rel.X + ct * rel.Y);
}
}
protected:
std::array<Point, NV> vertex;
};
#endif
#ifndef Shape_HH
#define Shape_HH
#include "Point.hh"
#include <string>
class Shape {
public:
virtual ~Shape() = default;
virtual void rotate(double) = 0;
virtual void translate(Point) = 0;
virtual double area() const = 0;
virtual double perimeter() const = 0;
virtual std::string name() const = 0;
};
#endif
#include "Triangle.hh"
#include <cmath>
// A "static" function in a source file (not a static member function of a class)
// is meant to be visible only in the same translation unit, most often just that
// source file.
static inline double sqr(Point p) { return p * p; }
Triangle::Triangle(Point p1, Point p2, Point p3)
: Polygon<3>{}
{
vertex[0] = p1;
vertex[1] = p2;
vertex[2] = p3;
}
double Triangle::area() const
{
double s = 0.5 * perimeter();
double a = sqrt(sqr(vertex[0] - vertex[1]));
double b = sqrt(sqr(vertex[0] - vertex[2]));
double c = sqrt(sqr(vertex[1] - vertex[2]));
return sqrt(s * (s - a) * (s - b) * (s - c));
}
#include "Polygon.hh"
#include <string>
class Triangle : public Polygon<3> {
public:
Triangle() = default;
Triangle(Point p1, Point p2, Point p3);
Triangle(const Triangle&) = default;
Triangle(Triangle&&) = default;
Triangle& operator=(const Triangle&) = default;
Triangle& operator=(Triangle&&) = default;
double area() const override;
std::string name() const override { return "Triangle"; }
};
#include "Circle.hh"
#include "Triangle.hh"
#include <chrono>
#include <random>
#include <iostream>
#include <vector>
#include <memory>
using element_type = std::unique_ptr<Shape>;
constexpr auto N = 100000ul;
std::mt19937_64 engine;
std::discrete_distribution sel{ 0.5, 0.5 };
std::exponential_distribution length{ 1.0 };
auto name(const std::vector<element_type>& v, size_t i)
{
return v[i]->name();
}
auto area(const std::vector<element_type>& v, size_t i)
{
return v[i]->area();
}
void construct_objects(std::vector<element_type>& v)
{
for (auto i = 0ul; i < N; ++i) {
auto isel = sel(engine);
switch (isel) {
case 0: {
auto radius = length(engine);
auto centrepos = Point(length(engine), length(engine));
v.emplace_back(std::make_unique<Circle>(radius, centrepos));
break;
}
case 1: {
auto v1 = Point(length(engine), length(engine));
auto v2 = Point(length(engine), length(engine));
auto v3 = Point(length(engine), length(engine));
v.emplace_back(std::make_unique<Triangle>(v1, v2, v3));
break;
}
};
}
}
void calc_area_all(const std::vector<element_type>& v)
{
auto max_loc = 0ul;
auto max_area = 0.;
for (size_t i = 0; i < v.size(); ++i) {
auto ar = area(v, i);
if (i < 5) {
std::cout << i << ": " << name(v, i) << " with area "
<< ar << "\n";
}
if (ar > max_area) {
max_loc = i;
}
}
std::cout << "Largest object: \n";
auto nm = name(v, max_loc);
auto ar = area(v, max_loc);
std::cout << "Name : " << nm << ", area = " << ar << "\n";
}
int main()
{
std::vector<element_type> shapes;
shapes.reserve(N);
auto t0 = std::chrono::steady_clock::now();
construct_objects(shapes);
auto t1 = std::chrono::steady_clock::now();
calc_area_all(shapes);
auto t2 = std::chrono::steady_clock::now();
std::cout << "Object creation time for " << N << " objects, "
<< std::chrono::duration<double>(t1 - t0).count() << "\n"
<< "Area evaluation time for " << N << " objects, "
<< std::chrono::duration<double>(t2 - t1).count() << "\n";
}
cmake_minimum_required(VERSION 3.10)
project(polymorphic_w_any CXX)
set(CMAKE_CXX_EXTENSIONS OFF)
set (CMAKE_CXX_STANDARD 17)
set (CMAKE_CXX_STANDARD_REQUIRED ON)
set(Headers Point.hh Polygon.hh Triangle.hh Circle.hh)
add_executable(${PROJECT_NAME} Point.cc Triangle.cc Circle.cc main.cc ${Headers})
#include "Circle.hh"
constexpr double pi = 3.141592653589793;
Circle::Circle(double rad, const Point& p)
: r{ rad }
, c{ p }
{
}
double Circle::area() const
{
return pi * r * r;
}
double Circle::perimeter() const
{
return 2 * pi * r;
}
void Circle::rotate(double phi) { phi = 0; }
void Circle::translate(Point p)
{
c += p;
}
#ifndef Circle_HH
#define Circle_HH
#include "Point.hh"
#include <string>
class Circle {
public:
Circle() = default;
Circle(double rad, const Point& p);
Circle(const Circle& cir) = default;
Circle(Circle&& cir) = default;
Circle& operator=(const Circle& cir) = default;
Circle& operator=(Circle&& cir) = default;
std::string name() const { return "Circle"; }
void rotate(double phi);
void translate(Point p);
double area() const;
double perimeter() const;
inline double circumference() const { return perimeter(); }
private:
double r{ 1.0 };
Point c{}; // Use default constructor of class Point to create c
};
#endif
#include "Point.hh"
#include <iostream>
Point::Point(double x, double y)
: X{ x }
, Y{ y }
{
}
Point& Point::operator+=(const Point& p)
{
X += p.X;
Y += p.Y;
return *this;
}
Point& Point::operator-=(const Point& p)
{
X -= p.X;
Y -= p.Y;
return *this;
}
Point Point::operator+(const Point& p) const
{
return { X + p.X, Y + p.Y };
}
Point Point::operator-(const Point& p) const
{
return { X - p.X, Y - p.Y };
}
double Point::operator*(const Point& p) const
{
return (X * p.X + Y * p.Y);
}
Point Point::operator*(double f) const
{
return { f * X, f * Y };
}
Point operator*(double f, const Point& p)
{
return { f * p.X, f * p.Y };
}
std::ostream& operator<<(std::ostream& os, const Point& p)
{
os << "(" << p.X << ", " << p.Y << ")";
return os;
}
#ifndef Point_HH
#define Point_HH
class ostream;
struct Point {
double X = 0, Y = 0;
Point() = default;
Point(const Point&) = default;
Point(Point&&) = default;
Point& operator=(const Point& p) = default;
Point& operator=(Point&& p) = default;
Point(double x, double y);
Point& operator+=(const Point& p);
Point& operator-=(const Point& p);
Point operator+(const Point& p) const;
Point operator-(const Point& p) const;
double operator*(const Point& p) const;
Point operator*(double f) const;
};
Point operator*(double f, const Point& p);
ostream& operator<<(ostream& os, const Point& p);
#endif
#ifndef Polygon_HH
#define Polygon_HH
#include "Point.hh"
#include <array>
#include <cmath>
#include <string>
template <unsigned int NV>
class Polygon {
static_assert(NV > 2, "Can't have polygon with less than 3 sides");
public:
Polygon() = default;
Polygon(const Polygon&) = default;
Polygon(Polygon&&) = default;
Polygon& operator=(const Polygon& pg) = default;
Polygon& operator=(Polygon&&) = default;
constexpr auto n_vertexes() const { return NV; }
std::string name() const { return "Polygon<" + std::to_string(NV) + ">"; }
double perimeter() const
{
double ans = 0;
for (size_t i = 1; i < vertex.size(); ++i) {
ans += sqrt((vertex[i] - vertex[i - 1]) * (vertex[i] - vertex[i - 1]));
}
ans += sqrt((vertex.front() - vertex.back()) * (vertex.front() - vertex.back()));
return ans;
}
void translate(Point p)
{
for (auto& pt : vertex)
pt += p;
}
void rotate(double phi)
{
Point center;
for (auto pt : vertex)
center += pt;
center = (1.0 / NV) * center;
double ct = cos(phi), st = sin(phi);
for (auto& pt : vertex) {
auto rel = pt - center;
pt = center + Point(ct * rel.X + st * rel.Y, -st * rel.X + ct * rel.Y);
}
}
protected:
std::array<Point, NV> vertex;
};
#endif
#include "Triangle.hh"
#include <cmath>
// A "static" function in a source file (not a static member function of a class)
// is meant to be visible only in the same translation unit, most often just that
// source file.
static inline double sqr(Point p) { return p * p; }
Triangle::Triangle(Point p1, Point p2, Point p3)
{
vertex[0] = p1;
vertex[1] = p2;
vertex[2] = p3;
}
double Triangle::area() const
{
double s = 0.5 * perimeter();
double a = sqrt(sqr(vertex[0] - vertex[1]));
double b = sqrt(sqr(vertex[0] - vertex[2]));
double c = sqrt(sqr(vertex[1] - vertex[2]));
return sqrt(s * (s - a) * (s - b) * (s - c));
}
#include "Polygon.hh"
class Triangle : public Polygon<3> {
public:
using Polygon<3>::Polygon;
using Polygon<3>::operator=;
Triangle(Point p1, Point p2, Point p3);
double area() const;
};
#include "Circle.hh"
#include "Triangle.hh"
#include <chrono>
#include <random>
#include <iostream>
#include <vector>
#include <any>
constexpr auto N = 100000ul;
std::mt19937_64 engine;
std::discrete_distribution sel{ 0.5, 0.5 };
std::exponential_distribution length{ 1.0 };
using element_type = std::any;
auto name(const std::vector<element_type>& v, size_t i)
{
if (v[i].type() == typeid(Triangle)) {
return std::any_cast<Triangle>(v[i]).name();
} else {
return std::any_cast<Circle>(v[i]).name();
}
}
auto area(const std::vector<element_type>& v, size_t i)
{
if (v[i].type() == typeid(Triangle)) {
return std::any_cast<Triangle>(v[i]).area();
} else {
return std::any_cast<Circle>(v[i]).area();
}
}
void construct_objects(std::vector<element_type>& v)
{
for (auto i = 0ul; i < N; ++i) {
auto isel = sel(engine);
switch (isel) {
case 0: {
auto radius = length(engine);
auto centrepos = Point(length(engine), length(engine));
v.emplace_back(std::in_place_type_t<Circle>{}, radius, centrepos);
break;
}
case 1: {
auto v1 = Point(length(engine), length(engine));
auto v2 = Point(length(engine), length(engine));
auto v3 = Point(length(engine), length(engine));
v.emplace_back(std::in_place_type_t<Triangle>{}, v1, v2, v3);
break;
}
};
}
}
void calc_area_all(const std::vector<element_type>& v)
{
auto max_loc = 0ul;
auto max_area = 0.;
for (size_t i = 0; i < v.size(); ++i) {
auto ar = area(v, i);
if (i < 5) {
std::cout << i << ": " << name(v, i) << " with area "
<< ar << "\n";
}
if (ar > max_area) {
max_loc = i;
}
}
std::cout << "Largest object: \n";
auto nm = name(v, max_loc);
auto ar = area(v, max_loc);
std::cout << "Name : " << nm << ", area = " << ar << "\n";
}
int main()
{
std::vector<element_type> shapes;
shapes.reserve(N);
auto t0 = std::chrono::steady_clock::now();
construct_objects(shapes);
auto t1 = std::chrono::steady_clock::now();
calc_area_all(shapes);
auto t2 = std::chrono::steady_clock::now();
std::cout << "Object creation time for " << N << " objects, "
<< std::chrono::duration<double>(t1 - t0).count() << "\n"
<< "Area evaluation time for " << N << " objects, "
<< std::chrono::duration<double>(t2 - t1).count() << "\n";
}
cmake_minimum_required(VERSION 3.10)
project(polymorphic_w_variant CXX)
set(CMAKE_CXX_EXTENSIONS OFF)
set (CMAKE_CXX_STANDARD 17)
set (CMAKE_CXX_STANDARD_REQUIRED ON)
set(Headers Point.hh Polygon.hh Triangle.hh Circle.hh)
add_executable(${PROJECT_NAME} Point.cc Triangle.cc Circle.cc main.cc ${Headers})
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment