About distortion:
(...) By definition, this pure tone is a sinewave - no other waveform satisfies the criterion for purity . As soon as a sinewave is modified, the waveform that now exists is created by adding harmonics. Likewise, anything that adds harmonics changes the waveform - the two are inextricably intertwined. For example, amplifying devices do not add harmonics per sé! Amplifying devices modify the waveshape, and this requires that harmonics are added to create the 'new' waveform. The creation of harmonics is a physics requirement, and has nothing (directly) to do with the type of device that caused the modification to the waveform.
This page is about an analogue implementation of this subset sum problem solution.
R code for intermodulation[code] # OH - 2018 - Subsetsum implementation to reduce large datasets # Using third order intermodulation products # based on "A general algorithm to calcuate third order intermodulation product locations for any number of tones" (2015) # by: Chris Arnott library(stats) library(pracma) plot.fourier <- function(fourier.series, f.0, ts) { w <- 2*pi*f.0 trajectory <- sapply(ts, function(t) fourier.series(t,w)) plot(ts, trajectory, type="l", xlab="time", ylab="f(t)"); abline(h=0,lty=3) } plot.frequency.spectrum <- function(X.k, xlimits=c(0,length(X.k))) { plot.data <- cbind(0:(length(X.k)-1), Mod(X.k)) # TODO: why this scaling is necessary? plot.data[2:length(X.k),2] <- 2*plot.data[2:length(X.k),2] plot(plot.data, t="h", lwd=2, main="", xlab="Frequency (Hz)", ylab="Strength", xlim=xlimits, ylim=c(0,max(Mod(plot.data[,2])))) } #f.sum <- function(t,w) { # dc.component + # sum( component.strength * sin(component.freqs*w*t + component.delay)) #} f.sum <- function(t,w) { sum( sin(component.freqs*w*t )) } readkey <- function() { cat ("Press [enter] to continue") line <- readline() } # MAIN n <- 4 orig <- c(1,2,3,4) print("original set:",cat(sets)) targetsum <- 7 f1 <- 1212.5 fch <- 60 sets <- f1 + fch*orig targetfreq <- f1 + fch*target # move components to frequency domain to reduce the list in "sets" acq.freq <- 100 # base data acquisition (sample) frequency (Hz) time <- 60 # measuring time interval (seconds) ts <- seq(0,time-1/acq.freq,1/acq.freq) # vector of sampling time-points (s) f.0 <- 1/time component.freqs <- sets # frequency of signal components (Hz) # how this looks in a plot w <- 2*pi*f.0 trajectory <- sapply(ts, function(t) f.sum(t,w)) # Intermodulation - third order product trajectory<-trajectory**3 X.k <- fft(trajectory) # find all harmonics with fft() plot.frequency.spectrum(Mod(X.k), xlimits=c(0,acq.freq*time/2)) #plot(trajectory,type="l") # frequency location of sum distortion products #find peaks spectrum <- Mod(X.k)[0:5000] #plot(spectrum,type='l') p<-findpeaks(spectrum, npeaks=50, threshold=4, sortstr=TRUE) points(p[, 2], p[, 1], pch=20, col="maroon") peaks <- p[,2][order(p[,2])] peaks sets