<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>ＳｔｕｆｆｏｎｍｙＭｉｎｄ</title>
    <description>Supposedly my Blog</description>
    <link>https://sangarshanan.com/</link>
    <atom:link href="https://sangarshanan.com/feed.xml" rel="self" type="application/rss+xml" />
    <pubDate>Wed, 22 Jul 2026 14:50:36 +0000</pubDate>
    <lastBuildDate>Wed, 22 Jul 2026 14:50:36 +0000</lastBuildDate>
    <generator>Jekyll v3.10.0</generator>
    
      <item>
        <title>On Recommendation systems 💿</title>
        <description>&lt;p&gt;For the past couple months at &lt;a href=&quot;https://www.deezer.com/&quot;&gt;Deezer&lt;/a&gt; I have gotten to explore a fair bit of Recommender systems, I have had some &lt;a href=&quot;https://sangarshanan.com/2025/10/05/expanding-music/&quot;&gt;strong opinions&lt;/a&gt; about them in the past and it was quite interesting to see how they actually work at an company that heavily works on these recommendations.&lt;/p&gt;

&lt;p&gt;My favorite thing about these Recommender systems is the fact that the first thing we learn about them, as a rather historical exercise is the GroupLens collaborative filtering, which is if I am being honest not too far off from how we do things currently. We can try to replace user based algorithms with item based algorithms or combine them with a weighted averages. And this works quite well until we reach a scale threshold where modelling all users or all items maxes out our compute poor machines so we simply get into latent space, identifying dimensions that group similar users and similar items, Here comes the SVD based collaborative filtering.&lt;/p&gt;

&lt;p&gt;This was back in the early 2000s and to be honest even today, when everyone wants make transformer sandwiches and LLM Paninis, the crux of production grade recommender systems is still, simple matrix factorization.&lt;/p&gt;

&lt;p&gt;We do inject some smart logic here and there, I found Funk SVD pretty cool, and how it dealt with sparsity in the data by literally just initializing it with random values rather than making it zero and approximating using SGD. Very gangster indeed. Once the era of more and more data began we began fixing this sparsity with implicit signals like users like clicks, play, intent to download and all the other shit product managers go on about.&lt;/p&gt;

&lt;p&gt;And then comes the Neural network era, We have: Embarrassingly Shallow Autoencoder and if it isn’t obvious from the name it has no hidden layers and gives us a very nice closed-form solution and there is Collaborative Denoising Autoencoder which  very interestingly when initialized with linear activation and no bias collapsed into an SVD. There is also neural CF which decided that dot product for similarity isnt good enough and put a neural network to capture non linear relations but at lower epochs it did not really beat existing benchmarks and so the complexity that these approaches brought was not really justified by performance.&lt;/p&gt;

&lt;p&gt;Of course when we get into specifics there are transformers giving us sequential recommendation and people do plug in LLMs here and then for sprinkled hallucinations, But the fact is the industry is still running on linear algebra and that just really makes me happy.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;My research at Deezer has been focused on embedding aggregation, the stability of centroids &amp;amp; I have also been exploring alternate representations and the Geometry of SVD. Hopefully I will write about this after a long hard rumination session that is due post my intern days in Paris. SO there will be a RecSys part 2 soon but until then I run back to buying baguettes.&lt;/p&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Sun, 05 Jul 2026 00:00:00 +0000</pubDate>
        <link>https://sangarshanan.com/2026/07/05/status-update-deezer/</link>
        <guid isPermaLink="true">https://sangarshanan.com/2026/07/05/status-update-deezer/</guid>
        
        <category>music-tech</category>
        
        
      </item>
    
      <item>
        <title>Expect Typos 🚧</title>
        <description>&lt;p&gt;It’s the fourth day of Canicule in Paris and my thoughts have officially melted with my brain. A month down, doing research I have gotten into the habit of writing down my thoughts and a lot of the times not even writing code, Because of my insistence on being an engineer I am not feeling productive and often have to resist the urge to optimize and get things done. This is definitely gonna require some more neural pathway rewiring and is something I need to work on and maybe write about at a later stage? And so as I think about my research days and wait for my brain to restart with the sun setting, I decided to re-read some of my blogs and noticed a bunch of random typos and sometimes bad grammatical errors. Now, I know no one religiously reads these, except me in the future (Hey there) and this blog is essentially my public diary/ learning journal of sorts and I continue to only write for myself. which is great BUT somehow a baser instinct kicked in and I proceeded to ask an agent to fix all the typos and mistakes of my earlier blogs, and this did not end here, I even tried to “optimize” some of my writings. In hindsight “what the fuck” but also I would still fully understand all my posts even if they were bombarded by a barrage of insane typos cause I wrote it, the mistakes along with the text is mine. Anyway all this is to say that I am no longer going to ask an LLM to write for me. This blog shall remain, for my sake, my words and mine only, So expect typos.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Written by a human.&lt;/p&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Mon, 29 Jun 2026 00:00:00 +0000</pubDate>
        <link>https://sangarshanan.com/2026/06/29/expect-typos/</link>
        <guid isPermaLink="true">https://sangarshanan.com/2026/06/29/expect-typos/</guid>
        
        <category>life</category>
        
        
      </item>
    
      <item>
        <title>Thinking for a living.</title>
        <description>&lt;p&gt;A case for Research (excerpts from a braindump)&lt;/p&gt;

