Skip to content

Commit b88f306

Browse files
Merge pull request #67 from SpiceSharp/development
v3.1.1
2 parents d622fb4 + b2498bb commit b88f306

61 files changed

Lines changed: 2860 additions & 727 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

SpiceSharpBehavioral/Builders/Direct/ComplexBuilderHelper.cs

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public static class ComplexBuilderHelper
1616
/// <summary>
1717
/// A set of default functions.
1818
/// </summary>
19-
public static readonly Dictionary<string, Func<Complex[], Complex>> Defaults = new Dictionary<string, Func<Complex[], Complex>>(StringComparer.OrdinalIgnoreCase)
19+
public static Dictionary<string, Func<Complex[], Complex>> Defaults { get; set; } = new Dictionary<string, Func<Complex[], Complex>>(StringComparer.OrdinalIgnoreCase)
2020
{
2121
{ "abs", Abs },
2222
{ "sgn", Sgn },
@@ -50,9 +50,15 @@ public static class ComplexBuilderHelper
5050
{ "min", Min },
5151
{ "max", Max },
5252
{ "atan2", Atan2 },
53+
{ "atanh", Atanh },
5354
{ "hypot", Hypot },
5455
{ "rnd", Random }, { "rand", Random },
55-
{ "if", If }
56+
{ "if", If },
57+
{ "limit", Limit },
58+
{ "db", Decibels },
59+
{ "arg", args => args.Check(1)[0].Phase * 180.0 / Math.PI },
60+
{ "real", args => args.Check(1)[0].Real },
61+
{ "imag", args => args.Check(1)[0].Imaginary },
5662
};
5763

5864
private static Complex[] Check(this Complex[] args, int expected)
@@ -84,6 +90,20 @@ private static void OnFunctionFound(object sender, FunctionFoundEventArgs<Comple
8490
}
8591
}
8692

93+
/// <summary>
94+
/// Helper methods that changes the equality comparer for function names.
95+
/// </summary>
96+
/// <param name="comparer">The name comparer.</param>
97+
public static void RemapFunctions(IEqualityComparer<string> comparer)
98+
{
99+
var nmap = new Dictionary<string, Func<Complex[], Complex>>(comparer);
100+
foreach (var map in Defaults)
101+
{
102+
nmap.Add(map.Key, map.Value);
103+
}
104+
Defaults = nmap;
105+
}
106+
87107
// No-argument functions
88108
private static Complex Random(Complex[] args) { args.Check(0); return _rnd.NextDouble(); }
89109

@@ -122,6 +142,11 @@ private static Complex Nint(Complex[] args)
122142
var arg = args.Check(1)[0];
123143
return new Complex(Math.Round(arg.Real, 0), Math.Round(arg.Imaginary, 0));
124144
}
145+
private static Complex Decibels(Complex[] args)
146+
{
147+
var arg = args.Check(1)[0];
148+
return 10 * Math.Log10(arg.Real * arg.Real + arg.Imaginary * arg.Imaginary);
149+
}
125150

126151
// Two-argument functions
127152
private static Complex Pow(Complex[] args) { args.Check(2); return Complex.Pow(args[0], args[1]); }
@@ -136,10 +161,15 @@ private static Complex Round(Complex[] args)
136161
return new Complex(Math.Round(arg.Real, n), Math.Round(arg.Imaginary, n));
137162
}
138163
private static Complex Atan2(Complex[] args) { args.Check(2); return Math.Atan2(args[0].Real, args[1].Real); }
164+
165+
private static Complex Atanh(Complex[] args) { args.Check(1); return HelperFunctions.Atanh(args[0]); }
166+
139167
private static Complex Hypot(Complex[] args) { args.Check(2); return HelperFunctions.Hypot(args[0], args[1]); }
140168

141169
// Three-argument functions
142170
private static Complex If(Complex[] args) { args.Check(3); return args[0].Real > 0.5 ? args[1] : args[2]; }
171+
172+
private static Complex Limit(Complex[] args) { args.Check(3); return HelperFunctions.Limit(args[0], args[1], args[2]); }
143173

144174
// N-argument functions
145175
private static Complex Pwl(Complex[] args)

