Skip to content

Commit bb20a75

Browse files
subhendudash02pre-commit-ci[bot]
authored andcommitted
Add circular convolution (TheAlgorithms#8158)
* add circular convolution * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * add type hint for __init__ * rounding off final values to 2 and minor changes * add test case for unequal signals * changes in list comprehension and enumeraton --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 1a10cdf commit bb20a75

File tree

1 file changed

+99
-0
lines changed

1 file changed

+99
-0
lines changed

electronics/circular_convolution.py

+99
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
# https://en.wikipedia.org/wiki/Circular_convolution
2+
3+
"""
4+
Circular convolution, also known as cyclic convolution,
5+
is a special case of periodic convolution, which is the convolution of two
6+
periodic functions that have the same period. Periodic convolution arises,
7+
for example, in the context of the discrete-time Fourier transform (DTFT).
8+
In particular, the DTFT of the product of two discrete sequences is the periodic
9+
convolution of the DTFTs of the individual sequences. And each DTFT is a periodic
10+
summation of a continuous Fourier transform function.
11+
12+
Source: https://en.wikipedia.org/wiki/Circular_convolution
13+
"""
14+
15+
import doctest
16+
from collections import deque
17+
18+
import numpy as np
19+
20+
21+
class CircularConvolution:
22+
"""
23+
This class stores the first and second signal and performs the circular convolution
24+
"""
25+
26+
def __init__(self) -> None:
27+
"""
28+
First signal and second signal are stored as 1-D array
29+
"""
30+
31+
self.first_signal = [2, 1, 2, -1]
32+
self.second_signal = [1, 2, 3, 4]
33+
34+
def circular_convolution(self) -> list[float]:
35+
"""
36+
This function performs the circular convolution of the first and second signal
37+
using matrix method
38+
39+
Usage:
40+
>>> import circular_convolution as cc
41+
>>> convolution = cc.CircularConvolution()
42+
>>> convolution.circular_convolution()
43+
[10, 10, 6, 14]
44+
45+
>>> convolution.first_signal = [0.2, 0.4, 0.6, 0.8, 1.0, 1.2, 1.4, 1.6]
46+
>>> convolution.second_signal = [0.1, 0.3, 0.5, 0.7, 0.9, 1.1, 1.3, 1.5]
47+
>>> convolution.circular_convolution()
48+
[5.2, 6.0, 6.48, 6.64, 6.48, 6.0, 5.2, 4.08]
49+
50+
>>> convolution.first_signal = [-1, 1, 2, -2]
51+
>>> convolution.second_signal = [0.5, 1, -1, 2, 0.75]
52+
>>> convolution.circular_convolution()
53+
[6.25, -3.0, 1.5, -2.0, -2.75]
54+
55+
>>> convolution.first_signal = [1, -1, 2, 3, -1]
56+
>>> convolution.second_signal = [1, 2, 3]
57+
>>> convolution.circular_convolution()
58+
[8, -2, 3, 4, 11]
59+
60+
"""
61+
62+
length_first_signal = len(self.first_signal)
63+
length_second_signal = len(self.second_signal)
64+
65+
max_length = max(length_first_signal, length_second_signal)
66+
67+
# create a zero matrix of max_length x max_length
68+
matrix = [[0] * max_length for i in range(max_length)]
69+
70+
# fills the smaller signal with zeros to make both signals of same length
71+
if length_first_signal < length_second_signal:
72+
self.first_signal += [0] * (max_length - length_first_signal)
73+
elif length_first_signal > length_second_signal:
74+
self.second_signal += [0] * (max_length - length_second_signal)
75+
76+
"""
77+
Fills the matrix in the following way assuming 'x' is the signal of length 4
78+
[
79+
[x[0], x[3], x[2], x[1]],
80+
[x[1], x[0], x[3], x[2]],
81+
[x[2], x[1], x[0], x[3]],
82+
[x[3], x[2], x[1], x[0]]
83+
]
84+
"""
85+
for i in range(max_length):
86+
rotated_signal = deque(self.second_signal)
87+
rotated_signal.rotate(i)
88+
for j, item in enumerate(rotated_signal):
89+
matrix[i][j] += item
90+
91+
# multiply the matrix with the first signal
92+
final_signal = np.matmul(np.transpose(matrix), np.transpose(self.first_signal))
93+
94+
# rounding-off to two decimal places
95+
return [round(i, 2) for i in final_signal]
96+
97+
98+
if __name__ == "__main__":
99+
doctest.testmod()

0 commit comments

Comments
 (0)