Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 94 additions & 0 deletions NumFlat/Mat/Mat.Complex.cs
Original file line number Diff line number Diff line change
Expand Up @@ -105,5 +105,99 @@ private static void ConjugateDiv(in Vec<Complex> x, double y, in Vec<Complex> de
pd += destination.Stride;
}
}

/// <summary>
/// Extracts the real part of each element in the complex matrix.
/// </summary>
/// <param name="x">
/// The complex matrix.
/// </param>
/// <param name="destination">
/// The destination of the real parts.
/// </param>
/// <remarks>
/// This method does not allocate managed heap memory.
/// </remarks>
public static void Real(in Mat<Complex> x, in Mat<double> destination)
{
ThrowHelper.ThrowIfEmpty(x, nameof(x));
ThrowHelper.ThrowIfEmpty(destination, nameof(destination));

if (destination.RowCount != x.RowCount)
{
throw new ArgumentException("'destination.RowCount' must match 'x.RowCount'.");
}

if (destination.ColCount != x.ColCount)
{
throw new ArgumentException("'destination.ColCount' must match 'x.ColCount'.");
}

var sx = x.Memory.Span;
var sd = destination.Memory.Span;
var ox = 0;
var od = 0;
while (od < sd.Length)
{
var px = ox;
var pd = od;
var end = od + destination.RowCount;
while (pd < end)
{
sd[pd] = sx[px].Real;
px++;
pd++;
}
ox += x.Stride;
od += destination.Stride;
}
}

/// <summary>
/// Extracts the imaginary part of each element in the complex matrix.
/// </summary>
/// <param name="x">
/// The complex matrix.
/// </param>
/// <param name="destination">
/// The destination of the imaginary parts.
/// </param>
/// <remarks>
/// This method does not allocate managed heap memory.
/// </remarks>
public static void Imaginary(in Mat<Complex> x, in Mat<double> destination)
{
ThrowHelper.ThrowIfEmpty(x, nameof(x));
ThrowHelper.ThrowIfEmpty(destination, nameof(destination));

if (destination.RowCount != x.RowCount)
{
throw new ArgumentException("'destination.RowCount' must match 'x.RowCount'.");
}

if (destination.ColCount != x.ColCount)
{
throw new ArgumentException("'destination.ColCount' must match 'x.ColCount'.");
}

var sx = x.Memory.Span;
var sd = destination.Memory.Span;
var ox = 0;
var od = 0;
while (od < sd.Length)
{
var px = ox;
var pd = od;
var end = od + destination.RowCount;
while (pd < end)
{
sd[pd] = sx[px].Imaginary;
px++;
pd++;
}
ox += x.Stride;
od += destination.Stride;
}
}
}
}
44 changes: 44 additions & 0 deletions NumFlat/Mat/MatrixExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,50 @@ public static Mat<Complex> ConjugateTranspose(in this Mat<Complex> x)
return result;
}

/// <summary>
/// Extracts the real part of each element in the complex matrix.
/// </summary>
/// <param name="x">
/// The complex matrix.
/// </param>
/// <returns>
/// The real parts of the complex matrix.
/// </returns>
/// <remarks>
/// This method allocates a new matrix which is independent from the original matrix.
/// To avoid the allocation, use <see cref="Mat.Real(in Mat{Complex}, in Mat{double})"/> instead.
/// </remarks>
public static Mat<double> Real(in this Mat<Complex> x)
{
ThrowHelper.ThrowIfEmpty(x, nameof(x));

var result = new Mat<double>(x.RowCount, x.ColCount);
Mat.Real(x, result);
return result;
}

/// <summary>
/// Extracts the imaginary part of each element in the complex matrix.
/// </summary>
/// <param name="x">
/// The complex matrix.
/// </param>
/// <returns>
/// The imaginary parts of the complex matrix.
/// </returns>
/// <remarks>
/// This method allocates a new matrix which is independent from the original matrix.
/// To avoid the allocation, use <see cref="Mat.Imaginary(in Mat{Complex}, in Mat{double})"/> instead.
/// </remarks>
public static Mat<double> Imaginary(in this Mat<Complex> x)
{
ThrowHelper.ThrowIfEmpty(x, nameof(x));

var result = new Mat<double>(x.RowCount, x.ColCount);
Mat.Imaginary(x, result);
return result;
}

/// <summary>
/// Computes a matrix inversion, <c>X^-1</c>.
/// </summary>
Expand Down
68 changes: 68 additions & 0 deletions NumFlat/Vec/Vec.Complex.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,5 +34,73 @@ public static void Conjugate(in Vec<Complex> x, in Vec<Complex> destination)
pd += destination.Stride;
}
}

/// <summary>
/// Extracts the real part of each element in the complex vector.
/// </summary>
/// <param name="x">
/// The complex vector.
/// </param>
/// <param name="destination">
/// The destination of the real parts.
/// </param>
/// <remarks>
/// This method does not allocate managed heap memory.
/// </remarks>
public static void Real(in Vec<Complex> x, in Vec<double> destination)
{
ThrowHelper.ThrowIfEmpty(x, nameof(x));
ThrowHelper.ThrowIfEmpty(destination, nameof(destination));

if (destination.Count != x.Count)
{
throw new ArgumentException("'destination.Count' must match 'x.Count'.");
}

var sx = x.Memory.Span;
var sd = destination.Memory.Span;
var px = 0;
var pd = 0;
while (pd < sd.Length)
{
sd[pd] = sx[px].Real;
px += x.Stride;
pd += destination.Stride;
}
}

/// <summary>
/// Extracts the imaginary part of each element in the complex vector.
/// </summary>
/// <param name="x">
/// The complex vector.
/// </param>
/// <param name="destination">
/// The destination of the imaginary parts.
/// </param>
/// <remarks>
/// This method does not allocate managed heap memory.
/// </remarks>
public static void Imaginary(in Vec<Complex> x, in Vec<double> destination)
{
ThrowHelper.ThrowIfEmpty(x, nameof(x));
ThrowHelper.ThrowIfEmpty(destination, nameof(destination));

if (destination.Count != x.Count)
{
throw new ArgumentException("'destination.Count' must match 'x.Count'.");
}

var sx = x.Memory.Span;
var sd = destination.Memory.Span;
var px = 0;
var pd = 0;
while (pd < sd.Length)
{
sd[pd] = sx[px].Imaginary;
px += x.Stride;
pd += destination.Stride;
}
}
}
}
44 changes: 44 additions & 0 deletions NumFlat/Vec/VectorExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,50 @@ public static Vec<Complex> Conjugate(in this Vec<Complex> x)
return result;
}

/// <summary>
/// Extracts the real part of each element in the complex vector.
/// </summary>
/// <param name="x">
/// The complex vector.
/// </param>
/// <returns>
/// The real parts of the complex vector.
/// </returns>
/// <remarks>
/// This method allocates a new vector which is independent from the original vector.
/// To avoid the allocation, use <see cref="Vec.Real(in Vec{Complex}, in Vec{double})"/> instead.
/// </remarks>
public static Vec<double> Real(in this Vec<Complex> x)
{
ThrowHelper.ThrowIfEmpty(x, nameof(x));

var result = new Vec<double>(x.Count);
Vec.Real(x, result);
return result;
}

/// <summary>
/// Extracts the imaginary part of each element in the complex vector.
/// </summary>
/// <param name="x">
/// The complex vector.
/// </param>
/// <returns>
/// The imaginary parts of the complex vector.
/// </returns>
/// <remarks>
/// This method allocates a new vector which is independent from the original vector.
/// To avoid the allocation, use <see cref="Vec.Imaginary(in Vec{Complex}, in Vec{double})"/> instead.
/// </remarks>
public static Vec<double> Imaginary(in this Vec<Complex> x)
{
ThrowHelper.ThrowIfEmpty(x, nameof(x));

var result = new Vec<double>(x.Count);
Vec.Imaginary(x, result);
return result;
}

