# NumPy Mathematical Functions

The NumPy package has several dedicated classes and modules to provide mathematical functions and operations for numpy arrays.

### Arithmetic operations:

The arithmetic operations are the basic mathematical operations like addition, subtraction, multiplication, division, etc. The NumPy provides a lot of functions for arithmetic operations.

• add(), subtract(), multiply() and divide()
• true_divide() and floor_divide()
• reciprocal()
• power() and float_power()
• mod() and fmod()
• modf()
• divmod()

### add(), subtract(), multiply() and divide():

The NumPy add() function is used to add two arrays element-wise. The `add()` function returns a ndarray having the sum of input arrays, the resultant array will be scalar if both the input arrays are scalar.

Syntax:

``add(x1, x2)``

The x1 and x2 parameters are the input arrays to be added, if x1 and x2 don’t have similar shapes then they must be broadcastable to a common shape(which becomes the shape of the output array). The out parameter is a location into which the result is stored(optional parameter).

``````import numpy as np
a = np.arange(9).reshape(3, 3)
b = np.array([2, 3, 4])

#Output:
[[ 2  4  6]
[ 5  7  9]
[ 8 10 12]]``````

The output is the same if we do `a+b` directly(both a and b must be numpy array).

Similarly for the `subtract()`, `multiply()` and `divide()` functions all parameters will be the same as add() function. They will also perform element-wise subtraction, multiplication, and division respectively.

``````print(np.subtract(a, b))

#Output:
[[-2 -2 -2]
[ 1  1  1]
[ 4  4  4]]

print(np.multiply(a, b))

#Output:
[[ 0  3  8]
[ 6 12 20]
[12 21 32]]

print(np.divide(a, b))

#Output:
[[0.         0.33333333 0.5       ]
[1.5        1.33333333 1.25      ]
[3.         2.33333333 2.        ]]``````

### true_divide() and floor_divide():

The true_divide() function returns the division of input element-wise. The true_divide() adjusts the output datatype to present the best answer, regardless of input datatypes. Whereas the floor_divide() function returns the closest integer smaller or equal to the division of the inputs.

Syntax:

``true_divide(x1, x2)``

The `floor_divide()` function has the same syntax as `true_divide()` function and parameters are the same as `add()` function.

``````a = np.arange(1, 10)
print(np.true_divide(a, 2.5))

#Output:
[0.4 0.8 1.2 1.6 2.  2.4 2.8 3.2 3.6]

print(np.floor_divide(a, 2.5))

#Output:
[0. 0. 1. 1. 2. 2. 2. 3. 3.]``````

### reciprocal():

The reciprocal() function of NumPy returns the reciprocal of the given array, element-wise. The `reciprocal()` returns a `ndarray` with reciprocal values. The output of the `reciprocal()` function is scalar if the input is scalar.

Syntax:

``reciprocal(x)``

The x parameter is an input array or a scalar value. The out parameter is a location where the output of `reciprocal()` be stored(optional parameter).

``````arr = np.arange(1.0,10.0).reshape(3, 3)

print(np.reciprocal(arr))
#Output:
[[1.         0.5        0.33333333]
[0.25       0.2        0.16666667]
[0.14285714 0.125      0.11111111]]``````

### power() and float_power():

The power() function First array elements raised to powers from second array, element-wise. If the power value is a negative integer then the power() function raises a ValueError. Whereas in the float_power() function, the power can be a negative integer or negative float value.

Both functions return a `ndarray` having first array elements raised to the power of second array elements, if the input is scalar then the output is also scalar.

Syntax:

``power(x1, x2)``

The x1 and x2 parameters are the input arrays. Syntax for `float_power()` function is the same as the `power()` function.

``````p = np.arange(3, 0, -1)
p_n = np.arange(-3, 0)
print(np.power(arr, p))

#Output:
[[  1.   4.   3.]
[ 64.  25.   6.]
[343.  64.   9.]]

print(np.float_power(arr, p_n))

#Output:
[[1.         0.25       0.33333333]
[0.015625   0.04       0.16666667]
[0.00291545 0.015625   0.11111111]]``````

### mod() and fmod():

The mod() function returns the element-wise remainder of the division between two arrays. The remainder has the same sign as the divisor. The fmod() function is also used to get the remainder of the division, element-wise. The difference is the sign of remainder will be the same as the sign of the dividend.

Syntax:

``mod(x1, x2)``

The x1 parameter is the dividend and the x2 parameter is the divisor. The Syntax of `fmod() `function is the same as the `mod()` function.

``````arr=np.array([[1, -2, 3], [-4, 5, 6], [7, 8, -9]])
divisor = np.array([-3,-1,-2])
print(np.mod(arr, divisor))

#Output:
[[-2  0 -1]
[-1  0  0]
[-2  0 -1]]

print(np.fmod(arr, divisor))

#Output:
[[ 1  0  1]
[-1  0  0]
[ 1  0 -1]]``````

### modf():

The modf() function returns the fractional and integral parts of an array, element-wise. The fractional and integral parts are negative if the given element is negative.

Syntax:

``modf(x)``

The x parameter is the input array, and the out parameter is the location into which the result is stored(optional parameter).

``````a = np.array([1.2, -0.7, 5.7, 53])
print(np.modf(a))

#Output:
(array([ 0.2, -0.7,  0.7,  0. ]), array([ 1., -0.,  5., 53.]))``````

### divmod():