&lt;p&gt;What is my definition of a good days work? I have been thinking about this a lot lately. Engineering has a tangible definition, You push out a new feature or maybe fix a couple bugs! That’s great but do I think deeply? Have I questioned concepts I assume to be true? Do I really think about the bug or is my impulse to just put a bandaid on it cause doing that now takes less time than it takes me to piss. It’s getting increasingly hard with autonomous agents taking over my life. I spend days on autopilot and still feel a sense of fulfillment cause I did get tangible things done without remotely using any part of my brain. But do I think outside of work?&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/in-post/modernisme.png&quot; alt=&quot;modernisme&quot; /&gt;&lt;/p&gt;

&lt;p&gt;As I was writing the earlier paragraph, I opened Youtube and watched a couple videos of the subway takes guy telling me how to feel about something and I really believe him. Something has caused my brain to develop this incredible aversion to thinking. You know, the thing that makes you human. Why should I even bother sitting and thinking? The world is overstimuating and I have already spent enough time figuring out how to make what I need to live a life of comfortable mediocrity. I have job that demands just enough “creative work” from me that I can now do without thinking, And after work i watch something from my Letterboxd list. I don’ t even think about the movie anymore, i just sleep. I am not thinking because its not helping me anymore but I can always do it when push comes to shove. I know what you are thinking, you think I can’t do it right? Well I am gonna prove it to you. I will do that by sitting down and writing this, thereby taking this train of thought to completion! If i can do that without getting swung into distractions that now exist all around me. Maybe you will believe me then but to be honest I don’t really care if you believe me or not.&lt;/p&gt;

&lt;p&gt;Why am I talking about this? Well you see, recently I started doing research which is quite different from engineering. I am used to coding my way out of problems and I have been an engineer for a long time, before this time, a different person existed, in school, a teenager. I barely remember him but I know he was obedient and timid. I feel bad for him as I think of him in third person but one thing I know to be true: He was curious, he was willing to think and his thinking made him so uncomfortable that he forgot who he was.&lt;/p&gt;

&lt;p&gt;When you are doing Research, there are no sprints, tasks and results, Forget result, there is sometimes not even a problem statement. Just something interesting, something worth spending time thinking about, poking around, scratching your head. Failing to understand, running completely in the wrong direction for weeks. Reading, More reading than doing. More understanding than building. This is how engineering felt like in the beginning, when I was also an intern 6 years ago, this is what work that makes you think should feel like and work is supposed to make you think.&lt;/p&gt;

&lt;p&gt;But is this how life is supposed to make you feel. Are feelings research questions? Have you ever thought about why something make you mad? or do we all just jump into chaos and start useless wars. We are becoming a new flavor of society that struggles to complete it’s thoughts and keeps jumping between infinite un-thought opinions. But I don’t really care about all that. What I am really looking forward to is being uncomfortable again, maybe this time around I won’t completely forget who I am.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Written by a human.&lt;/p&gt;
&lt;/blockquote&gt;
</description>
        <pubDate>Fri, 12 Jun 2026 00:00:00 +0000</pubDate>
        <link>https://sangarshanan.com/2026/06/12/doing-research/</link>
        <guid isPermaLink="true">https://sangarshanan.com/2026/06/12/doing-research/</guid>
        
        <category>life</category>
        
        
      </item>
    
      <item>
        <title>Research Internship at Deezer 💜</title>
        <description>&lt;p&gt;I have been very excited about this one for quite some time! Back in December I gave an interview to intern with the Research team at Deezer, I was really anxious initially, as I am an engineer with no formal research background and I heard that these positions are mostly offered to PhD students. I was also in my first year of my master’s, just started a few months ago, so I naturally was being stoic but honestly I really wanted this, because Deezer was a really great fit for me, not only have they done some really cool research, they have also taken a clear stance on GenAI and are one of the very few artist first streaming platforms. So I really doubled down on the preparation when I got a message that I cleared the initial round.&lt;/p&gt;

&lt;p&gt;After submitting the assignment which was to come up with a research proposal (big surprise) and having the interview to discuss the said proposal, I got an acceptance email from &lt;a href=&quot;https://scholar.google.com/citations?user=YAyP5psAAAAJ&amp;amp;hl=fr&quot;&gt;Darius&lt;/a&gt; to join the team for a 6-month internship in Paris just after New Year and that made me stupidly happy :) But I did not realize then that this was just the beginning and the hard part was getting work authorization before my start date from the French government. There was a long period of anxious waiting, fear of the offer getting cancelled or given to someone else but finally we were able to make do by cutting down my internship duration to less than 90 days and btw I still have not gotten any response from the French authorities 🫠.&lt;/p&gt;

