test_blas.py 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079
  1. #
  2. # Created by: Pearu Peterson, April 2002
  3. #
  4. from __future__ import division, print_function, absolute_import
  5. __usage__ = """
  6. Build linalg:
  7. python setup.py build
  8. Run tests if scipy is installed:
  9. python -c 'import scipy;scipy.linalg.test()'
  10. """
  11. import math
  12. import numpy as np
  13. from numpy.testing import (assert_equal, assert_almost_equal, assert_,
  14. assert_array_almost_equal, assert_allclose)
  15. from pytest import raises as assert_raises
  16. from numpy import float32, float64, complex64, complex128, arange, triu, \
  17. tril, zeros, tril_indices, ones, mod, diag, append, eye, \
  18. nonzero
  19. from numpy.random import rand, seed
  20. from scipy.linalg import _fblas as fblas, get_blas_funcs, toeplitz, solve, \
  21. solve_triangular
  22. try:
  23. from scipy.linalg import _cblas as cblas
  24. except ImportError:
  25. cblas = None
  26. REAL_DTYPES = [float32, float64]
  27. COMPLEX_DTYPES = [complex64, complex128]
  28. DTYPES = REAL_DTYPES + COMPLEX_DTYPES
  29. def test_get_blas_funcs():
  30. # check that it returns Fortran code for arrays that are
  31. # fortran-ordered
  32. f1, f2, f3 = get_blas_funcs(
  33. ('axpy', 'axpy', 'axpy'),
  34. (np.empty((2, 2), dtype=np.complex64, order='F'),
  35. np.empty((2, 2), dtype=np.complex128, order='C'))
  36. )
  37. # get_blas_funcs will choose libraries depending on most generic
  38. # array
  39. assert_equal(f1.typecode, 'z')
  40. assert_equal(f2.typecode, 'z')
  41. if cblas is not None:
  42. assert_equal(f1.module_name, 'cblas')
  43. assert_equal(f2.module_name, 'cblas')
  44. # check defaults.
  45. f1 = get_blas_funcs('rotg')
  46. assert_equal(f1.typecode, 'd')
  47. # check also dtype interface
  48. f1 = get_blas_funcs('gemm', dtype=np.complex64)
  49. assert_equal(f1.typecode, 'c')
  50. f1 = get_blas_funcs('gemm', dtype='F')
  51. assert_equal(f1.typecode, 'c')
  52. # extended precision complex
  53. f1 = get_blas_funcs('gemm', dtype=np.longcomplex)
  54. assert_equal(f1.typecode, 'z')
  55. # check safe complex upcasting
  56. f1 = get_blas_funcs('axpy',
  57. (np.empty((2, 2), dtype=np.float64),
  58. np.empty((2, 2), dtype=np.complex64))
  59. )
  60. assert_equal(f1.typecode, 'z')
  61. def test_get_blas_funcs_alias():
  62. # check alias for get_blas_funcs
  63. f, g = get_blas_funcs(('nrm2', 'dot'), dtype=np.complex64)
  64. assert f.typecode == 'c'
  65. assert g.typecode == 'c'
  66. f, g, h = get_blas_funcs(('dot', 'dotc', 'dotu'), dtype=np.float64)
  67. assert f is g
  68. assert f is h
  69. class TestCBLAS1Simple(object):
  70. def test_axpy(self):
  71. for p in 'sd':
  72. f = getattr(cblas, p+'axpy', None)
  73. if f is None:
  74. continue
  75. assert_array_almost_equal(f([1, 2, 3], [2, -1, 3], a=5),
  76. [7, 9, 18])
  77. for p in 'cz':
  78. f = getattr(cblas, p+'axpy', None)
  79. if f is None:
  80. continue
  81. assert_array_almost_equal(f([1, 2j, 3], [2, -1, 3], a=5),
  82. [7, 10j-1, 18])
  83. class TestFBLAS1Simple(object):
  84. def test_axpy(self):
  85. for p in 'sd':
  86. f = getattr(fblas, p+'axpy', None)
  87. if f is None:
  88. continue
  89. assert_array_almost_equal(f([1, 2, 3], [2, -1, 3], a=5),
  90. [7, 9, 18])
  91. for p in 'cz':
  92. f = getattr(fblas, p+'axpy', None)
  93. if f is None:
  94. continue
  95. assert_array_almost_equal(f([1, 2j, 3], [2, -1, 3], a=5),
  96. [7, 10j-1, 18])
  97. def test_copy(self):
  98. for p in 'sd':
  99. f = getattr(fblas, p+'copy', None)
  100. if f is None:
  101. continue
  102. assert_array_almost_equal(f([3, 4, 5], [8]*3), [3, 4, 5])
  103. for p in 'cz':
  104. f = getattr(fblas, p+'copy', None)
  105. if f is None:
  106. continue
  107. assert_array_almost_equal(f([3, 4j, 5+3j], [8]*3), [3, 4j, 5+3j])
  108. def test_asum(self):
  109. for p in 'sd':
  110. f = getattr(fblas, p+'asum', None)
  111. if f is None:
  112. continue
  113. assert_almost_equal(f([3, -4, 5]), 12)
  114. for p in ['sc', 'dz']:
  115. f = getattr(fblas, p+'asum', None)
  116. if f is None:
  117. continue
  118. assert_almost_equal(f([3j, -4, 3-4j]), 14)
  119. def test_dot(self):
  120. for p in 'sd':
  121. f = getattr(fblas, p+'dot', None)
  122. if f is None:
  123. continue
  124. assert_almost_equal(f([3, -4, 5], [2, 5, 1]), -9)
  125. def test_complex_dotu(self):
  126. for p in 'cz':
  127. f = getattr(fblas, p+'dotu', None)
  128. if f is None:
  129. continue
  130. assert_almost_equal(f([3j, -4, 3-4j], [2, 3, 1]), -9+2j)
  131. def test_complex_dotc(self):
  132. for p in 'cz':
  133. f = getattr(fblas, p+'dotc', None)
  134. if f is None:
  135. continue
  136. assert_almost_equal(f([3j, -4, 3-4j], [2, 3j, 1]), 3-14j)
  137. def test_nrm2(self):
  138. for p in 'sd':
  139. f = getattr(fblas, p+'nrm2', None)
  140. if f is None:
  141. continue
  142. assert_almost_equal(f([3, -4, 5]), math.sqrt(50))
  143. for p in ['c', 'z', 'sc', 'dz']:
  144. f = getattr(fblas, p+'nrm2', None)
  145. if f is None:
  146. continue
  147. assert_almost_equal(f([3j, -4, 3-4j]), math.sqrt(50))
  148. def test_scal(self):
  149. for p in 'sd':
  150. f = getattr(fblas, p+'scal', None)
  151. if f is None:
  152. continue
  153. assert_array_almost_equal(f(2, [3, -4, 5]), [6, -8, 10])
  154. for p in 'cz':
  155. f = getattr(fblas, p+'scal', None)
  156. if f is None:
  157. continue
  158. assert_array_almost_equal(f(3j, [3j, -4, 3-4j]), [-9, -12j, 12+9j])
  159. for p in ['cs', 'zd']:
  160. f = getattr(fblas, p+'scal', None)
  161. if f is None:
  162. continue
  163. assert_array_almost_equal(f(3, [3j, -4, 3-4j]), [9j, -12, 9-12j])
  164. def test_swap(self):
  165. for p in 'sd':
  166. f = getattr(fblas, p+'swap', None)
  167. if f is None:
  168. continue
  169. x, y = [2, 3, 1], [-2, 3, 7]
  170. x1, y1 = f(x, y)
  171. assert_array_almost_equal(x1, y)
  172. assert_array_almost_equal(y1, x)
  173. for p in 'cz':
  174. f = getattr(fblas, p+'swap', None)
  175. if f is None:
  176. continue
  177. x, y = [2, 3j, 1], [-2, 3, 7-3j]
  178. x1, y1 = f(x, y)
  179. assert_array_almost_equal(x1, y)
  180. assert_array_almost_equal(y1, x)
  181. def test_amax(self):
  182. for p in 'sd':
  183. f = getattr(fblas, 'i'+p+'amax')
  184. assert_equal(f([-2, 4, 3]), 1)
  185. for p in 'cz':
  186. f = getattr(fblas, 'i'+p+'amax')
  187. assert_equal(f([-5, 4+3j, 6]), 1)
  188. # XXX: need tests for rot,rotm,rotg,rotmg
  189. class TestFBLAS2Simple(object):
  190. def test_gemv(self):
  191. for p in 'sd':
  192. f = getattr(fblas, p+'gemv', None)
  193. if f is None:
  194. continue
  195. assert_array_almost_equal(f(3, [[3]], [-4]), [-36])
  196. assert_array_almost_equal(f(3, [[3]], [-4], 3, [5]), [-21])
  197. for p in 'cz':
  198. f = getattr(fblas, p+'gemv', None)
  199. if f is None:
  200. continue
  201. assert_array_almost_equal(f(3j, [[3-4j]], [-4]), [-48-36j])
  202. assert_array_almost_equal(f(3j, [[3-4j]], [-4], 3, [5j]),
  203. [-48-21j])
  204. def test_ger(self):
  205. for p in 'sd':
  206. f = getattr(fblas, p+'ger', None)
  207. if f is None:
  208. continue
  209. assert_array_almost_equal(f(1, [1, 2], [3, 4]), [[3, 4], [6, 8]])
  210. assert_array_almost_equal(f(2, [1, 2, 3], [3, 4]),
  211. [[6, 8], [12, 16], [18, 24]])
  212. assert_array_almost_equal(f(1, [1, 2], [3, 4],
  213. a=[[1, 2], [3, 4]]), [[4, 6], [9, 12]])
  214. for p in 'cz':
  215. f = getattr(fblas, p+'geru', None)
  216. if f is None:
  217. continue
  218. assert_array_almost_equal(f(1, [1j, 2], [3, 4]),
  219. [[3j, 4j], [6, 8]])
  220. assert_array_almost_equal(f(-2, [1j, 2j, 3j], [3j, 4j]),
  221. [[6, 8], [12, 16], [18, 24]])
  222. for p in 'cz':
  223. for name in ('ger', 'gerc'):
  224. f = getattr(fblas, p+name, None)
  225. if f is None:
  226. continue
  227. assert_array_almost_equal(f(1, [1j, 2], [3, 4]),
  228. [[3j, 4j], [6, 8]])
  229. assert_array_almost_equal(f(2, [1j, 2j, 3j], [3j, 4j]),
  230. [[6, 8], [12, 16], [18, 24]])
  231. def test_syr_her(self):
  232. x = np.arange(1, 5, dtype='d')
  233. resx = np.triu(x[:, np.newaxis] * x)
  234. resx_reverse = np.triu(x[::-1, np.newaxis] * x[::-1])
  235. y = np.linspace(0, 8.5, 17, endpoint=False)
  236. z = np.arange(1, 9, dtype='d').view('D')
  237. resz = np.triu(z[:, np.newaxis] * z)
  238. resz_reverse = np.triu(z[::-1, np.newaxis] * z[::-1])
  239. rehz = np.triu(z[:, np.newaxis] * z.conj())
  240. rehz_reverse = np.triu(z[::-1, np.newaxis] * z[::-1].conj())
  241. w = np.c_[np.zeros(4), z, np.zeros(4)].ravel()
  242. for p, rtol in zip('sd', [1e-7, 1e-14]):
  243. f = getattr(fblas, p+'syr', None)
  244. if f is None:
  245. continue
  246. assert_allclose(f(1.0, x), resx, rtol=rtol)
  247. assert_allclose(f(1.0, x, lower=True), resx.T, rtol=rtol)
  248. assert_allclose(f(1.0, y, incx=2, offx=2, n=4), resx, rtol=rtol)
  249. # negative increments imply reversed vectors in blas
  250. assert_allclose(f(1.0, y, incx=-2, offx=2, n=4),
  251. resx_reverse, rtol=rtol)
  252. a = np.zeros((4, 4), 'f' if p == 's' else 'd', 'F')
  253. b = f(1.0, x, a=a, overwrite_a=True)
  254. assert_allclose(a, resx, rtol=rtol)
  255. b = f(2.0, x, a=a)
  256. assert_(a is not b)
  257. assert_allclose(b, 3*resx, rtol=rtol)
  258. assert_raises(Exception, f, 1.0, x, incx=0)
  259. assert_raises(Exception, f, 1.0, x, offx=5)
  260. assert_raises(Exception, f, 1.0, x, offx=-2)
  261. assert_raises(Exception, f, 1.0, x, n=-2)
  262. assert_raises(Exception, f, 1.0, x, n=5)
  263. assert_raises(Exception, f, 1.0, x, lower=2)
  264. assert_raises(Exception, f, 1.0, x, a=np.zeros((2, 2), 'd', 'F'))
  265. for p, rtol in zip('cz', [1e-7, 1e-14]):
  266. f = getattr(fblas, p+'syr', None)
  267. if f is None:
  268. continue
  269. assert_allclose(f(1.0, z), resz, rtol=rtol)
  270. assert_allclose(f(1.0, z, lower=True), resz.T, rtol=rtol)
  271. assert_allclose(f(1.0, w, incx=3, offx=1, n=4), resz, rtol=rtol)
  272. # negative increments imply reversed vectors in blas
  273. assert_allclose(f(1.0, w, incx=-3, offx=1, n=4),
  274. resz_reverse, rtol=rtol)
  275. a = np.zeros((4, 4), 'F' if p == 'c' else 'D', 'F')
  276. b = f(1.0, z, a=a, overwrite_a=True)
  277. assert_allclose(a, resz, rtol=rtol)
  278. b = f(2.0, z, a=a)
  279. assert_(a is not b)
  280. assert_allclose(b, 3*resz, rtol=rtol)
  281. assert_raises(Exception, f, 1.0, x, incx=0)
  282. assert_raises(Exception, f, 1.0, x, offx=5)
  283. assert_raises(Exception, f, 1.0, x, offx=-2)
  284. assert_raises(Exception, f, 1.0, x, n=-2)
  285. assert_raises(Exception, f, 1.0, x, n=5)
  286. assert_raises(Exception, f, 1.0, x, lower=2)
  287. assert_raises(Exception, f, 1.0, x, a=np.zeros((2, 2), 'd', 'F'))
  288. for p, rtol in zip('cz', [1e-7, 1e-14]):
  289. f = getattr(fblas, p+'her', None)
  290. if f is None:
  291. continue
  292. assert_allclose(f(1.0, z), rehz, rtol=rtol)
  293. assert_allclose(f(1.0, z, lower=True), rehz.T.conj(), rtol=rtol)
  294. assert_allclose(f(1.0, w, incx=3, offx=1, n=4), rehz, rtol=rtol)
  295. # negative increments imply reversed vectors in blas
  296. assert_allclose(f(1.0, w, incx=-3, offx=1, n=4),
  297. rehz_reverse, rtol=rtol)
  298. a = np.zeros((4, 4), 'F' if p == 'c' else 'D', 'F')
  299. b = f(1.0, z, a=a, overwrite_a=True)
  300. assert_allclose(a, rehz, rtol=rtol)
  301. b = f(2.0, z, a=a)
  302. assert_(a is not b)
  303. assert_allclose(b, 3*rehz, rtol=rtol)
  304. assert_raises(Exception, f, 1.0, x, incx=0)
  305. assert_raises(Exception, f, 1.0, x, offx=5)
  306. assert_raises(Exception, f, 1.0, x, offx=-2)
  307. assert_raises(Exception, f, 1.0, x, n=-2)
  308. assert_raises(Exception, f, 1.0, x, n=5)
  309. assert_raises(Exception, f, 1.0, x, lower=2)
  310. assert_raises(Exception, f, 1.0, x, a=np.zeros((2, 2), 'd', 'F'))
  311. def test_syr2(self):
  312. x = np.arange(1, 5, dtype='d')
  313. y = np.arange(5, 9, dtype='d')
  314. resxy = np.triu(x[:, np.newaxis] * y + y[:, np.newaxis] * x)
  315. resxy_reverse = np.triu(x[::-1, np.newaxis] * y[::-1]
  316. + y[::-1, np.newaxis] * x[::-1])
  317. q = np.linspace(0, 8.5, 17, endpoint=False)
  318. for p, rtol in zip('sd', [1e-7, 1e-14]):
  319. f = getattr(fblas, p+'syr2', None)
  320. if f is None:
  321. continue
  322. assert_allclose(f(1.0, x, y), resxy, rtol=rtol)
  323. assert_allclose(f(1.0, x, y, n=3), resxy[:3, :3], rtol=rtol)
  324. assert_allclose(f(1.0, x, y, lower=True), resxy.T, rtol=rtol)
  325. assert_allclose(f(1.0, q, q, incx=2, offx=2, incy=2, offy=10),
  326. resxy, rtol=rtol)
  327. assert_allclose(f(1.0, q, q, incx=2, offx=2, incy=2, offy=10, n=3),
  328. resxy[:3, :3], rtol=rtol)
  329. # negative increments imply reversed vectors in blas
  330. assert_allclose(f(1.0, q, q, incx=-2, offx=2, incy=-2, offy=10),
  331. resxy_reverse, rtol=rtol)
  332. a = np.zeros((4, 4), 'f' if p == 's' else 'd', 'F')
  333. b = f(1.0, x, y, a=a, overwrite_a=True)
  334. assert_allclose(a, resxy, rtol=rtol)
  335. b = f(2.0, x, y, a=a)
  336. assert_(a is not b)
  337. assert_allclose(b, 3*resxy, rtol=rtol)
  338. assert_raises(Exception, f, 1.0, x, y, incx=0)
  339. assert_raises(Exception, f, 1.0, x, y, offx=5)
  340. assert_raises(Exception, f, 1.0, x, y, offx=-2)
  341. assert_raises(Exception, f, 1.0, x, y, incy=0)
  342. assert_raises(Exception, f, 1.0, x, y, offy=5)
  343. assert_raises(Exception, f, 1.0, x, y, offy=-2)
  344. assert_raises(Exception, f, 1.0, x, y, n=-2)
  345. assert_raises(Exception, f, 1.0, x, y, n=5)
  346. assert_raises(Exception, f, 1.0, x, y, lower=2)
  347. assert_raises(Exception, f, 1.0, x, y,
  348. a=np.zeros((2, 2), 'd', 'F'))
  349. def test_her2(self):
  350. x = np.arange(1, 9, dtype='d').view('D')
  351. y = np.arange(9, 17, dtype='d').view('D')
  352. resxy = x[:, np.newaxis] * y.conj() + y[:, np.newaxis] * x.conj()
  353. resxy = np.triu(resxy)
  354. resxy_reverse = x[::-1, np.newaxis] * y[::-1].conj()
  355. resxy_reverse += y[::-1, np.newaxis] * x[::-1].conj()
  356. resxy_reverse = np.triu(resxy_reverse)
  357. u = np.c_[np.zeros(4), x, np.zeros(4)].ravel()
  358. v = np.c_[np.zeros(4), y, np.zeros(4)].ravel()
  359. for p, rtol in zip('cz', [1e-7, 1e-14]):
  360. f = getattr(fblas, p+'her2', None)
  361. if f is None:
  362. continue
  363. assert_allclose(f(1.0, x, y), resxy, rtol=rtol)
  364. assert_allclose(f(1.0, x, y, n=3), resxy[:3, :3], rtol=rtol)
  365. assert_allclose(f(1.0, x, y, lower=True), resxy.T.conj(),
  366. rtol=rtol)
  367. assert_allclose(f(1.0, u, v, incx=3, offx=1, incy=3, offy=1),
  368. resxy, rtol=rtol)
  369. assert_allclose(f(1.0, u, v, incx=3, offx=1, incy=3, offy=1, n=3),
  370. resxy[:3, :3], rtol=rtol)
  371. # negative increments imply reversed vectors in blas
  372. assert_allclose(f(1.0, u, v, incx=-3, offx=1, incy=-3, offy=1),
  373. resxy_reverse, rtol=rtol)
  374. a = np.zeros((4, 4), 'F' if p == 'c' else 'D', 'F')
  375. b = f(1.0, x, y, a=a, overwrite_a=True)
  376. assert_allclose(a, resxy, rtol=rtol)
  377. b = f(2.0, x, y, a=a)
  378. assert_(a is not b)
  379. assert_allclose(b, 3*resxy, rtol=rtol)
  380. assert_raises(Exception, f, 1.0, x, y, incx=0)
  381. assert_raises(Exception, f, 1.0, x, y, offx=5)
  382. assert_raises(Exception, f, 1.0, x, y, offx=-2)
  383. assert_raises(Exception, f, 1.0, x, y, incy=0)
  384. assert_raises(Exception, f, 1.0, x, y, offy=5)
  385. assert_raises(Exception, f, 1.0, x, y, offy=-2)
  386. assert_raises(Exception, f, 1.0, x, y, n=-2)
  387. assert_raises(Exception, f, 1.0, x, y, n=5)
  388. assert_raises(Exception, f, 1.0, x, y, lower=2)
  389. assert_raises(Exception, f, 1.0, x, y,
  390. a=np.zeros((2, 2), 'd', 'F'))
  391. def test_gbmv(self):
  392. seed(1234)
  393. for ind, dtype in enumerate(DTYPES):
  394. n = 7
  395. m = 5
  396. kl = 1
  397. ku = 2
  398. # fake a banded matrix via toeplitz
  399. A = toeplitz(append(rand(kl+1), zeros(m-kl-1)),
  400. append(rand(ku+1), zeros(n-ku-1)))
  401. A = A.astype(dtype)
  402. Ab = zeros((kl+ku+1, n), dtype=dtype)
  403. # Form the banded storage
  404. Ab[2, :5] = A[0, 0] # diag
  405. Ab[1, 1:6] = A[0, 1] # sup1
  406. Ab[0, 2:7] = A[0, 2] # sup2
  407. Ab[3, :4] = A[1, 0] # sub1
  408. x = rand(n).astype(dtype)
  409. y = rand(m).astype(dtype)
  410. alpha, beta = dtype(3), dtype(-5)
  411. func, = get_blas_funcs(('gbmv',), dtype=dtype)
  412. y1 = func(m=m, n=n, ku=ku, kl=kl, alpha=alpha, a=Ab,
  413. x=x, y=y, beta=beta)
  414. y2 = alpha * A.dot(x) + beta * y
  415. assert_array_almost_equal(y1, y2)
  416. def test_sbmv_hbmv(self):
  417. seed(1234)
  418. for ind, dtype in enumerate(DTYPES):
  419. n = 6
  420. k = 2
  421. A = zeros((n, n), dtype=dtype)
  422. Ab = zeros((k+1, n), dtype=dtype)
  423. # Form the array and its packed banded storage
  424. A[arange(n), arange(n)] = rand(n)
  425. for ind2 in range(1, k+1):
  426. temp = rand(n-ind2)
  427. A[arange(n-ind2), arange(ind2, n)] = temp
  428. Ab[-1-ind2, ind2:] = temp
  429. A = A.astype(dtype)
  430. A = A + A.T if ind < 2 else A + A.conj().T
  431. Ab[-1, :] = diag(A)
  432. x = rand(n).astype(dtype)
  433. y = rand(n).astype(dtype)
  434. alpha, beta = dtype(1.25), dtype(3)
  435. if ind > 1:
  436. func, = get_blas_funcs(('hbmv',), dtype=dtype)
  437. else:
  438. func, = get_blas_funcs(('sbmv',), dtype=dtype)
  439. y1 = func(k=k, alpha=alpha, a=Ab, x=x, y=y, beta=beta)
  440. y2 = alpha * A.dot(x) + beta * y
  441. assert_array_almost_equal(y1, y2)
  442. def test_spmv_hpmv(self):
  443. seed(1234)
  444. for ind, dtype in enumerate(DTYPES+COMPLEX_DTYPES):
  445. n = 3
  446. A = rand(n, n).astype(dtype)
  447. if ind > 1:
  448. A += rand(n, n)*1j
  449. A = A.astype(dtype)
  450. A = A + A.T if ind < 4 else A + A.conj().T
  451. c, r = tril_indices(n)
  452. Ap = A[r, c]
  453. x = rand(n).astype(dtype)
  454. y = rand(n).astype(dtype)
  455. xlong = arange(2*n).astype(dtype)
  456. ylong = ones(2*n).astype(dtype)
  457. alpha, beta = dtype(1.25), dtype(2)
  458. if ind > 3:
  459. func, = get_blas_funcs(('hpmv',), dtype=dtype)
  460. else:
  461. func, = get_blas_funcs(('spmv',), dtype=dtype)
  462. y1 = func(n=n, alpha=alpha, ap=Ap, x=x, y=y, beta=beta)
  463. y2 = alpha * A.dot(x) + beta * y
  464. assert_array_almost_equal(y1, y2)
  465. # Test inc and offsets
  466. y1 = func(n=n-1, alpha=alpha, beta=beta, x=xlong, y=ylong, ap=Ap,
  467. incx=2, incy=2, offx=n, offy=n)
  468. y2 = (alpha * A[:-1, :-1]).dot(xlong[3::2]) + beta * ylong[3::2]
  469. assert_array_almost_equal(y1[3::2], y2)
  470. assert_almost_equal(y1[4], ylong[4])
  471. def test_spr_hpr(self):
  472. seed(1234)
  473. for ind, dtype in enumerate(DTYPES+COMPLEX_DTYPES):
  474. n = 3
  475. A = rand(n, n).astype(dtype)
  476. if ind > 1:
  477. A += rand(n, n)*1j
  478. A = A.astype(dtype)
  479. A = A + A.T if ind < 4 else A + A.conj().T
  480. c, r = tril_indices(n)
  481. Ap = A[r, c]
  482. x = rand(n).astype(dtype)
  483. alpha = (DTYPES+COMPLEX_DTYPES)[mod(ind, 4)](2.5)
  484. if ind > 3:
  485. func, = get_blas_funcs(('hpr',), dtype=dtype)
  486. y2 = alpha * x[:, None].dot(x[None, :].conj()) + A
  487. else:
  488. func, = get_blas_funcs(('spr',), dtype=dtype)
  489. y2 = alpha * x[:, None].dot(x[None, :]) + A
  490. y1 = func(n=n, alpha=alpha, ap=Ap, x=x)
  491. y1f = zeros((3, 3), dtype=dtype)
  492. y1f[r, c] = y1
  493. y1f[c, r] = y1.conj() if ind > 3 else y1
  494. assert_array_almost_equal(y1f, y2)
  495. def test_spr2_hpr2(self):
  496. seed(1234)
  497. for ind, dtype in enumerate(DTYPES):
  498. n = 3
  499. A = rand(n, n).astype(dtype)
  500. if ind > 1:
  501. A += rand(n, n)*1j
  502. A = A.astype(dtype)
  503. A = A + A.T if ind < 2 else A + A.conj().T
  504. c, r = tril_indices(n)
  505. Ap = A[r, c]
  506. x = rand(n).astype(dtype)
  507. y = rand(n).astype(dtype)
  508. alpha = dtype(2)
  509. if ind > 1:
  510. func, = get_blas_funcs(('hpr2',), dtype=dtype)
  511. else:
  512. func, = get_blas_funcs(('spr2',), dtype=dtype)
  513. u = alpha.conj() * x[:, None].dot(y[None, :].conj())
  514. y2 = A + u + u.conj().T
  515. y1 = func(n=n, alpha=alpha, x=x, y=y, ap=Ap)
  516. y1f = zeros((3, 3), dtype=dtype)
  517. y1f[r, c] = y1
  518. y1f[[1, 2, 2], [0, 0, 1]] = y1[[1, 3, 4]].conj()
  519. assert_array_almost_equal(y1f, y2)
  520. def test_tbmv(self):
  521. seed(1234)
  522. for ind, dtype in enumerate(DTYPES):
  523. n = 10
  524. k = 3
  525. x = rand(n).astype(dtype)
  526. A = zeros((n, n), dtype=dtype)
  527. # Banded upper triangular array
  528. for sup in range(k+1):
  529. A[arange(n-sup), arange(sup, n)] = rand(n-sup)
  530. # Add complex parts for c,z
  531. if ind > 1:
  532. A[nonzero(A)] += 1j * rand((k+1)*n-(k*(k+1)//2)).astype(dtype)
  533. # Form the banded storage
  534. Ab = zeros((k+1, n), dtype=dtype)
  535. for row in range(k+1):
  536. Ab[-row-1, row:] = diag(A, k=row)
  537. func, = get_blas_funcs(('tbmv',), dtype=dtype)
  538. y1 = func(k=k, a=Ab, x=x)
  539. y2 = A.dot(x)
  540. assert_array_almost_equal(y1, y2)
  541. y1 = func(k=k, a=Ab, x=x, diag=1)
  542. A[arange(n), arange(n)] = dtype(1)
  543. y2 = A.dot(x)
  544. assert_array_almost_equal(y1, y2)
  545. y1 = func(k=k, a=Ab, x=x, diag=1, trans=1)
  546. y2 = A.T.dot(x)
  547. assert_array_almost_equal(y1, y2)
  548. y1 = func(k=k, a=Ab, x=x, diag=1, trans=2)
  549. y2 = A.conj().T.dot(x)
  550. assert_array_almost_equal(y1, y2)
  551. def test_tbsv(self):
  552. seed(1234)
  553. for ind, dtype in enumerate(DTYPES):
  554. n = 6
  555. k = 3
  556. x = rand(n).astype(dtype)
  557. A = zeros((n, n), dtype=dtype)
  558. # Banded upper triangular array
  559. for sup in range(k+1):
  560. A[arange(n-sup), arange(sup, n)] = rand(n-sup)
  561. # Add complex parts for c,z
  562. if ind > 1:
  563. A[nonzero(A)] += 1j * rand((k+1)*n-(k*(k+1)//2)).astype(dtype)
  564. # Form the banded storage
  565. Ab = zeros((k+1, n), dtype=dtype)
  566. for row in range(k+1):
  567. Ab[-row-1, row:] = diag(A, k=row)
  568. func, = get_blas_funcs(('tbsv',), dtype=dtype)
  569. y1 = func(k=k, a=Ab, x=x)
  570. y2 = solve(A, x)
  571. assert_array_almost_equal(y1, y2)
  572. y1 = func(k=k, a=Ab, x=x, diag=1)
  573. A[arange(n), arange(n)] = dtype(1)
  574. y2 = solve(A, x)
  575. assert_array_almost_equal(y1, y2)
  576. y1 = func(k=k, a=Ab, x=x, diag=1, trans=1)
  577. y2 = solve(A.T, x)
  578. assert_array_almost_equal(y1, y2)
  579. y1 = func(k=k, a=Ab, x=x, diag=1, trans=2)
  580. y2 = solve(A.conj().T, x)
  581. assert_array_almost_equal(y1, y2)
  582. def test_tpmv(self):
  583. seed(1234)
  584. for ind, dtype in enumerate(DTYPES):
  585. n = 10
  586. x = rand(n).astype(dtype)
  587. # Upper triangular array
  588. A = triu(rand(n, n)) if ind < 2 else triu(rand(n, n)+rand(n, n)*1j)
  589. # Form the packed storage
  590. c, r = tril_indices(n)
  591. Ap = A[r, c]
  592. func, = get_blas_funcs(('tpmv',), dtype=dtype)
  593. y1 = func(n=n, ap=Ap, x=x)
  594. y2 = A.dot(x)
  595. assert_array_almost_equal(y1, y2)
  596. y1 = func(n=n, ap=Ap, x=x, diag=1)
  597. A[arange(n), arange(n)] = dtype(1)
  598. y2 = A.dot(x)
  599. assert_array_almost_equal(y1, y2)
  600. y1 = func(n=n, ap=Ap, x=x, diag=1, trans=1)
  601. y2 = A.T.dot(x)
  602. assert_array_almost_equal(y1, y2)
  603. y1 = func(n=n, ap=Ap, x=x, diag=1, trans=2)
  604. y2 = A.conj().T.dot(x)
  605. assert_array_almost_equal(y1, y2)
  606. def test_tpsv(self):
  607. seed(1234)
  608. for ind, dtype in enumerate(DTYPES):
  609. n = 10
  610. x = rand(n).astype(dtype)
  611. # Upper triangular array
  612. A = triu(rand(n, n)) if ind < 2 else triu(rand(n, n)+rand(n, n)*1j)
  613. A += eye(n)
  614. # Form the packed storage
  615. c, r = tril_indices(n)
  616. Ap = A[r, c]
  617. func, = get_blas_funcs(('tpsv',), dtype=dtype)
  618. y1 = func(n=n, ap=Ap, x=x)
  619. y2 = solve(A, x)
  620. assert_array_almost_equal(y1, y2)
  621. y1 = func(n=n, ap=Ap, x=x, diag=1)
  622. A[arange(n), arange(n)] = dtype(1)
  623. y2 = solve(A, x)
  624. assert_array_almost_equal(y1, y2)
  625. y1 = func(n=n, ap=Ap, x=x, diag=1, trans=1)
  626. y2 = solve(A.T, x)
  627. assert_array_almost_equal(y1, y2)
  628. y1 = func(n=n, ap=Ap, x=x, diag=1, trans=2)
  629. y2 = solve(A.conj().T, x)
  630. assert_array_almost_equal(y1, y2)
  631. def test_trmv(self):
  632. seed(1234)
  633. for ind, dtype in enumerate(DTYPES):
  634. n = 3
  635. A = (rand(n, n)+eye(n)).astype(dtype)
  636. x = rand(3).astype(dtype)
  637. func, = get_blas_funcs(('trmv',), dtype=dtype)
  638. y1 = func(a=A, x=x)
  639. y2 = triu(A).dot(x)
  640. assert_array_almost_equal(y1, y2)
  641. y1 = func(a=A, x=x, diag=1)
  642. A[arange(n), arange(n)] = dtype(1)
  643. y2 = triu(A).dot(x)
  644. assert_array_almost_equal(y1, y2)
  645. y1 = func(a=A, x=x, diag=1, trans=1)
  646. y2 = triu(A).T.dot(x)
  647. assert_array_almost_equal(y1, y2)
  648. y1 = func(a=A, x=x, diag=1, trans=2)
  649. y2 = triu(A).conj().T.dot(x)
  650. assert_array_almost_equal(y1, y2)
  651. def test_trsv(self):
  652. seed(1234)
  653. for ind, dtype in enumerate(DTYPES):
  654. n = 15
  655. A = (rand(n, n)+eye(n)).astype(dtype)
  656. x = rand(n).astype(dtype)
  657. func, = get_blas_funcs(('trsv',), dtype=dtype)
  658. y1 = func(a=A, x=x)
  659. y2 = solve(triu(A), x)
  660. assert_array_almost_equal(y1, y2)
  661. y1 = func(a=A, x=x, lower=1)
  662. y2 = solve(tril(A), x)
  663. assert_array_almost_equal(y1, y2)
  664. y1 = func(a=A, x=x, diag=1)
  665. A[arange(n), arange(n)] = dtype(1)
  666. y2 = solve(triu(A), x)
  667. assert_array_almost_equal(y1, y2)
  668. y1 = func(a=A, x=x, diag=1, trans=1)
  669. y2 = solve(triu(A).T, x)
  670. assert_array_almost_equal(y1, y2)
  671. y1 = func(a=A, x=x, diag=1, trans=2)
  672. y2 = solve(triu(A).conj().T, x)
  673. assert_array_almost_equal(y1, y2)
  674. class TestFBLAS3Simple(object):
  675. def test_gemm(self):
  676. for p in 'sd':
  677. f = getattr(fblas, p+'gemm', None)
  678. if f is None:
  679. continue
  680. assert_array_almost_equal(f(3, [3], [-4]), [[-36]])
  681. assert_array_almost_equal(f(3, [3], [-4], 3, [5]), [-21])
  682. for p in 'cz':
  683. f = getattr(fblas, p+'gemm', None)
  684. if f is None:
  685. continue
  686. assert_array_almost_equal(f(3j, [3-4j], [-4]), [[-48-36j]])
  687. assert_array_almost_equal(f(3j, [3-4j], [-4], 3, [5j]), [-48-21j])
  688. def _get_func(func, ps='sdzc'):
  689. """Just a helper: return a specified BLAS function w/typecode."""
  690. for p in ps:
  691. f = getattr(fblas, p+func, None)
  692. if f is None:
  693. continue
  694. yield f
  695. class TestBLAS3Symm(object):
  696. def setup_method(self):
  697. self.a = np.array([[1., 2.],
  698. [0., 1.]])
  699. self.b = np.array([[1., 0., 3.],
  700. [0., -1., 2.]])
  701. self.c = np.ones((2, 3))
  702. self.t = np.array([[2., -1., 8.],
  703. [3., 0., 9.]])
  704. def test_symm(self):
  705. for f in _get_func('symm'):
  706. res = f(a=self.a, b=self.b, c=self.c, alpha=1., beta=1.)
  707. assert_array_almost_equal(res, self.t)
  708. res = f(a=self.a.T, b=self.b, lower=1, c=self.c, alpha=1., beta=1.)
  709. assert_array_almost_equal(res, self.t)
  710. res = f(a=self.a, b=self.b.T, side=1, c=self.c.T,
  711. alpha=1., beta=1.)
  712. assert_array_almost_equal(res, self.t.T)
  713. def test_summ_wrong_side(self):
  714. f = getattr(fblas, 'dsymm', None)
  715. if f is not None:
  716. assert_raises(Exception, f, **{'a': self.a, 'b': self.b,
  717. 'alpha': 1, 'side': 1})
  718. # `side=1` means C <- B*A, hence shapes of A and B are to be
  719. # compatible. Otherwise, f2py exception is raised
  720. def test_symm_wrong_uplo(self):
  721. """SYMM only considers the upper/lower part of A. Hence setting
  722. wrong value for `lower` (default is lower=0, meaning upper triangle)
  723. gives a wrong result.
  724. """
  725. f = getattr(fblas, 'dsymm', None)
  726. if f is not None:
  727. res = f(a=self.a, b=self.b, c=self.c, alpha=1., beta=1.)
  728. assert np.allclose(res, self.t)
  729. res = f(a=self.a, b=self.b, lower=1, c=self.c, alpha=1., beta=1.)
  730. assert not np.allclose(res, self.t)
  731. class TestBLAS3Syrk(object):
  732. def setup_method(self):
  733. self.a = np.array([[1., 0.],
  734. [0., -2.],
  735. [2., 3.]])
  736. self.t = np.array([[1., 0., 2.],
  737. [0., 4., -6.],
  738. [2., -6., 13.]])
  739. self.tt = np.array([[5., 6.],
  740. [6., 13.]])
  741. def test_syrk(self):
  742. for f in _get_func('syrk'):
  743. c = f(a=self.a, alpha=1.)
  744. assert_array_almost_equal(np.triu(c), np.triu(self.t))
  745. c = f(a=self.a, alpha=1., lower=1)
  746. assert_array_almost_equal(np.tril(c), np.tril(self.t))
  747. c0 = np.ones(self.t.shape)
  748. c = f(a=self.a, alpha=1., beta=1., c=c0)
  749. assert_array_almost_equal(np.triu(c), np.triu(self.t+c0))
  750. c = f(a=self.a, alpha=1., trans=1)
  751. assert_array_almost_equal(np.triu(c), np.triu(self.tt))
  752. # prints '0-th dimension must be fixed to 3 but got 5',
  753. # FIXME: suppress?
  754. # FIXME: how to catch the _fblas.error?
  755. def test_syrk_wrong_c(self):
  756. f = getattr(fblas, 'dsyrk', None)
  757. if f is not None:
  758. assert_raises(Exception, f, **{'a': self.a, 'alpha': 1.,
  759. 'c': np.ones((5, 8))})
  760. # if C is supplied, it must have compatible dimensions
  761. class TestBLAS3Syr2k(object):
  762. def setup_method(self):
  763. self.a = np.array([[1., 0.],
  764. [0., -2.],
  765. [2., 3.]])
  766. self.b = np.array([[0., 1.],
  767. [1., 0.],
  768. [0, 1.]])
  769. self.t = np.array([[0., -1., 3.],
  770. [-1., 0., 0.],
  771. [3., 0., 6.]])
  772. self.tt = np.array([[0., 1.],
  773. [1., 6]])
  774. def test_syr2k(self):
  775. for f in _get_func('syr2k'):
  776. c = f(a=self.a, b=self.b, alpha=1.)
  777. assert_array_almost_equal(np.triu(c), np.triu(self.t))
  778. c = f(a=self.a, b=self.b, alpha=1., lower=1)
  779. assert_array_almost_equal(np.tril(c), np.tril(self.t))
  780. c0 = np.ones(self.t.shape)
  781. c = f(a=self.a, b=self.b, alpha=1., beta=1., c=c0)
  782. assert_array_almost_equal(np.triu(c), np.triu(self.t+c0))
  783. c = f(a=self.a, b=self.b, alpha=1., trans=1)
  784. assert_array_almost_equal(np.triu(c), np.triu(self.tt))
  785. # prints '0-th dimension must be fixed to 3 but got 5', FIXME: suppress?
  786. def test_syr2k_wrong_c(self):
  787. f = getattr(fblas, 'dsyr2k', None)
  788. if f is not None:
  789. assert_raises(Exception, f, **{'a': self.a,
  790. 'b': self.b,
  791. 'alpha': 1.,
  792. 'c': np.zeros((15, 8))})
  793. # if C is supplied, it must have compatible dimensions
  794. class TestSyHe(object):
  795. """Quick and simple tests for (zc)-symm, syrk, syr2k."""
  796. def setup_method(self):
  797. self.sigma_y = np.array([[0., -1.j],
  798. [1.j, 0.]])
  799. def test_symm_zc(self):
  800. for f in _get_func('symm', 'zc'):
  801. # NB: a is symmetric w/upper diag of ONLY
  802. res = f(a=self.sigma_y, b=self.sigma_y, alpha=1.)
  803. assert_array_almost_equal(np.triu(res), np.diag([1, -1]))
  804. def test_hemm_zc(self):
  805. for f in _get_func('hemm', 'zc'):
  806. # NB: a is hermitian w/upper diag of ONLY
  807. res = f(a=self.sigma_y, b=self.sigma_y, alpha=1.)
  808. assert_array_almost_equal(np.triu(res), np.diag([1, 1]))
  809. def test_syrk_zr(self):
  810. for f in _get_func('syrk', 'zc'):
  811. res = f(a=self.sigma_y, alpha=1.)
  812. assert_array_almost_equal(np.triu(res), np.diag([-1, -1]))
  813. def test_herk_zr(self):
  814. for f in _get_func('herk', 'zc'):
  815. res = f(a=self.sigma_y, alpha=1.)
  816. assert_array_almost_equal(np.triu(res), np.diag([1, 1]))
  817. def test_syr2k_zr(self):
  818. for f in _get_func('syr2k', 'zc'):
  819. res = f(a=self.sigma_y, b=self.sigma_y, alpha=1.)
  820. assert_array_almost_equal(np.triu(res), 2.*np.diag([-1, -1]))
  821. def test_her2k_zr(self):
  822. for f in _get_func('her2k', 'zc'):
  823. res = f(a=self.sigma_y, b=self.sigma_y, alpha=1.)
  824. assert_array_almost_equal(np.triu(res), 2.*np.diag([1, 1]))
  825. class TestTRMM(object):
  826. """Quick and simple tests for dtrmm."""
  827. def setup_method(self):
  828. self.a = np.array([[1., 2., ],
  829. [-2., 1.]])
  830. self.b = np.array([[3., 4., -1.],
  831. [5., 6., -2.]])
  832. def test_ab(self):
  833. f = getattr(fblas, 'dtrmm', None)
  834. if f is not None:
  835. result = f(1., self.a, self.b)
  836. # default a is upper triangular
  837. expected = np.array([[13., 16., -5.],
  838. [5., 6., -2.]])
  839. assert_array_almost_equal(result, expected)
  840. def test_ab_lower(self):
  841. f = getattr(fblas, 'dtrmm', None)
  842. if f is not None:
  843. result = f(1., self.a, self.b, lower=True)
  844. expected = np.array([[3., 4., -1.],
  845. [-1., -2., 0.]]) # now a is lower triangular
  846. assert_array_almost_equal(result, expected)
  847. def test_b_overwrites(self):
  848. # BLAS dtrmm modifies B argument in-place.
  849. # Here the default is to copy, but this can be overridden
  850. f = getattr(fblas, 'dtrmm', None)
  851. if f is not None:
  852. for overwr in [True, False]:
  853. bcopy = self.b.copy()
  854. result = f(1., self.a, bcopy, overwrite_b=overwr)
  855. # C-contiguous arrays are copied
  856. assert_(bcopy.flags.f_contiguous is False and
  857. np.may_share_memory(bcopy, result) is False)
  858. assert_equal(bcopy, self.b)
  859. bcopy = np.asfortranarray(self.b.copy()) # or just transpose it
  860. result = f(1., self.a, bcopy, overwrite_b=True)
  861. assert_(bcopy.flags.f_contiguous is True and
  862. np.may_share_memory(bcopy, result) is True)
  863. assert_array_almost_equal(bcopy, result)
  864. def test_trsm():
  865. seed(1234)
  866. for ind, dtype in enumerate(DTYPES):
  867. tol = np.finfo(dtype).eps*1000
  868. func, = get_blas_funcs(('trsm',), dtype=dtype)
  869. # Test protection against size mismatches
  870. A = rand(4, 5).astype(dtype)
  871. B = rand(4, 4).astype(dtype)
  872. alpha = dtype(1)
  873. assert_raises(Exception, func, alpha, A, B)
  874. assert_raises(Exception, func, alpha, A.T, B)
  875. n = 8
  876. m = 7
  877. alpha = dtype(-2.5)
  878. A = (rand(m, m) if ind < 2 else rand(m, m) + rand(m, m)*1j) + eye(m)
  879. A = A.astype(dtype)
  880. Au = triu(A)
  881. Al = tril(A)
  882. B1 = rand(m, n).astype(dtype)
  883. B2 = rand(n, m).astype(dtype)
  884. x1 = func(alpha=alpha, a=A, b=B1)
  885. assert_equal(B1.shape, x1.shape)
  886. x2 = solve(Au, alpha*B1)
  887. assert_allclose(x1, x2, atol=tol)
  888. x1 = func(alpha=alpha, a=A, b=B1, trans_a=1)
  889. x2 = solve(Au.T, alpha*B1)
  890. assert_allclose(x1, x2, atol=tol)
  891. x1 = func(alpha=alpha, a=A, b=B1, trans_a=2)
  892. x2 = solve(Au.conj().T, alpha*B1)
  893. assert_allclose(x1, x2, atol=tol)
  894. x1 = func(alpha=alpha, a=A, b=B1, diag=1)
  895. Au[arange(m), arange(m)] = dtype(1)
  896. x2 = solve(Au, alpha*B1)
  897. assert_allclose(x1, x2, atol=tol)
  898. x1 = func(alpha=alpha, a=A, b=B2, diag=1, side=1)
  899. x2 = solve(Au.conj().T, alpha*B2.conj().T)
  900. assert_allclose(x1, x2.conj().T, atol=tol)
  901. x1 = func(alpha=alpha, a=A, b=B2, diag=1, side=1, lower=1)
  902. Al[arange(m), arange(m)] = dtype(1)
  903. x2 = solve(Al.conj().T, alpha*B2.conj().T)
  904. assert_allclose(x1, x2.conj().T, atol=tol)