-
Notifications
You must be signed in to change notification settings - Fork 1
/
matSubVec.c
94 lines (83 loc) · 2.79 KB
/
matSubVec.c
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
#include "mex.h"
#include "matrix.h"
/*
* Function to subtract a vector from a matrix without having to use
* repmat. Both have to be real for now. Aligns the vector by
* whichever dimension of tha matrix matches. If both dimensions of
* the matrix match, uses the current orientation of the vector.
*
* Copyright (C) 2005 Michael Mandel, mim at ee columbia edu;
* distributable under GPL
*/
void doMath(int mM, int mN, int vM, int vN,
double* mData, double* vData, double*rData);
void mexFunction (int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
if(nlhs > 1)
mexErrMsgTxt("Requires at most 1 output argument.");
if(nrhs != 2)
mexErrMsgTxt("Requires 2 input arguments.");
const mxArray *mat = prhs[0];
const mxArray *vec = prhs[1];
int mM = mxGetM(mat), mN = mxGetN(mat);
int vM = mxGetM(vec), vN = mxGetN(vec);
if(mM != vM && mM != vN && mN != vM && mN != vN)
mexErrMsgTxt("Matrix not compatible with vector");
/* Make return argument */
mxArray *res;
if(mxIsComplex(mat) || mxIsComplex(vec))
res = mxCreateDoubleMatrix(mM, mN, mxCOMPLEX);
else
res = mxCreateDoubleMatrix(mM, mN, mxREAL);
plhs[0] = res;
/* Always do real parts */
doMath(mM,mN,vM,vN,mxGetPr(mat),mxGetPr(vec),mxGetPr(res));
/* Figure out whether to do imaginary parts */
if(mxIsComplex(mat) && !mxIsComplex(vec)) {
/* Matrix complex, vector real, copy the matrix over to result */
int i;
double* mData = mxGetPi(mat);
double* rData = mxGetPi(res);
for(i = 0; i<mM*mN; i++)
rData[i] = mData[i];
} else if(mxIsComplex(vec) && !mxIsComplex(mat)) {
/* Res is initialized to all 0s, right? Matrix real, vector
complex. Subtract vector from a matrix of all zeros, i.e. the
imaginary part of the result matrix. */
doMath(mM,mN,vM,vN,mxGetPi(res),mxGetPi(vec),mxGetPi(res));
} else if(mxIsComplex(res)) {
/* Both matrix and vector are complex, easy to handle. */
doMath(mM,mN,vM,vN,mxGetPi(mat),mxGetPi(vec),mxGetPi(res));
}
}
void doMath(int mM, int mN, int vM, int vN,
double* mData, double* vData, double*rData)
{
int i,j;
if(mM == mN) {
/* Special case for square matrices */
if(vM < vN) {
/* row vector */
for(j = 0; j < mN; j++)
for(i = 0; i < mM; i++)
rData[i + j*mM] = mData[i + j*mM] - vData[j];
} else {
/* column vector */
for(j = 0; j < mN; j++)
for(i = 0; i < mM; i++)
rData[i + j*mM] = mData[i + j*mM] - vData[i];
}
} else {
if(mM == vM || mM == vN) {
/* Vector matches columns */
for(j = 0; j < mN; j++)
for(i = 0; i < mM; i++)
rData[i + j*mM] = mData[i + j*mM] - vData[i];
} else {
/* Vector matches rows */
for(j = 0; j < mN; j++)
for(i = 0; i < mM; i++)
rData[i + j*mM] = mData[i + j*mM] - vData[j];
}
}
}