


HAVE_FCN Test for optional functionality / version info.
TORF = HAVE_FCN(TAG)
TORF = HAVE_FCN(TAG, TOGGLE)
VER_STR = HAVE_FCN(TAG, 'vstr')
VER_NUM = HAVE_FCN(TAG, 'vnum')
DATE = HAVE_FCN(TAG, 'date')
INFO = HAVE_FCN(TAG, 'all')
Returns availability, version and release information for optional
MATPOWER functionality. All information is cached, and the cached values
returned on subsequent calls. If the functionality exists, an attempt is
made to determine the release date and version number. The second
argument defines which value is returned, as follows:
<none> 1 = optional functionality is available, 0 = not available
'vstr' version number as a string (e.g. '3.11.4')
'vnum' version number as numeric value (e.g. 3.011004)
'date' release date as a string (e.g. '20-Jan-2015')
'all' struct with fields named 'av' (for 'availability'), 'vstr',
'vnum' and 'date', and values corresponding to the above,
respectively.
For functionality that is not available, all calls with a string-valued
second argument will return an empty value.
Alternatively, the optional functionality specified by TAG can be toggled
OFF or ON by calling HAVE_FCN with a numeric second argument TOGGLE with
one of the following values:
0 - turn OFF the optional functionality
1 - turn ON the optional functionality (if available)
-1 - toggle the ON/OFF state of the optional functionality
Possible values for input TAG and their meanings:
bpmpd - BP, BPMPD interior point solver
clp - CLP, LP/QP solver(http://www.coin-or.org/projects/Clp.xml)
opti_clp - version of CLP distributed with OPTI Toolbox
(http://www.i2c2.aut.ac.nz/Wiki/OPTI/)
cplex - CPLEX, IBM ILOG CPLEX Optimizer
fmincon - FMINCON, solver from Optimization Toolbox 2.x +
fmincon_ipm - FMINCON with Interior Point solver, from Opt Tbx 4.x +
glpk - GLPK, GNU Linear Programming Kit
gurobi - GUROBI, Gurobi solver (http://www.gurobi.com/), 5.x +
intlinprog - INTLINPROG, MILP solver from Optimization
Toolbox 7.0 (R2014a)+
ipopt - IPOPT, NLP solver
(http://www.coin-or.org/projects/Ipopt.xml)
linprog - LINPROG, LP solver from Optimization Toolbox 2.x +
linprog_ds - LINPROG with dual-simplex solver
from Optimization Toolbox 7.1 (R2014b) +
knitro - KNITRO, NLP solver (http://www.ziena.com/)
knitromatlab - KNITRO, version 9.0.0+
ktrlink - KNITRO, version < 9.0.0 (requires Opt Tbx)
matlab - code is running under Matlab, as opposed to Octave
minopf - MINOPF, MINOPF, MINOS-based OPF solver
mosek - MOSEK, LP/QP solver (http://www.mosek.com/)
optimoptions - OPTIMOPTIONS, option setting funciton for Optim Tbx 6.3+
pardiso - PARDISO, Parallel Sparse Direct and Linear Solver
(http://www.pardiso-project.org)
quadprog - QUADPROG, QP solver from Optimization Toolbox 2.x +
quadprog_ls - QUADPROG with large-scale interior point convex solver
from Optimization Toolbox 6.x +
pdipmopf - PDIPMOPF, primal-dual interior point method OPF solver
scpdipmopf - SCPDIPMOPF, step-controlled PDIPM OPF solver
smartmarket - RUNMARKET and friends, for running an auction
tralmopf - TRALMOPF, trust region based augmented Langrangian
OPF solver
octave - code is running under Octave, as opposed to MATLAB
sdp_pf - SDP_PF applications of semi-definite programming
relaxation of power flow equations
yalmip - YALMIP SDP modeling platform
sedumi - SeDuMi SDP solver
sdpt3 - SDPT3 SDP solver
Examples:
if have_fcn('minopf')
results = runopf(mpc, mpoption('opf.ac.solver', 'MINOPF'));
end
Optional functionality can also be toggled OFF and ON by calling HAVE_FCN
with the following syntax,
TORF = HAVE_FCN(TAG, TOGGLE)
where TOGGLE takes a numeric value as follows:


0001 function rv = have_fcn(tag, rtype) 0002 %HAVE_FCN Test for optional functionality / version info. 0003 % TORF = HAVE_FCN(TAG) 0004 % TORF = HAVE_FCN(TAG, TOGGLE) 0005 % VER_STR = HAVE_FCN(TAG, 'vstr') 0006 % VER_NUM = HAVE_FCN(TAG, 'vnum') 0007 % DATE = HAVE_FCN(TAG, 'date') 0008 % INFO = HAVE_FCN(TAG, 'all') 0009 % 0010 % Returns availability, version and release information for optional 0011 % MATPOWER functionality. All information is cached, and the cached values 0012 % returned on subsequent calls. If the functionality exists, an attempt is 0013 % made to determine the release date and version number. The second 0014 % argument defines which value is returned, as follows: 0015 % <none> 1 = optional functionality is available, 0 = not available 0016 % 'vstr' version number as a string (e.g. '3.11.4') 0017 % 'vnum' version number as numeric value (e.g. 3.011004) 0018 % 'date' release date as a string (e.g. '20-Jan-2015') 0019 % 'all' struct with fields named 'av' (for 'availability'), 'vstr', 0020 % 'vnum' and 'date', and values corresponding to the above, 0021 % respectively. 0022 % 0023 % For functionality that is not available, all calls with a string-valued 0024 % second argument will return an empty value. 0025 % 0026 % Alternatively, the optional functionality specified by TAG can be toggled 0027 % OFF or ON by calling HAVE_FCN with a numeric second argument TOGGLE with 0028 % one of the following values: 0029 % 0 - turn OFF the optional functionality 0030 % 1 - turn ON the optional functionality (if available) 0031 % -1 - toggle the ON/OFF state of the optional functionality 0032 % 0033 % Possible values for input TAG and their meanings: 0034 % bpmpd - BP, BPMPD interior point solver 0035 % clp - CLP, LP/QP solver(http://www.coin-or.org/projects/Clp.xml) 0036 % opti_clp - version of CLP distributed with OPTI Toolbox 0037 % (http://www.i2c2.aut.ac.nz/Wiki/OPTI/) 0038 % cplex - CPLEX, IBM ILOG CPLEX Optimizer 0039 % fmincon - FMINCON, solver from Optimization Toolbox 2.x + 0040 % fmincon_ipm - FMINCON with Interior Point solver, from Opt Tbx 4.x + 0041 % glpk - GLPK, GNU Linear Programming Kit 0042 % gurobi - GUROBI, Gurobi solver (http://www.gurobi.com/), 5.x + 0043 % intlinprog - INTLINPROG, MILP solver from Optimization 0044 % Toolbox 7.0 (R2014a)+ 0045 % ipopt - IPOPT, NLP solver 0046 % (http://www.coin-or.org/projects/Ipopt.xml) 0047 % linprog - LINPROG, LP solver from Optimization Toolbox 2.x + 0048 % linprog_ds - LINPROG with dual-simplex solver 0049 % from Optimization Toolbox 7.1 (R2014b) + 0050 % knitro - KNITRO, NLP solver (http://www.ziena.com/) 0051 % knitromatlab - KNITRO, version 9.0.0+ 0052 % ktrlink - KNITRO, version < 9.0.0 (requires Opt Tbx) 0053 % matlab - code is running under Matlab, as opposed to Octave 0054 % minopf - MINOPF, MINOPF, MINOS-based OPF solver 0055 % mosek - MOSEK, LP/QP solver (http://www.mosek.com/) 0056 % optimoptions - OPTIMOPTIONS, option setting funciton for Optim Tbx 6.3+ 0057 % pardiso - PARDISO, Parallel Sparse Direct and Linear Solver 0058 % (http://www.pardiso-project.org) 0059 % quadprog - QUADPROG, QP solver from Optimization Toolbox 2.x + 0060 % quadprog_ls - QUADPROG with large-scale interior point convex solver 0061 % from Optimization Toolbox 6.x + 0062 % pdipmopf - PDIPMOPF, primal-dual interior point method OPF solver 0063 % scpdipmopf - SCPDIPMOPF, step-controlled PDIPM OPF solver 0064 % smartmarket - RUNMARKET and friends, for running an auction 0065 % tralmopf - TRALMOPF, trust region based augmented Langrangian 0066 % OPF solver 0067 % octave - code is running under Octave, as opposed to MATLAB 0068 % sdp_pf - SDP_PF applications of semi-definite programming 0069 % relaxation of power flow equations 0070 % yalmip - YALMIP SDP modeling platform 0071 % sedumi - SeDuMi SDP solver 0072 % sdpt3 - SDPT3 SDP solver 0073 % 0074 % Examples: 0075 % if have_fcn('minopf') 0076 % results = runopf(mpc, mpoption('opf.ac.solver', 'MINOPF')); 0077 % end 0078 % 0079 % Optional functionality can also be toggled OFF and ON by calling HAVE_FCN 0080 % with the following syntax, 0081 % TORF = HAVE_FCN(TAG, TOGGLE) 0082 % where TOGGLE takes a numeric value as follows: 0083 0084 % Private tags for internal use only: 0085 % catchme - support for 'catch me' syntax in try/catch constructs 0086 % evalc - support for evalc() function 0087 % ipopt_auxdata - support for ipopt_auxdata(), required by 3.11 and later 0088 % regexp_split - support for 'split' argument to regexp() 0089 0090 % MATPOWER 0091 % Copyright (c) 2004-2015 by Power System Engineering Research Center (PSERC) 0092 % by Ray Zimmerman, PSERC Cornell 0093 % 0094 % $Id: have_fcn.m 2662 2015-03-20 20:02:08Z ray $ 0095 % 0096 % This file is part of MATPOWER. 0097 % Covered by the 3-clause BSD License (see LICENSE file for details). 0098 % See http://www.pserc.cornell.edu/matpower/ for more info. 0099 0100 if nargin > 1 && isnumeric(rtype) 0101 toggle = 1; 0102 on_off = rtype; 0103 if on_off < 0 0104 TorF = have_fcn(tag); 0105 on_off = ~TorF; 0106 end 0107 else 0108 toggle = 0; 0109 end 0110 0111 persistent fcns; 0112 0113 if toggle %% change availability 0114 if on_off %% turn on if available 0115 fcns = rmfield(fcns, tag); %% delete field to force re-check 0116 else %% turn off 0117 if ~isfield(fcns, tag) %% not yet been checked 0118 TorF = have_fcn(tag); %% cache result first 0119 end 0120 fcns.(tag).av = 0; %% then turn off 0121 end 0122 TorF = have_fcn(tag); %% return cached value 0123 else %% detect availability 0124 %% info not yet cached? 0125 if ~isfield(fcns, tag) 0126 %%----- determine installation status, version number, etc. ----- 0127 %% initialize default values 0128 TorF = 0; 0129 vstr = ''; 0130 rdate = ''; 0131 0132 switch tag 0133 %%----- public tags ----- 0134 case 'bpmpd' 0135 TorF = exist('bp', 'file') == 3; 0136 if TorF 0137 v = bpver('all'); 0138 vstr = v.Version; 0139 rdate = v.Date; 0140 end 0141 case 'clp' 0142 tmp = have_fcn('opti_clp', 'all'); 0143 if tmp.av %% have opti_clp 0144 TorF = tmp.av; 0145 vstr = tmp.vstr; 0146 rdate = tmp.date; 0147 elseif exist('clp','file') == 2 && exist('mexclp','file') == 3 0148 TorF = 1; 0149 vstr = ''; 0150 end 0151 case 'opti_clp' 0152 TorF = exist('opti_clp', 'file') == 2 && exist('clp', 'file') == 3; 0153 if TorF 0154 str = evalc('clp'); 0155 pat = 'CLP: COIN-OR Linear Programming \[v([^\s,]+), Built ([^\]])+\]'; %% OPTI, Giorgetti/Currie 0156 [s,e,tE,m,t] = regexp(str, pat); 0157 if ~isempty(t) 0158 vstr = t{1}{1}; 0159 rdate = datestr(t{1}{2}, 'dd-mmm-yyyy'); 0160 end 0161 end 0162 case 'cplex' 0163 if exist('cplexqp', 'file') 0164 %% it's installed, but we need to check for MEX for this arch 0165 p = which('cplexqp'); %% get the path 0166 len = length(p) - length('cplexqp.p'); 0167 w = what(p(1:len)); %% look for mex files on the path 0168 for k = 1:length(w.mex) 0169 if regexp(w.mex{k}, 'cplexlink[^\.]*'); 0170 TorF = 1; 0171 break; 0172 end 0173 end 0174 end 0175 if TorF 0176 try 0177 cplex = Cplex('null'); 0178 vstr = cplex.getVersion; 0179 catch 0180 TorF = 0; 0181 end 0182 end 0183 case {'fmincon', 'fmincon_ipm', 'intlinprog', 'linprog', ... 0184 'linprog_ds', 'optimoptions', 'quadprog', 'quadprog_ls'} 0185 if license('test', 'optimization_toolbox') 0186 v = ver('optim'); 0187 vstr = v.Version; 0188 rdate = v.Date; 0189 switch tag 0190 case 'fmincon' 0191 TorF = exist('fmincon', 'file') == 2 || ... 0192 exist('fmincon', 'file') == 6; 0193 case 'intlinprog' 0194 TorF = exist('intlinprog', 'file') == 2; 0195 case 'linprog' 0196 TorF = exist('linprog', 'file') == 2; 0197 case 'quadprog' 0198 TorF = exist('quadprog', 'file') == 2; 0199 otherwise 0200 otver = vstr2num(vstr); 0201 switch tag 0202 case 'fmincon_ipm' 0203 if otver >= 4 %% Opt Tbx 4.0+ (R208a+, Matlab 7.6+) 0204 TorF = 1; 0205 else 0206 TorF = 0; 0207 end 0208 case 'linprog_ds' 0209 if otver >= 7.001 %% Opt Tbx 7.1+ (R2014b+, Matlab 8.4+) 0210 TorF = 1; 0211 else 0212 TorF = 0; 0213 end 0214 case 'optimoptions' 0215 if otver >= 6.003 %% Opt Tbx 6.3+ (R2013a+, Matlab 8.1+) 0216 TorF = 1; 0217 else 0218 TorF = 0; 0219 end 0220 case 'quadprog_ls' 0221 if otver >= 6 %% Opt Tbx 6.0+ (R2011a+, Matlab 7.12+) 0222 TorF = 1; 0223 else 0224 TorF = 0; 0225 end 0226 end 0227 end 0228 else 0229 TorF = 0; 0230 end 0231 case 'glpk' 0232 if exist('glpk','file') == 3 %% Windows OPTI install (no glpk.m) 0233 TorF = 1; 0234 str = evalc('glpk'); 0235 pat = 'GLPK: GNU Linear Programming Kit \[v([^\s,]+), Built ([^\]])+\]'; %% OPTI, Giorgetti/Currie 0236 [s,e,tE,m,t] = regexp(str, pat); 0237 if ~isempty(t) 0238 vstr = t{1}{1}; 0239 rdate = datestr(t{1}{2}, 'dd-mmm-yyyy'); 0240 end 0241 elseif exist('glpk','file') == 2 %% others have glpk.m and ... 0242 if exist('__glpk__','file') == 3 %% octave __glpk__ MEX 0243 TorF = 1; 0244 if have_fcn('evalc') 0245 str = evalc('glpk(1, 1, 1, 1, 1, ''U'', ''C'', -1, struct(''msglev'', 3))'); 0246 pat = 'GLPK Simplex Optimizer, v([^\s,]+)'; 0247 [s,e,tE,m,t] = regexp(str, pat); 0248 if ~isempty(t) 0249 vstr = t{1}{1}; 0250 end 0251 end 0252 elseif exist('glpkcc','file') == 3 %% Matlab glpkcc MEX 0253 TorF = 1; 0254 str = evalc('glpk'); 0255 pat = 'GLPK Matlab interface\. Version: ([^\s,]+)'; %% glpkccm, Giorgetti/Klitgord 0256 [s,e,tE,m,t] = regexp(str, pat); 0257 if ~isempty(t) 0258 vstr = t{1}{1}; 0259 end 0260 end 0261 end 0262 case 'gurobi' 0263 TorF = exist('gurobi', 'file') == 3; 0264 if TorF 0265 try 0266 model = struct( ... 0267 'A', sparse(1), ... 0268 'rhs', 1, ... 0269 'sense', '=', ... 0270 'vtype', 'C', ... 0271 'obj', 1, ... 0272 'modelsense', 'min' ... 0273 ); 0274 params = struct( ... 0275 'outputflag', 0 ... 0276 ); 0277 result = gurobi(model, params); 0278 vstr = sprintf('%d.%d.%d', result.versioninfo.major, result.versioninfo.minor, result.versioninfo.technical); 0279 catch % gurobiError 0280 fprintf('Gurobi Error!\n'); 0281 % disp(gurobiError.message); 0282 end 0283 end 0284 case 'ipopt' 0285 TorF = exist('ipopt', 'file') == 3; 0286 if TorF 0287 str = evalc('qps_ipopt([],1,1,1,1,1,1,1,struct(''verbose'', 2))'); 0288 pat = 'Ipopt version ([^\s,]+)'; 0289 [s,e,tE,m,t] = regexp(str, pat); 0290 if ~isempty(t) 0291 vstr = t{1}{1}; 0292 if vstr2num(vstr) >= 3.011 && ... 0293 ~exist('ipopt_auxdata', 'file') 0294 TorF = 0; 0295 warning('Improper installation of IPOPT. Version %s detected, but IPOPT_AUXDATA.M is missing.', vstr); 0296 end 0297 end 0298 end 0299 case 'knitro' %% any Knitro 0300 tmp = have_fcn('knitromatlab', 'all'); 0301 if tmp.av 0302 TorF = tmp.av; 0303 vstr = tmp.vstr; 0304 rdate = tmp.date; 0305 else 0306 tmp = have_fcn('ktrlink', 'all'); 0307 if tmp.av 0308 TorF = tmp.av; 0309 vstr = tmp.vstr; 0310 rdate = tmp.date; 0311 end 0312 end 0313 case {'knitromatlab', 'ktrlink'} 0314 %% knitromatlab for Knitro 9.0 or greater 0315 %% ktrlink for pre-Knitro 9.0, requires Optim Toolbox 0316 TorF = exist(tag, 'file') == 2; 0317 if TorF 0318 try 0319 str = evalc(['[x fval] = ' tag '(@(x)1,1);']); 0320 end 0321 TorF = exist('fval', 'var') && fval == 1; 0322 if TorF 0323 pat = 'KNITRO ([^\s]+)\n'; 0324 [s,e,tE,m,t] = regexp(str, pat); 0325 if ~isempty(t) 0326 vstr = t{1}{1}; 0327 end 0328 end 0329 end 0330 case 'matlab' 0331 v = ver('matlab'); 0332 if ~isempty(v) && isfield(v, 'Version') && ~isempty(v.Version) 0333 TorF = 1; 0334 vstr = v.Version; 0335 rdate = v.Date; 0336 end 0337 case 'minopf' 0338 TorF = exist('minopf', 'file') == 3; 0339 if TorF 0340 v = minopfver('all'); 0341 vstr = v.Version; 0342 rdate = v.Date; 0343 end 0344 case 'mosek' 0345 TorF = exist('mosekopt', 'file') == 3; 0346 if TorF 0347 % MOSEK Version 6.0.0.93 (Build date: 2010-10-26 13:03:27) 0348 % MOSEK Version 6.0.0.106 (Build date: 2011-3-17 10:46:54) 0349 % MOSEK Version 7.0.0.134 (Build date: 2014-10-2 11:10:02) 0350 pat = 'Version (\.*\d)+.*Build date: (\d+-\d+-\d+)'; 0351 [s,e,tE,m,t] = regexp(evalc('mosekopt'), pat); 0352 if ~isempty(t) 0353 vstr = t{1}{1}; 0354 rdate = datestr(t{1}{2}, 'dd-mmm-yyyy'); 0355 end 0356 end 0357 case 'smartmarket' 0358 TorF = exist('runmarket', 'file') == 2; 0359 if TorF 0360 v = mpver('all'); 0361 vstr = v.Version; 0362 rdate = v.Date; 0363 end 0364 case 'octave' 0365 TorF = exist('OCTAVE_VERSION', 'builtin') == 5; 0366 if TorF 0367 v = ver('octave'); 0368 vstr = v.Version; 0369 rdate = v.Date; 0370 end 0371 case 'pardiso' 0372 TorF = exist('pardisoinit', 'file') == 3 && ... 0373 exist('pardisoreorder', 'file') == 3 && ... 0374 exist('pardisofactor', 'file') == 3 && ... 0375 exist('pardisosolve', 'file') == 3 && ... 0376 exist('pardisofree', 'file') == 3; 0377 if TorF 0378 try 0379 A = sparse([1 2; 3 4]); 0380 b = [1;1]; 0381 % Summary PARDISO 5.1.0: ( reorder to reorder ) 0382 pat = 'Summary PARDISO (\.*\d)+:'; 0383 info = pardisoinit(11, 0); 0384 info = pardisoreorder(A, info, false); 0385 % [s,e,tE,m,t] = regexp(evalc('info = pardisoreorder(A, info, true);'), pat); 0386 % if ~isempty(t) 0387 % vstr = t{1}{1}; 0388 % end 0389 info = pardisofactor(A, info, false); 0390 [x, info] = pardisosolve(A, b, info, false); 0391 pardisofree(info); 0392 if any(x ~= [-1; 1]) 0393 TorF = 0; 0394 end 0395 catch 0396 TorF = 0; 0397 end 0398 end 0399 case {'pdipmopf', 'scpdipmopf', 'tralmopf'} 0400 if have_fcn('matlab') 0401 v = ver('Matlab'); 0402 vn = vstr2num(v.Version); 0403 %% requires >= MATLAB 6.5 (R13) (released 20-Jun-2002) 0404 %% older versions do not have mxCreateDoubleScalar() function 0405 %% (they have mxCreateScalarDouble() instead) 0406 if vn >= 6.005 0407 switch tag 0408 case 'pdipmopf' 0409 TorF = exist('pdipmopf', 'file') == 3; 0410 case 'scpdipmopf' 0411 TorF = exist('scpdipmopf', 'file') == 3; 0412 case 'tralmopf' 0413 %% requires >= MATLAB 7.3 (R2006b) (released 03-Aug-2006) 0414 %% older versions do not include the needed form of chol() 0415 if vn >= 7.003 0416 TorF = exist('tralmopf', 'file') == 3; 0417 else 0418 TorF = 0; 0419 end 0420 end 0421 else 0422 TorF = 0; 0423 end 0424 if TorF 0425 v = feval([tag 'ver'], 'all'); 0426 vstr = v.Version; 0427 rdate = v.Date; 0428 end 0429 end 0430 case 'sdp_pf' 0431 TorF = have_fcn('yalmip') && exist('mpoption_info_sdp_pf', 'file') == 2; 0432 if TorF 0433 v = sdp_pf_ver('all'); 0434 vstr = v.Version; 0435 rdate = v.Date; 0436 end 0437 case 'yalmip' 0438 TorF = ~have_fcn('octave') && exist('yalmip','file') == 2; 0439 %% YALMIP does not yet work with Octave, rdz 1/6/14 0440 if TorF 0441 str = evalc('yalmip;'); 0442 pat = 'Version\s+([^\s]+)\n'; 0443 [s,e,tE,m,t] = regexp(str, pat); 0444 if ~isempty(t) 0445 rdate = t{1}{1}; 0446 vstr = datestr(rdate, 'yy.mm.dd'); 0447 end 0448 end 0449 case 'sdpt3' 0450 TorF = exist('sdpt3','file') == 2; 0451 if TorF 0452 str = evalc('help sdpt3'); 0453 pat = 'version\s+([^\s]+).*Last Modified: ([^\n]+)\n'; 0454 [s,e,tE,m,t] = regexp(str, pat); 0455 if ~isempty(t) 0456 vstr = t{1}{1}; 0457 rdate = datestr(t{1}{2}, 'dd-mmm-yyyy'); 0458 end 0459 end 0460 case 'sedumi' 0461 TorF = exist('sedumi','file') == 2; 0462 if TorF 0463 str = evalc('x = sedumi([1 1], 1, [1;2])'); 0464 pat = 'SeDuMi\s+([^\s]+)'; 0465 [s,e,tE,m,t] = regexp(str, pat); 0466 if ~isempty(t) 0467 vstr = t{1}{1}; 0468 end 0469 end 0470 0471 %%----- private tags ----- 0472 case 'catchme' %% not supported by Matlab <= 7.4 (R2007a), Octave <= 3.6 0473 if have_fcn('octave') 0474 if have_fcn('octave', 'vnum') <= 3.006 0475 TorF = 0; 0476 else 0477 TorF = 1; 0478 end 0479 else 0480 if have_fcn('matlab', 'vnum') <= 7.004 0481 TorF = 0; 0482 else 0483 TorF = 1; 0484 end 0485 end 0486 case 'evalc' 0487 if have_fcn('octave') 0488 TorF = 0; 0489 else 0490 TorF = 1; 0491 end 0492 case 'ipopt_auxdata' 0493 if have_fcn('ipopt') 0494 vn = have_fcn('ipopt', 'vnum'); 0495 if ~isempty(vn) && vn >= 3.011 0496 TorF = 1; 0497 end 0498 end 0499 case 'regexp_split' %% missing for Matlab < 7.3 & Octave < 3.8 0500 if have_fcn('matlab') && have_fcn('matlab', 'vnum') >= 7.003 0501 TorF = 1; 0502 elseif have_fcn('octave', 'vnum') >= 3.008 0503 TorF = 1; 0504 end 0505 0506 %%----- unknown tag ----- 0507 otherwise 0508 error('have_fcn: unknown functionality %s', tag); 0509 end 0510 0511 %% assign values to cache 0512 fcns.(tag).av = TorF; 0513 fcns.(tag).vstr = vstr; 0514 if isempty(vstr) 0515 fcns.(tag).vnum = []; 0516 else 0517 fcns.(tag).vnum = vstr2num(vstr); 0518 end 0519 fcns.(tag).date = rdate; 0520 end 0521 end 0522 0523 %% extract desired values from cache 0524 if nargin < 2 || toggle 0525 rv = fcns.(tag).av; 0526 else 0527 switch lower(rtype) 0528 case 'vstr' 0529 rv = fcns.(tag).vstr; 0530 case 'vnum' 0531 rv = fcns.(tag).vnum; 0532 case 'date' 0533 rv = fcns.(tag).date; 0534 case 'all' 0535 rv = fcns.(tag); 0536 end 0537 end 0538 0539 function num = vstr2num(vstr) 0540 % Converts version string to numerical value suitable for < or > comparisons 0541 % E.g. '3.11.4' --> 3.011004 0542 pat = '\.?(\d+)'; 0543 [s,e,tE,m,t] = regexp(vstr, pat); 0544 b = 1; 0545 num = 0; 0546 for k = 1:length(t) 0547 num = num + b * str2num(t{k}{1}); 0548 b = b / 1000; 0549 end