/********************************************************************/ /* Copyright (c) 2017 System fugen G.K. and Yuzi Mizuno */ /* All rights reserved. */ /********************************************************************/ #include "MGCLStdAfx.h" #include "mg/NDDArray.h" #include "mg/KnotVector.h" #include "mg/Knot.h" #include "mg/BPointSeq.h" #include "mg/Tolerance.h" #include "cskernel/bkdtpg.h" #include "cskernel/Bkdtwe.h" #include "cskernel/bkktdp.h" #include "cskernel/Bkcdtn.h" #include "cskernel/Bkcrng.h" #include "cskernel/Bkdmix.h" #include "cskernel/Bkdnp.h" #include "cskernel/bkmlt.h" #if defined(_DEBUG) #define new DEBUG_NEW #undef THIS_FILE static char THIS_FILE[] = __FILE__; #endif // MGNDDArray // Implementation of Class MGNDDArray // Constructor //Constructor MGNDDArray of size n and lenght=n. MGNDDArray::MGNDDArray( int n, //size of this. const double* data //data array of length n if data!=NULL. ):m_capacity(n),m_length(n),m_current(0){ if(n){ m_element=new double[n]; if(data) for(int i=0; i=4 && t.bdim()>=4); int km1=t.order()-1, n=t.bdim(); int nstart=0; if(begin==MGENDC_1D || begin==MGENDC_2D) nstart=1; else if(begin==MGENDC_12D) nstart=2; int nend=0; if(end==MGENDC_1D || end==MGENDC_2D) nend=1; else if(end==MGENDC_12D) nend=2; int newn=n-nstart-nend; m_element=new double[newn]; m_capacity=m_length=newn; int newnm1=newn-1; int id,id1; double fkm1 = double(km1); m_element[0]= t(km1); for(int i=1;i n) id=n; r+= t(id); } m_element[i]=r/fkm1; } m_element[newnm1]=t(n); } // From data point, obtain data point of updated number. MGNDDArray::MGNDDArray(const MGNDDArray& tau1, int nnew) :m_element(0),m_length(0),m_capacity(0),m_current(0){ *this=tau1; change_number(nnew); } // From data point, obtain data point of updated value range. MGNDDArray::MGNDDArray(const MGNDDArray& tau1, double ts, double te) //BKCRNG :m_element(new double[tau1.length()]),m_length(tau1.length()) ,m_capacity(tau1.length()),m_current(0){ assert(ts0 && knot.multiplicity()>0); double tau=knot.value(); int imult=knot.multiplicity(); int mult = mult_max>imult ? imult : mult_max; int i=MGNDDArray::locate(tau); if(i>=0){ int current_mult=i; while(i>=0 && (*this)(i)==tau) i-=1; current_mult=current_mult-i; //current_mult is the multiplicity of tau. int able_to_add = mult_max - current_mult; //number of multiplicity if(able_to_add < mult) mult=able_to_add; } if(mult<0) mult=0; int newlength=m_length+mult; if(capacity() < newlength) reshape(newlength); int rval=mult; if(mult){ int endid=newlength-1; int j=m_length-1; while(j>i) (*this)(endid--)=(*this)(j--); while(mult--) (*this)(++i)=tau; } set_length(newlength); return rval; //Return number of data added. } //Delete one data at index. int MGNDDArray::del_data(int index){ assert(length()>0); if(index=m_element[nm1]) return nm1; if(taunm1){ m_current = nm1-1; ihi = nm1; } int istep=1; if(tau0 && taunm1) ihi=nm1; // **** NOW m_element[m_current] <= tau < m_element[ihi] . NARROW THE INTERVAL. while(1){ int middle=(m_current+ihi)/2; if(middle==m_current)//IT IS ASSUMED THAT MIDDLE=m_current IN CASE ihi=m_current+1. break; if(tau=1 ); int is=start+1; int multi_found; int isf; bkmlt_(m_length, data(), is, multi, &isf, &multi_found); if(isf>0) isf=isf-1; else isf=length()-1; index=isf; return multi_found; } // Change data point range. void MGNDDArray::change_range(double ts, double te){ assert(ts0 && length()>0); if(m_length == nnew) return *this; MGNDDArray temp(nnew); const int lenm1=m_length-1; double dlenm1=ref(lenm1), d0=ref(0); if(dlenm1<=d0) for(int i=0; ilenm1) inc=inc_total-inc_now; else{ inc=int((ref(iend)-ref(i1))*ratio+.5); if(inc+inc_now>inc_total) inc=inc_total-inc_now; } int n2=n1+inc; bkcdtn_(n1, data()+i1, n2, temp.data()+j1); i1+=n1-1; j1+=n2-1; inc_now+=inc; inext=i1+mult; } while(j1prev){ (*this)(i++)=current; prev=current; } } set_length(i); } //Remove too near data points. Removal will be done with the ordinates. void MGNDDArray::remove_too_near( bool allow_multi, //indicates if multiple data point is allowed or not. //when allow_multi=false, multiple data points will be removed. //when allow_multi=true, will not be removed. double ratio //maximum ratio allowed for neighboring span. //let ti=(*this)[i], then //if (t(i+1)-ti)/(ti-t(i-1))>ratio or (t(i+1)-ti)/(ti-t(i-1))<1/ratio, //a data point will be removed(along with the ordinates). ){ int n=length(), ordinates_size=0, sd=0; int IMLT=1; if(allow_multi) IMLT=0; bkdnp_(&n,data(),0,ordinates_size,sd,IMLT,ratio); set_length(n); } //Remove too near data points. Removal will be done with the ordinates. void MGNDDArray::remove_too_near( MGBPointSeq& ordinates, //ordinate. //ordinates.length() must be equal to this->length(). bool allow_multi, //indicates if multiple data point is allowed or not. //when allow_multi=false, multiple data points will be removed. //when allow_multi=true, will not be removed. double ratio //maximum ratio allowed for neighboring span. //let ti=(*this)[i], then //if (t(i+1)-ti)/(ti-t(i-1))>ratio or (t(i+1)-ti)/(ti-t(i-1))<1/ratio, //a data point will be removed(along with the ordinates). ){ assert(ordinates.length()==length()); int n=length(), ordinates_size=ordinates.capacity(), sd=ordinates.sdim(); int IMLT=1; if(allow_multi) IMLT=0; bkdnp_(&n,data(),ordinates.data(),ordinates_size,sd,IMLT,ratio); set_length(n); ordinates.set_length(n); } //Change the size. void MGNDDArray::reshape(int size, int start){ int new_length=m_length+start; if(sizem_capacity) data=new double[size]; else{ data=m_element; size=m_capacity;} for(int i=n-1; i>=0 ; i--) data[start+i]=m_element[i]; if(m_element!=data){ delete[] m_element; m_element=data; m_capacity=size; } m_length=new_length; m_current=0; } //Resize the array. Result will contain garbages. void MGNDDArray::resize(int nsize){ if(m_element) delete[] m_element; m_element=new double[nsize]; m_capacity=m_length=nsize; m_current=0; } //Set this as a null NDDArray. void MGNDDArray::set_null(){ if(m_element) delete[] m_element; m_element=0; m_capacity=m_length=0; m_current=0; } #define INITIAL_LENGTH 20 ///store data at the position i of this array. ///tau(i) must be => tau(i-1). ///When i>=capacity(), reshape will take place. ///The data validity is not checked. void MGNDDArray::store_with_capacityCheck( int i, ///the postion to store at. double data///the data to store. ){ assert(i>=0); if(i>=m_capacity){ int new_capacity; if(m_capacity>=INITIAL_LENGTH) new_capacity=int(m_capacity*1.3); else new_capacity=INITIAL_LENGTH; if(i>=new_capacity) new_capacity=i+1; reshape(new_capacity); m_length=new_capacity; } m_element[i]=data; } //From Knot vector, obtain data point seq abscissa. MGNDDArray& MGNDDArray::update_from_knot(const MGKnotVector& t){ m_length=t.bdim(); if(capacity()=0.){ for(int i=0; i