Same random numbers in C++ as computed by Python3 numpy.random.rand - python

I would like to duplicate in C++ the testing for some code that has already been implemented in Python3 which relies on numpy.random.rand and randn values and a specific seed (e.g., seed = 1).
I understand that Python's random implementation is based on a Mersenne twister. The C++ standard library also supplies this in std::mersenne_twister_engine.
The C++ version returns an unsigned int, whereas Python rand is a floating point value.
Is there a way to obtain the same values in C++ as are generated in Python, and be sure that they are the same? And the same for an array generated by randn ?

You can do it this way for integer values:
import numpy as np
np.random.seed(12345)
print(np.random.randint(256**4, dtype='<u4', size=1)[0])
#include <iostream>
#include <random>
int main()
{
std::mt19937 e2(12345);
std::cout << e2() << std::endl;
}
The result of both snippets is 3992670690
By looking at source code of rand you can implement it in your C++ code this way:
import numpy as np
np.random.seed(12345)
print(np.random.rand())
#include <iostream>
#include <iomanip>
#include <random>
int main()
{
std::mt19937 e2(12345);
int a = e2() >> 5;
int b = e2() >> 6;
double value = (a * 67108864.0 + b) / 9007199254740992.0;
std::cout << std::fixed << std::setprecision(16) << value << std::endl;
}
Both random values are 0.9296160928171479
It would be convenient to use std::generate_canonical, but it uses another method to convert the output of Mersenne twister to double. The reason they differ is likely that generate_canonical is more optimized than the random generator used in NumPy, as it avoids costly floating point operations, especially multiplication and division, as seen in source code. However it seems to be implementation dependent, while NumPy produces the same result on all platforms.
double value = std::generate_canonical<double, std::numeric_limits<double>::digits>(e2);
This doesn't work and produces result 0.8901547132827379, which differs from the output of Python code.

