"""Own direct DFT, not an FFT implementation or NumPy benchmark."""
import cmath,math,json
def dft(x,n=None):
    n=len(x) if n is None else n
    if n<len(x):raise ValueError('no implicit crop in this exercise')
    a=x+[0.]*(n-len(x))
    return [sum(v*cmath.exp(-2j*math.pi*k*t/n) for t,v in enumerate(a)) for k in range(n)]
def case(freq,count,pad=None,hann=False):
    rate=64;x=[math.cos(2*math.pi*freq*t/rate) for t in range(count)]
    weights=[.5-.5*math.cos(2*math.pi*t/(count-1)) for t in range(count)] if hann else [1.]*count
    values=[a*b for a,b in zip(x,weights)];s=dft(values,pad);n=len(s)
    expected=sum(v*v for v in values);actual=sum(abs(z)**2 for z in s)/n
    assert abs(actual-expected)<1e-10
    mags=[abs(z) for z in s[:n//2+1]];peak=max(range(len(mags)),key=lambda k:mags[k])
    return {'tone_hz':freq,'observed_samples':count,'transform_length':n,'observed_duration_seconds':count/rate,'grid_spacing_hz':rate/n,'symmetric_Hann_window':hann,'nonnegative_bin_magnitudes':mags,'nonnegative_peak_bin':peak,'peak_grid_hz':peak*rate/n,'parseval_error':abs(actual-expected),'zero_padded_new_observations':0}
def demo():
    rows=[case(8,16),case(10,16),case(10,32),case(10,16,64),case(8,16,hann=True)]
    assert [r['grid_spacing_hz'] for r in rows]==[4,4,2,1,4]
    assert rows[0]['nonnegative_peak_bin']==2 and rows[2]['nonnegative_peak_bin']==5
    assert rows[3]['observed_duration_seconds']==rows[1]['observed_duration_seconds']
    return {'rate_hz':64,'cases':rows,'own_direct_DFT_not_efficient_FFT':True,'numpy_or_scipy_executed':False,'speech_pitch_or_ASR_quality_measured':False}
if __name__=='__main__':print(json.dumps(demo(),ensure_ascii=False,indent=2))
