Related
I am trying to create a symmetric matrix n x n matrix and fill it using a n*(n+1)/2 dimension array using the boost library in c++.
So far, I am able to create the matrix, and fill it with random values using the following code
#include <iostream>
#include <fstream>
#include </usr/include/boost/numeric/ublas/matrix.hpp>
#include </usr/include/boost/numeric/ublas/matrix_sparse.hpp>
#include </usr/include/boost/numeric/ublas/symmetric.hpp>
#include </usr/include/boost/numeric/ublas/io.hpp>
using namespace std;
int test_boost () {
using namespace boost::numeric::ublas;
symmetric_matrix<double, upper> m_sym (3, 3);
double filler[6] = {0, 1, 2, 3, 4, 5};
for (unsigned i = 0; i < m_sym.size1 (); ++ i)
for (unsigned j = i; j < m_sym.size2 (); ++ j)
m_sym (i, j) = filler[i+j*m_sym.size1()];
std::cout << m_sym << std::endl;
return 0;
}
What I am trying to do is fill the upper (or lower) part of the symmetric matrix using the values from the array filler. So the output upper symmetric matrix should be
| 0 | 1 | 2 |
------------------------------------------------
0 | 0 1 3
1 | 1 2 4
2 | 3 4 5
Any idea on how to do that?
I'd simplify this a bit by just keeping an iterator that traverses filler from start to end:
symmetric_matrix<double, upper> m_sym (3, 3);
double filler[6] = {0, 1, 2, 3, 4, 5};
assert(m_sym.size1() == m_sym.size2());
double const* in = std::begin(filler);
for (size_t i = 0; i < m_sym.size1(); ++ i)
for (size_t j = 0; j <= i && in != std::end(filler); ++ j)
m_sym (i, j) = *in++;
Prints: Live On Coliru
I'd personally suggest creating a helper function like:
Live On Wandbox
#include <iostream>
#include <fstream>
#include <boost/numeric/ublas/matrix.hpp>
#include <boost/numeric/ublas/matrix_sparse.hpp>
#include <boost/numeric/ublas/symmetric.hpp>
#include <boost/numeric/ublas/io.hpp>
namespace bnu = boost::numeric::ublas;
template <typename T = double>
bnu::symmetric_matrix<T, bnu::upper> make_symmetric(std::initializer_list<T> filler) {
size_t n = (sqrt(8*filler.size() + 1) - 1)/2;
assert((n*(n+1))/2 == filler.size());
bnu::symmetric_matrix<T, bnu::upper> result(n, n);
auto in = std::begin(filler);
for (size_t i = 0; i < result.size1(); ++ i)
for (size_t j = 0; j <= i && in != std::end(filler); ++ j)
result (i, j) = *in++;
return result;
}
int main() {
std::cout << make_symmetric({0,1,2}) << "\n";
std::cout << make_symmetric({0,1,2,3,4,5}) << "\n";
std::cout << make_symmetric({0,1,2,3,4,5,6,7,8,9}) << "\n";
}
Prints
[2,2]((0,1),(1,2))
[3,3]((0,1,3),(1,2,4),(3,4,5))
[4,4]((0,1,3,6),(1,2,4,7),(3,4,5,8),(6,7,8,9))
Note: the size checks use the series expansion for 1 + ... + n and the inverse of that: n = 1/2 (sqrt(8 x + 1) - 1)
I have a function in C++ (call it
"weightmatrix") that takes a vector of size n as input, which contains a series of numbers a, b, c..., and returns an n-dimensional vector made up of subvectors of size c, b, a...
That was complicated sounding. Basically, in practice it should look like this:
vector<int> vector_sizes = {2, 3, 1};
cout << "Resulting matrix: " << weightmatrix(vector_sizes); // Function takes vector of size 3
/* Returns the following 3 dimensional matrix:
{ { {0, 0},
{0, 0},
{0, 0} },
{0, 0, 0} }
*/
It's a weird one, I know. I just need to generate a vector without knowing beforehand how many dimensions it will be. Any help or advice you could throw in my way would be awesome.
Here is a solution using a template MultiVector class that returns a MultiVectorView from it's operator[].
The underlying data is stored in a plain std::vector but can be accessed with the vec[x][y][z] syntax.
There is no checking for correct usage, and only very basic functionality is implemented but it gives an idea how it could be done.
#include <iostream>
#include <vector>
template <typename T>
class MultiVector;
template <typename T>
class MultiVectorView {
public:
MultiVectorView(MultiVector<T>& vec_, int index_, int dimension_) : vec(vec_), index(index_), dimension(dimension_) {}
MultiVector<T>& vec;
int index;
int dimension;
MultiVectorView& operator[](std::size_t n_index) {
int index_multiplyer = 1;
for (int i=0; i<dimension; ++i)
index_multiplyer *= vec.dimensions[i];
index += n_index*index_multiplyer;
dimension++;
return *this;
}
operator T() {
return vec.content[index];
}
MultiVectorView& operator=(T val) {
vec.content[index] = val;
return *this;
}
};
template <typename T>
class MultiVector {
public:
MultiVector(std::vector<int> dimensions_) : dimensions(dimensions_) {
int size = dimensions[0];
for (int i = 1; i<dimensions.size(); ++i)
size *= dimensions[i];
content.resize(size);
}
MultiVectorView<T> operator[](std::size_t index) {
return MultiVectorView<T>(*this, index, 1);
}
std::vector<T> content;
std::vector<int> dimensions;
};
int main() {
std::vector<int> v = {2,3,2};
MultiVector<int> test(v);
int tmp = 0;
for (int x = 0; x < v[0]; ++x)
for (int y = 0; y < v[1]; ++y)
for (int z = 0; z < v[2]; ++z) {
test[x][y][z] = tmp++;
}
for (int i=0; i<test.content.size(); ++i)
std::cout << std::endl << test.content[i] << " ";
int b = test[1][2][1];
std::cout << std::endl << "b = " << b << std::endl << "test[0][1][1] = " << test[0][1][1] << std::endl;
}
I took the hint of Galik to make a small sample:
#include <cassert>
#include <iostream>
#include <vector>
template <typename ELEM>
class NDArrayT {
private:
// dimensions
std::vector<size_t> _dims;
// data
std::vector<ELEM> _data;
public:
NDArrayT(const std::vector<size_t> &dims):
_dims(dims)
{
size_t size = _dims.empty() ? 0 : 1;
for (size_t dim : _dims) size *= dim;
_data.resize(size);
}
NDArrayT(
const std::vector<size_t> &dims,
const std::vector<ELEM> &data):
NDArrayT<ELEM>(dims)
{
assert(_data.size() == data.size());
std::copy(data.begin(), data.end(), _data.begin());
}
ELEM& operator[](const std::vector<size_t> &indices)
{
size_t i = 0, j = 0;
for (size_t n = _dims.size(); j < n; ++j) {
i *= _dims[j]; i += indices[j];
}
return _data[i];
}
const ELEM& operator[](const std::vector<size_t> &indices) const
{
size_t i = 0, j = 0;
for (size_t n = _dims.size(); j < n; ++j) {
i *= _dims[j]; i += indices[j];
}
return _data[i];
}
};
using namespace std;
ostream& operator<<(ostream &out, const vector<size_t> &values)
{
const char *sep = "";
for (size_t value : values) {
out << sep << value; sep = ", ";
}
return out;
}
bool inc(vector<size_t> &indices, const vector<size_t> &dims)
{
for (size_t i = indices.size(); i--;) {
if (++indices[i] < dims[i]) return false;
indices[i] = 0;
}
return true; // overflow
}
int main()
{
// build sample data
vector<double> data(2 * 3 * 4);
for (size_t i = data.size(); i--;) data[i] = (double)i;
// build sample array
typedef NDArrayT<double> NDArrayDouble;
const vector<size_t> dims = { 2, 3, 4 };
NDArrayDouble a(dims, data);
// print sample array (check subscript)
vector<size_t> indices(dims.size(), 0);
do {
cout << "a[" << indices << "]: " << a[indices] << endl;
} while (!inc(indices, dims));
// done
return 0;
}
Compiled and tested on ideone.
Output is:
a[0, 0, 0]: 0
a[0, 0, 1]: 1
a[0, 0, 2]: 2
a[0, 0, 3]: 3
a[0, 1, 0]: 4
a[0, 1, 1]: 5
a[0, 1, 2]: 6
a[0, 1, 3]: 7
a[0, 2, 0]: 8
a[0, 2, 1]: 9
a[0, 2, 2]: 10
a[0, 2, 3]: 11
a[1, 0, 0]: 12
a[1, 0, 1]: 13
a[1, 0, 2]: 14
a[1, 0, 3]: 15
a[1, 1, 0]: 16
a[1, 1, 1]: 17
a[1, 1, 2]: 18
a[1, 1, 3]: 19
a[1, 2, 0]: 20
a[1, 2, 1]: 21
a[1, 2, 2]: 22
a[1, 2, 3]: 23
The "arithmetic" to manage multi-dimensional arrays in contiguous memory is actually quite simple. I guess, the most "revolutionary" idea of this sample is the operator[]() which uses a std::vector<size_t> to provide the indices for each dimension.
While I was writing this down, a lot of alternatives for indexing came in my mind. – There is much space for fantasy...
E.g. for linear (one-dimensional) access, a second operator[] for size_t might be provided as well.
I want to get array h[16]={16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,}, but I get an error:
If I delete status = vslCorrSetStart(task, h_start); in code, it will work normally, and array h[16]={0,0,0,0,0,16,15,14,0,12,11,10,0,8,7,6}.
What can I do?
#include <assert.h>
#include <mkl.h>
#include <iostream>
using namespace std;
void main()
{
//input
const double f[16] = { 1 , 2 , 3 , 4,
5 , 6 , 7 , 8,
9 , 10, 11, 12,
13, 14, 15, 16,};
//kernel
const double g[9] = { 0, 0, 0,
0, 1, 0,
0, 0, 0 };
//out
double h[16] = { 0 };
VSLCorrTaskPtr task;
MKL_INT f_shape[2] = { 4, 4 };
MKL_INT g_shape[2] = { 3, 3 };
MKL_INT h_shape[2] = { 4, 4 };
MKL_INT h_start[2] = { 1, 1 };
MKL_INT f_stride[2] = { f_shape[1], 1 };
MKL_INT g_stride[2] = { g_shape[1], 1 };
MKL_INT h_stride[2] = { h_shape[1], 1 };
int status;
status = vsldCorrNewTask(&task, VSL_CORR_MODE_DIRECT, 2, f_shape, g_shape, h_shape);
assert(status == VSL_STATUS_OK);
status = vslCorrSetStart(task, h_start);
assert(status == VSL_STATUS_OK);
//always get wrong,return -2303 I can't find the problem
status = vsldCorrExec(task, f, f_stride, g, g_stride, h, h_stride);
assert(status == VSL_STATUS_OK);
status = vslCorrDeleteTask(&task);
assert(status == VSL_STATUS_OK);
//print the result
for (int r = 0; r < 4; r++)
{
cout << r << "(out): ";
for (int c = 0; c < 4; c++)
{
cout << h[r * 4 + c] << " ";
}
cout << endl;
}
}
How can I do the equivalent of the following using C++/STL? I want to fill a std::vector with a range of values [min, max).
# Python
>>> x = range(0, 10)
>>> x
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
I suppose I could use std::generate_n and provide a functor to generate the sequence, but I was wondering if there is a more succinct way of doing this using STL?
In C++11, there's std::iota:
#include <vector>
#include <numeric> //std::iota
int main() {
std::vector<int> x(10);
std::iota(std::begin(x), std::end(x), 0); //0 is the starting number
}
C++20 introduced a lazy version (just like Python) as part of the ranges library:
#include <iostream>
#include <ranges>
namespace views = std::views;
int main() {
for (int x : views::iota(0, 10)) {
std::cout << x << ' '; // 0 1 2 3 4 5 6 7 8 9
}
}
There is boost::irange:
std::vector<int> x;
boost::push_back(x, boost::irange(0, 10));
I ended up writing some utility functions to do this. You can use them as follows:
auto x = range(10); // [0, ..., 9]
auto y = range(2, 20); // [2, ..., 19]
auto z = range(10, 2, -2); // [10, 8, 6, 4]
The code:
#include <vector>
#include <stdexcept>
template <typename IntType>
std::vector<IntType> range(IntType start, IntType stop, IntType step)
{
if (step == IntType(0))
{
throw std::invalid_argument("step for range must be non-zero");
}
std::vector<IntType> result;
IntType i = start;
while ((step > 0) ? (i < stop) : (i > stop))
{
result.push_back(i);
i += step;
}
return result;
}
template <typename IntType>
std::vector<IntType> range(IntType start, IntType stop)
{
return range(start, stop, IntType(1));
}
template <typename IntType>
std::vector<IntType> range(IntType stop)
{
return range(IntType(0), stop, IntType(1));
}
I've been using this library for this exact purpose for years:
https://github.com/klmr/cpp11-range
Works very well and the proxies are optimized out.
for (auto i : range(1, 5))
cout << i << "\n";
for (auto u : range(0u))
if (u == 3u)
break;
else
cout << u << "\n";
for (auto c : range('a', 'd'))
cout << c << "\n";
for (auto i : range(100).step(-3))
if (i < 90)
break;
else
cout << i << "\n";
for (auto i : indices({"foo", "bar"}))
cout << i << '\n';
There is boost::irange, but it does not provide floating point, negative steps and can not directly initialize stl containers.
There is also numeric_range in my RO library
In RO, to initialize a vector:
vector<int> V=range(10);
Cut-n-paste example from doc page (scc - c++ snippet evaluator):
// [0,N) open-ended range. Only range from 1-arg range() is open-ended.
scc 'range(5)'
{0, 1, 2, 3, 4}
// [0,N] closed range
scc 'range(1,5)'
{1, 2, 3, 4, 5}
// floating point
scc 'range(1,5,0.5)'
{1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5}
// negative step
scc 'range(10,0,-1.5)'
{10, 8.5, 7, 5.5, 4, 2.5, 1}
// any arithmetic type
scc "range('a','z')"
a b c d e f g h i j k l m n o p q r s t u v w x y z
// no need for verbose iota. (vint - vector<int>)
scc 'vint V = range(5); V'
{0, 1, 2, 3, 4}
// is lazy
scc 'auto NR = range(1,999999999999999999l); *find(NR.begin(), NR.end(), 5)'
5
// Classic pipe. Alogorithms are from std::
scc 'vint{3,1,2,3} | sort | unique | reverse'
{3, 2, 1}
// Assign 42 to 2..5
scc 'vint V=range(0,9); range(V/2, V/5) = 42; V'
{0, 1, 42, 42, 42, 5, 6, 7, 8, 9}
// Find (brute force algorithm) maximum of `cos(x)` in interval: `8 < x < 9`:
scc 'range(8, 9, 0.01) * cos || max'
-0.1455
// Integrate sin(x) from 0 to pi
scc 'auto d=0.001; (range(0,pi,d) * sin || add) * d'
2
// Total length of strings in vector of strings
scc 'vstr V{"aaa", "bb", "cccc"}; V * size || add'
9
// Assign to c-string, then append `"XYZ"` and then remove `"bc"` substring :
scc 'char s[99]; range(s) = "abc"; (range(s) << "XYZ") - "bc"'
aXYZ
// Hide phone number:
scc "str S=\"John Q Public (650)1234567\"; S|isdigit='X'; S"
John Q Public (XXX)XXXXXXX
For those who can't use C++11 or libraries:
vector<int> x(10,0); // 0 is the starting number, 10 is the range size
transform(x.begin(),x.end(),++x.begin(),bind2nd(plus<int>(),1)); // 1 is the increment
A range() function similar to below will help:
#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
// define range function (only once)
template <typename T>
vector <T> range(T N1, T N2) {
vector<T> numbers(N2-N1);
iota(numbers.begin(), numbers.end(), N1);
return numbers;
}
vector <int> arr = range(0, 10);
vector <int> arr2 = range(5, 8);
for (auto n : arr) { cout << n << " "; } cout << endl;
// output: 0 1 2 3 4 5 6 7 8 9
for (auto n : arr2) { cout << n << " "; } cout << endl;
// output: 5 6 7
I don't know of a way to do it like in python but another alternative is obviously to for loop through it:
for (int i = range1; i < range2; ++i) {
x.push_back(i);
}
chris's answer is better though if you have c++11
If you can't use C++11, you can use std::partial_sum to generate numbers from 1 to 10. And if you need numbers from 0 to 9, you can then subtract 1 using transform:
std::vector<int> my_data( 10, 1 );
std::partial_sum( my_data.begin(), my_data.end(), my_data.begin() );
std::transform(my_data.begin(), my_data.end(), my_data.begin(), bind2nd(std::minus<int>(), 1));
Some time ago I wrote the following _range class, which behaves like Python range (put it to the "range.h"):
#pragma once
#include <vector>
#include <cassert>
template < typename T = size_t >
class _range
{
const T kFrom, kEnd, kStep;
public:
///////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////
//
// INPUT:
// from - Starting number of the sequence.
// end - Generate numbers up to, but not including this number.
// step - Difference between each number in the sequence.
//
// REMARKS:
// Parameters must be all positive or all negative
//
_range( const T from, const T end, const T step = 1 )
: kFrom( from ), kEnd( end ), kStep( step )
{
assert( kStep != 0 );
assert( ( kFrom >= 0 && kEnd > 0 && kStep > 0 ) || ( kFrom < 0 && kEnd < 0 && kStep < 0 ) );
}
// Default from==0, step==1
_range( const T end )
: kFrom( 0 ), kEnd( end ), kStep( 1 )
{
assert( kEnd > 0 );
}
public:
class _range_iter
{
T fVal;
const T kStep;
public:
_range_iter( const T v, const T step ) : fVal( v ), kStep( step ) {}
operator T () const { return fVal; }
operator const T & () { return fVal; }
const T operator * () const { return fVal; }
const _range_iter & operator ++ () { fVal += kStep; return * this; }
bool operator == ( const _range_iter & ri ) const
{
return ! operator != ( ri );
}
bool operator != ( const _range_iter & ri ) const
{
// This is a tricky part - when working with iterators
// it checks only once for != which must be a hit to stop;
// However, this does not work if increasing kStart by N times kSteps skips over kEnd
return fVal < 0 ? fVal > ri.fVal : fVal < ri.fVal;
}
};
const _range_iter begin() { return _range_iter( kFrom, kStep ); }
const _range_iter end() { return _range_iter( kEnd, kStep ); }
public:
// Conversion to any vector< T >
operator std::vector< T > ( void )
{
std::vector< T > retRange;
for( T i = kFrom; i < kEnd; i += kStep )
retRange.push_back( i );
return retRange; // use move semantics here
}
};
// A helper to use pure range meaning _range< size_t >
typedef _range<> range;
And some test code looks like the following one:
#include "range.h"
#include <iterator>
#include <fstream>
using namespace std;
void RangeTest( void )
{
ofstream ostr( "RangeTest.txt" );
if( ostr.is_open() == false )
return;
// 1:
ostr << "1st test:" << endl;
vector< float > v = _range< float >( 256 );
copy( v.begin(), v.end(), ostream_iterator< float >( ostr, ", " ) );
// 2:
ostr << endl << "2nd test:" << endl;
vector< size_t > v_size_t( range( 0, 100, 13 ) );
for( auto a : v_size_t )
ostr << a << ", ";
// 3:
ostr << endl << "3rd test:" << endl;
auto vvv = range( 123 ); // 0..122 inclusive, with step 1
for( auto a : vvv )
ostr << a << ", ";
// 4:
ostr << endl << "4th test:" << endl;
// Can be used in the nested loops as well
for( auto i : _range< float >( 0, 256, 16.5 ) )
{
for( auto j : _range< int >( -2, -16, -3 ) )
{
ostr << j << ", ";
}
ostr << endl << i << endl;
}
}
As an iterator:
#include <iostream>
class Range {
int x, y, z;
public:
Range(int x) {this->x = 0; this->y = x; this->z = 1;}
Range(int x, int y) {this->x = x; this->y = y; this->z = 1;}
Range(int x, int y, int z) {this->x = x; this->y = y; this->z = z;}
struct Iterator
{
Iterator (int val, int inc) : val{val}, inc{inc} {}
Iterator& operator++(){val+=inc; return *this;}
int operator*() const {return val;}
friend bool operator!=(const Iterator& a, const Iterator& b){return a.val < b.val;}
private:
int val, inc;
};
Iterator begin() {return Iterator(x,z);}
Iterator end() {return Iterator(y,z);}
};
int main() {
for (auto i: Range(10))
{
std::cout << i << ' '; //0 1 2 3 4 5 6 7 8 9
}
std::cout << '\n';
for (auto i: Range(1,10))
{
std::cout << i << ' '; //1 2 3 4 5 6 7 8 9
}
std::cout << '\n';
for (auto i: Range(-10,10,3))
{
std::cout << i << ' '; //-10 -7 -4 -1 2 5 8
}
return 0;
}
How can I do the equivalent of the following using C++/STL? I want to fill a std::vector with a range of values [min, max).
# Python
>>> x = range(0, 10)
>>> x
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
I suppose I could use std::generate_n and provide a functor to generate the sequence, but I was wondering if there is a more succinct way of doing this using STL?
In C++11, there's std::iota:
#include <vector>
#include <numeric> //std::iota
int main() {
std::vector<int> x(10);
std::iota(std::begin(x), std::end(x), 0); //0 is the starting number
}
C++20 introduced a lazy version (just like Python) as part of the ranges library:
#include <iostream>
#include <ranges>
namespace views = std::views;
int main() {
for (int x : views::iota(0, 10)) {
std::cout << x << ' '; // 0 1 2 3 4 5 6 7 8 9
}
}
There is boost::irange:
std::vector<int> x;
boost::push_back(x, boost::irange(0, 10));
I ended up writing some utility functions to do this. You can use them as follows:
auto x = range(10); // [0, ..., 9]
auto y = range(2, 20); // [2, ..., 19]
auto z = range(10, 2, -2); // [10, 8, 6, 4]
The code:
#include <vector>
#include <stdexcept>
template <typename IntType>
std::vector<IntType> range(IntType start, IntType stop, IntType step)
{
if (step == IntType(0))
{
throw std::invalid_argument("step for range must be non-zero");
}
std::vector<IntType> result;
IntType i = start;
while ((step > 0) ? (i < stop) : (i > stop))
{
result.push_back(i);
i += step;
}
return result;
}
template <typename IntType>
std::vector<IntType> range(IntType start, IntType stop)
{
return range(start, stop, IntType(1));
}
template <typename IntType>
std::vector<IntType> range(IntType stop)
{
return range(IntType(0), stop, IntType(1));
}
I've been using this library for this exact purpose for years:
https://github.com/klmr/cpp11-range
Works very well and the proxies are optimized out.
for (auto i : range(1, 5))
cout << i << "\n";
for (auto u : range(0u))
if (u == 3u)
break;
else
cout << u << "\n";
for (auto c : range('a', 'd'))
cout << c << "\n";
for (auto i : range(100).step(-3))
if (i < 90)
break;
else
cout << i << "\n";
for (auto i : indices({"foo", "bar"}))
cout << i << '\n';
There is boost::irange, but it does not provide floating point, negative steps and can not directly initialize stl containers.
There is also numeric_range in my RO library
In RO, to initialize a vector:
vector<int> V=range(10);
Cut-n-paste example from doc page (scc - c++ snippet evaluator):
// [0,N) open-ended range. Only range from 1-arg range() is open-ended.
scc 'range(5)'
{0, 1, 2, 3, 4}
// [0,N] closed range
scc 'range(1,5)'
{1, 2, 3, 4, 5}
// floating point
scc 'range(1,5,0.5)'
{1, 1.5, 2, 2.5, 3, 3.5, 4, 4.5, 5}
// negative step
scc 'range(10,0,-1.5)'
{10, 8.5, 7, 5.5, 4, 2.5, 1}
// any arithmetic type
scc "range('a','z')"
a b c d e f g h i j k l m n o p q r s t u v w x y z
// no need for verbose iota. (vint - vector<int>)
scc 'vint V = range(5); V'
{0, 1, 2, 3, 4}
// is lazy
scc 'auto NR = range(1,999999999999999999l); *find(NR.begin(), NR.end(), 5)'
5
// Classic pipe. Alogorithms are from std::
scc 'vint{3,1,2,3} | sort | unique | reverse'
{3, 2, 1}
// Assign 42 to 2..5
scc 'vint V=range(0,9); range(V/2, V/5) = 42; V'
{0, 1, 42, 42, 42, 5, 6, 7, 8, 9}
// Find (brute force algorithm) maximum of `cos(x)` in interval: `8 < x < 9`:
scc 'range(8, 9, 0.01) * cos || max'
-0.1455
// Integrate sin(x) from 0 to pi
scc 'auto d=0.001; (range(0,pi,d) * sin || add) * d'
2
// Total length of strings in vector of strings
scc 'vstr V{"aaa", "bb", "cccc"}; V * size || add'
9
// Assign to c-string, then append `"XYZ"` and then remove `"bc"` substring :
scc 'char s[99]; range(s) = "abc"; (range(s) << "XYZ") - "bc"'
aXYZ
// Hide phone number:
scc "str S=\"John Q Public (650)1234567\"; S|isdigit='X'; S"
John Q Public (XXX)XXXXXXX
For those who can't use C++11 or libraries:
vector<int> x(10,0); // 0 is the starting number, 10 is the range size
transform(x.begin(),x.end(),++x.begin(),bind2nd(plus<int>(),1)); // 1 is the increment
A range() function similar to below will help:
#include <algorithm>
#include <iostream>
#include <numeric>
#include <vector>
using namespace std;
// define range function (only once)
template <typename T>
vector <T> range(T N1, T N2) {
vector<T> numbers(N2-N1);
iota(numbers.begin(), numbers.end(), N1);
return numbers;
}
vector <int> arr = range(0, 10);
vector <int> arr2 = range(5, 8);
for (auto n : arr) { cout << n << " "; } cout << endl;
// output: 0 1 2 3 4 5 6 7 8 9
for (auto n : arr2) { cout << n << " "; } cout << endl;
// output: 5 6 7
I don't know of a way to do it like in python but another alternative is obviously to for loop through it:
for (int i = range1; i < range2; ++i) {
x.push_back(i);
}
chris's answer is better though if you have c++11
If you can't use C++11, you can use std::partial_sum to generate numbers from 1 to 10. And if you need numbers from 0 to 9, you can then subtract 1 using transform:
std::vector<int> my_data( 10, 1 );
std::partial_sum( my_data.begin(), my_data.end(), my_data.begin() );
std::transform(my_data.begin(), my_data.end(), my_data.begin(), bind2nd(std::minus<int>(), 1));
Some time ago I wrote the following _range class, which behaves like Python range (put it to the "range.h"):
#pragma once
#include <vector>
#include <cassert>
template < typename T = size_t >
class _range
{
const T kFrom, kEnd, kStep;
public:
///////////////////////////////////////////////////////////
// Constructor
///////////////////////////////////////////////////////////
//
// INPUT:
// from - Starting number of the sequence.
// end - Generate numbers up to, but not including this number.
// step - Difference between each number in the sequence.
//
// REMARKS:
// Parameters must be all positive or all negative
//
_range( const T from, const T end, const T step = 1 )
: kFrom( from ), kEnd( end ), kStep( step )
{
assert( kStep != 0 );
assert( ( kFrom >= 0 && kEnd > 0 && kStep > 0 ) || ( kFrom < 0 && kEnd < 0 && kStep < 0 ) );
}
// Default from==0, step==1
_range( const T end )
: kFrom( 0 ), kEnd( end ), kStep( 1 )
{
assert( kEnd > 0 );
}
public:
class _range_iter
{
T fVal;
const T kStep;
public:
_range_iter( const T v, const T step ) : fVal( v ), kStep( step ) {}
operator T () const { return fVal; }
operator const T & () { return fVal; }
const T operator * () const { return fVal; }
const _range_iter & operator ++ () { fVal += kStep; return * this; }
bool operator == ( const _range_iter & ri ) const
{
return ! operator != ( ri );
}
bool operator != ( const _range_iter & ri ) const
{
// This is a tricky part - when working with iterators
// it checks only once for != which must be a hit to stop;
// However, this does not work if increasing kStart by N times kSteps skips over kEnd
return fVal < 0 ? fVal > ri.fVal : fVal < ri.fVal;
}
};
const _range_iter begin() { return _range_iter( kFrom, kStep ); }
const _range_iter end() { return _range_iter( kEnd, kStep ); }
public:
// Conversion to any vector< T >
operator std::vector< T > ( void )
{
std::vector< T > retRange;
for( T i = kFrom; i < kEnd; i += kStep )
retRange.push_back( i );
return retRange; // use move semantics here
}
};
// A helper to use pure range meaning _range< size_t >
typedef _range<> range;
And some test code looks like the following one:
#include "range.h"
#include <iterator>
#include <fstream>
using namespace std;
void RangeTest( void )
{
ofstream ostr( "RangeTest.txt" );
if( ostr.is_open() == false )
return;
// 1:
ostr << "1st test:" << endl;
vector< float > v = _range< float >( 256 );
copy( v.begin(), v.end(), ostream_iterator< float >( ostr, ", " ) );
// 2:
ostr << endl << "2nd test:" << endl;
vector< size_t > v_size_t( range( 0, 100, 13 ) );
for( auto a : v_size_t )
ostr << a << ", ";
// 3:
ostr << endl << "3rd test:" << endl;
auto vvv = range( 123 ); // 0..122 inclusive, with step 1
for( auto a : vvv )
ostr << a << ", ";
// 4:
ostr << endl << "4th test:" << endl;
// Can be used in the nested loops as well
for( auto i : _range< float >( 0, 256, 16.5 ) )
{
for( auto j : _range< int >( -2, -16, -3 ) )
{
ostr << j << ", ";
}
ostr << endl << i << endl;
}
}
As an iterator:
#include <iostream>
class Range {
int x, y, z;
public:
Range(int x) {this->x = 0; this->y = x; this->z = 1;}
Range(int x, int y) {this->x = x; this->y = y; this->z = 1;}
Range(int x, int y, int z) {this->x = x; this->y = y; this->z = z;}
struct Iterator
{
Iterator (int val, int inc) : val{val}, inc{inc} {}
Iterator& operator++(){val+=inc; return *this;}
int operator*() const {return val;}
friend bool operator!=(const Iterator& a, const Iterator& b){return a.val < b.val;}
private:
int val, inc;
};
Iterator begin() {return Iterator(x,z);}
Iterator end() {return Iterator(y,z);}
};
int main() {
for (auto i: Range(10))
{
std::cout << i << ' '; //0 1 2 3 4 5 6 7 8 9
}
std::cout << '\n';
for (auto i: Range(1,10))
{
std::cout << i << ' '; //1 2 3 4 5 6 7 8 9
}
std::cout << '\n';
for (auto i: Range(-10,10,3))
{
std::cout << i << ' '; //-10 -7 -4 -1 2 5 8
}
return 0;
}