For completeness and to avoid re-inventing the wheel, here is an implementation for both numpy.rand and numpy.randn in C++
The header file:
#ifndef RANDOMNUMGEN_NUMPYCOMPATIBLE_H
#define RANDOMNUMGEN_NUMPYCOMPATIBLE_H
#include "RandomNumGenerator.h"
//Uniform distribution - numpy.rand
class RandomNumGen_NumpyCompatible {
public:
RandomNumGen_NumpyCompatible();
RandomNumGen_NumpyCompatible(std::uint_fast32_t newSeed);
std::uint_fast32_t min() const { return m_mersenneEngine.min(); }
std::uint_fast32_t max() const { return m_mersenneEngine.max(); }
void seed(std::uint_fast32_t seed);
void discard(unsigned long long); // NOTE!! Advances and discards twice as many values as passed in to keep tracking with Numpy order
uint_fast32_t operator()(); //Simply returns the next Mersenne value from the engine
double getDouble(); //Calculates the next uniformly random double as numpy.rand does
std::string getGeneratorType() const { return "RandomNumGen_NumpyCompatible"; }
private:
std::mt19937 m_mersenneEngine;
};
///////////////////
//Gaussian distribution - numpy.randn
class GaussianRandomNumGen_NumpyCompatible {
public:
GaussianRandomNumGen_NumpyCompatible();
GaussianRandomNumGen_NumpyCompatible(std::uint_fast32_t newSeed);
std::uint_fast32_t min() const { return m_mersenneEngine.min(); }
std::uint_fast32_t max() const { return m_mersenneEngine.max(); }
void seed(std::uint_fast32_t seed);
void discard(unsigned long long); // NOTE!! Advances and discards twice as many values as passed in to keep tracking with Numpy order
uint_fast32_t operator()(); //Simply returns the next Mersenne value from the engine
double getDouble(); //Calculates the next normally (Gaussian) distrubuted random double as numpy.randn does
std::string getGeneratorType() const { return "GaussianRandomNumGen_NumpyCompatible"; }
private:
bool m_haveNextVal;
double m_nextVal;
std::mt19937 m_mersenneEngine;
};
#endif
And the implementation:
#include "RandomNumGen_NumpyCompatible.h"
RandomNumGen_NumpyCompatible::RandomNumGen_NumpyCompatible()
{
}
RandomNumGen_NumpyCompatible::RandomNumGen_NumpyCompatible(std::uint_fast32_t seed)
: m_mersenneEngine(seed)
{
}
void RandomNumGen_NumpyCompatible::seed(std::uint_fast32_t newSeed)
{
m_mersenneEngine.seed(newSeed);
}
void RandomNumGen_NumpyCompatible::discard(unsigned long long z)
{
//Advances and discards TWICE as many values to keep with Numpy order
m_mersenneEngine.discard(2*z);
}
std::uint_fast32_t RandomNumGen_NumpyCompatible::operator()()
{
return m_mersenneEngine();
}
double RandomNumGen_NumpyCompatible::getDouble()
{
int a = m_mersenneEngine() >> 5;
int b = m_mersenneEngine() >> 6;
return (a * 67108864.0 + b) / 9007199254740992.0;
}
///////////////////
GaussianRandomNumGen_NumpyCompatible::GaussianRandomNumGen_NumpyCompatible()
: m_haveNextVal(false)
{
}
GaussianRandomNumGen_NumpyCompatible::GaussianRandomNumGen_NumpyCompatible(std::uint_fast32_t seed)
: m_haveNextVal(false), m_mersenneEngine(seed)
{
}
void GaussianRandomNumGen_NumpyCompatible::seed(std::uint_fast32_t newSeed)
{
m_mersenneEngine.seed(newSeed);
}
void GaussianRandomNumGen_NumpyCompatible::discard(unsigned long long z)
{
//Burn some CPU cyles here
for (unsigned i = 0; i < z; ++i)
getDouble();
}
std::uint_fast32_t GaussianRandomNumGen_NumpyCompatible::operator()()
{
return m_mersenneEngine();
}
double GaussianRandomNumGen_NumpyCompatible::getDouble()
{
if (m_haveNextVal) {
m_haveNextVal = false;
return m_nextVal;
}
double f, x1, x2, r2;
do {
int a1 = m_mersenneEngine() >> 5;
int b1 = m_mersenneEngine() >> 6;
int a2 = m_mersenneEngine() >> 5;
int b2 = m_mersenneEngine() >> 6;
x1 = 2.0 * ((a1 * 67108864.0 + b1) / 9007199254740992.0) - 1.0;
x2 = 2.0 * ((a2 * 67108864.0 + b2) / 9007199254740992.0) - 1.0;
r2 = x1 * x1 + x2 * x2;
} while (r2 >= 1.0 || r2 == 0.0);
/* Box-Muller transform */
f = sqrt(-2.0 * log(r2) / r2);
m_haveNextVal = true;
m_nextVal = f * x1;
return f * x2;
}

