vectorize non aligned data in a struct method - c++

I have this simple struct:
struct cbt
{
vector<vector<int>> tree;
int depth;
int data;
cbt(int max_size) // just initializes tree
{
depth = (int) log2(max_size);
unsigned int l;
for(int i = 0; i <= depth; i++)
{
l = (unsigned int) pow(2,i);
tree.push_back(vector<int>(l,0));
}
}
inline void update(int pos, int value)
{
int diff = value - data;
int p = pos>>1;
for(int i = depth; i >= 0; i--)
{
tree[i][p] += diff;
p = p>>1;
}
}
};
Is there any way to vectorize the loop in the update() function even thought the data is not aligned?
In my code the update() function is called billions of times and so I was hoping to make it as fast as possible.

Related

How to pass an array of structure by reference for sorting?

In this code , I am creating an array of structure and trying to sort the structure array based on "arr_time" field. I am having problem on how to pass the structure array by reference in function sort_process() .
#include<iostream>
using namespace std;
struct process {
public:
int p_id,arr_time,burst_time,comp_time;
};
void sort_process( process x[],int len)
{
int i,j;
process temp;
for(i=0;i<len;i++)
{
for(j=0;j<len-1;j++)
{
if(x[j].arr_time > x[j+1].arr_time)
{
temp = x[j];
x[j] = x[j+1];
x[j+1] = temp;
}
}
}
}
int main()
{
int n,i=0,j=0,k=0,t=0,flag;
cout<<"\n Enter number of processes : ";
cin>>n;
process p[n];
for(i=0;i<n;i++)
initialize(p[i]);
sort_process(p,n);
return 0;
}
You can simply use std::sort in the header <algorithm>:
std::sort(p, p+n, [](const process & p1, const process & p2){return p1 < p2}); // Will sort p in ascending order
But if you really want to do it manually and pass the array to a function, you can create the function as:
void sort_process(process * x, std::size_t len) // copy the pointer
{
std::sort(x, x+len, [](const process & p1, const process & p2){return p1 < p2;});
}
But passing process x[] as you did is equivalent.
Note: As we refer to an array by the pointer to its first element, what your are passing here is a pointer to the first element too (and not the array).
If you really want to pass it by reference, you can do it as follows:
void sort_process(process * const & x, std::size_t len)
{
std::sort(x, x+len, [](const process & p1, const process & p2){return p1 < p2;});
}
I added a const qualifier to forbid the modification of the pointer as it is not a copy but a reference to the original one
But you don't really gain anything by passing a reference here in my opinion.
Seems like you are afraid of dynamic arrays and pointers. Try this:
#include<iostream>
using namespace std;
struct process
{
int p_id, arr_time, burst_time, comp_time;
void initialize()
{
p_id = arr_time = burst_time = comp_time = 0;
}
process()
{
p_id = arr_time = burst_time = comp_time = 0;
}
~process() {}
};
void sort_process(process*& x, int len)
{
int i, j;
process temp;
for (i = 0; i < len; i++)
{
for (j = 0; j < len - 1; j++)
{
if (x[j].arr_time > x[j + 1].arr_time)
{
temp = x[j];
x[j] = x[j + 1];
x[j + 1] = temp;
}
}
}
}
int main()
{
int n, i = 0, j = 0, k = 0, t = 0, flag;
cout << "\n Enter number of processes : ";
cin >> n;
process* p = new process[n];
for (i = 0; i < n; i++)
p[i].initialize();
sort_process(p, n);
for (i = 0; i < n; i++)
p[i].~process();
delete[] p; p = 0;
return 0;
}

Segmentation fault at std::thread

