a 2D version
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

476 lines
16 KiB

% mtimesx_build compiles mtimesx.c with BLAS libraries
%******************************************************************************
%
% MATLAB (R) is a trademark of The Mathworks (R) Corporation
%
% Function: mtimesx_build
% Filename: mtimesx_build.m
% Programmer: James Tursa
% Version: 1.40
% Date: October 4, 2010
% Copyright: (c) 2009, 2010 by James Tursa, All Rights Reserved
%
% This code uses the BSD License:
%
% Redistribution and use in source and binary forms, with or without
% modification, are permitted provided that the following conditions are
% met:
%
% * Redistributions of source code must retain the above copyright
% notice, this list of conditions and the following disclaimer.
% * Redistributions in binary form must reproduce the above copyright
% notice, this list of conditions and the following disclaimer in
% the documentation and/or other materials provided with the distribution
%
% THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
% AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
% IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
% ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
% LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
% CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
% SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
% INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
% CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
% ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
% POSSIBILITY OF SUCH DAMAGE.
%
%--
%
% mtimesx_build compiles mtimesx.c and mtimesx_RealTimesReal.c with the BLAS
% libraries libmwblas.lib (if present) or libmwlapack.lib (if libmwblas.lib
% is not present). This function basically works as follows:
%
% - Opens the current mexopts.bat file in the directory [prefdir], and
% checks to make sure that the compiler selected is cl or lcc. If it
% is not, then a warning is issued and the compilation continues with
% the assumption that the microsoft BLAS libraries will work.
%
% - Looks for the file libmwblas.lib or libmwlapack.lib files in the
% appropriate directory: [matlabroot '\extern\lib\win32\microsoft']
% or [matlabroot '\extern\lib\win32\lcc']
% or [matlabroot '\extern\lib\win64\microsoft']
% or [matlabroot '\extern\lib\win64\lcc']
%
% - Changes directory to the directory of the file mtimesx.m.
%
% - Compiles mtimesx.c (which includes mtimesx_RealTimesReal.c) along with
% either libmwblas.lib or libmwlapack.lib depending on the version of
% MATLAB. The resulting exedcutable mex file is placed in the same
% directory as the source code. The files mtimesx.m, mtimesx.c, and
% mtimesx_RealTimesReal.c must all be in the same directory.
%
% - Changes the directory back to the original directory.
%
% Change Log:
% 2009/Sep/27 --> 1.00, Initial Release
% 2010/Feb/15 --> 1.10, Fixed largearrardims typo to largeArrayDims
% 2010/Oct/04 --> 1.40, Updated support for OpenMP compiling
%
%**************************************************************************
function mtimesx_build(x)
disp(' ');
disp('... Build routine for mtimesx');
TRUE = 1;
FALSE = 0;
%\
% Check for number of inputs & outputs
%/
noopenmp = FALSE;
if( nargin == 1 )
if( isequal(upper(x),'NOOPENMP') )
noopenmp = TRUE;
else
error('Invalid input.');
end
elseif( nargin ~= 0 )
error('Too many inputs. Expected none.');
end
if( nargout ~= 0 )
error('Too many outputs. Expected none.');
end
%\
% Check for non-PC
%/
disp('... Checking for PC');
try
% ispc does not appear in MATLAB 5.3
pc = ispc ;
catch
% if ispc fails, assume we are on a Windows PC if it's not unix
pc = ~isunix ;
end
if( ~pc )
disp('Non-PC auto build is not currently supported. You will have to');
disp('manually compile the mex routine. E.g., as follows:');
disp(' ');
disp('>> blas_lib = ''the_actual_path_and_name_of_your_systems_BLAS_library''');
disp('>> mex(''-DDEFINEUNIX'',''mtimesx.c'',blas_lib)');
disp(' ');
disp('or');
disp(' ');
disp('>> mex(''-DDEFINEUNIX'',''-largeArrayDims'',''mtimesx.c'',blas_lib)');
disp(' ');
error('Unable to compile mtimesx.c');
end
%\
% Check to see that mtimesx.c source code is present
%/
disp('... Finding path of mtimesx C source code files');
try
mname = mfilename('fullpath');
catch
mname = mfilename;
end
cname = [mname(1:end-6) '.c'];
if( isempty(dir(cname)) )
disp('Cannot find the file mtimesx.c in the same directory as the');
disp('file mtimesx_build.m. Please ensure that they are in the same');
disp('directory and try again. The following file was not found:');
disp(' ');
disp(cname);
disp(' ');
error('Unable to compile mtimesx.c');
end
disp(['... Found file mtimesx.c in ' cname]);
%\
% Check to see that mtimesx_RealTimesReal.c source code is present
%/
rname = [mname(1:end-13) 'mtimesx_RealTimesReal.c'];
if( isempty(dir(rname)) )
disp('Cannot find the file mtimesx_RealTimesReal.c in the same');
disp('directory as the file mtimesx_build.m. Please ensure that');
disp('they are in the same directory and try again. The');
disp('following file was not found:');
disp(' ');
disp(rname);
disp(' ');
error('Unable to compile mtimesx.c');
end
disp(['... Found file mtimesx_RealTimesReal.c in ' rname]);
%\
% Open the current mexopts.bat file
%/
% mexopts = [prefdir '\mexopts.bat'];
mexopts = [prefdir '\mex_C_win64.xml'];
fid = fopen(mexopts);
if( fid == -1 )
error('A C/C++ compiler has not been selected with mex -setup');
end
disp(['... Opened the mexopts.bat file in ' mexopts]);
disp('... Reading the mexopts.bat file to find the compiler and options used.');
%\
% Check for the correct compiler selected.
%/
ok_cl = FALSE;
ok_lcc = FALSE;
omp_option = '';
compiler = '(unknown)';
compilername = '';
while( TRUE )
tline = fgets(fid);
if( isequal(tline,-1) )
break;
else
if( isempty(compilername) )
y = findstr(tline,'OPTS.BAT');
if( ~isempty(y) )
x = findstr(tline,'rem ');
if( ~isempty(x) )
compilername = tline(x+4:y-1);
end
end
end
x = findstr(tline,'COMPILER=lcc');
if( ~isempty(x) )
ok_lcc = TRUE;
libdir = 'lcc';
compiler = 'LCC';
disp(['... ' compiler ' is the selected compiler']);
break;
end
x = findstr(tline,'COMPILER=cl');
if( ~isempty(x) )
ok_cl = TRUE;
libdir = 'microsoft';
compiler = ['Microsoft_' compilername '_cl'];
omp_option = ' /openmp';
disp(['... ' compiler ' is the selected compiler']);
break;
end
x = findstr(tline,'COMPILER=bcc32');
if( ~isempty(x) )
ok_cl = TRUE;
libdir = 'microsoft';
compiler = ['Borland_' compilername '_bcc32'];
disp(['... ' compiler ' is the selected compiler']);
disp('... Assuming that Borland will link with Microsoft libraries');
break;
end
x = findstr(tline,'COMPILER=icl');
if( ~isempty(x) )
ok_cl = TRUE;
if( pc )
omp_option = ' -Qopenmp';
else
omp_option = ' -openmp';
end
libdir = 'microsoft';
compiler = ['Intel_' compilername '_icl'];
disp(['... ' compiler ' is the selected compiler']);
disp('... Assuming that Intel will link with Microsoft libraries');
break;
end
x = findstr(tline,'COMPILER=wc1386');
if( ~isempty(x) )
ok_cl = TRUE;
libdir = 'microsoft';
compiler = ['Watcom_' compilername '_wc1386'];
disp(['... ' compiler ' is the selected compiler']);
disp('... Assuming that Watcom will link with Microsoft libraries');
break;
end
x = findstr(tline,'COMPILER=gcc');
if( ~isempty(x) )
ok_cl = TRUE;
libdir = 'microsoft';
omp_option = ' -fopenmp';
compiler = 'GCC';
disp(['... ' compiler ' is the selected compiler']);
disp('... Assuming that GCC will link with Microsoft libraries');
break;
end
end
end
fclose(fid);
%\
% MS Visual C/C++ or lcc compiler has not been selected
%/
if( ~(ok_cl | ok_lcc) )
warning('... Supported C/C++ compiler has not been selected with mex -setup');
warning('... Assuming that Selected Compiler will link with Microsoft libraries');
warning('... Continuing at risk ...');
libdir = 'microsoft';
end
%\
% If an OpenMP supported compiler is potentially present, make sure that the
% necessary compile option is present in the mexopts.bat file on the COMPFLAGS
% line. If necessary, build a new mexopts.bat file with the correct option
% added to the COMPFLAGS line.
%/
while( TRUE )
ok_openmp = FALSE;
ok_compflags = FALSE;
xname = '';
if( isempty(omp_option) )
disp('... OpenMP compiler not detected ... you may want to check this website:');
disp(' http://openmp.org/wp/openmp-compilers/');
elseif( noopenmp )
disp(['... OpenMP compiler potentially detected, but not checking for ''' omp_option ''' compile option']);
else
disp('... OpenMP compiler potentially detected');
disp(['... Checking to see that the ''' omp_option ''' compile option is present']);
fid = fopen(mexopts);
while( TRUE )
tline = fgets(fid);
if( isequal(tline,-1) )
break;
else
x = findstr(tline,'set COMPFLAGS');
if( ~isempty(x) )
ok_compflags = TRUE;
x = findstr(tline,omp_option);
if( ~isempty(x) )
ok_openmp = TRUE;
end
break;
end
end
end
fclose(fid);
if( ~ok_compflags )
warning(['... COMPFLAGS line not found ... ''' omp_option ''' will not be added.']);
elseif( ~ok_openmp )
disp(['... The ''' omp_option ''' compile option is not present ... adding it']);
xname = [mname(1:end-6) '_mexopts.bat'];
disp(['... Creating custom options file ' xname ' with the ''' omp_option ''' option added.']);
fid = fopen(mexopts);
fidx = fopen(xname,'w');
if( fidx == -1 )
xname = '';
warning(['... Unable to create custom mexopts.bat file ... ''' omp_option ''' will not be added']);
else
while( TRUE )
tline = fgets(fid);
if( isequal(tline,-1) )
break;
else
x = findstr(tline,'set COMPFLAGS');
if( ~isempty(x) )
n = numel(tline);
e = n;
while( tline(e) < 32 )
e = e - 1;
end
tline = [tline(1:e) omp_option tline(e+1:n)];
end
fwrite(fidx,tline);
end
end
fclose(fidx);
end
fclose(fid);
end
end
%\
% Construct full file name of libmwblas.lib and libmwlapack.lib. Note that
% not all versions have both files. Earlier versions only had the lapack
% file, which contained both blas and lapack routines.
%/
comp = computer;
mext = mexext;
lc = length(comp);
lm = length(mext);
cbits = comp(max(1:lc-1):lc);
mbits = mext(max(1:lm-1):lm);
if( isequal(cbits,'64') | isequal(mbits,'64') )
compdir = 'win64';
largearraydims = '-largeArrayDims';
else
compdir = 'win32';
largearraydims = '';
end
lib_blas = [matlabroot '\extern\lib\' compdir '\' libdir '\libmwblas.lib'];
d = dir(lib_blas);
if( isempty(d) )
disp('... BLAS library file not found, so linking with the LAPACK library');
lib_blas = [matlabroot '\extern\lib\' compdir '\' libdir '\libmwlapack.lib'];
end
disp(['... Using BLAS library lib_blas = ''' lib_blas '''']);
%\
% Save old directory and change to source code directory
%/
cdold = cd;
if( length(mname) > 13 )
cd(mname(1:end-13));
end
%\
% Do the compile
%/
disp('... Now attempting to compile ...');
disp(' ');
try
if( isunix )
if( isempty(largearraydims) )
if( isempty(xname) )
disp(['mex(''-DDEFINEUNIX'',''' cname ''',lib_blas,''-DCOMPILER=' compiler ''')']);
disp(' ');
mex('-DDEFINEUNIX',cname,lib_blas,['-DCOMPILER=' compiler]);
else
disp(['mex(''-f'',''' xname ''',''-DDEFINEUNIX'',''' cname ''',lib_blas,''-DCOMPILER=' compiler ''')']);
disp(' ');
mex('-f',xname,'-DDEFINEUNIX',cname,lib_blas,['-DCOMPILER=' compiler]);
end
else
if( isempty(xname) )
disp(['mex(''-DDEFINEUNIX'',''' cname ''',''' largearraydims ''',lib_blas,''-DCOMPILER=' compiler ''')']);
disp(' ');
mex('-DDEFINEUNIX',largearraydims,cname,lib_blas,['-DCOMPILER=' compiler]);
else
disp(['mex(''-f'',''' xname ''',''-DDEFINEUNIX'',''' cname ''',''' largearraydims ''',lib_blas,''-DCOMPILER=' compiler ''')']);
disp(' ');
mex('-f',xname,'-DDEFINEUNIX',largearraydims,cname,lib_blas,['-DCOMPILER=' compiler]);
end
end
else
if( isempty(largearraydims) )
if( isempty(xname) )
disp(['mex(''' cname ''',lib_blas,''-DCOMPILER=' compiler ''')']);
disp(' ');
mex(cname,lib_blas,['-DCOMPILER=' compiler]);
else
disp(['mex(''-f'',''' xname ''',''' cname ''',lib_blas,''-DCOMPILER=' compiler ''')']);
disp(' ');
mex('-f',xname,cname,lib_blas,['-DCOMPILER=' compiler]);
end
else
if( isempty(xname) )
disp(['mex(''' cname ''',''' largearraydims ''',lib_blas,''-DCOMPILER=' compiler ''')']);
disp(' ');
mex(cname,largearraydims,lib_blas,['-DCOMPILER=' compiler]);
else
disp(['mex(''-f'',''' xname ''',''' cname ''',''' largearraydims ''',lib_blas,''-DCOMPILER=' compiler ''')']);
disp(' ');
mex('-f',xname,cname,largearraydims,lib_blas,['-DCOMPILER=' compiler]);
end
end
end
disp('... mex mtimesx.c build completed ... you may now use mtimesx.');
disp(' ');
mtimesx;
break;
catch
if( noopenmp )
cd(cdold);
disp(' ');
disp('... Well, *that* didn''t work either!');
disp(' ');
disp('The mex command failed. This may be because you have already run');
disp('mex -setup and selected a non-C compiler, such as Fortran. If this');
disp('is the case, then rerun mex -setup and select a C/C++ compiler.');
disp(' ');
error('Unable to compile mtimesx.c');
else
disp(' ');
disp('... Well, *that* didn''t work ...');
disp(' ');
if( isequal(omp_option,' /openmp') )
disp('This may be because an OpenMP compile option was added that the');
disp('compiler did not like. For example, the Standard versions of the');
disp('Microsoft C/C++ compilers do not support OpenMP, only the');
disp('Professional versions do. Attempting to compile again but this');
disp(['time will not add the ''' omp_option ''' option.'])
else
disp('This may be because an OpenMP compile option was added that the');
disp('compiler did not like. Attempting to compile again, but this time');
disp(['will not add the ''' omp_option ''' option.'])
end
disp(' ');
noopenmp = TRUE;
end
end
end
%\
% Restore old directory
%/
cd(cdold);
return
end