I've a written a function to calculate the correlation matrix for variables (risks) held in a flat file structure. I.e. RiskID | Year | Amount
I have written the function because the library routines that I can find necessitate a matrix input. That is, RiskID as 2nd dimension and year as the 1st dimension - with amounts as actual array values. The matrix needs to be complete, in that zero values must be included also and hence for sparsely populated non zero data - this leads to wasted iterations which can be bypassed. The routine relies upon the data being sorted first by Year (asc) then by RiskID (asc)
I have written the routine in C++ (for speed) to be compiled as a dll and referenced in VB.NET. I need to pass 3 arrays (one each for each of the headers) and return a 2 dimensional array back to VB.NET. I guess I'm cheating by passing 3 individual 1d arrays instead of a 2d array but there you go. I'll post the full C++ routine as others may find it useful if seeking to do something similar. I'd be surprised if this hasn't been done before - but I just can't find it.
I lack the interop knowledge to implement this properly and am getting nowhere googling around. As far as I can workout I may need to use SAFEARRAY ?
Or is there a quick fix to this problem? Or is SAFEARRAY a piece of cake. Either way an example would be very helpful.
Also, as a side note - I'm sure the memory management is failing somewhere?
Here is the Visual C++ (VS2013)
Header File
#ifndef CorrelLib_EXPORTS
#define CorrelLib_API __declspec(dllexport)
#else
#define CorrelLib_API __declspec(dllimport)
#endif
// Returns correlation matrix for values in flat file
extern "C" CorrelLib_API double** __stdcall CalcMatrix(int* Risk, int* Year, double* Loss, const int& RowNo, const int& RiskNo, const int& NoSimYear);
CPP File
#include "stdafx.h"
#include "CorrelLib.h"
#include <memory>
#include <ctime>
using namespace std;
extern "C" CorrelLib_API double** __stdcall CalcMatrix(int* Risk, int* Year, double* Loss, const int& RowNo, const int& RiskNo, const int& NoSimYear)
{
int a, b;
int i, j, k;
int YearCount, MissingYears;
int RowTrack;
//Relies on Year and Risk being sorted in ascending order in those respective orders Year asc, Risk asc
double *RiskTrack = new double[RiskNo](); //array of pointers?
int *RiskTrackBool = new int[RiskNo](); //() sets inital values to zero
double *RiskAvg = new double[RiskNo]();
double *RiskSD = new double[RiskNo]();
//Create 2d array to hold results 'array of pointers to 1D arrays of doubles'
double** Res = new double*[RiskNo];
for (i = 0; i < RiskNo; ++i)
{
Res[i] = new double[RiskNo](); //()sets initial values to zero
}
//calculate average
for (i = 0; i < RowNo; i++)
{
a = Risk[i];
RiskAvg[a] = RiskAvg[a] + Loss[i];
}
for (i = 0; i < RiskNo; i++)
{
RiskAvg[i] = RiskAvg[i] / NoSimYear;
}
//Enter Main Loop
YearCount = 0;
i = 0; //start at first row
do {
YearCount = YearCount + 1;
a = Risk[i];
RiskTrack[a] = Loss[i] - RiskAvg[a];
RiskTrackBool[a] = 1;
j = i + 1;
do
{
if (Year[j] != Year[i])
{
break;
}
b = (int)Risk[j];
RiskTrack[b] = Loss[j] - RiskAvg[b];
RiskTrackBool[b] = 1;
j = j + 1;
} while (j < RowNo);
RowTrack = j;
//check through RiskTrack and if no entry set to 0 - avg
for (j = 0; j < RiskNo; j++)
{
if (RiskTrackBool[j] == 0)
{
RiskTrack[j] = -1.0 * RiskAvg[j];
RiskTrackBool[j] = 1;
}
}
//Now loop through and perform calcs
for (j = 0; j < RiskNo; j++)
{
//SD
RiskSD[j] = RiskSD[j] + RiskTrack[j] * RiskTrack[j];
//Covar
for (k = j + 1; k < RiskNo; k++)
{
Res[j][k] = Res[j][k] + RiskTrack[j] * RiskTrack[k];
}
}
//Reset RiskTrack
for (k = 0; k<RiskNo; k++)
{
RiskTrack[k] = 0.0;
RiskTrackBool[k] = 0;
}
i = RowTrack;
} while (i < RowNo);
//Account For Missing Years
MissingYears = NoSimYear - YearCount;
for (i = 0; i < RiskNo; i++)
{
//SD
RiskSD[i] = RiskSD[i] + MissingYears * RiskAvg[i] * RiskAvg[i];
//Covar
for (j = i + 1; j < RiskNo; j++)
{
Res[i][j] = Res[i][j] + MissingYears * RiskAvg[i] * RiskAvg[j];
}
}
//Covariance Matrix
for (i = 0; i < RiskNo; i++)
{
//SD
RiskSD[i] = sqrt(RiskSD[i] / (NoSimYear - 1));
if (RiskSD[i] == 0.0)
{
RiskSD[i] = 1.0;
}
//Covar
for (j = i + 1; j < RiskNo; j++)
{
Res[i][j] = Res[i][j] / (NoSimYear - 1);
}
}
//Correlation Matrix
for (i = 0; i < RiskNo; i++)
{
Res[i][i] = 1.0;
for (j = i + 1; j < RiskNo; j++)
{
Res[i][j] = Res[i][j] / (RiskSD[i] * RiskSD[j]);
}
}
//Clean up
delete[] RiskTrack;
delete[] RiskTrackBool;
delete[] RiskAvg;
delete[] RiskSD;
//Return Array
return Res;
}
Def File
LIBRARY CorrelLib
EXPORTS
CalcMatrix
VB.NET
I've created a simple winform with a button which triggers the code below. I wish to link to the dll, pass the arrays and receive the result as a 2d array.
Imports System
Imports System.Runtime.InteropServices
Public Class Form1
<DllImport("CorrelLib.dll", EntryPoint:="CalcMatrix", CallingConvention:=CallingConvention.StdCall)> _
Public Shared Function CorrelMatrix2(ByRef Risk_FE As Integer, ByRef Year_FE As Integer, ByRef Loss_FE As Double, _
ByRef RowNo As Long, ByRef RiskNo As Long, ByRef NoSimYear As Long) As Double(,)
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim i As Integer, j As Integer
Dim Risk() As Long, Year() As Long, Loss() As Double
Dim NoRisks As Long, NoSimYear As Long, NoRows As Long
Dim counter As Long
Dim Result(,) As Double
NoRisks = 50
NoSimYear = 10000
NoRows = NoRisks * NoSimYear
ReDim Risk(0 To NoRows - 1), Year(0 To NoRows - 1), Loss(0 To NoRows - 1)
counter = 0
For i = 1 To NoSimYear
For j = 1 To NoRisks
Risk(counter) = j
Year(counter) = i
Loss(counter) = CDbl(Math.Floor((1000000 - 1 + 1) * Rnd())) + 1
counter = counter + 1
Next j
Next i
Dim dllDirectory As String = "C:\Users\Documents\Visual Studio 2013\Projects\CorrelLibTestForm"
Environment.SetEnvironmentVariable("PATH", Environment.GetEnvironmentVariable("PATH") + ";" + dllDirectory)
Result = CorrelMatrix2(Risk(1), Year(1), Loss(1), NoRows, NoRisks, NoSimYear)
End Sub
End Class
Current Error Message
An unhandled exception of type >'System.Runtime.InteropServices.MarshalDirectiveException' occurred in >CorrelLibTestForm.exe
Additional information: Cannot marshal 'return value': Invalid >managed/unmanaged type combination.
A double ** pointer to a pointer is not the same with a 2 dimension array in vb. Your best bet is to return just a pointer:
double *pdbl;
pdbl = &res[0][0];
return pdbl; //pdbl points to the first element
In vb you use an IntPtr to get the pointer:
Dim Result As IntPtr = Marshal.AllocHGlobal(4)
Dim dbl As Double
Result = CorrelMatrix2(Risk(1), Year(1), Loss(1), NoRows, NoRisks, NoSimYear)
//derefference the double pointer, i(integer) is actually the index in the array of doubles
dbl = CType(Marshal.PtrToStructure(IntPtr.Add(Result, i * 8), GetType(Double)), Double)
Your res array in c++ function needs to be public so the memory allocated to it is valid after the function returns.
Related
This question already exists:
How to implement convolution algorithm with SSE?
Closed 1 year ago.
My goal is to implement exactly that algorithm using only CPU and using SSE:
My array's sizes a multiple of 4 and they are aligned:
const int INPUT_SIGNAL_ARRAY_SIZE = 256896;
const int IMPULSE_RESPONSE_ARRAY_SIZE = 318264;
const int OUTPUT_SIGNAL_ARRAY_SIZE = INPUT_SIGNAL_ARRAY_SIZE + IMPULSE_RESPONSE_ARRAY_SIZE;
__declspec(align(16)) float inputSignal_dArray[INPUT_SIGNAL_ARRAY_SIZE];
__declspec(align(16)) float impulseResponse_dArray[IMPULSE_RESPONSE_ARRAY_SIZE];
__declspec(align(16)) float outputSignal_dArray[OUTPUT_SIGNAL_ARRAY_SIZE];
I have written CPU "method" and it works correctly:
//#pragma optimize( "", off )
void computeConvolutionOutputCPU(float* inputSignal, float* impulseResponse, float* outputSignal) {
float* pInputSignal = inputSignal;
float* pImpulseResponse = impulseResponse;
float* pOutputSignal = outputSignal;
#pragma loop(no_vector)
for (int i = 0; i < OUTPUT_SIGNAL_ARRAY_SIZE; i++)
{
*(pOutputSignal + i) = 0;
#pragma loop(no_vector)
for (int j = 0; j < IMPULSE_RESPONSE_ARRAY_SIZE; j++)
{
if (i - j >= 0 && i - j < INPUT_SIGNAL_ARRAY_SIZE)
{
*(pOutputSignal + i) = *(pOutputSignal + i) + *(pImpulseResponse + j) * (*(pInputSignal + i - j));
}
}
}
}
//#pragma optimize( "", on )
On the other hand I should use function with SSE. I tried the following code:
void computeConvolutionOutputSSE(float* inputSignal, float* impulseResponse, float* outputSignal) {
__m128* pInputSignal = (__m128*) inputSignal;
__m128* pImpulseResponse = (__m128*) impulseResponse;
__m128* pOutputSignal = (__m128*) outputSignal;
int nOuterLoop = OUTPUT_SIGNAL_ARRAY_SIZE / 4;
int nInnerLoop = IMPULSE_RESPONSE_ARRAY_SIZE / 4;
int quarterOfInputSignal = INPUT_SIGNAL_ARRAY_SIZE / 4;
__m128 m0 = _mm_set_ps1(0);
for (int i = 0; i < nOuterLoop; i++)
{
*(pOutputSignal + i) = m0;
for (int j = 0; j < nInnerLoop; j++)
{
if ((i - j) >= 0 && (i - j) < quarterOfInputSignal)
{
*(pOutputSignal + i) = _mm_add_ps(
*(pOutputSignal + i),
_mm_mul_ps(*(pImpulseResponse + j), *(pInputSignal + i - j))
);
}
}
}
}
And function above works not correct and produces not the same values like CPU.
The problem was specified on stackoverflow with following comment :
*(pInputSignal + i - j) is incorrect in case of SSE, because it's not an i-j offset away from current value, it's (i-j) * 4 . THe thing is,
as I remember it, the idea of using pointer that way is incorrect
unless intrinsics had changed since then - in my time one had to
"load" values into an instance of __m128 in this case, as H(J) and
X(I-J) are in unaligned location (and sequence breaks).
and
Since you care about individual floats and their order, probably best
to use const float*, with _mm_loadu_ps instead of just dereferencing
(which is like _mm_load_ps). That way you can easily do unaligned
loads that get the floats you want into the vector element positions
you want, and the pointer math works the same as for scalar. You just
have to take into account that load(ptr) actually gets you a vector of
elements from ptr+0..3.
But I can't use this information because have no idea how to properly access array with SSE in this case.
you need 128-bit float32 value , not msvc float.
see _mm_broadcast_ss
This question already has answers here:
C: using clock() to measure time in multi-threaded programs
(2 answers)
Closed 2 years ago.
I am implementing pattern matching algorithm, by moving template gradient info over entire target's gradient image , that too at each rotation (-60 to 60). I have already saved the template info for each rotation ,i.e. 121 templates are already preprocessed and saved.
But the issue is, this is consuming lot of time (approx 110ms), so decided to split the matching at set of rotations (-60 to -30 , -30 to 0, 0 to 30 and 30 to 60) into 4 threads, but threading is taking more time that single process (approx 115ms to 120ms).
Snippet of code is...
#define MAXTARGETNUM 64
MatchResultA totalResultsTemp[MAXTARGETNUM];
void CShapeMatch::match(ShapeInfo *ShapeInfoVec, search_region SearchRegion, float MinScore, float Greediness, int width,int height, int16_t *pBufGradX ,int16_t *pBufGradY,float *pBufMag, bool corr)
{
MatchResultA resultsPerDeg[MAXTARGETNUM];
....
....
int startX = SearchRegion.StartX;
int startY = SearchRegion.StartY;
int endX = SearchRegion.EndX;
int endY = SearchRegion.EndY;
float AngleStep = SearchRegion.AngleStep;
float AngleStart = SearchRegion.AngleStart;
float AngleStop = SearchRegion.AngleStop;
int startIndex = (int)(ShapeInfoVec[0].AngleNum/2) + ShapeInfoVec[0].AngleNum%2+(int)AngleStart/AngleStep;
int stopIndex = (int)(ShapeInfoVec[0].AngleNum/2) + ShapeInfoVec[0].AngleNum%2+(int)AngleStop/AngleStep;
for (int k = startIndex; k < stopIndex ; k++){
....
for(int j = startY; j < endY; j++){
for(int i = startX; i < endX; i++){
for(int m = 0; m < ShapeInfoVec[k].NoOfCordinates; m++)
{
curX = i + (ShapeInfoVec[k].Coordinates + m)->x; // template X coordinate
curY = j + (ShapeInfoVec[k].Coordinates + m)->y ; // template Y coordinate
iTx = *(ShapeInfoVec[k].EdgeDerivativeX + m); // template X derivative
iTy = *(ShapeInfoVec[k].EdgeDerivativeY + m); // template Y derivative
iTm = *(ShapeInfoVec[k].EdgeMagnitude + m); // template gradients magnitude
if(curX < 0 ||curY < 0||curX > width-1 ||curY > height-1)
continue;
offSet = curY*width + curX;
iSx = *(pBufGradX + offSet); // get corresponding X derivative from source image
iSy = *(pBufGradY + offSet); // get corresponding Y derivative from source image
iSm = *(pBufMag + offSet);
if (PartialScore > MinScore)
{
float Angle = ShapeInfoVec[k].Angel;
bool hasFlag = false;
for(int n = 0; n < resultsNumPerDegree; n++)
{
if(abs(resultsPerDeg[n].CenterLocX - i) < 5 && abs(resultsPerDeg[n].CenterLocY - j) < 5)
{
hasFlag = true;
if(resultsPerDeg[n].ResultScore < PartialScore)
{
resultsPerDeg[n].Angel = Angle;
resultsPerDeg[n].CenterLocX = i;
resultsPerDeg[n].CenterLocY = j;
resultsPerDeg[n].ResultScore = PartialScore;
break;
}
}
}
if(!hasFlag)
{
resultsPerDeg[resultsNumPerDegree].Angel = Angle;
resultsPerDeg[resultsNumPerDegree].CenterLocX = i;
resultsPerDeg[resultsNumPerDegree].CenterLocY = j;
resultsPerDeg[resultsNumPerDegree].ResultScore = PartialScore;
resultsNumPerDegree ++;
}
minScoreTemp = minScoreTemp < PartialScore ? PartialScore : minScoreTemp;
}
}
}
for(int i = 0; i < resultsNumPerDegree; i++)
{
mtx.lock();
totalResultsTemp[totalResultsNum] = resultsPerDeg[i];
totalResultsNum++;
mtx.unlock();
}
n++;
}
void CallerFunction(){
int16_t *pBufGradX = (int16_t *) malloc(bufferSize * sizeof(int16_t));
int16_t *pBufGradY = (int16_t *) malloc(bufferSize * sizeof(int16_t));
float *pBufMag = (float *) malloc(bufferSize * sizeof(float));
clock_t start = clock();
float temp_stop = SearchRegion->AngleStop;
SearchRegion->AngleStop = -30;
thread t1(&CShapeMatch::match, this, ShapeInfoVec, *SearchRegion, MinScore, Greediness, width, height, pBufGradX ,pBufGradY,pBufMag, corr);
SearchRegion->AngleStart = -30;
SearchRegion->AngleStop=0;
thread t2(&CShapeMatch::match, this, ShapeInfoVec, *SearchRegion, MinScore, Greediness, width, height, pBufGradX ,pBufGradY,pBufMag, corr);
SearchRegion->AngleStart = 0;
SearchRegion->AngleStop=30;
thread t3(&CShapeMatch::match, this, ShapeInfoVec, *SearchRegion, MinScore, Greediness,width, height, pBufGradX ,pBufGradY,pBufMag, corr);
SearchRegion->AngleStart = 30;
SearchRegion->AngleStop=temp_stop;
thread t4(&CShapeMatch::match, this, ShapeInfoVec, *SearchRegion, MinScore, Greediness,width, height, pBufGradX ,pBufGradY,pBufMag, corr);
t1.join();
t2.join();
t3.join();
t4.join();
clock_t end = clock();
cout << 1000*(double)(end-start)/CLOCKS_PER_SEC << endl;
}
As we can see there are plenty of heap access but they just are read-only. Only totalResultTemp and totalResultNum are shared global resource on which write are performed.
My PC configuration is,
i5-7200U CPU # 2.50GHz 4 cores
4 Gig RAM
Ubuntu 18
for(int i = 0; i < resultsNumPerDegree; i++)
{
mtx.lock();
totalResultsTemp[totalResultsNum] = resultsPerDeg[i];
totalResultsNum++;
mtx.unlock();
}
You writing into static array, and mutexes are really time consuming. Instead of creating locks try to use std::atomic_int, or in my opinion even better, just pass to function exact place where to store result, so problem with sync is not your problem anymore
POSIX Threads in c/c++ are not concurrent since the time assigned by the operative system to each parent process must be split into the number of threads it has. Thus, your algorithm is executing only core. To leverage multicore technology, you must use OpenMP. This interface library let you split your algorithm in different physic cores. This is a good OpenMP tutorial
For empty vector Fun1 returns 0. Function Fun2, which should be equivalent to Fun1 (only one small change, see below), crashes with error vector subscript out of range. Any ideas why is that?
Code run in Visual Studio 2017
int Fun1(vector<int> service_times) {
sort(service_times.begin(), service_times.end());
int sum = 0;
int sumi = 0;
int st = service_times.size() - 1;//condition stired in variable
for (int i = 0; i < st; i++)
{
sumi += service_times[i];
sum = sum + sumi;
}
return sum;
}
int Fun2(vector<int> service_times) {
sort(service_times.begin(), service_times.end());
int sum = 0;
int sumi = 0;
for (int i = 0; i < (service_times.size() - 1); i++)//condition
//directly written
{
sumi += service_times[i];
sum = sum + sumi;
}
return sum;
}
Since service_times is an empty vector, service_times.size() ought to return 0, no?
No. It returns size_t(0), which is an unsigned type. Therefore, service_times.size() - 1 is a unsigned - signed operation, where the signed value (1) is "promoted" to unsigned type. Therefore, 0 - 1 is actually numeric_limits<size_t>::max().
In the first function, you saved it by storing it again in an int variable: it becomes -1 again. Therefore, i < st is i < -1, which worked incidentally. However, in the second function, i < st is actually i < <some ultra big value>, which, LOL.
I am making a 3D application where a boat has to drive through buoy tracks. I also need to store the tracks in groups or "layouts". The buoys class is basically a list of "buoy layouts" inside of which is a list of "buoy tracks", inside of which is a list of buoys.
I checked the local variable watcher and all memory allocations in the constructor appear to work. Later when the calculateCoordinates function is called it enters a for loop. On the first iteration of the for loop the functions pointer is used and works fine, but then on this line
ctMain[j+1][1] = 0;
the function pointers are set to NULL. I am guessing it has something to with the structs not being allocated or addressed correctly. I am not sure what to do from here. Maybe I am not understanding how malloc is working.
Update
I replaced the M3DVector3d main_track with double ** main_track, thinking maybe malloc is not handling the typedefs correctly. But I am getting the same error when trying to access the main_track variable later in calculateCoordinates.
Update
It ended up being memory corruption caused by accessing a pointer wrong in the line
rotatePointD(&(cTrack->main_track[j]), rotation);
It only led to an error later when I tried to access it.
// Buoys.h
////////////////////////////////////////////
struct buoy_layout_t;
struct buoy_track_t;
typedef double M3DVector3d[3];
class Buoys {
public:
Buoys();
struct buoy_layout_t ** buoyLayouts;
int nTrackLayouts;
int currentLayoutID;
void calculateCoordinates();
};
struct buoy_track_t {
int nMain, nYellow, nDistract;
M3DVector3d * main_track,
yellow_buoys,
distraction_buoys;
double (*f)(double x);
double (*fp)(double x);
double thickness;
M3DVector3d start, end;
};
struct buoy_layout_t {
int nTracks;
buoy_track_t ** tracks;
};
// Buoys.cpp
/////////////////////////////
// polynomial and its derivative, for shape of track
double buoyfun1(double x) {return (1.0/292.0)*x*(x-12.0)*(x-24.0);}
double buoyfun1d(double x) {return (1.0/292.0)*((3.0*pow(x,2))-(72.0*x)+288.0);}
// ... rest of buoy shape functions go here ...
Buoys::Buoys() {
struct buoy_layout_t * cLayout;
struct buoy_track_t * cTrack;
nTrackLayouts = 1;
buoyLayouts = (buoy_layout_t **) malloc(nTrackLayouts*sizeof(*buoyLayouts));
for (int i = 0; i < nTrackLayouts; i++) {
buoyLayouts[i] = (buoy_layout_t *) malloc(sizeof(*(buoyLayouts[0])));
}
currentLayoutID = 0;
// ** Layout 1 **
cLayout = buoyLayouts[0];
cLayout->nTracks = 1;
cLayout->tracks = (buoy_track_t **) malloc(sizeof(*(cLayout->tracks)));
for (int i = 0; i < 1; i++) {
cLayout->tracks[i] = (buoy_track_t *) malloc (sizeof(*(cLayout->tracks)));
}
cTrack = cLayout->tracks[0];
cTrack->main_track = (M3DVector3d *) malloc(30*sizeof(*(cTrack->main_track)));
cTrack->nMain = 30;
cTrack->f = buoyfun1;
cTrack->fp = buoyfun1d;
cTrack->thickness = 5.5;
cTrack->start[0] = 0; cTrack->start[1] = 0; cTrack->start[2] = 0;
cTrack->end[0] = 30; cTrack->end[1] = 0; cTrack->end[2] = -19;
// ... initialize rest of layouts here ...
// ** Layout 2 **
// ** Layout 3 **
// ...
// ** Layout N **
calculateCoordinates();
}
void Buoys::calculateCoordinates()
{
int i, j;
buoy_layout_t * cLayout = buoyLayouts[0];
for (i = 0; i < (cLayout->nTracks); i++) {
buoy_track_t * cTrack = cLayout->tracks[i];
M3DVector3d * ctMain = cTrack->main_track;
double thickness = cTrack->thickness;
double rotation = getAngleD(cTrack->start[0], cTrack->start[2],
cTrack->end[0], cTrack->end[2]);
double full_disp = sqrt(pow((cTrack->end[0] - cTrack->start[0]), 2)
+ pow((cTrack->end[2] - cTrack->start[2]), 2));
// nBuoys is nBuoys per side. So one side has nBuoys/2 buoys.
for (j=0; j < cTrack->nMain; j+=2) {
double id = j*((full_disp)/(cTrack->nMain));
double y = (*(cTrack->f))(id);
double yp = (*(cTrack->fp))(id);
double normal, normal_a;
if (yp!=0) {
normal = -1.0/yp;
}
else {
normal = 999999999;
}
if (normal > 0) {
normal_a = atan(normal);
}
else {
normal_a = atan(normal) + PI;
}
ctMain[j][0] = id + ((thickness/2.0)*cos(normal_a));
ctMain[j][1] = 0;
ctMain[j][2] = y + ((thickness/2.0)*sin(normal_a));
ctMain[j+1][0] = id + ((thickness/2.0)*cos(normal_a+PI));
ctMain[j+1][1] = 0; // function pointers get set to null here
ctMain[j+1][2] = y + ((thickness/2.0)*sin(normal_a+PI));
}
for (j=0; j < cTrack->nMain; j++) {
rotatePointD(&(cTrack->main_track[j]), rotation);
}
}
}
Unless there are requirements for learning pointers or you cannot use STL, given you are using C++ I'd strongly recommend you use more STL, it is your friend. But anyways...
First, the type of ctMain is *M3DVector3D. So you can safely access ctMain[0], but you cannot access ctMain[1], maybe you meant for the type of ctMain to be **M3DVector3D, in which case the line for initialization you had written which is:
cTrack->main_track = (M3DVector3d *) malloc(30*sizeof(*(cTrack->main_track)));
would make sense.
More Notes
Why are you allocating 30 of these here?
cTrack->main_track = (M3DVector3d *) malloc(30*sizeof(*(cTrack->main_track)));
Given the type of main_track, you only need:
cTrack->main_track = (M3DVector3d *) malloc(sizeof(M3DVector3d));
In addition, for organizational purposes, when doing sizeof you may want to give the actual type to check the sizeof, as opposed to the variable (there should be no difference, just organizational), these two changes:
buoyLayouts = (buoy_layout_t **) malloc(nTrackLayouts*sizeof(buoy_layout_t*));
for (int i = 0; i < nTrackLayouts; i++) {
buoyLayouts[i] = (buoy_layout_t *) malloc(sizeof(buoy_layout_t));
}
cLayout->tracks = (buoy_track_t **) malloc(clayout->nTracks * sizeof(buoy_track_t*));
for (int i = 0; i < 1; i++) {
cLayout->tracks[i] = (buoy_track_t *) malloc(sizeof(buoy_track_t));
}
I'm fairly new to C++ and I'm attempting to learn how to use pointers. I have the following file that creates coordinates and then moves them in random directions using a random number generator.
The value sigmaf_point is inputted from a text file:
void methane_coords(double *&sigmaf_point)
double dummy_int = 1;
string dummystring;
string s;
ifstream Dfile;
std::stringstream out;
out << 1;
s = out.str() + ".TXT";
Dfile.open (s.c_str());
if (Dfile.fail())
{
return;
}
for (int i=0; i<dummy_int; i++)
{
Dfile >> sigmaf_point[i];
}
Which I then use in another function:
double initial_energy(double **coords_fluid, const double *box_size){
// Loop over all pairs of atoms and calculate the LJ energy
double total_energy = 0;
for (int i = 0; i <= n_atoms-1; i++)
{
sf1=sigmaf_point(coords_fluid[i][3]);
ef1=epsilonf_point(coords_fluid[i][3]);
// Energy fluid-fluid
for (int j = i+1; j <= n_atoms-1; j++)
{
sf2=sigmaf_point(coords_fluid[j][3]);
ef2=epsilonf_point(coords_fluid[j][3]);
double delta_x = coords_fluid[j][0] - coords_fluid[i][0];
double delta_y = coords_fluid[j][1] - coords_fluid[i][1];
double delta_z = coords_fluid[j][2] - coords_fluid[i][2];
// Apply periodic boundaries
delta_x = make_periodic(delta_x, box_size[0]);
delta_y = make_periodic(delta_y, box_size[1]);
delta_z = make_periodic(delta_z, box_size[2]);
// Calculate the LJ potential
s=(sf1+sf2)/2.0;
e=pow((ef1*ef2),0.5);
double r = pow((delta_x*delta_x) + (delta_y*delta_y) +
(delta_z*delta_z),0.5)/s;
double e_lj = 4*((1/pow(r,12.0))-(1/pow(r,6.0))/e);
total_energy = (total_energy + e_lj);
}
}
coords_fluid is created in the main file like so:
double **coords_fluid = new double*[5000];
Now the problem is with sf1=sigmaf_point(coords_fluid[i][3]);
I get the error "expression must have pointer to function type" for sigmaf_point. I'm a bit confused about this, I know it's about how I call the variable but can't seem to fix it.
Cheers
First of all: Rereference to pointers are completly useless since it a pointer is already a sort of reference.
So change double *& to double * or double &. It will be faster.
Besides I see that you're using sigmaf_point as a function and as an array.
Which one is it?
Could you give the declaration of sigmaf_point?
Assuming it's an array change
sf1 = sigmaf_point(coords_fluid[i][3]);
to
sf1 = sigmaf_point[coords_fluid[i][3]];