Undescribed Horrific Abuse, One Victim & Survivor of Many gmkarl at gmail.com
Thu Nov 17 03:51:48 PST 2022

0458 !

Where I left off yesterday, after giving complex phase to my square
wave, the matrix looks better, but there are still components that
aren't conjugates.

(Pdb) p inverse_mat[:,6]
array([-0.0625-0.0625j,  0.0625-0.0625j, -0.0625+0.0625j, -0.0625-0.0625j,
        0.0625-0.0625j, -0.0625+0.0625j, -0.0625-0.0625j,  0.0625+0.0625j,
       -0.0625-0.0625j,  0.0625-0.0625j, -0.0625+0.0625j, -0.0625-0.0625j,
        0.0625-0.0625j, -0.0625+0.0625j, -0.0625-0.0625j,  0.0625+0.0625j])
(Pdb) p freqs
array([ 0.    ,  0.0625,  0.125 ,  0.1875,  0.25  ,  0.3125,  0.375 ,
        0.4375, -0.5   , -0.4375, -0.375 , -0.3125, -0.25  , -0.1875,
       -0.125 , -0.0625])

It looks to me like the first component that isn't a conjugate when
negated is frequency 0.25 . 0.25 makes 0.0625-0.0625j, whereas -0.25
makes 0.0625-0.0625j: the two values are the same.

I've likely made this situation by having a function that doesn't
produce the property.

The 0-offset sample shows it much easier:
(Pdb) p inverse_mat[:,0]
array([-0.0625-0.0625j, -0.0625-0.0625j, -0.0625-0.0625j, -0.0625-0.0625j,
       -0.0625-0.0625j, -0.0625-0.0625j, -0.0625-0.0625j, -0.0625-0.0625j,
       -0.0625-0.0625j, -0.0625-0.0625j, -0.0625-0.0625j, -0.0625-0.0625j,
       -0.0625-0.0625j, -0.0625-0.0625j, -0.0625-0.0625j, -0.0625-0.0625j])

It looks like it has no conjugates at all.