SpiceSharpBehavioral/Builders/Direct/RealBuilderHelper.cs

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public static class RealBuilderHelper
1616
/// <summary>
1717
/// A set of default functions.
1818
/// </summary>
19-
public static readonly Dictionary<string, Func<double[], double>> Defaults = new Dictionary<string, Func<double[], double>>()
19+
public static Dictionary<string, Func<double[], double>> Defaults { get; set; } = new Dictionary<string, Func<double[], double>>()
2020
{
2121
{ "abs", Abs },
2222
{ "sgn", Sgn },
@@ -50,9 +50,15 @@ public static class RealBuilderHelper
5050
{ "min", Min },
5151
{ "max", Max },
5252
{ "atan2", Atan2 },
53+
{ "atanh", Atanh },
5354
{ "hypot", Hypot },
5455
{ "rnd", Random }, { "rand", Random },
55-
{ "if", If }
56+
{ "if", If },
57+
{ "limit", Limit },
58+
{ "real", args => args.Check(1)[0] },
59+
{ "imag", args => 0.0 },
60+
{ "arg", args => 0.0 },
61+
{ "db", args => 20 * Log10(args) }
5662
};
5763

5864
private static double[] Check(this double[] args, int expected)
@@ -84,6 +90,20 @@ private static void OnFunctionFound(object sender, FunctionFoundEventArgs<double
8490
}
8591
}
8692

93+
/// <summary>
94+
/// Helper methods that changes the equality comparer for function names.
95+
/// </summary>
96+
/// <param name="comparer">The name comparer.</param>
97+
public static void RemapFunctions(IEqualityComparer<string> comparer)
98+
{
99+
var nmap = new Dictionary<string, Func<double[], double>>(comparer);
100+
foreach (var map in Defaults)
101+
{
102+
nmap.Add(map.Key, map.Value);
103+
}
104+
Defaults = nmap;
105+
}
106+
87107
// No-argument functions
88108
private static double Random(double[] args) { args.Check(0); return _rnd.NextDouble(); }
89109

@@ -119,10 +139,12 @@ private static void OnFunctionFound(object sender, FunctionFoundEventArgs<double
119139
private static double Max(double[] args) { args.Check(2); return Math.Max(args[0], args[1]); }
120140
private static double Round(double[] args) { args.Check(2); return Math.Round(args[0], (int)args[1]); }
121141
private static double Atan2(double[] args) { args.Check(2); return Math.Atan2(args[0], args[1]); }
142+
private static double Atanh(double[] args) { args.Check(1); return HelperFunctions.Atanh(args[0]); }
122143
private static double Hypot(double[] args) { args.Check(2); return HelperFunctions.Hypot(args[0], args[1]); }
123144

124145
// Three-argument functions
125146
private static double If(double[] args) { args.Check(3); return args[0] > 0.5 ? args[1] : args[2]; }
147+
private static double Limit(double[] args) { args.Check(3); return HelperFunctions.Limit(args[0], args[1], args[2]); }
126148

127149
// N-argument functions
128150
private static double Pwl(double[] args)

SpiceSharpBehavioral/Builders/Functions.cs

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,20 @@ public static bool Equals(Complex left, Complex right, double relTol, double abs
9494
return true;
9595
}
9696

97+
/// <summary>
98+
/// Gets the real part of a complex number.
99+
/// </summary>
100+
/// <param name="arg">The argument.</param>
101+
/// <returns>The real part.</returns>
102+
public static Complex Real(Complex arg) => arg.Real;
103+
104+
/// <summary>
105+
/// Gets the imaginary part of a complex number.
106+
/// </summary>
107+
/// <param name="arg">The argument.</param>
108+
/// <returns>The imaginary part.</returns>
109+
public static Complex Imag(Complex arg) => arg.Imaginary;
110+
97111
/// <summary>
98112
/// Takes the natural logarithm.
99113
/// </summary>
@@ -142,6 +156,34 @@ public static Complex Log10(Complex arg)
142156
return Complex.Log10(arg);
143157
}
144158