After doing a bit of testing, it does seem that the values are within a tolerance (see #fdermishin 's comment below) when the C++ unsigned int is divided by the maximum value for an unsigned int like this:
#include <limits>
...
std::mt19937 generator1(seed); // mt19937 is a standard mersenne_twister_engine
unsigned val1 = generator1();
std::cout << "Gen 1 random value: " << val1 << std::endl;
std::cout << "Normalized Gen 1: " << static_cast<double>(val1) / std::numeric_limits<std::uint32_t>::max() << std::endl;
However, Python's version seems to skip every other value.
Given the following two programs:
#!/usr/bin/env python3
import numpy as np
def main():
np.random.seed(1)
for i in range(0, 10):
print(np.random.rand())
###########
# Call main and exit success
if __name__ == "__main__":
main()
sys.exit()
and
#include <cstdlib>
#include <iostream>
#include <random>
#include <limits>
int main()
{
unsigned seed = 1;
std::mt19937 generator1(seed); // mt19937 is a standard mersenne_twister_engine
for (unsigned i = 0; i < 10; ++i) {
unsigned val1 = generator1();
std::cout << "Normalized, #" << i << ": " << (static_cast<double>(val1) / std::numeric_limits<std::uint32_t>::max()) << std::endl;
}
return EXIT_SUCCESS;
}
the Python program prints:
0.417022004702574
0.7203244934421581
0.00011437481734488664
0.30233257263183977
0.14675589081711304
0.0923385947687978
0.1862602113776709
0.34556072704304774
0.39676747423066994
0.538816734003357
whereas the C++ program prints:
Normalized, #0: 0.417022
Normalized, #1: 0.997185
Normalized, #2: 0.720324
Normalized, #3: 0.932557
Normalized, #4: 0.000114381
Normalized, #5: 0.128124
Normalized, #6: 0.302333
Normalized, #7: 0.999041
Normalized, #8: 0.146756
Normalized, #9: 0.236089
I could easily skip every other value in the C++ version, which should give me numbers that match the Python version (within a tolerance). But why would Python's implementation seem to skip every other value, or where do these extra values in the C++ version come from?

Related

Matrix multiplication benchmarking on Titan RTX with double and single precisions

I am trying to understand the difference in performances between single and double precisions of our GPU workstation.
Our workstation is equipped with two TITAN RTX GPUs, but I am running the benchmark on a sigle Titan RTX.
I am testing the performance with cublas matrix-matrix multiplications. I multiply 8192x8192 matrices that consist of random floats or doubles. To ensure that there is no mistake on my end, I also repeat this procedure in Python using cupy library, and the results are very similar.
The test results are ~75 ms per 1 multiplication for floats and ~2,000 ms for doubles.
If I had an older GPU, this would make a lot of sense, as 75*32 = 2,400~2000, so that my double-precision performance would be ~32 times poorer as expected from the table https://docs.nvidia.com/cuda/cuda-c-programming-guide/index.html#arithmetic-instructions.
However, my GPU has Compute Capability 7.5, therefore I expect degradation of the performance with doubles only by a factor of 2.
Other info: Ubuntu 18 LTS, nvcc 10.2, driver 440.82.
Here is the CUDA code:
#include <iostream>
#include <chrono>
#include <string>
#include <cuda_runtime.h>
#include "cublas_v2.h"
#include <math.h>
#include <stdio.h>
#include <cuda.h>
#include <device_functions.h>
#include <sstream>
#include <time.h>
unsigned long mix(unsigned long a, unsigned long b, unsigned long c)
{
a=a-b; a=a-c; a=a^(c >> 13);
b=b-c; b=b-a; b=b^(a << 8);
c=c-a; c=c-b; c=c^(b >> 13);
a=a-b; a=a-c; a=a^(c >> 12);
b=b-c; b=b-a; b=b^(a << 16);
c=c-a; c=c-b; c=c^(b >> 5);
a=a-b; a=a-c; a=a^(c >> 3);
b=b-c; b=b-a; b=b^(a << 10);
c=c-a; c=c-b; c=c^(b >> 15);
return c;
}
using namespace std;
int main()
{
int deviceCount;
cudaGetDeviceCount(&deviceCount);
cudaDeviceProp deviceProp;
cublasStatus_t err;
cudaGetDeviceProperties(&deviceProp, 0);
printf("Detected %d devices \n", deviceCount);
printf("Device %d has compute capability %d.%d:\n\t maxshmem %d. \n\t maxthreads per block %d. \n\t max threads dim %d. %d. %d.\n ", 0,
deviceProp.major, deviceProp.minor, deviceProp.sharedMemPerBlock, deviceProp.maxThreadsPerBlock, deviceProp.maxThreadsDim[0],
deviceProp.maxThreadsDim[1], deviceProp.maxThreadsDim[2]);
cudaEvent_t start_d, stop_d;
cudaEventCreate(&start_d);
cudaEventCreate(&stop_d);
//RND insicialization
unsigned long seed = mix(clock(), time(NULL), 0);
srand(seed);
int N=8192;
int Nloops=2;
int memsize=N*N*sizeof(double);
double *a = (double *)malloc(memsize);
double *b = (double *)malloc(memsize);
double *c = (double *)malloc(memsize);
for (int i = 0; i < N; i++)
for (int j = 0; j < N; j++){
a[i*N+j]=((double)rand() / RAND_MAX);
b[i*N+j]=((double)rand() / RAND_MAX);
}
double *a_d, *b_d, *c_d;
cudaMalloc((void **)&a_d, memsize);
cudaMalloc((void **)&b_d, memsize);
cudaMalloc((void **)&c_d, memsize);
cudaMemcpy(a_d, a, memsize, cudaMemcpyHostToDevice);
cudaMemcpy(b_d, b, memsize, cudaMemcpyHostToDevice);
cublasHandle_t handle;
cublasCreate(&handle);
double alpha=1.0;
double beta=0.0;
auto start = chrono::steady_clock::now();
clock_t start1;
start1 = clock();
cudaEventRecord(start_d);
if (cudaGetLastError() != cudaSuccess)
printf("%s \n",cudaGetErrorString(cudaGetLastError()));
for (int i=0; i<Nloops; i++)
cublasDgemm(handle, CUBLAS_OP_N, CUBLAS_OP_N, N,N,N,&alpha,a_d,N,b_d,N,&beta,c_d,N);
cudaEventRecord(stop_d);
cudaDeviceSynchronize();
auto end = chrono::steady_clock::now();
start1 = clock() - start1;
cudaEventSynchronize(stop_d);
cublasDestroy(handle);
float milliseconds = 0;
cudaEventElapsedTime(&milliseconds, start_d, stop_d);
std::cout << "Cuda event " << milliseconds /Nloops << " ms" <<endl;
std::cout << " time elapsed " << start1 / (double)CLOCKS_PER_SEC /Nloops << '\n';
cout << "time elapsed for 1 multiplication: " << ((double)chrono::duration_cast<chrono::microseconds>(end-start).count() )/(Nloops*1000.0)<< " milliseconds" <<endl;
free(a); free(b); free(c);
cudaFree(a_d); cudaFree(b_d); cudaFree(c_d);
}
And this is the python code that yields consistent results:
import cupy as cp
import time
iterations = 2
a = cp.random.rand(8192,8192).astype(cp.float64)
b = cp.random.rand(8192,8192).astype(cp.float64)
def ab(a,b,iterations):
for i in range(iterations):
cp.matmul(a,b,out=None)
ab(a,b,1) # warm up
cp.cuda.Device(0).synchronize()
t1 = time.time()
ab(a,b,iterations)
cp.cuda.Device(0).synchronize()
t2 = time.time()
total = (t2-t1)/iterations
print(total)
Ok, I found the answer. In that table that I link in my quesiton, there is a footnote that says that for compute capability 7.5 (which is the case here) the performance is 2, but not 32, and for floats it is 64, which means that multiplication-addition operations for doubles are 32 times slower than for the floats.
If both the float and double problems were fully arithmetic-bound, I would expect the slowdown to be ~32. In reality, the slowdown is slightly smaller (2000/75 ~ 27), which may be a consequence of the problem with floats being bandwidth-bound, or maybe it is related to other things.

How to write 2D std vector of floats to HDF5 file and then read it in python

I want to write a 2D vector of floats to a HDF5 file.
I used the following code (writeh5.cpp):
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <H5Cpp.h>
using namespace H5;
using namespace std;
int main(void) {
int nrow = 5;
int ncol = 4;
vector<vector< double > > vec2d;
vec2d.resize(nrow, vector<double>(ncol, 0.0));
srand((unsigned)time(0));
typename vector< vector< double > >::iterator row;
typename vector< double >::iterator col;
for (row = vec2d.begin(); row != vec2d.end(); row++) {
cout << endl;
for (col = row->begin(); col != row->end(); col++) {
*col = (rand()/(RAND_MAX+1.0));
cout << *col << '\t';
}
}
cout << endl;
H5File file("test.h5", H5F_ACC_TRUNC);
// dataset dimensions
hsize_t dimsf[2];
dimsf[0] = nrow;
dimsf[1] = ncol;
DataSpace dataspace(2, dimsf);
DataType datatype(H5::PredType::NATIVE_DOUBLE);
DataSet dataset = file.createDataSet("data", datatype, dataspace);
// dataset.write(vec2d.data(), H5::PredType::NATIVE_DOUBLE);
dataset.write(&vec2d[0][0], H5::PredType::NATIVE_DOUBLE);
cout << endl << " vec2d has " << endl;
for (row = vec2d.begin(); row != vec2d.end(); row++) {
cout << endl;
for (col = row->begin(); col != row->end(); col++) {
cout << *col << '\t';
}
}
cout << endl;
dataset.close();
dataspace.close();
file.close();
return 0;
}
I compiled it using g++ writeh5.cpp -I/usr/include/hdf5/ -lhdf5_cpp -lhdf5 -Wall
A run of the code produced the following output:
0.325553 0.598941 0.364489 0.0125061
0.374205 0.0319419 0.380329 0.815621
0.863754 0.386279 0.0173515 0.15448
0.703936 0.372486 0.728436 0.991631
0.666207 0.568983 0.807475 0.964276
And the file test.h5
Then when i read this file from python (using the following)
import h5py
import numpy as np
file = h5py.File("test.h5", 'r')
dataset = np.array(file["data"])
print dataset
file.close()
I got
[[ 3.25553381e-001 5.98941262e-001 3.64488814e-001 1.25061036e-002]
[ 0.00000000e+000 2.42092166e-322 3.74204732e-001 3.19418786e-002]
[ 3.80329057e-001 8.15620518e-001 0.00000000e+000 2.42092166e-322]
[ 8.63753530e-001 3.86278684e-001 1.73514970e-002 1.54479635e-001]
[ 0.00000000e+000 2.42092166e-322 7.03935940e-001 3.72486182e-001]]
the first row is good, the other rows are garbage.
I tried with dataset.write(&vec2d[0]... and dataset.write(vec2d[0].data()..., i got similar problems.
I want to
Write a HDF5 file with the contents of a 2D std::vector of doubles,
Read the file in python and store the contents in a numpy array
What i am doing wrong?
Apparently, I am not allowed to pass a std::vector of vectors to the write function. Thus, copying the elements of the vector to an static array solves the problem, because the write function accepts happily this array.
However, I am not happy with this solution, I expected to use the vectors
directly into the write function.
Here is the code:
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
#include <H5Cpp.h>
using namespace H5;
using namespace std;
int main(void) {
int nrow = 5;
int ncol = 4;
vector<vector< double > > vec2d;
vec2d.resize(nrow, vector<double>(ncol, 0.0));
srand((unsigned)time(0));
// generate some data
typename vector< vector< double > >::iterator row;
typename vector< double >::iterator col;
for (row = vec2d.begin(); row != vec2d.end(); row++) {
cout << endl;
for (col = row->begin(); col != row->end(); col++) {
*col = (rand()/(RAND_MAX+1.0));
cout << *col << '\t';
}
}
cout << endl;
double varray[nrow][ncol];
for( int i = 0; i<nrow; ++i) {
cout << endl;
for( int j = 0; j<ncol; ++j) {
varray[i][j] = vec2d[i][j];
}
}
H5File file("test.h5", H5F_ACC_TRUNC);
// dataset dimensions
hsize_t dimsf[2];
dimsf[0] = nrow;
dimsf[1] = ncol;
DataSpace dataspace(2, dimsf);
DataType datatype(H5::PredType::NATIVE_DOUBLE);
DataSet dataset = file.createDataSet("data", datatype, dataspace);
dataset.write(varray, H5::PredType::NATIVE_DOUBLE);
cout << endl;
dataset.close();
dataspace.close();
file.close();
return 0;
}
I ran into the same problem when i converted my data from a vector to a dynamic 2D array. The problem with the h5write command is not that it will not accept a vector, It does not understand the concept of a pointer array. it only writes out contiguous memory. A vector of vectors is not contiguous in memory but instead a pointer array to a bunch of vectors. That is why when you passed the first element of the array the first row was correct. The rest of the table is just the garbage in memory following the first vector.
My solution was creating a giant 1D vector and performing my own indexing to convert back and forth. This is similar to the approach in h5_writedyn.c https://www.hdfgroup.org/ftp/HDF5/examples/misc-examples/h5_writedyn.c
What is this?
gives
0.325553 0.598941 0.364489 0.0125061
0.374205 0.0319419 0.380329 0.815621
0.863754 0.386279 0.0173515 0.15448
0.703936 0.372486 0.728436 0.991631
0.666207 0.568983 0.807475 0.964276
I don't see a print your c++ code. Did you read the file with some other tool?
(yes, this is a clarifying question, but it requires too much formatting to fit in a comment).
https://stackoverflow.com/a/24622720/901925
Writing 2-D array int[n][m] to HDF5 file using Visual C++
The solution talks about writing a vector of vectors. It also talks about writing variable length arrays.
You may have to put in the dataset write in a row iterator
for (row = vec2d.begin(); row != vec2d.end(); row++) {
dataset.write(*row, H5::PredType::NATIVE_DOUBLE);
# or dataset.write(row[0], ...)?
}
}

C++ (something that is like a python list)

I'm new to C++ and C++ Builder; I was working before in python. I'm working on a project and I need some help.
I'm looking for a type that works the same as list does in Python. I have tried the vector but it doesn't work well for me. I need a variable where I can store random data in. I'm using rand() to get the numbers but the numbers are not always different they will repeat itself. So I tried the BoxList and it works for storing items in it. I Have done it in Python just so you can see what I'm trying to say to you all.
import random
pool= list()
for number in range(1,11):
pool.append(number)
random.shuffle(pool)
print(pool)
This would give me:
[6, 2, 10, 8, 9, 3, 7, 4, 5, 1] # or some other random shuffled numbers
The other idea is that I could check if the random number I'm looking for is in the BoxList but I have no idea how to do that.
Edit:
Im working in c++ builder and i have problems with getting the number to enter my ListBox.
Im doing a simple program that will help me study. i have like 100 questions and i would like it to ask me a question(the number of the question) and then i click one button if my answer was right and the other if my question was wrong.!
the gui
this is the code:
//---------------------------------------------------------------------------
#include <fmx.h>
#pragma hdrstop
#include <vector>
#include <iostream>
#include "Unit3.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.fmx"
TForm3 *Form3;
int right = 0;
int wrong = 0 ;
int allQuestions = 0;
int currentQuestion = 0;
int toTheEnd = 0;
std::vector<int> asked;
//---------------------------------------------------------------------------
__fastcall TForm3::TForm3(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm3::Button3Click(TObject *Sender)
{
allQuestions = Edit1->Text.ToInt();
right = 0;
wrong = 0;
Label1->Text = allQuestions;
toTheEnd = allQuestions;
}
//---------------------------------------------------------------------------
void __fastcall TForm3::Button1Click(TObject *Sender)
{
right += 1;
toTheEnd -= 1;
Label1->Text = toTheEnd;
Label3->Text = right;
}
//---------------------------------------------------------------------------
void __fastcall TForm3::Button2Click(TObject *Sender)
{
wrong += 1;
toTheEnd -= 1;
Label1->Text = toTheEnd;
Label2->Text = wrong;
}
//---------------------------------------------------------------------------
I hope you guyz understand what im trying to say here if its not, plz tell me.
It's not clear to me why a std::vector won't work for you, because it has very similar properties to python's list type.
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> pool;
for (int i=1; i<11; ++i)
pool.push_back(i);
std::random_shuffle(pool.begin(), pool.end());
for (std::vector<int>::const_iterator i = pool.begin(); i != pool.end(); ++i)
std::cout << *i << " ";
std::cout << "\n";
// Or, you could print this way:
for (int i=0; i<pool.size(); ++i)
std::cout << pool[i] << " ";
std::cout << "\n";
}
This code outputs:
[7:47am][wlynch#watermelon /tmp] ./ex
6 10 7 4 8 9 5 2 3 1
6 10 7 4 8 9 5 2 3 1

Returning the first index of an element in a vector in C++

I am trying to find the first index of an element in a vector in c++.
Let's say you have a vector: [2, 3, 4, 2, 6, 7, 1, 2, 6, 3].
I would like to find the position of the number 6.
So the first time the number 6 occurs is at an index value of 4.
Is there a function that can do that in C++?
I know in Python, I can use the list.index(n) method to do that for me.
std::vector<int> vct;
//insert value
//use std::find to get iterator
auto itr=std::find(vct.begin(), vct.end(), 6);
if(itr==vct.end())
return;
auto index=std::distance(vct.begin(), itr);
You could use:
InputIterator find (InputIterator beg, InputIterator end, const T& value)
which is defined in #include <algorithm>.
Usage
Say you have the following vector:
std::vector<int> numberVector;
numberVector.push_back(1);
numberVector.push_back(2);
numberVector.push_back(3);
numberVector.push_back(4);
numberVector.push_back(5);
You could find index of 4 by:
std::vector<int>::iterator position = std::find(
numberVector.begin(), numberVector.end(), 4
);
Then check whether it's found:
bool exists = (position != numberVector.end());
If it exists, then you could get the index by:
int index = position - numbVector.begin();
You would need to do something like this:
int getIndexOf(std::vector<int> v, int num)
{
for(std::vector<int>::size_type i = 0; i != v.size(); i++)
{
if(v[i] == num)
{
return i;
}
}
return -1;
}
EDIT: As efficiency is definitely a consideration, perhaps this may be a viable solution. I am storing the index of each item from the vector into its corresponding hashed value in an unordered_multimap. Note: this is assuming the vector will not have its contents changing super frequently.
#include <unordered_map>
#include <algorithm>
typedef std::unordered_multimap<int,int>::const_iterator IntMapIterator;
typedef std::pair<int,int> IntPair;
std::unordered_multimap<int,int> hashValues(const std::vector<int>& vec)
{
std::unordered_multimap<int,int> hashedValues;
for(std::vector<int>::size_type i = 0; i != vec.size(); i++)
{
hashedValues.emplace(vec[i], i);
}
return hashedValues;
}
struct IntPairComparator
{
bool operator()(const IntPair& left, const IntPair& right) const
{
return left.second < right.second;
}
};
int getEarliestIndex(const std::unordered_multimap<int,int>& hashedValues, int num)
{
std::pair<IntMapIterator,IntMapIterator> range = hashedValues.equal_range(num);
IntPair minPair = *std::min_element(range.first, range.second, IntPairComparator());
return minPair.second;
}
int main(int argc, const char* argv[])
{
std::vector<int> bigVector;
// do stuff and fill contents of vector
std::unordered_multimap<int,int>& hashedValues = hashValues(bigVector);
int earliestIndex = getEarliestIndex(hashedValues, 6);
}
May be you can use this, if your vector is not very large..
std::find(vector.begin(), vector.end(), item)!=vector.end()
You will directly get the iterator pointing to that value..
in case you vector is too large, you can some binary_search, lower_bound, or upper_bound algorithms, because using this for huge vectors impact performance..
No, there is no explicit function that can do this but what #51k has pointed in the right direction. You might have to write your own implementation if you have a need, other have mentioned some of those
To expand on Geoffrey Tucker's response, you can actually generalize to a template function as such:
#include <algorithm>
#include <iterator>
#include <vector>
template <typename T=int, class ContainerType=std::vector<T> >
typename std::iterator_traits<typename ContainerType::iterator>::difference_type
get_index_of(const ContainerType& c, const T& t) {
ContainerType::const_iterator itr = std::find(c.begin(), c.end(), t);
return (std::distance(c.begin(), itr));
}
Note that here, the index returned for an item not in the container is actually past the value of c.size(), where c is the container (in your case, a vector). This differs from Geoffrey's implementation where he returns -1; here, we leave it up to the container type to determine what the return type of the function will be.
#include <iostream>
#include <vector>
using namespace std;
int find_index( int n, vector<int> & v )
{
int pos = 0;
for( const auto i : v ) { if( i == n ) return pos; ++pos; }
return -1; // not found index
}
int main()
{
vector<int> v{ 2, 3, 4, 2, 6, 7, 1, 2, 6, 3 };
cout << find_index( 6, v ) << endl;
}

Passing an array using Ctypes

So my python program is
from ctypes import *
import ctypes
number = [0,1,2]
testlib = cdll.LoadLibrary("./a.out")
testlib.init.argtypes = [ctypes.c_int]
testlib.init.restype = ctypes.c_double
#create an array of size 3
testlib.init(3)
#Loop to fill the array
#use AccessArray to preform an action on the array
And the C part is
#include <stdio.h>
double init(int size){
double points[size];
return points[0];
}
double fillarray(double value, double location){
// i need to access
}
double AccessArray(double value, double location){
// i need to acess the array that is filled in the previous function
}
So what I need to do is to pass an array from the python part to the C function somehow move that array in C to the another function where I will access it in order to process it.
I'm stuck though because I cant figure out a way to move the array in the C part.
can someone show me how to do this?
You should try something like this (in your C code):
#include <stdio.h>
double points[1000];//change 1000 for the maximum size for you
int sz = 0;
double init(int size){
//verify size <= maximum size for the array
for(int i=0;i<size;i++) {
points[i] = 1;//change 1 for the init value for you
}
sz = size;
return points[0];
}
double fillarray(double value, double location){
//first verify 0 < location < sz
points[(int)location] = value;
}
double AccessArray(double value, double location){
//first verify 0 < location < sz
return points[(int)location];
}
This is a very simple solution but if you need to allocate an array with just any size you shoul study the use of malloc
Maybe something like this?
$ cat Makefile
go: a.out
./c-double
a.out: c.c
gcc -fpic -shared c.c -o a.out
zareason-dstromberg:~/src/outside-questions/c-double x86_64-pc-linux-gnu 27062 - above cmd done 2013 Fri Dec 27 11:03 AM
$ cat c.c
#include <stdio.h>
#include <malloc.h>
double *init(int size) {
double *points;
points = malloc(size * sizeof(double));
return points;
}
double fill_array(double *points, int size) {
int i;
for (i=0; i < size; i++) {
points[i] = (double) i;
}
}
double access_array(double *points, int size) {
// i need to access the array that is filled in the previous function
int i;
for (i=0; i < size; i++) {
printf("%d: %f\n", i, points[i]);
}
}
zareason-dstromberg:~/src/outside-questions/c-double x86_64-pc-linux-gnu 27062 - above cmd done 2013 Fri Dec 27 11:03 AM
$ cat c-double
#!/usr/local/cpython-3.3/bin/python
import ctypes
testlib = ctypes.cdll.LoadLibrary("./a.out")
testlib.init.argtypes = [ctypes.c_int]
testlib.init.restype = ctypes.c_void_p
#create an array of size 3
size = 3
double_array = testlib.init(size)
#Loop to fill the array
testlib.fill_array(double_array, size)
#use AccessArray to preform an action on the array
testlib.access_array(double_array, size)

Categories