diff --git a/AdaptiveTreeVisualization.vcxproj b/AdaptiveTreeVisualization.vcxproj index 6e1765e..4300eb7 100644 --- a/AdaptiveTreeVisualization.vcxproj +++ b/AdaptiveTreeVisualization.vcxproj @@ -142,12 +142,15 @@ true + . Console true true true + $(OutDir) + ZLIB.lib;JPEG.lib;PNG.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) diff --git a/Makefile b/Makefile index 6961475..f5f6c1b 100644 --- a/Makefile +++ b/Makefile @@ -126,10 +126,12 @@ make_dir: $(MD) -p $(BIN) $(BIN)$(PR_TARGET): $(PR_OBJECTS) - $(CXX) -o $@ $(PR_OBJECTS) $(LFLAGS) + cd PNG && make + $(CXX) -o $@ $(PR_OBJECTS) -L$(BIN) $(LFLAGS) -ljpeg -lmypng -lz $(BIN)$(SR_TARGET): $(SR_OBJECTS) - $(CXX) -o $@ $(SR_OBJECTS) $(LFLAGS) + cd PNG && make + $(CXX) -o $@ $(SR_OBJECTS) -L$(BIN) $(LFLAGS) -ljpeg -lmypng -lz $(BIN)$(ST_TARGET): $(ST_OBJECTS) $(CXX) -o $@ $(ST_OBJECTS) $(LFLAGS) @@ -142,7 +144,8 @@ $(BIN)$(IS_TARGET): $(IS_OBJECTS) $(CXX) -o $@ $(IS_OBJECTS) -L$(BIN) $(LFLAGS) -ljpeg -lmypng -lz $(BIN)$(AV_TARGET): $(AV_OBJECTS) - $(CXX) -o $@ $(AV_OBJECTS) $(LFLAGS) + cd PNG && make + $(CXX) -o $@ $(AV_OBJECTS) -L$(BIN) $(LFLAGS) -ljpeg -lmypng -lz $(BIN)%.o: $(SRC)%.c $(CC) -c -o $@ -I$(INCLUDE) $< diff --git a/PoissonRecon.vcxproj b/PoissonRecon.vcxproj index fa78d9c..b5acc2c 100644 --- a/PoissonRecon.vcxproj +++ b/PoissonRecon.vcxproj @@ -154,7 +154,7 @@ X64 - %(AdditionalIncludeDirectories) + .;%(AdditionalIncludeDirectories) WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE;%(PreprocessorDefinitions) MultiThreadedDLL @@ -177,10 +177,11 @@ MachineX64 - psapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + ZLIB.lib;JPEG.lib;PNG.lib;psapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) $(OutDir)$(TargetName)$(TargetExt) + $(OutDir) diff --git a/SSDRecon.vcxproj b/SSDRecon.vcxproj index 3647f45..1a5bd3e 100644 --- a/SSDRecon.vcxproj +++ b/SSDRecon.vcxproj @@ -144,14 +144,16 @@ true + . Console true true true - psapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + ZLIB.lib;JPEG.lib;PNG.lib;psapi.lib;kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) UseLinkTimeCodeGeneration + $(OutDir) diff --git a/Src/AdaptiveTreeVisualization.cpp b/Src/AdaptiveTreeVisualization.cpp index 98d4ed8..ddf70d0 100644 --- a/Src/AdaptiveTreeVisualization.cpp +++ b/Src/AdaptiveTreeVisualization.cpp @@ -38,6 +38,7 @@ DAMAGE. #include "FEMTree.h" #include "Ply.h" #include "PointStreamData.h" +#include "Image.h" cmdLineParameter< char* > In( "in" ) , @@ -89,6 +90,65 @@ void ShowUsage( char* ex ) printf( "\t[--%s]\n" , Verbose.name ); } +template< typename Real , unsigned int Dim > +bool WriteImage( const Real *values , int res , const char *fileName , bool verbose ) +{ + if( Dim!=2 ) return false; + int resolution = 1; + for( int d=0 ; d [0,255]\n" , avg - 2*std , avg + 2*std ); + + unsigned char *pixels = new unsigned char[ resolution*3 ]; +#pragma omp parallel for + for( int i=0 ; i( (Real)1. , std::max< Real >( (Real)-1. , ( values[i] - avg ) / (2*std ) ) ); + v = (Real)( ( v + 1. ) / 2. * 256. ); + unsigned char color = (unsigned char )std::min< Real >( (Real)255. , std::max< Real >( (Real)0. , v ) ); + for( int c=0 ; c<3 ; c++ ) pixels[i*3+c ] = color; + } + bool success = ImageWriter::Write( fileName , pixels , res , res , 3 ); + delete[] pixels; + return success; +} + +template< typename Real , unsigned int Dim > +void WriteGrid( const Real *values , int res , const char *fileName ) +{ + int resolution = 1; + for( int d=0 ; d void _Execute( const FEMTree< Dim , Real >* tree , FILE* fp ) { @@ -100,39 +160,12 @@ void _Execute( const FEMTree< Dim , Real >* tree , FILE* fp ) // Output the grid if( OutGrid.set ) { - FILE* _fp = fopen( OutGrid.value , "wb" ); - if( !_fp ) WARN( "Failed to open grid file for writing: %s" , OutGrid.value ); - else - { - int res = 0; - double t = Time(); - Pointer( Real ) values = tree->template regularGridEvaluate< true >( coefficients , res , -1 , PrimalGrid.set ); - if( Verbose.set ) printf( "Got grid: %.2f(s)\n" , Time()-t ); - - int cells = 1; - for( int d=0 ; d( cells ); - - Real min , max; - min = max = values[0]; - for( int i=0 ; i( min , values[i] ) , max = std::max< Real >( max , values[i] ); - - int strides[Dim] , _strides[Dim] ; strides[0] = _strides[0] = 1; - int idx[Dim+1] , _idx[Dim+1] ; idx[0] = _idx[0] = 0; - for( int d=1 ; d::Run - ( - 0 , res , - [&]( int d , int i ){ _idx[d+1] = _idx[d] + _strides[d] * i , idx[d+1] = idx[d] + strides[d] * i; } , - [&]( void ){ fValues[ _idx[Dim] ] = (float)values[ idx[Dim] ]; } - ); - DeletePointer( values ); - - fwrite( &res , sizeof(int) , 1 , _fp ); - fwrite( fValues , sizeof(float) , cells , _fp ); - fclose( _fp ); - FreePointer( fValues ); - } + int res = 0; + double t = Time(); + Pointer( Real ) values = tree->template regularGridEvaluate< true >( coefficients , res , -1 , PrimalGrid.set ); + if( Verbose.set ) printf( "Got grid: %.2f(s)\n" , Time()-t ); + if( !WriteImage< Real , Dim >( values , res , OutGrid.value , Verbose.set ) ) WriteGrid< Real , Dim >( values , res , OutGrid.value ); + DeletePointer( values ); } // Output the mesh diff --git a/Src/EDTInHeat.cpp b/Src/EDTInHeat.cpp index 79f0c0b..40a966a 100644 --- a/Src/EDTInHeat.cpp +++ b/Src/EDTInHeat.cpp @@ -567,12 +567,7 @@ int main( int argc , char* argv[] ) static const int Degree = DEFAULT_FEM_DEGREE; static const BoundaryType BType = BOUNDARY_FREE; - WARN( "Compiled for degree-%d, boundary-%s, %s-precision _only_" , Degree , BoundaryNames[ BType ] , sizeof(DefaultFloatType)==4 ? "single" : "double" ); -#if 1 WARN( "Compiled for degree-%d, boundary-%s, %s-precision _only_" , Degree , BoundaryNames[ BType ] , sizeof(Real)==4 ? "single" : "double" ); -#else - WARN( "Compiled for degree-%d, boundary-%s, %s-precision _only_" , Degree , BoundaryNames[ BType ] , sizeof(DefaultFloatType)==4 ? "single" : "double" ); -#endif if( BaseDepth.value>FullDepth.value ) { if( BaseDepth.set ) WARN( "Base depth must be smaller than full depth: %d <= %d" , BaseDepth.value , FullDepth.value ); diff --git a/Src/FEMTree.IsoSurface.specialized.inl b/Src/FEMTree.IsoSurface.specialized.inl index 9f6744e..4bc2f36 100644 --- a/Src/FEMTree.IsoSurface.specialized.inl +++ b/Src/FEMTree.IsoSurface.specialized.inl @@ -26,6 +26,8 @@ ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF S DAMAGE. */ +#include +#include #include #include "MyMiscellany.h" #include "MarchingCubes.h" @@ -1646,6 +1648,14 @@ public: double cornersTime , verticesTime , edgesTime , surfaceTime; double copyFinerTime , setTableTime; IsoStats( void ) : cornersTime(0) , verticesTime(0) , edgesTime(0) , surfaceTime(0) , copyFinerTime(0) , setTableTime(0) {;} + std::string toString( void ) const + { + std::stringstream stream; + stream << "Corners / Vertices / Edges / Surface / Set Table / Copy Finer: "; + stream << std::fixed << std::setprecision(1) << cornersTime << " / " << verticesTime << " / " << edgesTime << " / " << surfaceTime << " / " << setTableTime << " / " << copyFinerTime; + stream << " (s)"; + return stream.str(); + } }; template< typename Data , unsigned int ... FEMSigs , unsigned int WeightDegree , unsigned int DataSig > static IsoStats Extract( UIntPack< FEMSigs ... > , UIntPack< WeightDegree > , UIntPack< DataSig > , const FEMTree< Dim , Real >& tree , const DensityEstimator< WeightDegree >* densityWeights , const SparseNodeData< ProjectiveData< Data , Real > , IsotropicUIntPack< Dim , DataSig > >* data , const DenseNodeData< Real , UIntPack< FEMSigs ... > >& coefficients , Real isoValue , CoredMeshData< Vertex >& mesh , std::function< void ( Vertex& , Point< Real , Dim > , Real , Data ) > SetVertex , bool nonLinearFit , bool addBarycenter , bool polygonMesh , bool flipOrientation ) diff --git a/Src/FEMTree.System.inl b/Src/FEMTree.System.inl index fdc368b..316596e 100644 --- a/Src/FEMTree.System.inl +++ b/Src/FEMTree.System.inl @@ -242,7 +242,7 @@ int FEMTree< Dim , Real >::_solveFullSystemGS( UIntPack< FEMSigs ... > , const t double bNorm=0 , inRNorm=0 , outRNorm=0; if( depth>=0 ) { - SparseMatrix< Real > M; + SparseMatrix< Real , int , WindowSize< UIntPack< BSplineOverlapSizes< FEMSignature< FEMSigs >::Degree >::OverlapSize ... > >::Size > M; double t = Time(); Pointer( Real ) D = AllocPointer< Real >( _sNodesEnd( depth ) - _sNodesBegin( depth ) ); Pointer( T ) _constraints = AllocPointer< T >( _sNodesSize( depth ) ); @@ -263,11 +263,11 @@ int FEMTree< Dim , Real >::_solveFullSystemGS( UIntPack< FEMSigs ... > , const t Pointer( T ) X = GetPointer( &solution[0] + _sNodesBegin( depth ) , _sNodesSize( depth ) ); if( computeNorms ) #pragma omp parallel for reduction( + : bNorm , inRNorm ) - for( int j=0 ; j ) start = M[j]; - ConstPointer( MatrixEntry< Real > ) end = start + (unsigned long long)M.rowSizes[j]; + ConstPointer( MatrixEntry< Real > ) end = start + (unsigned long long)M.rowSize(j); ConstPointer( MatrixEntry< Real > ) e; for( e=start ; e!=end ; e++ ) temp += X[ e->N ] * e->Value; bNorm += Dot( B[j] , B[j] ); @@ -282,11 +282,11 @@ int FEMTree< Dim , Real >::_solveFullSystemGS( UIntPack< FEMSigs ... > , const t if( computeNorms ) #pragma omp parallel for reduction( + : outRNorm ) - for( int j=0 ; j ) start = M[j]; - ConstPointer( MatrixEntry< Real > ) end = start + (unsigned long long)M.rowSizes[j]; + ConstPointer( MatrixEntry< Real > ) end = start + (unsigned long long)M.rowSize(j); ConstPointer( MatrixEntry< Real > ) e; for( e=start ; e!=end ; e++ ) temp += X[ e->N ] * e->Value; outRNorm += Dot( temp-B[j] , temp-B[j] ); @@ -408,7 +408,7 @@ int FEMTree< Dim , Real >::_solveSlicedSystemGS( UIntPack< FEMSigs ... > , const // The number of in-core blocks over which we either solve or compute residuals int matrixBlocks = std::max< int >( 1 , std::min< int >( solveBlocks+2*residualOffset , blockEnd-blockBegin ) ); // The list of matrices for each in-memory block - Pointer( SparseMatrix< Real > ) _M = NewPointer< SparseMatrix< Real > >( matrixBlocks ); + Pointer( SparseMatrix< Real , int , WindowSize< UIntPack< BSplineOverlapSizes< FEMSignature< FEMSigs >::Degree >::OverlapSize ... > >::Size > ) _M = NewPointer< SparseMatrix< Real , int , WindowSize< UIntPack< BSplineOverlapSizes< FEMSignature< FEMSigs >::Degree >::OverlapSize ... > >::Size > >( matrixBlocks ); Pointer( Pointer( Real ) ) _D = AllocPointer< Pointer( Real ) >( matrixBlocks ); std::vector< Pointer( T ) > _constraints( matrixBlocks ); for( int i=0 ; i::_solveSlicedSystemGS( UIntPack< FEMSigs ... > , const // If we are solving forward we start in a block S with S mod ColorModulus = ColorModulus-1 // and end in a block E with E mod ColorModulus = 0 while( MOD( solveWindow.begin(!forward) , ColorModulus )!=( forward ? ColorModulus-1 : 0 ) ) solveWindow -= dir , residualWindow -= dir; + int maxBlockSize = 0; + BlockWindow _residualWindow = residualWindow; + for( ; _residualWindow.end(!forward)*dir( maxBlockSize , _sNodesEnd( depth , BlockLast( b ) ) - _sNodesBegin( depth , BlockFirst( b ) ) ); + } + for( int i=0 ; i( maxBlockSize ) , _D[i] = AllocPointer< Real >( maxBlockSize ); for( ; residualWindow.end(!forward)*dir::_solveSlicedSystemGS( UIntPack< FEMSigs ... > , const int b = residualBlock , _b = MOD( b , matrixBlocks ); t = Time(); - FreePointer( _D[_b] ); - _D[_b] = AllocPointer< Real >( _sNodesEnd( depth , BlockLast( b ) ) - _sNodesBegin( depth , BlockFirst( b ) ) ); - FreePointer( _constraints[_b] ); - _constraints[_b] = AllocPointer< T >( _sNodesEnd( depth , BlockLast( b ) ) - _sNodesBegin( depth , BlockFirst( b ) ) ); _getSliceMatrixAndProlongationConstraints( UIntPack< FEMSigs ... >() , F , _M[_b] , _D[_b] , bsData , depth , _sNodesBegin( depth , BlockFirst( b ) ) , _sNodesEnd( depth , BlockLast( b ) ) , prolongedSolution , _constraints[_b] , ccStencil , pcStencils , interpolationInfo... ); #pragma omp parallel for for( int i=_sNodesBegin( depth , BlockFirst( b ) ) ; i<_sNodesEnd( depth , BlockLast( b ) ) ; i++ ) _constraints[_b][ i - _sNodesBegin( depth , BlockFirst( b ) ) ] = constraints[i] - _constraints[_b][ i - _sNodesBegin( depth , BlockFirst( b ) ) ]; @@ -452,11 +456,11 @@ int FEMTree< Dim , Real >::_solveSlicedSystemGS( UIntPack< FEMSigs ... > , const ConstPointer( T ) B = _constraints[_b]; ConstPointer( T ) X = XBlocks( depth , b , solution ); #pragma omp parallel for reduction( + : bNorm , inRNorm ) - for( int j=0 ; j<_M[_b].rowNum ; j++ ) + for( int j=0 ; j<_M[_b].rows() ; j++ ) { T temp = {}; ConstPointer( MatrixEntry< Real > ) start = _M[_b][j]; - ConstPointer( MatrixEntry< Real > ) end = start + (unsigned long long)_M[_b].rowSizes[j]; + ConstPointer( MatrixEntry< Real > ) end = start + (unsigned long long)_M[_b].rowSize(j); ConstPointer( MatrixEntry< Real > ) e; for( e=start ; e!=end ; e++ ) temp += X[ e->N ] * e->Value; bNorm += Dot( B[j] , B[j] ); @@ -493,11 +497,11 @@ int FEMTree< Dim , Real >::_solveSlicedSystemGS( UIntPack< FEMSigs ... > , const ConstPointer( T ) B = _constraints[_b]; ConstPointer( T ) X = XBlocks( depth , b , solution ); #pragma omp parallel for reduction( + : outRNorm ) - for( int j=0 ; j<_M[_b].rowNum ; j++ ) + for( int j=0 ; j<_M[_b].rows() ; j++ ) { T temp = {}; ConstPointer( MatrixEntry< Real > ) start = _M[_b][j]; - ConstPointer( MatrixEntry< Real > ) end = start + (unsigned long long)_M[_b].rowSizes[j]; + ConstPointer( MatrixEntry< Real > ) end = start + (unsigned long long)_M[_b].rowSize(j); ConstPointer( MatrixEntry< Real > ) e; for( e=start ; e!=end ; e++ ) temp += X[ e->N ] * e->Value; outRNorm += Dot( temp-B[j] , temp-B[j] ); @@ -525,7 +529,7 @@ int FEMTree< Dim , Real >::_solveSystemCG( UIntPack< FEMSigs ... > , const typen int iter = 0; Pointer( T ) X = GetPointer( &solution[0] + _sNodesBegin(depth) , _sNodesSize(depth) ); ConstPointer( T ) B = GetPointer( &constraints[0] + _sNodesBegin(depth) , _sNodesSize(depth) ); - SparseMatrix< Real > M; + SparseMatrix< Real , int , WindowSize< UIntPack< BSplineOverlapSizes< FEMSignature< FEMSigs >::Degree >::OverlapSize ... > >::Size > M; double& systemTime = stats.systemTime; double& solveTime = stats. solveTime; @@ -544,10 +548,10 @@ int FEMTree< Dim , Real >::_solveSystemCG( UIntPack< FEMSigs ... > , const typen systemTime = Time()-systemTime; solveTime = Time(); // Solve the linear system - accuracy = Real( accuracy / 100000 ) * M.rowNum; + accuracy = Real( accuracy / 100000 ) * M.rows(); int dims[] = { ( _BSplineEnd< FEMSigs >( depth ) - _BSplineBegin< FEMSigs >( depth ) ) ... }; int nonZeroRows = 0; - for( int i=0 ; i::BType ... }; @@ -558,11 +562,11 @@ int FEMTree< Dim , Real >::_solveSystemCG( UIntPack< FEMSigs ... > , const typen if( computeNorms ) { #pragma omp parallel for reduction( + : bNorm , inRNorm ) - for( int j=0 ; j ) start = M[j]; - ConstPointer( MatrixEntry< Real > ) end = start + (unsigned long long)M.rowSizes[j]; + ConstPointer( MatrixEntry< Real > ) end = start + (unsigned long long)M.rowSize(j); ConstPointer( MatrixEntry< Real > ) e; for( e=start ; e!=end ; e++ ) temp += X[ e->N ] * e->Value; bNorm += Dot( B[j] , B[j] ); @@ -574,33 +578,33 @@ int FEMTree< Dim , Real >::_solveSystemCG( UIntPack< FEMSigs ... > , const typen struct SPDFunctor { protected: - const SparseMatrix< Real >& _M; + const SparseMatrix< Real , int , WindowSize< UIntPack< BSplineOverlapSizes< FEMSignature< FEMSigs >::Degree >::OverlapSize ... > >::Size >& _M; bool _addDCTerm; public: - SPDFunctor( const SparseMatrix< Real >& M , bool addDCTerm ) : _M(M) , _addDCTerm(addDCTerm){ } + SPDFunctor( const SparseMatrix< Real , int , WindowSize< UIntPack< BSplineOverlapSizes< FEMSignature< FEMSigs >::Degree >::OverlapSize ... > >::Size >& M , bool addDCTerm ) : _M(M) , _addDCTerm(addDCTerm){ } void operator()( ConstPointer( T ) in , Pointer( T ) out ) const { _M.multiply( in , out ); if( _addDCTerm ) { T average = {}; - for( int i=0 ; i<_M.rowNum ; i++ ) average += in[i]; - average /= _M.rowNum; - for( int i=0 ; i<_M.rowNum ; i++ ) out[i] += average; + for( int i=0 ; i<_M.rows() ; i++ ) average += in[i]; + average /= _M.rows(); + for( int i=0 ; i<_M.rows() ; i++ ) out[i] += average; } } }; - if( iters ) iter = SolveCG< SPDFunctor , T , Real >( SPDFunctor( M , addDCTerm ) , (int)M.rowNum , ( ConstPointer( T ) )B , iters , X , Real( accuracy ) , Dot ); + if( iters ) iter = SolveCG< SPDFunctor , T , Real >( SPDFunctor( M , addDCTerm ) , (int)M.rows() , ( ConstPointer( T ) )B , iters , X , Real( accuracy ) , Dot ); solveTime = Time()-solveTime; if( computeNorms ) { #pragma omp parallel for reduction( + : outRNorm ) - for( int j=0 ; j ) start = M[j]; - ConstPointer( MatrixEntry< Real > ) end = start + (unsigned long long)M.rowSizes[j]; + ConstPointer( MatrixEntry< Real > ) end = start + (unsigned long long)M.rowSize(j); ConstPointer( MatrixEntry< Real > ) e; for( e=start ; e!=end ; e++ ) temp += X[ e->N ] * e->Value; outRNorm += Dot( temp-B[j] , temp-B[j] ); @@ -657,11 +661,11 @@ void FEMTree< Dim , Real >::_solveRegularMG( UIntPack< FEMSigs ... > , typename const SparseMatrix< Real , int >& _M = M.back(); ConstPointer( T ) _X = X.back(); #pragma omp parallel for reduction( + : bNorm , inRNorm ) - for( int j=0 ; j<_M.rowNum ; j++ ) + for( int j=0 ; j<_M.rows() ; j++ ) { T temp = {}; ConstPointer( MatrixEntry< Real > ) start = _M[j]; - ConstPointer( MatrixEntry< Real > ) end = start + (unsigned long long)_M.rowSizes[j]; + ConstPointer( MatrixEntry< Real > ) end = start + (unsigned long long)_M.rowSize(j); ConstPointer( MatrixEntry< Real > ) e; for( e=start ; e!=end ; e++ ) temp += _X[ e->N ] * e->Value; bNorm += Dot( _B[j] , _B[j] ); @@ -689,24 +693,24 @@ void FEMTree< Dim , Real >::_solveRegularMG( UIntPack< FEMSigs ... > , typename struct SPDFunctor { protected: - const SparseMatrix< Real >& _M; + const SparseMatrix< Real , int >& _M; bool _addDCTerm; public: - SPDFunctor( const SparseMatrix< Real >& M , bool addDCTerm ) : _M(M) , _addDCTerm(addDCTerm){ } + SPDFunctor( const SparseMatrix< Real , int >& M , bool addDCTerm ) : _M(M) , _addDCTerm(addDCTerm){ } void operator()( ConstPointer( T ) in , Pointer( T ) out ) const { _M.multiply( in , out ); if( _addDCTerm ) { T average = {}; - for( int i=0 ; i<_M.rowNum ; i++ ) average += in[i]; - average /= _M.rowNum; - for( int i=0 ; i<_M.rowNum ; i++ ) out[i] += average; + for( int i=0 ; i<_M.rows() ; i++ ) average += in[i]; + average /= _M.rows(); + for( int i=0 ; i<_M.rows() ; i++ ) out[i] += average; } } }; int nonZeroRows = 0; - for( int i=0 ; i( depth ) - _BSplineBegin< FEMSigs >( depth ) ) ... }; for( int dd=0 ; dd::_solveRegularMG( UIntPack< FEMSigs ... > , typename const SparseMatrix< Real , int >& _M = M.back(); ConstPointer( T ) _X = X.back(); #pragma omp parallel for reduction( + : outRNorm ) - for( int j=0 ; j<_M.rowNum ; j++ ) + for( int j=0 ; j<_M.rows() ; j++ ) { T temp = {}; ConstPointer( MatrixEntry< Real > ) start = _M[j]; - ConstPointer( MatrixEntry< Real > ) end = start + (unsigned long long)_M.rowSizes[j]; + ConstPointer( MatrixEntry< Real > ) end = start + (unsigned long long)_M.rowSize(j); ConstPointer( MatrixEntry< Real > ) e; for( e=start ; e!=end ; e++ ) temp += _X[ e->N ] * e->Value; outRNorm += Dot( temp-_B[j] , temp-_B[j] ); @@ -885,6 +889,70 @@ void FEMTree< Dim , Real >::_addPointValues( UIntPack< FEMSigs ... > , StaticWin ); } +template< unsigned int Dim , class Real > +template< typename T , unsigned int ... PointDs , unsigned int ... FEMSigs > +T FEMTree< Dim , Real >::_setMatrixRowAndGetConstraintFromProlongation( UIntPack< FEMSigs ... > , const BaseSystem< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& F , const typename FEMTreeNode::template ConstNeighbors< UIntPack< BSplineOverlapSizes< FEMSignature< FEMSigs >::Degree >::OverlapSize ... > >& pNeighbors , const typename FEMTreeNode::template ConstNeighbors< UIntPack< BSplineOverlapSizes< FEMSignature< FEMSigs >::Degree >::OverlapSize ... > >& neighbors , size_t idx , SparseMatrix< Real , int , WindowSize< UIntPack< BSplineOverlapSizes< FEMSignature< FEMSigs >::Degree >::OverlapSize ... > >::Size > &M , int offset , const PCStencils< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& pcStencils , const CCStencil< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& ccStencil , const PointEvaluator< UIntPack< FEMSigs ... > , UIntPack< FEMSignature< FEMSigs >::Degree ... > >& bsData , ConstPointer( T ) prolongedSolution , const InterpolationInfo< T , PointDs >* ... interpolationInfo ) const +{ + T constraint ={}; + typedef UIntPack< ( -BSplineOverlapSizes< FEMSignature< FEMSigs >::Degree >::OverlapStart ) ... > OverlapRadii; + typedef UIntPack< BSplineOverlapSizes< FEMSignature< FEMSigs >::Degree >::OverlapSize ... > OverlapSizes; + + int count = 0; + const FEMTreeNode* node = neighbors.neighbors.data[ WindowIndex< OverlapSizes , OverlapRadii >::Index ]; + Pointer( MatrixEntry< Real > ) row = M[idx]; + + LocalDepth d ; LocalOffset off; + _localDepthAndOffset( node , d , off ); + if( d>0 && prolongedSolution ) + { + int cIdx = (int)( node - node->parent->children ); + constraint = _getConstraintFromProlongedSolution( UIntPack< FEMSigs ... >() , F , neighbors , pNeighbors , node , prolongedSolution , pcStencils.data[cIdx] , bsData , interpolationInfo... ); + } + + bool isInterior = BaseFEMIntegrator::IsInteriorlyOverlapped( UIntPack< FEMSignature< FEMSigs >::Degree ... >() , UIntPack< FEMSignature< FEMSigs >::Degree ... >() , d , off ); + + StaticWindow< Real , UIntPack< BSplineOverlapSizes< FEMSignature< FEMSigs >::Degree >::OverlapSize ... > > pointValues; + memset( pointValues.data , 0 , sizeof(Real)*WindowSize< OverlapSizes >::Size ); + _addPointValues( UIntPack< FEMSigs ... >() , pointValues , neighbors , bsData , interpolationInfo ... ); + int nodeIndex = node->nodeData.nodeIndex; + if( isInterior ) // General case, so try to make fast + { + const FEMTreeNode* const * _nodes = neighbors.neighbors.data; + ConstPointer( double ) _stencil = ccStencil.data; + Real* _values = pointValues.data; + row[count++] = MatrixEntry< Real >( nodeIndex-offset , (Real)( _values[ WindowIndex< OverlapSizes , OverlapRadii >::Index ] + _stencil[ WindowIndex< OverlapSizes , OverlapRadii >::Index ] ) ); + for( int i=0 ; i::Size ; i++ ) if( _isValidFEM1Node( _nodes[i] ) ) + { + if( i!=WindowIndex< OverlapSizes , OverlapRadii >::Index ) row[count++] = MatrixEntry< Real >( _nodes[i]->nodeData.nodeIndex-offset , (Real)( _values[i] + _stencil[i] ) ); + } + } + else + { + LocalDepth d ; LocalOffset off; + _localDepthAndOffset( node , d , off ); + Real temp = (Real)F.ccIntegrate( off , off ) + pointValues.data[ WindowIndex< OverlapSizes , OverlapRadii >::Index ]; + + row[count++] = MatrixEntry< Real >( nodeIndex-offset , temp ); + LocalOffset _off; + WindowLoop< Dim >::Run + ( + ZeroUIntPack< Dim >() , OverlapSizes() , + [&]( int d , int i ){ _off[d] = off[d] - (int)OverlapRadii::Values[d] + i; } , + [&]( const FEMTreeNode* _node , Real pointValue ) + { + if( node!=_node && FEMIntegrator::IsValidFEMNode( UIntPack< FEMSigs ... >() , d , _off ) ) + { + Real temp = (Real)F.ccIntegrate( _off , off ) + pointValue; + if( _isValidFEM1Node( _node ) ) row[count++] = MatrixEntry< Real >( _node->nodeData.nodeIndex-offset , temp ); + } + } , + neighbors.neighbors() , pointValues() + ); + } + M.setRowSize( idx , count ); + return constraint; +} + template< unsigned int Dim , class Real > template< typename T , unsigned int ... PointDs , unsigned int ... FEMSigs > T FEMTree< Dim , Real >::_setMatrixRowAndGetConstraintFromProlongation( UIntPack< FEMSigs ... > , const BaseSystem< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& F , const typename FEMTreeNode::template ConstNeighbors< UIntPack< BSplineOverlapSizes< FEMSignature< FEMSigs >::Degree >::OverlapSize ... > >& pNeighbors , const typename FEMTreeNode::template ConstNeighbors< UIntPack< BSplineOverlapSizes< FEMSignature< FEMSigs >::Degree >::OverlapSize ... > >& neighbors , Pointer( MatrixEntry< Real > ) row , int offset , const PCStencils< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& pcStencils , const CCStencil< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& ccStencil , const PointEvaluator< UIntPack< FEMSigs ... > , UIntPack< FEMSignature< FEMSigs >::Degree ... > >& bsData , ConstPointer( T ) prolongedSolution , const InterpolationInfo< T , PointDs >* ... interpolationInfo ) const @@ -1501,7 +1569,7 @@ CumulativeDerivativeValues< T , Dim , PointD > FEMTree< Dim , Real >::_finerFunc template< unsigned int Dim , class Real > template< unsigned int ... FEMSigs , typename T , unsigned int ... PointDs > -int FEMTree< Dim , Real >::_getSliceMatrixAndProlongationConstraints( UIntPack< FEMSigs ... > , const typename BaseFEMIntegrator::template System< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& F , SparseMatrix< Real >& matrix , Pointer( Real ) diagonalR , const PointEvaluator< UIntPack< FEMSigs ... > , UIntPack< FEMSignature< FEMSigs >::Degree ... > >& bsData , LocalDepth depth , int nBegin , int nEnd , ConstPointer( T ) prolongedSolution , Pointer( T ) constraints , const CCStencil< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& ccStencil , const PCStencils< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& pcStencils , const InterpolationInfo< T , PointDs >* ... interpolationInfo ) const +int FEMTree< Dim , Real >::_getSliceMatrixAndProlongationConstraints( UIntPack< FEMSigs ... > , const typename BaseFEMIntegrator::template System< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& F , SparseMatrix< Real , int , WindowSize< UIntPack< BSplineOverlapSizes< FEMSignature< FEMSigs >::Degree >::OverlapSize ... > >::Size >& matrix , Pointer( Real ) diagonalR , const PointEvaluator< UIntPack< FEMSigs ... > , UIntPack< FEMSignature< FEMSigs >::Degree ... > >& bsData , LocalDepth depth , int nBegin , int nEnd , ConstPointer( T ) prolongedSolution , Pointer( T ) constraints , const CCStencil< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& ccStencil , const PCStencils< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& pcStencils , const InterpolationInfo< T , PointDs >* ... interpolationInfo ) const { typedef UIntPack< FEMSignature< FEMSigs >::Degree ... > FEMDegrees; typedef UIntPack< BSplineOverlapSizes< FEMSignature< FEMSigs >::Degree >::OverlapSize ... > OverlapSizes; @@ -1518,18 +1586,9 @@ int FEMTree< Dim , Real >::_getSliceMatrixAndProlongationConstraints( UIntPack< // Get the matrix row size typename FEMTreeNode::template ConstNeighbors< OverlapSizes > neighbors , pNeighbors; neighborKey.getNeighbors( OverlapRadii() , OverlapRadii() , node , pNeighbors , neighbors ); -#if defined( __GNUC__ ) && __GNUC__ < 5 -#warning "you've got me gcc version<5" - int count = _getMatrixRowSize( UIntPack< FEMSigs ... >() , neighbors ); -#else // !__GNUC__ || __GNUC__ >=5 - int count = _getMatrixRowSize< FEMSigs ... >( neighbors ); -#endif // __GNUC__ || __GNUC__ < 4 - // Allocate memory for the row - matrix.setRowSize( i , count ); - // Set the row entries - if( constraints ) constraints[i] = _setMatrixRowAndGetConstraintFromProlongation( UIntPack< FEMSigs ... >() , F , pNeighbors , neighbors , matrix[i] , nBegin , pcStencils , ccStencil , bsData , prolongedSolution , interpolationInfo... ); - else _setMatrixRowAndGetConstraintFromProlongation( UIntPack< FEMSigs ... >() , F , pNeighbors , neighbors , matrix[i] , nBegin , pcStencils , ccStencil , bsData , prolongedSolution , interpolationInfo... ); + if( constraints ) constraints[i] = _setMatrixRowAndGetConstraintFromProlongation( UIntPack< FEMSigs ... >() , F , pNeighbors , neighbors , i , matrix , nBegin , pcStencils , ccStencil , bsData , prolongedSolution , interpolationInfo... ); + else _setMatrixRowAndGetConstraintFromProlongation( UIntPack< FEMSigs ... >() , F , pNeighbors , neighbors , i , matrix , nBegin , pcStencils , ccStencil , bsData , prolongedSolution , interpolationInfo... ); if( diagonalR ) diagonalR[i] = (Real)1. / matrix[i][0].Value; } else if( constraints ) constraints[i] = T(); @@ -1547,12 +1606,12 @@ int FEMTree< Dim , Real >::_getSliceMatrixAndProlongationConstraints( UIntPack< template< unsigned int Dim , class Real > template< typename T , unsigned int ... PointDs , unsigned int ... FEMSigs > -SparseMatrix< Real > FEMTree< Dim , Real >::systemMatrix( UIntPack< FEMSigs ... > , typename BaseFEMIntegrator::template System< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& F , LocalDepth depth , const InterpolationInfo< T , PointDs >* ... interpolationInfo ) const +SparseMatrix< Real , int > FEMTree< Dim , Real >::systemMatrix( UIntPack< FEMSigs ... > , typename BaseFEMIntegrator::template System< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& F , LocalDepth depth , const InterpolationInfo< T , PointDs >* ... interpolationInfo ) const { _setFEM1ValidityFlags( UIntPack< FEMSigs ... >() ); typedef typename BaseFEMIntegrator::template System< UIntPack< FEMSignature< FEMSigs >::Degree ... > > BaseSystem; if( depth<0 || depth>_maxDepth ) ERROR_OUT( "System depth out of bounds: %d <= %d <= %d" , 0 , depth , _maxDepth ); - SparseMatrix< Real > matrix; + SparseMatrix< Real , int > matrix; F.init( depth ); PointEvaluator< UIntPack< FEMSigs ... > , UIntPack< FEMSignature< FEMSigs >::Degree ... > > bsData( depth ); @@ -1588,13 +1647,13 @@ SparseMatrix< Real > FEMTree< Dim , Real >::systemMatrix( UIntPack< FEMSigs ... template< unsigned int Dim , class Real > template< typename T , unsigned int ... PointDs , unsigned int ... FEMSigs > -SparseMatrix< Real > FEMTree< Dim , Real >::prolongedSystemMatrix( UIntPack< FEMSigs ... > , typename BaseFEMIntegrator::template System< UIntPack::Degree ... > >& F , LocalDepth highDepth , const InterpolationInfo< T , PointDs >* ... interpolationInfo ) const +SparseMatrix< Real , int > FEMTree< Dim , Real >::prolongedSystemMatrix( UIntPack< FEMSigs ... > , typename BaseFEMIntegrator::template System< UIntPack::Degree ... > >& F , LocalDepth highDepth , const InterpolationInfo< T , PointDs >* ... interpolationInfo ) const { _setFEM1ValidityFlags( UIntPack< FEMSigs ... >() ); if( highDepth<=0 || highDepth>_maxDepth ) ERROR_OUT( "System depth out of bounds: %d < %d <= %d" , 0 , highDepth , _maxDepth ); LocalDepth lowDepth = highDepth-1; - SparseMatrix< Real > matrix; + SparseMatrix< Real , int > matrix; F.init( highDepth ); PointEvaluator< UIntPack< FEMSigs ... > , UIntPack< FEMSignature< FEMSigs >::Degree ... > > bsData( highDepth ); typedef UIntPack< ( -BSplineOverlapSizes< FEMSignature< FEMSigs >::Degree >::OverlapStart ) ... > OverlapRadii; @@ -1625,9 +1684,9 @@ SparseMatrix< Real > FEMTree< Dim , Real >::prolongedSystemMatrix( UIntPack< FEM template< unsigned int Dim , class Real > template< unsigned int ... FEMSigs > -SparseMatrix< Real > FEMTree< Dim , Real >::downSampleMatrix( UIntPack< FEMSigs ... > , LocalDepth highDepth ) const +SparseMatrix< Real , int > FEMTree< Dim , Real >::downSampleMatrix( UIntPack< FEMSigs ... > , LocalDepth highDepth ) const { - SparseMatrix< Real > matrix; + SparseMatrix< Real , int > matrix; _setFEM1ValidityFlags( UIntPack< FEMSigs ... >() ); typedef UIntPack< FEMSignature< FEMSigs >::Degree ... > FEMDegrees; typedef UIntPack< BSplineSupportSizes< FEMSignature< FEMSigs >::Degree >::UpSampleSize ... > UpSampleSizes; @@ -1714,56 +1773,56 @@ SparseMatrix< Real > FEMTree< Dim , Real >::downSampleMatrix( UIntPack< FEMSigs template< unsigned int Dim , class Real > template< typename T , unsigned int ... PointDs , unsigned int ... FEMSigs > -SparseMatrix< Real > FEMTree< Dim , Real >::fullSystemMatrix( UIntPack< FEMSigs ... > , typename BaseFEMIntegrator::template System< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& F , LocalDepth depth , bool nonRefinableOnly , const InterpolationInfo< T , PointDs >* ... interpolationInfo ) const +SparseMatrix< Real , int > FEMTree< Dim , Real >::fullSystemMatrix( UIntPack< FEMSigs ... > , typename BaseFEMIntegrator::template System< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& F , LocalDepth depth , bool nonRefinableOnly , const InterpolationInfo< T , PointDs >* ... interpolationInfo ) const { - SparseMatrix< Real > M; - std::vector< SparseMatrix< Real > > systemMatrices( depth+1 ); - std::vector< SparseMatrix< Real > > prolongedSystemMatrices( depth ); - std::vector< std::vector< SparseMatrix< Real > > > upSampleMatrices( depth-1 ); + SparseMatrix< Real , int > M; + std::vector< SparseMatrix< Real , int > > systemMatrices( depth+1 ); + std::vector< SparseMatrix< Real , int > > prolongedSystemMatrices( depth ); + std::vector< std::vector< SparseMatrix< Real , int > > > upSampleMatrices( depth-1 ); for( int d=0 ; d& M = systemMatrices[d]; + SparseMatrix< Real , int >& M = systemMatrices[d]; M.resize( size ); - SparseMatrix< Real > _M = systemMatrix< Real >( UIntPack< FEMSigs ... >() , F , d , interpolationInfo ... ); + SparseMatrix< Real , int > _M = systemMatrix< Real >( UIntPack< FEMSigs ... >() , F , d , interpolationInfo ... ); #pragma omp parallel for for( int i=0 ; i<_M.rows() ; i++ ) { - M.setRowSize( i + _sNodesBegin(d) , _M.rowSizes[i] ); - for( int j=0 ; j<_M.rowSizes[i] ; j++ ) M[i+_sNodesBegin(d)][j] = MatrixEntry< Real >( _M[i][j].N + _sNodesBegin(d) , _M[i][j].Value ); + M.setRowSize( i + _sNodesBegin(d) , _M.rowSize(i) ); + for( int j=0 ; j<_M.rowSize(i) ; j++ ) M[i+_sNodesBegin(d)][j] = MatrixEntry< Real >( _M[i][j].N + _sNodesBegin(d) , _M[i][j].Value ); } } for( int d=0 ; d& M = prolongedSystemMatrices[d]; + SparseMatrix< Real , int >& M = prolongedSystemMatrices[d]; M.resize( size ); - SparseMatrix< Real > _M = prolongedSystemMatrix< Real >( UIntPack< FEMSigs ... >() , F , d+1 , interpolationInfo ... ); + SparseMatrix< Real , int > _M = prolongedSystemMatrix< Real >( UIntPack< FEMSigs ... >() , F , d+1 , interpolationInfo ... ); #pragma omp parallel for for( int i=0 ; i<_M.rows() ; i++ ) { - M.setRowSize( i + _sNodesBegin(d+1) , _M.rowSizes[i] ); - for( int j=0 ; j<_M.rowSizes[i] ; j++ ) M[i+_sNodesBegin(d+1)][j] = MatrixEntry< Real >( _M[i][j].N + _sNodesBegin(d) , _M[i][j].Value ); + M.setRowSize( i + _sNodesBegin(d+1) , _M.rowSize(i) ); + for( int j=0 ; j<_M.rowSize(i) ; j++ ) M[i+_sNodesBegin(d+1)][j] = MatrixEntry< Real >( _M[i][j].N + _sNodesBegin(d) , _M[i][j].Value ); } } for( int d=0 ; d& M = upSampleMatrices[d][d+1]; + SparseMatrix< Real , int >& M = upSampleMatrices[d][d+1]; M.resize( size ); - SparseMatrix< Real > _M = downSampleMatrix( UIntPack< FEMSigs ... >() , d+1 ).transpose( _sNodesSize( d+1 ) ); + SparseMatrix< Real , int > _M = downSampleMatrix( UIntPack< FEMSigs ... >() , d+1 ).transpose( _sNodesSize( d+1 ) ); #pragma omp parallel for for( int i=0 ; i<_M.rows() ; i++ ) { - M.setRowSize( i + _sNodesBegin(d+1) , _M.rowSizes[i] ); - for( int j=0 ; j<_M.rowSizes[i] ; j++ ) M[i+_sNodesBegin(d+1)][j] = MatrixEntry< Real >( _M[i][j].N + _sNodesBegin(d) , _M[i][j].Value ); + M.setRowSize( i + _sNodesBegin(d+1) , _M.rowSize(i) ); + for( int j=0 ; j<_M.rowSize(i) ; j++ ) M[i+_sNodesBegin(d+1)][j] = MatrixEntry< Real >( _M[i][j].N + _sNodesBegin(d) , _M[i][j].Value ); } for( int dd=0 ; dd _M; + SparseMatrix< Real , int > _M; int _d1 = d1 FEMTree< Dim , Real >::fullSystemMatrix( UIntPack< FEMSigs M += Matrix( d1 , d1 ); for( int d2=0 ; d2<=depth ; d2++ ) if( d1!=d2 ) { - SparseMatrix< Real > _M = Matrix( d1 , d2 ); + SparseMatrix< Real , int > _M = Matrix( d1 , d2 ); #pragma omp parallel for - for( int i=0 ; i<_M.rows() ; i++ ) if( _M.rowSizes[i] ) + for( int i=0 ; i<_M.rows() ; i++ ) if( _M.rowSize(i) ) { - size_t oldSize = M.rowSizes[i]; - M.resetRowSize( i , oldSize + _M.rowSizes[i] ); - for( int j=0 ; j<_M.rowSizes[i] ; j++ ) M[i][oldSize+j] = _M[i][j]; + size_t oldSize = M.rowSize(i); + M.resetRowSize( i , oldSize + _M.rowSize(i) ); + for( int j=0 ; j<_M.rowSize(i) ; j++ ) M[i][oldSize+j] = _M[i][j]; } } } @@ -1802,8 +1861,8 @@ SparseMatrix< Real > FEMTree< Dim , Real >::fullSystemMatrix( UIntPack< FEMSigs else { int jj=0; - for( int j=0 ; j +#include template< unsigned int Dim , class Real > class FEMTree; @@ -1940,6 +1941,8 @@ protected: template< unsigned int ... FEMSigs > int _getMatrixRowSize( const typename FEMTreeNode::template ConstNeighbors< UIntPack< BSplineOverlapSizes< FEMSignature< FEMSigs >::Degree >::OverlapSize ... > >& neighbors ) const; #endif // __GNUC__ || __GNUC__ < 4 + template< typename T , unsigned int ... PointDs , unsigned int ... FEMSigs > + T _setMatrixRowAndGetConstraintFromProlongation( UIntPack< FEMSigs ... > , const BaseSystem< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& F , const typename FEMTreeNode::template ConstNeighbors< UIntPack< BSplineOverlapSizes< FEMSignature< FEMSigs >::Degree >::OverlapSize ... > >& pNeighbors , const typename FEMTreeNode::template ConstNeighbors< UIntPack< BSplineOverlapSizes< FEMSignature< FEMSigs >::Degree >::OverlapSize ... > >& neighbors , size_t idx , SparseMatrix< Real , int , WindowSize< UIntPack< BSplineOverlapSizes< FEMSignature< FEMSigs >::Degree >::OverlapSize ... > >::Size > &M , int offset , const PCStencils< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& pcStencils , const CCStencil< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& ccStencil , const PointEvaluator< UIntPack< FEMSigs ... > , UIntPack< FEMSignature< FEMSigs >::Degree ... > >& bsData , ConstPointer( T ) prolongedSolution , const InterpolationInfo< T , PointDs >* ... interpolationInfo ) const; template< typename T , unsigned int ... PointDs , unsigned int ... FEMSigs > T _setMatrixRowAndGetConstraintFromProlongation( UIntPack< FEMSigs ... > , const BaseSystem< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& F , const typename FEMTreeNode::template ConstNeighbors< UIntPack< BSplineOverlapSizes< FEMSignature< FEMSigs >::Degree >::OverlapSize ... > >& pNeighbors , const typename FEMTreeNode::template ConstNeighbors< UIntPack< BSplineOverlapSizes< FEMSignature< FEMSigs >::Degree >::OverlapSize ... > >& neighbors , Pointer( MatrixEntry< Real > ) row , int offset , const PCStencils< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& pcStencils , const CCStencil< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& ccStencil , const PointEvaluator< UIntPack< FEMSigs ... > , UIntPack< FEMSignature< FEMSigs >::Degree ... > >& bsData , ConstPointer( T ) prolongedSolution , const InterpolationInfo< T , PointDs >* ... interpolationInfo ) const; template< typename T , unsigned int ... PointDs , unsigned int ... FEMSigs > @@ -1974,7 +1977,7 @@ protected: CumulativeDerivativeValues< T , Dim , PointD > _finerFunctionValues( UIntPack< FEMSigs ... > , Point< Real , Dim > p , const ConstPointSupportKey< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& neighborKey , const FEMTreeNode* node , const PointEvaluator< UIntPack< FEMSigs ... > , UIntPack< FEMSignature< FEMSigs >::Degree ... > >& bsData , ConstPointer( T ) coefficients ) const; template< unsigned int ... FEMSigs , typename T , unsigned int ... PointDs > - int _getSliceMatrixAndProlongationConstraints( UIntPack< FEMSigs ... > , const BaseSystem< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& F , SparseMatrix< Real >& matrix , Pointer( Real ) diagonalR , const PointEvaluator< UIntPack< FEMSigs ... > , UIntPack< FEMSignature< FEMSigs >::Degree ... > >& bsData , LocalDepth depth , int nBegin , int nEnd , ConstPointer( T ) prolongedSolution , Pointer( T ) constraints , const CCStencil < UIntPack< FEMSignature< FEMSigs >::Degree ... > >& ccStencil , const PCStencils< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& pcStencils , const InterpolationInfo< T , PointDs >* ... interpolationInfo ) const; + int _getSliceMatrixAndProlongationConstraints( UIntPack< FEMSigs ... > , const BaseSystem< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& F , SparseMatrix< Real , int , WindowSize< UIntPack< BSplineOverlapSizes< FEMSignature< FEMSigs >::Degree >::OverlapSize ... > >::Size >& matrix , Pointer( Real ) diagonalR , const PointEvaluator< UIntPack< FEMSigs ... > , UIntPack< FEMSignature< FEMSigs >::Degree ... > >& bsData , LocalDepth depth , int nBegin , int nEnd , ConstPointer( T ) prolongedSolution , Pointer( T ) constraints , const CCStencil < UIntPack< FEMSignature< FEMSigs >::Degree ... > >& ccStencil , const PCStencils< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& pcStencils , const InterpolationInfo< T , PointDs >* ... interpolationInfo ) const; // Down samples constraints @(depth) to constraints @(depth-1) template< class C , unsigned ... Degrees , unsigned int ... FEMSigs > void _downSample( UIntPack< FEMSigs ... > , typename BaseFEMIntegrator::template RestrictionProlongation< UIntPack< Degrees ... > >& RP , LocalDepth highDepth , Pointer( C ) constraints ) const; @@ -2422,14 +2425,14 @@ public: } template< typename T , unsigned int ... PointDs , unsigned int ... FEMSigs > - SparseMatrix< Real > systemMatrix( UIntPack< FEMSigs ... > , typename BaseFEMIntegrator::System< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& F , LocalDepth depth , const InterpolationInfo< T , PointDs >* ... interpolationInfo ) const; + SparseMatrix< Real , int > systemMatrix( UIntPack< FEMSigs ... > , typename BaseFEMIntegrator::System< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& F , LocalDepth depth , const InterpolationInfo< T , PointDs >* ... interpolationInfo ) const; template< typename T , unsigned int ... PointDs , unsigned int ... FEMSigs > - SparseMatrix< Real > prolongedSystemMatrix( UIntPack< FEMSigs ... > , typename BaseFEMIntegrator::System< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& F , LocalDepth highDepth , const InterpolationInfo< T , PointDs >* ... interpolationInfo ) const; + SparseMatrix< Real , int > prolongedSystemMatrix( UIntPack< FEMSigs ... > , typename BaseFEMIntegrator::System< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& F , LocalDepth highDepth , const InterpolationInfo< T , PointDs >* ... interpolationInfo ) const; template< unsigned int ... FEMSigs > - SparseMatrix< Real > downSampleMatrix( UIntPack< FEMSigs ... > , LocalDepth highDepth ) const; + SparseMatrix< Real , int > downSampleMatrix( UIntPack< FEMSigs ... > , LocalDepth highDepth ) const; template< typename T , unsigned int ... PointDs , unsigned int ... FEMSigs > - SparseMatrix< Real > fullSystemMatrix( UIntPack< FEMSigs ... > , typename BaseFEMIntegrator::System< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& F , LocalDepth depth , bool nonRefinableOnly , const InterpolationInfo< T , PointDs >* ... interpolationInfo ) const; + SparseMatrix< Real , int > fullSystemMatrix( UIntPack< FEMSigs ... > , typename BaseFEMIntegrator::System< UIntPack< FEMSignature< FEMSigs >::Degree ... > >& F , LocalDepth depth , bool nonRefinableOnly , const InterpolationInfo< T , PointDs >* ... interpolationInfo ) const; struct SolverInfo { @@ -2543,7 +2546,10 @@ template< unsigned int Dim , class Real > double FEMTree< Dim , Real >::_LocalMe template< unsigned int Dim , class Real , class Vertex > struct IsoSurfaceExtractor { - struct IsoStats{}; + struct IsoStats + { + std::string toString( void ) const { return std::string( "Iso-surface extraction not supported for dimension %d" , Dim ); } + }; template< typename Data , unsigned int ... FEMSigs , unsigned int WeightDegree , unsigned int DataSig > static IsoStats Extract ( diff --git a/Src/FEMTree.inl b/Src/FEMTree.inl index bf00596..b07a188 100644 --- a/Src/FEMTree.inl +++ b/Src/FEMTree.inl @@ -482,7 +482,8 @@ void FEMTree< Dim , Real >::finalizeForMultigrid( LocalDepth fullDepth , const H for( LocalDepth d=_maxDepth-1 ; d>=0 ; d-- ) { std::vector< FEMTreeNode* > nodes; - for( FEMTreeNode* node=_tree->nextNode() ; node ; node=_tree->nextNode( node ) ) if( _localDepth( node )==d && IsActiveNode< Dim >( node->children ) ) nodes.push_back( node ); + auto NodeTerminationLambda = [&]( const FEMTreeNode *node ){ return _localDepth( node )==d; }; + for( FEMTreeNode* node=_tree->nextNode( NodeTerminationLambda , NULL ) ; node ; node=_tree->nextNode( NodeTerminationLambda , node ) ) if( _localDepth( node )==d && IsActiveNode< Dim >( node->children ) ) nodes.push_back( node ); #pragma omp parallel for for( int i=0 ; i::finalizeForMultigrid( LocalDepth fullDepth , const H template< unsigned int Dim , class Real > void FEMTree< Dim , Real >::_setSpaceValidityFlags( void ) const { +#pragma omp parallel for for( int i=0 ; i<_sNodes.size() ; i++ ) { const unsigned char MASK = ~( FEMTreeNodeData::SPACE_FLAG ); @@ -606,12 +608,17 @@ template< unsigned int Dim , class Real > template< class HasDataFunctor > void FEMTree< Dim , Real >::_clipTree( const HasDataFunctor& f , LocalDepth fullDepth ) { - for( FEMTreeNode* temp=_tree->nextNode() ; temp ; temp=_tree->nextNode(temp) ) if( temp->children && _localDepth( temp )>=fullDepth ) - { - bool hasData = false; - for( int c=0 ; c<(1<children + c ); - for( int c=0 ; c<(1<( temp->children+c , !hasData ); - } + std::vector< FEMTreeNode * > nodes; + auto NodeTerminationLambda = [&]( const FEMTreeNode *node ){ return _localDepth( node )==fullDepth; }; + for( FEMTreeNode* temp=_tree->nextNode( NodeTerminationLambda , NULL ) ; temp ; temp=_tree->nextNode( NodeTerminationLambda , temp ) ) if( _localDepth( temp )==fullDepth ) nodes.push_back( temp ); +#pragma omp parallel for + for( int i=0 ; inextNode() ; node ; node=nodes[i]->nextNode(node) ) if( node->children ) + { + bool hasData = false; + for( int c=0 ; c<(1<children + c ); + for( int c=0 ; c<(1<( node->children+c , !hasData ); + } } template< unsigned int Dim , class Real > diff --git a/Src/PNG.inl b/Src/PNG.inl index da5daae..d024f78 100644 --- a/Src/PNG.inl +++ b/Src/PNG.inl @@ -99,7 +99,6 @@ inline bool PNGReader::GetInfo( const char* fileName , unsigned int& width , uns return true; } -#if 1 PNGWriter::PNGWriter( const char* fileName , unsigned int width , unsigned int height , unsigned int channels , unsigned int quality ) { _currentRow = 0; @@ -148,52 +147,3 @@ unsigned int PNGWriter::nextRows( const unsigned char* rows , unsigned int rowNu for( unsigned int r=0 ; rwidth ) ); return _currentRow += rowNum; } -#else - -void PNGWriteColor( const char* fileName , const unsigned char* pixels , int width , int height ) -{ - FILE* fp = fopen( fileName , "wb" ); - if( !fp ) ERROR_OUT( "Failed to open file for writing: %s" , fileName ); - png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING,0,0,0); - if(!png_ptr) return; - png_infop info_ptr = png_create_info_struct(png_ptr); - if(!info_ptr) return; - png_init_io(png_ptr, fp); - // turn off compression or set another filter - // png_set_filter(png_ptr, 0, PNG_FILTER_NONE); - png_set_IHDR(png_ptr, info_ptr, width , height , - 8,PNG_COLOR_TYPE_RGB, - PNG_INTERLACE_NONE, - PNG_COMPRESSION_TYPE_DEFAULT, - PNG_FILTER_TYPE_DEFAULT); - if (0) { // high-level write - std::vector matrix( width * height * 3 ); - std::vector row_pointers( height ); - for(int y=0;y buffer(width*3); - for(int y=0;y , std::tuple< SampleData ... > , FEMTr else isoStats = IsoSurfaceExtractor< Dim , Real , Vertex >::template Extract< TotalPointSampleData >( Sigs() , UIntPack< WEIGHT_DEGREE >() , UIntPack< DataSig >() , tree , density , NULL , solution , isoValue , *mesh , SetVertex , !LinearFit.set , !NonManifold.set , PolygonMesh.set , false ); #endif // __GNUC__ || __GNUC__ < 4 messageWriter( "Vertices / Polygons: %d / %d\n" , mesh->outOfCorePointCount()+mesh->inCorePoints.size() , mesh->polygonCount() ); - messageWriter( "Corners / Vertices / Edges / Surface / Set Table / Copy Finer: %.1f / %.1f / %.1f / %.1f / %.1f / %.1f (s)\n" , isoStats.cornersTime , isoStats.verticesTime , isoStats.edgesTime , isoStats.surfaceTime , isoStats.setTableTime , isoStats.copyFinerTime ); + std::string isoStatsString = isoStats.toString() + std::string( "\n" ); + messageWriter( isoStatsString.c_str() ); if( PolygonMesh.set ) profiler.dumpOutput2( comments , "# Got polygons:" ); else profiler.dumpOutput2( comments , "# Got triangles:" ); @@ -350,6 +352,65 @@ void ExtractMesh( UIntPack< FEMSigs ... > , std::tuple< SampleData ... > , FEMTr delete mesh; } +template< typename Real , unsigned int Dim > +bool WriteImage( const Real *values , int res , const char *fileName , bool verbose ) +{ + if( Dim!=2 ) return false; + int resolution = 1; + for( int d=0 ; d [0,255]\n" , avg - 2*std , avg + 2*std ); + + unsigned char *pixels = new unsigned char[ resolution*3 ]; +#pragma omp parallel for + for( int i=0 ; i( (Real)1. , std::max< Real >( (Real)-1. , ( values[i] - avg ) / (2*std ) ) ); + v = (Real)( ( v + 1. ) / 2. * 256. ); + unsigned char color = (unsigned char )std::min< Real >( (Real)255. , std::max< Real >( (Real)0. , v ) ); + for( int c=0 ; c<3 ; c++ ) pixels[i*3+c ] = color; + } + bool success = ImageWriter::Write( fileName , pixels , res , res , 3 ); + delete[] pixels; + return success; +} + +template< typename Real , unsigned int Dim > +void WriteGrid( const Real *values , int res , const char *fileName ) +{ + int resolution = 1; + for( int d=0 ; d void Execute( int argc , char* argv[] , UIntPack< FEMSigs ... > ) { @@ -601,28 +662,16 @@ void Execute( int argc , char* argv[] , UIntPack< FEMSigs ... > ) if( VoxelGrid.set ) { - FILE* fp = fopen( VoxelGrid.value , "wb" ); - if( !fp ) WARN( "Failed to open voxel file for writing: %s" , VoxelGrid.value ); - else - { - int res = 0; - profiler.start(); - Pointer( Real ) values = tree.template regularGridEvaluate< true >( solution , res , -1 , PrimalVoxel.set ); + int res = 0; + profiler.start(); + Pointer( Real ) values = tree.template regularGridEvaluate< true >( solution , res , -1 , PrimalVoxel.set ); + int resolution = 1; + for( int d=0 ; d( values , res , VoxelGrid.value , Verbose.set ) ) WriteGrid< Real , DIMENSION >( values , res , VoxelGrid.value ); + DeletePointer( values ); } if( Out.set ) diff --git a/Src/RegularTree.h b/Src/RegularTree.h index f7c5892..5e1a1c2 100644 --- a/Src/RegularTree.h +++ b/Src/RegularTree.h @@ -78,6 +78,13 @@ public: const RegularTreeNode* nextLeaf( const RegularTreeNode* currentLeaf=NULL ) const; RegularTreeNode* nextLeaf( RegularTreeNode* currentLeaf=NULL ); + + // This lambda takes a RegularTreeNode* as an argument and returns true if we do not need to traverse the tree beyond the specified node. + template< typename NodeTerminationLambda > + const RegularTreeNode* nextNode( NodeTerminationLambda &ntl , const RegularTreeNode* currentNode ) const; + template< typename NodeTerminationLambda > + RegularTreeNode* nextNode( NodeTerminationLambda &ntl , RegularTreeNode* currentNode ); + const RegularTreeNode* nextNode( const RegularTreeNode* currentNode=NULL ) const; RegularTreeNode* nextNode( RegularTreeNode* currentNode=NULL ); const RegularTreeNode* nextBranch( const RegularTreeNode* current ) const; diff --git a/Src/RegularTree.inl b/Src/RegularTree.inl index 2382344..bafec9a 100644 --- a/Src/RegularTree.inl +++ b/Src/RegularTree.inl @@ -311,6 +311,23 @@ RegularTreeNode< Dim , NodeData , DepthAndOffsetType >* RegularTreeNode< Dim , N else return temp->nextLeaf(); } +template< unsigned int Dim , class NodeData , class DepthAndOffsetType > +template< typename NodeTerminationLambda > +const RegularTreeNode< Dim , NodeData , DepthAndOffsetType >* RegularTreeNode< Dim , NodeData , DepthAndOffsetType >::nextNode( NodeTerminationLambda &ntl , const RegularTreeNode *current ) const +{ + if( !current ) return this; + else if( current->children && !ntl(current) ) return current->children; + else return nextBranch( current ); +} +template< unsigned int Dim , class NodeData , class DepthAndOffsetType > +template< typename NodeTerminationLambda > +RegularTreeNode< Dim , NodeData , DepthAndOffsetType >* RegularTreeNode< Dim , NodeData , DepthAndOffsetType >::nextNode( NodeTerminationLambda &ntl , RegularTreeNode* current ) +{ + if( !current ) return this; + else if( current->children && !ntl(current) ) return current->children; + else return nextBranch( current ); +} + template< unsigned int Dim , class NodeData , class DepthAndOffsetType > const RegularTreeNode< Dim , NodeData , DepthAndOffsetType >* RegularTreeNode< Dim , NodeData , DepthAndOffsetType >::nextNode( const RegularTreeNode* current ) const { diff --git a/Src/SSDRecon.cpp b/Src/SSDRecon.cpp index 22817dc..9845c10 100644 --- a/Src/SSDRecon.cpp +++ b/Src/SSDRecon.cpp @@ -48,6 +48,7 @@ DAMAGE. #include "FEMTree.h" #include "Ply.h" #include "PointStreamData.h" +#include "Image.h" MessageWriter messageWriter; @@ -292,7 +293,11 @@ template< unsigned int Dim , typename Real , typename TotalPointSampleData > struct SystemDual { CumulativeDerivativeValues< Real , Dim , 1 > weight; - SystemDual( Real v , Real g ) : weight( v , g , g , g ) { } + SystemDual( Real v , Real g ) + { + weight[0] = v; + for( int d=0 ; d operator()( Point< Real , Dim > p , const TotalPointSampleData& data , const CumulativeDerivativeValues< Real , Dim , 1 >& dValues ) const { return dValues * weight; @@ -360,7 +365,8 @@ void ExtractMesh( UIntPack< FEMSigs ... > , std::tuple< SampleData ... > , FEMTr else isoStats = IsoSurfaceExtractor< Dim , Real , Vertex >::template Extract< TotalPointSampleData >( Sigs() , UIntPack< WEIGHT_DEGREE >() , UIntPack< DataSig >() , tree , density , NULL , solution , isoValue , *mesh , SetVertex , NonLinearFit.set , !NonManifold.set , PolygonMesh.set , false ); #endif // __GNUC__ || __GNUC__ < 4 messageWriter( "Vertices / Polygons: %d / %d\n" , mesh->outOfCorePointCount()+mesh->inCorePoints.size() , mesh->polygonCount() ); - messageWriter( "Corners / Vertices / Edges / Surface / Set Table / Copy Finer: %.1f / %.1f / %.1f / %.1f / %.1f / %.1f (s)\n" , isoStats.cornersTime , isoStats.verticesTime , isoStats.edgesTime , isoStats.surfaceTime , isoStats.setTableTime , isoStats.copyFinerTime ); + std::string isoStatsString = isoStats.toString() + std::string( "\n" ); + messageWriter( isoStatsString.c_str() ); if( PolygonMesh.set ) profiler.dumpOutput2( comments , "# Got polygons:" ); else profiler.dumpOutput2( comments , "# Got triangles:" ); @@ -370,6 +376,65 @@ void ExtractMesh( UIntPack< FEMSigs ... > , std::tuple< SampleData ... > , FEMTr delete mesh; } +template< typename Real , unsigned int Dim > +bool WriteImage( const Real *values , int res , const char *fileName , bool verbose ) +{ + if( Dim!=2 ) return false; + int resolution = 1; + for( int d=0 ; d [0,255]\n" , avg - 2*std , avg + 2*std ); + + unsigned char *pixels = new unsigned char[ resolution*3 ]; +#pragma omp parallel for + for( int i=0 ; i( (Real)1. , std::max< Real >( (Real)-1. , ( values[i] - avg ) / (2*std ) ) ); + v = (Real)( ( v + 1. ) / 2. * 256. ); + unsigned char color = (unsigned char )std::min< Real >( (Real)255. , std::max< Real >( (Real)0. , v ) ); + for( int c=0 ; c<3 ; c++ ) pixels[i*3+c ] = color; + } + bool success = ImageWriter::Write( fileName , pixels , res , res , 3 ); + delete[] pixels; + return success; +} + +template< typename Real , unsigned int Dim > +void WriteGrid( const Real *values , int res , const char *fileName ) +{ + int resolution = 1; + for( int d=0 ; d void Execute( int argc , char* argv[] , UIntPack< FEMSigs ... > ) { @@ -602,28 +667,16 @@ void Execute( int argc , char* argv[] , UIntPack< FEMSigs ... > ) if( VoxelGrid.set ) { - FILE* fp = fopen( VoxelGrid.value , "wb" ); - if( !fp ) WARN( "Failed to open voxel file for writing: %s" , VoxelGrid.value ); - else - { - int res = 0; - profiler.start(); - Pointer( Real ) values = tree.template regularGridEvaluate< true >( solution , res , -1 , PrimalVoxel.set ); + int res = 0; + profiler.start(); + Pointer( Real ) values = tree.template regularGridEvaluate< true >( solution , res , -1 , PrimalVoxel.set ); + int resolution = 1; + for( int d=0 ; d( values , res , VoxelGrid.value , Verbose.set ) ) WriteGrid< Real , DIMENSION >( values , res , VoxelGrid.value ); + DeletePointer( values ); } if( Out.set ) diff --git a/Src/SparseMatrix.h b/Src/SparseMatrix.h index bc157e1..8c6bbf8 100644 --- a/Src/SparseMatrix.h +++ b/Src/SparseMatrix.h @@ -31,9 +31,11 @@ DAMAGE. #include "SparseMatrixInterface.h" #include "Array.h" -template< class T , class IndexType=int > class SparseMatrix : public SparseMatrixInterface< T , ConstPointer( MatrixEntry< T , IndexType > ) > +template< class T , class IndexType , size_t MaxRowSize=0 > class SparseMatrix; + +template< class T , class IndexType > class SparseMatrix< T , IndexType , 0 > : public SparseMatrixInterface< T , ConstPointer( MatrixEntry< T , IndexType > ) > { - template< class T2 , class IndexType2 > friend class SparseMatrix; + template< class T2 , class IndexType2 , size_t MaxRowSize2 > friend class SparseMatrix; Pointer( Pointer( MatrixEntry< T , IndexType > ) ) _entries; public: static void Swap( SparseMatrix& M1 , SparseMatrix& M2 ) @@ -52,17 +54,17 @@ public: SparseMatrix( const SparseMatrix& M ); SparseMatrix( SparseMatrix&& M ); template< class T2 , class IndexType2 > - SparseMatrix( const SparseMatrix< T2 , IndexType2 >& M ); + SparseMatrix( const SparseMatrix< T2 , IndexType2 , 0 >& M ); ~SparseMatrix(); SparseMatrix& operator = ( SparseMatrix&& M ); SparseMatrix< T , IndexType >& operator = ( const SparseMatrix< T , IndexType >& M ); template< class T2 , class IndexType2 > - SparseMatrix< T , IndexType >& operator = ( const SparseMatrix< T2 , IndexType2 >& M ); + SparseMatrix< T , IndexType , 0 >& operator = ( const SparseMatrix< T2 , IndexType2 , 0 >& M ); template< class T2 > void operator()( const T2* in , T2* out ) const; template< class T2 , class IndexType2 > - SparseMatrix< T , IndexType >& copy( const SparseMatrix< T2 , IndexType2 >& M ); + SparseMatrix< T , IndexType , 0 >& copy( const SparseMatrix< T2 , IndexType2 , 0 >& M ); inline ConstPointer( MatrixEntry< T , IndexType > ) begin( size_t row ) const { return _entries[row]; } inline ConstPointer( MatrixEntry< T , IndexType > ) end ( size_t row ) const { return _entries[row] + (unsigned long long)rowSizes[row]; } @@ -100,5 +102,57 @@ public: template< class const_iterator > static SparseMatrix Transpose( const SparseMatrixInterface< T , const_iterator >& At , size_t outRows , T (*TransposeFunction)( const T& )=NULL ); }; + +template< class T , class IndexType , size_t MaxRowSize > class SparseMatrix : public SparseMatrixInterface< T , ConstPointer( MatrixEntry< T , IndexType > ) > +{ + template< class T2 , class IndexType2 > friend class _SparseMatrix; + Pointer( MatrixEntry< T , IndexType > ) _entries; + size_t _rowNum; + Pointer( size_t ) _rowSizes; + size_t _maxRows; +public: + static void Swap( SparseMatrix& M1 , SparseMatrix& M2 ) + { + std::swap( M1._rowNum , M2._rowNum ); + std::swap( M1._rowSizes , M2._rowSizes ); + std::swap( M1._entries , M2._entries ); + } + typedef SparseMatrixInterface< T , ConstPointer( MatrixEntry< T , IndexType > ) > Interface; + typedef ConstPointer( MatrixEntry< T , IndexType > ) RowIterator; + + SparseMatrix( void ); + SparseMatrix( const SparseMatrix& M ); + SparseMatrix( SparseMatrix&& M ); + template< class T2 , class IndexType2 > + SparseMatrix( const SparseMatrix< T2 , IndexType2 , MaxRowSize >& M ); + SparseMatrix& operator = ( SparseMatrix&& M ); + SparseMatrix< T , IndexType , MaxRowSize >& operator = ( const SparseMatrix< T , IndexType , MaxRowSize >& M ); + template< class T2 , class IndexType2 > + SparseMatrix< T , IndexType , MaxRowSize >& operator = ( const SparseMatrix< T2 , IndexType2 , MaxRowSize >& M ); + ~SparseMatrix( void ); + + template< class T2 > void operator()( const T2* in , T2* out ) const; + + inline ConstPointer( MatrixEntry< T , IndexType > ) begin( size_t row ) const { return _entries + MaxRowSize * row; } + inline ConstPointer( MatrixEntry< T , IndexType > ) end ( size_t row ) const { return _entries + MaxRowSize * row + (unsigned long long)_rowSizes[row]; } + inline size_t rows ( void ) const { return _rowNum; } + inline size_t rowSize ( size_t idx ) const { return _rowSizes[idx]; } + + SparseMatrix( size_t rowNum ); + void resize ( size_t rowNum ); + void setRowSize( size_t row , size_t rowSize ); + void resetRowSize( size_t row , size_t rowSize ); + inline Pointer( MatrixEntry< T , IndexType > ) operator[] ( size_t idx ) { return _entries + MaxRowSize * idx; } + inline ConstPointer( MatrixEntry< T , IndexType > ) operator[] ( size_t idx ) const { return _entries + MaxRowSize * idx; } + + // With copy move, these should be well-behaved from a memory perspective + SparseMatrix operator * ( T s ) const; + SparseMatrix operator / ( T s ) const; + SparseMatrix& operator *= ( T s ); + SparseMatrix& operator /= ( T s ); + + Pointer( T ) operator * ( const Pointer( T ) in ) const; +}; + #include "SparseMatrix.inl" #endif /* __SPARSEMATRIX_HPP */ diff --git a/Src/SparseMatrix.inl b/Src/SparseMatrix.inl index 44d2b3d..d912c1d 100644 --- a/Src/SparseMatrix.inl +++ b/Src/SparseMatrix.inl @@ -30,15 +30,11 @@ DAMAGE. #include #include -/////////////////// -// SparseMatrix // -/////////////////// -/////////////////////////////////////// -// SparseMatrix Methods and Memebers // -/////////////////////////////////////// - +/////////////////////////////////////////////////////////////// +// SparseMatrix (unconstrained max row size specialization) // +/////////////////////////////////////////////////////////////// template< class T , class IndexType > -SparseMatrix< T , IndexType >::SparseMatrix( void ) +SparseMatrix< T , IndexType , 0 >::SparseMatrix( void ) { rowSizes = NullPointer( size_t ); rowNum = 0; @@ -46,7 +42,7 @@ SparseMatrix< T , IndexType >::SparseMatrix( void ) } template< class T , class IndexType > -SparseMatrix< T , IndexType >::SparseMatrix( size_t rowNum ) +SparseMatrix< T , IndexType , 0 >::SparseMatrix( size_t rowNum ) { this->rowNum = 0; rowSizes = NullPointer( size_t ); @@ -54,7 +50,7 @@ SparseMatrix< T , IndexType >::SparseMatrix( size_t rowNum ) resize( rowNum ); } template< class T , class IndexType > -SparseMatrix< T , IndexType >::SparseMatrix( const SparseMatrix& M ) +SparseMatrix< T , IndexType , 0 >::SparseMatrix( const SparseMatrix& M ) { rowSizes = NullPointer( size_t ); rowNum = 0; @@ -67,7 +63,7 @@ SparseMatrix< T , IndexType >::SparseMatrix( const SparseMatrix& M ) } } template< class T , class IndexType > -SparseMatrix< T , IndexType >::SparseMatrix( SparseMatrix&& M ) +SparseMatrix< T , IndexType , 0 >::SparseMatrix( SparseMatrix&& M ) { rowSizes = NullPointer( size_t ); rowNum = 0; @@ -77,7 +73,7 @@ SparseMatrix< T , IndexType >::SparseMatrix( SparseMatrix&& M ) } template< class T , class IndexType > template< class T2 , class IndexType2 > -SparseMatrix< T , IndexType >::SparseMatrix( const SparseMatrix< T2 , IndexType2 >& M ) +SparseMatrix< T , IndexType , 0 >::SparseMatrix( const SparseMatrix< T2 , IndexType2 , 0 >& M ) { rowSizes = NullPointer( size_t ); rowNum = 0; @@ -92,7 +88,7 @@ SparseMatrix< T , IndexType >::SparseMatrix( const SparseMatrix< T2 , IndexType2 template< class T , class IndexType > template< class T2 , class IndexType2 > -SparseMatrix< T , IndexType >& SparseMatrix< T , IndexType >::copy( const SparseMatrix< T2 , IndexType2 >& M ) +SparseMatrix< T , IndexType , 0 >& SparseMatrix< T , IndexType , 0 >::copy( const SparseMatrix< T2 , IndexType2 , 0 >& M ) { resize( M.rowNum ); for ( int i=0 ; i& SparseMatrix< T , IndexType >::copy( const Sparse return *this; } template< class T , class IndexType > -SparseMatrix< T , IndexType >& SparseMatrix< T , IndexType >::operator = ( SparseMatrix< T , IndexType >&& M ) +SparseMatrix< T , IndexType , 0 >& SparseMatrix< T , IndexType , 0 >::operator = ( SparseMatrix< T , IndexType , 0 >&& M ) { Swap( *this , M ); return *this; } template< class T , class IndexType > -SparseMatrix< T , IndexType >& SparseMatrix< T , IndexType >::operator = ( const SparseMatrix< T , IndexType >& M ) +SparseMatrix< T , IndexType , 0 >& SparseMatrix< T , IndexType , 0 >::operator = ( const SparseMatrix< T , IndexType , 0 >& M ) { resize( M.rowNum ); for( int i=0 ; i& SparseMatrix< T , IndexType >::operator = ( const } template< class T , class IndexType > template< class T2 , class IndexType2 > -SparseMatrix< T , IndexType >& SparseMatrix< T , IndexType >::operator = (const SparseMatrix< T2 , IndexType2 >& M) +SparseMatrix< T , IndexType , 0 >& SparseMatrix< T , IndexType , 0 >::operator = (const SparseMatrix< T2 , IndexType2 , 0 >& M) { resize( M.rowNum ); for( int i=0 ; i& SparseMatrix< T , IndexType >::operator = (const template< class T , class IndexType > template< class T2 > -void SparseMatrix< T , IndexType >::operator() ( const T2* in , T2* out ) const { Interface::multiply( in , out ); } +void SparseMatrix< T , IndexType , 0 >::operator() ( const T2* in , T2* out ) const { Interface::multiply( in , out ); } - -template< class T , class IndexType > SparseMatrix< T , IndexType >::~SparseMatrix( void ) { resize( 0 ); } +template< class T , class IndexType > SparseMatrix< T , IndexType , 0 >::~SparseMatrix( void ) { resize( 0 ); } template< class T , class IndexType > -void SparseMatrix< T , IndexType >::resize( size_t r ) +void SparseMatrix< T , IndexType , 0 >::resize( size_t r ) { if( rowNum>0 ) { @@ -163,7 +158,7 @@ void SparseMatrix< T , IndexType >::resize( size_t r ) } template< class T , class IndexType > -void SparseMatrix< T , IndexType >::setRowSize( size_t row , size_t count ) +void SparseMatrix< T , IndexType , 0 >::setRowSize( size_t row , size_t count ) { if( row>=0 && row::setRowSize( size_t row , size_t count ) else ERROR_OUT( "Row is out of bounds: 0 <= %d < %d" , (int)row , (int)rowNum ); } template< class T , class IndexType > -void SparseMatrix< T , IndexType >::resetRowSize( size_t row , size_t count ) +void SparseMatrix< T , IndexType , 0 >::resetRowSize( size_t row , size_t count ) { if( row>=0 && row::resetRowSize( size_t row , size_t count ) } template< class T , class IndexType > -SparseMatrix< T , IndexType > SparseMatrix< T , IndexType >::Identity( size_t dim ) +SparseMatrix< T , IndexType , 0 > SparseMatrix< T , IndexType , 0 >::Identity( size_t dim ) { SparseMatrix I; I.resize( dim ); @@ -199,52 +194,52 @@ SparseMatrix< T , IndexType > SparseMatrix< T , IndexType >::Identity( size_t di return I; } template< class T , class IndexType > -SparseMatrix< T , IndexType >& SparseMatrix< T , IndexType >::operator *= ( T s ) +SparseMatrix< T , IndexType , 0 >& SparseMatrix< T , IndexType , 0 >::operator *= ( T s ) { #pragma omp parallel for for( int i=0 ; i -SparseMatrix< T , IndexType >& SparseMatrix< T , IndexType >::operator /= ( T s ){ return (*this) * ( (T)1./s ); } +SparseMatrix< T , IndexType , 0 >& SparseMatrix< T , IndexType , 0 >::operator /= ( T s ){ return (*this) * ( (T)1./s ); } template< class T , class IndexType > -SparseMatrix< T , IndexType >& SparseMatrix< T , IndexType >::operator *= ( const SparseMatrix< T , IndexType >& B ) +SparseMatrix< T , IndexType , 0 >& SparseMatrix< T , IndexType , 0 >::operator *= ( const SparseMatrix< T , IndexType , 0 >& B ) { SparseMatrix foo = (*this) * B; (*this) = foo; return *this; } template< class T , class IndexType > -SparseMatrix< T , IndexType >& SparseMatrix< T , IndexType >::operator += ( const SparseMatrix< T , IndexType >& B ) +SparseMatrix< T , IndexType , 0 >& SparseMatrix< T , IndexType , 0 >::operator += ( const SparseMatrix< T , IndexType , 0 >& B ) { SparseMatrix foo = (*this) + B; (*this) = foo; return *this; } template< class T , class IndexType > -SparseMatrix< T , IndexType >& SparseMatrix< T , IndexType >::operator -= ( const SparseMatrix< T , IndexType >& B ) +SparseMatrix< T , IndexType , 0 >& SparseMatrix< T , IndexType , 0 >::operator -= ( const SparseMatrix< T , IndexType , 0 >& B ) { SparseMatrix foo = (*this) - B; (*this) = foo; return *this; } template< class T , class IndexType > -SparseMatrix< T , IndexType > SparseMatrix< T , IndexType >::operator * ( T s ) const +SparseMatrix< T , IndexType , 0 > SparseMatrix< T , IndexType , 0 >::operator * ( T s ) const { SparseMatrix out = (*this); return out *= s; } template< class T , class IndexType > -SparseMatrix< T , IndexType > SparseMatrix< T , IndexType >::operator / ( T s ) const { return (*this) * ( (T)1. / s ); } +SparseMatrix< T , IndexType , 0 > SparseMatrix< T , IndexType , 0 >::operator / ( T s ) const { return (*this) * ( (T)1. / s ); } template< class T , class IndexType > -Pointer( T ) SparseMatrix< T , IndexType >::operator * ( const Pointer( T ) in ) const +Pointer( T ) SparseMatrix< T , IndexType , 0 >::operator * ( const Pointer( T ) in ) const { Pointer( T ) out = AllocPointer< T >( rowNum ); MultiplyParallel( in , out , omp_get_num_procs() , 0 ); return out; } template< class T , class IndexType > -SparseMatrix< T , IndexType > SparseMatrix< T , IndexType >::operator * ( const SparseMatrix< T , IndexType >& B ) const +SparseMatrix< T , IndexType , 0 > SparseMatrix< T , IndexType , 0 >::operator * ( const SparseMatrix< T , IndexType , 0 >& B ) const { SparseMatrix out; const SparseMatrix& A = *this; @@ -279,7 +274,7 @@ SparseMatrix< T , IndexType > SparseMatrix< T , IndexType >::operator * ( const return out; } template< class T , class IndexType > -SparseMatrix< T , IndexType > SparseMatrix< T , IndexType >::operator + ( const SparseMatrix< T , IndexType >& B ) const +SparseMatrix< T , IndexType , 0 > SparseMatrix< T , IndexType , 0 >::operator + ( const SparseMatrix< T , IndexType , 0 >& B ) const { const SparseMatrix& A = *this; size_t rowNum = std::max< size_t >( A.rowNum , B.rowNum ); @@ -313,7 +308,7 @@ SparseMatrix< T , IndexType > SparseMatrix< T , IndexType >::operator + ( const return out; } template< class T , class IndexType > -SparseMatrix< T , IndexType > SparseMatrix< T , IndexType >::operator - ( const SparseMatrix< T , IndexType >& B ) const +SparseMatrix< T , IndexType , 0 > SparseMatrix< T , IndexType , 0 >::operator - ( const SparseMatrix< T , IndexType , 0 >& B ) const { const SparseMatrix& A = *this; size_t rowNum = std::max< size_t >( A.rowNum , B.rowNum ); @@ -348,7 +343,7 @@ SparseMatrix< T , IndexType > SparseMatrix< T , IndexType >::operator - ( const } template< class T , class IndexType > -SparseMatrix< T , IndexType > SparseMatrix< T , IndexType >::transpose( T (*TransposeFunction)( const T& ) ) const +SparseMatrix< T , IndexType , 0 > SparseMatrix< T , IndexType , 0 >::transpose( T (*TransposeFunction)( const T& ) ) const { SparseMatrix A; const SparseMatrix& At = *this; @@ -382,7 +377,7 @@ SparseMatrix< T , IndexType > SparseMatrix< T , IndexType >::transpose( T (*Tran return A; } template< class T , class IndexType > -SparseMatrix< T , IndexType > SparseMatrix< T , IndexType >::transpose( size_t aRows , T (*TransposeFunction)( const T& ) ) const +SparseMatrix< T , IndexType , 0 > SparseMatrix< T , IndexType , 0 >::transpose( size_t aRows , T (*TransposeFunction)( const T& ) ) const { SparseMatrix A; const SparseMatrix& At = *this; @@ -421,7 +416,7 @@ SparseMatrix< T , IndexType > SparseMatrix< T , IndexType >::transpose( size_t a template< class T , class IndexType > template< class A_const_iterator , class B_const_iterator > -SparseMatrix< T , IndexType > SparseMatrix< T , IndexType >::Multiply( const SparseMatrixInterface< T , A_const_iterator >& A , const SparseMatrixInterface< T , B_const_iterator >& B ) +SparseMatrix< T , IndexType , 0 > SparseMatrix< T , IndexType , 0 >::Multiply( const SparseMatrixInterface< T , A_const_iterator >& A , const SparseMatrixInterface< T , B_const_iterator >& B ) { SparseMatrix M; size_t aCols = 0 , aRows = A.rows(); @@ -458,9 +453,9 @@ SparseMatrix< T , IndexType > SparseMatrix< T , IndexType >::Multiply( const Spa } template< class T , class IndexType > template< class const_iterator > -SparseMatrix< T , IndexType > SparseMatrix< T , IndexType >::Transpose( const SparseMatrixInterface< T , const_iterator >& At , T (*TransposeFunction)( const T& ) ) +SparseMatrix< T , IndexType , 0 > SparseMatrix< T , IndexType , 0 >::Transpose( const SparseMatrixInterface< T , const_iterator >& At , T (*TransposeFunction)( const T& ) ) { - SparseMatrix< T , IndexType > A; + SparseMatrix< T , IndexType , 0 > A; size_t aRows = 0 , aCols = At.rows(); for( size_t i=0 ; iN ) aRows = iter->N+1; @@ -490,9 +485,9 @@ SparseMatrix< T , IndexType > SparseMatrix< T , IndexType >::Transpose( const Sp } template< class T , class IndexType > template< class const_iterator > -SparseMatrix< T , IndexType > SparseMatrix< T , IndexType >::Transpose( const SparseMatrixInterface< T , const_iterator >& At , size_t outRows , T (*TransposeFunction)( const T& ) ) +SparseMatrix< T , IndexType , 0 > SparseMatrix< T , IndexType , 0 >::Transpose( const SparseMatrixInterface< T , const_iterator >& At , size_t outRows , T (*TransposeFunction)( const T& ) ) { - SparseMatrix< T , IndexType > A; + SparseMatrix< T , IndexType , 0 > A; size_t _aRows = 0 , aCols = At.rows() , aRows = outRows; for( size_t i=0 ; iN ) _aRows = iter->N+1; if( _aRows>aRows ) ERROR_OUT( "Prescribed output dimension too low: %d < %zu" , aRows , _aRows ); @@ -521,3 +516,148 @@ SparseMatrix< T , IndexType > SparseMatrix< T , IndexType >::Transpose( const Sp } return true; } + +/////////////////////////////////////////// +// SparseMatrix (bounded max row size ) // +/////////////////////////////////////////// + +template< class T , class IndexType , size_t MaxRowSize > +SparseMatrix< T , IndexType , MaxRowSize >::SparseMatrix( void ) +{ + _rowSizes = NullPointer( size_t ); + _rowNum = 0; + _entries = NullPointer( MatrixEntry< T , IndexType > ); + _maxRows = 0; +} + +template< class T , class IndexType , size_t MaxRowSize > +SparseMatrix< T , IndexType , MaxRowSize >::SparseMatrix( size_t rowNum ) : SparseMatrix() +{ + resize( rowNum ); +} +template< class T , class IndexType , size_t MaxRowSize > +SparseMatrix< T , IndexType , MaxRowSize >::SparseMatrix( const SparseMatrix& M ) : SparseMatrix() +{ + resize( M._rowNum ); + for( int i=0 ; i<_rowNum ; i++ ) + { + _rowSizes[i] = M._rowSizes[i]; + for( int j=0 ; j<_rowSizes[i] ; j++ ) _entries[ i + MaxRowSize*j ] = M._rowEntries[ i + MaxRowSize*j ]; + } +} +template< class T , class IndexType , size_t MaxRowSize > +SparseMatrix< T , IndexType , MaxRowSize >::SparseMatrix( SparseMatrix&& M ) : SparseMatrix() +{ + Swap( *this , M ); +} +template< class T , class IndexType , size_t MaxRowSize > +template< class T2 , class IndexType2 > +SparseMatrix< T , IndexType , MaxRowSize >::SparseMatrix( const SparseMatrix< T2 , IndexType2 , MaxRowSize >& M ) : SparseMatrix() +{ + resize( M._rowNum ); + for( int i=0 ; i<_rowNum ; i++ ) + { + _rowSizes[i] = M._rowSizes[i]; + for( int j=0 ; j<_rowSizes[i] ; j++ ) _entries[ i + MaxRowSize*j ] = MatrixEntry< T , IndexType >( M._rowEntries[i][j].N , T( M._entries[ i + MaxRowSize*j ].Value ) ); + } +} + +template< class T , class IndexType , size_t MaxRowSize > +SparseMatrix< T , IndexType , MaxRowSize >& SparseMatrix< T , IndexType , MaxRowSize >::operator = ( SparseMatrix< T , IndexType , MaxRowSize >&& M ) +{ + Swap( *this , M ); + return *this; +} + +template< class T , class IndexType , size_t MaxRowSize > +SparseMatrix< T , IndexType , MaxRowSize >& SparseMatrix< T , IndexType , MaxRowSize >::operator = ( const SparseMatrix< T , IndexType , MaxRowSize >& M ) +{ + resize( M._rowNum ); + for( int i=0 ; i<_rowNum ; i++ ) + { + _rowSizes[i] = M._rowSizes[i]; + for( int j=0 ; j<_rowSizes[i] ; j++ ) _entries[ i + MaxRowSize*j ] = M._entries[ i + MaxRowSize*j ]; + } + return *this; +} + +template< class T , class IndexType , size_t MaxRowSize > +template< class T2 , class IndexType2 > +SparseMatrix< T , IndexType , MaxRowSize >& SparseMatrix< T , IndexType , MaxRowSize >::operator = ( const SparseMatrix< T2 , IndexType2 , MaxRowSize >& M ) +{ + resize( M._rowNum ); + for( int i=0 ; i<_rowNum ; i++ ) + { + _rowSizes[i] = M._rowSizes[i]; + for( int j=0 ; j<_rowSizes[i] ; j++ ) _entries[ i + MaxRowSize*j ] = MatrixEntry< T , IndexType >( M._entries[ i + MaxRowSize*j ].N , T( M._entries[ i + MaxRowSize*j ].Value ) ); + } + return *this; +} + +template< class T , class IndexType , size_t MaxRowSize > +template< class T2 > +void SparseMatrix< T , IndexType , MaxRowSize >::operator() ( const T2* in , T2* out ) const { Interface::multiply( in , out ); } + +template< class T , class IndexType , size_t MaxRowSize > SparseMatrix< T , IndexType , MaxRowSize >::~SparseMatrix( void ) { resize( 0 ); } + +template< class T , class IndexType , size_t MaxRowSize > +void SparseMatrix< T , IndexType , MaxRowSize >::resize( size_t rowNum ) +{ + _rowNum = rowNum; + if( !rowNum || rowNum>_maxRows ) + { + FreePointer( _rowSizes ); + FreePointer( _entries ); + + if( rowNum ) + { + _rowSizes = AllocPointer< size_t >( rowNum ) , memset( _rowSizes , 0 , sizeof(size_t)*rowNum ); + _entries = AllocPointer< MatrixEntry< T , IndexType > >( rowNum * MaxRowSize ); + _maxRows = rowNum; + } + } +} + +template< class T , class IndexType , size_t MaxRowSize > +void SparseMatrix< T , IndexType , MaxRowSize >::setRowSize( size_t row , size_t rowSize ) +{ + if( row>=_rowNum ) ERROR_OUT( "Row is out of bounds: 0 <= %d < %d" , (int)row , (int)_rowNum ); + else if( rowSize>MaxRowSize ) ERROR_OUT( "Row size larger than max row size: %d < %d" , (int)rowSize , (int)MaxRowSize ); + else _rowSizes[row] = rowSize; +} +template< class T , class IndexType , size_t MaxRowSize > +void SparseMatrix< T , IndexType , MaxRowSize >::resetRowSize( size_t row , size_t rowSize ) +{ + if( row>=_rowNum ) ERROR_OUT( "Row is out of bounds: 0 <= %d < %d" , (int)row , (int)_rowNum ); + else if( rowSize>MaxRowSize ) ERROR_OUT( "Row size larger than max row size: %d < %d" , (int)rowSize , (int)MaxRowSize ); + else _rowSizes[row] = rowSize; +} + +template< class T , class IndexType , size_t MaxRowSize > +SparseMatrix< T , IndexType , MaxRowSize >& SparseMatrix< T , IndexType , MaxRowSize >::operator *= ( T s ) +{ +#pragma omp parallel for + for( int i=0 ; i<_rowNum*MaxRowSize ; i++ ) _entries[i].Value *= s; + return *this; +} + +template< class T , class IndexType , size_t MaxRowSize > +SparseMatrix< T , IndexType , MaxRowSize >& SparseMatrix< T , IndexType , MaxRowSize >::operator /= ( T s ){ return (*this) * ( (T)1./s ); } + +template< class T , class IndexType , size_t MaxRowSize > +SparseMatrix< T , IndexType , MaxRowSize > SparseMatrix< T , IndexType , MaxRowSize >::operator * ( T s ) const +{ + SparseMatrix out = (*this); + return out *= s; +} + +template< class T , class IndexType , size_t MaxRowSize > +SparseMatrix< T , IndexType , MaxRowSize > SparseMatrix< T , IndexType , MaxRowSize >::operator / ( T s ) const { return (*this) * ( (T)1. / s ); } + +template< class T , class IndexType , size_t MaxRowSize > +Pointer( T ) SparseMatrix< T , IndexType , MaxRowSize >::operator * ( const Pointer( T ) in ) const +{ + Pointer( T ) out = AllocPointer< T >( _rowNum ); + MultiplyParallel( in , out , omp_get_num_procs() , 0 ); + return out; +}