Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/scipy/linalg/blas.py: 75%

102 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-12-12 06:31 +0000

1""" 

2Low-level BLAS functions (:mod:`scipy.linalg.blas`) 

3=================================================== 

4 

5This module contains low-level functions from the BLAS library. 

6 

7.. versionadded:: 0.12.0 

8 

9.. note:: 

10 

11 The common ``overwrite_<>`` option in many routines, allows the 

12 input arrays to be overwritten to avoid extra memory allocation. 

13 However this requires the array to satisfy two conditions 

14 which are memory order and the data type to match exactly the 

15 order and the type expected by the routine. 

16 

17 As an example, if you pass a double precision float array to any 

18 ``S....`` routine which expects single precision arguments, f2py 

19 will create an intermediate array to match the argument types and 

20 overwriting will be performed on that intermediate array. 

21 

22 Similarly, if a C-contiguous array is passed, f2py will pass a 

23 FORTRAN-contiguous array internally. Please make sure that these 

24 details are satisfied. More information can be found in the f2py 

25 documentation. 

26 

27.. warning:: 

28 

29 These functions do little to no error checking. 

30 It is possible to cause crashes by mis-using them, 

31 so prefer using the higher-level routines in `scipy.linalg`. 

32 

33Finding functions 

34----------------- 

35 

36.. autosummary:: 

37 :toctree: generated/ 

38 

39 get_blas_funcs 

40 find_best_blas_type 

41 

42BLAS Level 1 functions 

43---------------------- 

44 

45.. autosummary:: 

46 :toctree: generated/ 

47 

48 caxpy 

49 ccopy 

50 cdotc 

51 cdotu 

52 crotg 

53 cscal 

54 csrot 

55 csscal 

56 cswap 

57 dasum 

58 daxpy 

59 dcopy 

60 ddot 

61 dnrm2 

62 drot 

63 drotg 

64 drotm 

65 drotmg 

66 dscal 

67 dswap 

68 dzasum 

69 dznrm2 

70 icamax 

71 idamax 

72 isamax 

73 izamax 

74 sasum 

75 saxpy 

76 scasum 

77 scnrm2 

78 scopy 

79 sdot 

80 snrm2 

81 srot 

82 srotg 

83 srotm 

84 srotmg 

85 sscal 

86 sswap 

87 zaxpy 

88 zcopy 

89 zdotc 

90 zdotu 

91 zdrot 

92 zdscal 

93 zrotg 

94 zscal 

95 zswap 

96 

97BLAS Level 2 functions 

98---------------------- 

99 

100.. autosummary:: 

101 :toctree: generated/ 

102 

103 sgbmv 

104 sgemv 

105 sger 

106 ssbmv 

107 sspr 

108 sspr2 

109 ssymv 

110 ssyr 

111 ssyr2 

112 stbmv 

113 stpsv 

114 strmv 

115 strsv 

116 dgbmv 

117 dgemv 

118 dger 

119 dsbmv 

120 dspr 

121 dspr2 

122 dsymv 

123 dsyr 

124 dsyr2 

125 dtbmv 

126 dtpsv 

127 dtrmv 

128 dtrsv 

129 cgbmv 

130 cgemv 

131 cgerc 

132 cgeru 

133 chbmv 

134 chemv 

135 cher 

136 cher2 

137 chpmv 

138 chpr 

139 chpr2 

140 ctbmv 

141 ctbsv 

142 ctpmv 

143 ctpsv 

144 ctrmv 

145 ctrsv 

146 csyr 

147 zgbmv 

148 zgemv 

149 zgerc 

150 zgeru 

151 zhbmv 

152 zhemv 

153 zher 

154 zher2 

155 zhpmv 

156 zhpr 

157 zhpr2 

158 ztbmv 

159 ztbsv 

160 ztpmv 

161 ztrmv 

162 ztrsv 

163 zsyr 

164 

165BLAS Level 3 functions 

166---------------------- 

167 

168.. autosummary:: 

169 :toctree: generated/ 

170 

171 sgemm 

172 ssymm 

173 ssyr2k 

174 ssyrk 

175 strmm 

176 strsm 

177 dgemm 

178 dsymm 

179 dsyr2k 

180 dsyrk 

181 dtrmm 

182 dtrsm 

183 cgemm 

184 chemm 

185 cher2k 

186 cherk 

187 csymm 

188 csyr2k 

189 csyrk 

190 ctrmm 

191 ctrsm 

192 zgemm 

193 zhemm 

194 zher2k 

195 zherk 

196 zsymm 

197 zsyr2k 

198 zsyrk 

199 ztrmm 

200 ztrsm 

201 

202""" 

203# 

204# Author: Pearu Peterson, March 2002 

205# refactoring by Fabian Pedregosa, March 2010 

206# 

207 

208__all__ = ['get_blas_funcs', 'find_best_blas_type'] 

209 

210import numpy as _np 

211import functools 

212 

213from scipy.linalg import _fblas 

214try: 

215 from scipy.linalg import _cblas 

216except ImportError: 

217 _cblas = None 

218 

