wolffd@0
|
1 /*
|
wolffd@0
|
2 mex -c mexutil.c
|
wolffd@0
|
3 mex repmat.c mexutil.obj
|
wolffd@0
|
4 to check for warnings:
|
wolffd@0
|
5 gcc -Wall -I/cygdrive/c/MATLAB6p1/extern/include -c repmat.c
|
wolffd@0
|
6 */
|
wolffd@0
|
7 #include "mexutil.h"
|
wolffd@0
|
8 #include <string.h>
|
wolffd@0
|
9
|
wolffd@0
|
10 /* repeat a block of memory rep times */
|
wolffd@0
|
11 void memrep(char *dest, size_t chunk, int rep)
|
wolffd@0
|
12 {
|
wolffd@0
|
13 #if 0
|
wolffd@0
|
14 /* slow way */
|
wolffd@0
|
15 int i;
|
wolffd@0
|
16 char *p = dest;
|
wolffd@0
|
17 for(i=1;i<rep;i++) {
|
wolffd@0
|
18 p += chunk;
|
wolffd@0
|
19 memcpy(p, dest, chunk);
|
wolffd@0
|
20 }
|
wolffd@0
|
21 #else
|
wolffd@0
|
22 /* fast way */
|
wolffd@0
|
23 if(rep == 1) return;
|
wolffd@0
|
24 memcpy(dest + chunk, dest, chunk);
|
wolffd@0
|
25 if(rep & 1) {
|
wolffd@0
|
26 dest += chunk;
|
wolffd@0
|
27 memcpy(dest + chunk, dest, chunk);
|
wolffd@0
|
28 }
|
wolffd@0
|
29 /* now repeat using a block twice as big */
|
wolffd@0
|
30 memrep(dest, chunk<<1, rep>>1);
|
wolffd@0
|
31 #endif
|
wolffd@0
|
32 }
|
wolffd@0
|
33
|
wolffd@0
|
34 void repmat(char *dest, const char *src, int ndim, int *destdimsize,
|
wolffd@0
|
35 int *dimsize, const int *dims, int *rep)
|
wolffd@0
|
36 {
|
wolffd@0
|
37 int d = ndim-1;
|
wolffd@0
|
38 int i, chunk;
|
wolffd@0
|
39 /* copy the first repetition into dest */
|
wolffd@0
|
40 if(d == 0) {
|
wolffd@0
|
41 chunk = dimsize[0];
|
wolffd@0
|
42 memcpy(dest,src,chunk);
|
wolffd@0
|
43 }
|
wolffd@0
|
44 else {
|
wolffd@0
|
45 /* recursively repeat each slice of src */
|
wolffd@0
|
46 for(i=0;i<dims[d];i++) {
|
wolffd@0
|
47 repmat(dest + i*destdimsize[d-1], src + i*dimsize[d-1],
|
wolffd@0
|
48 ndim-1, destdimsize, dimsize, dims, rep);
|
wolffd@0
|
49 }
|
wolffd@0
|
50 chunk = destdimsize[d-1]*dims[d];
|
wolffd@0
|
51 }
|
wolffd@0
|
52 /* copy the result rep-1 times */
|
wolffd@0
|
53 memrep(dest,chunk,rep[d]);
|
wolffd@0
|
54 }
|
wolffd@0
|
55
|
wolffd@0
|
56 void mexFunction(int nlhs, mxArray *plhs[],
|
wolffd@0
|
57 int nrhs, const mxArray *prhs[])
|
wolffd@0
|
58 {
|
wolffd@0
|
59 const mxArray *srcmat;
|
wolffd@0
|
60 int ndim, *dimsize, eltsize;
|
wolffd@0
|
61 const int *dims;
|
wolffd@0
|
62 int ndimdest, *destdims, *destdimsize;
|
wolffd@0
|
63 char *src, *dest;
|
wolffd@0
|
64 int *rep;
|
wolffd@0
|
65 int i,nrep;
|
wolffd@0
|
66 int extra_rep = 1;
|
wolffd@0
|
67 int empty;
|
wolffd@0
|
68
|
wolffd@0
|
69 if(nrhs < 2) mexErrMsgTxt("Usage: xrepmat(A, [N M ...])");
|
wolffd@0
|
70 srcmat = prhs[0];
|
wolffd@0
|
71 if(mxIsSparse(srcmat)) {
|
wolffd@0
|
72 mexErrMsgTxt("Sorry, can't handle sparse matrices yet.");
|
wolffd@0
|
73 }
|
wolffd@0
|
74 if(mxIsCell(srcmat)) {
|
wolffd@0
|
75 mexErrMsgTxt("Sorry, can't handle cell arrays yet.");
|
wolffd@0
|
76 }
|
wolffd@0
|
77 ndim = mxGetNumberOfDimensions(srcmat);
|
wolffd@0
|
78 dims = mxGetDimensions(srcmat);
|
wolffd@0
|
79 eltsize = mxGetElementSize(srcmat);
|
wolffd@0
|
80
|
wolffd@0
|
81 /* compute dimension sizes */
|
wolffd@0
|
82 dimsize = mxCalloc(ndim, sizeof(int));
|
wolffd@0
|
83 dimsize[0] = eltsize*dims[0];
|
wolffd@0
|
84 for(i=1;i<ndim;i++) dimsize[i] = dimsize[i-1]*dims[i];
|
wolffd@0
|
85
|
wolffd@0
|
86 /* determine repetition vector */
|
wolffd@0
|
87 ndimdest = ndim;
|
wolffd@0
|
88 if(nrhs == 2) {
|
wolffd@0
|
89 nrep = mxGetN(prhs[1]);
|
wolffd@0
|
90 if(nrep > ndimdest) ndimdest = nrep;
|
wolffd@0
|
91 rep = mxCalloc(ndimdest, sizeof(int));
|
wolffd@0
|
92 for(i=0;i<nrep;i++) {
|
wolffd@0
|
93 double repv = mxGetPr(prhs[1])[i];
|
wolffd@0
|
94 rep[i] = (int)repv;
|
wolffd@0
|
95 }
|
wolffd@0
|
96 if(nrep == 1) {
|
wolffd@0
|
97 /* special behavior */
|
wolffd@0
|
98 nrep = 2;
|
wolffd@0
|
99 rep[1] = rep[0];
|
wolffd@0
|
100 }
|
wolffd@0
|
101 }
|
wolffd@0
|
102 else {
|
wolffd@0
|
103 nrep = nrhs-1;
|
wolffd@0
|
104 if(nrep > ndimdest) ndimdest = nrep;
|
wolffd@0
|
105 rep = mxCalloc(ndimdest, sizeof(int));
|
wolffd@0
|
106 for(i=0;i<nrep;i++) {
|
wolffd@0
|
107 rep[i] = (int)*mxGetPr(prhs[i+1]);
|
wolffd@0
|
108 }
|
wolffd@0
|
109 }
|
wolffd@0
|
110 for(i=nrep;i<ndimdest;i++) rep[i] = 1;
|
wolffd@0
|
111
|
wolffd@0
|
112 /* compute output size */
|
wolffd@0
|
113 destdims = mxCalloc(ndimdest, sizeof(int));
|
wolffd@0
|
114 for(i=0;i<ndim;i++) destdims[i] = dims[i]*rep[i];
|
wolffd@0
|
115 for(;i<ndimdest;i++) {
|
wolffd@0
|
116 destdims[i] = rep[i];
|
wolffd@0
|
117 extra_rep *= rep[i];
|
wolffd@0
|
118 }
|
wolffd@0
|
119 destdimsize = mxCalloc(ndim, sizeof(int));
|
wolffd@0
|
120 destdimsize[0] = eltsize*destdims[0];
|
wolffd@0
|
121 for(i=1;i<ndim;i++) destdimsize[i] = destdimsize[i-1]*destdims[i];
|
wolffd@0
|
122
|
wolffd@0
|
123
|
wolffd@0
|
124 /* for speed, array should be uninitialized */
|
wolffd@0
|
125 plhs[0] = mxCreateNumericArray(ndimdest, destdims, mxGetClassID(srcmat),
|
wolffd@0
|
126 mxIsComplex(srcmat)?mxCOMPLEX:mxREAL);
|
wolffd@0
|
127
|
wolffd@0
|
128 /* if any rep[i] == 0, output should be empty array.
|
wolffd@0
|
129 Added by KPM 11/13/02.
|
wolffd@0
|
130 */
|
wolffd@0
|
131 empty = 0;
|
wolffd@0
|
132 for (i=0; i < nrep; i++) {
|
wolffd@0
|
133 if (rep[i]==0)
|
wolffd@0
|
134 empty = 1;
|
wolffd@0
|
135 }
|
wolffd@0
|
136 if (empty)
|
wolffd@0
|
137 return;
|
wolffd@0
|
138
|
wolffd@0
|
139 src = (char*)mxGetData(srcmat);
|
wolffd@0
|
140 dest = (char*)mxGetData(plhs[0]);
|
wolffd@0
|
141 repmat(dest,src,ndim,destdimsize,dimsize,dims,rep);
|
wolffd@0
|
142 if(ndimdest > ndim) memrep(dest,destdimsize[ndim-1],extra_rep);
|
wolffd@0
|
143 if(mxIsComplex(srcmat)) {
|
wolffd@0
|
144 src = (char*)mxGetPi(srcmat);
|
wolffd@0
|
145 dest = (char*)mxGetPi(plhs[0]);
|
wolffd@0
|
146 repmat(dest,src,ndim,destdimsize,dimsize,dims,rep);
|
wolffd@0
|
147 if(ndimdest > ndim) memrep(dest,destdimsize[ndim-1],extra_rep);
|
wolffd@0
|
148 }
|
wolffd@0
|
149 }
|