File: mpi_kmeans_mex.cxx

package info (click to toggle)
libmpikmeans 1.5%2Bdfsg-7
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 332 kB
  • sloc: cpp: 1,673; makefile: 148; python: 56; sh: 5
file content (161 lines) | stat: -rw-r--r-- 3,536 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#include <memory.h>
#include "mex.h"
#include "mpi_kmeans.h"
#include <assert.h>

void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{

#ifdef COMPILE_WITH_ICC
	unsigned int dims[2];
#else
	mwSize dims[2];
#endif

	if (nrhs < 2){
		mexPrintf("at least two input arguments expected.");
		return;
	}
	unsigned int maxiter = 0;
	if (nrhs > 2)
		maxiter = (unsigned int) *(mxGetPr(prhs[2]));
	
	unsigned int restarts = 0;
	if (nrhs > 3)
		restarts = (unsigned int) *(mxGetPr(prhs[3]));

#ifdef KMEANS_VERBOSE
	if (restarts>0)
		printf("will do %d restarts\n",restarts);
#endif

	if ((nlhs > 3) || (nlhs < 1)){
		mexPrintf("minimal one, maximal three output arguments expected.");
		return;
	}

#ifdef INPUT_TYPE
#if INPUT_TYPE==0
	if (!mxIsDouble(prhs[0]) || mxIsComplex(prhs[0]) ||
		mxGetNumberOfDimensions(prhs[0]) != 2)
	{
		mexPrintf("input 1 (X) must be a real double matrix");
		return;
	}
#elif INPUT_TYPE==1
	if (!mxIsSingle(prhs[0]) || mxIsComplex(prhs[0]) ||
		mxGetNumberOfDimensions(prhs[0]) != 2)
	{
		mexPrintf("input 1 (X) must be a real single matrix");
		return;
	}
#endif
#endif

	unsigned int dim = mxGetM(prhs[0]);
	unsigned int npts = mxGetN(prhs[0]);

	unsigned int nclus = 0;
	if (mxGetN(prhs[1])==1 && mxGetM(prhs[1])==1)
		nclus = (unsigned int)*(mxGetPr(prhs[1]));
	else
	{
		nclus = mxGetN(prhs[1]);
		if (dim != mxGetM(prhs[1]))
			mexErrMsgTxt("Dimension mismatch");
	}
	if (nclus == 0)
		mexErrMsgTxt("Number of Clusters is zero");

	if (npts < nclus)
		mexErrMsgTxt("less training points than clusters to compute");

	if (mxIsSingle(prhs[1]))
		printf("Is Single!\n");


	if (mxIsComplex(prhs[1]) ||
		mxGetNumberOfDimensions(prhs[1]) != 2)
	{
		mexPrintf("input 2 (CX) must be a real double matrix compatible with input 1 (X)");
		return;
	}

	dims[0] = dim;
	dims[1] = nclus;

#ifdef INPUT_TYPE
#if INPUT_TYPE==0
	//plhs[0] = mxCreateDoubleMatrix(dim, nclus, mxREAL);
	plhs[0] = mxCreateNumericArray(2, dims, mxDOUBLE_CLASS, mxREAL);
#elif INPUT_TYPE==2


	plhs[0] = mxCreateNumericArray(2, dims, mxSINGLE_CLASS, mxREAL);
#endif
#endif

	PREC *CXp = (PREC*)mxGetPr(plhs[0]);

	/* input points */
	const PREC *X = (PREC*)mxGetPr(prhs[0]);

	/* sanity check */
	for (unsigned int i=0 ; i<npts*dim; i++)
		if (mxIsNaN(X[i])||mxIsInf(X[i]))
			mexErrMsgTxt("NaN or Inf in the input data detected... abort");


	/* return also the assignment */
	unsigned int *assignment = NULL;
	if (nlhs>2) 
	{
		dims[0] = npts;
		dims[1] = 1;
		plhs[2] = mxCreateNumericArray(2,dims,mxUINT32_CLASS,mxREAL);
		assignment = (unsigned int*)mxGetPr(plhs[2]);
	}
	else
		assignment = (unsigned int *) malloc(npts * sizeof(unsigned int)); 	/* assignement of points to cluster */

	assert(assignment);

	if ((mxGetN(prhs[1])==mxGetM(prhs[1]))==1)
	{
		/* select nclus points from data at random... */
		unsigned int *order = (unsigned int*)malloc(npts * sizeof(unsigned int));
		randperm(order,npts);
		for ( unsigned int i=0; i<nclus; i++)
			for (unsigned int k=0; k<dim; k++ )
				CXp[(i*dim)+k] = (double)X[order[i]*dim+k];
		free(order);
	}
	else
	{
		/* ... or copy initial guess to CXp */
		memcpy(CXp,mxGetPr(prhs[1]),dim*nclus*sizeof(PREC));
	}

	/* start kmeans */
	PREC sse = kmeans(CXp,X,assignment,dim,npts,nclus,maxiter,restarts);

	if (nlhs>1)
	{
		plhs[1] = mxCreateScalarDouble(0.0);
		PREC *psse = (PREC*)mxGetPr(plhs[1]);
		psse[0] = sse;
	}

	/* return also the assignment */
	if (nlhs>2)
	{
		for ( unsigned int i=0; i<npts; i++)
			assignment[i]++;
	}
	else
		free(assignment);
}