2
0
mirror of https://github.com/esiur/esiur-dotnet.git synced 2025-06-27 05:23:13 +00:00
This commit is contained in:
2022-10-16 22:16:00 +03:00
parent 8e17a5b677
commit 6537913b11
14 changed files with 516 additions and 1 deletions

View File

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<Folder Include="Signals\Modulation\" />
<Folder Include="Optimization\" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,69 @@
using Esiur.Analysis.Statistics;
using Esiur.Analysis.Units;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Security.Cryptography.X509Certificates;
using System.Text;
namespace Esiur.Analysis.Signals
{
public static class Capacity
{
public struct CSI
{
public double SNR;
public Probability Probability;
public CSI(double snr, double probability)
{
SNR = snr;
Probability = probability;
}
}
public struct OutageCapacity
{
public BitRate Capacity;
public double MinSNR;
public Probability Outage;
public double Bandwidth;
public OutageCapacity(Probability outage, double minSNR, double bandwidth)
{
MinSNR = minSNR;
Outage = outage;
Bandwidth = bandwidth;
Capacity = (1 - Outage) * bandwidth * Math.Log(1 + minSNR, 2);
}
public override string ToString() => $" {MinSNR.ToString("F")} <{Outage}> => {Capacity}";
}
public static double Compute(double bandwidth, double snr)
=> bandwidth * Math.Log(1 + snr, 2);
public static double ComputeErgodic(double bandwidth, CSI[] receiverCSI)
{
return bandwidth * receiverCSI.Sum(x => Math.Log(1 + x.SNR, 2) * x.Probability);
}
public static OutageCapacity[] ComputeOutage(double bandwidth, CSI[] receiverCSI)
{
var sorted = receiverCSI.OrderBy(x => x.SNR);
var rt = sorted.Select(x => {
var pOut = receiverCSI.Where(csi => csi.SNR < x.SNR).Sum(x => x.Probability);
return new OutageCapacity()
{
Outage = pOut,
MinSNR = x.SNR,
Capacity = (1 - pOut) * bandwidth * Math.Log(1 + x.SNR, 2)
};
});
return rt.ToArray();
}
}
}

View File

@ -0,0 +1,55 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Esiur.Analysis.Signals
{
public static class DSP
{
public static double[] ConvolveMany(params double[][] signals)
{
var rt = signals[0];
for (var i = 1; i < signals.Length; i++)
rt = rt.Convolve(signals[i]);
return rt;
}
public static double[] Convolve(this double[] signal, double[] filter)
{
var length = signal.Length + filter.Length - 1;
var rt = new double[length];
//for (var i = 0; i < signal.Length; i++)
// for (var j = 0; j < filter.Length; j++)
// rt[i + j] += signal[i] * filter[j];
for (var i = 0; i < length; i++)
{
for (var j = 0; j < signal.Length && i - j >= 0 && i - j < filter.Length; j++)
{
rt[i] = signal[j] * filter[i - j];
}
}
return rt;
}
public static double[] CrossCorrelate(this double[] signal, double[] filter)
{
var length = signal.Length + filter.Length - 1;
var rt = new double[length];
for (var i = 0; i < length; i++)
{
for (var j = 0; j < signal.Length && j + i < filter.Length; j++)
{
rt[i] = signal[j] * filter[i + j];
}
}
return rt;
}
}
}

View File

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Esiur.Analysis.Signals
{
public static class Propagation
{
public static readonly double LightSpeed = 2.99792458e8;
public static double FindReceivedPower(double transmittedPower, double distance,
double transmitterGain, double receiverGain, double pathLoss)
{
throw new NotImplementedException();
}
}
}

View File

@ -0,0 +1,31 @@
using Esiur.Analysis.Units;
using System;
using System.Collections.Generic;
using System.Text;
namespace Esiur.Analysis.Statistics
{
public struct Probability
{
public double Value;
public static implicit operator Probability(double v) => new Probability(v);
public static implicit operator double(Probability v) => v.Value;
public Probability(double value)
{
if (value > 1 || value < 0)
throw new Exception("0 >= Probability <= 1");
Value = value;
}
public double ToPercentage() => Value * 100;
public Probability FromPercentage(double value) => new Probability(value / 100);
public override string ToString()
{
return (Math.Round(Value * 10000) / 100) + "%";
}
}
}

View File

