Skip to content

Commit 2e6f9c6

Browse files
committed
fix qrDecompose
1 parent 27094a5 commit 2e6f9c6

File tree

12 files changed

+1457
-337
lines changed

12 files changed

+1457
-337
lines changed
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
namespace FSharp.Stats.Algebra
2+
3+
4+
open System
5+
open FSharp.Stats
6+
open FSharp.Stats.Acceleration
7+
8+
[<Struct>]
9+
type Householder<'T when 'T :> Numerics.INumber<'T>> =
10+
{
11+
V: Vector<'T>
12+
Tau: 'T
13+
Beta: 'T
14+
}
15+
16+
17+
type Householder() =
18+
19+
static member inline create<'T when 'T :> Numerics.INumber<'T>
20+
and 'T : (new: unit -> 'T)
21+
and 'T : struct
22+
and 'T : comparison
23+
and 'T :> ValueType
24+
and 'T :> Numerics.IRootFunctions<'T>>
25+
(x: Vector<'T>) : Householder<'T> =
26+
27+
let xSpan = x.AsSpan()
28+
let alpha = xSpan[0]
29+
let tail = xSpan.Slice(1)
30+
31+
let zero = GenericMath.zero<'T>
32+
let one = GenericMath.one<'T>
33+
34+
let sigma =
35+
SIMDUtils.mapFoldUnchecked(
36+
(fun v -> v * v),
37+
(fun x -> x * x),
38+
(+),
39+
(+),
40+
zero,
41+
tail
42+
)
43+
44+
if sigma.Equals(zero) then
45+
let v = Vector.zeroCreate x.Length
46+
v.[0] <- one
47+
{
48+
V = v
49+
Tau = zero
50+
Beta = alpha
51+
}
52+
else
53+
let sum = alpha * alpha + sigma
54+
let beta = GenericMath.sqrt sum
55+
56+
let v0 =
57+
if alpha <= zero then alpha - beta
58+
else -sigma / (alpha + beta)
59+
60+
let tau =
61+
let v0Sq = v0 * v0
62+
(v0Sq + v0Sq) / (sigma + v0Sq)
63+
64+
let v = Vector.divideScalar v0 x // SIMD-aware scalar division
65+
v.[0] <- one
66+
67+
{
68+
V = v
69+
Tau = tau
70+
Beta = beta
71+
}
72+
73+
static member inline applyLeft<'T when 'T :> Numerics.INumber<'T>
74+
and 'T : (new: unit -> 'T)
75+
and 'T : struct
76+
and 'T : equality
77+
and 'T :> ValueType>
78+
(h: Householder<'T>, A: Matrix<'T>, rowOffset: int) =
79+
80+
let v = h.V
81+
let tau = h.Tau
82+
let m = A.NumRows
83+
let n = A.NumCols
84+
let vLen = v.Length
85+
86+
//for j = 0 to n - 1 do
87+
// let mutable dot = GenericMath.zero<'T>
88+
// for i = 0 to vLen - 1 do
89+
// dot <- dot + v.[i] * A.[rowOffset + i, j]
90+
// let scale = tau * dot
91+
// for i = 0 to vLen - 1 do
92+
// A.[rowOffset + i, j] <- A.[rowOffset + i, j] - scale * v.[i]
93+
94+
for j = 0 to n - 1 do
95+
let mutable dot = GenericMath.zero<'T>
96+
for i = 0 to vLen - 1 do
97+
let row = rowOffset + i
98+
if row < m then
99+
dot <- dot + v.[i] * A.[row, j]
100+
let scale = tau * dot
101+
for i = 0 to vLen - 1 do
102+
let row = rowOffset + i
103+
if row < m then
104+
A.[row, j] <- A.[row, j] - scale * v.[i]
105+
106+
107+
static member inline applyRight<'T when 'T :> Numerics.INumber<'T>
108+
and 'T : (new: unit -> 'T)
109+
and 'T : struct
110+
and 'T : equality
111+
and 'T :> ValueType>
112+
(h: Householder<'T>, A: Matrix<'T>, colOffset: int) =
113+
114+
let v = h.V
115+
let tau = h.Tau
116+
let m = A.NumRows
117+
let vLen = v.Length
118+
119+
for i = 0 to m - 1 do
120+
let mutable dot = GenericMath.zero<'T>
121+
for j = 0 to vLen - 1 do
122+
dot <- dot + A.[i, colOffset + j] * v.[j]
123+
let scale = tau * dot
124+
for j = 0 to vLen - 1 do
125+
A.[i, colOffset + j] <- A.[i, colOffset + j] - scale * v.[j]
126+

src/FSharp.Stats/AlgTypes/Vector.fs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ open System.Runtime.InteropServices
66
/// Vector as an array type alias
77
type Vector<'T when 'T :> Numerics.INumber<'T>> = 'T []
88

9+
910
type Vector =
1011

1112

@@ -23,6 +24,7 @@ type Vector =
2324
and 'T : struct
2425
and 'T :> ValueType> (v1 : Vector<'T>) (v2 : Vector<'T>) : Vector<'T> =
2526

27+
2628
if v1.Length <> v2.Length then
2729
invalidArg "" "Cannot add two vectors of different dimensions."
2830

src/FSharp.Stats/AlgTypes/VectorExt.fs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -214,3 +214,13 @@ module Vector =
214214
///
215215
let inline pow (power: 'T) (v:Vector<'T>) : Vector<'T> =
216216
v |> Array.map (fun x -> GenericMath.pow x power)
217+
218+
219+
/// Returns a subvector from offset i to the end of the vector.
220+
let inline sub (i: int) (v: Vector<'T>) : Vector<'T> =
221+
if i < 0 || i > v.Length then
222+
invalidArg (nameof i) "Index out of bounds."
223+
let len = v.Length - i
224+
let res = Array.zeroCreate<'T> len
225+
Array.blit v i res 0 len
226+
res

0 commit comments

Comments
 (0)