/// <summary>
/// Converts the vector to a single-row matrix.
/// </summary>
Expand Down
54 changes: 54 additions & 0 deletions NumFlatTest/MatTests/ComplexTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,59 @@ public void Conjugate(int rowCount, int colCount, int xStride, int dstStride)

TestMatrix.FailIfOutOfRangeWrite(dst);
}

[TestCase(1, 1, 1, 1)]
[TestCase(1, 1, 3, 5)]
[TestCase(2, 2, 2, 2)]
[TestCase(2, 2, 4, 3)]
[TestCase(3, 2, 3, 3)]
[TestCase(3, 2, 4, 5)]
[TestCase(2, 3, 2, 3)]
[TestCase(2, 3, 4, 4)]
[TestCase(6, 3, 8, 7)]
[TestCase(4, 7, 5, 9)]
public void Real(int rowCount, int colCount, int xStride, int dstStride)
{
var x = TestMatrix.RandomComplex(42, rowCount, colCount, xStride);
var dst = TestMatrix.RandomDouble(0, rowCount, colCount, dstStride);

using (x.EnsureUnchanged())
{
Mat.Real(x, dst);
}

var expected = x.Map(value => value.Real);

NumAssert.AreSame(expected, dst, 0);

TestMatrix.FailIfOutOfRangeWrite(dst);
}

[TestCase(1, 1, 1, 1)]
[TestCase(1, 1, 3, 5)]
[TestCase(2, 2, 2, 2)]
[TestCase(2, 2, 4, 3)]
[TestCase(3, 2, 3, 3)]
[TestCase(3, 2, 4, 5)]
[TestCase(2, 3, 2, 3)]
[TestCase(2, 3, 4, 4)]
[TestCase(6, 3, 8, 7)]
[TestCase(4, 7, 5, 9)]
public void Imaginary(int rowCount, int colCount, int xStride, int dstStride)
{
var x = TestMatrix.RandomComplex(42, rowCount, colCount, xStride);
var dst = TestMatrix.RandomDouble(0, rowCount, colCount, dstStride);

using (x.EnsureUnchanged())
{
Mat.Imaginary(x, dst);
}

var expected = x.Map(value => value.Imaginary);

NumAssert.AreSame(expected, dst, 0);

TestMatrix.FailIfOutOfRangeWrite(dst);
}
}
}
50 changes: 50 additions & 0 deletions NumFlatTest/MatTests/MatrixExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,56 @@ public void ConjugateTranspose(int rowCount, int colCount, int xStride)
}
}

[TestCase(1, 1, 1)]
[TestCase(2, 2, 2)]
[TestCase(2, 2, 4)]
[TestCase(3, 1, 3)]
[TestCase(1, 3, 1)]
[TestCase(1, 3, 2)]
[TestCase(3, 2, 3)]
[TestCase(2, 3, 2)]
[TestCase(4, 5, 8)]
[TestCase(9, 6, 11)]
public void Real(int rowCount, int colCount, int xStride)
{
var x = TestMatrix.RandomComplex(42, rowCount, colCount, xStride);

Mat<double> actual;
using (x.EnsureUnchanged())
{
actual = x.Real();
}

var expected = x.Map(value => value.Real);

NumAssert.AreSame(expected, actual, 0);
}

[TestCase(1, 1, 1)]
[TestCase(2, 2, 2)]
[TestCase(2, 2, 4)]
[TestCase(3, 1, 3)]
[TestCase(1, 3, 1)]
[TestCase(1, 3, 2)]
[TestCase(3, 2, 3)]
[TestCase(2, 3, 2)]
[TestCase(4, 5, 8)]
[TestCase(9, 6, 11)]
public void Imaginary(int rowCount, int colCount, int xStride)
{
var x = TestMatrix.RandomComplex(42, rowCount, colCount, xStride);

Mat<double> actual;
using (x.EnsureUnchanged())
{
actual = x.Imaginary();
}

var expected = x.Map(value => value.Imaginary);

NumAssert.AreSame(expected, actual, 0);
}

[TestCase(1, 1)]
[TestCase(2, 2)]
[TestCase(3, 3)]
Expand Down
Loading