changeset 10376:f87eaefec72d octave-forge

fastlscomplex compiles now, comments cleaned up. (Still not tested.)
author benjf5
date Mon, 04 Jun 2012 20:12:13 +0000
parents 12f0d1c2b947
children 1dea4e435de8
files extra/lssa/fastlscomplex.cpp
diffstat 1 files changed, 43 insertions(+), 66 deletions(-) [+]
line wrap: on
line diff
--- a/extra/lssa/fastlscomplex.cpp	Mon Jun 04 11:41:32 2012 +0000
+++ b/extra/lssa/fastlscomplex.cpp	Mon Jun 04 20:12:13 2012 +0000
@@ -1,17 +1,7 @@
-/* Copyright (C) 2012 Benjamin Lewis <benjf5@gmail.com>
+/* 
  * fastlscomplex.cpp, compiles to fastlscomplex.oct
- * 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 the Free Software
- * Foundation; either version 3 of the License, or (at your option) any later
- * version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
- * details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, see <http://www.gnu.org/licenses/>.
+ * Conversion to C++, with wrapper for Octave of the code from 
+ * A. Mathias' nuspectral package.
  */
 
 #include <octave/oct.h>
@@ -20,21 +10,18 @@
 #include <string>
 #include <iostream>
 
-typedef struct
-{   double x, t;
-} XTElem;
+ComplexRowVector fastlscomplex ( RowVector tvals, ComplexRowVector xvals, octave_idx_type n, 
+				 double length, int ncoeff, int noctaves, double omegamax );
 
 inline double sqr(double x) 
 {   return x*x;   }
 
-#define PNUM 12;
-
 
 #define SETXT(p_, op_, x_, t_) (p_)->x op_ x_; (p_++)->t op_ t_;
 #define SETT(p_, op_, x_, t_)  *p_++ op_ t_;
 #define SETX(p_, op_, x_, t_) *p_++ op_ x_;
 /* h is a complex aux. variable; it is used for assignment times I everywhere */
-#define SETIX(p_, op_, x_, t_) h = x_; RE(*(p_)) op_ -IM(h); IM(*(p_)) op_ RE(h); p_++;
+#define SETIX(p_, op_, x_, t_) h = x_; (*(p_)).real() op_ -(h.imag()); (*(p_)).imag() op_ h.real(); p_++;
 
         /* Macro that sums up the power series terms into the power series
 	 * element record pointed to by p_.
@@ -46,7 +33,7 @@
          */
         // -10 points, comments don't match method.
 #define EXP_IOT_SERIES(p_, el_, t_, op_, setr_, seti_)		\
