it has been a few hours since I am dealing with this issue. I was wondering if someone could point out what am I doing wrong, and if possible - how to fix it. Essentially, I am simply trying to generate n number of object pairs and store them into a vector<pair<Foo, Foo>>. The algorithm involves random number generator. I use STL <random> and its components like m19937, uniform_real_distribution and uniform_int_distribution. Below is the simplified version of what I am trying to do representing the case I got at hand. The second loop always cuts short. However, I fail to see the reason why. Essentially, I never get to see the program execute completely. The last two messages never show.
program
#include <iostream>
#include <vector>
#include <random>
#include <utility>
// utility
using std::pair;
// random
using std::mt19937;
using std::uniform_int_distribution;
using std::uniform_real_distribution;
// iostream
using std::cout;
using std::endl;
// vector
using std::vector;
class Event{
private:
double x, y;
public:
Event(const double X, const double Y);
};
Event::Event(const double X, const double Y): x(X), y(Y){}
int main(){
cout << "Initializing storage..." << endl;
vector<Event> population;
vector<pair<Event,Event>> selection;
cout << "Initializing necessary member variables..." << endl;
const unsigned int SEED = 14112017;
const unsigned int MAX_ITERATIONS = 10000;
const double MIN = 1;
const double MAX = 10000;
mt19937 engine(SEED);
cout << "Generating the initial population..." << endl;
uniform_real_distribution<> real_distribution(MIN, MAX);
for(unsigned int i = 0; i < MAX_ITERATIONS; ++i){
double x = real_distribution(engine);
double y = real_distribution(engine);
Event event(x, y);
population.push_back(event);
}
cout << "Success! The initial population has been generated successfully" << endl;
population.shrink_to_fit();
cout << "Starting the selection process..." << endl;
unsigned int random = 0;
uniform_int_distribution<> int_distribution(MIN, MAX);
for(unsigned int i = 0; i < MAX_ITERATIONS; ++i){
random = int_distribution(engine);
Event event_x = population.at(random);
random = int_distribution(engine);
Event event_y = population.at(random);
pair<Event, Event> bound(event_x, event_y);
selection.push_back(bound);
}
cout << "Success! The selection process has been completed successfully" << endl;
selection.shrink_to_fit();
cout << "population size: " << population.size() << endl;
cout << "selection size: " << selection.size() << endl;
return 0;
}
I compile the above using cygwins C++ compiler, and I execute the code in command-prompt. The OS is Windows 10 x64. The box has 32 GB memory.
uniform_int_distributions constructor is as follows:
explicit uniform_int_distribution( IntType a = 0,
IntType b = std::numeric_limits<IntType>::max() );
By default, it returns an integer which covers all positive values of that type. The range includes the value of the second parameter. If it wouldn't, it would be cumbersome to specify we want all positive integers.
cppreference.com does not document it, but the C++ standard does: Thanks #Cubbi
This is documented on cppreference.com, or in the C++ standard:
26.5.8.2.1 Class template uniform_int_distribution [rand.dist.uni.int]
1 A uniform_int_distribution random number
distribution produces random integers i, a ≤ i ≤ b, distributed
according to the constant discrete probability function
[...]
// constructors and reset functions
explicit uniform_int_distribution(IntType a = 0, IntType b = numeric_limits<IntType>::max());
Here:
uniform_int_distribution<> int_distribution(MIN, MAX);
for(unsigned int i = 0; i < MAX_ITERATIONS; ++i){
random = int_distribution(engine);
Event event_x = population.at(random);
random = int_distribution(engine);
Event event_y = population.at(random);
random can take the value MAX, which is out of the bounds of the population vector.
Related
I want to use protocol buffer to send and receive the following type using gRPC
std:array<std::complex<int>, 2> bar_array;
Sources used to get idea: 1, 2
What I have done so far
My approach (Intentionally I am omitting here the unnecessary code)
proto file
syntax = "proto3";
package expcmake;
message child_data {
repeated int32 child_data_list = 1;
}
message Address {
child_data child_data_var = 8;
repeated child_data parent_data_list = 9;
}
server.cpp
Here, at first I have made a dummy std:array<std::complex<int>, 2> data. Then, I have filled the child_data_list with the std::complex<int> data. After each filling of real and imaginary part I have pushed them in the parent_data_list. Also, at this moment I have cleared the child_data_list.
Client message name is NameQuery, while Server message name is Address
In Server side both message are passed as pointer
class AddressBookService final : public expcmake::AddressBook::Service {
public:
virtual ::grpc::Status GetAddress(::grpc::ServerContext* context, const ::expcmake::NameQuery* request, ::expcmake::Address* response)
{
// omitting unnecessary lines
// populate bar_array with std::complex<int> data
std::complex<int> z4 = 1. + 2i, z5 = 1. - 2i; // conjugates
bar_array = {z4, z5};
std::cout << "bar array printing whose size: " << bar_array.size() << std::endl;
for(int i = 0; i < bar_array.size(); i++) {
std::cout << bar_array[i] << " ";
}
std::cout << std::endl;
// Use parent_data_list protocol buffer message type to fill with the content of bar_array
for (int i = 0; i < bar_array.size(); i++){
// Use child_data protocol buffer message type to fill with the content of complex int data
response->mutable_child_data_var()->add_child_data_list(real(bar_array[i]));
response->mutable_child_data_var()->add_child_data_list(imag(bar_array[i]));
// Use parent_data_list protocol buffer message type to fill with the content of child_data -> child_data_list data
response->add_parent_data_list() -> child_data_list();
// clear the child_data message. Reason to keep child_data_list new in every iteration otherwise add_child_data_list will append new data (eg: 1,2,1,-2) which is wrong. Expected is (1,2) then (1,-2)
response->mutable_child_data_var()->clear_child_data_list();
}
// This is zero which I have got. Without clearing it is 4 which is also correct I believe as per the concept of protocol buffer message type
std::cout << "response->mutable_child_data_var()->child_data_list_size(): " << response->mutable_child_data_var()->child_data_list_size() << std::endl;
// This is 2 which meets my requirement
std::cout << "response->parent_data_list_size(): " << response->parent_data_list_size() << std::endl;
// omitting unnecessary lines
}
};
client.cpp
int main(int argc, char* argv[])
{
// Setup request
expcmake::NameQuery query;
expcmake::Address result;
// printing the content of child_data -> child_data_list data array/container. There I have seen 1,2,1,-2 if I don't do the clear operation on child_data_list in server side. So, I guess it is correctly got the data
for(int i = 0; i < result.mutable_child_data_var()->child_data_list_size(); i++)
std::cout << "Child Data at index [" << i << "]: " << result.mutable_child_data_var()->child_data_list(i) << std::endl;
// This one making problem
// printing the content of parent_data_list type/container
// for(int i = 0; i < result.parent_data_list_size(); i++){
// std::cout << "Parent Data at index [" << i << "]: " << result.mutable_parent_data_list(i) << std::endl; // This give me the memory address
// Tried others to fetch the data but failed. Eg: result.parent_data_list(i) // failed
//
// }
}
Snippet from the generated pb file
// repeated int32 child_data_list = 1;
int child_data_list_size() const;
private:
int _internal_child_data_list_size() const;
public:
void clear_child_data_list();
private:
::PROTOBUF_NAMESPACE_ID::int32 _internal_child_data_list(int index) const;
const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >&
_internal_child_data_list() const;
void _internal_add_child_data_list(::PROTOBUF_NAMESPACE_ID::int32 value);
::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >*
_internal_mutable_child_data_list();
public:
::PROTOBUF_NAMESPACE_ID::int32 child_data_list(int index) const;
void set_child_data_list(int index, ::PROTOBUF_NAMESPACE_ID::int32 value);
void add_child_data_list(::PROTOBUF_NAMESPACE_ID::int32 value);
const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >&
child_data_list() const;
::PROTOBUF_NAMESPACE_ID::RepeatedField< ::PROTOBUF_NAMESPACE_ID::int32 >*
mutable_child_data_list();
// .expcmake.child_data child_data_var = 8;
bool has_child_data_var() const;
private:
bool _internal_has_child_data_var() const;
public:
void clear_child_data_var();
const ::expcmake::child_data& child_data_var() const;
PROTOBUF_MUST_USE_RESULT ::expcmake::child_data* release_child_data_var();
::expcmake::child_data* mutable_child_data_var();
void set_allocated_child_data_var(::expcmake::child_data* child_data_var);
private:
const ::expcmake::child_data& _internal_child_data_var() const;
::expcmake::child_data* _internal_mutable_child_data_var();
public:
void unsafe_arena_set_allocated_child_data_var(
::expcmake::child_data* child_data_var);
::expcmake::child_data* unsafe_arena_release_child_data_var();
// repeated .expcmake.child_data parent_data_list = 9;
int parent_data_list_size() const;
private:
int _internal_parent_data_list_size() const;
public:
void clear_parent_data_list();
::expcmake::child_data* mutable_parent_data_list(int index);
::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::expcmake::child_data >*
mutable_parent_data_list();
private:
const ::expcmake::child_data& _internal_parent_data_list(int index) const;
::expcmake::child_data* _internal_add_parent_data_list();
public:
const ::expcmake::child_data& parent_data_list(int index) const;
::expcmake::child_data* add_parent_data_list();
const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::expcmake::child_data >&
parent_data_list() const;
I guess
Is the filling of the message field is incorrectly done !! Though the size is not saying that
I am not catching the protobuf syntax(which is generated in the pb file) in right way to fetch the data
Need suggestions(helpful if can provide the syntax too).
The mutable_* prefixed APIs are for mutating (modifying/adding) elements and they return a pointer. The mutable_* and set_* APIs should only be used while filling the data. Once data is filled, you should not be using mutable_* APIs to check sizes. After receiving the response from the server, the client will most probably be consuming it, not mutating. You need to update the client-side accordingly.
Also, you can use a range-based for loop to iterate over child_data_list of child_data_var like this:
const auto child_data_list = result.child_data_var().child_data_list();
for (const auto element : child_data_list)
{
// process element
}
Apart from that, you're using std::array (a fixed-size array) i.e. std:array<std::complex<int>, 2>, alternatively here's another way to model this without repeated which does not represent a fixed-size array.
complex.proto
syntax = "proto3";
package pb;
message Complex {
int32 real = 1;
int32 imag = 2;
}
message Compound {
Complex c1 = 1;
Complex c2 = 2;
}
The message Complex emulates an std::complex type and Compound an std::array with only 2 elements c1 and c2.
With this, you can easily convert the protobuf message to std::complex and vice versa. Once converted to std::complex, you can perform its supported operations as needed.
Compile complex.proto:
protoc --cpp_out=. ./complex.proto
For the C++ API, look for the accessors in the generated complex.pb.h file under public. The official doc Protocol Buffer Basics: C++ also lists the C++ API examples under The Protocol Buffer API section.
Here's a complete C++ example with the above complex.proto:
main.cpp
#include <iostream>
#include <complex>
#include <array>
#include <cstdlib>
#include "complex.pb.h"
namespace my {
using complex = std::complex<int>;
using compound = std::array<std::complex<int>, 2>;
}
int main()
{
const auto my_c1 = my::complex{ 1, 2 };
const auto my_c2 = my::complex{ 2, 4 };
const auto my_compound_1 = my::compound{ my_c1, my_c2 };
std::cout << "my_compound_1 [size: " << my_compound_1.size() << "]\n";
std::cout << "my_c1: " << my_c1 << '\n';
std::cout << "my_c2: " << my_c2 << '\n';
pb::Compound pb_compound;
pb_compound.mutable_c1()->set_real(my_compound_1[0].real());
pb_compound.mutable_c1()->set_imag(my_compound_1[0].imag());
pb_compound.mutable_c2()->set_real(my_compound_1[1].real());
pb_compound.mutable_c2()->set_imag(my_compound_1[1].imag());
std::cout << "\npb_compound:\n";
pb_compound.PrintDebugString();
const auto serialized_compound = pb_compound.SerializeAsString();
// send
// receive
pb::Compound deserialized_compound;
if (!deserialized_compound.ParseFromString(serialized_compound))
{
std::cerr << "[ERROR] Parsing failed!\n";
return EXIT_FAILURE;
}
std::cout << "\n\npb_compound (deserialized):\n";
deserialized_compound.PrintDebugString();
const auto pb_c1 = deserialized_compound.c1();
const auto pb_c2 = deserialized_compound.c2();
const auto my_c3 = my::complex{ pb_c1.real(), pb_c1.imag() };
const auto my_c4 = my::complex{ pb_c2.real(), pb_c2.imag() };
const auto my_compound_2 = my::compound{ my_c3, my_c4 };
std::cout << "my_compound_2 [size: " << my_compound_2.size() << "]\n";
std::cout << "my_c3: " << my_c3 << '\n';
std::cout << "my_c4: " << my_c4 << '\n';
const auto sum = my_c3 + my_c4;
std::cout << "sum: " << sum << '\n';
return EXIT_SUCCESS;
}
Compile with g++:
g++ main.cpp complex.pb.cc -o pb_complex `pkg-config --cflags --libs protobuf`
Run:
$ ./pb_complex
my_compound_1 [size: 2]
my_c1: (1,2)
my_c2: (2,4)
pb_compound:
c1 {
real: 1
imag: 2
}
c2 {
real: 2
imag: 4
}
pb_compound (deserialized):
c1 {
real: 1
imag: 2
}
c2 {
real: 2
imag: 4
}
my_compound_2 [size: 2]
my_c3: (1,2)
my_c4: (2,4)
sum: (3,6)
The way I was accessing the filed parent_data_list was wrong. I am posting the approach which has solved the issue.
A little change in proto file
syntax = "proto3";
package expcmake;
message child_data {
repeated int32 child_data_list = 1 [packed=true];
}
message Address {
repeated child_data parent_data_list = 1;
}
Reason to use packed see this
server.cpp
class AddressBookService final : public expcmake::AddressBook::Service {
public:
virtual ::grpc::Status GetAddress(::grpc::ServerContext* context, const ::expcmake::NameQuery* request, ::expcmake::Address* response){
// omitting unnecessary lines
// populate bar_array with std::complex<int> data
std::complex<int> z4 = 1. + 2i, z5 = 1. - 2i; // conjugates
bar_array = {z4, z5};
// Now goal is to pass this bar_array as a protobuf message
// Use parent_data_list protocol buffer message type to fill with the content of bar_array
for (int i = 0; i < bar_array.size(); i++){
// make a 2D array. Eg: std::array<std::complex<int>>. In each iteration, new sub_content will be added (here sub_content means child_data_list)
response->add_parent_data_list() -> child_data_list();
// Followings are filling the child_data_list with the required data(Real and Imag part of the complex data which is already generated)
response->mutable_parent_data_list(i)->add_child_data_list(real(bar_array[i]));
response->mutable_parent_data_list(i)->add_child_data_list(imag(bar_array[i]));
}
}
return grpc::Status::OK;
};
After the completion of the iteration, A 2D type of message will be generated which is parent_data_list = [[child_data_list], [child_data_list]]. Don't consider it as a real scenario. Just for presentation I am using it.
client.cpp
std::cout <<"Using Mutable" << std::endl;
for(int i = 0; i < result.parent_data_list_size(); i++){
for(int j = 0 ; j<result.mutable_parent_data_list(i)->child_data_list_size(); j++){
std::cout << "Value [" << i << "][" << j << "]: " << result.mutable_parent_data_list(i)->child_data_list(j) << std::endl;
}
}
// Following is same as before. Added as I was in turmoil to understand the properties generated by protobuf. Hope could be helpful for beginners like me
std::cout <<"Without Mutable property" << std::endl;
for(int i = 0; i < result.parent_data_list_size(); i++){
for(int j = 0 ; j < result.parent_data_list(i).child_data_list_size(); j++){
std::cout << "Value [" << i << "][" << j << "]: " << result.parent_data_list(i).child_data_list(j) << std::endl;
}
}
In client side I am accessing the child_data_list with index which is not properly mimic the C++ style. Would be great if I can in one line print the value of parent_data_list[n] data. As far I have studied the generated pb.h file my understanding is that it is not possible as no return function I have not found without index for the repeated field. Or may be I am missing something important again.
I am quite fresh in coding C code, trying to use FFTW from the well-known website http://www.fftw.org/ in my Visual Studio 2019.
I followed the tutorial (https://www.youtube.com/watch?v=geYbCA137PU), but an error appeared: LNK1104 cannot open file 'libfftw3-3.lib'
How should I solve the problem? I have googled it, but looks like most of the solution not quite suitable to mine. Almost the last step! Please!
#include <iostream>
#include <fftw3.h>
using namespace std;
//macros for real and imaginary parts
#define REAL 0
#define IMAG 1
//length of complex array
#define N 8
/*Computes the 1-D fast Fourier transform*/
void fft(fftw_complex* in, fftw_complex* out)
{
// creat a DFT plan
fftw_plan plan = fftw_plan_dft_1d(N, in, out, FFTW_FORWARD, FFTW_ESTIMATE);
// execute the plan
fftw_execute(plan);
// do some cleaning
fftw_destroy_plan(plan);
fftw_cleanup();
}
/*Computes the 1-D inverse fast Fourier transform*/
void ifft(fftw_complex* in, fftw_complex* out)
{
// creat a IDFT plan
fftw_plan plan = fftw_plan_dft_1d(N, in, out, FFTW_BACKWARD, FFTW_ESTIMATE);
// execute the plan
fftw_execute(plan);
// do some cleaning
fftw_destroy_plan(plan);
fftw_cleanup();
// scale the output to obtain the exact inverse
for (int i = 0; i < N; ++i) {
out[i][REAL] /= N;
out[i][IMAG] /= N;
}
}
/*Display complex numbers in the form a +/- bi. */
void displayComplex(fftw_complex* y)
{
for (int i = 0; i < N; ++i)
if (y[i][IMAG] < 0)
cout << y[i][REAL] << " - " << abs(y[i][IMAG]) << "i" << endl;
else
cout << y[i][REAL] << " + " << y[i][IMAG] << "i" << endl;
}
/*Display real part of complex number*/
void displayReal(fftw_complex* y)
{
for (int i = 0; i < N; ++i)
cout << y[i][REAL] << endl;
}
/* Test */
int main()
{
// input array
fftw_complex x[N];
// output array
fftw_complex y[N];
// fill the first of some numbers
for (int i = 0; i < N; ++i) {
x[i][REAL] = i + 1; // i.e.{1 2 3 4 5 6 7 8}
x[i][IMAG] = 0;
}
// compute the FFT of x and store the result in y.
fft(x, y);
// display the result
cout << "FFT =" << endl;
displayComplex(y);
// compute the IFFT of x and store the result in y.
ifft(y, x);
// display the result
cout << "\nIFFT =" << endl;
displayReal(x);
}
#HAL9000 Thanks for your remind, I found out that I have converted the wrong name of .def so I generated a "libfftw3-3l.lib". That's why it couldn't open the file, it has been solved now!
#include <iostream>
#include <exception>
using namespace std;
class Inventory{
friend istream& operator>>(istream&, Inventory);
friend ostream& operator<<(ostream&, Inventory);
private:
int stock;
int quant;
int price;
public:
Inventory(int=0,int=0,double=0);
};
Inventory::Inventory(int s, int q, double p){
stock=s;
quant=q;
price=p;
}
istream& operator>>(istream& in, Inventory){
int s;
int q;
double p;
cout << "Enter stock number: ";
in >> s;
cout << "Enter quantity: ";
in >> q;
cout << "Enter price: ";
in >>p;
Inventory inv(s,q,p);
return in;
}
ostream& operator<<(ostream& out, Inventory inv){
out << "The stock number is: " << inv.stock << endl << "The quantity is: " <<
inv.quant << endl << "The price is: " << inv.price << endl;
return out;
}
int main()
{
Inventory inv[5]={};
for(int i = 0; i <5; i++){
cin >> inv[i];
}
cout<<"------------------------" << endl;
for(int i=0;i<5;i++){
cout<<inv[i];
cout<<"------------------------" << endl;
}
return 0;
}
I can not figure out why when I use the overloaded << operator in the for loop it is displaying zero's, am I not storing the price, quantity and price to the object array correctly? I have tried not using a contructor and using one it did not make a difference, any ideas why the integers and double are not storing to the array?
Your were close! See my // change here comment markers (there are several) in the code below.
The 0's had nothing to do with the << overload, but rather the >> overload.
The deal is that you can use the 'in' istream to input directly to the class variables (without trying to call some other function, or a need for extra variables) in the >> overload, but you need to pass an Inventory reference to do so.
I was surprised that there was no error trying to set primitives to 0 in the constructor parameters?? (I'm likely very 'rusty' on newer C++ handling, been over 15+ years for me), but anyway:
#include <iostream>
#include <exception>
using namespace std;
class Inventory{
friend istream& operator>>(istream&, Inventory&); // change here (Inventory reference)
friend ostream& operator<<(ostream&, Inventory);
private:
int stock;
int quant;
double price; // change here
public:
Inventory(int,int,double); // change here
};
Inventory::Inventory(int s = 0, int q = 0, double p = 0){ // change here
stock=s;
quant=q;
price=p;
}
istream& operator>>(istream& in, Inventory& inv){ // change here (inventory reference)
// change here (removed variables)
cout << "Enter stock number: ";
in >> inv.stock; // change here
cout << "Enter quantity: ";
in >> inv.quant; // change here
cout << "Enter price: ";
in >> inv.price; // change here
// change here (removed function call)
return in;
}
ostream& operator<<(ostream& out, Inventory inv){
out << "The stock number is: " << inv.stock << endl << "The quantity is: " <<
inv.quant << endl << "The price is: " << inv.price << endl;
return out;
}
int main()
{
const int ITEMS = 5; // change here (constant to replace hard-coded value)
Inventory inv[ITEMS]={}; // change here (use the constant)
for(int i = 0; i <ITEMS; i++){ // change here (use the constant)
cin >> inv[i];
}
cout<<"------------------------" << endl;
for(int i=0;i<ITEMS;i++){ // change here (use the constant)
cout<<inv[i];
cout<<"------------------------" << endl;
}
return 0;
}
Give that a run and see how it goes:
Here's my example output when I changed the constant (my change inside the main function) to 2 for a basic test run:
Enter stock number: 123
Enter quantity: 4
Enter price: 2.1
Enter stock number: 467
Enter quantity: 1
Enter price: 1.2
------------------------
The stock number is: 123
The quantity is: 4
The price is: 2.1
------------------------
The stock number is: 467
The quantity is: 1
The price is: 1.2
------------------------
I am trying to write a function to perform a sparse Cholesky decomposition using the Eigen library, where I pass in both the pointers to the input matrix data and the pointers to where I want to store the output matrix.
The program is currently
#include <iostream>
#include <Eigen/Dense>
#include <Eigen/SparseCore>
#include <Eigen/SparseCholesky>
using namespace std;
using namespace Eigen;
struct CSC {
int *indptr;
int *indices;
double *data;
int nnz;
};
int cholesky_sparse_d_c(struct CSC *A, struct CSC *L,
int rows, int cols, int nnz) {
// Find sparse Cholesky factorisation of matrix A and store in triangular
// matrix L i.e A = L L.T.
// First we must build the sparse matrix A.
Map<SparseMatrix <double> > A_sp(rows, cols, nnz,
A->indptr, A->indices, A->data);
cout << "A: " << endl << A_sp << endl;
// Now compute the sparse Cholesky decomposition.
SimplicialLLT<SparseMatrix<double> > SLLT;
SLLT.compute(A_sp);
if (SLLT.info() != Success) {
cout << "Decomposition failed";
return -1;
}
cout << "Sparse lower factor of A:" << endl << SLLT.matrixL()
<< endl;
// Put the values back into L. Note I am not sure if we need to create a
// `temp` variable here, as the call `.matrixL()` may be free.
SparseMatrix<double > temp(SLLT.matrixL());
L->indptr = (int *) temp.outerIndexPtr();
L->indices = (int *) temp.innerIndexPtr();
L->data = (double *) temp.valuePtr();
L->nnz = (int) temp.nonZeros();
Map<SparseMatrix <double> > L_sp(rows, cols, L->nnz,
L->indptr, L->indices, L->data);
cout << "L: " << endl << L_sp << endl;
return 0;
}
int main() {
struct CSC A;
int A_indptr[] = {0, 1, 2};
int A_indices[] = {0, 1};
double A_data[] = {1.1, 2.2};
A.indptr = A_indptr;
A.indices = A_indices;
A.data = A_data;
struct CSC L;
cholesky_sparse_d_c(&A, &L, 2, 2, 2);
cout << L.indptr[0] << L.indptr[1] << L.indptr[2] << endl;
cout << L.indices[0] << L.indices[1] << L.indices[2] << endl;
cout << L.data[0] << L.data[1] << L.data[2] << endl;
}
As mentioned in the code, I am not sure if the temp variable is necessary as
L_indptr = SLLT.matrixL().outerIndexPtr();
L_indices = SLLT.matrixL().innerIndexPtr();
L_data = SLLT.matrixL().valuePtr();
may be fine (I am not sure if matrixL() is a free operation).
Regardless, when this function exits the memory that the L pointers were pointing to will now be free'd. I could copy the memory but this is unnecessary and inefficient. What I would ideally like to do is tell SLLT to not create new pointers for
.outerIndexPtr()
.innerIndexPtr()
.valuePtr()
but to use the pointers in the L structure provided.
Is there a way to do this?
If you insist on saving a copy (it should be very cheep compared to the decomposition), then the simplest and safest would be to keep SLLT alive as long as your L, for instance by creating a small structure storing both objects and being responsible for destroying both of them.
Otherwise, you could imagine moving SLLT.matrixL() into L, but then you'll have to free the allocated memories, but you cannot as you don't know how it was allocated. To allocate yourself L and pass it SLLT, you need a way to exactly know the number of non-zeros in L. Actually, this information is computed by the analyzePattern step, but this method also pre-allocate SLLT.matrixL(), so that's too late.
I am looking for a more faster way of dealing with the following C code. I have an image of 640x480 and I want to decimate it by a factor of 2 by removing every other rows and columns in the image. I have attached the code in the following. Is there any better way to optimize the code.
#define INPUT_NUM_ROW 480
#define INPUT_NUM_COL 640
#define OUTPUT_NUM_ROW 240
#define OUTPUT_NUM_COL 320
unsigned char inputBuf[INPUT_NUM_ROW* INPUT_NUM_COL];
unsigned char outputBuf[OUTPUT_NUM_ROW* OUTPUT_NUM_COL];
void imageDecimate(unsigned char *outputImage , unsigned char *inputImage)
{
/* Fill in your code here */
for (int p = 0; p< OUTPUT_NUM_ROW; p++) {
for (int q = 0; q < OUTPUT_NUM_COL; q++) {
outputImage[p*OUTPUT_NUM_COL + q] = inputImage[(p*INPUT_NUM_COL+q)*2];
// cout << "The pixel at " << p*OUTPUT_NUM_COL+q << " is " << outputImage[p*OUTPUT_NUM_COL+q] << endl;
}
}
}
Rather than doing the math every time in the inner loop, you could do this:
int outputIndex;
int inputIndex;
for (int p = 0; p< OUTPUT_NUM_ROW; p++) {
inputIndex = p * INPUT_NUM_COL * 2;
outputIndex = p * OUTPUT_NUM_COL;
for (int q = 0; q < OUTPUT_NUM_COL; q++) {
outputImage[outputIndex] = inputImage[inputIndex];
inputIndex += 2;
outputIndex++;
// cout << "The pixel at " << p*OUTPUT_NUM_COL+q << " is " << outputImage[p*OUTPUT_NUM_COL+q] << endl;
}
}
}
You could do the incrementing inline with the copying assignment too, and you could also only assign inputIndex and outputIndex the first time, but it wouldn't get you as much of a performance boost as moving the calculation out of the inner loop. I assume that bulk copying functions don't have this kind of incrementing flexibility, but if they do and they use hardware acceleration that is available on all of your target platforms, then that would be a better choice.
I am also assuming that array access like this compiles down to the most optimized pointer arithmetic that you could use.