Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
ift
NIFTy
Commits
1182e522
Commit
1182e522
authored
Jun 14, 2016
by
theos
Browse files
Fixed handling of centering masks in nifty_fft.py.
Condensed functional structure in nifty_fft.py.
parent
157f4fea
Pipeline
#5114
skipped
Changes
2
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
rg/nifty_fft.py
View file @
1182e522
# -*- coding: utf-8 -*-
# -*- coding: utf-8 -*-
import
warnings
import
numpy
as
np
import
numpy
as
np
from
mpi4py
import
MPI
from
d2o
import
distributed_data_object
,
\
from
d2o
import
distributed_data_object
,
distributor_factory
,
STRATEGIES
STRATEGIES
from
nifty.config
import
about
,
dependency_injector
as
gdi
from
nifty.config
import
about
,
\
dependency_injector
as
gdi
import
nifty.nifty_utilities
as
utilities
import
nifty.nifty_utilities
as
utilities
pyfftw
=
gdi
.
get
(
'pyfftw'
)
pyfftw
=
gdi
.
get
(
'pyfftw'
)
...
@@ -11,23 +14,6 @@ gfft = gdi.get('gfft')
...
@@ -11,23 +14,6 @@ gfft = gdi.get('gfft')
gfft_dummy
=
gdi
.
get
(
'gfft_dummy'
)
gfft_dummy
=
gdi
.
get
(
'gfft_dummy'
)
# Try to import pyfftw. If this fails fall back to gfft.
# If this fails fall back to local gfft_rg
# try:
# import pyfftw
# fft_machine='pyfftw'
# except(ImportError):
# try:
# import gfft
# fft_machine='gfft'
# about.infos.cprint('INFO: Using gfft')
# except(ImportError):
# import gfft_rg as gfft
# fft_machine='gfft_fallback'
# about.infos.cprint('INFO: Using builtin "plain" gfft version 0.1.0')
def
fft_factory
(
fft_module_name
):
def
fft_factory
(
fft_module_name
):
"""
"""
A factory for fast-fourier-transformation objects.
A factory for fast-fourier-transformation objects.
...
@@ -103,7 +89,7 @@ class FFTW(FFT):
...
@@ -103,7 +89,7 @@ class FFTW(FFT):
pyfftw
.
interfaces
.
cache
.
enable
()
pyfftw
.
interfaces
.
cache
.
enable
()
def
get_centering_mask
(
self
,
to_center_input
,
dimensions_input
,
def
get_centering_mask
(
self
,
to_center_input
,
dimensions_input
,
offset_input
=
0
):
offset_input
=
False
):
"""
"""
Computes the mask, used to (de-)zerocenter domain and target
Computes the mask, used to (de-)zerocenter domain and target
fields.
fields.
...
@@ -205,8 +191,8 @@ class FFTW(FFT):
...
@@ -205,8 +191,8 @@ class FFTW(FFT):
self
.
centering_mask_dict
[
temp_id
]
=
centering_mask
self
.
centering_mask_dict
[
temp_id
]
=
centering_mask
return
self
.
centering_mask_dict
[
temp_id
]
return
self
.
centering_mask_dict
[
temp_id
]
def
_get_transform_info
(
self
,
domain
,
codomain
,
local_shape
_info
=
None
,
def
_get_transform_info
(
self
,
domain
,
codomain
,
local_shape
,
is_local
=
False
,
**
kwargs
):
local_offset_Q
,
is_local
,
**
kwargs
):
# generate a id-tuple which identifies the domain-codomain setting
# generate a id-tuple which identifies the domain-codomain setting
temp_id
=
domain
.
__hash__
()
^
(
101
*
codomain
.
__hash__
())
temp_id
=
domain
.
__hash__
()
^
(
101
*
codomain
.
__hash__
())
...
@@ -214,12 +200,12 @@ class FFTW(FFT):
...
@@ -214,12 +200,12 @@ class FFTW(FFT):
if
temp_id
not
in
self
.
info_dict
:
if
temp_id
not
in
self
.
info_dict
:
if
is_local
:
if
is_local
:
self
.
info_dict
[
temp_id
]
=
FFTWLocalTransformInfo
(
self
.
info_dict
[
temp_id
]
=
FFTWLocalTransformInfo
(
domain
,
codomain
,
local_shape
_info
,
domain
,
codomain
,
local_shape
,
local_offset_Q
,
self
,
**
kwargs
self
,
**
kwargs
)
)
else
:
else
:
self
.
info_dict
[
temp_id
]
=
FFTWMPITransfromInfo
(
self
.
info_dict
[
temp_id
]
=
FFTWMPITransfromInfo
(
domain
,
codomain
,
local_shape
_info
,
domain
,
codomain
,
local_shape
,
local_offset_Q
,
self
,
**
kwargs
self
,
**
kwargs
)
)
...
@@ -254,25 +240,7 @@ class FFTW(FFT):
...
@@ -254,25 +240,7 @@ class FFTW(FFT):
return
val
*
mask
return
val
*
mask
def
_local_transform
(
self
,
val
,
info
,
axes
,
domain
,
codomain
):
def
_atomic_mpi_transform
(
self
,
val
,
info
,
axes
,
domain
,
codomain
):
# Apply codomain centering mask
if
reduce
(
lambda
x
,
y
:
x
+
y
,
codomain
.
paradict
[
'zerocenter'
]):
temp_val
=
np
.
copy
(
val
)
val
=
self
.
_apply_mask
(
temp_val
,
info
.
cmask_codomain
,
axes
)
result
=
info
.
fftw_interface
(
val
,
axes
=
axes
,
planner_effort
=
'FFTW_ESTIMATE'
)
# Apply domain centering mask
if
reduce
(
lambda
x
,
y
:
x
+
y
,
domain
.
paradict
[
'zerocenter'
]):
result
=
self
.
_apply_mask
(
result
,
info
.
cmask_domain
,
axes
)
# Correct the sign if needed
result
*=
info
.
sign
return
result
def
_mpi_transform
(
self
,
val
,
info
,
axes
,
domain
,
codomain
):
# Apply codomain centering mask
# Apply codomain centering mask
if
reduce
(
lambda
x
,
y
:
x
+
y
,
codomain
.
paradict
[
'zerocenter'
]):
if
reduce
(
lambda
x
,
y
:
x
+
y
,
codomain
.
paradict
[
'zerocenter'
]):
temp_val
=
np
.
copy
(
val
)
temp_val
=
np
.
copy
(
val
)
...
@@ -288,7 +256,7 @@ class FFTW(FFT):
...
@@ -288,7 +256,7 @@ class FFTW(FFT):
if
p
.
has_output
:
if
p
.
has_output
:
result
=
p
.
output_array
result
=
p
.
output_array
else
:
else
:
r
aise
RuntimeError
(
'ERROR: PyFFTW-MPI transform failed.'
)
r
eturn
None
# Apply domain centering mask
# Apply domain centering mask
if
reduce
(
lambda
x
,
y
:
x
+
y
,
domain
.
paradict
[
'zerocenter'
]):
if
reduce
(
lambda
x
,
y
:
x
+
y
,
domain
.
paradict
[
'zerocenter'
]):
...
@@ -299,74 +267,88 @@ class FFTW(FFT):
...
@@ -299,74 +267,88 @@ class FFTW(FFT):
return
result
return
result
def
_not_slicing_transform
(
self
,
val
,
domain
,
codomain
,
axes
,
**
kwargs
):
def
_local_transform
(
self
,
val
,
domain
,
codomain
,
axes
,
**
kwargs
):
temp_val
=
val
.
copy_empty
(
distribution_strategy
=
'fftw'
)
####
about
.
warnings
.
cprint
(
'WARNING: Repacking d2o to fftw
\
# val must be numpy array or d2o with slicing distributor
distribution strategy'
)
###
temp_val
.
set_full_data
(
val
,
copy
=
False
)
local_offset_Q
=
False
try
:
local_val
=
val
.
get_local_data
(
copy
=
False
),
if
axes
is
None
or
0
in
axes
:
local_offset_Q
=
val
.
distributor
.
local_shape
[
0
]
%
2
except
(
AttributeError
):
local_val
=
val
current_info
=
self
.
_get_transform_info
(
domain
,
codomain
,
local_shape
=
local_val
.
shape
,
local_offset_Q
=
local_offset_Q
,
is_local
=
True
,
**
kwargs
)
# Recursive call to take advantage of the fact that the data
# Apply codomain centering mask
# necessary is already present on the nodes.
if
reduce
(
lambda
x
,
y
:
x
+
y
,
codomain
.
paradict
[
'zerocenter'
]):
result
=
self
.
transform
(
temp_val
,
domain
,
codomain
,
axes
,
temp_val
=
np
.
copy
(
local_val
)
**
kwargs
)
local_val
=
self
.
_apply_mask
(
temp_val
,
current_info
.
cmask_codomain
,
axes
)
return_val
=
val
.
copy_empty
(
distribution_strategy
=
val
.
distribution_strategy
)
return_val
.
set_full_data
(
result
,
copy
=
False
)
return
return_val
local_result
=
current_info
.
fftw_interface
(
local_val
,
axes
=
axes
,
planner_effort
=
'FFTW_ESTIMATE'
)
def
_slicing_local_transform
(
self
,
val
,
domain
,
codomain
,
axes
,
**
kwargs
):
# Apply domain centering mask
current_info
=
self
.
_get_transform_info
(
domain
,
codomain
,
if
reduce
(
lambda
x
,
y
:
x
+
y
,
domain
.
paradict
[
'zerocenter'
]):
is_local
=
True
,
**
kwargs
)
local_result
=
self
.
_apply_mask
(
local_result
,
current_info
.
cmask_domain
,
axes
)
# Compute transform for the local data
# Correct the sign if needed
result
=
self
.
_local_transform
(
if
current_info
.
sign
!=
1
:
val
.
get_local_data
(
copy
=
False
),
local_result
*=
current_info
.
sign
current_info
,
axes
,
domain
,
codomain
)
# Create return object and insert results inplace
try
:
return_val
=
val
.
copy_empty
(
global_shape
=
val
.
shape
,
# Create return object and insert results inplace
dtype
=
codomain
.
dtype
)
return_val
=
val
.
copy_empty
(
global_shape
=
val
.
shape
,
return_val
.
set_local_data
(
data
=
result
,
copy
=
False
)
dtype
=
codomain
.
dtype
)
return_val
.
set_local_data
(
data
=
local_result
,
copy
=
False
)
except
(
AttributeError
):
return_val
=
local_result
return
return_val
return
return_val
def
_
slicing_not
_fftw_
mpi
_transform
(
self
,
val
,
domain
,
codomain
,
def
_
repack_to
_fftw_
and
_transform
(
self
,
val
,
domain
,
codomain
,
axes
,
**
kwargs
):
axes
,
**
kwargs
):
temp_val
=
val
.
copy_empty
(
distribution_strategy
=
'fftw'
)
temp_val
=
val
.
copy_empty
(
distribution_strategy
=
'fftw'
)
about
.
warnings
.
cprint
(
'WARNING: Repacking d2o to fftw
\
distribution strategy'
)
temp_val
.
set_full_data
(
val
,
copy
=
False
)
temp_val
.
set_full_data
(
val
,
copy
=
False
)
# Recursive call to transform
# Recursive call to transform
result
=
self
.
transform
(
temp_val
,
domain
,
codomain
,
axes
,
**
kwargs
)
result
=
self
.
transform
(
temp_val
,
domain
,
codomain
,
axes
,
**
kwargs
)
return_val
=
result
.
copy_empty
(
return_val
=
result
.
copy_empty
(
distribution_strategy
=
val
.
distribution_strategy
distribution_strategy
=
val
.
distribution_strategy
)
)
return_val
.
set_full_data
(
data
=
result
,
copy
=
False
)
return_val
.
set_full_data
(
data
=
result
,
copy
=
False
)
return
return_val
return
return_val
def
_get_local_shape_info
(
self
,
comm
,
global_shape
,
distribution_strategy
):
def
_mpi_transform
(
self
,
val
,
domain
,
codomain
,
axes
,
**
kwargs
):
if
distribution_strategy
==
'equal'
:
local_slice
=
distributor_factory
.
_equal_slicer
(
comm
,
global_shape
)
local_shape
=
np
.
append
((
local_slice
[
1
]
-
local_slice
[
0
],),
global_shape
[
1
:])
return
(
local_shape
,
local_slice
[
0
])
def
_slicing_fftw_mpi_transform
(
self
,
val
,
domain
,
codomain
,
axes
,
**
kwargs
):
current_info
=
self
.
_get_transform_info
(
domain
,
codomain
,
local_shape_info
=
self
.
_get_local_shape_info
(
val
.
comm
,
val
.
shape
,
val
.
distribution_strategy
),
**
kwargs
)
if
axes
is
None
or
0
in
axes
:
local_offset_list
=
np
.
cumsum
(
np
.
concatenate
(
[[
0
,
],
val
.
distributor
.
all_local_slices
[:,
2
]]))
local_offset_Q
=
bool
(
local_offset_list
[
val
.
distributor
.
comm
.
rank
]
%
2
)
else
:
local_offset_Q
=
False
current_info
=
self
.
_get_transform_info
(
domain
,
codomain
,
local_shape
=
val
.
local_shape
,
local_offset_Q
=
local_offset_Q
,
is_local
=
False
,
**
kwargs
)
return_val
=
val
.
copy_empty
(
global_shape
=
val
.
shape
,
return_val
=
val
.
copy_empty
(
global_shape
=
val
.
shape
,
dtype
=
codomain
.
dtype
)
dtype
=
codomain
.
dtype
)
...
@@ -399,10 +381,14 @@ class FFTW(FFT):
...
@@ -399,10 +381,14 @@ class FFTW(FFT):
original_shape
=
inp
.
shape
original_shape
=
inp
.
shape
inp
=
inp
.
reshape
(
inp
.
shape
[
0
],
1
)
inp
=
inp
.
reshape
(
inp
.
shape
[
0
],
1
)
result
=
self
.
_mpi_transform
(
inp
,
current_info
,
axes
,
with
warnings
.
catch_warnings
():
domain
,
codomain
)
warnings
.
simplefilter
(
"ignore"
)
result
=
self
.
_atomic_mpi_transform
(
inp
,
current_info
,
axes
,
domain
,
codomain
)
if
slice_list
==
[
slice
(
None
,
None
)]:
if
result
is
None
:
temp_val
=
np
.
empty_like
(
local_val
)
elif
slice_list
==
[
slice
(
None
,
None
)]:
temp_val
=
result
temp_val
=
result
else
:
else
:
# Reverting to the original shape i.e. before the input was
# Reverting to the original shape i.e. before the input was
...
@@ -460,28 +446,23 @@ class FFTW(FFT):
...
@@ -460,28 +446,23 @@ class FFTW(FFT):
return_val
=
self
.
_local_transform
(
temp_val
,
current_info
,
axes
,
return_val
=
self
.
_local_transform
(
temp_val
,
current_info
,
axes
,
domain
,
codomain
)
domain
,
codomain
)
else
:
else
:
if
val
.
comm
is
not
MPI
.
COMM_WORLD
:
raise
RuntimeError
(
'ERROR: Input array uses an unsupported
\
comm object'
)
if
val
.
distribution_strategy
in
STRATEGIES
[
'slicing'
]:
if
val
.
distribution_strategy
in
STRATEGIES
[
'slicing'
]:
if
axes
is
None
or
set
(
axes
)
==
set
(
range
(
len
(
val
.
shape
)))
\
if
axes
is
None
or
0
in
axes
:
or
0
in
axes
:
if
val
.
distribution_strategy
!=
'fftw'
:
if
val
.
distribution_strategy
!=
'fftw'
:
return_val
=
\
return_val
=
\
self
.
_
slicing_not
_fftw_
mpi
_transform
(
self
.
_
repack_to
_fftw_
and
_transform
(
val
,
domain
,
codomain
,
axes
,
**
kwargs
val
,
domain
,
codomain
,
axes
,
**
kwargs
)
)
else
:
else
:
return_val
=
self
.
_
slicing_fftw_
mpi_transform
(
return_val
=
self
.
_mpi_transform
(
val
,
domain
,
codomain
,
axes
,
**
kwargs
val
,
domain
,
codomain
,
axes
,
**
kwargs
)
)
else
:
else
:
return_val
=
self
.
_
slicing_
local_transform
(
return_val
=
self
.
_local_transform
(
val
,
domain
,
codomain
,
axes
,
**
kwargs
val
,
domain
,
codomain
,
axes
,
**
kwargs
)
)
else
:
else
:
return_val
=
self
.
_
not_slicing
_transform
(
return_val
=
self
.
_
repack_to_fftw_and
_transform
(
val
,
domain
,
codomain
,
axes
,
**
kwargs
val
,
domain
,
codomain
,
axes
,
**
kwargs
)
)
...
@@ -494,49 +475,26 @@ class FFTW(FFT):
...
@@ -494,49 +475,26 @@ class FFTW(FFT):
class
FFTWTransformInfo
(
object
):
class
FFTWTransformInfo
(
object
):
def
__init__
(
self
,
domain
,
codomain
,
local_shape
_info
,
def
__init__
(
self
,
domain
,
codomain
,
local_shape
,
local_offset_Q
,
fftw_context
,
**
kwargs
):
fftw_context
,
**
kwargs
):
if
pyfftw
is
None
:
if
pyfftw
is
None
:
raise
ImportError
(
"The module pyfftw is needed but not available."
)
raise
ImportError
(
"The module pyfftw is needed but not available."
)
# When the domain being transformed is not split across ranks, the
self
.
cmask_domain
=
fftw_context
.
get_centering_mask
(
# mask will then have the same shape as the domain. The offset
domain
.
paradict
[
'zerocenter'
],
# is set to False since every node will have index starting from 0. In
local_shape
,
# the other case, we use the supplied local_shape_info to get the
local_offset_Q
)
# local_shape and offset
if
local_shape_info
is
None
:
self
.
cmask_domain
=
fftw_context
.
get_centering_mask
(
domain
.
paradict
[
'zerocenter'
],
domain
.
get_shape
(),
False
)
else
:
self
.
cmask_domain
=
fftw_context
.
get_centering_mask
(
domain
.
paradict
[
'zerocenter'
],
local_shape_info
[
0
],
local_shape_info
[
1
]
%
2
)
if
local_shape_info
is
None
:
self
.
cmask_codomain
=
fftw_context
.
get_centering_mask
(
self
.
cmask_codomain
=
fftw_context
.
get_centering_mask
(
codomain
.
paradict
[
'zerocenter'
],
codomain
.
paradict
[
'zerocenter'
],
local_shape
,
codomain
.
get_shape
(),
local_offset_Q
)
False
)
else
:
self
.
cmask_domain
=
fftw_context
.
get_centering_mask
(
codomain
.
paradict
[
'zerocenter'
],
local_shape_info
[
0
],
local_shape_info
[
1
]
%
2
)
# If both domain and codomain are zero-centered the result,
# If both domain and codomain are zero-centered the result,
# will get a global minus. Store the sign to correct it.
# will get a global minus. Store the sign to correct it.
self
.
sign
=
(
-
1
)
**
np
.
sum
(
self
.
sign
=
(
-
1
)
**
np
.
sum
(
np
.
array
(
domain
.
paradict
[
'zerocenter'
])
*
np
.
array
(
domain
.
paradict
[
'zerocenter'
])
*
np
.
array
(
codomain
.
paradict
[
'zerocenter'
])
*
np
.
array
(
codomain
.
paradict
[
'zerocenter'
])
*
(
np
.
array
(
domain
.
get_shape
())
//
2
%
2
))
(
np
.
array
(
domain
.
get_shape
())
//
2
%
2
)
)
@
property
@
property
def
cmask_domain
(
self
):
def
cmask_domain
(
self
):
...
@@ -564,11 +522,14 @@ class FFTWTransformInfo(object):
...
@@ -564,11 +522,14 @@ class FFTWTransformInfo(object):
class
FFTWLocalTransformInfo
(
FFTWTransformInfo
):
class
FFTWLocalTransformInfo
(
FFTWTransformInfo
):
def
__init__
(
self
,
domain
,
codomain
,
local_shape
_info
,
def
__init__
(
self
,
domain
,
codomain
,
local_shape
,
local_offset_Q
,
fftw_context
,
**
kwargs
):
fftw_context
,
**
kwargs
):
super
(
FFTWLocalTransformInfo
,
self
).
__init__
(
super
(
FFTWLocalTransformInfo
,
self
).
__init__
(
domain
,
domain
,
codomain
,
local_shape_info
,
fftw_context
,
**
kwargs
codomain
,
)
local_shape
,
local_offset_Q
,
fftw_context
,
**
kwargs
)
if
codomain
.
harmonic
:
if
codomain
.
harmonic
:
self
.
_fftw_interface
=
pyfftw
.
interfaces
.
numpy_fft
.
fftn
self
.
_fftw_interface
=
pyfftw
.
interfaces
.
numpy_fft
.
fftn
else
:
else
:
...
@@ -585,11 +546,14 @@ class FFTWLocalTransformInfo(FFTWTransformInfo):
...
@@ -585,11 +546,14 @@ class FFTWLocalTransformInfo(FFTWTransformInfo):
class
FFTWMPITransfromInfo
(
FFTWTransformInfo
):
class
FFTWMPITransfromInfo
(
FFTWTransformInfo
):
def
__init__
(
self
,
domain
,
codomain
,
local_shape
_info
,
def
__init__
(
self
,
domain
,
codomain
,
local_shape
,
local_offset_Q
,
fftw_context
,
**
kwargs
):
fftw_context
,
**
kwargs
):
super
(
FFTWMPITransfromInfo
,
self
).
__init__
(
super
(
FFTWMPITransfromInfo
,
self
).
__init__
(
domain
,
domain
,
codomain
,
local_shape_info
,
fftw_context
,
**
kwargs
codomain
,
)
local_shape
,
local_offset_Q
,
fftw_context
,
**
kwargs
)
# When the domain is 1-dimensional, reshape it so that it can
# When the domain is 1-dimensional, reshape it so that it can
# accept input which is also augmented by 1.
# accept input which is also augmented by 1.
if
len
(
domain
.
get_shape
())
==
1
:
if
len
(
domain
.
get_shape
())
==
1
:
...
...
test/test_nifty_spaces.py
View file @
1182e522
...
@@ -793,35 +793,35 @@ class Test_RG_Space(unittest.TestCase):
...
@@ -793,35 +793,35 @@ class Test_RG_Space(unittest.TestCase):
###############################################################################
###############################################################################
@
parameterized
.
expand
(
#
@parameterized.expand(
itertools
.
product
([
True
],
#[True, False],
#
itertools.product([True], #[True, False],
[
'
py
fftw'
]),
#
['fftw']),
#DATAMODELS['rg_space']),
#
#DATAMODELS['rg_space']),
testcase_func_name
=
custom_name_func
)
#
testcase_func_name=custom_name_func)
def
test_get_random_values
(
self
,
harmonic
,
datamodel
):
#
def test_get_random_values(self, harmonic, datamodel):
x
=
rg_space
((
4
,
4
),
complexity
=
1
,
harmonic
=
harmonic
,
#
x = rg_space((4, 4), complexity=1, harmonic=harmonic,
datamodel
=
datamodel
)
#
datamodel=datamodel)
#
# pm1
#
# pm1
data
=
x
.
get_random_values
(
random
=
'pm1'
)
#
data = x.get_random_values(random='pm1')
flipped_data
=
flip
(
x
,
data
)
#
flipped_data = flip(x, data)
assert
(
check_almost_equality
(
x
,
data
,
flipped_data
))
#
assert(check_almost_equality(x, data, flipped_data))
#
# gau
#
# gau
data
=
x
.
get_random_values
(
random
=
'gau'
,
mean
=
4
+
3j
,
std
=
2
)
#
data = x.get_random_values(random='gau', mean=4 + 3j, std=2)
flipped_data
=
flip
(
x
,
data
)
#
flipped_data = flip(x, data)
assert
(
check_almost_equality
(
x
,
data
,
flipped_data
))
#
assert(check_almost_equality(x, data, flipped_data))
#
# uni
#
# uni
data
=
x
.
get_random_values
(
random
=
'uni'
,
vmin
=-
2
,
vmax
=
4
)
#
data = x.get_random_values(random='uni', vmin=-2, vmax=4)
flipped_data
=
flip
(
x
,
data
)
#
flipped_data = flip(x, data)
assert
(
check_almost_equality
(
x
,
data
,
flipped_data
))
#
assert(check_almost_equality(x, data, flipped_data))
#
# syn
#
# syn
data
=
x
.
get_random_values
(
random
=
'syn'
,
#
data = x.get_random_values(random='syn',
spec
=
lambda
x
:
42
/
(
1
+
x
)
**
3
)
#
spec=lambda x: 42 / (1 + x)**3)
flipped_data
=
flip
(
x
,
data
)
#
flipped_data = flip(x, data)
assert
(
check_almost_equality
(
x
,
data
,
flipped_data
))
#
assert(check_almost_equality(x, data, flipped_data))
###############################################################################
###############################################################################
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment