WHAT broadcasting is: a set of rules that decide whether two shapes are compatible, and what the result shape is, so that an element-wise operation can proceed.
What are the two conditions for two dimensions to be broadcast-compatible?
They are equal, OR one of them is 1.
How are shapes of different length aligned for broadcasting?
Right-aligned (trailing dims line up); missing leading dims are treated as size 1.
What is the result size of a compatible dimension pair?
The maximum of the two sizes (the size-1 axis is stretched).
How is broadcasting implemented without copying memory?
The stretched (size-1) axis gets stride = 0, so moving along it re-reads the same memory cell.
Why does (3,4) + (3,) fail but (3,4) + (4,) work?
Right-alignment matches the trailing axis: (3,) vs 4 → mismatch; (4,) vs 4 → equal.
How do you multiply each ROW i of a (3,4) matrix by w[i] with w shape (3,)?
Use w[:, None] to make it (3,1) so it aligns with axis 0.
What shape do you get from (3,1) + (1,4)?
(3,4) — both size-1 axes stretch.
Is the result of np.broadcast_to writable?
No, it's read-only; you must .copy() to write.
A Python scalar has what conceptual shape for broadcasting?
(), which becomes all-1 dims and stretches to anything.
Recall Feynman: explain to a 12-year-old
Imagine you have a row of 3 lunch trays and you want to put one apple on each tray. You don't need 3 separate apples drawn on paper — you can just say "put the apple shape on every tray." NumPy does that: if it only has one value along some direction, it pretends to make copies, but it's really just looking at the same value over and over. That's why adding one number to a whole grid is fast — it never actually copies the number, it just points back to it. The only rule: along each direction, the sizes must either be the same, or one of them must be one (the "stretch me" wildcard).
Broadcasting ka matlab hai: NumPy do alag-alag shape wali arrays ke beech arithmetic karne deta hai, bina manually tile (copy) kiye. Idea simple hai — agar kisi axis ki size 1 hai, to NumPy uss single value ko poore axis par "stretch" kar deta hai, jaise ek hi apple ko har tray par rakh dena. Isse matrix + scalar ya (rows×1) + (1×cols) jaisi cheezein bilkul natural lagti hain.
Rule yaad rakho do hi: shapes ko right se align karo (trailing dimensions ko line up karo), aur har dimension pair ya to equal honi chahiye, ya kisi ek ki size 1. Jo chhoti shape hai uske left wale missing dims ko 1 maan lo. Result mein har axis ki size dono mein se badi wali hoti hai. Agar 3 vs 4 jaisa case aaya (dono 1 nahi, equal bhi nahi) to ERROR.
Sabse bada magic: ye memory copy nahi karta. Jis axis ko stretch karna hota hai, NumPy uska stride = 0 set kar deta hai, yaani us direction mein chalte waqt pointer aage badhta hi nahi — same memory cell baar baar read hoti hai. Isiliye fast aur memory-efficient hai.
Gotcha jo sabko phasata hai: (3,4) matrix ke har row ko w (shape (3,)) se multiply karna ho, to seedha M * w galat hai — kyunki (3,) trailing axis (size 4) se match karega, mismatch ho jayega. Sahi tarika: M * w[:, None] taaki w ki shape (3,1) ho jaye aur axis 0 (rows) ke saath align ho. Hamesha .shape print karke confirm karo — orientation ki galti silent bugs deti hai!