typedef struct _ppm_struct* ppm_struct;
typedef unsigned char ppm_subpixel;
typedef ppm_subpixel (*ppm_pixel_func)(ppm_subpixel);
struct ppm_pixel {
ppm_subpixel red;
ppm_subpixel green;
ppm_subpixel blue;
};
struct _ppm_struct {
unsigned int width;
unsigned int height;
unsigned int max_color;
ppm_pixel *firstpixel;
};
So I have this function call:
void pppm_color_pixel(ppm_struct p, ppm_struct out, ppm_pixel_func func, int threads) {
//ppm_pixel_func func2 = &inverse_pixel;
unsigned int w = p->width;
unsigned int h = p->height;
ppm_pixel *iterator = p->firstpixel;
std::thread th[threads];
long long total_pixels = w*h;
unsigned int count_for_thread = total_pixels/threads;
for(int j = 0; j<threads; ++j) {
th[j] = std::thread(pppm_color_chunk_pixel,func, *iterator,count_for_thread);
iterator = &iterator[count_for_thread];
}
for(int j = 0; j<threads; ++j) {
th[j].join();
}
The next two function: funct is inverse subpixel
ppm_subpixel inverse_subpixel(ppm_subpixel subpixel) {
subpixel = 255- subpixel;
return subpixel;
}
void pppm_color_chunk_pixel(ppm_pixel_func func, ppm_pixel start_pixel, unsigned int count) {
ppm_pixel *iterator = &start_pixel;
for(unsigned int i = 0; i< count; ++i) {
iterator[i].red = func(iterator[i].red);
iterator[i].green = func(iterator[i].green);
iterator[i].blue = func(iterator[i].blue);
}
}
The main:
pppm_color_pixel(p,out, &inverse_subpixel,pppm_get_max_cores());
The problem is that when I run this it shows me a segmentation fault. This happen on this line:
iterator[i].green = func(iterator[i].green);
What I really don't understand is that i = 2 or more when this happens. It doesn't crash from the first time. Even if I try to call only a single thread the result is the same.
pppm_color_chunk_pixel accepts a copy of ppm_pixel. Since it is copied by value, passing *iterator to it will cause only one element to be copied. Iterating over anything after &start_pixel will fail.
Since std::thread doesn't pass objects by reference, you also need a reference-wrapper for this.
void pppm_color_chunk_pixel(ppm_pixel_func func, ppm_pixel& start_pixel, unsigned int count) {
ppm_pixel* iterator = &start_pixel;
for (unsigned int i = 0; i < count; ++i) {
iterator[i].red = func(iterator[i].red);
iterator[i].green = func(iterator[i].green);
iterator[i].blue = func(iterator[i].blue);
}
Calling it:
for (int j = 0; j < threads; ++j) {
th[j] = std::thread(pppm_color_chunk_pixel, func, std::ref(*iterator), count_for_thread);
iterator = &iterator[count_for_thread];
}
I have not tested it, but I guess this is your problem.

Initializing an Array C++

My code is trying to implement the union-find algorithm and I have the id[] array and the sz[] array. I initialize them in the Union-Find constructor, but once I try to use those arrays in the methods within the Union-Find class, it changes all the array values to 1. I don't understand why. Is there something obvious that I'm missing??
H File
class UnionFind{
public:
UnionFind(int size);
void join(int x, int y);
int connected(int x, int y);
int find(int x);
private:
int size;
int id[];
int sz[];
};
CPP File
UnionFind::UnionFind(int size){
this->id[size] = id[size];
for(int i = 0; i < size; i++){
id[i] = i;
}
for(int i = 0; i < size; i++){
sz[i] = 1;
}
}
int UnionFind::find(int l){
//Path Compression Finding the Root
for(int i = 0; i < 5; i++){
}
while(l != id[l]){
id[l] = id[id[l]];
l = id[l];
}
return l;
}
void UnionFind::join(int x, int y){
int m = find(x);
int n = find(y);
if(sz[m] < sz[n]){
id[m] = n;
sz[n] += sz[m];
}
else{
id[n] = m;
sz[m] += sz[n];
}
}
int UnionFind::connected(int x, int y){
if(find(x) == find(y)){
return 1;
}
else{
return 0;
}
}
From the comments.
you can't have int id[] as a class member,
use std::vector (resize and fill in constructor),
your forgot to set member size in constructor,
your find algorithm uses path halving not path compression (this does not affect the running time).
Side note: you can use a single array/vector to implement your disjoint set data structure.

Use function from another class or struct in a function within this class

I am creating a hash table and need to have this chained hash table tested with different hash functions.
I have hash structs such as
struct Hasher {
virtual int hash(std::string s, int N) = 0;
};
struct SumHasher : Hasher {
int hash(std::string s, int N){
int result = 0;
for (int i=0; i<s.size(); ++i)
result += s[i];
return int (std::abs((int)result)) % N;
}
};
struct ProdHasher : Hasher {
int hash(std::string s, int N) {
int result = 1;
for (int i=0; i<s.size(); ++i)
result *= s[i];
return int (std::abs((int)result)) % N;
}
};
struct ShiftHasher : Hasher {
int hash(std::string s, int N){
const int shift = 6; unsigned z = 0;
const int mask = ~z >> (32-shift); // lower 6 bits on
int result = 0;
for (int i = 0; i < s.length(); i++)
result = (result << shift) | (s[i] & mask);
return int (std::abs((int)result)) % N;
}
};
Now how can I use this functions within the Hashtable class by creating a struct hash type then passing that object to the constructor
class ChainedHashTable
{
ListNode **T; // array of linked lists
int capacity;
public:
Hasher *myhash;
int info;
ChainedHashTable(int numberOfChains, Hasher *myHasher){
myhash = hasher;
capacity = numberOfChains;
T = new ListNode* [capacity];
for (int i=0; i<capacity; ++i)
T[i] = NULL;
}
.......
void ChainedHashTable::insert(std::string key, int info){
int h = myhash::hash(key, capacity);
T[h] = ListNode::make(key, info, T[h]);
}
you should use:
myhash->hash(key, capacity)

Segfault error when calling a method through pointer

I have a baseclass called gridObject
Here's the header file:
#ifndef ITEM_H
#define ITEM_H
class gridObject
{
public:
gridObject();
virtual ~gridObject();
virtual int get_GridID() = 0;
virtual int get_x() = 0;
virtual int get_y() = 0;
virtual int get_direction() = 0;
void set_x(int x);
void set_y(int y);
void set_direction(unsigned int direction);
protected:
private:
int _x;
int _y;
unsigned int _direction;
};
#endif // ITEM_H
I have a subclass called player
Here's the get_GridID() method in the class file:
int player::get_GridID() { return 2; }
There's also a grid class that keeps track of all the objects on it via a 2d vector. In the header file, there's that vector:
private:
vector<vector<gridObject*> > _position;
Here are the methods for setting and getting an object at a specific position, respectively:
void grid::setGridPosition(int x, int y, gridObject* obj) { _position[y][x] = obj; }
gridObject* grid::getGridPosition(int x, int y) { return _position[y][x]; }
The problem I'm having is here:
int main()
{
grid * gr = new grid(10, 10);
player p(0, 0, 100);
gridObject * go = &p;
gr->setGridPosition(0, 0, go);
cout << gr->getGridPosition(0, 0)->get_GridID();
return 0;
}
It crashes at: cout << gr->getGridPosition(0, 0)->get_GridID();
I have included all of the appropriate header files.
EDIT: Here is the constructor for grid and the initialization of _position:
grid::grid(int width, int length)
{
setSize(width, length);
}
void grid::setSize(int width, int length)
{
setLength(length);
setWidth(width);
}
void grid::setLength(int val) { _position.resize(val); }
void grid::setWidth(int val)
{
for(unsigned int i = 0; i < _position.size() - 1; i++)
for(unsigned int j = 0; j < _position.at(i).size() - 1; j++)
_position.at(i).resize(val);
}
You're working with vector of vectors:
vector<vector<gridObject*> > _position;
but the way you initialize _position is following:
_position.resize(length);
for(unsigned int i = 0; i < _position.size() - 1; i++)
for(unsigned int j = 0; j < _position.at(i).size() - 1; j++)
_position.at(i).resize(width);
Note that the first resize constructs length objects of type vector<gridObject*>. Then you are iterating not through these newly-constructed vectors, but rather their elements (second nested loop), which in this case causes that the line _position.at(i).resize(width); is never executed and thus _position[y][x] = obj tries to access the invalid memory resulting in undefined behavior that you observe as segmentation fault.
Try this instead (in grid::setSize):
_position.resize(length);
for(unsigned int i = 0; i < _position.size() - 1; ++i)
_position[i].resize(width);
and also consider using typedef for creating an alias for std::vector<gridObject*> :)