Add exact-zero guards in various classes to prevent division by zero errors

This commit is contained in:
Miha Kralj
2026-02-16 21:57:11 -08:00
parent 63ae2c9ab2
commit b63b9730e1
10 changed files with 18 additions and 2 deletions
+2
View File
@@ -180,6 +180,7 @@ public sealed class Cg : AbstractBase
private double CalculateCg()
{
int n = _buffer.Count;
// skipcq: CS-R1077 - Exact-zero guard: _sum is cumulative price sum; zero means empty buffer, division by zero below
if (n == 0 || _sum == 0)
{
return 0;
@@ -299,6 +300,7 @@ public sealed class Cg : AbstractBase
sum += price;
}
// skipcq: CS-R1077 - Exact-zero guard: sum is cumulative price sum; zero means empty buffer, division by zero below
if (sum == 0)
{
output[i] = 0;
+1
View File
@@ -321,6 +321,7 @@ public sealed class Homod : AbstractBase
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static double Atan2(double y, double x)
{
// skipcq: CS-R1077 - Exact-zero guard: both quadrature components zero means no signal; atan2(0,0) is undefined
if (y == 0.0 && x == 0.0)
{
return 0.0; // Return 0 instead of error for robustness
+2
View File
@@ -206,9 +206,11 @@ public sealed class HtSine : AbstractBase
prevI2 = i2;
double tempReal1 = period;
// skipcq: CS-R1077 - Exact-zero guard: atan(im/re) requires nonzero denominator; zero im/re means no signal energy
if (im != 0.0 && re != 0.0)
{
double angle = Math.Atan(im / re);
// skipcq: CS-R1077 - Exact-zero guard: angle == 0 means period is undefined (division by angle below)
if (angle != 0.0)
{
period = (2.0 * Math.PI) / angle;
+1
View File
@@ -133,6 +133,7 @@ public sealed class Pmo : AbstractBase
}
else
{
// skipcq: CS-R1077 - Exact-zero guard: PrevClose is a price; zero means no prior data, division by zero produces Infinity
roc = _state.PrevClose != 0.0
? ((value / _state.PrevClose) - 1.0) * 100.0
: 0.0;
+3 -1
View File
@@ -81,7 +81,8 @@ public sealed class Rocp : AbstractBase
else
{
double past = _buffer[0];
result = past != 0 ? 100.0 * (value - past) / past : 0.0; // Avoid division by zero
// skipcq: CS-R1077 - Exact-zero guard: IEEE 754 div-by-zero produces Infinity; any nonzero denominator is valid
result = past != 0 ? 100.0 * (value - past) / past : 0.0;
}
Last = new TValue(input.Time, result);
@@ -150,6 +151,7 @@ public sealed class Rocp : AbstractBase
else
{
double past = source[i - period];
// skipcq: CS-R1077 - Exact-zero guard: IEEE 754 div-by-zero produces Infinity; any nonzero denominator is valid
output[i] = past != 0 ? 100.0 * (source[i] - past) / past : 0.0;
}
}
+3 -1
View File
@@ -81,7 +81,8 @@ public sealed class Rocr : AbstractBase
else
{
double past = _buffer[0];
result = past != 0 ? value / past : 1.0; // Avoid division by zero
// skipcq: CS-R1077 - Exact-zero guard: IEEE 754 div-by-zero produces Infinity; any nonzero denominator is valid
result = past != 0 ? value / past : 1.0;
}
Last = new TValue(input.Time, result);
@@ -150,6 +151,7 @@ public sealed class Rocr : AbstractBase
else
{
double past = source[i - period];
// skipcq: CS-R1077 - Exact-zero guard: IEEE 754 div-by-zero produces Infinity; any nonzero denominator is valid
output[i] = past != 0 ? source[i] / past : 1.0;
}
}
+2
View File
@@ -329,6 +329,7 @@ public sealed class Bbs : ITValuePublisher
_prevSqueezeOn = squeezeOn;
// === Bandwidth ===
// skipcq: CS-R1077 - Exact-zero guard: bbMean is a price average; zero means no data, not rounding artifact
double bandwidth = bbMean != 0.0 ? ((bbUpper - bbLower) / bbMean) * 100.0 : 0.0;
// === Resync for floating-point drift ===
@@ -611,6 +612,7 @@ public sealed class Bbs : ITValuePublisher
squeezeOn[i] = bbUpper < kcUpper && bbLower > kcLower;
// Bandwidth
// skipcq: CS-R1077 - Exact-zero guard: bbMean is a price average; zero means no data, not rounding artifact
bandwidth[i] = bbMean != 0.0 ? ((bbUpper - bbLower) / bbMean) * 100.0 : 0.0;
}
}
+2
View File
@@ -147,6 +147,7 @@ public sealed class Cfo : AbstractBase
double tsf = Math.FusedMultiplyAdd(slope, _period - 1, intercept);
// CFO = 100 * (source - tsf) / source
// skipcq: CS-R1077 - Exact-zero guard: value is a price; zero means no data, division by zero produces Infinity
double cfo = value == 0.0 ? double.NaN : 100.0 * (value - tsf) / value;
Last = new TValue(input.Time, cfo);
@@ -304,6 +305,7 @@ public sealed class Cfo : AbstractBase
double intercept = (sumY - slope * sumX) / period;
double tsf = Math.FusedMultiplyAdd(slope, period - 1, intercept);
// skipcq: CS-R1077 - Exact-zero guard: val is a price; zero means no data, division by zero produces Infinity
output[i] = val == 0.0 ? double.NaN : 100.0 * (val - tsf) / val;
}
}
+1
View File
@@ -307,6 +307,7 @@ public sealed class Mode : AbstractBase
for (int i = 1; i < count; i++)
{
// skipcq: CS-R1077 - Exact-equality required: mode detection counts identical values in a sorted array; epsilon would merge distinct prices
if (sorted[i] == sorted[i - 1])
{
currentFreq++;
+1
View File
@@ -226,6 +226,7 @@ public sealed class Spearman : AbstractBase
{
countSmaller++;
}
// skipcq: CS-R1077 - Exact-equality required: Spearman tie-detection needs bit-identical values; epsilon would create false ties
if (vj == vi)
{
countEqual++; // includes self