import pypocketfft import pyfftw import numpy as np import pytest from numpy.testing import assert_ pmp = pytest.mark.parametrize shapes1D = ((10,), (127,)) shapes2D = ((128, 128), (128, 129), (1, 129), (129,1)) shapes3D = ((32,17,39),) shapes = shapes1D+shapes2D+shapes3D len1D=range(1,2048) def _l2error(a,b): return np.sqrt(np.sum(np.abs(a-b)**2)/np.sum(np.abs(a)**2)) def fftn(a, axes=None, inorm=0, inplace=False, nthreads=1): return pypocketfft.c2c(a, axes=axes, forward=True, inorm=inorm, inplace=inplace, nthreads=nthreads) def ifftn(a, axes=None, inorm=0, inplace=False, nthreads=1): return pypocketfft.c2c(a, axes=axes, forward=False, inorm=inorm, inplace=inplace, nthreads=nthreads) def rfftn(a, axes=None, inorm=0, nthreads=1): return pypocketfft.r2c(a, axes=axes, forward=True, inorm=inorm, nthreads=nthreads) def irfftn(a, axes=None, lastsize=0, inorm=0, nthreads=1): return pypocketfft.c2r(a, axes=axes, lastsize=lastsize,forward=False, inorm=inorm, nthreads=nthreads) def rfft_scipy(a, axis, inorm=0, inplace=False, nthreads=1): return pypocketfft.r2r_fftpack(a, axes=(axis,), input_halfcomplex=False, forward=True, inorm=inorm, inplace=inplace, nthreads=nthreads) def irfft_scipy(a, axis, inorm=0, inplace=False, nthreads=1): return pypocketfft.r2r_fftpack(a, axes=(axis,), input_halfcomplex=True, forward=False, inorm=inorm, inplace=inplace, nthreads=nthreads) @pmp("len", len1D) @pmp("inorm", [0,1,2]) def test1D(len, inorm): a=np.random.rand(len)-0.5 + 1j*np.random.rand(len)-0.5j b=a.astype(np.complex64) c=a.astype(np.complex256) assert_(_l2error(a, ifftn(fftn(c,inorm=inorm), inorm=2-inorm))<1e-18) assert_(_l2error(a, ifftn(fftn(a,inorm=inorm), inorm=2-inorm))<1.5e-15) assert_(_l2error(a.real, ifftn(fftn(a.real,inorm=inorm), inorm=2-inorm))<1.5e-15) assert_(_l2error(a.real, fftn(ifftn(a.real,inorm=inorm), inorm=2-inorm))<1.5e-15) assert_(_l2error(a.real, irfftn(rfftn(a.real,inorm=inorm), inorm=2-inorm,lastsize=len))<1.5e-15) tmp=a.copy() assert_ (ifftn(fftn(tmp, inplace=True, inorm=inorm), inplace=True, inorm=2-inorm) is tmp) assert_(_l2error(tmp, a)<1.5e-15) assert_(_l2error(b, ifftn(fftn(b, inorm=inorm), inorm=2-inorm))<6e-7) assert_(_l2error(b.real, ifftn(fftn(b.real,inorm=inorm), inorm=2-inorm))<6e-7) assert_(_l2error(b.real, fftn(ifftn(b.real,inorm=inorm), inorm=2-inorm))<6e-7) assert_(_l2error(b.real, irfftn(rfftn(b.real, inorm=inorm), lastsize=len, inorm=2-inorm))<6e-7) tmp=b.copy() assert_ (ifftn(fftn(tmp, inplace=True, inorm=inorm), inplace=True, inorm=2-inorm) is tmp) assert_(_l2error(tmp, b)<6e-7) @pmp("shp", shapes) @pmp("nthreads", (0,1,2)) def test_fftn(shp, nthreads): a=np.random.rand(*shp)-0.5 + 1j*np.random.rand(*shp)-0.5j assert_(_l2error(pyfftw.interfaces.numpy_fft.fftn(a), fftn(a, nthreads=nthreads))<1e-15) a=a.astype(np.complex64) assert_(_l2error(pyfftw.interfaces.numpy_fft.fftn(a), fftn(a, nthreads=nthreads))<5e-7) @pmp("shp", shapes2D) @pmp("axes", ((0,),(1,),(0,1),(1,0))) def test_fftn2D(shp, axes): a=np.random.rand(*shp)-0.5 + 1j*np.random.rand(*shp)-0.5j assert_(_l2error(pyfftw.interfaces.numpy_fft.fftn(a, axes=axes), fftn(a, axes=axes))<1e-15) a=a.astype(np.complex64) assert_(_l2error(pyfftw.interfaces.numpy_fft.fftn(a, axes=axes), fftn(a, axes=axes))<5e-7) @pmp("shp", shapes) def test_rfftn(shp): a=np.random.rand(*shp)-0.5 assert_(_l2error(pyfftw.interfaces.numpy_fft.rfftn(a), rfftn(a))<1e-15) a=a.astype(np.float32) assert_(_l2error(pyfftw.interfaces.numpy_fft.rfftn(a), rfftn(a))<5e-7) @pmp("shp", shapes) def test_rfft_scipy(shp): for i in range(len(shp)): a=np.random.rand(*shp)-0.5 assert_(_l2error(pyfftw.interfaces.scipy_fftpack.rfft(a,axis=i), rfft_scipy(a,axis=i))<1e-15) assert_(_l2error(pyfftw.interfaces.scipy_fftpack.irfft(a,axis=i), irfft_scipy(a,axis=i,inorm=2))<1e-15) @pmp("shp", shapes2D) @pmp("axes", ((0,),(1,),(0,1),(1,0))) def test_rfftn2D(shp, axes): a=np.random.rand(*shp)-0.5 assert_(_l2error(pyfftw.interfaces.numpy_fft.rfftn(a, axes=axes), rfftn(a, axes=axes))<1e-15) a=a.astype(np.float32) assert_(_l2error(pyfftw.interfaces.numpy_fft.rfftn(a, axes=axes), rfftn(a, axes=axes))<5e-7) @pmp("shp", shapes) def test_identity(shp): a=np.random.rand(*shp)-0.5 + 1j*np.random.rand(*shp)-0.5j assert_(_l2error(ifftn(fftn(a),inorm=2), a)<1.5e-15) assert_(_l2error(ifftn(fftn(a.real),inorm=2), a.real)<1.5e-15) assert_(_l2error(fftn(ifftn(a.real),inorm=2), a.real)<1.5e-15) tmp=a.copy() assert_ (ifftn(fftn(tmp, inplace=True), inorm=2, inplace=True) is tmp) assert_(_l2error(tmp, a)<1.5e-15) a=a.astype(np.complex64) assert_(_l2error(ifftn(fftn(a),inorm=2), a)<6e-7) @pmp("shp", shapes) def test_identity_r(shp): a=np.random.rand(*shp)-0.5 b=a.astype(np.float32) for ax in range(a.ndim): n = a.shape[ax] assert_(_l2error(irfftn(rfftn(a,(ax,)),(ax,),lastsize=n,inorm=2), a)<1e-15) assert_(_l2error(irfftn(rfftn(b,(ax,)),(ax,),lastsize=n,inorm=2), b)<5e-7) @pmp("shp", shapes) def test_identity_r2(shp): a=np.random.rand(*shp)-0.5 + 1j*np.random.rand(*shp)-0.5j a=rfftn(irfftn(a)) assert_(_l2error(rfftn(irfftn(a),inorm=2), a)<1e-15) @pmp("shp", shapes2D+shapes3D) def test_genuine_hartley(shp): a=np.random.rand(*shp)-0.5 v1 = pypocketfft.genuine_hartley(a) v2 = fftn(a.astype(np.complex128)) v2 = v2.real+v2.imag assert_(_l2error(v1, v2)<1e-15) @pmp("shp", shapes) def test_hartley_identity(shp): a=np.random.rand(*shp)-0.5 v1 = pypocketfft.separable_hartley(pypocketfft.separable_hartley(a))/a.size assert_(_l2error(a, v1)<1e-15) @pmp("shp", shapes) def test_genuine_hartley_identity(shp): a=np.random.rand(*shp)-0.5 v1 = pypocketfft.genuine_hartley(pypocketfft.genuine_hartley(a))/a.size assert_(_l2error(a, v1)<1e-15) v1 = a.copy() assert_(pypocketfft.genuine_hartley(pypocketfft.genuine_hartley(v1, inplace=True), inorm=2, inplace=True) is v1) assert_(_l2error(a, v1)<1e-15) @pmp("shp", shapes2D) @pmp("axes", ((0,),(1,),(0,1),(1,0))) def test_genuine_hartley_2D(shp, axes): a=np.random.rand(*shp)-0.5 assert_(_l2error(pypocketfft.genuine_hartley(pypocketfft.genuine_hartley(a, axes=axes), axes=axes, inorm=2),a)<1e-15)