# How to Loop in mexfunction?

2 views (last 30 days)
Chang seok Ma on 13 Feb 2021
Commented: Chang seok Ma on 20 Feb 2021
Hello,
I am working on 2d array in mexfunction. And I have a couple of questions about it.
This is the example that I modify a code that I found on the website.
/*==========================================================
* arrayMultiplier.c
*
* Multiplies a 1xN matrix with a N X N matrix
* and outputs a 1xN matrix
*
* The calling syntax is:
* outMatrix = arrayProduct(vector, array)
*========================================================*/
#include "mex.h"
/* The computational routine */
void arrayMultiplier( double *vec, double *arr, int n, int temp ,double *z){
temp = temp + 1;
for (int i=0; i<n; i++) {
for(int j=0; j<n; j++) {
z[i] += vec[j] * arr[j+i*n];
}
}
}
/* The gateway function */
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[]) {
double *vec;
double *arr;
int nr;
double *outMatrix;
int tempr;
vec = mxGetPr(prhs[0]);
arr = mxGetPr(prhs[1]); /* This is where the warning appears */
nr = mxGetScalar(prhs[2]); /*The "n" parameter of the 1 x n output matrix*/
tempr = mxGetScalar(prhs[3]);
/* creating the output matrix */
plhs[0] = mxCreateDoubleMatrix(1,nr,mxREAL);
/* get a pointer to the real data in the output matrix */
outMatrix = mxGetPr(plhs[0]);
/* call the computational routine */
arrayMultiplier(vec,arr,nr,tempr,outMatrix);
}
After this I made .m file
clear all;
clc;
tic
cd 'C:\Users\chang\Desktop\New Folder'
mex testing.c
% ================ 1. Parameters and Constants ============================
numb = 1
A = [1,2,3,4];
B = [1,2,3,4;5,6,7,8;1,2,3,4;5,6,7,8];
AAA = testing(A, B, 4, numb);
I thought by running this code, I should get numb = 2 becasue I added temp = temp +1 in the .c file
Then I got right answer for A*B but numb is still 1 which is quite different from what I expected.
This is quite a simple version of what I am trying to do.
I am trying to use 'while' in the code but everytime I run the code it just run one time and never repeat.
while (it <= itmax) {
it = it ++;
Then I found out that 'temp = temp + 1' doesn't work as what I expected.
Any solutions?
P.S
Is there a way to have matrix multiplication inside mex function?
So that I can just just have A = matrixMultiply(B,C) instead of using for loop to get A.

James Tursa on 13 Feb 2021
Edited: James Tursa on 13 Feb 2021
You have a fundamental misunderstanding of how the C language works with pass-by-value scalar arguments. In this code:
void arrayMultiplier( double *vec, double *arr, int n, int temp ,double *z){ /* (1) */
temp = temp + 1; /* (2) */
:
void mexFunction( int nlhs, mxArray *plhs[],
int nrhs, const mxArray *prhs[]) {
int tempr;
tempr = mxGetScalar(prhs[3]); /* (3) */
arrayMultiplier(vec,arr,nr,tempr,outMatrix); /* (4) */
You pass in numb from MATLAB. In (3) above you get a copy of numb and place it in the tempr variable. From that point on you are working with the copy, not the original. So there is no way to alter the original numb by modifying tempr. Additionally, in (4) you pass tempr by value to the arrayMultiplier function. That means in (1) the temp variable is a copy of the tempr variable. You are not working with tempr directly anymore. So in (2) when you add 1 to temp, you are adding 1 to the copy and this has no effect on the original tempr variable.
There are ways to alter the MATLAB numb variable inplace in a mex routine using data pointers, but this violates the const attribute of prhs[ ] and is not advised because it can have nasty side effects.
You also asked about how to multiply matrices in mex functions without using loops. The short answer is to simply call the same BLAS library function that MATLAB uses in the background for matrix multiplies, which is dgemm for full double precision variables. You can see the interface here:
Some instructions for doing this in MATLAB can be found here:
James Tursa on 19 Feb 2021
Edited: James Tursa on 19 Feb 2021
Yes, same problem. C is an uninitialized pointer in mexFunction. So you pass it down to your functions and write into it and bad things happen. You need to allocate C first. E.g., you could put this in your mexFunction:
C = (double *) mxMalloc(m*n*sizeof(*C));
secondfn(A, m, n, C, P);
mxFree(C):
Chang seok Ma on 20 Feb 2021
Oh I get it.
However I think this only works in Case1. which only have small size matrices.
If I use somewhat bigger size matrices as it is in Case2, I get different results each time I run the code.
Do you think this is just a code error or is there any other thing that I am missing?
Thank you so much for all the comments. I really appreciate it.
#include "mex.h"
void firstfn(double *Af, double *Bf, size_t m, size_t n, size_t p, double *Df){
for(size_t k = 1; k <= n; k++){
for(size_t i = m*(k-1); i < m*k; i++){
size_t temp = i - m*(k-1);
for(size_t j = 0; j < p; j++){
Df[i] += Af[temp+j*m] * Bf[j+p*(k-1)] ;
}
}
}
}
void secondfn(double *As, double *Bs, size_t m, size_t n, size_t p, double *Ds, double *Ps){
firstfn(As, Bs, m, n, p, Ds);
for (size_t i = 0; i < m*n; i++){
Ps[i] = Ds[i];
}
}
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
{
double *A, *B, *D, *P; /* pointers to input & output matrices*/
size_t m,n,p; /* matrix dimensions */
A = mxGetPr(prhs[0]); /* first input matrix */
B = mxGetPr(prhs[1]); /* second input matrix */
m = mxGetM(prhs[0]); /* dimensions of input matrices */
p = mxGetN(prhs[0]);
n = mxGetN(prhs[1]);
plhs[0] = mxCreateDoubleMatrix(m, n, mxREAL);
P = mxGetPr(plhs[0]);
D = (double *) mxMalloc(m*n*sizeof(*D));
//secondfn(A, B, m, n, p, D, P);
secondfn(A, B, m, n, p, D, P);
mxFree(D);
}
Case 1.
A = [1 2 3 4 ;1 2 3 4 ];
B = [3 4 5 6 ; 7 8 9 10 ; 11 12 13 14 ; 7 8 9 10];
Case 2.
A= 2* ones(320,3);
B = [1/3 1/3 1/3]';