&lt;p&gt;I started my internship officially and for that I am glad but I am also now painfully aware of my status here. My passport matters more. The team at Deezer was incredibly nice and were really willing to go all the way to help me start the internship, whatever that took. ❤️ I am really happy about that.&lt;/p&gt;

&lt;p&gt;I am super excited for the next 3 months and I did say I always want to be more than an engineer, so now I start for the very first time, as a researcher.&lt;/p&gt;

&lt;p&gt;✨ C’est parti ✨&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;https://leblog.publibook.com/wp-content/uploads/2024/04/Deezer_Logo.jpg&quot; alt=&quot;img&quot; /&gt;&lt;/p&gt;
</description>
        <pubDate>Mon, 11 May 2026 00:00:00 +0000</pubDate>
        <link>https://sangarshanan.com/2026/05/11/joined-deezer/</link>
        <guid isPermaLink="true">https://sangarshanan.com/2026/05/11/joined-deezer/</guid>
        
        <category>life</category>
        
        
      </item>
    
      <item>
        <title>Livecoding with an Adversarial AI Agent 🤖</title>
        <description>&lt;p&gt;Hey guy&lt;/p&gt;

&lt;p&gt;Usually, when people talk about AI agents in music, they’re talking about copilots that finish your sentences and with livecoding maybe they make sure your chords aren’t trash? I say that’s boring and so I’ve been working on a project called &lt;em&gt;The Code Writes Back&lt;/em&gt; where instead of an agent that helps me, I built an adversarial one that actively tries to ruin my life (and my set) while I’m livecoding.&lt;/p&gt;

&lt;p&gt;I’m using &lt;a href=&quot;https://strudel.cc&quot;&gt;strudel.cc&lt;/a&gt;, a web-based livecoding environment. To allow for chaos, I used the Model Context Protocol (MCP) which are honestly just API wrappers with a fancy acronym. This is the setup.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;The Eyes &amp;amp; Ears:&lt;/strong&gt; A multimodal LLM “watches” my code in the browser and “listens” to the audio. My lil chaos instigator.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;The Hands:&lt;/strong&gt; I use Playwright (browser automation) to let the AI literally reach into the text buffer and rewrite code in real-time.&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;The Vibe Check:&lt;/strong&gt; To keep it from just deleting everything, it’s on a timer. Every 10 seconds, it takes one loop and chooses violence.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We spend all day interacting with black-box algorithms that curate our feeds and dictate our lives. By giving the AI direct access to my music, I’m making that struggle visible. I’m not the benevolent author anymore; I’m a negotiator trying to keep the plane flying while the co-pilot keeps setting off the fire extinguisher.&lt;/p&gt;

&lt;p&gt;It turns performing into debugging and adapting to bad code snippets. It can be frustrating and unpredictable, but honestly? Way more fun than livecoding alone, especially when I play from scratch.&lt;/p&gt;

&lt;div style=&quot;text-align:center; margin: 2rem 0;&quot;&gt;
    &lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/jDmvSKwfzNA&quot; title=&quot;YouTube video player&quot; style=&quot;border:none; max-width: 100%;&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot;&gt;
    &lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;Stay glitchy 🖖&lt;/p&gt;
</description>
        <pubDate>Sat, 02 May 2026 00:00:00 +0000</pubDate>
        <link>https://sangarshanan.com/2026/05/02/adversarial-agent-for-livecoding/</link>
        <guid isPermaLink="true">https://sangarshanan.com/2026/05/02/adversarial-agent-for-livecoding/</guid>
        
        <category>music-tech</category>
        
        
      </item>
    
      <item>
        <title>I play sets now 🎶</title>
        <description>&lt;p&gt;I went back to Bangalore in April! I met a lot of my besties and with help from livecode.blr we even managed to organize an algorave. We ran over time and I did not get to play but my friends took it upon themselves, booked us all an airbnb for me to play my set on the same night!! I got to play at another house party which was also organized for me and at a friends studio for the post credits of the algorave, here I even got to record my set.&lt;/p&gt;

&lt;div style=&quot;text-align:center; margin: 2em 0;&quot;&gt;
    &lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/VEhmTd4r6eI&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot;&gt;
    &lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;I come back to Barcelona feeling extremely grateful. I sure am scared and anxious for the next phase of my student life but I think I will be Ok :) Music and friends will keep me going.&lt;/p&gt;
</description>
        <pubDate>Sun, 19 Apr 2026 00:00:00 +0000</pubDate>
        <link>https://sangarshanan.com/2026/04/19/recorded-livecoded-set/</link>
        <guid isPermaLink="true">https://sangarshanan.com/2026/04/19/recorded-livecoded-set/</guid>
        
        <category>life</category>
        
        
      </item>
    
      <item>
        <title>Tales &amp; Projects from the Second Trimester 📚</title>
        <description>&lt;p&gt;The second trimester is officially over! This was a big one with all the major classes, Doing assignments with deadlines and writing papers was a bit hectic but also fun so I am gonna miss it. From now on, the course will shift more towards finding an appropriate idea for my thesis and to work on it. I have an internship coming up in May and tbf there are so many uncertainties about a lot of things which makes me quite anxious cause it’s no longer about the classes, but I do know that i want to speed run all the ideas that came up during my course and continue to build and learn things.&lt;/p&gt;

&lt;p&gt;I made a set recently for livecode blr and even though I like the output, I feel like it could be better and I really believe there is a skill gap that I would definitely like to bridge and start discovering my edge in music. its not about the performance, its something deeply personal. Art always is, I guess?&lt;/p&gt;

&lt;p&gt;Well, anyway, that was a tangent, here are the projects I worked on this trimester.&lt;/p&gt;

&lt;h3 id=&quot;infinite-lofi-generator&quot;&gt;Infinite Lofi Generator&lt;/h3&gt;

&lt;p&gt;This project is a collection of Python functions to generatively create Lofi music using MIDI (drums, chords and melody) and sends it across to ableton to Sonify them. The generative models used are intentionally old school, like L-Systems and Hidden Markov Models. cause I wanted to understand, improve and iterate on the models faster. Also i am in perpetual state of GPU poor.&lt;/p&gt;

&lt;p&gt;This was fun cause I was able to record interesting sections and make weird poly rhythmic beats, it acts more like a sampling tool for me rather than an AI music generator.&lt;/p&gt;

&lt;div style=&quot;text-align:center; margin: 2em 0;&quot;&gt;
    &lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/oURdZkIgkYM&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot;&gt;
    &lt;/iframe&gt;
&lt;/div&gt;
&lt;h3 id=&quot;windowed-latent-granular-resynthesis-with-encodec&quot;&gt;Windowed Latent Granular Resynthesis with Encodec&lt;/h3&gt;

&lt;p&gt;Training models is overrated, It is hella fun to manipulate audio without getting into the whole deal of training a big ass model! For our generative music class we were asked to explore Latent spaces of Neural Audio codecs and see what we can get out of them.&lt;/p&gt;

&lt;p&gt;This &lt;a href=&quot;https://naotokui.net/research/paper-latent-granular-resynthesis/&quot;&gt;paper&lt;/a&gt; by the folks at Neutone explores a cool technique for creative audio resynthesis by creating a “granular codebook” that encoded the source audio corpus into latent vector segments, then matches each latent grain of a target audio signal to its closest counterpart in the codebook. The resulting hybrid sequence is decoded to produce audio that preserves the target’s temporal structure while adopting the source’s timbral characteristics.&lt;/p&gt;

&lt;p&gt;The original paper works with music2latent but reworking this with Encodec would be interesting because Music2Latent is built for efficient generative modelling applications and for other downstream tasks whereas Encodec is for Neural Audio Compression. What this means is that the latent space is more entangled i.e., makes less sense but the resynthesis is sped up allowing for realtime streaming.&lt;/p&gt;

&lt;p&gt;I worked on this for my project and wrote a short report along with website that has audio samples!&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Here is my code: &lt;a href=&quot;https://github.com/Sangarshanan/latent-granular-resynthesis&quot;&gt;https://github.com/Sangarshanan/latent-granular-resynthesis&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Audio examples: &lt;a href=&quot;https://latent-granular-resynthesis.vercel.app/&quot;&gt;https://latent-granular-resynthesis.vercel.app/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Link to the original Implementation: &lt;a href=&quot;https://huggingface.co/spaces/naotokui/latentgranular/blob/main/app.py&quot;&gt;https://huggingface.co/spaces/naotokui/latentgranular/blob/main/app.py&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;ornamentation-classification-in-hindustani-vocal-music&quot;&gt;Ornamentation classification in Hindustani vocal music&lt;/h3&gt;

&lt;p&gt;This project started as a way to transcribe Bansuri music cause we have so many open audio recordings and I quickly realized I was too ambitious so we started with ornamentation detection and classification which is a prior for transcription! Me and my uber cool team worked on detection and classification of ornamentations by extending the work of Jain &amp;amp; Arthur (2023) (DLfM). Our project combined their rule-based approach with a density-driven adaptive windowing strategy that adjusts temporal resolution based on local melodic activity. We also evaluated deep learning models like the Temporal Convolutional Network (TCN) with different pooling strategies.&lt;/p&gt;

&lt;p&gt;Our project is on Github: &lt;a href=&quot;https://github.com/Sangarshanan/hindustani-ornamentation-classification&quot;&gt;https://github.com/Sangarshanan/hindustani-ornamentation-classification&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We plan to build on top of this by including more features such as timbre and loudness, since ornamentations are not distinguished solely by their pitch curves. It would be nice to publish this work!&lt;/p&gt;

