changeset 1047:c1ba49314018 octave-forge

support for real ND-arrays included
author schloegl
date Mon, 22 Sep 2003 16:08:49 +0000
parents 8106469539e6
children 3c9773a853bf
files extra/NaN/sumskipnan2.cpp
diffstat 1 files changed, 115 insertions(+), 108 deletions(-) [+]
line wrap: on
line diff
--- a/extra/NaN/sumskipnan2.cpp	Fri Sep 19 15:20:53 2003 +0000
+++ b/extra/NaN/sumskipnan2.cpp	Mon Sep 22 16:08:49 2003 +0000
@@ -1,22 +1,7 @@
 //-------------------------------------------------------------------
 #pragma hdrstop
 //-------------------------------------------------------------------
-// sumskipnan2: sums all non-NaN values
-//
-// Input:
-// - array to sum
-// - dimension to sum (1=columns; 2=rows; doesn't work for dim>2!!)
-//
-// Output:
-// - sums
-// - count of valid elements (optional)
-// - sums of squares (optional)
-// - sums of squares of squares (optional)
-//
-// Author:  Patrick Houweling (phouweling@yahoo.com)
-// Version: 1.0
-// Date:    17 september 2003
-//
+//   C-MEX implementation of SUMSKIPNAN - this function is part of the NaN-toolbox. 
 //
 //   This program is free software; you can redistribute it and/or modify
 //   it under the terms of the GNU General Public License as published by
@@ -33,126 +18,148 @@
 //   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 //
 //
+// sumskipnan2: sums all non-NaN values
+//
+// Input:
+// - array to sum
+// - dimension to sum (1=columns; 2=rows; doesn't work for dim>2!!)
+//
+// Output:
+// - sums
+// - count of valid elements (optional)
+// - sums of squares (optional)
+// - sums of squares of squares (optional)
+//
+// Author:  Patrick Houweling (phouweling@yahoo.com)
+// Version: 1.0
+// Date:    17 september 2003
+//
+// modified:
+//   Alois Schloegl <a.schloegl@ieee.org>    
+// 	$Revision$
+// 	$Id$
+//
 //-------------------------------------------------------------------
