VexCL: Index of maximum value in a vexcl vector - c++

How can I find the index of the maximum value in a VexCL vector? I can find the maximum value:
int h[] = {3, 2, 1, 5, 4};
vex::vector<int> d(ctx, 5);
vex::copy(h, d);
vex::Reductor<int, vex::MAX> max(ctx.queue());
int m = max(d);
Which gives m = 5 but is there a way to find the index of the maximum value, ind = 3?

You will need to
encode both vector value and vector position in a vexcl expression, and
create custom functor for vex::Reductor that would reduce the above expression based on its first component.
Here is the working code:
#include <iostream>
#include <vector>
#include <vexcl/vexcl.hpp>
// This function converts two integers to cl_int2
VEX_FUNCTION(cl_int2, make_int2, (int, x)(int, y),
int2 v = {x, y};
return v;
);
// This struct compares OpenCL vector types by the first component.
struct MAX0 {
template <class Tn>
struct impl {
typedef typename vex::cl_scalar_of<Tn>::type T;
// Initial value.
static Tn initial() {
Tn v;
if (std::is_unsigned<T>::value)
v.s[0] = static_cast<T>(0);
else
v.s[0] = -std::numeric_limits<T>::max();
return v;
}
// Device-side function call operator
struct device : vex::UserFunction<device, Tn(Tn, Tn)> {
static std::string name() { return "MAX_" + vex::type_name<Tn>(); }
static std::string body() { return "return prm1.x > prm2.x ? prm1 : prm2;"; }
};
// Host-side function call operator
Tn operator()(Tn a, Tn b) const {
return a.s[0] > b.s[0] ? a : b;
}
};
};
int main(int argc, char *argv[]) {
vex::Context ctx( vex::Filter::Env );
std::vector<int> h = {3, 2, 1, 5, 4};
vex::vector<int> d(ctx, h);
// Create reductor based on MAX0 operation,
// then reduce an expression that encodes both value and position of a
// vector element:
vex::Reductor<cl_int2, MAX0> max(ctx);
cl_int2 m = max(make_int2(d, vex::element_index()));
std::cout << "max value of " << m.s[0] << " at position " << m.s[1] << std::endl;
}
This outputs
max value of 5 at position 3

Related

List initialization of const and array structure fields