(Pdb) p create_freq2time(time_count, freqs, SINE)[:,0]
array([0.0625+0.j, 0.0625+0.j, 0.0625+0.j, 0.0625+0.j, 0.0625+0.j,
       0.0625+0.j, 0.0625+0.j, 0.0625+0.j, 0.0625+0.j, 0.0625+0.j,
       0.0625+0.j, 0.0625+0.j, 0.0625+0.j, 0.0625+0.j, 0.0625+0.j,
(Pdb) p create_freq2time(time_count, freqs, SQUARE)[:,0]
array([-0.0625-0.0625j, -0.0625-0.0625j, -0.0625-0.0625j, -0.0625-0.0625j,
       -0.0625-0.0625j, -0.0625-0.0625j, -0.0625-0.0625j, -0.0625-0.0625j,
       -0.0625-0.0625j, -0.0625-0.0625j, -0.0625-0.0625j, -0.0625-0.0625j,
       -0.0625-0.0625j, -0.0625-0.0625j, -0.0625-0.0625j, -0.0625-0.0625j])

My square wave never outputs a 0 value, so it is impossible for it to
match its complex conjugate at time=0, which has no negative. This
likely happens again at time=1, time=2, etc.

(Pdb) p complex_wavelet(SQUARE, np.array([0,0,1,-1,2,-2]))
array([-1.-1.j, -1.-1.j, -1.-1.j, -1.-1.j, -1.-1.j, -1.-1.j])

They're all equal, with no conjugates at all!

Thinking about this a little.

- i could change the wave so its minimum is 0, but then it would not
make negative conjugates unless i also negated the whole wave when
- i could make the wave a step wave that touches 0, 1, and -1, but
then it wouldn't be square any more
- i could also interpret the whole transform a little differently,
like i did to make the matrix supporting off-frequencies in the first
place, to facilitate this

I'm thinking that negating the wave when it is negative would match
the behavior of sine.
I'm accumulating the properties of the cosine wave that let it get
replaced by other functions.
- even i.e. f(x) == f(-x)
- zero at 90 degrees f(0.25) == 0
- negative at 180 degrees f(0.5) == -f(0)

Given my current complex wavelet function is taking the modulus of x
to be near zero, if I made an odd-function square wave that had a base
of 0 at 0 and hit +1 at t>0 and -1 at t<0, this could be considered
equivalent to a 3-valued step wave, in some way, since x would loop,
or I could stop looping x.

Instead of a square wave, I'm just using STEP = lambda x:
COSINE(x).round() . This significantly reduces the changes I need to

I'm thinking what's notable for the real-domain forward matrix, is the
frequencies need to be reconstructible from only half of them. At the
moment, that means that the second half _of the actual frequency data_
must be the reversed complex conjugates of the first half.

A simpler approach to this could have been to not use complex numbers
at all, and instead break data into two separate values. Then it would
be obvious how to engage real-domain data: you'd just remove the
complex data.


The assertion is still failing, but the frequencies look correct:
(Pdb) p (randvec @ create_time2freq(freqs=fftfreq(complex = True,
repetition_samples = 16), wavelet=STEP)).round(2)
array([ 9.13-0.j  , -1.17+0.32j,  0.24-0.7j , -0.43-1.37j,  0.6 -0.62j,
        0.16-0.9j ,  0.8 +1.07j, -0.22+0.21j, -0.32+0.j  , -0.22-0.21j,
        0.8 -1.07j,  0.16+0.9j ,  0.6 +0.62j, -0.43+1.37j,  0.24+0.7j ,
(Pdb) p (randvec @ unextracting_ft).round(2)
array([ 9.13-0.j  , -1.17+0.32j,  0.24-0.7j , -0.43-1.37j,  0.6 -0.62j,
        0.16-0.9j ,  0.8 +1.07j, -0.22+0.21j, -0.32-0.j  ])

The problem now must be in the inverse transform matrix, which is simpler.

For some reason the real frequency data is still retaining imaginary components:
(Pdb) p ((randvec @ unextracting_ft) @ extracting_ift).round(2)
array([0.55-0.25j, 0.4 -0.21j, 0.34+0.43j, 0.74+0.28j, 0.5 -0.12j,
       0.59+0.16j, 0.61-0.27j, 0.64-0.24j, 0.96+0.19j, 0.64-0.24j,
       0.61-0.27j, 0.59+0.16j, 0.5 -0.12j, 0.74+0.28j, 0.34+0.43j,
       0.4 -0.21j])
(Pdb) p randvec.round(2)
array([0.55, 0.72, 0.6 , 0.54, 0.42, 0.65, 0.44, 0.89, 0.96, 0.38, 0.79,
       0.53, 0.57, 0.93, 0.07, 0.09])


I'm here; it's a small and closed system:

126         if not is_complex:
127             has_nyquist = bool(freqs[-1] == 0.5)
128             head_idx = 1 if has_dc_offset else 0
129             tail_idx = len(freqs) - (1 if has_nyquist else 0)
131             # todo: remove test data
132             full_mat = complex_wavelet(wavelet,
np.outer(np.concatenate([freqs, -freqs[head_idx:tail_idx][::-1]]),
133             time_data = np.random.random(full_mat.shape[1])
134             extended_freq_data = time_data @ np.linalg.inv(full_mat)
135             freq_data = extended_freq_data[:len(freqs)]
136             import pdb; pdb.set_trace()
138             mat[head_idx:tail_idx,:] += complex_wavelet(wavelet,
np.outer(-freqs[head_idx:tail_idx], offsets))
139  ->         mat = mat.real

full_mat @ extended_freq_data == time_data correctly.
However, mat @ freq_data adds imaginary components to the output. They
are no longer canceling.

I don't yet understand why this is, given the same parts
(-freqs[head_idx,tail_idx]) are summed into the output.

So, like before, I imagine a thing to do is drilling down into the
matrix construction.

I'll consider sample 6.

(Pdb) p full_mat[:,6].round(3)
array([ 1.   -0.j   ,  0.223+0.975j, -0.901+0.434j, -0.623-0.782j,
        0.623-0.782j,  0.901+0.434j, -0.223+0.975j, -1.   +0.j   ,
       -0.223-0.975j,  0.901-0.434j,  0.623+0.782j, -0.623+0.782j,
       -0.901-0.434j,  0.223-0.975j,  1.   -0.j   ,  0.223+0.975j,
       -0.901+0.434j, -0.623-0.782j,  0.623-0.782j,  0.901+0.434j,
       -0.223+0.975j, -1.   +0.j   , -0.223-0.975j,  0.901-0.434j,
        0.623+0.782j, -0.623+0.782j, -0.901-0.434j,  0.223-0.975j])
(Pdb) p (extended_freq_data @ full_mat[:,6]).round(3)
(Pdb) p time_data[6].round(3)


So. Every item in that column #6, is multiplied by every frequency,
and they are summed.
As far as I know, that's what the code is already reproducing, so
there is something I'm conceiving wrongly going on here (as is often
the case).

I'll start by checking the top portion.
The mat that's failing is made with these 2 lines:
125         mat = complex_wavelet(wavelet, np.outer(freqs, offsets))
138             mat[head_idx:tail_idx,:] += complex_wavelet(wavelet,
np.outer(-freqs[head_idx:tail_idx], offsets))

I'll check the top portion first.

I failed to negate the nyquist frequency and found that the output
differed because of this:
(Pdb) p (extended_freq_data[:len(freqs)] @ full_mat[:len(freqs),6]).round(3)
(Pdb) p (extended_freq_data[:len(freqs)] @ np.outer(freqs,
(Pdb) p (extended_freq_data[:len(freqs)-1] @ np.outer(freqs,
(Pdb) p (extended_freq_data[:len(freqs)-1] @ np.outer(freqs,

Inspecting the source code, it looks like I am also failing to negate
the nyquist frequency there, too.
I tried inverting it and it still does not pass. 0648
-------------- next part --------------
A non-text attachment was scrubbed...
Name: fourier.py
Type: text/x-python
Size: 13430 bytes
Desc: not available
URL: <https://lists.cpunks.org/pipermail/cypherpunks/attachments/20221117/16329847/attachment.py>

More information about the cypherpunks mailing list