From cd7ea8c404f3534bc0896953fadfb9cb713909af Mon Sep 17 00:00:00 2001 From: 1a7r0ch3 Date: Mon, 17 Jun 2019 15:14:25 +0200 Subject: [PATCH 1/3] GNU Octave interface --- README.md | 10 ++--- install_octave.m | 102 +++++++++++++++++++++++++++++++++++++++++++++++ src/general.h | 28 +++++++------ 3 files changed, 123 insertions(+), 17 deletions(-) create mode 100644 install_octave.m diff --git a/README.md b/README.md index 6ba6280..59eb7c8 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ |[![Build Status](https://travis-ci.org/albarji/proxTV.svg?branch=master)](https://travis-ci.org/albarji/proxTV)|[![Build Status](https://travis-ci.org/albarji/proxTV.svg?branch=master)](https://travis-ci.org/albarji/proxTV)[(!)](#notes-on-mac-os-x)|Not supported (yet)| -**proxTV** is a toolbox implementing blazing fast implementations of Total Variation proximity operators, which form the basic building blocks for applications such as image denoising, image deconvolution, image inpainting, video denoising, or fused lasso models, to name a few. While the core algorithms are implemented in C to achieve top efficiency, Matlab and Python interfaces are provided for ease of use. +**proxTV** is a toolbox implementing blazing fast implementations of Total Variation proximity operators, which form the basic building blocks for applications such as image denoising, image deconvolution, image inpainting, video denoising, or fused lasso models, to name a few. While the core algorithms are implemented in C to achieve top efficiency, Matlab, GNU Octave and Python interfaces are provided for ease of use. Some examples of applications using **proxTV**: @@ -76,11 +76,11 @@ for direct access to all the package routines. The documentation of use of the package functions is maintained online at http://pythonhosted.org/prox_tv/. -## Matlab interface +## Matlab or GNU Octave interface ### Quick start guide -To install proxTV clone this repository and run `install` at the Matlab prompt once located at proxTV folder. If any problem arises please refer to the "Installation" subsection. +To install proxTV clone this repository and run `install` at the Matlab prompt (or `install_octave` at the Octave prompt) once located at proxTV folder. If any problem arises please refer to the "Installation" subsection. After that the TV solver can be invoked easily through the general purpose "TV" function. For instance, @@ -100,8 +100,8 @@ To install proxTV follow the steps: 1. Open Matlab. 2. Change directory to the folder where this README file is located. -3. Type: "install" -4. After compilation the message "proxTV successfully installed" will appear. If instead an error message shows up, check your mex compiler configuration (type "mex -setup"). If the error was produced by the "openmp" library, you might need to install it, or you can install proxTV with no multi-thread features by typing "install(1)". +3. Type: `install` (or `install_octave`) +4. After compilation the message "proxTV successfully installed" will appear. If instead an error message shows up, check your mex compiler configuration (type `mex -setup`). If the error was produced by the "openmp" library, you might need to install it, or you can install proxTV with no multi-thread features by typing `install(1)` (or `install_octave(1)`). 5. The install script automatically adds the relevant proxTV folders to your Matlab path. If this were to fail for some reason, you should manually add the /matlab subfolder to your Matlab path. You can do this e.g. by using the "pathtool()" utility. You may also add the /matlab/demos subfolder to try out the included demos. *Note*: this interface has only been tested under Linux. Installation might require LAPACK (http://www.netlib.org/lapack/) and BLAS (http://www.netlib.org/blas/) libraries. diff --git a/install_octave.m b/install_octave.m new file mode 100644 index 0000000..72daff3 --- /dev/null +++ b/install_octave.m @@ -0,0 +1,102 @@ +% +% install_octave(nopar) proxTV installation +% +% Compiles the required mex -v files for the proxTV library. +% +% Inputs: +% - [mode]: compilation mode +% 0: parallelization with OpenMP (default) +% 1: no parallelization +% 2: parallelization with mwlpack +% 3: debug mode +% +function install_octave(nopar) + % Check arguments. + if ~exist('nopar', 'var'), nopar=0; + else + if ~isa(nopar, 'double'), error('Input argument must be numeric'); end + end + + disp('Installing proxTV...'); + cd matlab + + %% compilation flags + [~, CXXFLAGS] = system('mkoctfile -p CXXFLAGS'); + [~, LDFLAGS] = system('mkoctfile -p LDFLAGS'); + % some versions introduces a newline character (10) + % in the output of 'system'; this must be removed + if CXXFLAGS(end)==10, CXXFLAGS = CXXFLAGS(1:end-1); end + if LDFLAGS(end)==10, LDFLAGS = LDFLAGS(1:end-1); end + CXXFLAGSorig = CXXFLAGS; + LDFLAGSorig = LDFLAGS; + + CXXFLAGS = [CXXFLAGS ' -fPIC -DOCTAVE']; + + if nopar == 0 + CXXFLAGS = [CXXFLAGS ' -O3 -fopenmp']; + LDFLAGS = [LDFLAGS ',-fopenmp']; + setenv('CXXFLAGS', CXXFLAGS); + setenv('LDFLAGS', LDFLAGS); + elseif nopar == 1 + disp('WARNING: parallelization disabled'); + CXXFLAGS = [CXXFLAGS ' -O3']; + setenv('CXXFLAGS', CXXFLAGS); + elseif nopar == 2 + disp('Installing multisrc mwlpack version'); + CXXFLAGS = [CXXFLAGS ' -O3 -fopenmp']; + LDFLAGS = [LDFLAGS ',-fopenmp']; + else + disp('WARNING: Installing in debug mode'); + CXXFLAGS = [CXXFLAGS ' -g -fopenmp']; + LDFLAGS = [LDFLAGS ',-fopenmp']; + end + + setenv('CXXFLAGS', CXXFLAGS); + setenv('LDFLAGS', LDFLAGS); + + %% Compile C modules + mex -v -c ../src/TVgenopt.cpp ../src/TVL1opt.cpp ../src/TVL1Wopt.cpp ... + ../src/TVL2opt.cpp ../src/TVLPopt.cpp ../src/TV2Dopt.cpp ... + ../src/TV2DWopt.cpp ../src/TVNDopt.cpp ../src/LPopt.cpp ... + ../src/utils.cpp ../src/condat_fast_tv.cpp ../src/johnsonRyanTV.cpp ... + ../src/TVL1opt_tautstring.cpp ../src/TVL1opt_hybridtautstring.cpp ... + ../src/TVL1opt_kolmogorov.cpp + + fprintf('\n'); + + %% Compile MEX + solvers = {'solveTV1_condat', 'solveTV1_condattautstring', ... + 'solveTV1_johnson', 'solveTV1_PN', 'solveTV1_linearizedTautString', ... + 'solveTV1_classicTautString', 'solveTV1_hybridTautString', ... + 'solveTV1_kolmogorov', 'TVL1Weighted', 'TVL1Weighted_tautString', ... + 'solveTV2_morec', 'solveTV2_PGc', 'solveTV2_morec2', 'solveTVgen', ... + 'solveTV2D_DR', 'solveTV2D_PD', 'solveTV2D_CondatChambollePock', ... + 'solveTV2D_Yang', 'solveTV2D_Kolmogorov', 'solveTV2DL1W', ... + 'solveTV3D_Yang', 'solveTVND_PDR', 'solveTVp_GPFW', 'solveTV'}; + for solver=solvers + if nopar == 0 || nopar == 1 + eval(['mex -v -lblas -llapack -lm ' solver{:} '.cpp "*.o"']); + elseif nopar == 2 + eval(['mex -v -lmwlapack -lm ' solver{:} '.cpp "*.o"']); + else + eval(['mex -v -DDEBUG -lblas -llapack -lm' solver{:} ... + '.cpp "*.o"']); + end + system(['rm -f ' solver{:} '.o']); % some versions keep the object file + end + clear *.mex + system('rm -f *.o'); + + cd .. + + % Add relevant proxTV folders to Matlab's path + % here = pwd(); + % addpath([here,'/matlab']); + % addpath([here,'/matlab/demos']); + % savepath(); + + setenv('CXXFLAGS', CXXFLAGSorig); + setenv('LDFLAGS', LDFLAGSorig); + + disp('proxTV successfully installed.'); +end diff --git a/src/general.h b/src/general.h index 96d7d98..f6287d6 100644 --- a/src/general.h +++ b/src/general.h @@ -16,20 +16,24 @@ #include /* Mex and LAPACK includes */ +#ifdef OCTAVE + #include "mex.h" + #define NOMATLAB +#endif #ifdef NOMATLAB -#undef lapack_int -#define lapack_int int -extern "C" { - void dpttrs_(lapack_int* n, lapack_int* nrhs, const double* d, const double* e, double* b, lapack_int* ldb, - lapack_int *info ); - void dpttrf_( lapack_int* n, double* d, double* e, lapack_int *info ); -} -inline double mxGetInf() { return INFINITY; } + #undef lapack_int + #define lapack_int int + extern "C" { + void dpttrs_(lapack_int* n, lapack_int* nrhs, const double* d, const double* e, double* b, lapack_int* ldb, + lapack_int *info ); + void dpttrf_( lapack_int* n, double* d, double* e, lapack_int *info ); + } + inline double mxGetInf() { return INFINITY; } #else -#include "mex.h" -#include "lapack.h" -#include "matrix.h" -#define lapack_int ptrdiff_t + #include "mex.h" + #include "lapack.h" + #include "matrix.h" + #define lapack_int ptrdiff_t #endif /* Uncomment to print debug messages to a debug file */ From 7d3f3fc75e2a5ca62fecd7e7ebff313c15fa0476 Mon Sep 17 00:00:00 2001 From: 1a7r0ch3 Date: Tue, 9 Jul 2019 00:19:13 +0200 Subject: [PATCH 2/3] -z muldefs for mul. def. mexFuntion with octave<=4 --- install_octave.m | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/install_octave.m b/install_octave.m index 72daff3..1f52743 100644 --- a/install_octave.m +++ b/install_octave.m @@ -30,7 +30,11 @@ function install_octave(nopar) CXXFLAGSorig = CXXFLAGS; LDFLAGSorig = LDFLAGS; - CXXFLAGS = [CXXFLAGS ' -fPIC -DOCTAVE']; + % CXXFLAGS = [CXXFLAGS ' -fPIC -DOCTAVE']; + % some octave versions keep intermediate object files; these must be + % destroyed to avoid multiple definitions of mexFunction() + % -z muldefs might still be needed in some versions + CXXFLAGS = [CXXFLAGS ' -fPIC -DOCTAVE -z muldefs']; if nopar == 0 CXXFLAGS = [CXXFLAGS ' -O3 -fopenmp']; @@ -82,7 +86,10 @@ function install_octave(nopar) eval(['mex -v -DDEBUG -lblas -llapack -lm' solver{:} ... '.cpp "*.o"']); end - system(['rm -f ' solver{:} '.o']); % some versions keep the object file + % some octave versions keep the object files; these must be destroyed + % here to avoid multiple definitions of mexFunction() + % -z muldefs might still be needed in some versions + system(['rm -f ' solver{:} '.o']); end clear *.mex system('rm -f *.o'); From 932130d6844ed01017ad555c9b65dd7231805711 Mon Sep 17 00:00:00 2001 From: 1a7r0ch3 Date: Wed, 10 Jul 2019 00:00:14 +0200 Subject: [PATCH 3/3] explicit dependency list for octave compilation --- install_octave.m | 32 +++++++++++++++----------------- 1 file changed, 15 insertions(+), 17 deletions(-) diff --git a/install_octave.m b/install_octave.m index 1f52743..295e549 100644 --- a/install_octave.m +++ b/install_octave.m @@ -30,11 +30,7 @@ function install_octave(nopar) CXXFLAGSorig = CXXFLAGS; LDFLAGSorig = LDFLAGS; - % CXXFLAGS = [CXXFLAGS ' -fPIC -DOCTAVE']; - % some octave versions keep intermediate object files; these must be - % destroyed to avoid multiple definitions of mexFunction() - % -z muldefs might still be needed in some versions - CXXFLAGS = [CXXFLAGS ' -fPIC -DOCTAVE -z muldefs']; + CXXFLAGS = [CXXFLAGS ' -fPIC -DOCTAVE']; if nopar == 0 CXXFLAGS = [CXXFLAGS ' -O3 -fopenmp']; @@ -59,12 +55,15 @@ function install_octave(nopar) setenv('LDFLAGS', LDFLAGS); %% Compile C modules - mex -v -c ../src/TVgenopt.cpp ../src/TVL1opt.cpp ../src/TVL1Wopt.cpp ... - ../src/TVL2opt.cpp ../src/TVLPopt.cpp ../src/TV2Dopt.cpp ... - ../src/TV2DWopt.cpp ../src/TVNDopt.cpp ../src/LPopt.cpp ... - ../src/utils.cpp ../src/condat_fast_tv.cpp ../src/johnsonRyanTV.cpp ... - ../src/TVL1opt_tautstring.cpp ../src/TVL1opt_hybridtautstring.cpp ... - ../src/TVL1opt_kolmogorov.cpp + deps = {'TVgenopt', 'TVL1opt', 'TVL1Wopt', 'TVL2opt', 'TVLPopt', ... + 'TV2Dopt', 'TV2DWopt', 'TVNDopt', 'LPopt', 'utils', ... + 'condat_fast_tv', 'johnsonRyanTV', 'TVL1opt_tautstring', ... + 'TVL1opt_hybridtautstring', 'TVL1opt_kolmogorov'}; + deps_obj = ''; + for dep=deps + eval(['mex -v -c ../src/' dep{:} '.cpp']); % compile dependency + deps_obj = [deps_obj ' ' dep{:} '.o']; % create list of object files + end fprintf('\n'); @@ -79,20 +78,19 @@ function install_octave(nopar) 'solveTV3D_Yang', 'solveTVND_PDR', 'solveTVp_GPFW', 'solveTV'}; for solver=solvers if nopar == 0 || nopar == 1 - eval(['mex -v -lblas -llapack -lm ' solver{:} '.cpp "*.o"']); + eval(['mex -v -lblas -llapack -lm ' solver{:} '.cpp ' deps_obj]); elseif nopar == 2 - eval(['mex -v -lmwlapack -lm ' solver{:} '.cpp "*.o"']); + eval(['mex -v -lmwlapack -lm ' solver{:} '.cpp ' deps_obj]); else eval(['mex -v -DDEBUG -lblas -llapack -lm' solver{:} ... - '.cpp "*.o"']); + '.cpp ' deps_obj]); end % some octave versions keep the object files; these must be destroyed % here to avoid multiple definitions of mexFunction() - % -z muldefs might still be needed in some versions system(['rm -f ' solver{:} '.o']); end - clear *.mex - system('rm -f *.o'); + clear *.mex % update mex function in octave workspace + system('rm -f *.o'); % remove dependencies object files cd ..