Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

irfft: weird when odd #539

Open
Inkbottle007 opened this issue Aug 12, 2020 · 1 comment
Open

irfft: weird when odd #539

Inkbottle007 opened this issue Aug 12, 2020 · 1 comment

Comments

@Inkbottle007
Copy link

Inkbottle007 commented Aug 12, 2020

Notice that the rfft of odd and even length signals are of the same shape. (?) Hum, I'm not sure about that. However when composing irfft with rttf on odd size sample, below is what happens:

(* https://ocaml.xyz/book/signal.html
   rfft composed with irfft in odd case behaves unexpectedly. *)

open Owl
open Owl_plplot
open Core
module G = Dense.Ndarray.Generic

(* Size of sample below is 6. We probe it with 6 different frequencies.  One of them is
   the zero frequency; the others have values arranged in a Hermitian sort of way,
   because we are in the "real" case.  So we only need 5 / 2 = 3 values. `rfft` on that
   sample gives us 4 values: all is well. *)
let even_a = [| 1.; 2.; 1.; -1.; 1.5; 1.0 |] |> Fun.flip Arr.of_array [| 6 |]

(* When the size of the sample is 5, for the exact same reasons as above, `rfft` returns a
   size 1 + 4 / 2 = 3, array, just as expected. Now when we call `irfft` on that it
   doesn't know from which case it comes from. `irfft` assumes it is the even case, so 3
   must be 1 + 3 / 2... Anyway, you'll figure it out. *)
let odd_a = even_a |> G.get_slice [ [ 0; 4 ] ]
let correct_even_rfft = even_a |> Owl_fft.D.rfft |> Owl_fft.D.irfft
let faulty_odd_rfft = odd_a |> Owl_fft.D.rfft |> Owl_fft.D.irfft

let mimicking_faulty_odd_rfft =
  odd_a
  |> G.cast_d2z
  |> Owl_fft.D.fft
  |> G.get_fancy [ L [ 0; 1; 2; 4 ] ]
  |> Owl_fft.D.ifft
  |> Dense.Ndarray.Z.re
;;

And the output:

#use "bin/rfft_odd_is_weird.ml";;
module G = Owl.Dense.Ndarray.Generic
val even_a : Arr.arr = 
  C0 C1 C2 C3  C4 C5 
R  1  2  1 -1 1.5  1 

val odd_a : (float, Bigarray.float64_elt) G.t =
  
  C0 C1 C2 C3  C4 
R  1  2  1 -1 1.5 

val correct_even_rfft :
  (float, Bigarray.float64_elt) Owl_dense_ndarray_generic.t =
  
  C0 C1 C2 C3  C4 C5 
R  1  2  1 -1 1.5  1 

val faulty_odd_rfft : (float, Bigarray.float64_elt) Owl_dense_ndarray_generic.t =
  
       C0      C1       C2      C3 
R 1.70789 2.40844 -0.37367 0.75734 

val mimicking_faulty_odd_rfft : Dense.Ndarray.Z.cast_arr =
  
       C0      C1       C2      C3 
R 1.70789 2.40844 -0.37367 0.75734 
@jzstark
Copy link
Collaborator

jzstark commented Aug 15, 2020

Thanks a lot for helping to clarify this matter!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants