Big Three Expression: crtlsvalidHeapPointer(block) - c++

I keep getting an error of "Expression: crtlsvalidHeapPointer(block)"
When I run the program, it executes all the way to the end but it triggers this error.
I believe I created big three expression. making deep copying and deleting previous address.
Is there I am missing point of creating big three expression?
#include <iostream>
using namespace std;
//between 0 and 255
class color {
int *red, *green, *blue;
public:
color() {
red = new int; green = new int; blue = new int;
*red = 0; *green = 0; *blue = 0; }
color(int r, int g, int b) {
if (r < 0 || r>255)
r = 0;
if (g < 0 || g>255)
g = 0;
if (b < 0 || b>255)
b = 0;
red = new int;
green = new int;
blue = new int;
*red = r;
*green = g;
*blue = b;
}
color(const color &rhs) :red(new int), green(new int), blue(new int) { *this = rhs; }
color & operator=(const color &rhs) {
if (this == &rhs)
return *this;
delete red;
delete green;
delete blue;
red = rhs.red;
green = rhs.green;
blue = rhs.blue;
return *this;
}
~color() {
delete red;
delete green;
delete blue;
};
color & operator +(const color & rhs) {
int r, g, b;
r = *red + *rhs.red;
if (r > 255)
r = 255;
g = *green + *rhs.green;
if (g > 255)
g = 255;
b = *blue + *rhs.blue;
if (b > 255)
b = 255;
color *thecolor = new color(r, g, b);
return *thecolor;
}
color & operator /(const color &rhs) {
int r, g, b;
if (*red == 0 || *rhs.red == 0)
r = 0;
else
r = *red / (*rhs.red);
if (*green == 0 || *rhs.green == 0)
g = 0;
else
g = *green / (*rhs.green);
if (*blue == 0 || *rhs.blue == 0)
b = 0;
else
b = *blue / (*rhs.blue);
color *newcolor = new color(r, g, b);
return *newcolor;
}
int getred() const { return *red; }
int getgreen()const { return *green; }
int getblue() const { return *blue; }
void set_red(int r) { *red = r; }
void set_green(int g) { *green = g; }
void set_blue(int b) { *blue = b; }
friend ostream &operator <<(ostream &out, const color &c) {
out << "(" << c.getred() << ", " << c.getgreen() << ", " << c.getblue() << ")";
return out;
}
};
int main() {
color c1(100, 150, 220);
color c2(23, 100, 76);
color c3(c1);
color c4 = c2;
//testing << operator
cout << "c1: " << c1 << endl;
cout << "c2: " << c2 << endl;
cout << "c3: " << c3 << endl;
cout << "c4: " << c4 << endl;
cout << "testing + and / operators" << endl;
cout << "c1+c2: " << c1 + c2 << endl;
cout << "c1/c2: " << c1 / c2 << endl;
return 0;
}

Related

Why I can't access data from array of objects?

I have a problem with my code, every time I use my arrays (vTab or eTab) of an object inside of cube:3D_obj it returns me pointer ID or nan. Well just for context here's the whole code, but those arrays are only the problem because the code is running fine.
For debugging purposes, I wrote cout's in some places. Also, I tried to init vTab[] as new vertice[8], but the same results.
I came up with one problem, that I might have to init verticle object outside of functions but i don't know actually how to handle it.
If you need to know this project have to represent simple 3D figures as data with classes/objects
Two vertices make an edge, edges make figures, etc.
IDE: I use Visual Studio on Windows
#define pi 3.14159265359
#define eps 0.0001
#include <iostream>
#include <math.h>
using namespace std;
double aprox(double x, double y) {
return round(10000 * x) / 10000;
}
class vertice {
double x;
double y;
double z;
friend ostream& operator<< (ostream& c, vertice& orig);
public:
vertice() {//init funciton
x = y = z = 0;
}
vertice(double ix, double iy, double iz) {//init function
x = ix;
y = iy;
z = iz;
}
vertice& operator- (vertice& orig) {
vertice temp = *this;
temp.x -= orig.x;
temp.y -= orig.y;
temp.z -= orig.z;
return temp;
}
vertice& operator+ (vertice& orig) {
vertice temp = *this;
temp.x += orig.x;
temp.y += orig.y;
temp.z += orig.z;
return temp;
}
void position(double ix, double iy, double iz) { //change the position of the vertice
x = ix;
y = iy;
z = iz;
}
void position(double ix) {
x = ix;
}
void rotate(double ax, double ay, double az, vertice anchorPoint = vertice(0, 0, 0)) { //rotate in 3D (angle) axis using anchor point
vertice tempVertice = *this - anchorPoint;
double cosX = cos(ax * pi / 180), cosY = cos(ay * pi / 180), cosZ = cos(az * pi / 180), sinX = sin(ax * pi / 180), sinY = sin(ay * pi / 180), sinZ = sin(az * pi / 180);
//rotate X
y = aprox(tempVertice.y * cosX - tempVertice.z * sinX, eps);
z = aprox(tempVertice.z * cosX + tempVertice.y * sinX, eps);
tempVertice = *this;
//rotate Y
x = aprox(tempVertice.x * cosY - tempVertice.z * sinY, eps);
z = aprox(tempVertice.z * cosY + tempVertice.x * sinY, eps);
tempVertice = *this;
//rotate Z
x = aprox(tempVertice.x * cosZ - tempVertice.y * sinZ, eps);
y = aprox(tempVertice.y * cosZ + tempVertice.x * sinZ, eps);
//tempVertice = *this;
*this = *this + anchorPoint;
}
//~vertice() {};
};
ostream& operator<< (ostream& c, vertice& orig) { //using << operator to stream data from vertice
cout << "x= " << orig.x << " | y= " << orig.y << " | z= " << orig.z;
return c;
}
class edge {
friend ostream& operator<< (ostream& c, edge& orig);
public:
vertice* v1;
vertice* v2;
edge() {
v1 = new vertice();
v2 = new vertice();
}
edge(vertice iv1, vertice iv2) {
v1 = &iv1;
v2 = &iv2;
}
};
ostream& operator<< (ostream& c, edge& orig) { //printing edges as two vertex
cout << "Edge: \n* " << *orig.v1 << "\n* " << *orig.v2 << endl;
return c;
}
class obj_3D {
vertice position;
vertice anchorPoint;
//material type; //not using
public:
void Draw() {}
//~obj_3D() {};
};
class cube : public obj_3D {
double a;
edge eTab[12];
vertice vTab[8];
public:
cube(double ia) { //creating vertices, edges according to object properaties.
a = ia;
double Ph = aprox(asin(sqrt(2) / 2), eps), Alph = aprox(asin(3 * sqrt(2) / 3), eps);
double TPh = 0, TAlph = 0;
double R = a * sqrt(2) / 2;
for (int i = 0; i < 8; i++) { //initializing vertices
vTab[i] = vertice();
vTab[i].position(R);
vTab[i].rotate(Ph + TPh, Alph+ TAlph, 0);
if (i == 3) {
TPh = 0;
TAlph = 180;
}
else TPh += 90;
cout << vTab[i] << endl; //for debuging purp.
}
for (int i = 0; i < 10; i++) { //initializing edges
if (i < 4) {
eTab[i] = edge(vTab[i], vTab[(i + 1) % 4]);
eTab[i + 4] = edge(vTab[i], vTab[i + 4]);
cout << eTab[i] << eTab[i + 4] << endl;
}
else {
eTab[i + 4] = edge(vTab[i], vTab[((i + 1) % 4) + 4]);
cout << eTab[i + 4] << endl;
}
}
}
void print() {
cout << "Cube: \n";
for (int i = 0; i < 12; i++) {
edge temp = eTab[i];
cout << i+1 << ". " << temp << endl;
}
}
};
int main() {
/*vertice a = vertice();
vertice b = vertice(4.2, 1.3, 2.2);
cout << b;
b = b + a;
b = b - a;
b.rotate(90, 90, 90);
cout << endl << a;
edge e1 = edge(a, b);
cout << endl << e1;*/
//vertice b = vertice();
//cout << b;
cube c1 = cube(4);
//c1.print();
}
I really will appreciate your help because I really am stuck here and don't know what to do...

BVH Tree Construction - Compiling gives Random mistakes

Much thanks for the help in additionally.
I'm trying to build a BVH Tree with Surface Area Heuristic, but everytime I compile my code it gives me random errors like:
"Access violation reading location"
"Run-Time Check Failure #2 - Stack around the variable 'x' was
corrupted."
"Stack overflow "
The errors happen in the BVH::buildSAH() function.
And I have tried to find a solution for the whole day, meaningless. Could it be something from the std::partition function or from sending variables with pointers to a recursion?
I'm reading from the book "Physically Based Rendering: From Theory to Implementation
By Matt Pharr, Greg Humphreys"
It works for 2 primitives in the area, but thats trivial...
If you would like to clone: https://github.com/vkaytsanov/MortonCode-BVH-KD
My BVH.hpp:
#include <vector>
#include <cassert>
#include <algorithm>
#include "memory.hpp"
#include "Screen.hpp"
#include "Point3D.hpp"
#include "BoundBox.hpp"
#pragma once
enum Axis{
X, Y, Z
};
struct MortonPrimitive{
int primitiveIndex;
uint32_t mortonCode;
};
struct BVHPrimitiveInfo {
BVHPrimitiveInfo() {}
BVHPrimitiveInfo(int primitiveNumber, const BoundBox& box) : primitiveNumber(primitiveNumber), box(box),
centroid(Point3D(box.pMin.x* 0.5f + box.pMax.x * 0.5f, box.pMin.y* 0.5f + box.pMax.y * 0.5f, box.pMin.z* 0.5f + box.pMax.z * 0.5f)) {}
int primitiveNumber;
BoundBox box;
Point3D centroid;
};
struct BVHNode {
void InitLeaf(int first, int n, const BoundBox& b) {
firstPrimOffset = first;
nPrimitives = n;
box = b;
children[0] = children[1] = nullptr;
}
void InitInterior(int axis, BVHNode* c0, BVHNode* c1) {
assert(c0 != NULL || c1 != NULL);
children[0] = c0;
children[1] = c1;
this->box = Union(c0->box, c1->box);
splitAxis = axis;
nPrimitives = 0;
}
BoundBox box;
BVHNode* children[2];
int splitAxis, firstPrimOffset, nPrimitives;
};
struct LinearBVHNode {
BoundBox bounds;
union {
int primitivesOffset; // leaf
int secondChildOffset; // interior
};
uint16_t nPrimitives; // 0 -> interior node
uint8_t axis; // interior node: xyz
uint8_t pad[1]; // ensure 32 byte total size
};
struct BVHLittleTree {
int startIndex;
int numPrimitives;
BVHNode* nodes;
};
struct BVH {
BVH(std::vector<std::shared_ptr<Primitive>> p) : primitives(std::move(p)) {
std::vector<BVHPrimitiveInfo> BVHPrimitives;
BVHPrimitives.reserve(primitives.size());
for (int i = 0; i < primitives.size(); i++) {
BVHPrimitives.push_back({ i, primitives[i]->box });
}
MemoryArena arena(1024 * 1024);
int totalNodes = 0;
std::vector<std::shared_ptr<Primitive>> orderedPrimitives;
orderedPrimitives.reserve(primitives.size());
BVHNode* root;
root = HLBVHBuild(arena, BVHPrimitives, &totalNodes, orderedPrimitives);
primitives.swap(orderedPrimitives);
BVHPrimitives.resize(0);
printf("BVH created with %d nodes for %d "
"primitives (%.4f MB), arena allocated %.2f MB\n",
(int)totalNodes, (int)primitives.size(),
float(totalNodes * sizeof(LinearBVHNode)) /
(1024.f * 1024.f),
float(arena.TotalAllocated()) /
(1024.f * 1024.f));
assert(root != NULL);
nodes = AllocAligned<LinearBVHNode>(totalNodes);
int offset = 0;
flattenBVHTree(root, &offset);
}
~BVH() { FreeAligned(nodes); }
BVHNode* build(std::vector<MortonPrimitive>&, std::vector<Primitive>&);
BVHNode* HLBVHBuild(MemoryArena& arena, const std::vector<BVHPrimitiveInfo>& BVHPrimitives, int* totalNodes, std::vector<std::shared_ptr<Primitive>>& orderedPrims);
BVHNode* emit(BVHNode*& nodes, const std::vector<BVHPrimitiveInfo>& BVHPrimitives, MortonPrimitive* mortonPrimitives, std::vector<std::shared_ptr<Primitive>>&, int, int*, int*, int);
BVHNode* buildSAH(MemoryArena& arena, std::vector<BVHNode*>& treeRoots, int start, int end, int* total) const;
int flattenBVHTree(BVHNode*, int*);
std::vector<std::shared_ptr<Primitive>> primitives;
LinearBVHNode* nodes = nullptr;
int maxPrimsInNode = 1;
};
inline uint32_t LeftShift3(uint32_t x) {
if (x == (1 << 10)) --x;
x = (x | (x << 16)) & 0b00000011000000000000000011111111;
x = (x | (x << 8)) & 0b00000011000000001111000000001111;
x = (x | (x << 4)) & 0b00000011000011000011000011000011;
x = (x | (x << 2)) & 0b00001001001001001001001001001001;
return x;
}
uint32_t EncodeMorton3(const Point3D& p) {
return (LeftShift3(p.z) << 2) |
(LeftShift3(p.y) << 1) |
(LeftShift3(p.x) << 0);
}
short bitValue(uint32_t& number, uint32_t& mask) {
return number & mask ? 1 : 0;
}
static void radixSort(std::vector<MortonPrimitive>* v)
{
std::vector<MortonPrimitive> tempVector(v->size());
const int bitsPerPass = 6;
const int nBits = 30;
static_assert((nBits % bitsPerPass) == 0,
"Radix sort bitsPerPass must evenly divide nBits");
const int nPasses = nBits / bitsPerPass;
for (int pass = 0; pass < nPasses; ++pass) {
// Perform one pass of radix sort, sorting _bitsPerPass_ bits
int lowBit = pass * bitsPerPass;
// Set in and out vector pointers for radix sort pass
std::vector<MortonPrimitive>& in = (pass & 1) ? tempVector : *v;
std::vector<MortonPrimitive>& out = (pass & 1) ? *v : tempVector;
// Count number of zero bits in array for current radix sort bit
const int nBuckets = 1 << bitsPerPass;
int bucketCount[nBuckets] = { 0 };
const int bitMask = (1 << bitsPerPass) - 1;
for (const MortonPrimitive& mp : in) {
int bucket = (mp.mortonCode >> lowBit) & bitMask;
++bucketCount[bucket];
}
// Compute starting index in output array for each bucket
int outIndex[nBuckets];
outIndex[0] = 0;
for (int i = 1; i < nBuckets; ++i)
outIndex[i] = outIndex[i - 1] + bucketCount[i - 1];
// Store sorted values in output array
for (const MortonPrimitive& mp : in) {
int bucket = (mp.mortonCode >> lowBit) & bitMask;
out[outIndex[bucket]++] = mp;
}
}
// Copy final result from _tempVector_, if needed
if (nPasses & 1) std::swap(*v, tempVector);
}
//BVHNode* BVH::build(std::vector<MortonPrimitive>& mortonPrimitives, std::vector<Primitive>& prims) {
//
//
//}
struct BucketInfo {
int count = 0;
BoundBox bounds;
};
BVHNode* BVH::HLBVHBuild(MemoryArena& arena, const std::vector<BVHPrimitiveInfo>& BVHPrimitives, int* totalNodes, std::vector<std::shared_ptr<Primitive>>& orderedPrims) {
BoundBox box;
for (const BVHPrimitiveInfo& pi : BVHPrimitives) {
box = box.Union(box, pi.centroid); // maybe it should be UNION #TODO
}
std::vector<MortonPrimitive> mortonPrims(BVHPrimitives.size());
for (int i = 0; i < BVHPrimitives.size(); i++) {
const int mortonBits = 10;
const int mortonScale = 1 << mortonBits;
mortonPrims[i].primitiveIndex = BVHPrimitives[i].primitiveNumber;
Point3D p = box.offset(BVHPrimitives[i].centroid);
p.x = p.x * mortonScale;
p.y = p.y * mortonScale;
p.z = p.z * mortonScale;
mortonPrims[i].mortonCode = EncodeMorton3(p);
}
radixSort(&mortonPrims);
//for (MortonPrimitive mp : mortonPrims) {
// std::cout << mp.primitiveIndex << " " << mp.mortonCode << std::endl;
//}
std::vector<BVHLittleTree> treesToBuild;
uint32_t mask = 0b00111111111111000000000000000000; // first 12 bits describe the position of the primitive
for (int start = 0, end = 1; end <= (int)mortonPrims.size(); end++) {
if (end == mortonPrims.size() || ((mortonPrims[start].mortonCode & mask) != (mortonPrims[end].mortonCode & mask))) {
int n = end - start;
int maxNodes = 2 * n;
BVHNode* nodes = arena.Alloc<BVHNode>(maxNodes, false);
treesToBuild.push_back({ start, n, nodes });
start = end;
}
}
int orderedPrimsOffset = 0;
orderedPrims.resize(primitives.size());
int nodesCreated = 0;
int firstBitIndex = 29 - 12;
for (int i = 0; i < treesToBuild.size(); i++) {
treesToBuild[i].nodes = BVH::emit(treesToBuild[i].nodes, BVHPrimitives, &mortonPrims[treesToBuild[i].startIndex], orderedPrims, treesToBuild[i].numPrimitives, &nodesCreated, &orderedPrimsOffset, firstBitIndex);
*totalNodes += nodesCreated;
}
totalNodes += nodesCreated;
std::vector<BVHNode*> finishedTrees;
finishedTrees.reserve(treesToBuild.size());
for (BVHLittleTree& tr : treesToBuild) {
finishedTrees.emplace_back(tr.nodes);
}
return buildSAH(arena, finishedTrees, 0, finishedTrees.size(), totalNodes);
}
BVHNode* BVH::emit(BVHNode*& nodes, const std::vector<BVHPrimitiveInfo>& BVHPrimitive, MortonPrimitive* mortonPrimitives, std::vector<std::shared_ptr<Primitive>>& orderedPrimitives, int primitivesCount, int* totalNodes, int* orderedPrimsOffset, int bitIndex) {
if (bitIndex == -1 || primitivesCount < maxPrimsInNode) {
(*totalNodes)++;
BVHNode* tmp = nodes++;
BoundBox box;
int firstPrimOffset = *orderedPrimsOffset;
for (int i = 0; i < primitivesCount; i++) {
int index = mortonPrimitives[i].primitiveIndex;
orderedPrimitives[firstPrimOffset + i] = primitives[index];
box = box.Union(box, BVHPrimitive[index].box);
}
tmp->InitLeaf(0, primitivesCount, box);
return tmp;
}
else {
int mask = 1 << bitIndex;
if ((mortonPrimitives[0].mortonCode & mask) == (mortonPrimitives[primitivesCount - 1].mortonCode & mask)){ // Next tree if nothing to split for this bit
return emit(nodes, BVHPrimitive, mortonPrimitives, orderedPrimitives, primitivesCount, totalNodes, orderedPrimsOffset, bitIndex - 1);
}
int start = 0;
int end = primitivesCount - 1;
while (start + 1 != end) {
int mid = (end - start) / 2 + start; // (start-end)/2
if ((mortonPrimitives[start].mortonCode & mask) == (mortonPrimitives[mid].mortonCode & mask)) {
start = mid;
}
else {
end = mid;
}
}
int split = end;
(*totalNodes)++;
BVHNode* tmp = nodes++;
BVHNode* lbvh[2];
lbvh[0] = emit(nodes, BVHPrimitive, mortonPrimitives, orderedPrimitives, split, totalNodes, orderedPrimsOffset, bitIndex-1);
lbvh[1] = emit(nodes, BVHPrimitive, &mortonPrimitives[split], orderedPrimitives, primitivesCount - split, totalNodes, orderedPrimsOffset, bitIndex - 1);
int axis = bitIndex % 3;
tmp->InitInterior(axis, lbvh[0], lbvh[1]);
return tmp;
}
}
BVHNode* BVH::buildSAH(MemoryArena& arena, std::vector<BVHNode*>& treeRoots, int start, int end, int* total) const {
int nodesCount = end - start;
if (nodesCount == 1) {
return treeRoots[start];
}
assert(nodesCount > 1);
(*total)++;
BVHNode* node = arena.Alloc<BVHNode>();
BoundBox box;
for (int i = start; i < end; i++) {
box = Union(box, treeRoots[i]->box);
}
BoundBox centroidBox;
for (int i = start; i < end; i++) {
Point3D centroid = Point3D((treeRoots[i]->box.pMin.x + treeRoots[i]->box.pMax.x) * 0.5f, (treeRoots[i]->box.pMin.y + treeRoots[i]->box.pMax.y) * 0.5f, (treeRoots[i]->box.pMin.z + treeRoots[i]->box.pMax.z) * 0.5f);
centroidBox = Union(centroidBox, centroid);
}
const int dimension = centroidBox.MaximumExtent();
const int nBuckets = 12;
struct Buckets {
int count = 0;
BoundBox box;
};
Buckets buckets[nBuckets];
for (int i = start; i < end; i++) {
float centroid = (treeRoots[i]->box.pMin[dimension] * 0.5f + treeRoots[i]->box.pMax[dimension] * 0.5f) ;
int b = nBuckets * ((centroid - centroidBox.pMin[dimension]) / (centroidBox.pMax[dimension] - centroidBox.pMin[dimension]));
if (b == nBuckets) b = nBuckets - 1;
//assert(b < nBuckets);
buckets[b].count++;
buckets[b].box = Union(buckets[b].box, treeRoots[i]->box);
}
float cost[nBuckets - 1];
for (int i = 0; i < nBuckets - 1; i++) {
BoundBox b0, b1;
int count0 = 0, count1 = 0;
for (int j = 0; j <= i; j++) {
b0 = Union(b0, buckets[j].box);
count0 += buckets[j].count;
}
for (int j = i+1; j < nBuckets; j++) {
b1 = Union(b1, buckets[j].box);
count1 += buckets[j].count;
}
cost[i] = (.125f + (count0 * b0.surfaceArea() + count1 * b1.surfaceArea())) / box.surfaceArea();
}
double minCost = cost[0];
int minCostSplitBucket = 0;
for (int i = 1; i < nBuckets - 1; ++i) {
if (cost[i] < minCost) {
minCost = cost[i];
minCostSplitBucket = i;
}
}
BVHNode** pmid = std::partition(&treeRoots[start], &treeRoots[end - 1] + 1, [=](const BVHNode* node) {
double centroid = (node->box.pMin[dimension]*0.5f + node->box.pMax[dimension] * 0.5f) ;
int b = nBuckets * ((centroid - centroidBox.pMin[dimension]) / (centroidBox.pMax[dimension] - centroidBox.pMin[dimension]));
if (b == nBuckets) b = nBuckets - 1;
return b <= minCostSplitBucket;
});
assert(pmid != NULL);
//std::cout << pmid << " " << &treeRoots[0];
int mid = pmid - &treeRoots[0];
//std::cout << start << " " << mid << std::endl;
//std::cout << mid << " " << end << std::endl;
std::cout << dimension << std::endl;
//assert(dimension < 3);
node->InitInterior(dimension, this->buildSAH(arena, treeRoots, start, mid, total), this->buildSAH(arena, treeRoots, mid, end, total));
return node;
}
int BVH::flattenBVHTree(BVHNode* node, int* offset) {
LinearBVHNode* linearNode = &nodes[*offset];
linearNode->bounds = node->box;
int myOffset = (*offset)++;
if (node->nPrimitives > 0) {
linearNode->primitivesOffset = node->firstPrimOffset;
linearNode->nPrimitives = node->nPrimitives;
}
else {
// Create interior flattened BVH node
linearNode->axis = node->splitAxis;
linearNode->nPrimitives = 0;
flattenBVHTree(node->children[0], offset);
linearNode->secondChildOffset = flattenBVHTree(node->children[1], offset);
}
return myOffset;
}
My Point3D.hpp
#include <cstdint>
#pragma once
struct Point3D {
float x;
float y;
float z;
Point3D(uint32_t, uint32_t, uint32_t);
Point3D();
int operator[](int);
int operator[](int) const;
Point3D operator+(int);
Point3D operator-(int);
Point3D operator-(Point3D&);
};
Point3D::Point3D() {
x = 0;
y = 0;
z = 0;
}
Point3D::Point3D(uint32_t x, uint32_t y, uint32_t z) {
this->x = x;
this->y = y;
this->z = z;
}
bool operator<(Point3D a, Point3D b) {
uint32_t xSquare = a.x * a.x;
uint32_t ySquare = a.y * a.y;
uint32_t zSquare = a.z * a.z;
uint32_t x2Square = b.x * b.x;
uint32_t y2Square = b.y * b.y;
uint32_t z2Square = b.z * b.z;
int64_t sum = std::sqrt(xSquare + ySquare + z2Square) - std::sqrt(x2Square + y2Square + z2Square);
return sum < 0 ||
sum == 0 && xSquare < x2Square ||
sum == 0 && xSquare == x2Square && ySquare < y2Square ||
sum == 0 && xSquare == x2Square && ySquare == y2Square && zSquare < z2Square;
}
bool operator>(Point3D a, Point3D b) {
uint32_t xSquare = a.x * a.x;
uint32_t ySquare = a.y * a.y;
uint32_t zSquare = a.z * a.z;
uint32_t x2Square = b.x * b.x;
uint32_t y2Square = b.y * b.y;
uint32_t z2Square = b.z * b.z;
int32_t sum = std::sqrt(xSquare + ySquare + z2Square) - std::sqrt(x2Square + y2Square + z2Square);
return sum > 0 ||
sum == 0 && xSquare > x2Square ||
sum == 0 && xSquare == x2Square && ySquare > y2Square ||
sum == 0 && xSquare == x2Square && ySquare == y2Square && zSquare > z2Square;
}
int Point3D::operator[](int i) {
if (i == 0) return x;
if (i == 1) return y;
return z;
}
Point3D Point3D::operator+(int i) {
this->x += i;
this->y += i;
this->z += i;
return *this;
}
Point3D Point3D::operator-(const int i) {
this->x -= i;
this->y -= i;
this->z -= i;
return *this;
}
Point3D Point3D::operator-(Point3D& p) {
this->x -= p.x;
this->y -= p.y;
this->z -= p.z;
return *this;
}
int Point3D::operator[](const int i) const {
if (i == 0) return x;
if (i == 1) return y;
return z;
}
My BoundBox.hpp
#include "Point3D.hpp"
#include "Vector3D.hpp"
#pragma once
struct BoundBox {
Point3D pMin;
Point3D pMax;
BoundBox(Point3D);
BoundBox(Point3D, Point3D);
BoundBox();
void setBounds(BoundBox);
void Union(BoundBox);
BoundBox Union(BoundBox&, Point3D&);
BoundBox Union(BoundBox, BoundBox);
BoundBox unite(BoundBox, BoundBox);
BoundBox unite(BoundBox);
const Point3D offset(const Point3D&);
Point3D diagonal();
const int MaximumExtent();
float surfaceArea();
};
BoundBox::BoundBox() {
float minNum = 0;
pMin = Point3D(800, 600, 300);
pMax = Point3D(minNum, minNum, minNum);
}
BoundBox::BoundBox(Point3D p){
pMin = p;
pMax = p;
}
BoundBox::BoundBox(Point3D p1, Point3D p2) {
pMin = Point3D(std::min(p1.x, p2.x), std::min(p1.y, p2.y), std::min(p1.z, p2.z));
pMax = Point3D(std::max(p1.x, p2.x), std::max(p1.y, p2.y), std::max(p1.z, p2.z));
}
BoundBox BoundBox::Union(BoundBox& box, Point3D& p) {
BoundBox newBox;
newBox.pMin = Point3D(std::min(box.pMin.x, p.x), std::min(box.pMin.y, p.y), std::min(box.pMin.z, p.z));
newBox.pMax = Point3D(std::max(box.pMax.x, p.x), std::max(box.pMax.y, p.y), std::max(box.pMax.z, p.z));
return newBox;
}
BoundBox BoundBox::Union(BoundBox box1, BoundBox box2) {
BoundBox newBox;
newBox.pMin = std::min(box1.pMin, box2.pMin);
newBox.pMax = std::max(box1.pMax, box2.pMax);
return newBox;
}
BoundBox Union(BoundBox box1, BoundBox box2) {
BoundBox newBox;
newBox.pMin = std::min(box1.pMin, box2.pMin);
newBox.pMax = std::max(box1.pMax, box2.pMax);
return newBox;
}
BoundBox BoundBox::unite(BoundBox b1, BoundBox b2) {
bool x = (b1.pMax.x >= b2.pMin.x) && (b1.pMin.x <= b2.pMax.x);
bool y = (b1.pMax.y >= b2.pMin.y) && (b1.pMin.y <= b2.pMax.y);
bool z = (b1.pMax.z >= b2.pMin.z) && (b1.pMin.z <= b2.pMax.z);
if (x && y && z) {
return Union(b1, b2);
}
}
BoundBox BoundBox::unite(BoundBox b2) {
bool x = (this->pMax.x >= b2.pMin.x) && (this->pMin.x <= b2.pMax.x);
bool y = (this->pMax.y >= b2.pMin.y) && (this->pMin.y <= b2.pMax.y);
bool z = (this->pMax.z >= b2.pMin.z) && (this->pMin.z <= b2.pMax.z);
if (x && y && z) {
return Union(*this, b2);
}
else return *this;
}
const int BoundBox::MaximumExtent() {
Point3D d = Point3D(this->pMax.x - this->pMin.x, this->pMax.y - this->pMin.y, this->pMax.z - this->pMin.z); // diagonal
if (d.x > d.y && d.x > d.z) {
return 0;
}
else if (d.y > d.z) {
return 1;
}
else {
return 2;
}
}
float BoundBox::surfaceArea() {
Point3D d = Point3D(this->pMax.x - this->pMin.x, this->pMax.y - this->pMin.y, this->pMax.z - this->pMin.z); // diagonal
return 2 * (d.x * d.y + d.x * d.z + d.y * d.z);
}
const Point3D BoundBox::offset(const Point3D& p) {
Point3D o = Point3D(p.x - pMin.x, p.y - pMin.y, p.z - pMin.z);
if (pMax.x > pMin.x) o.x /= pMax.x - pMin.x;
if (pMax.y > pMin.y) o.y /= pMax.y - pMin.y;
if (pMax.z > pMin.z) o.z /= pMax.z - pMin.z;
return o;
}
My memory.hpp
#include <list>
#include <cstddef>
#include <algorithm>
#include <malloc.h>
#include <stdlib.h>
#pragma once
#define ARENA_ALLOC(arena, Type) new ((arena).Alloc(sizeof(Type))) Type
void* AllocAligned(size_t size);
template <typename T>
T* AllocAligned(size_t count) {
return (T*)AllocAligned(count * sizeof(T));
}
void FreeAligned(void*);
class
#ifdef PBRT_HAVE_ALIGNAS
alignas(PBRT_L1_CACHE_LINE_SIZE)
#endif // PBRT_HAVE_ALIGNAS
MemoryArena {
public:
// MemoryArena Public Methods
MemoryArena(size_t blockSize = 262144) : blockSize(blockSize) {}
~MemoryArena() {
FreeAligned(currentBlock);
for (auto& block : usedBlocks) FreeAligned(block.second);
for (auto& block : availableBlocks) FreeAligned(block.second);
}
void* Alloc(size_t nBytes) {
// Round up _nBytes_ to minimum machine alignment
#if __GNUC__ == 4 && __GNUC_MINOR__ < 9
// gcc bug: max_align_t wasn't in std:: until 4.9.0
const int align = alignof(::max_align_t);
#elif !defined(PBRT_HAVE_ALIGNOF)
const int align = 16;
#else
const int align = alignof(std::max_align_t);
#endif
#ifdef PBRT_HAVE_CONSTEXPR
static_assert(IsPowerOf2(align), "Minimum alignment not a power of two");
#endif
nBytes = (nBytes + align - 1) & ~(align - 1);
if (currentBlockPos + nBytes > currentAllocSize) {
// Add current block to _usedBlocks_ list
if (currentBlock) {
usedBlocks.push_back(
std::make_pair(currentAllocSize, currentBlock));
currentBlock = nullptr;
currentAllocSize = 0;
}
// Get new block of memory for _MemoryArena_
// Try to get memory block from _availableBlocks_
for (auto iter = availableBlocks.begin();
iter != availableBlocks.end(); ++iter) {
if (iter->first >= nBytes) {
currentAllocSize = iter->first;
currentBlock = iter->second;
availableBlocks.erase(iter);
break;
}
}
if (!currentBlock) {
currentAllocSize = std::max(nBytes, blockSize);
currentBlock = AllocAligned<uint8_t>(currentAllocSize);
}
currentBlockPos = 0;
}
void* ret = currentBlock + currentBlockPos;
currentBlockPos += nBytes;
return ret;
}
template <typename T>
T* Alloc(size_t n = 1, bool runConstructor = true) {
T* ret = (T*)Alloc(n * sizeof(T));
if (runConstructor)
for (size_t i = 0; i < n; ++i) new (&ret[i]) T();
return ret;
}
void Reset() {
currentBlockPos = 0;
availableBlocks.splice(availableBlocks.begin(), usedBlocks);
}
size_t TotalAllocated() const {
size_t total = currentAllocSize;
for (const auto& alloc : usedBlocks) total += alloc.first;
for (const auto& alloc : availableBlocks) total += alloc.first;
return total;
}
private:
MemoryArena(const MemoryArena&) = delete;
MemoryArena & operator=(const MemoryArena&) = delete;
// MemoryArena Private Data
const size_t blockSize;
size_t currentBlockPos = 0, currentAllocSize = 0;
uint8_t * currentBlock = nullptr;
std::list<std::pair<size_t, uint8_t*>> usedBlocks, availableBlocks;
};
template <typename T, int logBlockSize>
class BlockedArray {
public:
// BlockedArray Public Methods
BlockedArray(int uRes, int vRes, const T* d = nullptr)
: uRes(uRes), vRes(vRes), uBlocks(RoundUp(uRes) >> logBlockSize) {
int nAlloc = RoundUp(uRes) * RoundUp(vRes);
data = AllocAligned<T>(nAlloc);
for (int i = 0; i < nAlloc; ++i) new (&data[i]) T();
if (d)
for (int v = 0; v < vRes; ++v)
for (int u = 0; u < uRes; ++u) (*this)(u, v) = d[v * uRes + u];
}
const int BlockSize() const { return 1 << logBlockSize; }
int RoundUp(int x) const {
return (x + BlockSize() - 1) & ~(BlockSize() - 1);
}
int uSize() const { return uRes; }
int vSize() const { return vRes; }
~BlockedArray() {
for (int i = 0; i < uRes * vRes; ++i) data[i].~T();
FreeAligned(data);
}
int Block(int a) const { return a >> logBlockSize; }
int Offset(int a) const { return (a & (BlockSize() - 1)); }
T& operator()(int u, int v) {
int bu = Block(u), bv = Block(v);
int ou = Offset(u), ov = Offset(v);
int offset = BlockSize() * BlockSize() * (uBlocks * bv + bu);
offset += BlockSize() * ov + ou;
return data[offset];
}
const T & operator()(int u, int v) const {
int bu = Block(u), bv = Block(v);
int ou = Offset(u), ov = Offset(v);
int offset = BlockSize() * BlockSize() * (uBlocks * bv + bu);
offset += BlockSize() * ov + ou;
return data[offset];
}
void GetLinearArray(T * a) const {
for (int v = 0; v < vRes; ++v)
for (int u = 0; u < uRes; ++u) * a++ = (*this)(u, v);
}
private:
// BlockedArray Private Data
T * data;
const int uRes, vRes, uBlocks;
};
void* AllocAligned(size_t size) {
return _aligned_malloc(size, 32);
}
void FreeAligned(void* ptr) {
if (!ptr) return;
_aligned_free(ptr);
}
and My Source.cpp
#include <iostream>
#include <vector>
#include <chrono>
#include "Point3D.hpp"
#include "Screen.hpp"
#include "BVH.hpp"
#define N 150
int main(){
auto startTime = std::chrono::high_resolution_clock::now();
Screen* screen = new Screen(800, 600, 300);
screen->generatePoints(N);
//for (MortonPrimitive m : mortonPrims) {
// std::cout << m.mortonCode << std::endl;
//}
std::vector<std::shared_ptr<Primitive>> primitives;
primitives.reserve(N);
for (int i = 0; i < N; i++) {
primitives.emplace_back(screen->castPointToPrimitive(i));
}
BVH test(primitives);
auto endTime = std::chrono::high_resolution_clock::now();
std::cout << "Time spent: " << std::chrono::duration_cast<std::chrono::milliseconds>(endTime - startTime).count() << "ms\n";
getchar();
delete screen;
}
Probably it would be wise to first cleanup your github. This mean update stuff to the recent c++ standard. It seems that you can use c++17 so use it. Also please look at some names. For example 'nodes' is used as member variable as well as parameter name, this is confusion. Please also initialize relevant (all) member variables.
Now it seems that the code in buildSAH override memory. It seems that it it can write over the end of buckets array.

