racket/collects/math/private/matrix/matrix-qr.rkt
Neil Toronto a1aa97c1fd `math/matrix' fixes; please merge to 5.3.2.
* Fixed type of `matrix-expt'

* Made matrix functions respect `array-strictness' parameter (mostly
  wrapping functions with `parameterize' and return values with
  `array-default-strictness'; reindentation makes changes look larger)

* Added strictness tests
(cherry picked from commit f40ad2ca9d)
2013-01-18 15:55:34 -05:00

49 lines
1.9 KiB
Racket

#lang typed/racket/base
(require "matrix-types.rkt"
"matrix-basic.rkt"
"matrix-arithmetic.rkt"
"matrix-constructors.rkt"
"matrix-gram-schmidt.rkt"
"../array/array-transform.rkt"
"../array/array-struct.rkt")
(provide matrix-qr)
#|
QR decomposition currently does Gram-Schmidt twice, as suggested by
Luc Giraud, Julien Langou, Miroslav Rozloznik.
On the round-off error analysis of the Gram-Schmidt algorithm with reorthogonalization.
Technical Report, 2002.
It normalizes only the second time.
I've verified experimentally that, with random, square matrices (elements in [0,1]), doing so
produces matrices for which `matrix-orthogonal?' returns #t with eps <= 10*epsilon.0, apparently
independently of the matrix size.
|#
(: matrix-qr/ns (case-> ((Matrix Real) Any -> (Values (Matrix Real) (Matrix Real)))
((Matrix Number) Any -> (Values (Matrix Number) (Matrix Number)))))
(define (matrix-qr/ns M full?)
(define B (matrix-gram-schmidt M #f))
(define Q
(matrix-gram-schmidt
(cond [(or (square-matrix? B) (and (matrix? B) (not full?))) B]
[(matrix? B) (array-append* (list B (matrix-basis-extension B)) 1)]
[full? (identity-matrix (matrix-num-rows M))]
[else (matrix-col (identity-matrix (matrix-num-rows M)) 0)])
#t))
(values Q (matrix-upper-triangle (matrix* (matrix-hermitian Q) M))))
(: matrix-qr (case-> ((Matrix Real) -> (Values (Matrix Real) (Matrix Real)))
((Matrix Real) Any -> (Values (Matrix Real) (Matrix Real)))
((Matrix Number) -> (Values (Matrix Number) (Matrix Number)))
((Matrix Number) Any -> (Values (Matrix Number) (Matrix Number)))))
(define (matrix-qr M [full? #t])
(define-values (Q R) (parameterize ([array-strictness #f])
(matrix-qr/ns M full?)))
(values (array-default-strict Q)
(array-default-strict R)))