&lt;h3 id=&quot;measuring-similarity-between-makams--ragas&quot;&gt;Measuring similarity between Makams &amp;amp; Ragas&lt;/h3&gt;

&lt;p&gt;So, this project basically compares two deep Eastern music traditions: Hindustani Ragas and Ottoman-Turkish Makams. Both of these share a similar approach to melody using massive systems of different modes and rules, so we fed some symbolic MusicXML datasets into the MelodyShape similarity framework to see how they stack up. We used ShapeH and Time metrics to analyze the melodic structure of everything from full compositions down to tiny little melodic fragments.&lt;/p&gt;

&lt;p&gt;We ended up focusing on three specific Hindustani Ragas and ran them against a corpus of Turkish Makams. The results were pretty cool, and Raga Bhairav consistently spit out strong matches with several Turkish Makams, basically proving the old music theory claims about their shared intervals with actual computational data.&lt;/p&gt;

&lt;p&gt;This was really fun cause it gave hard evidence for how these modal traditions connect, but it also definitely highlighted that working with purely symbolic data has its limits when you’re trying to capture the full, rich vibe of these complex musical systems.&lt;/p&gt;

&lt;p&gt;Our project with the slides, report and code (obv): &lt;a href=&quot;https://github.com/Sangarshanan/makam-and-ragas&quot;&gt;https://github.com/Sangarshanan/makam-and-ragas&lt;/a&gt;&lt;/p&gt;

&lt;h3 id=&quot;so-what-bro&quot;&gt;So what bro&lt;/h3&gt;

&lt;p&gt;Coming from engineering, this was my first time following traditional research approaches to problem statements, going from first principles, implementing papers, working on top of them, making potential improvements and also writing ISMIR type papers. A taste of academia :) A nice lil prep for my thesis (whatever that is gonna end up being)&lt;/p&gt;
</description>
        <pubDate>Wed, 25 Mar 2026 00:00:00 +0000</pubDate>
        <link>https://sangarshanan.com/2026/03/25/trimester2-projects/</link>
        <guid isPermaLink="true">https://sangarshanan.com/2026/03/25/trimester2-projects/</guid>
        
        <category>music-tech</category>
        
        
      </item>
    
      <item>
        <title>Esoteric performance tool with Spectrogram Art 🖼️</title>
        <description>&lt;p&gt;Spectrogram art is now new at all! Aphex twin did it in the 90s.&lt;/p&gt;

&lt;p&gt;I learnt a lot about his work which watching &lt;a href=&quot;https://www.youtube.com/watch?v=5wIOBBodoic&quot;&gt;this video&lt;/a&gt;! And this is only specific to electronic music, spectrogram easter egg also feature in games like the &lt;a href=&quot;https://www.theverge.com/2016/5/31/11825606/doom-2016-soundtrack-satan-666-inverted-pentagram&quot;&gt;satanic figured hidden in Doom soundtrack&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So I made something, An experimental performance tool or maybe an installation where sound is generated continuously by converting the image captured into a spectrogram.&lt;/p&gt;

&lt;p&gt;Here is the website: &lt;a href=&quot;https://everything-is-a-spectrogram.vercel.app/&quot;&gt;https://everything-is-a-spectrogram.vercel.app/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I made a demo of this tool by fkin around with sounds on strudel.cc&lt;/p&gt;

&lt;div style=&quot;text-align:center; margin: 2em 0;&quot;&gt;
    &lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/1wc6l5TQjfs&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;All of the code is open source and is available here: &lt;a href=&quot;https://github.com/Sangarshanan/everything-is-a-spectrogram&quot;&gt;https://github.com/Sangarshanan/everything-is-a-spectrogram&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;how-it-works&quot;&gt;How it works?&lt;/h2&gt;