@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Esiur.Analysis.Statistics
{
public static class Statistics
{
public static double Mean(this double[] values) => values.Sum() / values.Length;
public static double Variance(this double[] x)
{
var mean = x.Mean();
return x.Sum(x => Math.Pow(x - mean, 2)) / x.Length;
}
public static double StdDiv(this double[] x) => Math.Sqrt(x.Variance());
public static double Covariance(this double[] x, double[] y)
{
var n = x.Length < y.Length ? x.Length : y.Length;
var X = x.Mean();
var Y = y.Mean();
double rt = 0;
for (var i = 0; i < n; i++)
rt += (x[i] - X) * (y[i] - Y);
return rt / n;
}
public static double RMS(this double[] x) => Math.Sqrt(x.Sum(x => x * x) / x.Length);
public static double Correlation(this double[] x, double[] y)
{
return x.Covariance(y) / (x.StdDiv() * y.StdDiv());
}
}
}

View File

@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;
namespace Esiur.Analysis.Units
{
public enum BitRateKind
{
Bits,
Octets,
Bytes
}
public struct BitRate : IComparable
{
public double Value;
public BitRate(double value, BitRateKind kind = BitRateKind.Bits)
{
if (kind == BitRateKind.Bytes)
Value = value * 8;
else if (kind == BitRateKind.Octets)
Value = value * 7;
else
Value = value;
}
public static implicit operator BitRate(double d) => new BitRate(d);
public static implicit operator double(BitRate d) => d.Value;
//public static explicit operator PowerUnit(double d) => new PowerUnit(d, PowerUnitKind.Watt);
//public static explicit operator double(PowerUnit d) => d.Value;
//public static PowerUnit operator +(PowerUnit a) => a;
//public static PowerUnit operator -(PowerUnit a) => new PowerUnit(-a.num, a.den);
public static BitRate operator +(BitRate a, BitRate b)
=> new BitRate(a.Value + b.Value);
public static BitRate operator -(BitRate a, BitRate b)
=> new BitRate(a.Value - b.Value);
public static BitRate operator *(BitRate a, BitRate b)
=> new BitRate(a.Value * b.Value);
public static BitRate operator /(BitRate a, BitRate b)
{
if (b.Value == 0)
{
throw new DivideByZeroException();
}
return new BitRate(a.Value / b.Value);
}
public override string ToString()
{
if (Value >= 1e12)
return (Value / 1e12).ToString("F") + " tbps";
else if (Value >= 1e9)
return (Value / 1e9).ToString("F") + " gbps";
else if (Value >= 1e6)
return (Value / 1e6).ToString("F") + " mbps";
else if (Value >= 1e3)
return (Value * 1e3).ToString("F") + " kbps";
else
return Value.ToString("F") + " bps";
}
public int CompareTo(object obj)
{
if (obj is BitRate p)
return Value.CompareTo(p.Value);
else
return Value.CompareTo(obj);
}
}
}

View File

@ -0,0 +1,81 @@
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;
namespace Esiur.Analysis.Units
{
public enum PowerUnitKind
{
Watt,
Decibel
}
public struct PowerUnit : IComparable
{
public double Value;
public PowerUnit(double value, PowerUnitKind kind = PowerUnitKind.Watt)
{
if (kind == PowerUnitKind.Watt)
Value = value;
else if (kind == PowerUnitKind.Decibel)
Value = FromDb(value);
else
Value = 0;
}
public static implicit operator PowerUnit(double d) => new PowerUnit(d, PowerUnitKind.Watt);
public static implicit operator double(PowerUnit d) => d.Value;
//public static explicit operator PowerUnit(double d) => new PowerUnit(d, PowerUnitKind.Watt);
//public static explicit operator double(PowerUnit d) => d.Value;
//public static PowerUnit operator +(PowerUnit a) => a;
//public static PowerUnit operator -(PowerUnit a) => new PowerUnit(-a.num, a.den);
public static PowerUnit operator +(PowerUnit a, PowerUnit b)
=> new PowerUnit(a.Value + b.Value);
public static PowerUnit operator -(PowerUnit a, PowerUnit b)
=> new PowerUnit(a.Value - b.Value);
public static PowerUnit operator *(PowerUnit a, PowerUnit b)
=> new PowerUnit(a.Value * b.Value);
public static PowerUnit operator /(PowerUnit a, PowerUnit b)
{
if (b.Value == 0)
{
throw new DivideByZeroException();
}
return new PowerUnit(a.Value / b.Value);
}
public override string ToString()
{
if (Value < 1e-6)
return (Value * 1e9).ToString("F") + "nW";
else if (Value < 1e-3)
return (Value * 1e6).ToString("F") + "µW";
else if (Value < 1)
return (Value * 1e3).ToString("F") + "mW";
else
return Value.ToString("F") + "W";
}
public double ToDb() => 10 * Math.Log(10, Value);
public static double FromDb(double value) => Math.Pow(10, value / 10);
public int CompareTo(object obj)
{
if (obj is PowerUnit p)
return Value.CompareTo(p.Value);
else
return Value.CompareTo(obj);
}
}
}