Module 3 · Lesson 1

Universal Functions (ufuncs)

A ufunc is a function that operates elementwise on arrays, implemented in compiled C, supporting broadcasting, type casting, and more. Most of the math you already use is a ufunc: arr + 1 is shorthand for np.add(arr, 1), and arr1 * arr2 is shorthand for np.multiply(arr1, arr2).

CategoryExamples
Unary (one array in)np.sqrt, np.exp, np.log, np.abs, np.negative
Binary (two arrays in)np.add, np.subtract, np.multiply, np.divide, np.power

Because ufuncs are just functions, you can call them directly when you want to pass extra keyword arguments (like out= to write into an existing array) that an operator like + doesn’t give you access to.

a = np.array([1.0, 4.0, 9.0, 16.0])

print(a + 1)              # operator form
print(np.add(a, 1))       # explicit ufunc form -- identical result

print(np.sqrt(a))         # unary ufunc
print(np.multiply(a, 2))  # binary ufunc

Output:

[ 2.  5. 10. 17.]
[ 2.  5. 10. 17.]
[1. 2. 3. 4.]
[ 2.  8. 18. 32.]
1.1

Operators in disguise

Write same_result(a, b) that returns True if a + b (operator form) and np.add(a, b) (explicit ufunc form) produce exactly equal arrays for the given inputs, False otherwise. Use this to convince yourself they're always the same operation.

💡 Hint

Use np.array_equal to compare a + b with np.add(a, b), and wrap the result in bool(...) so you return a plain Python bool.

✅ Solution
def same_result(a, b):
    return bool(np.array_equal(a + b, np.add(a, b)))
1.2

Normalize with ufuncs only

Write rescale(arr) that maps every value of a float array into the [0, 1] range using the formula (x - min) / (max - min), using only ufuncs/array ops (.min(), .max(), -, /) — no Python loop.

💡 Hint

arr.min() and arr.max() give you scalars; subtract and divide the whole array by them at once.

✅ Solution
def rescale(arr):
    lo, hi = arr.min(), arr.max()
    return (arr - lo) / (hi - lo)