[PYTHON] Set the number of elements in a NumPy one-dimensional array to a power of 2 (0 padded)

(* We are looking for a more efficient method)

As a preparation for the Fast Fourier Transform, there are times when you want the number of elements in an array to be a power of two.

I will write a method to round up the number of elements to the power of 2 and fill the back with 0.

Define some functions. In addition, there are some things to check for the arguments of each function, so I will describe them as appropriate and summarize the ones including the exception `raise` at the end of this article.

Round up a positive integer to a power of 2.

First, define a function that rounds up any positive integer to the power of 2. (Omit the negative number check)

``````import numpy as np

def round_pow2(x :int) -> int:
"""Round up x to a power of 2

60 -> 64
40000 -> 65536
"""

return 1 << x.bit_length()
``````
``````print(round_pow2(1000))
# => 1024
``````

This function gets the length up to the first 1 of the `x` bit string and shifts 1 to the larger side. The bit column `1 0 0 ... 0` is a power of 2. The same is true for `2 ** x.bit_length ()`.

Expand the NumPy array and fill it with a number

I want 0 padding, but I define it as such because the abstraction of "filling with a certain number" is possible. This function also has something to check, but I'll omit it.

``````def back_padding(xs: np.ndarray, n: int, a) -> np.ndarray:
"""Fill the back with a so that there are n elements"""

v = np.empty(n, dtype=type(a))
v[:xs.shape[0]] = xs
v[xs.shape[0]:] = a

return v
``````
``````print(back_padding(np.arange(10), 15, 0))
#=> [0 1 2 3 4 5 6 7 8 9 0 0 0 0 0]
``````

What you should check is that `xs` is a one-dimensional array and that the number of elements in` xs` is less than or equal to `n`. You also need that the type of `a` matches the type of the element of` xs` (you may not need to worry too much about this).

Fill the back with a number so that the number of elements is a power of 2.

Combine the functions defined above and you're done. This must also be a one-dimensional array like `back_padding`, and the element type of the array and the element type of` a` must match.

``````def to_pow2_length(xs: np.ndarray, a) -> np.ndarray:
"""Fill the back with a so that the number of elements is a power of 2."""

``````

If you want to arrange it, you should be able to select before and after the side to be filled, or set `a` to` 0` or `0.0` as the initial value. I personally thought that this definition was sufficient, so I left it as it is.

Summary

The definition including docstring and exception is summarized below.

``````import numpy as np

def round_pow2(x :int) -> int:
"""Round up x to a power of 2

Example)
60 -> 64
40000 -> 65536

Arguments:
x (int > 0):Positive integer

Returns:
int:Integer to the power of 2
"""

if x < 1:
raise ValueError("x must be a positive integer.")

return 1 << x.bit_length()

def back_padding(xs: np.ndarray, n: int, a) -> np.ndarray:
"""Fill the back with a so that there are n elements

Arguments:
xs (np.ndarray[shape=(m,)]):Array
n (int > m):Element count
a (xs.dtype):Value to fill

Returns:
np.ndarray[shape=(n,)]:Array with extras filled with a
"""

if len(xs.shape) > 1:
raise ValueError("The array xs must be a one-dimensional array.")

if xs.shape[0] > n:
raise ValueError("n must be greater than the number of elements in the array xs.")

if xs.dtype != type(a):
raise ValueError("The type of a must match the type of the elements in the array xs.")

v = np.empty(n, dtype=type(a))
v[:xs.shape[0]] = xs
v[xs.shape[0]:] = a

return v

def to_pow2_length(xs: np.ndarray, a) -> np.ndarray:
"""Fill the back with a so that the number of elements is a power of 2.

Arguments:
xs (np.ndarray[shape=(n,)]):One-dimensional array
a (xs.dtype):Value to fill

Returns:
np.ndarray[shape=(2**p,)]:An array in which the number of elements is a power of 2 and the back is filled with a
"""