-#include <stdlib>
+//#include <stdlib>
 #include "mex.h"
 //-------------------------------------------------------------------
 void mexFunction(int POutputCount,  mxArray* POutput[], int PInputCount, const mxArray *PInputs[])
 {
-    int     M, N, m, n;
-    int     i, j;
-    int     LDimension;
+    const int	*SZ;	    
     double* LInput;
     double* LOutputSum;
     double* LOutputCount;
     double* LOutputSum2;
     double* LOutputSum4;
     double  x, x2;
-    int     LCount;
+    unsigned long   LCount;
     double  LSum, LSum2, LSum4;
 
+    unsigned		DIM = 1; 
+    unsigned long	D1, D2, D3, NN; 	//  	
+    unsigned    	ND, ND2;	// number of dimensions: input, output
+    unsigned long	ix1, ix2;	// index to input and output
+
+    unsigned    	i, j, k, l;	// running indices 
+    int 		*SZ2;		// size of output 	    
+
+     	
+
     // check for proper number of input and output arguments
     if ((PInputCount <= 0) || (PInputCount > 2))
         mexErrMsgTxt("SumSkipNan2 requires 1 or 2 arguments.");
-    if (POutputCount > 5)
+    if (POutputCount > 4)
         mexErrMsgTxt("SumSkipNan2 has 1 to 4 output arguments.");
 
     // get 1st argument
     if(!mxIsNumeric(PInputs[0]))
-        mexErrMsgTxt("First argument must be numeric.");
-    M = mxGetM(PInputs[0]);
-    N = mxGetN(PInputs[0]);
+	mexErrMsgTxt("First argument must be NUMERIC.");
+    if(!mxIsDouble(PInputs[0]))
+	mexErrMsgTxt("First argument must be DOUBLE.");
+    if(mxIsComplex(PInputs[0]))
+	mexErrMsgTxt("First argument must not be complex but REAL.");
     LInput = mxGetPr(PInputs[0]);
 
     // get 2nd argument
     if  (PInputCount == 2){
         if ((!mxIsNumeric(PInputs[1])) || (mxGetM(PInputs[1]) != 1) || (mxGetN(PInputs[1]) != 1))
             mexErrMsgTxt("Second argument must be scalar.");
-        LDimension = mxGetScalar(PInputs[1]);
-        if ((LDimension < 0) || (LDimension > 2))
-            mexErrMsgTxt("Only dimensions 1 and 2 are supported.");
-    }
-    else
-        LDimension = 1;
-
-    // create outputs
-    if (LDimension == 1){
-        m = 1;
-        n = N;
-    }
-    if (LDimension == 2){
-        m = M;
-        n = 1;
-    }
-    POutput[0]   = mxCreateDoubleMatrix(m, n, mxREAL);
-    LOutputSum   = mxGetPr(POutput[0]);
-    if (POutputCount >= 2){
-        POutput[1]   = mxCreateDoubleMatrix(m, n, mxREAL);
-        LOutputCount = mxGetPr(POutput[1]);
-    }
-    if (POutputCount >= 3){
-        POutput[2]   = mxCreateDoubleMatrix(m, n, mxREAL);
-        LOutputSum2  = mxGetPr(POutput[2]);
-    }
-    if (POutputCount >= 4){
-        POutput[3]   = mxCreateDoubleMatrix(m, n, mxREAL);
-        LOutputSum4  = mxGetPr(POutput[3]);
+        DIM = (unsigned long)(mxGetScalar(PInputs[1]));
     }
 
-    if (LDimension == 1){
-        // sum all non-NaN elements of each column
-        for (j=0; j<N; j++){
-            // init
-            LCount = 0;
-            LSum   = 0;
-            LSum2  = 0;
-            LSum4  = 0;
+    	ND = mxGetNumberOfDimensions(PInputs[0]);	
+    	NN = mxGetNumberOfElements(PInputs[0]);
+    	SZ = mxGetDimensions(PInputs[0]);		
+
+	ND2 = (ND>DIM ? ND : DIM);	// number of dimensions of output 
+	SZ2 = (int*)mxCalloc(ND2, sizeof(int)); // allocate memory for output size
+
+	for (j=0; j<ND; j++)		// copy size of input;  
+		SZ2[j] = SZ[j]; 	
+	for (j=ND; j<ND2; j++)		// in case DIM > ND, add extra elements 1 
+		SZ2[j] = 1; 	
+
+    	for (j=0, D1=1; j<DIM-1; D1=D1*SZ2[j++]); 	// D1 is the number of elements between two elements along dimension  DIM  
+	D2 = SZ2[DIM-1];		// D2 contains the size along dimension DIM 	
+    	for (j=DIM, D3=1;  j<ND; D3=D3*SZ2[j++]); 	// D3 is the number of blocks containing D1*D2 elements 
+
+	SZ2[DIM-1] = 1;		// size of output is same as size of input but SZ(DIM)=1;
+
+	    // create outputs
+	#define TYP mxDOUBLE_CLASS
+
+	POutput[0] = mxCreateNumericArray(ND2, SZ2, TYP, mxREAL);
+    	LOutputSum = mxGetPr(POutput[0]);
+    	if (POutputCount >= 2){
+		POutput[1] = mxCreateNumericArray(ND2, SZ2, TYP, mxREAL);
+        	LOutputCount = mxGetPr(POutput[1]);
+    	}
+    	if (POutputCount >= 3){
+		POutput[2] = mxCreateNumericArray(ND2, SZ2, TYP, mxREAL);
+        	LOutputSum2  = mxGetPr(POutput[2]);
+    	}
+    	if (POutputCount >= 4){
+		POutput[3] = mxCreateNumericArray(ND2, SZ2, TYP, mxREAL);
+        	LOutputSum4  = mxGetPr(POutput[3]);
+    	}
 
-            for (i=0; i<M; i++){
-                x = LInput[i + j*M];
-                if (!mxIsNaN(x)){
-                    LCount++;
-                    LSum += x;
-                    x2 = x*x;
-                    LSum2 += x2;
-                    LSum4 += x2*x2;
-                }
-            }
-            LOutputSum[j] = LSum;
-            if (POutputCount >= 2)
-                LOutputCount[j] = LCount;
-            if (POutputCount >= 3)
-                LOutputSum2[j] = LSum2;
-            if (POutputCount >= 4)
-                LOutputSum4[j] = LSum4;
-        }
-    }
-    if (LDimension == 2){
-        // sum all non-NaN elements of each row
-        for (i=0; i<M; i++){
-            // init
-            LCount = 0;
-            LSum   = 0;
-            LSum2  = 0;
-            LSum4  = 0;
+	// OUTER LOOP: along dimensions > DIM
+	for (l = 0; l<D3; l++) 	
+    	{
+		ix2 =   l*D1;	// index for output 
+		ix1 = ix2*D2;	// index for input 
 
-            for (j=0; j<N; j++){
-                x = LInput[i + j*M];
-                if (!mxIsNaN(x)){
-                    LCount++;
-                    LSum += x;
-                    x2 = x*x;
-                    LSum2 += x2;
-                    LSum4 += x2*x2;
-                }
-            }
-            LOutputSum[i] = LSum;
-            if (POutputCount >= 2)
-                LOutputCount[i] = LCount;
-            if (POutputCount >= 3)
-                LOutputSum2[i] = LSum2;
-            if (POutputCount >= 4)
-                LOutputSum4[i] = LSum4;
-        }
-    }
+		// Inner LOOP: along dimensions < DIM
+		for (k = 0; k<D1; k++, ix1++, ix2++) 	
+		{
+		        LCount = 0;
+			LSum   = 0.0;
+			LSum2  = 0.0;
+			LSum4  = 0.0;
+	        	    		
+			// LOOP  along dimension DIM
+	    		for (i=0; i<D2; i++) 	
+			{
+				x = LInput[ix1 + i*D1];
+        	        	if (!mxIsNaN(x))
+				{
+					LCount++; 
+					LSum += x; 
+					x2 = x*x;
+					LSum2 += x2; 
+					LSum4 += x2*x2; 
+				}
+			}
+			LOutputSum[ix2] = LSum;
+            		if (POutputCount >= 2)
+                		LOutputCount[ix2] = (double)LCount;
+            		if (POutputCount >= 3)
+                		LOutputSum2[ix2] = LSum2;
+            		if (POutputCount >= 4)
+                		LOutputSum4[ix2] = LSum4;
+		}
+	}
+	mxFree(SZ2);    	
 }
+
+