sonar-dotnet icon indicating copy to clipboard operation
sonar-dotnet copied to clipboard

SE: Improve arithmetic handling in loops

Open Tim-Pohlmann opened this issue 1 year ago • 6 comments

Follow-up to #8474 Specification

Currently, the SE engine is not conducting any calculations for arithmetic operations in loops. The following assumptions are approximations for calculations in a loop and can be added one by one:

  • Addition:
    • [x] positive + positive => [left.Min + right.Min, null]
    • [ ] negative + negative => [null, left.Max + right.Max] (partial implementation exists but does not handle 0)
    • [ ] number + positive constant => [left.Min + right, null]
    • [ ] number + negative constant => [null, left.Max + right]
    • [ ] number + 0 constant => [left.Min, left.Max]
  • Subtraction:
    • [ ] number - positive constant => [null, left.Max - right]
    • [ ] number - negative constant => [left.Min - right, null]
    • [ ] number - 0 constant => [left.Min, left.Max]
  • Multiplication:
    • [ ] number * 0 => [0, 0]
    • [ ] positive * positive => [left.Min * right.Min, null]
    • [ ] negative * positive constant => [null, left.Max * right]
  • Division:
    • [ ] positive / positive constant => [0, left.Max / right]
    • [ ] negative / positive constant => [left.Min / right, 0]
    • [ ] number / positive constant => [-left.Min / right, left.Max / right]
    • [ ] number / negative constant => [Max(|left.Min|, |left.Max|) / right, Max(|left.Min|, |left.Max|) / -right]
  • Remainder
    • [ ] number % constant => same logic as outside a loop
  • Bitwise And
    • [ ] number & number => same logic as outside a loop
  • Bitwise Or
    • [ ] number | number => same logic as outside a loop
  • Bitwise XOR
    • [ ] number ^ 0 constant => [left.Min, left.Max]
    • [ ] positive ^ positive => [0, null]
    • [ ] negative ^ positive constant => [null, -1]

Tim-Pohlmann avatar Feb 06 '24 11:02 Tim-Pohlmann

Addition: What about positive+negative? Is that intended to implicitly fall back to "we don't know" scenario?

We should be able to do multiplication for negative*negative too?

Why do the multiplication and division needs to work with constants only, and not positive/negative?

@pavel-mikula-sonarsource Generally speaking, my idea is, "Let's assume that the result is assigned to one of the operands and thus reused in this calculation in later iterations."

What about positive+negative? Is that intended to implicitly fall back to "we don't know" scenario? Yes. We should be able to do multiplication for negative*negative too? This would always be positive. But if it is assigned to one of the two operands, its signage would flip, and future iterations would give different results. Why do the multiplication and division needs to work with constants only, and not positive/negative? I want to avoid cases where the signage would flip. If the second operand is a constant, the result can only be assigned to the left operand, which would not result in a flipped signage.

Tim-Pohlmann avatar Feb 07 '24 15:02 Tim-Pohlmann

I want to avoid cases where the signage would flip. If the second operand is a constant, the result can only be assigned to the left operand, which would not result in a flipped signage.

That's the gap I'm asking about. If we do it with number (not constants) and we know if they are positive/negative, we never flip the signage.

We don't, because we don't know what the result will be assigned to:

var negative = -1;
var positive = 5;
while (condition)
{
    positive = positive * negative;    
}

Tim-Pohlmann avatar Feb 08 '24 09:02 Tim-Pohlmann