Skip to content

← Dtypes and Numerics step 2 of 6

Easy Primitives

Counting with the wrong operator

a = torch.tensor([True, True])
a + a          # tensor([True, True])

Not [2, 2]. Addition on two boolean tensors stays boolean, and in the boolean category addition is logical or. True + True is True.

Where this bites

Counting how many conditions hold:

votes = (a > 0) + (b > 0) + (c > 0)     # a bool tensor, not a count

Every position where at least one condition held reads True. The tensor has the right shape, the values look like a sensible mask, and the count you wanted is gone.

The fix

Leave the boolean category before adding:

(a > 0).int() + (b > 0).int() + (c > 0).int()
torch.stack([a > 0, b > 0, c > 0]).sum(dim=0)

sum is the safer instinct generally: it promotes bool to int64 on its own, which is why mask.sum() counts correctly while mask + mask does not. The asymmetry is not arbitrary, though it is easy to trip over: sum has one sensible answer for a boolean input and + has two, so one guesses and the other keeps you in the category you started in.

The related operators

a & b       # and
a | b       # or, and the same thing as + for bools
a ^ b       # xor
~a          # not

Using these on booleans says what you mean. Using + says something you probably did not.

Your task

def count_true(masks: list) -> torch.Tensor

Given a list of boolean tensors of the same shape, return an integer tensor counting, per position, how many of them are true.