# Condition in SparseArray does not check the condition for some matrix elements

Consider the following MWE:

SparseArray[{{i_, j_} /; (IntegerDigits[i - 1, 2, 2][] == 0) :> 1}, {4, 4}]


This should give a $$4\times 4$$ matrix in which the first two rows are filled with ones: IntegerDigits[i - 1, 2, 2][] == 0 checks that the first digit of the binary decomposition of $$i-1$$ is $$0$$, which happens for $$i=1$$ and $$i=2$$. If I actually run the above code, in v11.3, I instead get a matrix in which only the first row is filled with ones.

SparseArray[{{i_, j_} /; (IntegerDigits[i - 1, 2, 2][] == 1) :> 1}, {4, 4}]


in which I'm asking for the first digit of the binary decomposition to equal $$1$$, I get a zero matrix.

Funnily enough, If I instead ask for the second digits of the binary decomposition to be something, everything works correctly:

SparseArray[{{i_, j_} /; (IntegerDigits[i - 1, 2, 2][] == 0) :> 1}, {4, 4}]


gives first and third nonzero rows.

Something I've noticed by running trace on the first form is that at some point i seems to be set to some value before the actual checks on the matrix elements happen: This doesn't happen in the working examples. Does anyone understand why this happens?

It's also worth noting that I've tried to make the examples even simpler by using one-dimensional "matrices":

SparseArray[{i_ /; (IntegerDigits[i - 1, 2, 2][] == 0) :> 1}, 4]


This gives the correct results, but also strange errors, which using the trace shows some weird stuff going on (the i is replaced sometimes with a list and sometimes with an integer). This behaviour is solved by using i_Integer as condition, so I don't know if this behaviour is related to the other one.

• It seems to me the expression test is firing too quickly in this specific case. When SparseArray[{{i_, j_} /; (Echo[{i, j}]; (IntegerDigits[i - 1, 2, 2][] == 0)) :> 1}, {4, 4}] is evaluated, only entries in the first row show up, while in the equivalent SparseArray[{{i_, j_} /; (Echo[{i, j}]; (BitGet[i - 1, 1] == 0)) :> 1}, {4, 4}], all entries get checked. – J. M.'s discontentment Nov 19 '19 at 0:15
• OTOH, at least SparseArray[{{i_, j_} :> Block[{}, 1 /; IntegerDigits[i - 1, 2, 2][] == 0]}, {4, 4}] and SparseArray[{{i_, j_} :> RuleCondition[1, IntegerDigits[i - 1, 2, 2][] == 0]}, {4, 4}] work. (See here for more details.) – J. M.'s discontentment Nov 19 '19 at 0:21

The second syntax example at the top of the documentation of Condition indicates to me that the test should be placed after the RuleDelayed. When you do that, it works:

SparseArray[{{i_, j_} :> 1 /; IntegerDigits[i - 1, 2, 2][] == 0}, {4, 4}] // Normal
(* Out: {{1, 1, 1, 1}, {1, 1, 1, 1}, {0, 0, 0, 0}, {0, 0, 0, 0}} *)


@glS is on to something odd though. Look at the following attempts at comparing to zero. There should be no precision issues here to trip up Equal, since the result from IntegerDigits is an arbitrary-precision integer:

Table[
Normal@
SparseArray[{{i_, j_} /; isZero@First@IntegerDigits[i - 1, 2, 2] -> 1}, {4, 4}],
{isZero, {PossibleZeroQ, (SameQ[#, 0] &), (Equal[#, 0] &), EqualTo}}
]

(* Out:
{{{1, 1, 1, 1}, {1, 1, 1, 1}, {0, 0, 0, 0}, {0, 0, 0, 0}}, (* works as expected *)
{{1, 1, 1, 1}, {1, 1, 1, 1}, {0, 0, 0, 0}, {0, 0, 0, 0}}, (* works as expected *)
{{1, 1, 1, 1}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}, (* fails *)
{{1, 1, 1, 1}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}  (* fails *)
}
*)

• @glS Yes, but that's Rule, not RuleDelayed. – MarcoB Nov 18 '19 at 17:59
• does it? In the documentation of SparseArray, under basic examples, I have the following: s = SparseArray[{{i_, i_} -> -2, {i_, j_} /; Abs[i - j] == 1 -> 1}, {5, 5}] – glS Nov 18 '19 at 17:59
• that's true, but if you try this example with Rule instead of RuleDelayed, it still doesn't work – glS Nov 18 '19 at 18:00
• @glS Yes, I agree that something else is odd here, and that's not all due to RuleDelayed etc. See the added portion of my answer. – MarcoB Nov 18 '19 at 18:43
• ah, even just replacing == with === makes it work... I really don't know what to make of it. I don't understand where that weird i=. command comes from in the Trace – glS Nov 18 '19 at 18:50