-{       Real t = t_, tt; p_ = el_;    setr_(p_, op_, x, 1)	\
+{       double t = t_, tt; p_ = el_;    setr_(p_, op_, x, 1)	\
         tt  = -t;            seti_(p_, op_, x*tt, tt)		\
         tt *= t*(1.0/2.0);   setr_(p_, op_, x*tt, tt)		\
         tt *= t*(-1.0/3.0);  seti_(p_, op_, x*tt, tt)		\
@@ -62,7 +49,7 @@
 
 /* same as the above, but without alternating signs */
 #define EXPIOT_SERIES(p_, el_, t_, op_, setr_, seti_)		\
-{       Real t = t_, tt; p_ = el_;    setr_(p_, op_, x, 1)	\
+{       double t = t_, tt; p_ = el_;    setr_(p_, op_, x, 1)	\
 			     seti_(p_, op_, x*t,  t )		\
         tt  = t*t*(1.0/2.0); setr_(p_, op_, x*tt, tt)		\
         tt *= t*(1.0/3.0);   seti_(p_, op_, x*tt, tt)		\
@@ -76,29 +63,21 @@
         tt *= t*(1.0/11.0);  seti_(p_, op_, x*tt, tt)		\
 }
 
-#   define SRCARG   Real *tptr, Real *xptr, int n, double *lengthptr
-#   define SRCVAR   int k; Real length = *lengthptr;
-#   define SRCT     tptr[k]
-#   define SRCX     xptr[k]
+#   define SRCARG   double *tptr, double *xptr, int n, double *lengthptr
+#   define SRCVAR   int k; double length = *lengthptr;
+
+//I'll remove these very shortly
 #   define SRCFIRST k = 0
-#   define SRCAVAIL (k<n)
+#   define SRCAVAIL (k<n) 
 #   define SRCNEXT  k++
 
-#define FASTLSCOMPLEX_HELP \
-  "Takes the fast complex least-squares transform of irregularly sampled data.\n\
+DEFUN_DLD(fastlscomplex, args, nargout, "Takes the fast complex least-squares transform of irregularly sampled data.\n\
 When called, takes a time series with associated x-values, a number of octaves,\n\
 a number of coefficients per octave, the maximum frequency, and a length term.\n\
-It returns a complex row vector of the transformed series."
-
-DEFUN_DLD(fastlscomplex, args, nargout, FASTLSCOMPLEX_HELP ){
-  if ( args.length != 7 ) {
-    std::cout << "Improper number of arguments!" << std::endl;
-    std::cout << FASTLSCOMPLEX_HELP << std::endl;
-    return octave_value_list ();
-  }
+It returns a complex row vector of the transformed series." ){
   RowVector tvals = args(0).row_vector_value();
   ComplexRowVector xvals = args(1).complex_row_vector_value();
-  double length = ( tvals(tvals.numel()--) - tvals( octave_idx_type (0)));
+  double length = ( tvals((tvals.numel()-1)) - tvals( octave_idx_type (0)));
   int ncoeff = args(4).int_value();
   int noctaves = args(5).int_value();
   double omegamax = args(6).double_value();
@@ -121,7 +100,7 @@
   }
   // possibly include error for when omegamax isn't right?
   ComplexRowVector results = fastlscomplex(tvals, xvals, n, length, ncoeff, noctaves, omegamax);
-  return results;
+  return octave_value_list ( (octave_value) results );
 }
 
 ComplexRowVector fastlscomplex ( RowVector tvals, ComplexRowVector xvals, octave_idx_type n, 
@@ -134,11 +113,10 @@
   struct SumVec {
     SumVec *next;
     std::complex<double> elements[12];
-    int count;  }
-  *shead, *stail, *sp, *sq; //Names have been kept from the C, may change if I want to.
+    int count;  };
+  SumVec *shead, *stail, *sp, *sq;
   double dtelems[12],		/* power series elements of exp(-i dtau)  */
     *dte, *r,			/* Pointers into dtelems */
-    x,				/* abscissa and ordinate value, p-th power of t */
     tau, tau0, te,		/* Precomputation range centers and range end */
     tau0d,	                /* tau_h of first summand range at level d */
     dtau = (0.5*M_PI)/omegamax,/* initial precomputation interval radius */
@@ -149,48 +127,45 @@
     on_1,			/* n_1*(omega/mu)^p, n_1*(2*omega/mu)^p */
     mu = (0.5*M_PI)/length,  	/* Frequency shift: a quarter period of exp(i mu t) on length */
     tmp;
-  std::complex<double> zeta, zz, // Accumulators for spectral coefficients to place in Complex<double>
+  std::complex<double> zeta, zz, // Accumulators for spectral coefficients to place in complex<double>
     e, emul,
+    x,
     h, eoelems[12], oeelems[12],
     *eop, *oep,
     *ep, *op,
     *p, *q, *pe;
-  ComplexRowVector results (ncoeff*noctaves); //This *should* be the right size. I'll check against later sections of code.
+  ComplexRowVector results (ncoeff*noctaves);
 
   int i , j; // Counters; coefficient and octave, respectively.
-  // probable doubles: zetar, zetai, zzr, zzi, er, ei, emulr, emuli,
-  //    eoelemsr[12] eoelemsi[12], etc. (since I want to use Complex<double>
-  //    as little as possible.)
-  
+
   octave_idx_type k = 0;
   
   // Subdivision and precomputation, reinvisioned in an OOWorld.
   tau = tvals(k) + dtau;
   te = tau + dtau;
   tau0 = tau;
-  shead = stail = sp = alloca(sizeof(*sp));
+  shead = stail = sp = (SumVec*) operator new (sizeof(SumVec));
   sp->next = 0;
   { te = tvals(k) + ( 2 * dtau );
-    while ( k < n ) { //THIS makes no sense, n is the wrong type. Will need to fix that.
-      EXP_IOT_SERIES(p, sp->elems, mu*(tvals(k)-tau), =, SETX, SETIX);
+    while ( k < n ) { 
+      EXP_IOT_SERIES(p, sp->elements, mu*(tvals(k)-tau), =, SETX, SETIX);
       sp->count = 1;
       //Sum terms and show that there has been at least one precomputation.
       // I will probably replace the macro with a better explanation.
       for(SRCNEXT; SRCAVAIL && tvals(k) < te; SRCNEXT) {
 	x = xvals(k);
-	EXP_IOT_SERIES(p,sp->elems,mu*(tvals(k)-tau), +=, SETX, SETIX);
+	EXP_IOT_SERIES(p,sp->elements,mu*(tvals(k)-tau), +=, SETX, SETIX);
 	sp->count++;
       }
       if ( k >= n ) break;
       tau = te + dtau;
       te = tau + dtau;
-      sp = alloca(sizeof(*sp));
+      sp = (SumVec*) operator new (sizeof(*sp));
       stail->next = sp;
       stail = sp;
       sp->next = 0;
       sp->count = 0;
     } }
-  // Now isn't that just a nicer representation of much the same control structure as that ugly for-loop?
   // Defining starting values for the loops over octaves:
   ooct = omegamax / mu;
   omul = exp(-log(2)/ncoeff);
@@ -199,7 +174,7 @@
   dtaud = dtau;
   octave_idx_type iter ( 0 );
   // Looping over octaves
-  for ( j = noctave ; ; ooct *= 0.5 , omegaoct *= 0.5 , tau0d += dtaud , dtaud *= 2 ) {
+  for ( j = noctaves ; ; ooct *= 0.5 , omegaoct *= 0.5 , tau0d += dtaud , dtaud *= 2 ) {
     // Looping over&results per frequency
     for ( i = ncoeff, o = ooct, omega = omegaoct; i-- ; o *= omul, omega *= omul ) {
       e.real() = cos( - ( omega * tau0d ) ); e.imag() = sin( - ( omega * tau0d ) ); 
@@ -208,7 +183,9 @@
       // sets real, imag parts of emul
       for( zeta = 0 , sp = shead; sp; sp = sp->next, e *= emul ) {
 	if ( sp->count ) {
-	  for ( zz = std::complex<double>(0.0,0.0) , octave_idx_type i (0) , p = sp->elems , pe = p + 12 , on_1 = n_1 ; p < pe ; i++ ) {
+	  zz = std::complex<double>(0.0,0.0);
+	  octave_idx_type i ( 0 );
+	  for ( p = sp->elements , on_1 = n_1 ; i < (octave_idx_type) 12 ; i++ ) {
 	    zz += *p++ * on_1;
 	    on_1 *= 0;
 	  }
@@ -222,41 +199,41 @@
       EXPIOT_SERIES(r, dtelems, mu*dtaud, =, SETT, SETT);
       for(sp = shead; sp; sp = sp->next){
 	if(!(sq = sp->next) || !sq->count ) {
-	  for(p = sp->elems, eop = eoelems, dte = dtelems+1, pe = p+12; p < pe; p++, dte++)
+	  for(p = sp->elements, eop = eoelems, dte = dtelems+1, pe = p+12; p < pe; p++, dte++)
 	    {   ep = eop; *eop++ = *p;
 	      for(r = dtelems, *p = *ep * *r; ; )
-		{   if(++r>=dte) break; --ep; h   =  *ep * *r; RE(*p) -= IM(h); IM(*p) += RE(h);
+		{   if(++r>=dte) break; --ep; h   =  *ep * *r; (*p).real() -= h.imag(); (*p).imag() += h.real();
 		  if(++r>=dte) break; --ep; *p -=  *ep * *r;
-		  if(++r>=dte) break; --ep; h   = -*ep * *r; RE(*p) -= IM(h); IM(*p) += RE(h);
+		  if(++r>=dte) break; --ep; h   = -*ep * *r; (*p).real() -= h.imag(); (*p).imag() += h.real();
 		  if(++r>=dte) break; --ep; *p +=  *ep * *r;
 		}
 	    }
 	  if(!sq) break;		    /* reached the last precomputation range */
 	}
 	else
-	  if(sp->cnt)
-	    for(p = sp->elems, q = sq->elems, eop = eoelems, oep = oeelems, dte = dtelems+1, pe = p+12;
+	  if(sp->count)
+	    for(p = sp->elements, q = sq->elements, eop = eoelems, oep = oeelems, dte = dtelems+1, pe = p+12;
 		p < pe; p++, q++, dte++)
 	      {   ep = eop; *eop++ = *p+*q; *oep++ = *p-*q; op = oep;
 		for(r = dtelems, *p = *ep * *r; ; )
-		  {   if(++r>=dte) break; op -= 2; h   =  *op * *r; RE(*p) -= IM(h); IM(*p) += RE(h);
+		  {   if(++r>=dte) break; op -= 2; h   =  *op * *r; (*p).real() -= h.imag(); (*p).imag() += h.real();
 		    if(++r>=dte) break; ep -= 2; *p -=  *ep * *r;
-		    if(++r>=dte) break; op -= 2; h   = -*op * *r; RE(*p) -= IM(h); IM(*p) += RE(h);
+		    if(++r>=dte) break; op -= 2; h   = -*op * *r; (*p).real() -= h.imag(); (*p).imag() += h.real();
 		    if(++r>=dte) break; ep -= 2; *p +=  *ep * *r;
 		  }
 	      }
 	  else
-	    for(q = sq->elems, eop = eoelems, oep = oeelems, dte = dtelems+1, pe = q+12; q<pe; q++, dte++)
+	    for(q = sq->elements, eop = eoelems, oep = oeelems, dte = dtelems+1, pe = q+12; q<pe; q++, dte++)
 	      {   ep = eop; *eop++ = *q;
 		for(r = dtelems, *q = *ep * *r; ; )
-		  {   if(++r>=dte) break; --ep; h   =  *ep * *r; RE(*q) -= IM(h); IM(*q) += RE(h);
+		  {   if(++r>=dte) break; --ep; h   =  *ep * *r; (*q).real() -= h.imag(); (*q).imag() += h.real();
 		    if(++r>=dte) break; --ep; *p -=  *ep * *r;
-		    if(++r>=dte) break; --ep; h   = -*ep * *r; RE(*q) -= IM(h); IM(*q) += RE(h);
+		    if(++r>=dte) break; --ep; h   = -*ep * *r; (*q).real() -= h.imag(); (*q).imag() += h.real();
 		    if(++r>=dte) break; --ep; *q +=  *ep * *r;
 		  }
 	      }
 	
-	sp->cnt += sq->cnt; sp->next = sq->next; /* free(sq) if malloc'ed */
+	sp->count += sq->count; sp->next = sq->next; /* free(sq) if malloc'ed */
         }
     }
   }