159+
/// <summary>
160+
/// Gets the magnitude of the complex value in decibels.
161+
/// </summary>
162+
/// <param name="arg">The argument.</param>
163+
/// <returns>The magnitude in decibels.</returns>
164+
public static Complex Decibels(Complex arg) => 10 * Log10(arg.Real * arg.Real + arg.Imaginary * arg.Imaginary);
165+
166+
/// <summary>
167+
/// Gets the phase of the complex value in degrees.
168+
/// </summary>
169+
/// <param name="arg">The argument.</param>
170+
/// <returns>The phase in degrees.</returns>
171+
public static Complex Phase(Complex arg) => arg.Phase * 180.0 / Math.PI;
172+
173+
/// <summary>
174+
/// Computes the inverse arc tangent hyperbolic.
175+
/// </summary>
176+
/// <param name="arg">The argument.</param>
177+
/// <returns>The result.</returns>
178+
public static double Atanh(double arg) => 0.5 * Log(SafeDivide(1 + arg, 1 - arg));
179+
180+
/// <summary>
181+
/// Computes the inverse arc tangent hyperbolic.
182+
/// </summary>
183+
/// <param name="arg">The argument.</param>
184+
/// <returns>The result.</returns>
185+
public static Complex Atanh(Complex arg) => 0.5 * Log(SafeDivide(1 + arg, 1 - arg));
186+
145187
/// <summary>
146188
/// Raises a number to a power.
147189
/// </summary>
@@ -436,6 +478,29 @@ public static double Sign(double arg)
436478
/// <returns>The hypothenuse.</returns>
437479
public static double Hypot(double y, double x) => Math.Sqrt(x * x + y * y);
438480

481+
/// <summary>
482+
/// Returns the intermediate value of x, y, z.
483+
/// </summary>
484+
/// <param name="x">The argument</param>
485+
/// <param name="y">Mininum value.</param>
486+
/// <param name="z">Max value.</param>
487+
/// <returns></returns>
488+
public static double Limit(double x, double y, double z)
489+
{
490+
return Math.Min(Math.Max(x, Math.Min(y, z)), Math.Max(y, z));
491+
}
492+
493+
/// <summary>
494+
/// Returns the intermediate value of x, y, z.
495+
/// </summary>
496+
/// <param name="x">The argument</param>
497+
/// <param name="y">Mininum value.</param>
498+
/// <param name="z">Max value.</param>
499+
/// <returns></returns>
500+
public static Complex Limit(Complex x, Complex y, Complex z)
501+
{
502+
return Math.Min(Math.Max(x.Real, Math.Min(y.Real, z.Real)), Math.Max(y.Real, z.Real));
503+
}
439504
/// <summary>
440505
/// Returns the hypothenuse (sqrt(|x|^2+|y|^2)).
441506
/// </summary>

SpiceSharpBehavioral/Builders/Functions/ComplexFunctionBuilderHelper.cs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ private static readonly MethodInfo
3333
/// <summary>
3434
/// A set of default functions.
3535
/// </summary>
36-
public static readonly Dictionary<string, ApplyFunction> Defaults = new Dictionary<string, ApplyFunction>(StringComparer.OrdinalIgnoreCase)
36+
public static Dictionary<string, ApplyFunction> Defaults { get; set; } = new Dictionary<string, ApplyFunction>(StringComparer.OrdinalIgnoreCase)
3737
{
3838
{ "abs", Abs },
3939
{ "sgn", Sgn },
@@ -54,6 +54,7 @@ private static readonly MethodInfo
5454
{ "acos", Acos }, { "arccos", Acos },
5555
{ "atan", Atan }, { "arctan", Atan },
5656
{ "atan2", Atan2 },
57+
{ "atanh", Atanh },
5758
{ "hypot", Hypot },
5859
{ "u", U }, { "du(0)", Zero },
5960
{ "u2", U2 }, { "du2(0)", DU2 },
@@ -69,7 +70,12 @@ private static readonly MethodInfo
6970
{ "min", Min },
7071
{ "max", Max },
7172
{ "rnd", Random }, { "rand", Random },
72-
{ "if", If }
73+
{ "if", If },
74+
{ "limit", Limit },
75+
{ "db", Decibels },
76+
{ "arg", Argument },
77+
{ "real", (ils, args) => ils.Call(HelperFunctions.Real, args) },
78+
{ "imag", (ils, args) => ils.Call(HelperFunctions.Imag, args) },
7379
};
7480

7581
private static IReadOnlyList<Node> Check(this IReadOnlyList<Node> nodes, int expected)
@@ -98,6 +104,20 @@ private static void OnFunctionFound(object sender, FunctionFoundEventArgs<Comple
98104
}
99105
}
100106