Unhandled exception Access violation writing location

When I compile my program I get this unhandled exception that I don't understand or know how to fix.
Exception thrown at 0x00007FF6DFF937FE in My
Code.exe: 0xC0000005: Access violation writing location
0x000002E07396F000.
If there is a handler for this exception, the program may be safely
continued.
//main.cpp
#include <iostream>
#include <fstream>
#include <sstream>
#include <algorithm>
#include <vector>
#include <string>
#include "Image.h"
Image readPPM(const char* file);
void writePPM(const Image &img, const char* file);
int main()
{
std::vector<Image> inputImages;
inputImages.resize(13);
Image *outputImage;
for (int x = 1; x < 14; x++)
{
inputImages.push_back(Image(3264, 2448));
inputImages[x] = readPPM(std::string("Images/ImageStacker_set1/IMG_" + std::to_string(x) + ".ppm").c_str());
}
outputImage = new Image(3264, 2448);
outputImage->pixels = new Image::Rgb[3264, 2448];
for (int x = 0; x < 3264 * 2448; x++) {
float sumR = 0.f;
float sumG = 0.f;
float sumB = 0.f;
for (int i = 0; i < 12; i++) {
sumR += inputImages[i].pixels[x].r;
sumG += inputImages[i].pixels[x].g;
sumB += inputImages[i].pixels[x].b;
}
outputImage->pixels[x].r = sumR / 13;
outputImage->pixels[x].g = sumG / 13;
outputImage->pixels[x].b = sumB / 13;
}
writePPM(*outputImage, "testPPM.ppm");
return 0;
}
Image readPPM(const char *filename)
{
//Remove this cout to prevent multiple outputs
std::cout << "Reading image ..." << std::endl;
std::ifstream ifs;
ifs.open(filename, std::ios::binary);
Image src;
try {
if (ifs.fail()) {
throw("Can't open the input file - is it named correctly/is it in the right directory?");
}
std::string header;
int w, h, b;
ifs >> header;
if (strcmp(header.c_str(), "P6") != 0) throw("Can't read the input file - is it in binary format (Has P6 in the header)?");
ifs >> w >> h >> b;
src.w = w;
src.h = h;
//std::cout << w << " " << h << std::endl;
src.pixels = new Image::Rgb[w * h]; // this is throw an exception if bad_alloc
ifs.ignore(256, '\n'); // skip empty lines in necessary until we get to the binary data
unsigned char pix[3]; // read each pixel one by one and convert bytes to floats
for (int i = 0; i < w * h; ++i) {
ifs.read(reinterpret_cast<char *>(pix), 3);
src.pixels[i].r = pix[0] / 255.f;
src.pixels[i].g = pix[1] / 255.f;
src.pixels[i].b = pix[2] / 255.f;
}
ifs.close();
}
catch (const char *err) {
fprintf(stderr, "%s\n", err);
ifs.close();
}
//Confirm image read
//Delete this to prevent multiple lines output
std::cout << "Image read" << std::endl;
return src;
}
//Write data out to a ppm file
//Constructs the header as above
void writePPM(const Image &img, const char *filename)
{
//std::cout << filename << std::endl;
std::cout << "Writing image ..." << std::endl;
if (img.w == 0 || img.h == 0) { fprintf(stderr, "Can't save an empty image\n"); return; }
std::ofstream ofs;
try {
ofs.open(filename, std::ios::binary); // need to spec. binary mode for Windows users
if (ofs.fail()) throw("Can't open output file");
ofs << "P6\n" << img.w << " " << img.h << "\n255\n";
//std::cout << "P6\n" << img.w << " " << img.h << "\n255\n";
unsigned char r, g, b;
// loop over each pixel in the image, clamp and convert to byte format
for (int i = 0; i < img.w * img.h; ++i) {
r = static_cast<unsigned char>(std::min(1.f, img.pixels[i].r) * 255);
g = static_cast<unsigned char>(std::min(1.f, img.pixels[i].g) * 255);
b = static_cast<unsigned char>(std::min(1.f, img.pixels[i].b) * 255);
ofs << r << g << b;
}
ofs.close();
//Confirm image write
std::cout << "Image written" << std::endl;
}
catch (const char *err) {
fprintf(stderr, "%s\n", err);
ofs.close();
}
}
Image.h
#pragma once
//*********************************************
//Image class to hold and allow manipulation of images once read into the
code
//from https://www.scratchapixel.com/
//*********************************************
#include <cstdlib>
#include <cstdio>
class Image
{
public:
// Rgb structure, i.e. a pixel
struct Rgb
{
Rgb() : r(0), g(0), b(0) {}
Rgb(float c) : r(c), g(c), b(c) {}
Rgb(float _r, float _g, float _b) : r(_r), g(_g), b(_b) {}
bool operator != (const Rgb &c) const
{
return c.r != r || c.g != g || c.b != b;
}
Rgb& operator *= (const Rgb &rgb)
{
r *= rgb.r, g *= rgb.g, b *= rgb.b; return *this;
}
Rgb& operator += (const Rgb &rgb)
{
r += rgb.r, g += rgb.g, b += rgb.b; return *this;
}
friend float& operator += (float &f, const Rgb rgb)
{
f += (rgb.r + rgb.g + rgb.b) / 3.f; return f;
}
float r, g, b;
};
Image() : w(0), h(0), pixels(nullptr) { /* empty image */ }
Image(const unsigned int &_w, const unsigned int &_h, const Rgb &c =
kBlack) :
w(_w), h(_h), pixels(NULL)
{
pixels = new Rgb[w * h];
for (int i = 0; i < w * h; ++i)
pixels[i] = c;
}
//copy constructor
Image(const Image &im)
{
w = im.w;
h = im.h;
pixels = new Rgb[im.w * im.h];
for (int i = 0; i < im.w * im.h; ++i)
pixels[i] = im.pixels[i];
}
//copy assignment operator
Image& operator=(const Image& other)
{
w = other.w;
h = other.h;
pixels = new Rgb[other.w * other.h];
for (int i = 0; i < other.w * other.h; ++i)
pixels[i] = other.pixels[i];
return *this;
}
const Rgb& operator [] (const unsigned int &i) const
{
return pixels[i];
}
Rgb& operator [] (const unsigned int &i)
{
return pixels[i];
}
~Image()
{
if (pixels != NULL) delete[] pixels;
//delete[] pixels;
}
//unsigned int w, h; // Image resolution
int w, h; // Image resolution
Rgb *pixels; // 1D array of pixels
static const Rgb kBlack, kWhite, kRed, kGreen, kBlue; // Preset colors
};
const Image::Rgb Image::kBlack = Image::Rgb(0);
const Image::Rgb Image::kWhite = Image::Rgb(1);
const Image::Rgb Image::kRed = Image::Rgb(1, 0, 0);
const Image::Rgb Image::kGreen = Image::Rgb(0, 1, 0);
const Image::Rgb Image::kBlue = Image::Rgb(0, 0, 1);
Here's the code that appears to be causing the problem. When debugging it seems to be that there's something wrong with the pointers here:
outputImage->pixels[x].r = sumR / 13;
outputImage->pixels[x].g = sumG / 13;
outputImage->pixels[x].b = sumB / 13;
Sorry I can't really provide anything else to go on but I have never had an error like this before so I don't know where to start in fixing it.
There's some level of bad here. But I believe at the core you meant to write:
inputImages[x] = Image(3264, 2448);
inputImages[x].pixels = readPPM(std::string("Images/ImageStacker_set1/IMG_" + std::to_string(x) + ".ppm").c_str());
Stepping through your code:
std::vector<Image> inputImages - Leaves inputImages with a size of 0
inputImages.resize(13); - Leaves inputImages with a size of 13 default constructed Images
inputImages.push_back(Image(3264, 2448)); - Increments the size of inputImages by 1 by adding a default image onto the tail end, ultimately increasing the size of inputImages to 26
inputImages[x] = readPPM(std::string("Images/ImageStacker_set1/IMG_" + std::to_string(x) + ".ppm").c_str()); - Modifies one of the default constructed Images in inputImages' [1 - 12] then finally modifies the first Image(3264, 2448) in inputImages
This means that at a minimum you have 13 Image(3264, 2448) objects that are never accessed. The 1st element that is accessed by the code in question, inputImage[0] is a default constructed Image. And unless readPPM returns an Image with an allocated pixels field, there are no Images in inputImages [1 - 12] range which can support access to their pixels field.