&lt;p&gt;To make this, I had to turn pixels and its properties to sound attributes! For each image we have&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;X-axis (columns) is mapped to time (this is a constant)&lt;/li&gt;
  &lt;li&gt;Y-axis (rows) which is mapped to the frequency&lt;/li&gt;
  &lt;li&gt;Brightness of the image controls the volume&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We can do frequency mapping with a simple geometric progressions which is basically numbers spaced evenly on a log scale, I am also quantizing these frequencies to actual musical note frequencies&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;freqs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;geomspace&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MAX_FREQ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;MIN_FREQ&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;HEIGHT&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Once we have the frequencies we can just and calculate the volume and finally mix the frequencies together!&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;col_idx&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;bp&quot;&gt;self&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;WIDTH&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;col_intensities&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;pixels&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[:,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;col_idx&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Brightness of this column
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;phases&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pi&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;freqs&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;t_global&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;waves&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;sin&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;phases&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Generate waves (sine/ saw, square?)
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;weighted_waves&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;waves&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;col_intensities&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Scale by brightness
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;col_audio&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;sum&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;weighted_waves&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;axis&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;  &lt;span class=&quot;c1&quot;&gt;# Mix all frequencies
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here for each column (time slice), we generate sine waves for all frequencies, scale them by pixel brightness and mixes them together! The sine wave is a constant as well and can be technically replaced with any kind of synthesis.&lt;/p&gt;
</description>
        <pubDate>Wed, 21 Jan 2026 00:00:00 +0000</pubDate>
        <link>https://sangarshanan.com/2026/01/21/spectrogram-music/</link>
        <guid isPermaLink="true">https://sangarshanan.com/2026/01/21/spectrogram-music/</guid>
        
        <category>music-tech</category>
        
        
      </item>
    
      <item>
        <title>AI music detection with checkerboard artifacts</title>
        <description>&lt;p&gt;Last year was crazy for AI music tools; the heavily funded ones ended up getting record deals and their usage has skyrocketed. There is AI slop everywhere now and with music its not different. Apps like Spotify have already been pushing AI music to their listeners for years, and this is only going to get worse. I knew the end of near when Mohini Dey started doing Suno ads! Oh I can all day more about how art being 10xed is the worst thing to happen to the arts in the last century but there are tons of people doing that already without any real regulation in sight; So I want to write about something tangible, something I am personally invested in: How do we reliably detect AI music, and how do we protect human artists and their music from this regurgitated, algorithmic hell slop?&lt;/p&gt;

&lt;p&gt;Several independent researchers have developed models for detecting and tagging AI music, which is a great step in the right direction. But the industry keeps evolving, and models can always be engineered to beat this metaphorical Turing test. There are also issues with interpretability and generalization of these AI detection models.&lt;/p&gt;

&lt;p&gt;There are tools like &lt;a href=&quot;https://mosis.eecs.utk.edu/harmonycloak.html&quot;&gt;HarmonyCloak&lt;/a&gt; that claim to make music unlearnable for generative AI models while leaving no perceptible artifacts, but I’ve talked to some people who refute this claim and we also had a friend who tried to use this model to poison our tracks released as a part of Algorave India compilation Album unsuccessfully :( Also HarmonyCloak seems to have started with the MIDI format and does not yet support raw audio formats, as the paper mentions, “The raw audio waveform format can be either converted from the MIDI files using DAWs or recorded from physical instruments.” Bruh what?! And this might be a nitpick, but I was personally never able to run the model locally cause of the massive compute required to add imperceptible adversarial noise. It’s not all bad, though, cause there is potential work yet to be done in this research direction.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/in-post/ai-0music.jpeg&quot; alt=&quot;ai-ai-thanos&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Benn Jordan made a couple of cool videos about &lt;a href=&quot;https://www.youtube.com/watch?v=QVXfcIb3OKo&amp;amp;t&quot;&gt;detecting AI music&lt;/a&gt; and &lt;a href=&quot;https://www.youtube.com/watch?v=xMYm2d9bmEA&amp;amp;t=358s&quot;&gt;poison-pilling music&lt;/a&gt; to make it unlearnable with adversarial noise, kind of the same direction: using AI to beat AI. Very related, and I’m also plugging Benn cause his videos are cool.&lt;/p&gt;

&lt;p&gt;The most interesting work yet has been from Deezer, which is also ISMIR 2025’s best paper: &lt;strong&gt;A Fourier Explanation of AI-Music Artifacts&lt;/strong&gt;. It’s elegant in a way that I was able to reproduce some of the work in the paper so easily and locally with just my Jupyter notebook, which, these days, is so hard to do without a ton of GPUs at your disposal.&lt;/p&gt;

&lt;h3 id=&quot;checkerboard-artifact&quot;&gt;Checkerboard artifact&lt;/h3&gt;

&lt;p&gt;There was a paper by Google way back in 2016 talking about &lt;a href=&quot;https://distill.pub/2016/deconv-checkerboard/&quot;&gt;Deconvolution and Checkerboard Artifacts&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A lot of generative tools use deconvolution layers for upsampling the latent representation, and when doing so, pixels sometimes receive more “contributions” from the convolution than others, creating variations in a regular pattern.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;For audio, this means that the outputs of generative models will produce small frequency artifacts, i.e., peaks.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This does however depend on the model architecture, and models can always use modified upsampling mechanisms to avoid this irregular kernel overlap.&lt;/p&gt;

&lt;p&gt;To reproduce the fingerprint from the paper: I calculate a basic STFT to convert the audio to frequency domain, taking the average spectrum over time with a sliding window and detecting peak values. I also subtract the local minima of the spectrum over the window to highlight the local variations and also remove bandwidth that is of no use (filtering [5-16 kHz]).&lt;/p&gt;

&lt;p&gt;This is how the plot looks for a track generated by Suno:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/in-post/ai-fourier.png&quot; alt=&quot;ai&quot; /&gt;&lt;/p&gt;

&lt;p&gt;And this is how it looks for “Everything in Its Right Place” by Radiohead:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/img/in-post/not-ai-fourier.png&quot; alt=&quot;ai&quot; /&gt;&lt;/p&gt;

&lt;p&gt;This is a very specific example but you can see a very clear difference. For the real track, the peaks are relatively uniform and scattered throughout the frequency range and the pattern looks more like natural harmonic content. AI music has a much sharper frequency cutoff and peaks that are more periodic and really stand out.&lt;/p&gt;

&lt;p&gt;Once we have these fingerprints, we can easily just train a very simple linear classifier, since different models have different peak patterns we would be able to classify between models as well and technically be able to tell if a track was generated with Suno v2 or Suno v3! Which is pretty fucking cool!&lt;/p&gt;

&lt;p&gt;Not to break your bubble but this idea is fully robust, cause even simple audio manipulations like pitch shifting can change the peak frequencies and easily break our classifier. In the future, models could also build around this by using different upsampling techniques to make these artifacts disappear.&lt;/p&gt;

&lt;p&gt;But the paper is still important cause it demonstrates something very fundamental: &lt;strong&gt;AI music artifacts are not bugs but mathematical certainties given the architecture choice&lt;/strong&gt;, and you don’t need millions of parameters to detect AI music, sometimes an STFT will do :)&lt;/p&gt;

&lt;p&gt;I am still exploring AI poison pill models that are build in a way that is more accessible to independent musicians looking to protect their work! And I really believe working on this with first principles in mind and simpler models would be the way to go. If you are reading this and are interested in similar ideas or know something I’d find interesting plis ping me as I am always available to discuss cool shit. My socials are pasted everywhere on this site.&lt;/p&gt;

&lt;p&gt;Ta Ta for now :wq&lt;/p&gt;
</description>
        <pubDate>Thu, 08 Jan 2026 00:00:00 +0000</pubDate>
        <link>https://sangarshanan.com/2026/01/08/ai-music-detection/</link>
        <guid isPermaLink="true">https://sangarshanan.com/2026/01/08/ai-music-detection/</guid>
        
        <category>music-tech</category>
        
        
      </item>
    
      <item>
        <title>Multiplications with Convolution &amp; FFT ♾️</title>
        <description>&lt;p&gt;I have been revisiting a lot of concepts related to FFTs and convolutions recently as part of my coursework, and interestingly, I ran into something so fundamental that I surprisingly hadn’t encountered before. It’s &lt;strong&gt;the convolution theorem&lt;/strong&gt;, which says that the convolution of two functions (or signals) is the product of their Fourier transforms. So, &lt;strong&gt;convolution in the time domain is the same as multiplication in the frequency domain&lt;/strong&gt;, which means we can use this for something as basic as calculating the product of two random integers, rather than the repeated addition method we are taught in school.&lt;/p&gt;

&lt;p&gt;This is how we are taught to multiply with pen and paper if we want multiply 23 by 17:&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-math&quot;&gt;23 x 17
23 + 23 + 23 + ... 17 times

23
x 17
-----
1 6 1
2 3 
-----
391
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;We can write this in Python like this:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;multiply_by_add&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;or&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# Convert to strings to access digits
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;str_a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;str_b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;len_a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str_a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;len_b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str_b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# Result array - maximum length is len_a + len_b
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;len_a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;len_b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# Multiply each digit of b with each digit of a
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;len_b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;digit_b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str_b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
        
        &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;len_a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
            &lt;span class=&quot;n&quot;&gt;digit_a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;str_a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
            
            &lt;span class=&quot;c1&quot;&gt;# Multiply two single digits using repeated addition
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;product&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
            &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;digit_b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
                &lt;span class=&quot;n&quot;&gt;product&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;digit_a&lt;/span&gt;
            
            &lt;span class=&quot;c1&quot;&gt;# Position in result array
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;pos&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;len_b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;len_a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;j&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
            
            &lt;span class=&quot;c1&quot;&gt;# Add product to current position
