1function spqr_make (opt1) 2%SPQR_MAKE compiles the SuiteSparseQR mexFunctions 3% 4% Example: 5% spqr_make 6% 7% SuiteSparseQR relies on CHOLMOD, AMD, and COLAMD, and optionally CCOLAMD, 8% CAMD, and METIS. Next, type 9% 10% spqr_make 11% 12% in the MATLAB command window. If METIS is not present in ../../metis-5.1.0, 13% then it is not used. 14% 15% To compile using Intel's Threading Building Blocks (TBB) use: 16% 17% spqr_make ('tbb') 18% 19% TBB parallelism is not the default, since it conflicts with the multithreaded 20% BLAS (the Intel MKL are OpenMP based, for example). This may change in 21% future versions. 22% 23% You must type the spqr_make command while in the SuiteSparseQR/MATLAB 24% directory. 25% 26% See also spqr, spqr_solve, spqr_qmult, qr, mldivide 27 28% Copyright 2008, Timothy A. Davis, http://www.suitesparse.com 29 30details = 0 ; % 1 if details of each command are to be printed, 0 if not 31 32v = version ; 33try 34 % ispc does not appear in MATLAB 5.3 35 pc = ispc ; 36 mac = ismac ; 37catch %#ok 38 % if ispc fails, assume we are on a Windows PC if it's not unix 39 pc = ~isunix ; 40 mac = 0 ; 41end 42 43flags = '' ; 44is64 = (~isempty (strfind (computer, '64'))) ; 45if (is64) 46 % 64-bit MATLAB 47 flags = '-largeArrayDims' ; 48end 49 50% MATLAB 8.3.0 now has a -silent option to keep 'mex' from burbling too much 51if (~verLessThan ('matlab', '8.3.0')) 52 flags = ['-silent ' flags] ; 53end 54 55include = '-DNMATRIXOPS -DNMODIFY -I. -I../../AMD/Include -I../../COLAMD/Include -I../../CHOLMOD/Include -I../Include -I../../SuiteSparse_config' ; 56 57% Determine if METIS is available 58metis_path = '../../metis-5.1.0' ; 59have_metis = exist (metis_path, 'dir') ; 60 61% Determine if TBB is to be used 62if (nargin < 1) 63 tbb = 0 ; 64elseif (nargin < 2) 65 tbb = strcmp (opt1, 'tbb') ; 66end 67 68% fix the METIS 4.0.1 rename.h file 69if (have_metis) 70 fprintf ('Compiling SuiteSparseQR with METIS for MATLAB Version %s\n', v) ; 71 include = [include ' -I' metis_path '/include'] ; 72 include = [include ' -I' metis_path '/GKlib'] ; 73 include = [include ' -I' metis_path '/libmetis'] ; 74 include = [include ' -I../../CCOLAMD/Include -I../../CAMD/Include' ] ; 75else 76 fprintf ('Compiling SuiteSparseQR without METIS on MATLAB Version %s\n', v); 77 include = ['-DNPARTITION ' include ] ; 78end 79 80%------------------------------------------------------------------------------- 81% BLAS option 82%------------------------------------------------------------------------------- 83 84% This is exceedingly ugly. The MATLAB mex command needs to be told where to 85% find the LAPACK and BLAS libraries, which is a real portability nightmare. 86% The correct option is highly variable and depends on the MATLAB version. 87 88if (pc) 89 if (verLessThan ('matlab', '6.5')) 90 % MATLAB 6.1 and earlier: use the version supplied in CHOLMOD 91 lib = '../../CHOLMOD/MATLAB/lcc_lib/libmwlapack.lib' ; 92 elseif (verLessThan ('matlab', '7.5')) 93 % use the built-in LAPACK lib (which includes the BLAS) 94 lib = 'libmwlapack.lib' ; 95 elseif (verLessThan ('matlab', '9.5')) 96 lib = 'libmwlapack.lib libmwblas.lib' ; 97 else 98 lib = '-lmwlapack -lmwblas' ; 99 end 100else 101 if (verLessThan ('matlab', '7.5')) 102 % MATLAB 7.5 and earlier, use the LAPACK lib (including the BLAS) 103 lib = '-lmwlapack' ; 104 else 105 % MATLAB 7.6 requires the -lmwblas option; earlier versions do not 106 lib = '-lmwlapack -lmwblas' ; 107 end 108end 109 110if (is64 && ~verLessThan ('matlab', '7.8')) 111 % versions 7.8 and later on 64-bit platforms use a 64-bit BLAS 112 fprintf ('with 64-bit BLAS\n') ; 113 flags = [flags ' -DBLAS64'] ; 114end 115 116%------------------------------------------------------------------------------- 117% GPU option 118%------------------------------------------------------------------------------- 119 120% GPU not yet supported for the spqr MATLAB mexFunction 121% flags = [flags ' -DGPU_BLAS'] ; 122 123%------------------------------------------------------------------------------- 124% TBB option 125%------------------------------------------------------------------------------- 126 127% You should install TBB properly so that mex can find the library files and 128% include files, but you can also modify the tbb_lib_path and tbb_include_path 129% strings below to if you need to specify the path to your own installation of 130% TBB. 131 132% vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv 133% >>>>>>>>>>>>>>>>>>>>> EDIT THE tbb_path BELOW AS NEEDED <<<<<<<<<<<<<<<<<<<<<< 134if (pc) 135 % For Windows, with TBB installed in C:\TBB. Edit this line as needed: 136 tbb_path = 'C:\TBB\tbb21_009oss' ; 137else 138 % For Linux, edit this line as needed (not needed if already in /usr/lib): 139 tbb_path = '' ; 140end 141% ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 142 143% You should not have to edit the lines below. 144if (pc) 145 if (is64) 146 tbb_lib_path = [tbb_path '\ia32\vc9\lib\'] ; 147 else 148 tbb_lib_path = [tbb_path '\em64t\vc9\lib\'] ; 149 end 150 tbb_include_path = [tbb_path '\include\'] ; 151else 152 % For Linux, with TBB might be already installed in /usr/lib 153 if (exist ('/usr/lib/libtbb.so', 'file')) 154 % do not edit these lines 155 tbb_path = '' ; 156 tbb_lib_path = '' ; 157 tbb_include_path = '' ; 158 else 159 if (is64) 160 tbb_lib_path = '/em64t/cc4.1.0_libc2.4_kernel2.6.16.21/lib' ; 161 else 162 tbb_lib_path = '/ia32/cc4.1.0_libc2.4_kernel2.6.16.21/lib' ; 163 end 164 tbb_lib_path = [tbb_path tbb_lib_path] ; 165 tbb_include_path = [tbb_path '/include/'] ; 166 end 167end 168 169if (tbb) 170 fprintf ('Compiling with Intel TBB parallelism\n') ; 171 lib = [lib ' -L' tbb_lib_path ' -ltbb'] ; 172 include = [include ' -I' tbb_include_path ' -DHAVE_TBB' ] ; 173end 174 175if (~(pc || mac)) 176 % for POSIX timing routine 177 lib = [lib ' -lrt'] ; 178end 179 180%------------------------------------------------------------------------------- 181% ready to compile ... 182%------------------------------------------------------------------------------- 183 184config_src = { '../../SuiteSparse_config/SuiteSparse_config' } ; 185 186amd_c_src = { ... 187 '../../AMD/Source/amd_1', ... 188 '../../AMD/Source/amd_2', ... 189 '../../AMD/Source/amd_aat', ... 190 '../../AMD/Source/amd_control', ... 191 '../../AMD/Source/amd_defaults', ... 192 '../../AMD/Source/amd_dump', ... 193 '../../AMD/Source/amd_global', ... 194 '../../AMD/Source/amd_info', ... 195 '../../AMD/Source/amd_order', ... 196 '../../AMD/Source/amd_postorder', ... 197 '../../AMD/Source/amd_post_tree', ... 198 '../../AMD/Source/amd_preprocess', ... 199 '../../AMD/Source/amd_valid' } ; 200 201colamd_c_src = { 202 '../../COLAMD/Source/colamd' } ; 203 204% CAMD and CCOLAMD are not needed if we don't have METIS 205camd_c_src = { ... 206 '../../CAMD/Source/camd_1', ... 207 '../../CAMD/Source/camd_2', ... 208 '../../CAMD/Source/camd_aat', ... 209 '../../CAMD/Source/camd_control', ... 210 '../../CAMD/Source/camd_defaults', ... 211 '../../CAMD/Source/camd_dump', ... 212 '../../CAMD/Source/camd_global', ... 213 '../../CAMD/Source/camd_info', ... 214 '../../CAMD/Source/camd_order', ... 215 '../../CAMD/Source/camd_postorder', ... 216 '../../CAMD/Source/camd_preprocess', ... 217 '../../CAMD/Source/camd_valid' } ; 218 219ccolamd_c_src = { 220 '../../CCOLAMD/Source/ccolamd' } ; 221 222if (have_metis) 223 224 metis_c_src = { 225 'GKlib/b64', ... 226 'GKlib/blas', ... 227 'GKlib/csr', ... 228 'GKlib/error', ... 229 'GKlib/evaluate', ... 230 'GKlib/fkvkselect', ... 231 'GKlib/fs', ... 232 'GKlib/getopt', ... 233 'GKlib/gkregex', ... 234 'GKlib/graph', ... 235 'GKlib/htable', ... 236 'GKlib/io', ... 237 'GKlib/itemsets', ... 238 'GKlib/mcore', ... 239 'GKlib/memory', ... 240 'GKlib/omp', ... 241 'GKlib/pdb', ... 242 'GKlib/pqueue', ... 243 'GKlib/random', ... 244 'GKlib/rw', ... 245 'GKlib/seq', ... 246 'GKlib/sort', ... 247 'GKlib/string', ... 248 'GKlib/timers', ... 249 'GKlib/tokenizer', ... 250 'GKlib/util', ... 251 'libmetis/auxapi', ... 252 'libmetis/balance', ... 253 'libmetis/bucketsort', ... 254 'libmetis/checkgraph', ... 255 'libmetis/coarsen', ... 256 'libmetis/compress', ... 257 'libmetis/contig', ... 258 'libmetis/debug', ... 259 'libmetis/fm', ... 260 'libmetis/fortran', ... 261 'libmetis/frename', ... 262 'libmetis/gklib', ... 263 'libmetis/graph', ... 264 'libmetis/initpart', ... 265 'libmetis/kmetis', ... 266 'libmetis/kwayfm', ... 267 'libmetis/kwayrefine', ... 268 'libmetis/mcutil', ... 269 'libmetis/mesh', ... 270 'libmetis/meshpart', ... 271 'libmetis/minconn', ... 272 'libmetis/mincover', ... 273 'libmetis/mmd', ... 274 'libmetis/ometis', ... 275 'libmetis/options', ... 276 'libmetis/parmetis', ... 277 'libmetis/pmetis', ... 278 'libmetis/refine', ... 279 'libmetis/separator', ... 280 'libmetis/sfm', ... 281 'libmetis/srefine', ... 282 'libmetis/stat', ... 283 'libmetis/timing', ... 284 'libmetis/util', ... 285 'libmetis/wspace', ... 286 } ; 287 288 for i = 1:length (metis_c_src) 289 metis_c_src {i} = [metis_path '/' metis_c_src{i}] ; 290 end 291end 292 293cholmod_c_src = { 294 '../../CHOLMOD/Core/cholmod_aat', ... 295 '../../CHOLMOD/Core/cholmod_add', ... 296 '../../CHOLMOD/Core/cholmod_band', ... 297 '../../CHOLMOD/Core/cholmod_change_factor', ... 298 '../../CHOLMOD/Core/cholmod_common', ... 299 '../../CHOLMOD/Core/cholmod_complex', ... 300 '../../CHOLMOD/Core/cholmod_copy', ... 301 '../../CHOLMOD/Core/cholmod_dense', ... 302 '../../CHOLMOD/Core/cholmod_error', ... 303 '../../CHOLMOD/Core/cholmod_factor', ... 304 '../../CHOLMOD/Core/cholmod_memory', ... 305 '../../CHOLMOD/Core/cholmod_sparse', ... 306 '../../CHOLMOD/Core/cholmod_transpose', ... 307 '../../CHOLMOD/Core/cholmod_triplet', ... 308 '../../CHOLMOD/Check/cholmod_check', ... 309 '../../CHOLMOD/Check/cholmod_read', ... 310 '../../CHOLMOD/Check/cholmod_write', ... 311 '../../CHOLMOD/Cholesky/cholmod_amd', ... 312 '../../CHOLMOD/Cholesky/cholmod_analyze', ... 313 '../../CHOLMOD/Cholesky/cholmod_colamd', ... 314 '../../CHOLMOD/Cholesky/cholmod_etree', ... 315 '../../CHOLMOD/Cholesky/cholmod_factorize', ... 316 '../../CHOLMOD/Cholesky/cholmod_postorder', ... 317 '../../CHOLMOD/Cholesky/cholmod_rcond', ... 318 '../../CHOLMOD/Cholesky/cholmod_resymbol', ... 319 '../../CHOLMOD/Cholesky/cholmod_rowcolcounts', ... 320 '../../CHOLMOD/Cholesky/cholmod_rowfac', ... 321 '../../CHOLMOD/Cholesky/cholmod_solve', ... 322 '../../CHOLMOD/Cholesky/cholmod_spsolve', ... 323 '../../CHOLMOD/Supernodal/cholmod_super_numeric', ... 324 '../../CHOLMOD/Supernodal/cholmod_super_solve', ... 325 '../../CHOLMOD/Supernodal/cholmod_super_symbolic' } ; 326 327cholmod_c_partition_src = { 328 '../../CHOLMOD/Partition/cholmod_ccolamd', ... 329 '../../CHOLMOD/Partition/cholmod_csymamd', ... 330 '../../CHOLMOD/Partition/cholmod_camd', ... 331 '../../CHOLMOD/Partition/cholmod_metis', ... 332 '../../CHOLMOD/Partition/cholmod_nesdis' } ; 333 334% SuiteSparseQR does not need the MatrixOps or Modify modules of CHOLMOD 335% cholmod_unused = { 336% '../../CHOLMOD/MatrixOps/cholmod_drop', ... 337% '../../CHOLMOD/MatrixOps/cholmod_horzcat', ... 338% '../../CHOLMOD/MatrixOps/cholmod_norm', ... 339% '../../CHOLMOD/MatrixOps/cholmod_scale', ... 340% '../../CHOLMOD/MatrixOps/cholmod_sdmult', ... 341% '../../CHOLMOD/MatrixOps/cholmod_ssmult', ... 342% '../../CHOLMOD/MatrixOps/cholmod_submatrix', ... 343% '../../CHOLMOD/MatrixOps/cholmod_vertcat', ... 344% '../../CHOLMOD/MatrixOps/cholmod_symmetry', ... 345% '../../CHOLMOD/Modify/cholmod_rowadd', ... 346% '../../CHOLMOD/Modify/cholmod_rowdel', ... 347% '../../CHOLMOD/Modify/cholmod_updown' } ; 348 349% SuiteSparseQR source code, and mex support file 350spqr_cpp_src = { 351 '../Source/spqr_parallel', ... 352 '../Source/spqr_1colamd', ... 353 '../Source/spqr_1factor', ... 354 '../Source/spqr_1fixed', ... 355 '../Source/spqr_analyze', ... 356 '../Source/spqr_append', ... 357 '../Source/spqr_assemble', ... 358 '../Source/spqr_cpack', ... 359 '../Source/spqr_csize', ... 360 '../Source/spqr_cumsum', ... 361 '../Source/spqr_debug', ... 362 '../Source/spqr_factorize', ... 363 '../Source/spqr_fcsize', ... 364 '../Source/spqr_freefac', ... 365 '../Source/spqr_freenum', ... 366 '../Source/spqr_freesym', ... 367 '../Source/spqr_front', ... 368 '../Source/spqr_fsize', ... 369 '../Source/spqr_happly', ... 370 '../Source/spqr_happly_work', ... 371 '../Source/spqr_hpinv', ... 372 '../Source/spqr_kernel', ... 373 '../Source/spqr_larftb', ... 374 '../Source/spqr_panel', ... 375 '../Source/spqr_rconvert', ... 376 '../Source/spqr_rcount', ... 377 '../Source/spqr_rhpack', ... 378 '../Source/spqr_rmap', ... 379 '../Source/spqr_rsolve', ... 380 '../Source/spqr_shift', ... 381 '../Source/spqr_stranspose1', ... 382 '../Source/spqr_stranspose2', ... 383 '../Source/spqr_trapezoidal', ... 384 '../Source/spqr_type', ... 385 '../Source/spqr_tol', ... 386 '../Source/spqr_maxcolnorm', ... 387 '../Source/SuiteSparseQR_qmult', ... 388 '../Source/SuiteSparseQR', ... 389 '../Source/SuiteSparseQR_expert', ... 390 '../MATLAB/spqr_mx' } ; 391 392% SuiteSparse C source code, for MATLAB error handling 393spqr_c_mx_src = { '../MATLAB/spqr_mx_error' } ; 394 395% SuiteSparseQR mexFunctions 396spqr_mex_cpp_src = { 'spqr', 'spqr_qmult', 'spqr_solve', 'spqr_singletons' } ; 397 398if (pc) 399 % Windows does not have drand48 and srand48, required by METIS. Use 400 % drand48 and srand48 in CHOLMOD/MATLAB/Windows/rand48.c instead. 401 % Also provide Windows with an empty <strings.h> include file. 402 obj_extension = '.obj' ; 403 cholmod_c_src = [cholmod_c_src {'../../CHOLMOD/MATLAB/Windows/rand48'}] ; 404 include = [include ' -I../../CHOLMOD/MATLAB/Windows'] ; 405else 406 obj_extension = '.o' ; 407end 408 409% compile each library source file 410obj = '' ; 411 412c_source = [config_src amd_c_src colamd_c_src cholmod_c_src spqr_c_mx_src ] ; 413if (have_metis) 414 c_source = [c_source cholmod_c_partition_src ccolamd_c_src ] ; 415 c_source = [c_source camd_c_src metis_c_src] ; 416end 417 418cpp_source = spqr_cpp_src ; 419 420kk = 0 ; 421 422for f = cpp_source 423 ff = f {1} ; 424 slash = strfind (ff, '/') ; 425 if (isempty (slash)) 426 slash = 1 ; 427 else 428 slash = slash (end) + 1 ; 429 end 430 o = ff (slash:end) ; 431 obj = [obj ' ' o obj_extension] ; %#ok 432 s = sprintf ('mex %s -O %s -c %s.cpp', flags, include, ff) ; 433 kk = do_cmd (s, kk, details) ; 434end 435 436for f = c_source 437 ff = f {1} ; 438 if (isequal (ff, [metis_path '/GKlib/util'])) 439 % special case, since a file with the same name also exists in libmetis 440 copyfile ([ff '.c'], 'GKlib_util.c', 'f') ; 441 ff = 'GKlib_util' ; 442 o = 'GKlib_util' ; 443 elseif (isequal (ff, [metis_path '/GKlib/graph'])) 444 % special case, since a file with the same name also exist in libmetis 445 copyfile ([ff '.c'], 'GKlib_graph.c', 'f') ; 446 ff = 'GKlib_graph' ; 447 o = 'GKlib_graph' ; 448 else 449 slash = strfind (ff, '/') ; 450 if (isempty (slash)) 451 slash = 1 ; 452 else 453 slash = slash (end) + 1 ; 454 end 455 o = ff (slash:end) ; 456 end 457 % fprintf ('%s\n', o) ; 458 o = [o obj_extension] ; 459 obj = [obj ' ' o] ; %#ok 460 s = sprintf ('mex %s -DDLONG -O %s -c %s.c', flags, include, ff) ; 461 kk = do_cmd (s, kk, details) ; 462end 463 464 465% compile each mexFunction 466for f = spqr_mex_cpp_src 467 s = sprintf ('mex %s -O %s %s.cpp', flags, include, f{1}) ; 468 s = [s obj ' ' lib] ; %#ok 469 kk = do_cmd (s, kk, details) ; 470end 471 472% clean up 473s = ['delete ' obj] ; 474status = warning ('off', 'MATLAB:DELETE:FileNotFound') ; 475delete rename.h 476warning (status) ; 477do_cmd (s, kk, details) ; 478fprintf ('\nSuiteSparseQR successfully compiled\n') ; 479 480% remove the renamed METIS files, if they exist 481if (exist ('GKlib_util.c', 'file')) 482 delete ('GKlib_util.c') ; 483end 484if (exist ('GKlib_graph.c', 'file')) 485 delete ('GKlib_graph.c') ; 486end 487 488%------------------------------------------------------------------------------- 489function kk = do_cmd (s, kk, details) 490%DO_CMD evaluate a command, and either print it or print a "." 491if (details) 492 fprintf ('%s\n', s) ; 493else 494 if (mod (kk, 60) == 0) 495 fprintf ('\n') ; 496 end 497 kk = kk + 1 ; 498 fprintf ('.') ; 499end 500eval (s) ; 501 502