LNK1169 Error C++ with own classes

Just signed up, because my mind is blowing up on this stupid error.
I was calculating elliptic curves in a quick and dirty way with everything in 1 source-file.
Then I thought about cleaning up my code and start to separate the functions and classes in different files.
It's been a long time for me programming in C++ so I guess it is a really stupid beginner mistake.
So I am getting LNK1169-Error and LNK2005-Error and the solutions I found are about including .cpp which I am not doing. I although found out about the extern-keyword, but that seems to be kind of the solution for global variables.
Maybe someone can help me.
EDIT:
Sorry for putting that much code. I just don't know what is relevant for the error and what's not.
The error I am getting are like this:
fatal error LNK1169: one or more multiply defined symbols found. Elliptic 1 C:\Users\Björn\documents\visual studio 2015\Projects\Elliptic 1\Debug\Elliptic 1.exe
error LNK2005 "public: int __thiscall Value::operator==(class Value const &)" (??8Value##QAEHABV0##Z) already defined in Tests.obj
error LNK2005 "public: int __thiscall Value::operator==(int)" (??8Value##QAEHH#Z) already defined in Tests.obj
Here is my code:
Value.hpp
#pragma once
extern int PRIME;
// An own Int-Class to overload operators with modulo
class Value
{
public:
int v;
static friend std::ostream& operator<<(std::ostream& os, const Value& a);
Value()
{
this->v = 0;
}
Value(int a)
{
this->v = a;
}
Value operator+(const Value& other)
{
return Value((this->v + other.v) % PRIME);
}
Value operator+(int a)
{
return Value((this->v + a) % PRIME);
}
Value operator-(const Value& other)
{
Value t = Value((v - other.v) % PRIME);
if (t.v < 0)
{
t = t + PRIME;
return t;
}
return t;
}
Value operator-(int a)
{
Value t = Value((v - a) % PRIME);
if (t.v < 0)
{
t = t + PRIME;
return t;
}
return t;
}
void operator=(const Value other)
{
this->v = other.v;
}
Value operator*(const Value& a);
Value operator*(int a);
Value operator^(int a);
Value operator/(const Value& a);
int operator!=(int b);
int operator!=(const Value& b);
int operator==(int b);
int operator==(const Value& b);
Value operator~();
};
Value Value::operator*(const Value& a)
{
return Value((this->v*a.v) % PRIME);
}
Value Value::operator*(int a)
{
return Value((this->v*a) % PRIME);
}
Value Value::operator^(int b)
{
Value ret(1);
Value mul(this->v);
while (b)
{
if (b & 1)
ret = (ret * mul);
b = (b >> 1);
mul = mul * mul;
}
return ret;
}
Value Value::operator/(const Value& a)
{
if (a.v == 0)
return Value(0);
Value f = (Value)a ^ (PRIME - 2);
return *this * f;
}
int Value::operator!=(int b)
{
if (this->v != b)
return 1;
return 0;
}
int Value::operator!=(const Value& b)
{
if (this->v != b.v)
return 1;
return 0;
}
int Value::operator==(int b)
{
if (this->v == b)
return 1;
return 0;
}
int Value::operator==(const Value& b)
{
if (this->v == b.v)
return 1;
return 0;
}
Value Value::operator~()
{
return *this ^ ((PRIME - 1 + 2) / 4);
}
std::ostream& operator<<(std::ostream& os, const Value& a)
{
return os << a.v;
}
Point.hpp
#pragma once
#include "Value.hpp"
#include <iostream>
class Point
{
public:
Value x;
Value y;
Value z = 0;
static friend std::ostream& operator<<(std::ostream& os, const Point& p);
Point(int a, int b)
{
x.v = a;
y.v = b;
}
Point(int a, int b, int c)
{
x.v = a;
y.v = b;
z.v = c;
}
Point(Value a, Value b)
{
x.v = a.v;
y.v = b.v;
}
Point(Value a, Value b, Value c)
{
x.v = a.v;
y.v = b.v;
z.v = c.v;
}
Point& operator=(const Point& other)
{
x.v = other.x.v;
y.v = other.y.v;
z.v = other.z.v;
return *this;
}
int operator==(Point& other)
{
if (this->x == other.x && this->y == other.y && this->z == other.z)
return 1;
return 0;
}
int operator!=(Point& other)
{
if (this->x != other.x || this->y != other.y || this->z != other.z)
return 1;
return 0;
}
};
std::ostream& operator<<(std::ostream& os, const Point& p)
{
if ((Value)p.z == 0)
return os << "(" << p.x.v << "," << p.y.v << ")";
else
return os << "(" << p.x.v << "," << p.y.v << "," << p.z.v << ")";
}
Helper.hpp
#pragma once
#include "Point.hpp"
#include <vector>
// Forward declaration
int isEC(Value a, Value b);
Value calcEC(int x, Value a, Value b);
int testSqr(Value ySqr);
// Point Addition
Point add(Point p1, Point p2, Value a)
{
// 2D Addition
if (p1.z == 0 && p2.z == 0)
{
// 2 different points
if (p1.x.v != p2.x.v || p1.y.v != p2.y.v)
{
// m = (y2-y1)/(x2-x1)
Value h = p2.y - p1.y;
Value j = p2.x - p1.x;
Value m = h / j;
// x3 = m^2-x1-x2
Value f = m*m;
Value g = f - p1.x;
Value x3 = g - p2.x;
// y3 = m(x1-x3)-y1
Value t = p1.x - x3;
Value l = m * t;
Value y3 = l - p1.y;
if (x3.v < 0)
x3 = x3 + PRIME;
if (y3.v < 0)
y3 = y3 + PRIME;
return Point(x3, y3);
}
// Same points
else
{
// m = (3*x1^2+a)/(2*y1)
Value f = p1.x ^ 2;
Value g = f * 3;
Value h = g + a;
Value j = p1.y * 2;
Value m = h / j;
// x3 = m^2-2*x1
Value t = m*m;
Value x = p1.x * 2;
Value x3 = t - x;
// y3 = m(x1-x3)-y1
Value z = p1.x - x3;
Value i = m * z;
Value y3 = i - p1.y;
if (x3.v < 0)
x3 = x3 + PRIME;
if (y3.v < 0)
y3 = y3 + PRIME;
return Point(x3, y3);
}
}
// 3D Addition - Same points
else if (p1 == p2 && p1.z == 1 && p2.z == 1)
{
Value A = p1.y ^ 2;
Value B = p1.x * A * 4;
Value C = (A ^ 2) * 8;
Value D = (p1.x ^ 2)* 3 + a*(p1.z ^ 4);
//Value x3 = (((3 * (p1.x ^ 2) + a*(p1.z ^ 4)) ^ 2) - 8 * p1.x*(p1.y ^ 2));
Value x3 = (D ^ 2) - B * 2;
//Value y3 = (3 * (p1.x ^ 2) + a*(p1.z ^ 4)*(4 * p1.x*(p1.y ^ 2) - x3) - 8 * (p1.y ^ 4));
Value y3 = D*(B - x3) - C;
Value z3 = p1.y*p1.z * 2;
return Point(x3, y3, z3);
}
// 3D Addition - 2 different points
else if (p1 != p2)
{
Value A = p1.z ^ 2;
Value B = p1.z * A;
Value C = p2.x * A;
Value D = p2.y * B;
Value E = C - p1.x;
Value F = D - p1.y;
Value G = E ^ 2;
Value H = G * E;
Value I = p1.x * G;
Value x3 = (F ^ 2) - (H + (I * 2));
Value y3 = F*(I - x3) - p1.y*H;
Value z3 = p1.z * E;
return Point(x3, y3, z3);
}
return Point(0, 0, 0);
}
// Find all points and print them
std::vector<Point> findAllPoints(Value a, Value b)
{
Value ySqr;
std::vector<Point> vec;
std::cout << "Alle Punkte fuer a = " << a << ", b = " << b << " und Prime = " << PRIME << std::endl;
// Is it an elliptic curve?
if (isEC(a, b))
{
// Test all x-Values
for (int x = 0; x <= PRIME - 1;x++)
{
// y^2
ySqr = calcEC(x, a, b);
// Test ySqr for square by root
if (testSqr(ySqr))
{
//sqrt operator ~
Value yPos = ~ySqr;
std::cout << "(" << x << "," << yPos << ")\t";
Value yNeg = yPos - (yPos * 2);
// Save found points into vector
vec.push_back(Point(x, yPos));
vec.push_back(Point(x, yNeg));
if (yNeg != 0)
std::cout << "(" << x << "," << yNeg << ")\t";
}
}
//vec.insert(vec.begin(), Point(INFINITY, INFINITY));
std::cout << std::endl;
}
else
// Not an ellpitic curve
std::cout << "\na and b are not leading to an ellptic curve.";
return vec;
}
// Test if a and b lead to an EC
int isEC(Value a, Value b)
{
if ((a ^ 3) * 4 + (b ^ 2) * 27 != 0)
return 1;
return 0;
}
// Calculate y^2
Value calcEC(int x, Value a, Value b)
{
return Value(a*x + (x ^ 3) + b);
}
// Test ySqr for square by root
int testSqr(Value ySqr)
{
if ((ySqr ^ ((PRIME - 1) / 2)) == 1 || ySqr == 0)
return 1;
return 0;
}
Tests.hpp
#pragma once
#include "Helper.hpp"
class Tests
{
public:
void twoDAdd(Value a, Value b);
void twoDDoubling(Value a, Value b);
void threeDAdd(Value a, Value b);
void threeDDoubling(Value a, Value b);
};
Tests.cpp
#pragma once
#include <stdlib.h>
#include <vector>
#include <iostream>
#include <math.h>
#include <time.h>
#include "Tests.hpp"
// 2D - Addition
void Tests::twoDAdd(Value a, Value b)
{
std::cout << "\n========== 2D Addition ==========\n";
Point p2D1 = Point(5, 22);
Point p2D2 = Point(16, 27);
std::cout << p2D1 << " + " << p2D2 << " = " << add(p2D1, p2D2, a);
std::cout << std::endl;
}
// 2D - Doubling
void Tests::twoDDoubling(Value a, Value b)
{
std::cout << "\n========== 2D Doubling ==========\n";
Point p2D1 = Point(5, 22);
std::cout << "2 * " << p2D1 << " = " << add(p2D1, p2D1, a);
std::cout << std::endl << std::endl;
}
// 3D - Addition
void Tests::threeDAdd(Value a, Value b)
{
std::cout << "\n========== 3D Addition ==========\n";
std::cout << "All points for a = " << a << ", b = " << b << " and prime = " << PRIME << std::endl;
std::vector<Point> allPoints = findAllPoints(a, b);
std::srand(time(NULL));
int random = std::rand() % (allPoints.capacity() - 1);
Point tmp = allPoints.at(random);
std::cout << std::endl << "Random Point 1: " << tmp << std::endl << std::endl;
tmp.z = 1;
Point p1 = add(tmp, tmp, a);
std::cout << p1 << std::endl;
random = std::rand() % (allPoints.capacity() - 1);
tmp = allPoints.at(random);
std::cout << std::endl << "Random Point 2: " << tmp << std::endl << std::endl;
tmp.z = 1;
Point p2 = add(tmp, tmp, a);
std::cout << p2 << std::endl;
Point p3 = add(p1, p2, a);
std::cout << p3 << std::endl;
}
// 3D - Doubling
void Tests::threeDDoubling(Value a, Value b)
{
std::cout << "\n========== 3D Doubling ==========\n";
std::cout << "All points for a = " << a << ", b = " << b << " and prime = " << PRIME << std::endl;
std::vector<Point> allPoints = findAllPoints(a, b);
int random = std::rand() % (allPoints.capacity() - 1);
Point tmp = allPoints[random];
std::cout << std::endl << "Random Point: " << tmp << std::endl << std::endl;
Point p1 = add(tmp, tmp, a);
std::cout << p1 << std::endl;
tmp.z = 1;
Point p2 = add(tmp, tmp, a);
std::cout << p2 << std::endl;
Point p3 = Point(p2.x / (p2.z ^ 2), p2.y / (p2.z ^ 3));
std::cout << p3 << std::endl;
if (p1 == p3)
std::cout << "Point p1 == Point p3" << std::endl;
else
std::cout << "Point p1 != Point p3" << std::endl;
}
Main.cpp
#pragma once
#include <stdlib.h>
#include <vector>
#include <iostream>
#include <math.h>
#include <time.h>
#include "Tests.hpp"
int PRIME = 29;
void main()
{/*
Value a = 4;
Value b = 20;
std::vector<Point> allPoints = findAllPoints(a, b);
/*
// Tests ausfuehren
twoDAdd(a, b);
twoDDoubling(a, b);
threeDAdd(a, b);
threeDDoubling(a, b);
*/
std::cout << std::endl;
system("pause");
}
Thanks in advance and please excuse my "inperfect" way of coding.
This is happening because you have function definition in header files. Every file that we'll import your header files will have a body function - this is the reason why you have this error. If you want to have the definitions inside header files, you must use inline keyword. Otherwise you need to implement them in .cpp files (the "correct" way of solving this issue).
e.g
// Test if a and b lead to an EC
inline int isEC(Value a, Value b)
{
if ((a ^ 3) * 4 + (b ^ 2) * 27 != 0)
return 1;
return 0;
}
// Calculate y^2
inline Value calcEC(int x, Value a, Value b)
{
return Value(a*x + (x ^ 3) + b);
}
// Test ySqr for square by root
inline int testSqr(Value ySqr)
{
if ((ySqr ^ ((PRIME - 1) / 2)) == 1 || ySqr == 0)
return 1;
return 0;
}

Error on program opening

When I try to start my C++ program it stops with error "5.exe has stopped working". This program supposed to calculate how many tiles you need for pool, if number of tiles on one side is non-round number, add one row of tiles to it. P.S. Sorry for my bad English.
#include <iostream>
#include <math.h>
#include <cstdlib>
using namespace std;
int main()
{
int x,y,z;
int a,b;
cout << "Insert dimensions of pool in metres: " << endl;
cin >> x >> y >> z;
cout << "Insert dimensions of tile in centimeters: " << endl;
cin >> a >> b;
a=a/100;
b=b/100;
int brx = 0, brzx = 0, bry = 0, brzy = 0, bxpod = 0, bypod = 0;
if (x%a == 0) {
brx = x / a;
}
else {
brx = x / a + 1;
}
if (z%b == 0) {
brzx = z / b;
}
else {
brzx = z / b + 1;
}
if (y%a == 0) {
bry = y / a;
}
else {
bry = y / a + 1;
}
if (z%b == 0) {
brzy = z / b;
}
else {
brzy = z / b + 1;
}
if (x%a == 0) {
bxpod = x / a;
}
else {
bxpod = x / a + 1;
}
if (y%b == 0) {
bypod = y / b;
}
else {
bypod = y / b + 1;
}
int s = (brx*brzx + bry*brzy) * 2 + bxpod*bypod;
cout << "You need " << s << "tiles." << endl;
system("pause");
return 0;
}
Using a debugger, you can easily find that you have a division by 0 in the following lline:
if (x%a == 0) {
brx = x / a;
}
You are doing an integer division on "a":
a = a / 100;
So if a is lower than 100, a will be 0. 10 / 100 = 0.1 = 0 when cast as int.
You should use double instead of int