&lt;/span&gt;            &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pos&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;product&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# Handle carries
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;carry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;i&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)):&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;total&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;carry&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;i&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;total&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;carry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;total&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# Remove leading zeros
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# Convert to integer
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[::&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here we multiply every digit of a by every digit of b, so if there are 1,000 digits each, then we would need 1,000,000 operations, or $O(n^2)$.&lt;/p&gt;

&lt;p&gt;This is going to get really slow as the number of digits goes up. So instead of thinking about multiplication as repeated addition, let’s, for a second, think of numbers as polynomials.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-math&quot;&gt;Example: 123 × 456

123 = 1×10² + 2×10¹ + 3×10⁰ = 3 + 2x + 1x² [3,2,1]
456 = 4×10² + 5×10¹ + 6×10⁰ = 6 + 5x + 4x² [6,5,4]

Where x = 10 (our base)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we know that the multiplication of two 3-digit numbers can have a maximum of 6 digits in the result, so we can pad our integers to that length as we will run them through a convolution—just like we always do padding in CNNs.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-math&quot;&gt;[3, 2, 1] → [3, 2, 1, 0, 0, 0] 
[6, 5, 4] → [6, 5, 4, 0, 0, 0]
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Now we calculate the FFT of the polynomials to get the frequency values in the complex plane, and then run our convolution operation, which, being a pointwise multiplication, is much faster. Once that is done, we do an inverse FFT to go back to the real plane.&lt;/p&gt;

&lt;p&gt;Each frequency bin is independent; there is no summation across time.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;So, instead of convolving in the time domain, we multiply in the frequency domain, which is much faster: $O(n \log n)$.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;digits_a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; 
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;digits_b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;6&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;5&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;fft_a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fft&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fft&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;digits_a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;fft_b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fft&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fft&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;digits_b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;fft_result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fft_a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fft_b&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fft&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ifft&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fft_result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;real&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;&amp;gt;&amp;gt;&lt;/span&gt;  &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;astype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;array&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;([&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;18&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;27&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;28&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;13&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;4&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;  &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The inverse FFT reconstructs the final polynomial coefficients, which can be written as $18 + 27x + 28x^2 + 13x^3 + 4x^4$ with base 10, giving us 56088, which is exactly $123 \times 456$.&lt;/p&gt;

&lt;p&gt;Here is the full Python method:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;fft_multiply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Convert integers to digit arrays
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;str_a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;str_b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;),&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;digits_a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;str_a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[::&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;digits_b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;d&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;d&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;str_b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[::&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]]&lt;/span&gt;

    &lt;span class=&quot;k&quot;&gt;print&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;digits_a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;digits_b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# Pad to power of 2 for efficient FFT
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;n&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;digits_a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;digits_b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;**&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ceil&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;log2&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;n&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)))&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# Zero-pad
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;digits_a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;digits_a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;digits_b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;size&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;digits_b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# Perform convolution via FFT
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;fft_a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fft&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fft&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;digits_a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;fft_b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fft&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fft&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;digits_b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;fft_result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fft_a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fft_b&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fft&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;ifft&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;fft_result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;real&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# Handle carries
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;round&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;).&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;astype&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;carry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;final_digits&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[]&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;digit&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;result&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;total&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;digit&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;+&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;carry&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;final_digits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;total&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;carry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;total&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;//&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;carry&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;final_digits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;append&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;carry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;%&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;carry&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;//=&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# Remove leading zeros and convert back to integer
&lt;/span&gt;    &lt;span class=&quot;k&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;len&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;final_digits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;final_digits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;n&quot;&gt;final_digits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;pop&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;map&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;final_digits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;[::&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;])))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here, the total complexity is that of the FFT operation, which is &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;$O(n log n)&lt;/code&gt;. This means for 1,000 digits, there will be about 10,000 operations—significantly fewer than traditional addition.&lt;/p&gt;

&lt;p&gt;Benchmarking shows us the real speedup!&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s&quot;&gt;&quot;&quot;&quot;
Digits     FFT speed       Addition Speed     Speedup
------------------------------------------------------
100        0.5265          5.4833             10.41x
500        0.2716          73.4720            270.49x
1000       0.6748          178.9240           265.14x
2000       0.9318          773.8210           830.43x
------------------------------------------------------
&quot;&quot;&quot;&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;benchmark_multiplication&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num_digits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;c1&quot;&gt;# Generate large random integers
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;a&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;randint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num_digits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;join&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;np&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;random&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;randint&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;))&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;_&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;range&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;num_digits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;))&lt;/span&gt;
    
    &lt;span class=&quot;c1&quot;&gt;# Time school multiplication
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;perf_counter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;school_result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;school_multiply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;school_time&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;perf_counter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;

    &lt;span class=&quot;c1&quot;&gt;# Time FFT multiplication
&lt;/span&gt;    &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;perf_counter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;fft_result&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fft_multiply&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;a&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;b&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;fft_time&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;perf_counter&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;start&lt;/span&gt;
        
    &lt;span class=&quot;k&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;school_time&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fft_time&lt;/span&gt;

&lt;span class=&quot;k&quot;&gt;for&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;digits&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;100&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;500&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;1000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;2000&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;]:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;normal_t&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fft_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;benchmark_multiplication&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;digits&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;speedup&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;normal_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;/&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fft_t&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;fft_t&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;gt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;0&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;float&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&apos;inf&apos;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This was my homework from this &lt;a href=&quot;https://www.youtube.com/watch?v=KuXjwB4LzSA&quot;&gt;3Blue1Brown video&lt;/a&gt;.&lt;/p&gt;
</description>
        <pubDate>Sun, 04 Jan 2026 00:00:00 +0000</pubDate>
        <link>https://sangarshanan.com/2026/01/04/multiply-with-convolutions/</link>
        <guid isPermaLink="true">https://sangarshanan.com/2026/01/04/multiply-with-convolutions/</guid>
        
        <category>nerd</category>
        
        
      </item>
    
  </channel>
</rss>
