resizing boost::multi_array to match another - c++

I need to resize one multi_array to the size of another.
In Blitz++ I could just do
arr1.resize(arr2.shape());
Is there a multi_array solution of similar length? Because
arr1.resize(boost::extents[arr2.shape()[0]][arr2.shape()[1]]);
seems a little long and arduous.

You can use the shape() member. Sadly it cannot directly serve as an ExtentList (it doesn't model the Collection concept) but it's easy to make it into one:
using MA = multi_array<double, 2>;
MA ma(extents[12][34]);
auto& ma_shape = reinterpret_cast<boost::array<size_t, MA::dimensionality> const&>(*ma.shape());
So that
// demo
std::cout << "[" << ma_shape[0] << "][" << ma_shape[1] << "]\n";
Prints [12][34].
Now, ma_shape can directly be used to reshape/resize another array:
Live On Coliru
#include <boost/multi_array.hpp>
#include <iostream>
int main() {
using namespace boost;
using MA = multi_array<double, 2>;
MA ma(extents[12][34]);
auto& ma_shape = reinterpret_cast<boost::array<size_t, MA::dimensionality> const&>(*ma.shape());
// demo
std::cout << "[" << ma_shape[0] << "][" << ma_shape[1] << "]\n";
// resize
MA other;
assert(!std::equal(ma_shape.begin(), ma_shape.end(), other.shape()));
other.resize(ma_shape);
assert(std::equal(ma_shape.begin(), ma_shape.end(), other.shape()));
// reshape
other.resize(extents[1][12*34]);
assert(!std::equal(ma_shape.begin(), ma_shape.end(), other.shape()));
other.reshape(ma_shape);
assert(std::equal(ma_shape.begin(), ma_shape.end(), other.shape()));
}

I think this is another oversight of Boost.MultiArray. I have written a bunch of "utility" functions that allows to take the shape (dimension sizes), base indices (e.g. 0 or 1 for each dimension) and extensions (base indices and sizes in each dimension).
namespace boost{
template<class MultiArray>
detail::multi_array::extent_gen<MultiArray::dimensionality>
extension(MultiArray const& ma){ //this function is adapted from
typedef detail::multi_array::extent_gen<MultiArray::dimensionality> gen_type;
gen_type ret;
typedef typename gen_type::range range_type;
for(int i=0; i != MultiArray::dimensionality; ++i)
ret.ranges_[i] = range_type(ma.index_bases()[i], ma.index_bases()[i]+ma.shape()[i]);
return ret;
}
}
Which is later used as:
boost::multi::array<double, 3> m(boost::multi::extents[3][4][5]);
boost::multi::array<double, 3> n(extension(m)); // n takes the extension (and shape) of m
(If the base indexes are not zero it also works. It works also for view and other multi_array-type classes.)

Related

Iterating over more than one seq. container in C++11

I need a piece of advice for the following situation - I can't figure it out for hours:
How to walk through more than one seq . containers of same size (here: two vectors) in a simple way?
int main() {
int size = 3;
std::vector<int> v1{ 1, 2, 3 }, v2{ 6, 4, 2 };
// old-fashioned - ok
for (int i = 0; i < size; i++) {
std::cout << v1[i] << " " << v2[i] << std::endl;
}
// would like to do the same as above with auto range-for loop
// something like this - which would be fine for ONE vector.
// But this does not work. Do I need a hand-made iterator instead?
for (const auto& i:v1,v2) {
std::cout << i << " " << i << std::endl;
}
return EXIT_SUCCESS;
}
Thank you!
There is boost::combine() in Boost.Range that allows one to write
#include <iostream>
#include <iterator>
#include <vector>
#include <boost/range/combine.hpp>
int main()
{
std::vector<int> v1{ 1, 2, 3 }, v2{ 6, 4, 2 };
for (auto&& t : boost::combine(v1, v2))
std::cout << t.get<0>() << " " << t.get<1>() << "\n";
}
Live Example.
If you don't like to rely on this, you can spell out the combine() functionality yourself with Boost.Iterator's zip_iterator and Boost.Range's iterator_range and a little bit of C++14 deduced return-types:
template<class... Ranges>
auto combine(Ranges const&... ranges)
// add -> decltype( boost::make_iterator_range(...) ) in C++11
{
return boost::make_iterator_range(
boost::make_zip_iterator(boost::make_tuple(begin(ranges)...)),
boost::make_zip_iterator(boost::make_tuple(end(ranges)...))
);
}
Live Example.
Explanation: boost::make_zip_iterator creates a boost::tuple of iterators into your input ranges, and overloads all the usual operator++ and operator* that you know and love from regular iterators. The iterator_range then wraps two of these zip_iterators into a package with a begin() and end() function that allows it to be used by the C++11 range-for loop. It generalizes to more than two input ranges as well. You can unpack the K-th element from a tuple with the .get<K> member function.
The range-based for loop was designed as a convenience for iterating one range, because it's by far the most common case. If you need to iterate multiple ranges, which is not that most common case, you can still do it the traditional way:
for (auto i1 = begin(v1), i2 = begin(v2), e = end(v1); i1 != e; ++i1, ++i2)
{
// processing
}

Insert into boost::BIMAP using BOOST::associative property map ... failed

With reference to my previously asked question about boost::bimaps and boost associative property maps interface here, I want to use Put and Get helper functions for my bimap.
With reference to a sample code given here, I tried to add the following and i get a long compile error for assertion failed ... Here is the code :
#include <boost/bimap.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/bimap/property_map/set_support.hpp>
#include <iostream>
using namespace boost;
int main()
{
typedef int vertex_descriptor_t;
typedef boost::bimaps::bimap< vertex_descriptor_t, size_t > vd_idx_bimap_t;
typedef boost::associative_property_map<vd_idx_bimap_t::left_map> asso_vd_idx_bimap_t;
// define bimap
vd_idx_bimap_t my_bimap;
asso_vd_idx_bimap_t my_asso_bimap(my_bimap.left);
typedef typename vd_idx_bimap_t::value_type value_type;
my_bimap.insert( value_type( 1, 100 ) );
// print bimap
for(auto t = my_bimap.left.begin(); t != my_bimap.left.end(); ++t)
std::cout << t->first << " " << t->second << "\n";
int z = 1;
std::cout << "value = " << get ( my_bimap.left, z ) << std::endl; // prints correctly value = 100
// ERROR here .
boost::put( my_asso_bimap, 2, 19 );
}
It gives error as: ( a long list. but i have just put a snippet )
cannot convert âboost::bimaps::detail::non_mutable_data_unique_map_view_access<Derived, Tag, BimapType>::operator[](const CompatibleKey&)::BIMAP_STATIC_ERROR__OPERATOR_BRACKET_IS_NOT_SUPPORTED360::assert_arg<long unsigned int>()â (type âmpl_::failed************ (boost::bimaps::detai
There is also one error which gives me error at line number 364 of the file (property_map.hpp) in boost
put(const put_get_helper<Reference, PropertyMap>& pa, K k, const V& v)
{
static_cast<const PropertyMap&>(pa)[k] = v;
}
I understand the error that associative map cannot mutate the data as it references to the left map view . but How do I use put and get helper functions ?
I can use GET (my_bimap.left, z ) functions, but I am not able to use PUT function. I wanted to use associative property map for get and put functions to operate on actual bimap so that i dont have to use insert( value_type() )...
I hope I am clear enough for my problem. Please suggest.
In general you cannot update bimap entries via iterators:
The relations stored in the Bimap will not be in most cases modifiable directly by iterators because both sides are used as keys of key-based sets. When a bimap left view iterator is dereferenced the return type is signature-compatible with a std::pair< const A, const B >.
So there's your answer. Likewise, you couldn't
my_bimap.left[2] = 19;
http://www.boost.org/doc/libs/release/libs/bimap/doc/html/boost_bimap/the_tutorial/differences_with_standard_maps.html#boost_bimap.the_tutorial.differences_with_standard_maps.iterator__value_type
Now, reading a bit more on there leads me to "suspect" the following solution:
typedef bm::bimap< vertex_descriptor_t, bm::list_of<size_t> > vd_idx_bimap_t;
Disclaimer: I don't know about the semantics that this changes (?) but it at least appears to support writable references. The below sample prints
1 100
value = 100
1 100
2 42
See it Live On Coliru
Full Listing
#include <boost/bimap.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/bimap/property_map/set_support.hpp>
#include <boost/bimap/list_of.hpp>
#include <iostream>
using namespace boost;
int main()
{
typedef int vertex_descriptor_t;
namespace bm = boost::bimaps;
typedef bm::bimap< vertex_descriptor_t, bm::list_of<size_t> > vd_idx_bimap_t;
typedef boost::associative_property_map<vd_idx_bimap_t::left_map> asso_vd_idx_bimap_t;
// define bimap
vd_idx_bimap_t my_bimap;
asso_vd_idx_bimap_t my_asso_bimap(my_bimap.left);
typedef typename vd_idx_bimap_t::value_type value_type;
my_bimap.insert( value_type( 1, 100 ) );
// print bimap
for(auto t = my_bimap.left.begin(); t != my_bimap.left.end(); ++t)
std::cout << t->first << " " << t->second << "\n";
int z = 1;
std::cout << "value = " << get ( my_bimap.left, z ) << std::endl; // prints correctly value = 100
boost::put( my_asso_bimap, 2, 42 );
for(auto t = my_bimap.left.begin(); t != my_bimap.left.end(); ++t)
std::cout << t->first << " " << t->second << "\n";
}

Can I use a vector with the same functionality as a static array?

just a quick one:
I plan to have an array of AVL Trees (for an assignment, as you imagined - does anyone ever use AVL trees apart from data structures students anyway?) and I was wondering if I could use a nice vector - and take advantage of the for(auto i : vect) c++ 11 functionality.
What I want to do: AVLTree array of 1.000.000 elements so I can check in CONSTANT time if the tree exists or not (array position will be NULL or not)
AVLTree_GeeksforGeeks **AVLArray = new (AVLTree_GeeksforGeeks*)[1000000];
for(int i=0; i<1000000; i++){ AVLArray[i] = nullptr; } //init everything to null
//do stuff with AVL trees
//...
if(AVLTree[52000]!=nullptr)
{
cout << "tree exists!\n";
}
Is there an equivalent with vectors, that will allow me constant time of searching for a tree? All the examples I've seen use vector.push_back() and vector.find() to search.
You can use std::vector as suggested by Exceptyon:
std::vector<unique_ptr<AVLTree>> trees(1000000);
by using also the smart pointers implemented in c++11. If your concern is dynamic resizing keep in mind that you can can reserve an initial amount of storage when you create the vector (by passing it as a parameter in the constructor) or via the resize member.
If your concern is random access to its objects, rest assured that the operator[] has O(1) complexity.
If you know the total capacity of the container at compile time you could also consider using c++11's std::array which provides the same for each functionality as well as the same constant time access to its elements.
std::array<unique_ptr<AVLTree>, 1000000> trees;
vector will work because they have an overloaded operator[] that guarantee constant time access to the nth element.
But your code is not clear:
AVLTree_GeeksforGeeks *AVLArray = new AVLTree_GeeksforGeeks[1000000];
for(int i=0; i<1000000; i++){ AVLArray[i] = nullptr; } //init everything to null
If you set to nullptr, then you need a pointer. Is AVLTree_GeeksforGeeks a typedef on a pointer ? I assume it is not the case, and that there is a typo -- otherwise you just have to remove this typedef definition to use std::unique_ptr<TheRealTyp>. So to clarify, I suppose your code is really:
AVLTree_GeeksforGeeks **AVLArray = new (AVLTree_GeeksforGeeks*)[1000000];
for(int i=0; i<1000000; i++){ AVLArray[i] = nullptr; } //init everything to null
In that case, as suggested you should use a std::vector<std::unique_ptr<AVLTree_GeeksforGeeks>>, and you won't have to initialize it to nullptr and the test of nullity changed for a direct "test" of std::unique_ptr:
std::vector<std::unique_ptr<AVLTree_GeeksforGeeks>> AVLArray(100000);
// Do stuff with AVL trees
if (AVLArray[52000])
{
cout << "tree exists!\n";
}
Now, how to use a std::vector<std::unique_ptr<X>> ?
Setting a value in the already allocated zone: AVLArray[5200] = std::unique_ptr(new AVLTree_GeeksforGeeks));
Setting a entry to null: AVLArray[5200].reset()
If you need to add something (the vector will grow): AVLArray.push_back(std::unique_ptr(new AVLTree_GeeksforGeeks));
To iterate over use for (auto& elem: AVLArray). The & is mandatory otherwise a copy construcotr is called and std::unique_ptr forbids this.
Here a example:
#include <iostream>
#include <vector>
#include <memory>
// boost
#include <boost/range/algorithm/for_each.hpp>
#include <boost/range/adaptor/filtered.hpp>
class A {};
int main(int argc, char const *argv[])
{
std::vector<std::unique_ptr<A>> vector;
vector.resize(10000);
// Adding some values
if (!vector[100])
{
std::cout << "Adding vector[100]" << std::endl;
vector[100] = std::unique_ptr<A>(new A);
}
if (!vector[1000])
{
std::cout << "Adding vector[1000]" << std::endl;
vector[1000] = std::unique_ptr<A>(new A);
}
// Removing one
if (vector[100])
{
std::cout << "Removing vector[100]" << std::endl;
vector[100].reset();
}
std::cout << "Testing element." << std::endl;
auto printer = [](const std::unique_ptr<A>& elem) {
std::cout << "There is an elem !" << std::endl; };
// use auto& otherwise use unique_ptr(const unique_ptr&) that has been
// deleted)
for (auto& elem: vector)
{
if (elem)
{
printer(elem);
}
}
std::cout << "for_each element with filtering." << std::endl;
auto is_null = [](const std::unique_ptr<A>& elem) { return (bool) elem; };
// Just because I move boost range !
boost::for_each(vector | boost::adaptors::filtered(is_null), printer);
std::cout << "end !" << std::endl;
return 0;
}

C++ class specialiation when dealing with STL containers

I'd like a function to return the size in bytes of an object for fundamental types. I'd also like it to return the total size in bytes of an STL container. (I know this is not necessarily the size of the object in memory, and that's okay).
To this end, I've coded a memorysize namespace with a bytes function such that memorysize::bytes(double x) = 8 (on most compilers).
I've specialized it to correctly handle std::vector<double> types, but I don't want to code a different function for each class of the form std::vector<ANYTHING>, so how do I change the template to correctly handle this case?
Here's the working code:
#include <iostream>
#include <vector>
// return the size of bytes of an object (sort of...)
namespace memorysize
{
/// general object
template <class T>
size_t bytes(const T & object)
{
return sizeof(T);
}
/// specialization for a vector of doubles
template <>
size_t bytes<std::vector<double> >(const std::vector<double> & object)
{
return sizeof(std::vector<double>) + object.capacity() * bytes(object[0]);
}
/// specialization for a vector of anything???
}
int main(int argc, char ** argv)
{
// make sure it works for general objects
double x = 1.;
std::cout << "double x\n";
std::cout << "bytes(x) = " << memorysize::bytes(x) << "\n\n";
int y = 1;
std::cout << "int y\n";
std::cout << "bytes(y) = " << memorysize::bytes(y) << "\n\n";
// make sure it works for vectors of doubles
std::vector<double> doubleVec(10, 1.);
std::cout << "std::vector<double> doubleVec(10, 1.)\n";
std::cout << "bytes(doubleVec) = " << memorysize::bytes(doubleVec) << "\n\n";
// would like a new definition to make this work as expected
std::vector<int> intVec(10, 1);
std::cout << "std::vector<int> intVec(10, 1)\n";
std::cout << "bytes(intVec) = " << memorysize::bytes(intVec) << "\n\n";
return 0;
}
How do I change the template specification to allow for the more general std::vector<ANYTHING> case?
Thanks!
Modified your code accordingly:
/// specialization for a vector of anything
template < typename Anything >
size_t bytes(const std::vector< Anything > & object)
{
return sizeof(std::vector< Anything >) + object.capacity() * bytes( object[0] );
}
Note that now you have a problem if invoking bytes with an empty vector.
Edit: Scratch that. If I remember your previous question correctly, then if you get a vector of strings then you would like to take into account the size taken by each string. So instead you should do
/// specialization for a vector of anything
template < typename Anything >
size_t bytes(const std::vector< Anything > & object)
{
size_t result = sizeof(std::vector< Anything >);
foreach elem in object
result += bytes( elem );
result += ( object.capacity() - object.size() ) * sizeof( Anything ).
return result;
}

Printing an array in C++?

Is there a way of printing arrays in C++?
I'm trying to make a function that reverses a user-input array and then prints it out. I tried Googling this problem and it seemed like C++ can't print arrays. That can't be true can it?
Just iterate over the elements. Like this:
for (int i = numElements - 1; i >= 0; i--)
cout << array[i];
Note: As Maxim Egorushkin pointed out, this could overflow. See his comment below for a better solution.
Use the STL
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <ranges>
int main()
{
std::vector<int> userInput;
// Read until end of input.
// Hit control D
std::copy(std::istream_iterator<int>(std::cin),
std::istream_iterator<int>(),
std::back_inserter(userInput)
);
// ITs 2021 now move this up as probably the best way to do it.
// Range based for is now "probably" the best alternative C++20
// As we have all the range based extension being added to the language
for(auto const& value: userInput)
{
std::cout << value << ",";
}
std::cout << "\n";
// Print the array in reverse using the range based stuff
for(auto const& value: userInput | std::views::reverse)
{
std::cout << value << ",";
}
std::cout << "\n";
// Print in Normal order
std::copy(userInput.begin(),
userInput.end(),
std::ostream_iterator<int>(std::cout,",")
);
std::cout << "\n";
// Print in reverse order:
std::copy(userInput.rbegin(),
userInput.rend(),
std::ostream_iterator<int>(std::cout,",")
);
std::cout << "\n";
}
May I suggest using the fish bone operator?
for (auto x = std::end(a); x != std::begin(a); )
{
std::cout <<*--x<< ' ';
}
(Can you spot it?)
Besides the for-loop based solutions, you can also use an ostream_iterator<>. Here's an example that leverages the sample code in the (now retired) SGI STL reference:
#include <iostream>
#include <iterator>
#include <algorithm>
int main()
{
short foo[] = { 1, 3, 5, 7 };
using namespace std;
copy(foo,
foo + sizeof(foo) / sizeof(foo[0]),
ostream_iterator<short>(cout, "\n"));
}
This generates the following:
./a.out
1
3
5
7
However, this may be overkill for your needs. A straight for-loop is probably all that you need, although litb's template sugar is quite nice, too.
Edit: Forgot the "printing in reverse" requirement. Here's one way to do it:
#include <iostream>
#include <iterator>
#include <algorithm>
int main()
{
short foo[] = { 1, 3, 5, 7 };
using namespace std;
reverse_iterator<short *> begin(foo + sizeof(foo) / sizeof(foo[0]));
reverse_iterator<short *> end(foo);
copy(begin,
end,
ostream_iterator<short>(cout, "\n"));
}
and the output:
$ ./a.out
7
5
3
1
Edit: C++14 update that simplifies the above code snippets using array iterator functions like std::begin() and std::rbegin():
#include <iostream>
#include <iterator>
#include <algorithm>
int main()
{
short foo[] = { 1, 3, 5, 7 };
// Generate array iterators using C++14 std::{r}begin()
// and std::{r}end().
// Forward
std::copy(std::begin(foo),
std::end(foo),
std::ostream_iterator<short>(std::cout, "\n"));
// Reverse
std::copy(std::rbegin(foo),
std::rend(foo),
std::ostream_iterator<short>(std::cout, "\n"));
}
There are declared arrays and arrays that are not declared, but otherwise created, particularly using new:
int *p = new int[3];
That array with 3 elements is created dynamically (and that 3 could have been calculated at runtime, too), and a pointer to it which has the size erased from its type is assigned to p. You cannot get the size anymore to print that array. A function that only receives the pointer to it can thus not print that array.
Printing declared arrays is easy. You can use sizeof to get their size and pass that size along to the function including a pointer to that array's elements. But you can also create a template that accepts the array, and deduces its size from its declared type:
template<typename Type, int Size>
void print(Type const(& array)[Size]) {
for(int i=0; i<Size; i++)
std::cout << array[i] << std::endl;
}
The problem with this is that it won't accept pointers (obviously). The easiest solution, I think, is to use std::vector. It is a dynamic, resizable "array" (with the semantics you would expect from a real one), which has a size member function:
void print(std::vector<int> const &v) {
std::vector<int>::size_type i;
for(i = 0; i<v.size(); i++)
std::cout << v[i] << std::endl;
}
You can, of course, also make this a template to accept vectors of other types.
Most of the libraries commonly used in C++ can't print arrays, per se. You'll have to loop through it manually and print out each value.
Printing arrays and dumping many different kinds of objects is a feature of higher level languages.
It certainly is! You'll have to loop through the array and print out each item individually.
This might help
//Printing The Array
for (int i = 0; i < n; i++)
{cout << numbers[i];}
n is the size of the array
std::string ss[] = { "qwerty", "asdfg", "zxcvb" };
for ( auto el : ss ) std::cout << el << '\n';
Works basically like foreach.
My simple answer is:
#include <iostream>
using namespace std;
int main()
{
int data[]{ 1, 2, 7 };
for (int i = sizeof(data) / sizeof(data[0])-1; i >= 0; i--) {
cout << data[i];
}
return 0;
}
You can use reverse iterators to print an array in reverse:
#include <iostream>
int main() {
int x[] = {1,2,3,4,5};
for (auto it = std::rbegin(x); it != std::rend(x); ++it)
std::cout << *it;
}
output
54321
If you already reversed the array, you can replace std::rbegin and std::rend with std::begin/std::end, respectively, to iterate the array in forward direction.
It's quite straightforward to copy the array's elements to a suitable output iterator. For example (using C++20 for the Ranges version):
#include <algorithm>
#include <array>
#include <iostream>
#include <iterator>
template<typename T, std::size_t N>
std::ostream& print_array(std::ostream& os, std::array<T,N> const& arr)
{
std::ranges::copy(arr, std::ostream_iterator<T>(os, ", "));
return os;
}
Quick demo:
int main()
{
std::array example{ "zero", "one", "two", "three", };
print_array(std::cout, example) << '\n';
}
Of course it's more useful if we can output any kind of collection, not only arrays:
#include <algorithm>
#include <iterator>
#include <iosfwd>
#include <ranges>
template<std::ranges::input_range R>
std::ostream& print_array(std::ostream& os, R const& arr)
{
using T = std::ranges::range_value_t<R>;
std::ranges::copy(arr, std::ostream_iterator<T>(os, ", "));
return os;
}
The question mentions reversing the array for printing. That's easily achieved by using a view adapter:
print_array(std::cout, example | std::views::reverse) << '\n';
// Just do this, use a vector with this code and you're good lol -Daniel
#include <Windows.h>
#include <iostream>
#include <vector>
using namespace std;
int main()
{
std::vector<const char*> arry = { "Item 0","Item 1","Item 2","Item 3" ,"Item 4","Yay we at the end of the array"};
if (arry.size() != arry.size() || arry.empty()) {
printf("what happened to the array lol\n ");
system("PAUSE");
}
for (int i = 0; i < arry.size(); i++)
{
if (arry.max_size() == true) {
cout << "Max size of array reached!";
}
cout << "Array Value " << i << " = " << arry.at(i) << endl;
}
}
If you want to make a function that prints every single element in an array;
#include <iostream>
using namespace std;
int myArray[] = {1,2,3,4, 77, 88};
void coutArr(int *arr, int size){
for(int i=0; i<size/4; i++){
cout << arr[i] << endl;
}
}
int main(){
coutArr(myArray, sizeof(myArray));
}
The function above prints every single element in an array only, not commas etc.
You may be wondering "Why sizeoff(arr) divided by 4?". It's because cpp prints 4 if there's only a single element in an array.