-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathVector.cs
133 lines (121 loc) · 4.76 KB
/
Vector.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
using System;
using System.Linq;
namespace JA
{
public record Vector(params double[] Elements) : IQuantity
{
public static readonly Vector Empty = Array.Empty<double>();
public static implicit operator Vector(double[] array) => new (array);
public static implicit operator double[](Vector vector) => vector.Elements;
public Vector(int size) : this(CreateVector(size)) { }
public Vector(int size, Func<int, double> initializer) : this(CreateVector(size, initializer)) { }
static double[] CreateVector(int size, Func<int, double> initializer = null)
{
var result = new double[size];
if (initializer!=null)
{
for (int i = 0; i < result.Length; i++)
{
result[i] = initializer(i);
}
}
return result;
}
public static Vector Zero(int size) => new(size);
public static Vector Elemental(int size, int oneIndex)
=> new(size, (i) => i==oneIndex ? 1 : 0);
public static Vector Block(Vector vector, double scalar)
{
var result = new double[vector.Size+1];
Array.Copy(vector.Elements, result, vector.Size);
result[^1] = scalar;
return new Vector(result);
}
public bool GetBlock(out Vector vector, out double scalar)
{
if (Size>1)
{
vector = Elements[..^1];
scalar = Elements[^1];
return true;
}
vector = null;
scalar = 0;
return false;
}
public int Rank { get => 1; }
public int Size { get => Elements.Length; }
double IQuantity.Value { get => 0; }
double[] IQuantity.Array { get => Elements; }
double[][] IQuantity.Array2 { get => new[] { Elements }; }
public ref double this[Index index] => ref Elements[index];
public double[] this[Range range] => Elements[range];
public ReadOnlySpan<double> AsSpan() => AsSpan(Range.All);
public ReadOnlySpan<double> AsSpan(Range range)
{
var (offset, length)= range.GetOffsetAndLength(Elements.Length);
return new ReadOnlySpan<double>(Elements, offset, length);
}
public double[] Slice(int start, int length)
{
var slice = new double[length];
Array.Copy(Elements, start, slice, 0, length);
return slice;
}
#region Formatting
public override string ToString() => ToString("g");
public string ToString(string formatting) => ToString(formatting, null);
public string ToString(string formatting, IFormatProvider formatProvider)
=> $"[{string.Join(",", Elements.Select((x) => x.ToString(formatting, formatProvider)))}]";
#endregion
#region Algebra
public static Vector Add(Vector A, Vector B)
{
var result = new double[A.Elements.Length];
for (int i = 0; i < result.Length; i++)
{
result[i] = A.Elements[i] + B.Elements[i];
}
return new Vector(result);
}
public static Vector Subtract(Vector A, Vector B)
{
var result = new double[A.Elements.Length];
for (int i = 0; i < result.Length; i++)
{
result[i] = A.Elements[i] - B.Elements[i];
}
return new Vector(result);
}
public static Vector Scale(double factor, Vector A)
{
var result = new double[A.Elements.Length];
for (int i = 0; i < result.Length; i++)
{
result[i] = factor * A.Elements[i];
}
return new Vector(result);
}
public static double Dot(Vector A, Vector B)
{
double sum = 0;
for (int i = 0; i < A.Elements.Length; i++)
{
sum += A.Elements[i]*B.Elements[i];
}
return sum;
}
public static Matrix Outer(Vector A, Vector B) => new(A.Size, B.Size, (i, j)
=> A.Elements[i]*B.Elements[j]);
#endregion
#region Operators
public static Vector operator +(Vector a, Vector b) => Add(a, b);
public static Vector operator -(Vector a) => Scale(-1, a);
public static Vector operator -(Vector a, Vector b) => Subtract(a, b);
public static Vector operator *(double a, Vector b) => Scale(a, b);
public static Vector operator *(Vector a, double b) => Scale(b, a);
public static Vector operator /(Vector a, double b) => Scale(1 / b, a);
public static double operator *(Vector a, Vector b) => Dot(a, b);
#endregion
}
}