home *** CD-ROM | disk | FTP | other *** search
- #include <iostream.h>
- #include <alloc.h>
- #include <stdlib.h>
-
- /*---------------04-26-90 09:29am-------------------
- * An illustration of defining and using a class which employs
- * dynamically allocated arrays. The sequence class is used to manipulate
- * time-domain sequences for digital signal processing. We have an array
- * of signal values, and the time extent (in samples) which the signal
- * encompasses. We define operators for storing (=), convolving (*), adding,
- * subtracting, IIR convolution (/), construction and destruction.
- --------------------------------------------------*/
- class sequence {
- protected:
-
- double huge *seq; //sequence of points - some signals are long
- int lower_limit; //start time
- int upper_limit; //end time
-
- public:
- sequence(int lower=0, int upper=0); //default sequence is single point
- sequence(sequence& arg); //construct from other sequence
- ~sequence(void); //destructor
- double fetch(int index); //need operator to get datum
- void stuff(int index,double val); //and an operator to place datum
- void extent(int *lower, int *upper); //since limits are hidden, fetch them
- sequence operator* (sequence& arg); //convolution
- sequence& operator*= (sequence& arg); //convolution
- sequence operator/ (sequence& arg); //IIR filter
- sequence& operator/= (sequence& arg); //IIR filter
- sequence operator+ (sequence& arg); //add sequences
- sequence& operator+= (sequence &arg); //add in place
- sequence operator- (sequence& arg); //subtract
- sequence& operator-= (sequence &arg); //subtract in place
- sequence& operator= (sequence& arg); //copy
- int is_causal(void); //necessary for DSP
- };
-
- /*create a sequence of zeros, from lower to upper index*/
- sequence::sequence(int lower, int upper)
- {
- int i;
-
- if (lower>upper) {
- i=lower;
- lower=upper;
- upper=i;
- }
- seq=new double[upper+1-lower];
- if (seq==NULL) {
- cerr << "Cannot allocate sequence\n";
- exit(1);
- }
- lower_limit=lower;
- upper_limit=upper;
- for (i=lower;i<=upper;i++) {
- seq[i-lower]=0.0;
- }
- }
-
- /*create a sequence from another sequence*/
- sequence::sequence(sequence& arg)
- {
- int i;
-
- /*set limits*/
- lower_limit=arg.lower_limit;
- upper_limit=arg.upper_limit;
- /*allocate the array*/
- seq=new double[upper_limit+1-lower_limit];
- if(seq==NULL){
- cerr << "Cannot allocate sequence\n";
- exit(1);
- }
- /*transfer the data*/
- for(i=lower_limit;i<=upper_limit;i++){
- stuff(i,arg.fetch(i));
- }
- }
-
- /*destroy a sequence*/
- sequence::~sequence(void)
- {
- delete seq;
- }
-
- /*since the data array is hidden, we need this to put data in, if valid*/
- void sequence::stuff(int index,double val)
- {
- if ((index>=lower_limit)&&(index<=upper_limit)) {
- seq[index-lower_limit]=val;
- }
- }
-
- /*since the data array is hidden, we need this to put data in, if valid*/
- double sequence::fetch(int index)
- {
- if ((index>=lower_limit)&&(index<=upper_limit)) {
- return(seq[index-lower_limit]);
- } else {
- return((double) 0);
- }
- }
-
- /*since the limits are hidden, we use this to obtain them*/
- void sequence::extent(int *lower, int *upper)
- {
- *lower=lower_limit;
- *upper=upper_limit;
- }
-
- /************************************************
- * --- sequence sequence::operator* ---
- * How to convolve two sequences. NOTE that the operator is NOT by
- * reference. This is necessary, so as to NOT modify the left-hand
- * sequence
- ************************************************/
- sequence sequence::operator* (sequence& arg)
- {
- int i,j,lower=lower_limit+arg.lower_limit;
- int upper=upper_limit+arg.upper_limit;
- int this_bigger=(upper_limit+arg.lower_limit-
- (lower_limit+arg.upper_limit));
- /*---------------04-26-90 09:41am-------------------
- * The output is by value. The temp sequence is used to hold
- * the value
- --------------------------------------------------*/
- sequence temp(lower,upper);
-
- /*To speed the operation, we can reverse the order of the
- * Convolution, depending upon which sequence is longer*/
- if(this_bigger>0){
- /*Convoltion sum one direction*/
- for (i=lower;i<=upper;i++) {
- temp.stuff(i,0.0);
- for (j=arg.lower_limit;j<=arg.upper_limit;j++) {
- temp.stuff(i,temp.fetch(i)+fetch(i-j)*arg.fetch(j));
- }
- }
- } else {
- /*convolution sum other direction*/
- for (i=lower;i<=upper;i++) {
- temp.stuff(i,0.0);
- for (j=lower_limit;j<=upper_limit;j++) {
- temp.stuff(i,temp.fetch(i)+fetch(j)*arg.fetch(i-j));
- }
- }
- }
- return temp;
- }
-
- /*in-place convolution (sort of)*/
- sequence& sequence::operator*= (sequence& arg)
- {
- sequence temp(*this);
-
- *this=temp*arg;
- return *this;
- }
-
- /************************************************
- * --- sequence sequence::operator/ ---
- *
- * How to IIR filter. NOTE that the operator is NOT by
- * reference. This is necessary, so as to NOT modify the left-hand
- * sequence
- ************************************************/
- sequence sequence::operator/ (sequence& arg)
- {
- int i,j;
- /*the TEMP sequence is used to hold the output for value output*/
- sequence temp(lower_limit,upper_limit);
- double tempd1,tempd2;
-
- /*We can only do IIR filter if right-hand signal is causal*/
- if((!arg.is_causal())||(arg.fetch(0)==0.0)){
- cerr << "Divide by non-causal sequence\n";
- exit(1);
- }
- /*perform the IIR filter operation*/
- tempd1=1.0/arg.fetch(0);
- for (i=lower_limit;i<=upper_limit;i++) {
- tempd2=fetch(i);
- for (j=arg.lower_limit+1;j<=arg.upper_limit;j++) {
- tempd2-=temp.fetch(i-j)*arg.fetch(j);
- }
- temp.stuff(i,tempd2*tempd1);
- }
- return temp;
- }
- /*In-place IIR filtering (really) - NOTE: this IS call-by-reference*/
- sequence& sequence::operator/= (sequence& arg)
- {
- int i,j;
- double tempd1,tempd2;
-
- if((!arg.is_causal())||(arg.fetch(0)==0.0)){
- cerr << "Divide by non-causal sequence\n";
- exit(1);
- }
- tempd1=1.0/arg.fetch(0);
- for (i=lower_limit;i<=upper_limit;i++) {
- tempd2=fetch(i);
- for (j=arg.lower_limit+1;j<=arg.upper_limit;j++) {
- tempd2-=fetch(i-j)*arg.fetch(j);
- }
- stuff(i,tempd2*tempd1);
- }
- return *this;
- }
-
- /************************************************
- * --- sequence sequence::operator+ ---
- * Add two sequences
- ************************************************/
- sequence sequence::operator+ (sequence& arg)
- {
- int i,lower=min(lower_limit,arg.lower_limit);
- int upper=max(upper_limit,arg.upper_limit);
- sequence temp(lower,upper);
-
- for (i=lower;i<=upper;i++) {
- temp.stuff(i,fetch(i)+arg.fetch(i));
- }
- return temp;
- }
-
- /************************************************
- * --- sequence& sequence::operator+= ---
- * Add in-place. NOTE: Call-by-reference
- ************************************************/
- sequence& sequence::operator+= (sequence& arg)
- {
- if ((lower_limit==arg.lower_limit)&&(upper_limit==arg.upper_limit)) {
- int i,lim=upper_limit-lower_limit;
- for (i=0;i<=lim;i++)seq[i]+=arg.seq[i];
- } else {
- sequence temp(*this);
- *this=temp+arg;
- return *this;
- }
- }
-
- /************************************************
- * --- sequence sequence::operator- ---
- * Subtract two sequences
- ************************************************/
- sequence sequence::operator- (sequence& arg)
- {
- int i,lower=min(lower_limit,arg.lower_limit);
- int upper=max(upper_limit,arg.upper_limit);
- sequence temp(lower,upper);
-
- for (i=lower;i<=upper;i++) {
- temp.stuff(i,fetch(i)-arg.fetch(i));
- }
- return temp;
- }
-
- /************************************************
- * --- sequence& sequence::operator-= ---
- * Subtract in place. NOTE: Call-by-reference
- ************************************************/
- sequence& sequence::operator-= (sequence& arg)
- {
- if ((lower_limit==arg.lower_limit)&&(upper_limit==arg.upper_limit)) {
- int i,lim=upper_limit-lower_limit;
- for (i=0;i<=lim;i++)seq[i]-=arg.seq[i];
- } else {
- sequence temp(*this);
- *this=temp-arg;
- return *this;
- }
- }
-
- /************************************************
- * --- sequence& sequence::operator= ---
- * Copy operator. NOTE, since we want separate copies of the
- * signal, rather than just another POINTER to the SAME signal, we
- * must allocate and copy all the data.
- ************************************************/
- sequence& sequence::operator= (sequence& arg)
- {
- int i;
- /*we use old_seq, just in CASE somebody tries a=a*/
- double huge *old_seq=seq;
-
- lower_limit=arg.lower_limit;
- upper_limit=arg.upper_limit;
- seq=new double[upper_limit+1-lower_limit];
- if(seq==NULL){
- cerr << "Cannot allocate sequence\n";
- exit(1);
- }
- for(i=lower_limit;i<=upper_limit;i++){
- stuff(i,arg.fetch(i));
- }
- delete old_seq;
- return *this;
- }
-
- /************************************************
- * --- int sequence::is_causal ---
- * Need this for certain stability tests, and IIR filtering
- ************************************************/
- int sequence::is_causal(void)
- {
- return(lower_limit>=0);
- }
-
- sequence *fred, *mary, sam;
-
- main()
- {
- int u,l,i;
-
- fred= new sequence(0,5);
- mary= new sequence(0,10);
- for (i=0;i<=10;i++) {
- fred->stuff(i,1.0);
- mary->stuff(i,1.0);
- }
- cout << "\nconvolution:\n";
- sam=(*fred)*(*mary);
- sam.extent(&l,&u);
- for (i=l;i<=u;i++) {
- cout << "index=" << i << ", value=" <<sam.fetch(i) << "\n";
- }
- cout << "\naddition:\n";
- sam=(*fred)+(*mary);
- sam.extent(&l,&u);
- for (i=l;i<=u;i++) {
- cout << "index=" << i << ", value=" <<sam.fetch(i) << "\n";
- }
- cout << "\nautosubtration:\n";
- sam-=(*fred)+(*mary);
- sam.extent(&l,&u);
- for (i=l;i<=u;i++) {
- cout << "index=" << i << ", value=" <<sam.fetch(i) << "\n";
- }
- cout << "\nsubtraction:\n";
- sam=(*fred)-(*mary);
- sam.extent(&l,&u);
- for (i=l;i<=u;i++) {
- cout << "index=" << i << ", value=" <<sam.fetch(i) << "\n";
- }
- cout << "\nautoaddition:\n";
- sam+=(*mary)-(*fred);
- sam.extent(&l,&u);
- for (i=l;i<=u;i++) {
- cout << "index=" << i << ", value=" <<sam.fetch(i) << "\n";
- }
- delete fred;
- delete mary;
- fred= new sequence(0,200);
- mary= new sequence(0,1);
- fred->stuff(0,1);
- mary->stuff(0,0.5);
- mary->stuff(1,-0.495);
- cout << "\ndivision:\n";
- sam=(*fred)/(*mary);
- sam.extent(&l,&u);
- for (i=l;i<=u;i++) {
- cout << "index=" << i << ", value=" <<sam.fetch(i) << "\n";
- }
- cout << "\nself division:\n";
- (*fred)/=(*mary);
- (*fred).extent(&l,&u);
- for (i=l;i<=u;i++) {
- cout << "index=" << i << ", value=" <<fred->fetch(i) << "\n";
- }
- cout << "\ndelta:\n";
- (*fred)=sam-(*fred);
- (*fred).extent(&l,&u);
- for (i=l;i<=u;i++) {
- cout << "index=" << i << ", value=" <<fred->fetch(i) << "\n";
- }
- cout << "making sequence\n";
- delete fred;
- fred=new sequence(sam);
- cout << "\nbig multiplication\n";
- sam=(*fred)*(*mary);
- sam.extent(&l,&u);
- for (i=l;i<=u;i++) {
- cout << "index=" << i << ", value=" <<sam.fetch(i) << "\n";
- }
- sam=(*fred);
- cout << "\n self multiplication\n";
- sam*=(*mary);
- sam.extent(&l,&u);
- for (i=l;i<=u;i++) {
- cout << "index=" << i << ", value=" <<sam.fetch(i) << "\n";
- }
- cout << "Ram left=" << farcoreleft() << "\n";
- cout<<endl;
- }