The divmod() function of NumPy returns the element-wise quotient and remainder simultaneously. It is much faster than Python built-in divmod() function.

Syntax:

``divmod(x1, x2)``

The x1 parameter is the dividend array and the x2 parameter is the divisor array.

``````dividend = np.array([-30, 50, -60, 70, -90])
divisor = np.array([8, -2, -4.5, 7.3, 6.1])
print(np.divmod(dividend, divisor))

#Output:
(array([ -4., -25.,  13.,   9., -15.]), array([ 2. , -0. , -1.5,  4.3,  1.5]))``````

The first array in the output is the quotient array and then next is the remainder array.

### Complex operations:

Complex operations are the operations that deal with the complex number system(real and imaginary). The NumPy package has the following functions for basic complex operations.

• real()
• imag()
• conj()
• angle()

### real():

The real() function of NumPy is used for getting the real part of the given complex array. The `real()` function returns a `ndarray` having the real part of the input complex array.

Syntax:

``real(val)``

The val parameter is the input array. The array returned from the `real()` function has float as the datatype.

``````c = np.array([4 + 5j, 3.6 + 2j, 7.9 + 6j, 5 + 3.4j, 9j, 4, 67 + 0.8j])
print(np.real(c))

#Output:
[ 4.   3.6  7.9  5.   0.   4.  67. ]``````

### imag():

The imag() function returns the imaginary part of the given complex array.

Syntax:

``imag(val)``

The val parameter is the input array. If the val is real then the returned array has datatype same as the given array, and if val is complex the returned array has float as the datatype.

``````print(np.imag(c))

#Output:
[5.  2.  6.  3.4 9.  0.  0.8]``````

### conj():

The NumPy conj() function returns the complex conjugate of the complex numbers, element-wise. The complex conjugate of a complex number is obtained by changing the sign of its imaginary part. The `conj()` function returns a ndarray with datatype same as the input array.

Syntax:

``conj(x)``

The x parameter is the input array, and out is a location into which the result is stored(optional parameter).

``````c = np.array([2 - 5.8j, 1.6 + 2.7j, 4.9 + 6j, 5 - 8.4j, -7j, 1, 97 + 5.8j])
print(np.conj(c))

#Output:
[ 2. +5.8j  1.6-2.7j  4.9-6.j   5. +8.4j -0. +7.j   1. -0.j  97. -5.8j]``````

### angle():

The angle() function of NumPy returns the angle of the complex array, element-wise.

Syntax:

``angle(z, deg=False)``

The z parameter is the input complex array. The deg parameter is the angle unit, if deg is True then the angle is in degrees and if deg is False(default) then the angle is in radians.

`````` print(np.angle(c))

#Output:
[-1.23873686  1.03584125  0.88597508 -1.03388558 -1.57079633  0.
0.05972271]``````

### Bitwise operations:

The bitwise operations are the operation that deals with individual bits of the given operand. The NumPy package has the following functions to perform bitwise operations.

• bitwise_and()
• bitwise_or()
• invert()
• left_shift()
• right_shift()

### bitwise_and():

The bitwise_and() function computes the bitwise AND operation as per the binary representation of the integers of two arrays, element-wise.

Syntax:

``bitwise_and(x1, x2)``

The x1 and x2 parameters are the input arrays, and others are optional parameters.

``````a = np.arange(2, 12, 2)
b = np.arange(1, 6)
print(np.bitwise_and(a, b))

#Output:
[0 0 2 0 0]``````

The output array have 2 in third index as bitwise_and of 6(binary: 110) and 3((binary: 011) is 2(second bit is 1 i.e(21)).

### bitwise_or():

The bitwise_or() function of NumPy computes the bitwise OR operation as per the binary representation of the integers of two arrays, element-wise.

Syntax:

``bitwise_or(x1, x2)``

The parameters of the `bitwise_or()` function is the same as the `bitwise_and()` function.

``````print(np.bitwise_or(a, b))

#Output:
[ 3  6  7 12 15]``````

### bitwise_xor():

The bitwise_xor() function of NumPy computes the bitwise XOR operation as per the binary representation of the integers of two arrays, element-wise.

Syntax:

``bitwise_xor(x1, x2)``

The parameters of the `bitwise_xor()` function is the same as the `bitwise_and()` function.

``````print(np.bitwise_xor(a, b))

#Output:
[ 3  6  5 12 15]``````

### invert():

The invert() function of NumPy computes the bitwise NOT operation as per the binary representation of the integers of the input array, element-wise.

Syntax:

``invert(x)``

The x parameter is the input array and other parameters are optional.

``````print(np.invert(a))

#Output:
[ -3  -5  -7  -9 -11]``````

### left_shift():

The left_shift() function of NumPy shifts the bits of an integer to the left. The internal representation of numbers is in binary, bits are shifted to the left by appending 0s at the right of the binary value of the integer elements.

Syntax:

``left_shift(x1, x2)``

The x1 and x2 parameters can be arrays or integer values, and other parameters are optional.

``````a = np.arange(2, 10, 2)
b = np.arange(4)
print(np.left_shift(a, b))

#Output:
[ 2  8 24 64]``````

### right_shift():

The right_shift() function shifts the bits of an integer to the right. The bits are shifted to the right by appending 0s at the left of the binary value of the integer elements.

Syntax:

``right_shift(x1, x2)``

The parameters of `right_shift()` function is the same as the `left_shift()` function.

``````print(np.right_shift(a, b))

#Output:
[2 2 1 1]``````