Just recently started C++ programming for micro-controllers, and I've ran into situations* where it would be convenient to have a non-static const field on a struct that is always guaranteed to have a fixed value (same for every instance of the sturct, ever).
Given a struct
struct S {
const uint8_t c; // Should always be 42
char v;
uint32_t arr[4];
}
I'd like c to be a constant value, and the same constant value every time. I would love to be able to use the convenience of brace initializer lists, for setting v and the members of arr like
S some_var = {'v', { 0, 1, 2, 3 } };
Since I'd like c to be a constant, I'm under the impression that I have to use an initializer list for setting c, such as S() : c(42) {}, which works just fine, as long as I don't try to also initialize arr, in which case I'm lost on how the list should look like. Is this doable using C++11? (Also interested in an answer if this is not doable in C++11, but in some newer standard.)
Example code:
#include <stdio.h>
#include <stdint.h>
struct S {
const uint8_t c; // Should always be 42 on every instance
// of the struct due to hardware shenanigance
// (i.e. this struct is the representation of a register value)
char v;
uint32_t arr[4];
// This allows using "S s1;"
S() : c(42), v('a'), arr{} {}
// This allows using "S s2 = { 'v', 0, 1, 2, 3 };" works but it's clumsy:
S(uint32_t v, uint32_t arr0, uint32_t arr1, uint32_t arr2, uint32_t arr3) :
c(42), v(v), arr{ arr0, arr1, arr2, arr3 } {}
// I would like to do something along the lines of "S s2 = { 'v', { 0, 1, 2, 3 } };":
// S(uint32_t v, uint32_t arr[4] /*?*/) :
// c(42), v(v), arr{/*?*/} {}
};
// Main just for the sake of completeness
int main() {
// Works just fine
S s1;
printf("s1.c = %u\n", s1.c); // 42
printf("s1.v = '%c'\n", s1.v); // a
printf("s1.arr[3] = %u\n", s1.arr[3]); // 0
// Initialiation like this works with the line:12 signature:
S s2 = { 'v', 0, 1, 2, 3 };
// I'd like to initialize like this:
// S s2 = { 'v', { 0, 1, 2, 3 } };
printf("s2.c = %u\n", s2.c); // 42
printf("s2.v = '%c'\n", s2.v); // v
printf("s2.arr[3] = %u\n", s2.arr[3]); // 3
return 0;
}
*Context on why I'd want to do this: This might seem like a weird thing to want, since if the value is always the same, why bother storing it? Well imagine that the struct in question is a bitfield which corresponds to the register of an IC with which the micro-controller communicates. These registers sometimes have "reserved" fields, and the datasheet specifies what value you must write into these fields. From a programmer's point of view, it would be convenient if I never had to deal with setting said bits manually.
C++11 gives you std::array which is like a raw array, but comes with none of the "negatives" (array decay, can't copy). Using that you can get exactly what you want like
struct S {
const uint8_t c = 42;
char v = 'a';
std::array<uint32_t, 4> arr{};
// This allows using "S s1;"
S() {}
S(uint32_t v, std::array<uint32_t, 4> arr) : v(v), arr{arr} {}
};
// Main just for the sake of completeness
int main() {
// Works just fine
S s1;
printf("s1.c = %u\n", s1.c); // 42
printf("s1.v = '%c'\n", s1.v); // a
printf("s1.arr[3] = %u\n", s1.arr[3]); // 0
S s2 = { 'v', { 0, 1, 2, 3 } };
printf("s2.c = %u\n", s2.c); // 42
printf("s2.v = '%c'\n", s2.v); // v
printf("s2.arr[3] = %u\n", s2.arr[3]); // 3
return 0;
}
which outputs
s1.c = 42
s1.v = 'a'
s1.arr[3] = 0
s2.c = 42
s2.v = 'v'
s2.arr[3] = 3
If you absoluytley have to have a raw array in S then your other option is to use a std::initializer_list in the constructor. That would look like
struct S {
const uint8_t c = 42;
char v = 'a';
uint32_t arr[4]{};
// This allows using "S s1;"
S() {}
S(uint32_t v, std::initializer_list<uint32_t> data) : v(v)
{
int i = 0;
for (auto e : data)
arr[i++] = e;
}
};
// Main just for the sake of completeness
int main() {
// Works just fine
S s1;
printf("s1.c = %u\n", s1.c); // 42
printf("s1.v = '%c'\n", s1.v); // a
printf("s1.arr[3] = %u\n", s1.arr[3]); // 0
S s2 = { 'v', { 0, 1, 2, 3 } };
printf("s2.c = %u\n", s2.c); // 42
printf("s2.v = '%c'\n", s2.v); // v
printf("s2.arr[3] = %u\n", s2.arr[3]); // 3
return 0;
}
And you get the same results as the code using std::array.

How to count the equal elements of 2 different vectors in c++?

I am trying to find a way to count how many elements are equal in 2 different vectors of the same size in c++. The vectors hold structs and i want to compare the equality by a double variable of the struct shown on the example.
And to make it clear. I do NOT want to check if the 2 vectors are equal but only to count how many of their elements are.
The following doesn't work. It gives addresses instead of values. Also If I try to access the dist variable like pointsA[j].dist I get an error.
vector<struct PointWithDistance*> pointsA, pointsB;
//the struct
struct PointWithDistance {
Point *p;
double dist;
};
for (int j = 0; j < k; j++){
if (pointsA[j] == pointsB[j])
equalCount++;
}
vector<struct PointWithDistance*> pointsA, pointsB;
Did you mean to use pointers? If so, you have to do *(points[A]) (and b) because your current comparison compares the pointers, not their content.
Also, does the struct Point have an operator == so comparison on the type can be performed??
Do you want to force same positions? say, a vector {1,2,3} and a vector {2,3,4} by your algorithm will have 0 items equal, do you want that? If not, loop the first vector and use std::find (or std::upper_bound if the vector is sorted) on each element to the second vector.
Some quick code:
template <typename T=int> struct Point
{
T x,y;
bool operator==(const T& t) { return (x == t.x && y == t.y); }
};
std::vector<Point<>> p1 = {1,2,3};
std::vector<Point<>> p2 = {2,3,4};
for(auto& p : p1)
{
if (std::find(p2.begin(),p2.end(),p) != p2.end())
{
// similar++;
}
}
// or
assert(p1.size() == p2.size());
for(size_t i1 = 0 ; i1 < p1.size() ; i1++)
{
if (p1[i1] == p2[i1])
{
// equal++;
}
}
A generic solution to count the number of duplicates in 2 containers could look like this. Using std::transform_reduce to add (std::plus<>{}) the boolean result if an element was found in the container. Note how it can accep two different types of containers as long as their contained type stays the same (e.g. std::vector<int> and std::set<int>). The length of the containers don't have to be equal. There are two SFINAE implementations to differenciate between the case where T is a pointer and where it isn't:
#include <algorithm> //std::find, std::find_if
#include <cstddef> //std::size_t
#include <functional> //std::plus,
#include <iterator> //std::cbegin, std::cend
#include <numeric> //std::transform_reduce
#include <type_traits> //std::enable_if_t, std::is_pointer_v
namespace {
//core implementation for duplicate_count
template<class C, class F>
std::size_t duplicate_count_impl(const C& container, F pred) {
return std::transform_reduce(std::cbegin(container), std::cend(container), std::size_t{}, std::plus<>{}, pred);
}
}
//returns the number of duplicates in two (different) containers.
//overload for containers where T is a pointer type.
template<typename T, template <typename...> class C1, template <typename...> class C2, std::enable_if_t<std::is_pointer_v<T>>* = nullptr>
std::size_t duplicate_count(const C1<T>& a, const C2<T> &b) {
return duplicate_count_impl(b, [&](T ptr_b) -> bool {
return std::find_if(std::cbegin(a), std::cend(a), [&](T ptr_a) -> bool {
return *ptr_a == *ptr_b;
}) != std::cend(a);
});
}
//returns the number of duplicates in two (different) containers.
//overload for containers where T is not a pointer type.
template<typename T, template <typename...> class C1, template <typename...> class C2, std::enable_if_t<!std::is_pointer_v<T>>* = nullptr>
std::size_t duplicate_count(const C1<T>& a, const C2<T> &b) {
return duplicate_count_impl(b, [&](T n) -> bool {
return std::find(std::cbegin(a), std::cend(a), n) != std::cend(a);
});
}
#include <iostream>
#include <vector>
#include <list>
//[duplicate_count implementations]
struct Point {
int a, b;
bool operator==(const Point& other) const {
return this->a == a && this->b == other.b;
}
};
int main() {
{
std::list<int> v = { 1, 2, 7, 7 };
std::list<int> u = { 0, 1, 2, 7 };
std::cout << "list<int>\t number of duplicates: " << duplicate_count(v, u) << '\n';
}
{
auto[a, b, c, d] = std::make_tuple(0, 1, 2, 3);
std::vector<int*> v = { &b, &c, &d, &d };
std::vector<int*> u = { &a, &b, &c, &d };
std::cout << "vector<int*>\t number of duplicates: " << duplicate_count(v, u) << '\n';
}
{
auto[a, b, c, d] = std::make_tuple(
Point{ 0, 0 },
Point{ 1, 1 },
Point{ 2, 2 },
Point{ 4, 4 });
std::vector<Point*> v = { &b, &c, &d, &d };
std::vector<Point*> u = { &a, &b, &c, &d };
std::cout << "vector<Point*>\t number of duplicates: " << duplicate_count(v, u) << '\n';
}
}
list<int> number of duplicates: 3
vector<int*> number of duplicates: 3
vector<Point*> number of duplicates: 3
Your shown solution is good, fast and efficient.
It has some minor problem that can easily be resolved. In your definition vector<struct PointWithDistance*> pointsA, pointsB;, variables pointsA and pointsB are vectors, containing pointer to structs.
With pointsA[n] you will get a pointer to the struct. But you want the struct by itself. So you simply need to dereference the gotten pointer. And since you want to access a member of a struct (usually done with variable.member), you can use (*(pointsA[j])).dist or pointsA[j]->dist.
If the size of your vectors are guaranteed the same, then you simply need to update your code to
vector<struct PointWithDistance*> pointsA, pointsB;
//the struct
struct PointWithDistance {
Point *p;
double dist;
};
for (int j = 0; j < k; j++){
if (pointsA[j]->dist == pointsB[j]->dist)
equalCount++;
}
That is the only thing you were missing.
You can use the std::inner_product algorithm:
#include <iostream>
#include <numeric>
#include <vector>
int main () {
const std::vector a{7, 7, 7, 7};
const std::vector b{7, 6, 7, 7};
const auto equalCount = std::inner_product(
a.begin(), a.end(), b.begin(), 0,
std::plus<>(), std::equal_to<>()
);
std::cout << equalCount << " of the elements are equal.\n";
}
outputs
3 of the elements are equal.
It is a generalization of the standard inner product,
using the functions + (plus) and == (equal_to),
instead of + and *.
Thus it computes
0 + (a[0] == b[0]) + (a[1] == b[1]) + ....
This uses the fact that false/true can be interpreted as 0/1.

Adding contents to a variadic template type after instantiation

Current Source
At this point in my code I have this variadic template class:
template<typename ClassType, std::size_t... Args>
class Matrix {
private:
DimensionPack<Args...> dp;
public:
Matrix<ClassType, Args...>(){} // Default
// Public Access Members To Get Information From the DimensionPack which is based
// Not On The Type But Based On The Amount & Values Of This Template's Variadic Parameters
std::vector<unsigned int>& getDimensions() { return dp.dimensions; }
std::vector<unsigned int>& getEvenOrOdd() { return dp.even_or_odd; }
const unsigned int getNumberOfDimensions() const { return dp.total_dimensions; }
const unsigned int getTotalNumElements() const { return dp.total_elements; }
};
It uses this class and structure to do the needed calculations based on its variadic parameter list of values passed in (std::size_t...).
const unsigned int EVEN = 0;
const unsigned int ODD = 1;
struct MatrixDimensionOddOrEven {
const unsigned int even_or_odd;
explicit MatrixDimensionOddOrEven( unsigned int odd_or_even ) : even_or_odd( test( odd_or_even ) ) {}
private:
const unsigned int test( unsigned int value ) const {
if ( value == 0 ) {
std::ostringstream strStream;
strStream << __FUNCTION__ << "invalid number: " << value << " must be >= 1.";
Logger::log( strStream, Logger::TYPE_ERROR );
throw ExceptionHandler( strStream );
}
return ( ((value % 2) == 0) ? EVEN : ODD );
}
}; typedef MatrixDimensionOddOrEven MatDimOddEven;
template <std::size_t... Dims>
class DimensionPack {
public:
std::vector<std::size_t> dimensions;
std::vector<unsigned int> even_or_odd;
const std::size_t total_dimensions = sizeof...(Dims);
const std::size_t total_elements = countElements();
public:
DimensionPack() : dimensions{Dims...},
even_or_odd{ MatrixDimensionOddOrEven{Dims}.even_or_odd...} {
}
private:
std::size_t countElements() {
std::size_t val = 1; // Don't Init to 0 otherwise multiplication won't work here!
for ( std::size_t n = 0; n < dimensions.size(); n++ ) {
val *= dimensions.at( n );
}
return val;
}
};
At this point in my Matrix class I am able to successfully compile and get the results that are expected such as in these cases:
Examples Of Use:
Matrix<float, 1> mat1; // Single Element Matrix - Considered A Scalar Type
Matrix<float, 1,1...> mat1...; // Again - Single Element Matrix - Considered A Scalar Type
Matrix<float, n, m, 1, p> matNM1P; // Where n,m,p are > 1 makes that field of dimensionality flat such as a linear array or vector.
Matrix<float, 2,2> mat2x2; // creates a 2x2 Matrix with 4 elements of type float
Matrix<int, 3,3,3> mat3x3x3; // creates a 3x3x3 Volumetric Matrix with 27 elements of type int.
Matrix<type,n...> mat_multidimensional; // creates any higher order dimension of type.
I can pass them to this function to get the correct results and values:
template<typename type, std::size_t... dims>
void testMatrix( Matrix<type, dims...> matrix ) {
std::cout << "The Matrix Has " << matrix.getNumberOfDimensions() << " Total Dimensions:\n";
std::cout << "The Dimensions Are:\n";
for ( unsigned u = 0; u < matrix.getDimensions().size(); u++ ) {
std::cout << matrix.getDimensions()[u] << " ";
}
std::cout << std::endl;
std::cout << "The even and odd of each dimension are:\n";
for ( unsigned u = 0; u < matrix.getEvenOrOdd().size(); u++ ) {
std::cout << matrix.getEvenOrOdd()[u] << " ";
}
std::cout << std::endl;
std::cout << "The Matrix Has " << matrix.getTotalNumElements() << " total elements.\n\n";
}
Making my main.cpp look like this:
#include <Matrix.h>
int main() {
Matrix<float, 2, 3, 4> mat;
testMatrix( mat );
Matrix<int, 7, 9, 13, 15, 17> mat2;
testMatrix( mat2 );
Matrix<double, 255,255,255,255,255,255,255,255,255> mat9;
testMatrix( mat9 );
return 0;
}
Everything up to this point works fine and the results are expected.
The Goal
As you can see my Matrix class has a default constructor and now it is time to add contents to it. And this is where I'm sort of stuck.
For Example: If a user did the following they would have:
Matrix<float, 4,4,4> mat4x4x4; // A 3D Volumetric Matrix With 256 Elements
Matrix<float, 2,3,5> mat2x3x5; // A 3D Volumetric Matrix With 30 Elements
Matrix<float, 5,7,8,10> mat5x7x8x10; // A 4D Volumetric Matrix With 2800 Elements
Should I just accept a single vector<type> that has a fixed size that
matches the total amount of elements and create an indexing scheme?
Should I have nested <vector<vector<type>> where the amount of nested vectors matches the number of dimensions if the automation of doing such a thing can be done?
Should I create a helper structure that will nest up to 3 nested vectors then repeat that process if the automation of it can be done?
This is where I'm looking for good sound advice as to what my options should be and how it can easily be done.

Primitive array vs. Array template in C++

I got this question from the cracking the coding interview book. I was able to write this method in python and java. But when I tried to write it in c++, the compiler starts yelling at me. I think the problem is that in the main function, I had a array instantiated by a template but the function is taking in a primitive array. How should I instantiate a primitive array?
// Given a sorted array of positive integers with an empty spot (zero) at the
// end, insert an element in sorted order.
bool sortSortedArray(size_t arrInt[], size_t x)
{
size_t indexArr{0};
size_t insertNum{x};
while (x != 0) {
if (x < arrInt[indexArr]) {
size_t swapVal = arrInt[indexArr];
arrInt[indexArr];
insertNum = swapVal;
++indexArr;
}
}
return true;
}
// Test the sortSortedArray function.
int main()
{
array<size_t, 5> testArr{1, 4, 5, 8, 0};
if (sortSortedArray(testArr, 3)) {
return 0;
}
}
Either make testArr a primitive array:
int testArr[] = {1, 4, 5, 8, 0};
or call data() to get the underlying array:
if (sortSortedArray(testArr.data(), 3)) {
#include <cstddef>
#include <array>
#include <iostream>
// this is a function template because each std::array<> parameter set creates a
// a type and we need a function for each type (we know std::size_t is the element
// type so this is only parameterized on the size)
template<size_t ArrSize>
void sortSortedArray(
std::array<std::size_t, ArrSize>& arr,
const std::size_t insertNum)
{
// last position is known to be "empty"
arr[arr.size() - 1] = insertNum;
// swap value in last position leftwards until value to the left is less
auto pos = arr.size() - 1;
if (pos == 0)
return;
while (arr[pos - 1] > arr[pos])
{
const auto tmp = arr[pos - 1];
arr[pos - 1] = arr[pos];
arr[pos] = tmp;
--pos;
if (pos == 0)
return;
}
}
template<typename T, size_t N>
void printArray(const std::array<T, N>& r)
{
for (const auto i : r)
{
std::cout << i << " ";
}
std::cout << '\n';
}
int main()
{
std::array<std::size_t, 5> testArr{{1, 4, 5, 8, 0}};
printArray(testArr);
sortSortedArray(testArr, 3);
printArray(testArr);
}

remove arbitrary list of items from std::vector<std::vector<T> >

I have a vector of vectors, representing an array. I would like to remove rows efficiently, ie with minimal complexity and allocations
I have thought about building a new vector of vectors, copying only non-deleted rows, using move semantics, like this:
//std::vector<std::vector<T> > values is the array to remove rows from
//std::vector<bool> toBeDeleted contains "marked for deletion" flags for each row
//Count the new number of remaining rows
unsigned int newNumRows = 0;
for(unsigned int i=0;i<numRows();i++)
{
if(!toBeDeleted[i])
{
newNumRows++;
}
}
//Create a new array already sized in rows
std::vector<std::vector<T> > newValues(newNumRows);
//Move rows
for(unsigned int i=0;i<numRows();i++)
{
if(!toBeDeleted[i])
{
newValues[i] = std::move(values[i]);
}
}
//Set the new array and clear the old one efficiently
values = std::move(newValues);
Is this the most effective way?
Edit : I just figured that I could avoid allocating a new array by moving rows down iteratively, this could be slightly more efficient and code is much more simple:
unsigned int newIndex = 0;
for(unsigned int oldIndex=0;oldIndex<values.size();oldIndex++)
{
if(!toBeDeleted[oldIndex])
{
if(oldIndex!=newIndex)
{
values[newIndex] = std::move(values[oldIndex]);
}
newIndex++;
}
}
values.resize(newIndex);
Thanks!
This can be solved using a variation on the usual erase-remove idiom, with a lambda inside the std::remove_if that looks up the index of the current row inside an iterator range of to be removed indices:
#include <algorithm> // find, remove_if
#include <iostream>
#include <vector>
template<class T>
using M = std::vector<std::vector<T>>; // matrix
template<class T>
std::ostream& operator<<(std::ostream& os, M<T> const& m)
{
for (auto const& row : m) {
for (auto const& elem : row)
os << elem << " ";
os << "\n";
}
return os;
}
template<class T, class IdxIt>
void erase_rows(M<T>& m, IdxIt first, IdxIt last)
{
m.erase(
std::remove_if(
begin(m), end(m), [&](auto& row) {
auto const row_idx = &row - &m[0];
return std::find(first, last, row_idx) != last;
}),
end(m)
);
}
int main()
{
auto m = M<int> { { 0, 1, 2, 3 }, { 3, 4, 5, 6 }, { 6, 7, 8, 9 }, { 1, 0, 1, 0 } };
std::cout << m << "\n";
auto drop = { 1, 3 };
erase_rows(m, begin(drop), end(drop));
std::cout << m << "\n";
}
Live Example.
Note: because from C++11 onwards, std::vector has move semantics, shuffling rows around in your std::vector<std::vector<T>> is done using simple pointer manipulations, regardless of your type T (it would be quite different if you want column-deletion, though!).