219try: 

220 from scipy.linalg import _fblas_64 

221 HAS_ILP64 = True 

222except ImportError: 

223 HAS_ILP64 = False 

224 _fblas_64 = None 

225 

226# Expose all functions (only fblas --- cblas is an implementation detail) 

227empty_module = None 

228from scipy.linalg._fblas import * 

229del empty_module 

230 

231# all numeric dtypes '?bBhHiIlLqQefdgFDGO' that are safe to be converted to 

232 

233# single precision float : '?bBhH!!!!!!ef!!!!!!' 

234# double precision float : '?bBhHiIlLqQefdg!!!!' 

235# single precision complex : '?bBhH!!!!!!ef!!F!!!' 

236# double precision complex : '?bBhHiIlLqQefdgFDG!' 

237 

238_type_score = {x: 1 for x in '?bBhHef'} 

239_type_score.update({x: 2 for x in 'iIlLqQd'}) 

240 

241# Handle float128(g) and complex256(G) separately in case non-Windows systems. 

242# On Windows, the values will be rewritten to the same key with the same value. 

243_type_score.update({'F': 3, 'D': 4, 'g': 2, 'G': 4}) 

244 

245# Final mapping to the actual prefixes and dtypes 

246_type_conv = {1: ('s', _np.dtype('float32')), 

247 2: ('d', _np.dtype('float64')), 

248 3: ('c', _np.dtype('complex64')), 

249 4: ('z', _np.dtype('complex128'))} 

250 

251# some convenience alias for complex functions 

252_blas_alias = {'cnrm2': 'scnrm2', 'znrm2': 'dznrm2', 

253 'cdot': 'cdotc', 'zdot': 'zdotc', 

254 'cger': 'cgerc', 'zger': 'zgerc', 

255 'sdotc': 'sdot', 'sdotu': 'sdot', 

256 'ddotc': 'ddot', 'ddotu': 'ddot'} 

257 

258 

259def find_best_blas_type(arrays=(), dtype=None): 

260 """Find best-matching BLAS/LAPACK type. 

261 

262 Arrays are used to determine the optimal prefix of BLAS routines. 

263 

264 Parameters 

265 ---------- 

266 arrays : sequence of ndarrays, optional 

267 Arrays can be given to determine optimal prefix of BLAS 

268 routines. If not given, double-precision routines will be 

269 used, otherwise the most generic type in arrays will be used. 

270 dtype : str or dtype, optional 

271 Data-type specifier. Not used if `arrays` is non-empty. 

272 

273 Returns 

274 ------- 

275 prefix : str 

276 BLAS/LAPACK prefix character. 

277 dtype : dtype 

278 Inferred Numpy data type. 

279 prefer_fortran : bool 

280 Whether to prefer Fortran order routines over C order. 

281 

282 Examples 

283 -------- 

284 >>> import numpy as np 

285 >>> import scipy.linalg.blas as bla 

286 >>> rng = np.random.default_rng() 

287 >>> a = rng.random((10,15)) 

288 >>> b = np.asfortranarray(a) # Change the memory layout order 

289 >>> bla.find_best_blas_type((a,)) 

290 ('d', dtype('float64'), False) 

291 >>> bla.find_best_blas_type((a*1j,)) 

292 ('z', dtype('complex128'), False) 

293 >>> bla.find_best_blas_type((b,)) 

294 ('d', dtype('float64'), True) 

295 

296 """ 

297 dtype = _np.dtype(dtype) 

298 max_score = _type_score.get(dtype.char, 5) 

299 prefer_fortran = False 

300 

301 if arrays: 

302 # In most cases, single element is passed through, quicker route 

303 if len(arrays) == 1: 

304 max_score = _type_score.get(arrays[0].dtype.char, 5) 

305 prefer_fortran = arrays[0].flags['FORTRAN'] 

306 else: 

307 # use the most generic type in arrays 

308 scores = [_type_score.get(x.dtype.char, 5) for x in arrays] 

309 max_score = max(scores) 

310 ind_max_score = scores.index(max_score) 

311 # safe upcasting for mix of float64 and complex64 --> prefix 'z' 

312 if max_score == 3 and (2 in scores): 

313 max_score = 4 

314 

315 if arrays[ind_max_score].flags['FORTRAN']: 

316 # prefer Fortran for leading array with column major order 

317 prefer_fortran = True 

318 

319 # Get the LAPACK prefix and the corresponding dtype if not fall back 

320 # to 'd' and double precision float. 

321 prefix, dtype = _type_conv.get(max_score, ('d', _np.dtype('float64'))) 

322 

323 return prefix, dtype, prefer_fortran 

324 

325 

326def _get_funcs(names, arrays, dtype, 

327 lib_name, fmodule, cmodule, 

328 fmodule_name, cmodule_name, alias, 

329 ilp64=False): 

330 """ 

331 Return available BLAS/LAPACK functions. 

332 

333 Used also in lapack.py. See get_blas_funcs for docstring. 

334 """ 

335 

336 funcs = [] 

337 unpack = False 

338 dtype = _np.dtype(dtype) 

339 module1 = (cmodule, cmodule_name) 

340 module2 = (fmodule, fmodule_name) 

341 

342 if isinstance(names, str): 

343 names = (names,) 

344 unpack = True 

345 

346 prefix, dtype, prefer_fortran = find_best_blas_type(arrays, dtype) 

347 

348 if prefer_fortran: 

349 module1, module2 = module2, module1 

350 

351 for name in names: 

352 func_name = prefix + name 

353 func_name = alias.get(func_name, func_name) 

354 func = getattr(module1[0], func_name, None) 

355 module_name = module1[1] 

356 if func is None: 

357 func = getattr(module2[0], func_name, None) 

358 module_name = module2[1] 

359 if func is None: 

360 raise ValueError( 

361 '%s function %s could not be found' % (lib_name, func_name)) 

362 func.module_name, func.typecode = module_name, prefix 

363 func.dtype = dtype 

364 if not ilp64: 

365 func.int_dtype = _np.dtype(_np.intc) 

366 else: 

367 func.int_dtype = _np.dtype(_np.int64) 

368 func.prefix = prefix # Backward compatibility 

369 funcs.append(func) 

370 

371 if unpack: 

372 return funcs[0] 

373 else: 

374 return funcs 

375 

376 

377def _memoize_get_funcs(func): 

378 """ 

379 Memoized fast path for _get_funcs instances 

380 """ 

381 memo = {} 

382 func.memo = memo 

383 

384 @functools.wraps(func) 

385 def getter(names, arrays=(), dtype=None, ilp64=False): 

386 key = (names, dtype, ilp64) 

387 for array in arrays: 

388 # cf. find_blas_funcs 

389 key += (array.dtype.char, array.flags.fortran) 

390 

391 try: 

392 value = memo.get(key) 

393 except TypeError: 

394 # unhashable key etc. 

395 key = None 

396 value = None 

397 

398 if value is not None: 

399 return value 

400 

401 value = func(names, arrays, dtype, ilp64) 

402 

403 if key is not None: 

404 memo[key] = value 

405 

406 return value 

407 

408 return getter 

409 

410 

411@_memoize_get_funcs 

412def get_blas_funcs(names, arrays=(), dtype=None, ilp64=False): 

413 """Return available BLAS function objects from names. 

414 

415 Arrays are used to determine the optimal prefix of BLAS routines. 

416 

417 Parameters 

418 ---------- 

419 names : str or sequence of str 

420 Name(s) of BLAS functions without type prefix. 

421 

422 arrays : sequence of ndarrays, optional 

423 Arrays can be given to determine optimal prefix of BLAS 

424 routines. If not given, double-precision routines will be 

425 used, otherwise the most generic type in arrays will be used. 

426 

427 dtype : str or dtype, optional 

428 Data-type specifier. Not used if `arrays` is non-empty. 

429 

430 ilp64 : {True, False, 'preferred'}, optional 

431 Whether to return ILP64 routine variant. 

432 Choosing 'preferred' returns ILP64 routine if available, 

433 and otherwise the 32-bit routine. Default: False 

434 

435 Returns 

436 ------- 

437 funcs : list 

438 List containing the found function(s). 

439 

440 

441 Notes 

442 ----- 

443 This routine automatically chooses between Fortran/C 

444 interfaces. Fortran code is used whenever possible for arrays with 

445 column major order. In all other cases, C code is preferred. 

446 

447 In BLAS, the naming convention is that all functions start with a 

448 type prefix, which depends on the type of the principal 

449 matrix. These can be one of {'s', 'd', 'c', 'z'} for the NumPy 

450 types {float32, float64, complex64, complex128} respectively. 

451 The code and the dtype are stored in attributes `typecode` and `dtype` 

452 of the returned functions. 

453 

454 Examples 

455 -------- 

456 >>> import numpy as np 

457 >>> import scipy.linalg as LA 

458 >>> rng = np.random.default_rng() 

459 >>> a = rng.random((3,2)) 

460 >>> x_gemv = LA.get_blas_funcs('gemv', (a,)) 

461 >>> x_gemv.typecode 

462 'd' 

463 >>> x_gemv = LA.get_blas_funcs('gemv',(a*1j,)) 

464 >>> x_gemv.typecode 

465 'z' 

466 

467 """ 

468 if isinstance(ilp64, str): 

469 if ilp64 == 'preferred': 

470 ilp64 = HAS_ILP64 

471 else: 

472 raise ValueError("Invalid value for 'ilp64'") 

473 

474 if not ilp64: 

475 return _get_funcs(names, arrays, dtype, 

476 "BLAS", _fblas, _cblas, "fblas", "cblas", 

477 _blas_alias, ilp64=False) 

478 else: 

479 if not HAS_ILP64: 

480 raise RuntimeError("BLAS ILP64 routine requested, but Scipy " 

481 "compiled only with 32-bit BLAS") 

482 return _get_funcs(names, arrays, dtype, 

483 "BLAS", _fblas_64, None, "fblas_64", None, 

484 _blas_alias, ilp64=True)