w4nderlust wrote: > That's the way i'm working right now. > Really not right now, because i discovered a bug in the single thread > version and i'm correcting it at this time. Can you help me about it? > The problem is this: if the result matrix is a vector 1xn or nx1 the > final c.transpose() gives a segmentation fault. I really can't > understand why. > You can easly reproduce the problem addint a true as third parameter > to the function (it calculates only the diagonal values and returns it > in a colum vector). > Like: > A = sprand(400, 400, 0.02); > B = sprand(400, 400, 0.02); > Z= fl_spcompose(A, B, true); > > I attach the code >
I really have no idea what your code is trying to do, but trying to decypt what you've written and rewriting, I'd suggest the attached instead.. I suspect the code doesn't do what you want however as the matrix A is only checked at elements where the matrix B is non zero. D.
#include <octave/oct.h> #include <octave/parse.h> #define HELP " -- Loadable Function: C = fl_spcompose (A, B)\n -- Loadable Function: C = fl_spcompose (A, B, LOCK)\n -- Loadable Function: C = fl_spcompose (A, B, T)\n -- Loadable Function: C = fl_spcompose (A, B, T, S)\n -- Loadable Function: C = fl_spcompose (A, B, LOCK, T)\n\nReturns the T-Norm / S-Norm composition as basic inference mechanism of Fuzzy\nLogic. By default, it calculates the max-min composition.\n\nA and B must be matrices with conformant dimensions as in matrix product.\n\nWhen true, the boolean LOCK option forces to calculate the diagonal results\nonly and returns it as a column vector.\n\nThe arguments T and S allows you to specify a custom T-Norm and S-Norm function\nrespectively. They can be:\n - 'min': use the minimum function (default for T-Norm);\n - 'pro': use the product function;\n - 'max': use the maximum function (default for S-Norm);\n - 'sum': use the sum function;\n - function_handle: a user-defined function (at most 2 arguments).\n\nNote that only the predefined functions are calculated rapidly and in\nmultithread mode. Using a user-defined function as T-Norm and/or S-Norm\nwill result in a long time calculation. \n\n\n\n\n" #define MIN_ARG 2 #define MAX_ARG 4 #define STR_MINNORM "min" #define STR_PRONORM "pro" #define STR_MAXNORM "max" #define STR_SUMNORM "sum" #define ERR_INVALIDFUNC "fl_spcompose: the specified T-Norm or S-Norm function is invalid!\nPlease read help for details" #define ERR_ARG "fl_spcompose: invalid arguments number!\n" #define ERR_MATRIXSIZE "fl_spcompose: incompatible matrices dimensions\n" #define ERR_MATRIXTYPE "fl_spcompose: the first two argument must be matrices\n" #define ERR_LOCKOPTION "fl_spcompose: the lock_option must be 0 or 1\n" // Functions prototype declaration double (*calc_tnorm)(double,double); double (*calc_snorm)(double,double); double func_min(double first, double second); double func_prod(double first, double second); double func_max(double first, double second); double func_sum(double first, double second); double func_custom_tnorm(double first, double second); double func_custom_snorm(double first, double second); int checkFunction(octave_function *func); int assignFunction(octave_value arg, int tnorm); // T-Norm and S-Norm function pointers octave_function *tnorm; octave_function *snorm; /* Main function - Check the arguments and call the compose method */ DEFUN_DLD (fl_spcompose, args, nargout, HELP) { int numargs = args.length(); // Arguments number // Set the lock_option to default value (0) bool lockoption = false; // Set the T-Norm and S-Norm function pointer to default value // (Minimum and Maximum) calc_tnorm = func_min; calc_snorm = func_max; // Check if the argument number is correct if(numargs < MIN_ARG || numargs > MAX_ARG) { error(ERR_ARG); return octave_value_list(); } // Check if the first two arguments are matrices if(!args(0).is_matrix_type() || !args(1).is_matrix_type()) { error(ERR_MATRIXTYPE); return octave_value_list(); } // Analyze the third argument (can be the lockoption, a custom T-Norm // or a default string for T-Norm) if(numargs > 2) { // Check if the third argument is the lockoption. if(args(2).is_bool_scalar()) lockoption = args(2).bool_value (); // Check if the third argument is a function else if(args(2).is_function_handle()) { // Check if the custom T-Norm function has at most two arguments if(!checkFunction (args(2).function_value())) { error(ERR_INVALIDFUNC); return octave_value_list(); } else { // Set the custom T-Norm and force single thread mode tnorm = args(2).function_value(); calc_tnorm = func_custom_tnorm; } } // Check if the third argument is a string and try to //assign a default T-Norm else if(!((args(2).is_sq_string() || args(2).is_dq_string()) && assignFunction(args(2),1))) { error(ERR_INVALIDFUNC); return octave_value_list(); } } // Analyze the fourth argument (can be a custom T-Norm, a // default string for T-Norm or a custom S-Norm) if(numargs > 3) { // Check if the fourth argument is a function if(args(3).is_function_handle()) { if(lockoption) { // Check if the custom T-Norm function has at most // two arguments if(!checkFunction(args(3).function_value())) { error(ERR_INVALIDFUNC); return octave_value_list(); } else { // Set the custom T-Norm and force single thread mode tnorm = args(3).function_value(); calc_tnorm = func_custom_tnorm; } } else { // Check if the custom S-Norm function has at most two arguments if (!checkFunction(args(3).function_value())) { error(ERR_INVALIDFUNC); return octave_value_list(); } else { // Set the custom S-Norm and force single thread mode snorm = args(3).function_value(); calc_snorm = func_custom_snorm; } } } // Check if the fourth argument is a string (could be a default T-Norm) else if (args(3).is_sq_string() || args(3).is_dq_string()) { if (lockoption) { if (!assignFunction(args(3),1)) { error(ERR_INVALIDFUNC); return octave_value_list(); } } else { if (!assignFunction(args(3),0)) { error(ERR_INVALIDFUNC); return octave_value_list(); } } } else { error(ERR_INVALIDFUNC); return octave_value_list(); } } // Get the input matrices // Create constat versions of the input matrices to // prevent them to be filled by zeros on reading const SparseMatrix constA = args(0).sparse_matrix_value(); const SparseMatrix constB = args(1).sparse_matrix_value(); // Get the dimensions of matrices octave_idx_type rowsA,rowsB,colsA,colsB,nnzA,nnzB; rowsA = constA.dims()(0); colsA = constA.dims()(1); nnzA = constA.nnz(); rowsB = constB.dims()(0); colsB = constB.dims()(1); nnzB = constB.nnz(); // Check if the dimensions are compatible if(colsA != rowsB) { error(ERR_MATRIXSIZE); return octave_value_list(); } // Declare variables for the T-Norm and S-Norm values double snorm_val; double tnorm_val; if (lockoption) { ColumnVector C (rowsA); // Start the matrix composition // Calculate the composition for the specified rows // (between 0 and rowsA) for (int i = 0; i < rowsA; i++) { snorm_val = calc_tnorm(constA(i,0), constB(0,i)); // From b.cidx(i) to b.cidx(i+1)-1 there are all the // nonzero elements of the column j of b (constB actually) for (int k = constB.cidx(i); k <= (constB.cidx(i+1)-1); k++) { // b.ridx(k) is the row index of the actual nonzero // element in b (constB actually) so it is also the // column index of the element in a (constA actually) tnorm_val = calc_tnorm(constA(i, constB.ridx(k)), constB.data(k)); snorm_val = calc_snorm(snorm_val, tnorm_val); } C (i) = snorm_val; } return octave_value (C); } else { // Count the number of non-zero elements first. This should be // relatively low cost octave_idx_type nnzC = 0; for (octave_idx_type i = 0; i < rowsA; i++) { for(octave_idx_type j = 0; j < colsB; j++) { if (constB.cidx(j) != constB.cidx(j+1)) nnzC++; else { for (octave_idx_type k = constB.cidx(j); k < constB.cidx(j+1); k++) { if (constA(i, constB.ridx(k)) != 0) { nnzC++; break; } } } } } // Sets proper matrix dimension SparseMatrix C(colsB, rowsA, nnzC); // Start the matrix composition // Initialize the number of nonzero elemnts in sparse matrix c int nel = 0; C.xcidx(0) = 0; // Calculate the composition for the specified rows // (between 0 and rowsA) for (int i = 0; i < rowsA; i++) { for(int j = 0; j < colsB; j = j++) { snorm_val = calc_tnorm(constA(i,0), constB(0,j)); // From b.cidx(j) to b.cidx(j+1)-1 there are all the // nonzero elements of the column j of b (constB actually) for (int k = constB.cidx(j); k < constB.cidx(j+1); k++) { // b.ridx(k) is the row index of the actual nonzero // element in b (constB actually) so it is also the // column index of the element in a (constA actually) tnorm_val = calc_tnorm(constA(i, constB.ridx(k)), constB.data(k)); snorm_val = calc_snorm(snorm_val, tnorm_val); } if (snorm_val != 0) { // Equivalent to c(i, j) = snorm_val; C.xridx(nel) = j; C.xdata(nel++) = snorm_val; } } C.xcidx(i+1) = nel; } // Compress the result sparse matrix because it is initialized // with a number of nonzero element probably greater than the real one C.maybe_compress(); octave_stdout << "OK\n"; // Return the result sparse matrix (it's trasposed because we // have been working on the rows of its transpose return octave_value(C.transpose()); } } /* Calculate the minimum between the two values */ double func_min(double first, double second) { if(first < second) return first; else return second; } /* Calculate the product between the two values */ double func_prod(double first, double second) { return first*second; } /* Calculate the Maximum between the two values */ double func_max(double first, double second) { if(first > second) return first; else return second; } /* Calculate the sum between the two values */ double func_sum(double first, double second) { return first+second; } /* Calculate a custom T-Norm between the two values */ double func_custom_tnorm(double first, double second) { octave_value_list fargs; fargs(0) = octave_value(first); fargs(1) = octave_value(second); return feval(tnorm,fargs)(0).double_value(); } /* Calculate a custom S-Norm between the two values */ double func_custom_snorm(double first, double second) { octave_value_list fargs; fargs(0) = octave_value(first); fargs(1) = octave_value(second); return feval(snorm,fargs)(0).double_value(); } /* Returns 1 if an octave_function FUNC has at most 2 arguments. */ int checkFunction(octave_function *func) { octave_value_list testArgs; testArgs(0) = 1; testArgs(1) = 2; feval(func,testArgs); if(error_state) return 0; else return 1; } /* Assign a default function or T-Norm or S-Norm. If tnorm = 0 the function will be assigned as S-Norm, else the function will be assigned as T-Norm. Returns 0 if it fails*/ int assignFunction(octave_value arg, int tnorm) { int res = 1; if(arg.string_value() == STR_PRONORM) if(tnorm) calc_tnorm = func_prod; else calc_snorm = func_prod; else if (arg.string_value() == STR_MAXNORM) if(tnorm) calc_tnorm = func_max; else calc_snorm = func_max; else if (arg.string_value() == STR_SUMNORM) if(tnorm) calc_tnorm = func_sum; else calc_snorm = func_sum; else if(!(arg.string_value() == STR_MINNORM)) res = 0; return res; }
------------------------------------------------------------------------------ Gaining the trust of online customers is vital for the success of any company that requires sensitive data to be transmitted over the Web. Learn how to best implement a security strategy that keeps consumers' information secure and instills the confidence they need to proceed with transactions. http://p.sf.net/sfu/oracle-sfdevnl
_______________________________________________ Octave-dev mailing list Octave-dev@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/octave-dev