racket/collects/math/private/matrix/matrix-qr.rkt
Neil Toronto f5fa93572d Moar `math/matrix' review/refactoring
* Gram-Schmidt using vector type

* QR decomposition

* Operator 1-norm and maximum norm; stub for 2-norm and angle between
  subspaces (`matrix-basis-angle')

* `matrix-absolute-error' and `matrix-relative-error'; also predicates
  based on them, such as `matrix-identity?'

* Lots of shuffling code about

* Types that can have contracts, and an exhaustive test to make sure
  every value exported by `math/matrix' has a contract when used in
  untyped code

* Some more tests (still needs some)
2012-12-31 14:17:17 -07:00

40 lines
1.5 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")
(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 (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 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))))