a b/util/im2colstep.c
1
/**************************************************************************
2
 *
3
 * File name: im2colstep.c
4
 *
5
 * Ron Rubinstein
6
 * Computer Science Department
7
 * Technion, Haifa 32000 Israel
8
 * ronrubin@cs
9
 *
10
 * Last Updated: 31.8.2009
11
 *
12
 *************************************************************************/
13
14
15
#include "mex.h"
16
#include <string.h>
17
18
19
/* Input Arguments */
20
21
#define X_IN     prhs[0]
22
#define SZ_IN  prhs[1]
23
#define S_IN   prhs[2]
24
25
26
/* Output Arguments */
27
28
#define B_OUT   plhs[0]
29
30
31
void mexFunction(int nlhs, mxArray *plhs[], 
32
                     int nrhs, const mxArray*prhs[])
33
     
34
{ 
35
    double *x, *b, *s;
36
    mwSize sz[3], stepsize[3], n[3], ndims;
37
    mwIndex i, j, k, l, m, blocknum;
38
    
39
    
40
    /* Check for proper number of arguments */
41
    
42
    if (nrhs < 2 || nrhs > 3) {
43
      mexErrMsgTxt("Invalid number of input arguments."); 
44
    } else if (nlhs > 1) {
45
      mexErrMsgTxt("Too many output arguments."); 
46
    } 
47
    
48
    
49
    /* Check the the input dimensions */ 
50
    
51
    ndims = mxGetNumberOfDimensions(X_IN);
52
    
53
    if (!mxIsDouble(X_IN) || mxIsComplex(X_IN) || ndims>3) {
54
      mexErrMsgTxt("X should be a 2-D or 3-D double matrix.");
55
    }
56
    if (!mxIsDouble(SZ_IN) || mxIsComplex(SZ_IN) || mxGetNumberOfDimensions(SZ_IN)>2 || mxGetM(SZ_IN)*mxGetN(SZ_IN)!=ndims) {
57
      mexErrMsgTxt("Invalid block size.");
58
    }
59
    if (nrhs == 3) {
60
      if (!mxIsDouble(S_IN) || mxIsComplex(S_IN) || mxGetNumberOfDimensions(S_IN)>2 || mxGetM(S_IN)*mxGetN(S_IN)!=ndims) {
61
        mexErrMsgTxt("Invalid step size.");
62
      }
63
    }
64
    
65
    
66
    /* Get parameters */
67
    
68
    s = mxGetPr(SZ_IN);
69
    if (s[0]<1 || s[1]<1 || (ndims==3 && s[2]<1)) {
70
      mexErrMsgTxt("Invalid block size.");
71
    }
72
    sz[0] = (mwSize)(s[0] + 0.01);
73
    sz[1] = (mwSize)(s[1] + 0.01);
74
    sz[2] = ndims==3 ? (mwSize)(s[2] + 0.01) : 1;
75
    
76
    if (nrhs == 3) {
77
      s = mxGetPr(S_IN);
78
      if (s[0]<1 || s[1]<1 || (ndims==3 && s[2]<1)) {
79
        mexErrMsgTxt("Invalid step size.");
80
      }
81
      stepsize[0] = (mwSize)(s[0] + 0.01);
82
      stepsize[1] = (mwSize)(s[1] + 0.01);
83
      stepsize[2] = ndims==3 ? (mwSize)(s[2] + 0.01) : 1;
84
    }
85
    else {
86
      stepsize[0] = stepsize[1] = stepsize[2] = 1;
87
    }
88
    
89
    n[0] = (mxGetDimensions(X_IN))[0];
90
    n[1] = (mxGetDimensions(X_IN))[1];
91
    n[2] = ndims==3 ? (mxGetDimensions(X_IN))[2] : 1;
92
    
93
    if (n[0]<sz[0] || n[1]<sz[1] || (ndims==3 && n[2]<sz[2])) {
94
      mexErrMsgTxt("Block size too large.");
95
    }
96
    
97
    
98
    /* Create a matrix for the return argument */
99
    
100
    B_OUT = mxCreateDoubleMatrix(sz[0]*sz[1]*sz[2], ((n[0]-sz[0])/stepsize[0]+1)*((n[1]-sz[1])/stepsize[1]+1)*((n[2]-sz[2])/stepsize[2]+1), mxREAL);
101
    
102
    
103
    /* Assign pointers */
104
    
105
    x = mxGetPr(X_IN);
106
    b = mxGetPr(B_OUT);
107
            
108
    
109
    /* Do the actual computation */
110
    
111
    blocknum = 0;
112
    
113
    /* iterate over all blocks */
114
    for (k=0; k<=n[2]-sz[2]; k+=stepsize[2]) {
115
      for (j=0; j<=n[1]-sz[1]; j+=stepsize[1]) {
116
        for (i=0; i<=n[0]-sz[0]; i+=stepsize[0]) {
117
          
118
          /* copy single block */
119
          for (m=0; m<sz[2]; m++) {
120
            for (l=0; l<sz[1]; l++) {
121
              memcpy(b + blocknum*sz[0]*sz[1]*sz[2] + m*sz[0]*sz[1] + l*sz[0], x+(k+m)*n[0]*n[1]+(j+l)*n[0]+i, sz[0]*sizeof(double));
122
            }
123
          }
124
          blocknum++;
125
          
126
        }
127
      }
128
    }
129
    
130
    return;
131
}