Skip to content

Instantly share code, notes, and snippets.

@abar193
Created March 4, 2023 15:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save abar193/14479b8683cf46fed2c0a1958e6e1d14 to your computer and use it in GitHub Desktop.
Save abar193/14479b8683cf46fed2c0a1958e6e1d14 to your computer and use it in GitHub Desktop.
#include <iostream>
#include <cstdio>
#include <cmath>
typedef float f32;
typedef unsigned int u32;
const float Pi32 = 3.14159265;
const int SHAPES = 100500;
const int ITERATIONS = 1000;
// clean
class shape_base
{
public:
shape_base() {}
virtual f32 Area() = 0;
};
class square : public shape_base
{
public:
square(f32 SideInit) : Side(SideInit) {}
virtual f32 Area() {return Side*Side;}
private:
f32 Side;
};
class rectangle : public shape_base
{
public:
rectangle(f32 WidthInit, f32 HeightInit) : Width(WidthInit), Height(HeightInit) {}
virtual f32 Area() {return Width*Height;}
private:
f32 Width, Height;
};
class triangle : public shape_base
{
public:
triangle(f32 sideA, f32 sideB, f32 sideC) : sideA(sideA), sideB(sideB), sideC(sideC) {}
virtual f32 Area() {
f32 p = (sideA + sideB + sideC) / 2;
return sqrt(p * (p - sideA) * (p - sideB) * (p - sideC));
}
private:
f32 sideA, sideB, sideC;
};
class circle : public shape_base
{
public:
circle(f32 RadiusInit) : Radius(RadiusInit) {}
virtual f32 Area() {return Pi32*Radius*Radius;}
private:
f32 Radius;
};
f32 TotalAreaVTBL(int ShapeCount, shape_base **Shapes)
{
f32 Accum = 0.0f;
for(int ShapeIndex = 0; ShapeIndex < ShapeCount; ++ShapeIndex)
{
Accum += Shapes[ShapeIndex]->Area();
}
return Accum;
}
shape_base** generateShapes(int count) {
shape_base** base = static_cast<shape_base **>(malloc(count * sizeof(shape_base *)));
for(int i = 0; i < count; i++) {
int shape = rand() % 3;
if(shape == 0) {
base[i] = new square(rand());
} else if(shape == 1) {
base[i] = new rectangle(rand(), rand());
} else if(shape == 2) {
base[i] = new triangle(rand(), rand(), rand());
}
}
return base;
}
void destroyShapes(int size, shape_base** base) {
for(int i = 0; i < size; i++) {
free(base[i]);
}
free(base);
}
// switch
enum shape_type : u32
{
Shape_Square,
Shape_Rectangle,
Shape_Triangle,
Shape_Circle,
Shape_Count,
};
struct shape_union
{
shape_type Type;
f32 Width;
f32 Height;
f32 Side;
};
f32 GetAreaSwitch(shape_union Shape)
{
f32 Result = 0.0f;
switch(Shape.Type)
{
case Shape_Square: {Result = Shape.Width*Shape.Width;} break;
case Shape_Rectangle: {Result = Shape.Width*Shape.Height;} break;
case Shape_Triangle: {
f32 p = (Shape.Width + Shape.Height + Shape.Side) / 2;
Result = sqrt(p * (p-Shape.Width) * (p - Shape.Height) * (p - Shape.Side));
} break;
case Shape_Circle: {Result = Pi32*Shape.Width*Shape.Width;} break;
case Shape_Count: {} break;
}
return Result;
}
f32 TotalAreaSwitch(u32 ShapeCount, shape_union *Shapes)
{
f32 Accum = 0.0f;
for(u32 ShapeIndex = 0; ShapeIndex < ShapeCount; ++ShapeIndex)
{
Accum += GetAreaSwitch(Shapes[ShapeIndex]);
}
return Accum;
}
shape_union* generateShapesSwitch(int count) {
shape_union* base = static_cast<shape_union *>(malloc(count * sizeof(shape_union)));
for(int i = 0; i < count; i++) {
int shape = rand() % 3;
if(shape == 0) {
base[i].Type = Shape_Square;
base[i].Width = rand();
} else if(shape == 1) {
base[i].Type = Shape_Rectangle;
base[i].Width = rand();
base[i].Height = rand();
} else if(shape == 2) {
base[i].Type = Shape_Triangle;
base[i].Width = rand();
base[i].Height = rand();
base[i].Side = rand();
}
}
return base;
}
void destroyShapesSwitch(int size, shape_union* base) {
free(base);
}
// table, union or whatever
f32 const CTable[Shape_Count] = {1.0f, 1.0f, 0.5f, Pi32};
f32 GetAreaUnion(shape_union Shape)
{
if(Shape.Type == Shape_Triangle) {
f32 p = (Shape.Width + Shape.Height + Shape.Side) / 2;
return sqrt(p * (p - Shape.Width) * (p - Shape.Height) * (p - Shape.Side));
}
return CTable[Shape.Type]*Shape.Width*Shape.Height;
}
f32 TotalAreaUnion(u32 ShapeCount, shape_union *Shapes)
{
f32 Accum = 0.0f;
for(u32 ShapeIndex = 0; ShapeIndex < ShapeCount; ++ShapeIndex)
{
Accum += GetAreaUnion(Shapes[ShapeIndex]);
}
return Accum;
}
// display
double calcAvg(double arr[]) {
double s = 0;
for(int i = 0; i < ITERATIONS; i++) {
s += arr[i] / ITERATIONS;
}
return s;
}
int main() {
std::cout << "Hello, World!" << std::endl;
double timeClean[ITERATIONS], timeSwitch[ITERATIONS], timeUnion[ITERATIONS];
clock_t start, end;
shape_base** base = generateShapes(SHAPES);
shape_union* baseSwitch = generateShapesSwitch(SHAPES);
for(int i = 0; i < ITERATIONS; i++) {
start = clock();
/*std::cout << */TotalAreaVTBL(SHAPES, base);// << std::endl;
end = clock();
double time_taken = double(end - start) / double(CLOCKS_PER_SEC);
timeClean[i] = time_taken;
}
for(int i = 0; i < ITERATIONS; i++) {
start = clock();
TotalAreaUnion(SHAPES, baseSwitch);// << std::endl;
end = clock();
double time_taken = double(end - start) / double(CLOCKS_PER_SEC);
timeUnion[i] = time_taken;
}
for(int i = 0; i < ITERATIONS; i++) {
start = clock();
TotalAreaSwitch(SHAPES, baseSwitch);// << std::endl;
end = clock();
double time_taken = double(end - start) / double(CLOCKS_PER_SEC);
timeSwitch[i] = time_taken;
}
double cleanTime = calcAvg(timeClean);
double switchTime = calcAvg(timeSwitch);
double unionTime = calcAvg(timeUnion);
printf("Clean approach: %.5f\n", cleanTime);
printf("Switch approach: %.5f (%.5f)\n", switchTime, cleanTime / switchTime);
printf("Union approach: %.5f (%.5f)\n", unionTime, cleanTime / unionTime);
destroyShapes(SHAPES, base);
destroyShapesSwitch(SHAPES, baseSwitch);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment