|
241 | 241 | (from-array smat (list u-cols vt-rows) :input-layout :column-major)
|
242 | 242 | (from-array vt (list vt-rows cols) :input-layout :column-major)))))))
|
243 | 243 |
|
244 |
| -;; TODO: This returns only the real parts when with non-complex |
245 |
| -;; numbers. Should do something different? |
246 | 244 | (defun generate-lapack-eig-for-type (class type eig-function &optional real-type)
|
247 | 245 | ` (defmethod lapack-eig ((m ,class))
|
248 | 246 | (policy-cond:with-expectations (> speed safety)
|
|
273 | 271 | ;; run it again with optimal workspace size
|
274 | 272 | (,eig-function jobvl jobvr rows a rows ,@(if real-type `(w) `(wr wi))
|
275 | 273 | vl 1 vr rows work lwork ,@(when real-type `(rwork)) info)
|
276 |
| - (values (coerce ,@(if real-type `(w) `(wr)) 'list) (from-array vr (list rows cols) :input-layout :column-major)))))))) |
| 274 | + ,(if real-type |
| 275 | + `(values (coerce w 'list) |
| 276 | + (from-array vr (list rows cols) :input-layout :column-major)) |
| 277 | + `(values (cl:map 'list (lambda (a b) |
| 278 | + (if (zerop b) |
| 279 | + a |
| 280 | + (complex a b))) |
| 281 | + wr wi) |
| 282 | + (let* ((evecs (magicl:zeros (list rows cols) :type '(complex ,type))) |
| 283 | + (storage (magicl::storage evecs))) |
| 284 | + ;; square matrix |
| 285 | + (loop :with col-lapack := 0 |
| 286 | + :with col-result := 0 |
| 287 | + :with skip := nil |
| 288 | + :for zr :across wr |
| 289 | + :for zi :across wi |
| 290 | + :do (cond |
| 291 | + ;; real eigenvalue |
| 292 | + ((zerop zi) |
| 293 | + (when skip |
| 294 | + (warn "SKIP is T when we reached a real eigenvalue.")) |
| 295 | + (dotimes (r rows) |
| 296 | + ;; column-major |
| 297 | + (setf (aref storage (+ r (* col-result rows))) |
| 298 | + (complex (aref vr (+ r (* col-lapack rows)))))) |
| 299 | + (incf col-result) |
| 300 | + (incf col-lapack)) |
| 301 | + ;; complex eigenvalue with conjugate |
| 302 | + (skip |
| 303 | + (unless (cl:= skip (- zi)) |
| 304 | + (error "Reached a non-conjugate eigenvalue")) |
| 305 | + (setf skip nil)) |
| 306 | + ;; New complex eigenvalue |
| 307 | + (t |
| 308 | + ;; expect a conjugate in the next iteration |
| 309 | + (setf skip zi) |
| 310 | + (dotimes (r rows) |
| 311 | + ;; column-major |
| 312 | + (setf (aref storage (+ r (* col-result rows))) |
| 313 | + (complex |
| 314 | + (aref vr (+ r (* col-lapack rows))) |
| 315 | + (aref vr (+ r (* (1+ col-lapack) rows))))) |
| 316 | + (setf (aref storage (+ r (* (1+ col-result) rows))) |
| 317 | + (complex |
| 318 | + (aref vr (+ r (* col-lapack rows))) |
| 319 | + (- (aref vr (+ r (* (1+ col-lapack) rows))))))) |
| 320 | + (incf col-result 2) |
| 321 | + (incf col-lapack 2))) |
| 322 | + :finally (return evecs))))))))))) |
277 | 323 |
|
278 | 324 | (defun generate-lapack-hermitian-eig-for-type (class type eig-function real-type)
|
279 | 325 | `(defmethod lapack-hermitian-eig ((m ,class))
|
|
0 commit comments