107+
/// <summary>
108+
/// Helper methods that changes the equality comparer for function names.
109+
/// </summary>
110+
/// <param name="comparer">The name comparer.</param>
111+
public static void RemapFunctions(IEqualityComparer<string> comparer)
112+
{
113+
var nmap = new Dictionary<string, ApplyFunction>(comparer);
114+
foreach (var map in Defaults)
115+
{
116+
nmap.Add(map.Key, map.Value);
117+
}
118+
Defaults = nmap;
119+
}
120+
101121
// No-argument functions
102122
private static void Random(IILState<Complex> ils, IReadOnlyList<Node> arguments)
103123
{
@@ -138,6 +158,8 @@ private static void Nint(IILState<Complex> ils, IReadOnlyList<Node> arguments)
138158
ils.PushInt(0);
139159
ils.Generator.Emit(OpCodes.Call, _round);
140160
}
161+
private static void Decibels(IILState<Complex> ils, IReadOnlyList<Node> arguments) => ils.Call(HelperFunctions.Decibels, arguments);
162+
private static void Argument(IILState<Complex> ils, IReadOnlyList<Node> arguments) => ils.Call(HelperFunctions.Phase, arguments);
141163

142164
// Two-argument functions
143165
private static void Pow(IILState<Complex> ils, IReadOnlyList<Node> arguments) => ils.Call(Complex.Pow, arguments);
@@ -153,6 +175,7 @@ private static void Round(IILState<Complex> ils, IReadOnlyList<Node> arguments)
153175
ils.Generator.Emit(OpCodes.Call, _round);
154176
}
155177
private static void Atan2(IILState<Complex> ils, IReadOnlyList<Node> arguments) => ils.Call(HelperFunctions.Atan2, arguments);
178+
private static void Atanh(IILState<Complex> ils, IReadOnlyList<Node> arguments) => ils.Call(HelperFunctions.Atanh, arguments);
156179
private static void Hypot(IILState<Complex> ils, IReadOnlyList<Node> arguments) => ils.Call(HelperFunctions.Hypot, arguments);
157180

158181
// Three-argument functions
@@ -164,6 +187,7 @@ private static void If(IILState<Complex> ils, IReadOnlyList<Node> arguments)
164187
ilsc.PushDouble(0.5);
165188
ilsc.PushCheck(OpCodes.Bgt_S, arguments[1], arguments[2]);
166189
}
190+
private static void Limit(IILState<Complex> ils, IReadOnlyList<Node> arguments) => ils.Call(HelperFunctions.Limit, arguments);
167191

168192
// N-argument functions
169193
private static void Pwl(IILState<Complex> ils, IReadOnlyList<Node> arguments)

SpiceSharpBehavioral/Builders/Functions/IILState.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,5 +85,12 @@ public interface IILState<T>
8585
/// <param name="function">The function.</param>
8686
/// <param name="args">The arguments.</param>
8787
void Call(Func<T, T, T> function, IReadOnlyList<Node> args);
88+
89+
/// <summary>
90+
/// Shorthand for calling a function with three arguments.
91+
/// </summary>
92+
/// <param name="function">The function.</param>
93+
/// <param name="args">The arguments.</param>
94+
void Call(Func<T, T, T, T> function, IReadOnlyList<Node> args);
8895
}
8996
}

SpiceSharpBehavioral/Builders/Functions/ILState.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
using SpiceSharp;
2-
using SpiceSharp.Simulations;
32
using SpiceSharpBehavioral.Diagnostics;
43
using SpiceSharpBehavioral.Parsers.Nodes;
54
using System;
@@ -227,5 +226,21 @@ public void Call(Func<T, T, T> function, IReadOnlyList<Node> args)
227226
else
228227
Call(function, _invoke2, args);
229228
}
229+
230+
/// <summary>
231+
/// Calls the specified function.
232+
/// </summary>
233+
/// <param name="function">The function.</param>
234+
/// <param name="args">The arguments.</param>
235+
/// <exception cref="ArgumentMismatchException">Thrown if there aren't two arguments.</exception>
236+
public void Call(Func<T, T, T, T> function, IReadOnlyList<Node> args)
237+
{
238+
if (args == null || args.Count != 3)
239+
throw new ArgumentMismatchException(3, args?.Count ?? 0);
240+
if (function.Target == null)
241+
Call(null, function.GetMethodInfo(), args);
242+
else
243+
Call(function, _invoke2, args);
244+
}
230245
}
231246
}

0 commit comments

Comments
 (0)