def test_fspace_one(out_shape): """Check one element.""" fspace = FunctionSpace(odl.IntervalProd(0, 1), out_dtype=(float, out_shape)) points = _points(fspace.domain, 4) mesh_shape = (5, ) mesh = _meshgrid(fspace.domain, mesh_shape) point = 0.5 values_points_shape = out_shape + (4, ) values_point_shape = out_shape values_mesh_shape = out_shape + mesh_shape f_one = fspace.one() assert all_equal(f_one(points), np.ones(values_points_shape)) if not out_shape: assert f_one(point) == 1.0 else: assert all_equal(f_one(point), np.ones(values_point_shape)) assert all_equal(f_one(mesh), np.ones(values_mesh_shape)) out_points = np.empty(values_points_shape) out_mesh = np.empty(values_mesh_shape) f_one(points, out=out_points) f_one(mesh, out=out_mesh) assert all_equal(out_points, np.ones(values_points_shape)) assert all_equal(out_mesh, np.ones(values_mesh_shape))
def test_fspace_elem_power(power, out_shape): """Check taking powers of fspace elements.""" # Make sure test functions don't take negative values intv = odl.IntervalProd([1, 0], [2, 1]) fspace = FunctionSpace(intv, out_dtype=(float, out_shape)) points = _points(fspace.domain, 4) ndim = len(out_shape) with np.errstate(all='ignore'): if ndim == 0: f_elem = fspace.element(func_nd_oop) true_result = func_nd_ref(points)**power elif ndim == 1: f_elem = fspace.element(func_vec_nd_oop) true_result = func_vec_nd_ref(points)**power elif ndim == 2: f_elem = fspace.element(func_tens_oop) true_result = func_tens_ref(points)**power else: assert False # Out-of-place power f_elem_pow = f_elem**power assert all_almost_equal(f_elem_pow(points), true_result) out_arr = np.empty(out_shape + (4, )) f_elem_pow(points, out_arr) assert all_almost_equal(out_arr, true_result) # In-place power f_elem_pow = f_elem.copy() f_elem_pow **= power assert all_almost_equal(f_elem_pow(points), true_result) out_arr = np.empty(out_shape + (4, )) f_elem_pow(points, out_arr) assert all_almost_equal(out_arr, true_result)
def test_fspace_elem_real_imag_conj(out_shape): """Check taking real/imaginary parts of fspace elements.""" fspace = FunctionSpace(odl.IntervalProd(0, 1), out_dtype=(complex, out_shape)) ndim = len(out_shape) if ndim == 0: f_elem = fspace.element(func_complex_nd_oop) elif ndim == 1: f_elem = fspace.element(func_vec_complex_nd_oop) elif ndim == 2: f_elem = fspace.element(func_tens_complex_oop) else: assert False points = _points(fspace.domain, 4) mesh_shape = (5, ) mesh = _meshgrid(fspace.domain, mesh_shape) point = 0.5 values_points_shape = out_shape + (4, ) values_mesh_shape = out_shape + mesh_shape result_points = f_elem(points) result_point = f_elem(point) result_mesh = f_elem(mesh) assert all_almost_equal(f_elem.real(points), result_points.real) assert all_almost_equal(f_elem.real(point), result_point.real) assert all_almost_equal(f_elem.real(mesh), result_mesh.real) assert all_almost_equal(f_elem.imag(points), result_points.imag) assert all_almost_equal(f_elem.imag(point), result_point.imag) assert all_almost_equal(f_elem.imag(mesh), result_mesh.imag) assert all_almost_equal(f_elem.conj()(points), result_points.conj()) assert all_almost_equal(f_elem.conj()(point), np.conj(result_point)) assert all_almost_equal(f_elem.conj()(mesh), result_mesh.conj()) out_points = np.empty(values_points_shape, dtype=float) out_mesh = np.empty(values_mesh_shape, dtype=float) f_elem.real(points, out=out_points) f_elem.real(mesh, out=out_mesh) assert all_almost_equal(out_points, result_points.real) assert all_almost_equal(out_mesh, result_mesh.real) f_elem.imag(points, out=out_points) f_elem.imag(mesh, out=out_mesh) assert all_almost_equal(out_points, result_points.imag) assert all_almost_equal(out_mesh, result_mesh.imag) out_points = np.empty(values_points_shape, dtype=complex) out_mesh = np.empty(values_mesh_shape, dtype=complex) f_elem.conj()(points, out=out_points) f_elem.conj()(mesh, out=out_mesh) assert all_almost_equal(out_points, result_points.conj()) assert all_almost_equal(out_mesh, result_mesh.conj())
def test_addition(): fspace = FunctionSpace(odl.Interval(0, pi)) sine = fspace.element(np.sin) cosine = fspace.element(np.cos) sum_func = sine + cosine for x in [0.0, 0.2, 1.0]: assert almost_equal(sum_func(x), np.sin(x) + np.cos(x))
def test_fspace_vector_eval_complex(): rect, points, mg = _standard_setup_2d() fspace = FunctionSpace(rect, field=odl.ComplexNumbers()) f_novec = fspace.element(cfunc_2d_novec, vectorized=False) f_vec_oop = fspace.element(cfunc_2d_vec_oop, vectorized=True) f_vec_ip = fspace.element(cfunc_2d_vec_ip, vectorized=True) f_vec_dual = fspace.element(cfunc_2d_vec_dual, vectorized=True) true_arr = cfunc_2d_vec_oop(points) true_mg = cfunc_2d_vec_oop(mg) # Out-of-place assert f_novec([0.5, 1.5]) == cfunc_2d_novec([0.5, 1.5]) assert f_vec_oop([0.5, 1.5]) == cfunc_2d_novec([0.5, 1.5]) assert all_equal(f_vec_oop(points), true_arr) assert all_equal(f_vec_oop(mg), true_mg) # In-place standard implementation out_arr = np.empty((5,), dtype='complex128') out_mg = np.empty((2, 3), dtype='complex128') f_vec_oop(points, out=out_arr) f_vec_oop(mg, out=out_mg) assert all_equal(out_arr, true_arr) assert all_equal(out_mg, true_mg) with pytest.raises(TypeError): # ValueError: invalid vectorized input f_vec_oop(points[0]) # In-place only out_arr = np.empty((5,), dtype='complex128') out_mg = np.empty((2, 3), dtype='complex128') f_vec_ip(points, out=out_arr) f_vec_ip(mg, out=out_mg) assert all_equal(out_arr, true_arr) assert all_equal(out_mg, true_mg) # Standard out-of-place evaluation assert f_vec_ip([0.5, 1.5]) == cfunc_2d_novec([0.5, 1.5]) assert all_equal(f_vec_ip(points), true_arr) assert all_equal(f_vec_ip(mg), true_mg) # Dual use assert f_vec_dual([0.5, 1.5]) == cfunc_2d_novec([0.5, 1.5]) assert all_equal(f_vec_dual(points), true_arr) assert all_equal(f_vec_dual(mg), true_mg) out_arr = np.empty((5,), dtype='complex128') out_mg = np.empty((2, 3), dtype='complex128') f_vec_dual(points, out=out_arr) f_vec_dual(mg, out=out_mg) assert all_equal(out_arr, true_arr) assert all_equal(out_mg, true_mg)
def test_fspace_simple_attributes(): intv = odl.IntervalProd(0, 1) fspace = FunctionSpace(intv) fspace_r = FunctionSpace(intv, field=odl.RealNumbers()) fspace_c = FunctionSpace(intv, field=odl.ComplexNumbers()) assert fspace.domain == intv assert fspace.range == odl.RealNumbers() assert fspace_r.range == odl.RealNumbers() assert fspace_c.range == odl.ComplexNumbers()
def test_fspace_vector_equality(): rect = odl.IntervalProd([0, 0], [1, 2]) fspace = FunctionSpace(rect) f_novec = fspace.element(func_2d_novec, vectorized=False) f_vec_oop = fspace.element(func_2d_vec_oop, vectorized=True) f_vec_oop_2 = fspace.element(func_2d_vec_oop, vectorized=True) f_vec_ip = fspace.element(func_2d_vec_ip, vectorized=True) f_vec_ip_2 = fspace.element(func_2d_vec_ip, vectorized=True) f_vec_dual = fspace.element(func_2d_vec_dual, vectorized=True) f_vec_dual_2 = fspace.element(func_2d_vec_dual, vectorized=True) assert f_novec == f_novec assert f_novec != f_vec_oop assert f_novec != f_vec_ip assert f_novec != f_vec_dual assert f_vec_oop == f_vec_oop assert f_vec_oop == f_vec_oop_2 assert f_vec_oop != f_vec_ip assert f_vec_oop != f_vec_dual assert f_vec_ip == f_vec_ip assert f_vec_ip == f_vec_ip_2 assert f_vec_ip != f_vec_dual assert f_vec_dual == f_vec_dual assert f_vec_dual == f_vec_dual_2
def test_fspace_lincomb_vec_tens(a, b, out_shape): """Check linear combination in function spaces.""" if out_shape == (): return intv = odl.IntervalProd([0, 0], [1, 1]) fspace = FunctionSpace(intv, out_dtype=(float, out_shape)) points = _points(fspace.domain, 4) ndim = len(out_shape) if ndim == 1: f_elem1 = fspace.element(func_vec_nd_oop) f_elem2 = fspace.element(func_vec_nd_other) true_result = (a * func_vec_nd_ref(points) + b * func_vec_nd_other(points)) elif ndim == 2: f_elem1 = fspace.element(func_tens_oop) f_elem2 = fspace.element(func_tens_other) true_result = a * func_tens_ref(points) + b * func_tens_other(points) else: assert False out_func = fspace.element() fspace.lincomb(a, f_elem1, b, f_elem2, out_func) assert all_equal(out_func(points), true_result) out_arr = np.empty(out_shape + (4, )) out_func(points, out=out_arr) assert all_equal(out_arr, true_result)
def test_fspace_equality(): intv = odl.Interval(0, 1) intv2 = odl.Interval(-1, 1) fspace = FunctionSpace(intv) fspace_r = FunctionSpace(intv, field=odl.RealNumbers()) fspace_c = FunctionSpace(intv, field=odl.ComplexNumbers()) fspace_intv2 = FunctionSpace(intv2) assert fspace == fspace_r assert fspace != fspace_c assert fspace != fspace_intv2
def test_fspace_vector_ufunc(): intv = odl.IntervalProd(0, 1) points = _points(intv, num=5) mg = _meshgrid(intv, shape=(5, )) fspace = FunctionSpace(intv) f_vec = fspace.element(np.sin) assert f_vec(0.5) == np.sin(0.5) assert all_equal(f_vec(points), np.sin(points.squeeze())) assert all_equal(f_vec(mg), np.sin(mg[0]))
def test_fspace_vector_ufunc(): intv = odl.Interval(0, 1) points = _points(intv, num=5) mg = _meshgrid(intv, shape=(5,)) fspace = FunctionSpace(intv) f_vec = fspace.element(np.sin) assert f_vec(0.5) == np.sin(0.5) assert all_equal(f_vec(points), np.sin(points.squeeze())) assert all_equal(f_vec(mg), np.sin(mg[0]))
def test_interval(exponent): fspace = FunctionSpace(odl.Interval(0, pi)) lpdiscr = odl.uniform_discr(fspace, 10, exponent=exponent) if exponent == float("inf"): sine = fspace.element(np.sin) discr_sine = lpdiscr.element(sine) assert discr_sine.norm() <= 1 else: sine_p = fspace.element(lambda x: np.sin(x) ** (1 / exponent)) discr_sine_p = lpdiscr.element(sine_p) assert almost_equal(discr_sine_p.norm(), 2 ** (1 / exponent), places=2)
def test_rectangle(exponent): fspace = FunctionSpace(odl.Rectangle((0, 0), (pi, 2 * pi))) n, m = 10, 10 lpdiscr = odl.uniform_discr(fspace, (n, m), exponent=exponent) if exponent == float("inf"): sine2 = fspace.element(lambda x, y: np.sin(x) * np.sin(y)) discr_sine = lpdiscr.element(sine2) assert discr_sine.norm() <= 1 else: sine_p = fspace.element(lambda x, y: (np.sin(x) * np.sin(y)) ** (1 / exponent)) discr_sine_p = lpdiscr.element(sine_p) assert almost_equal(discr_sine_p.norm(), 4 ** (1 / exponent), places=2)
def test_fspace_vector_real_imag(): rect, _, mg = _standard_setup_2d() cspace = FunctionSpace(rect, field=odl.ComplexNumbers()) f = cspace.element(cfunc_2d_vec_oop) # real / imag on complex functions assert all_equal(f.real(mg), cfunc_2d_vec_oop(mg).real) assert all_equal(f.imag(mg), cfunc_2d_vec_oop(mg).imag) out_mg = np.empty((2, 3)) f.real(mg, out=out_mg) assert all_equal(out_mg, cfunc_2d_vec_oop(mg).real) f.imag(mg, out=out_mg) assert all_equal(out_mg, cfunc_2d_vec_oop(mg).imag) # real / imag on real functions, should be the function itself / zero rspace = FunctionSpace(rect) f = rspace.element(func_2d_vec_oop) assert all_equal(f.real(mg), f(mg)) assert all_equal(f.imag(mg), rspace.zero()(mg)) # Complex conjugate f = cspace.element(cfunc_2d_vec_oop) fbar = f.conj() assert all_equal(fbar(mg), cfunc_2d_vec_oop(mg).conj()) out_mg = np.empty((2, 3), dtype='complex128') fbar(mg, out=out_mg) assert all_equal(out_mg, cfunc_2d_vec_oop(mg).conj())
def test_fspace_vector_equality(): rect = odl.Rectangle([0, 0], [1, 2]) fspace = FunctionSpace(rect) f_novec = fspace.element(func_2d_novec, vectorized=False) f_vec_oop = fspace.element(func_2d_vec_oop, vectorized=True) f_vec_oop_2 = fspace.element(func_2d_vec_oop, vectorized=True) f_vec_ip = fspace.element(func_2d_vec_ip, vectorized=True) f_vec_ip_2 = fspace.element(func_2d_vec_ip, vectorized=True) f_vec_dual = fspace.element(func_2d_vec_dual, vectorized=True) f_vec_dual_2 = fspace.element(func_2d_vec_dual, vectorized=True) assert f_novec == f_novec assert f_novec != f_vec_oop assert f_novec != f_vec_ip assert f_novec != f_vec_dual assert f_vec_oop == f_vec_oop assert f_vec_oop == f_vec_oop_2 assert f_vec_oop != f_vec_ip assert f_vec_oop != f_vec_dual assert f_vec_ip == f_vec_ip assert f_vec_ip == f_vec_ip_2 assert f_vec_ip != f_vec_dual assert f_vec_dual == f_vec_dual assert f_vec_dual == f_vec_dual_2
def test_fspace_vector_arithmetic(variant, op): if variant == 'sv' and '=' in op: # makes no sense, quit return # Setup rect, points, mg = _standard_setup_2d() point = points.T[0] fspace = FunctionSpace(rect) a = -1.5 b = 2.0 array_out = np.empty((5, ), dtype=float) mg_out = np.empty((2, 3), dtype=float) # Initialize a bunch of elements f_novec = fspace.element(func_2d_novec, vectorized=False) f_vec = fspace.element(func_2d_vec_dual, vectorized=True) g_novec = fspace.element(other_func_2d_novec, vectorized=False) g_vec = fspace.element(other_func_2d_vec_dual, vectorized=True) out_novec = fspace.element(vectorized=False) out_vec = fspace.element(vectorized=True) if variant[0] == 'v': true_l_novec = func_2d_novec(point) true_l_arr = func_2d_vec_oop(points) true_l_mg = func_2d_vec_oop(mg) test_l_novec = f_novec test_l_vec = f_vec else: # 's' true_l_novec = true_l_arr = true_l_mg = a test_l_novec = test_l_vec = a if variant[1] == 'v': true_r_novec = other_func_2d_novec(point) true_r_arr = other_func_2d_vec_oop(points) true_r_mg = other_func_2d_vec_oop(mg) test_r_novec = g_novec test_r_vec = g_vec else: # 's' true_r_novec = true_r_arr = true_r_mg = b test_r_novec = test_r_vec = b true_novec = _op(true_l_novec, op, true_r_novec) true_arr = _op(true_l_arr, op, true_r_arr) true_mg = _op(true_l_mg, op, true_r_mg) out_novec = _op(test_l_novec, op, test_r_novec) out_vec = _op(test_l_vec, op, test_r_vec) assert almost_equal(out_novec(point), true_novec) assert all_equal(out_vec(points), true_arr) out_vec(points, out=array_out) assert all_equal(array_out, true_arr) assert all_equal(out_vec(mg), true_mg) out_vec(mg, out=mg_out) assert all_equal(mg_out, true_mg)
def test_fspace_vector_copy(): fspace = FunctionSpace(odl.IntervalProd(0, 1)) f_novec = fspace.element(func_1d_oop, vectorized=False) f_vec_ip = fspace.element(func_1d_ip, vectorized=True) f_vec_dual = fspace.element(func_1d_dual, vectorized=True) f_out = f_novec.copy() assert f_out == f_novec f_out = f_vec_ip.copy() assert f_out == f_vec_ip f_out = f_vec_dual.copy() assert f_out == f_vec_dual
def test_equals(): """Test equality check and hash.""" intv = odl.IntervalProd(0, 1) intv2 = odl.IntervalProd(-1, 1) fspace = FunctionSpace(intv) fspace_r = FunctionSpace(intv, field=odl.RealNumbers()) fspace_c = FunctionSpace(intv, field=odl.ComplexNumbers()) fspace_intv2 = FunctionSpace(intv2) _test_eq(fspace, fspace) _test_eq(fspace, fspace_r) _test_eq(fspace_c, fspace_c) _test_neq(fspace, fspace_c) _test_neq(fspace, fspace_intv2)
def test_fspace_vector_copy(): fspace = FunctionSpace(odl.Interval(0, 1)) f_novec = fspace.element(func_1d_oop, vectorized=False) f_vec_ip = fspace.element(func_1d_ip, vectorized=True) f_vec_dual = fspace.element(func_1d_dual, vectorized=True) f_out = f_novec.copy() assert f_out == f_novec f_out = f_vec_ip.copy() assert f_out == f_vec_ip f_out = f_vec_dual.copy() assert f_out == f_vec_dual
def test_fspace_elem_eval_unusual_dtypes(): """Check evaluation with unusual data types (int and string).""" str3 = odl.Strings(3) fspace = FunctionSpace(str3, out_dtype=int) strings = np.array(['aa', 'b', 'cab', 'aba']) out_vec = np.empty((4, ), dtype=int) # Vectorized for arrays only func_elem = fspace.element( lambda s: np.array([str(si).count('a') for si in s])) true_values = [2, 0, 1, 2] assert func_elem('abc') == 1 assert all_equal(func_elem(strings), true_values) func_elem(strings, out=out_vec) assert all_equal(out_vec, true_values)
def test_fspace_attributes(): """Check attribute access and correct values.""" intv = odl.IntervalProd(0, 1) # Scalar-valued function spaces fspace = FunctionSpace(intv) fspace_r = FunctionSpace(intv, out_dtype=float) fspace_c = FunctionSpace(intv, out_dtype=complex) fspace_s = FunctionSpace(intv, out_dtype='U1') scalar_spaces = (fspace, fspace_r, fspace_c, fspace_s) assert fspace.domain == intv assert fspace.field == odl.RealNumbers() assert fspace_r.field == odl.RealNumbers() assert fspace_c.field == odl.ComplexNumbers() assert fspace_s.field is None assert fspace.out_dtype == float assert fspace_r.out_dtype == float assert fspace_r.real_out_dtype == float assert fspace_r.complex_out_dtype == complex assert fspace_c.out_dtype == complex assert fspace_c.real_out_dtype == float assert fspace_c.complex_out_dtype == complex assert fspace_s.out_dtype == np.dtype('U1') assert fspace.is_real assert not fspace.is_complex assert fspace_r.is_real assert not fspace_r.is_complex assert fspace_c.is_complex assert not fspace_c.is_real with pytest.raises(AttributeError): fspace_s.real_out_dtype with pytest.raises(AttributeError): fspace_s.complex_out_dtype assert all(spc.scalar_out_dtype == spc.out_dtype for spc in scalar_spaces) assert all(spc.out_shape == () for spc in scalar_spaces) assert all(not spc.tensor_valued for spc in scalar_spaces) # Vector-valued function space fspace_vec = FunctionSpace(intv, out_dtype=(float, (2, ))) assert fspace_vec.field == odl.RealNumbers() assert fspace_vec.out_dtype == np.dtype((float, (2, ))) assert fspace_vec.scalar_out_dtype == float assert fspace_vec.out_shape == (2, ) assert fspace_vec.tensor_valued
def test_fspace_out_dtype(): rect = odl.IntervalProd([0, 0], [3, 5]) points = np.array([[0, 1], [0, 3], [3, 4], [2, 5]], dtype='int').T vec1 = np.array([0, 1, 3])[:, None] vec2 = np.array([1, 2, 4, 5])[None, :] mg = (vec1, vec2) true_arr = func_2d_vec_oop(points) true_mg = func_2d_vec_oop(mg) fspace = FunctionSpace(rect, out_dtype='int') f_vec = fspace.element(func_2d_vec_oop) assert all_equal(f_vec(points), true_arr) assert all_equal(f_vec(mg), true_mg) assert f_vec(points).dtype == np.dtype('int') assert f_vec(mg).dtype == np.dtype('int')
def test_fspace_out_dtype(): rect = odl.Rectangle([0, 0], [3, 5]) points = np.array([[0, 1], [0, 3], [3, 4], [2, 5]], dtype='int').T vec1 = np.array([0, 1, 3])[:, None] vec2 = np.array([1, 2, 4, 5])[None, :] mg = (vec1, vec2) true_arr = func_2d_vec_oop(points) true_mg = func_2d_vec_oop(mg) fspace = FunctionSpace(rect, out_dtype='int') f_vec = fspace.element(func_2d_vec_oop) assert all_equal(f_vec(points), true_arr) assert all_equal(f_vec(mg), true_mg) assert f_vec(points).dtype == np.dtype('int') assert f_vec(mg).dtype == np.dtype('int')
def test_equals(): """Test equality check and hash.""" intv = odl.IntervalProd(0, 1) intv2 = odl.IntervalProd(-1, 1) fspace = FunctionSpace(intv) fspace_r = FunctionSpace(intv, out_dtype=float) fspace_c = FunctionSpace(intv, out_dtype=complex) fspace_intv2 = FunctionSpace(intv2) fspace_vec = FunctionSpace(intv, out_dtype=(float, (2, ))) _test_eq(fspace, fspace) _test_eq(fspace, fspace_r) _test_eq(fspace_c, fspace_c) _test_neq(fspace, fspace_c) _test_neq(fspace, fspace_intv2) _test_neq(fspace_r, fspace_vec)
def test_fspace_elem_vectorized_init(vectorized): """Check init of fspace elements with(out) vectorization.""" intv = odl.IntervalProd(0, 1) fspace_scal = FunctionSpace(intv) fspace_scal.element(func_nd_oop, vectorized=vectorized) fspace_vec = FunctionSpace(intv, out_dtype=(float, (2, ))) fspace_vec.element(func_vec_nd_oop, vectorized=vectorized) fspace_vec.element(func_nd_oop_seq, vectorized=vectorized)
def test_fspace_one(): rect, points, mg = _standard_setup_2d() # real fspace = FunctionSpace(rect) one_vec = fspace.one() assert one_vec([0.5, 1.5]) == 1.0 assert all_equal(one_vec(points), np.ones(5, dtype=float)) assert all_equal(one_vec(mg), np.ones((2, 3), dtype=float)) # complex fspace = FunctionSpace(rect, field=odl.ComplexNumbers()) one_vec = fspace.one() assert one_vec([0.5, 1.5]) == 1.0 + 1j * 0.0 assert all_equal(one_vec(points), np.ones(5, dtype=complex)) assert all_equal(one_vec(mg), np.ones((2, 3), dtype=complex))
def test_fspace_vec_elem_eval(func_vec_nd, out_dtype): """Check evaluation of scalar-valued function elements.""" intv = odl.IntervalProd([0, 0], [1, 1]) fspace_vec = FunctionSpace(intv, out_dtype=(float, (2, ))) points = _points(fspace_vec.domain, 3) mesh_shape = (2, 3) mesh = _meshgrid(fspace_vec.domain, mesh_shape) point = [0.5, 0.5] values_points_shape = (2, 3) values_mesh_shape = (2, 2, 3) func_ref, func = func_vec_nd true_values_points = func_ref(points) true_values_mesh = func_ref(mesh) true_value_point = func_ref(point) func_elem = fspace_vec.element(func) # Out of place result_points = func_elem(points) result_mesh = func_elem(mesh) assert all_almost_equal(result_points, true_values_points) assert all_almost_equal(result_mesh, true_values_mesh) assert result_points.dtype == fspace_vec.scalar_out_dtype assert result_mesh.dtype == fspace_vec.scalar_out_dtype assert result_points.flags.writeable assert result_mesh.flags.writeable # In place out_points = np.empty(values_points_shape, dtype=fspace_vec.scalar_out_dtype) out_mesh = np.empty(values_mesh_shape, dtype=fspace_vec.scalar_out_dtype) func_elem(points, out=out_points) func_elem(mesh, out=out_mesh) assert all_almost_equal(out_points, true_values_points) assert all_almost_equal(out_mesh, true_values_mesh) # Single point evaluation result_point = func_elem(point) assert all_almost_equal(result_point, true_value_point) out_point = np.empty((2, ), dtype=fspace_vec.scalar_out_dtype) func_elem(point, out=out_point) assert all_almost_equal(out_point, true_value_point)
def test_fspace_vector_arithmetic(variant, op): if variant == 'sv' and '=' in op: # makes no sense, quit return # Setup rect, points, mg = _standard_setup_2d() point = points.T[0] fspace = FunctionSpace(rect) a = -1.5 b = 2.0 array_out = np.empty((5,), dtype=float) mg_out = np.empty((2, 3), dtype=float) # Initialize a bunch of elements f_novec = fspace.element(func_2d_novec, vectorized=False) f_vec = fspace.element(func_2d_vec_dual, vectorized=True) g_novec = fspace.element(other_func_2d_novec, vectorized=False) g_vec = fspace.element(other_func_2d_vec_dual, vectorized=True) out_novec = fspace.element(vectorized=False) out_vec = fspace.element(vectorized=True) if variant[0] == 'v': true_l_novec = func_2d_novec(point) true_l_arr = func_2d_vec_oop(points) true_l_mg = func_2d_vec_oop(mg) test_l_novec = f_novec test_l_vec = f_vec else: # 's' true_l_novec = true_l_arr = true_l_mg = a test_l_novec = test_l_vec = a if variant[1] == 'v': true_r_novec = other_func_2d_novec(point) true_r_arr = other_func_2d_vec_oop(points) true_r_mg = other_func_2d_vec_oop(mg) test_r_novec = g_novec test_r_vec = g_vec else: # 's' true_r_novec = true_r_arr = true_r_mg = b test_r_novec = test_r_vec = b true_novec = _op(true_l_novec, op, true_r_novec) true_arr = _op(true_l_arr, op, true_r_arr) true_mg = _op(true_l_mg, op, true_r_mg) out_novec = _op(test_l_novec, op, test_r_novec) out_vec = _op(test_l_vec, op, test_r_vec) assert almost_equal(out_novec(point), true_novec) assert all_equal(out_vec(points), true_arr) out_vec(points, out=array_out) assert all_equal(array_out, true_arr) assert all_equal(out_vec(mg), true_mg) out_vec(mg, out=mg_out) assert all_equal(mg_out, true_mg)
def test_fspace_elem_eval_vec_1d(func_vec_1d): """Test evaluation in 1d since it's a corner case regarding shapes.""" intv = odl.IntervalProd(0, 1) fspace_vec = FunctionSpace(intv, out_dtype=(float, (2, ))) points = _points(fspace_vec.domain, 3) mesh_shape = (4, ) mesh = _meshgrid(fspace_vec.domain, mesh_shape) point1 = 0.5 point2 = [0.5] values_points_shape = (2, 3) values_mesh_shape = (2, 4) value_point_shape = (2, ) func_ref, func = func_vec_1d true_result_points = np.array(func_ref(points)) true_result_mesh = np.array(func_ref(mesh)) true_result_point = np.array(func_ref(np.array([point1]))).squeeze() func_elem = fspace_vec.element(func) result_points = func_elem(points) result_mesh = func_elem(mesh) result_point1 = func_elem(point1) result_point2 = func_elem(point2) assert all_almost_equal(result_points, true_result_points) assert all_almost_equal(result_mesh, true_result_mesh) assert all_almost_equal(result_point1, true_result_point) assert all_almost_equal(result_point2, true_result_point) out_points = np.empty(values_points_shape, dtype=float) out_mesh = np.empty(values_mesh_shape, dtype=float) out_point1 = np.empty(value_point_shape, dtype=float) out_point2 = np.empty(value_point_shape, dtype=float) func_elem(points, out=out_points) func_elem(mesh, out=out_mesh) func_elem(point1, out=out_point1) func_elem(point2, out=out_point2) assert all_almost_equal(out_points, true_result_points) assert all_almost_equal(out_mesh, true_result_mesh) assert all_almost_equal(out_point1, true_result_point) assert all_almost_equal(out_point2, true_result_point)
def test_fspace_power(power): rect, points, mg = _standard_setup_2d() point = points.T[0] out_arr = np.empty(5) out_mg = np.empty((2, 3)) fspace = FunctionSpace(rect) # Not vectorized true_novec = func_2d_novec(point)**power f_novec = fspace.element(func_2d_novec, vectorized=False) pow_novec = f_novec**power assert almost_equal(pow_novec(point), true_novec) pow_novec = f_novec.copy() pow_novec **= power assert almost_equal(pow_novec(point), true_novec) # Vectorized true_arr = func_2d_vec_oop(points)**power true_mg = func_2d_vec_oop(mg)**power f_vec = fspace.element(func_2d_vec_dual, vectorized=True) pow_vec = f_vec**power assert all_almost_equal(pow_vec(points), true_arr) assert all_almost_equal(pow_vec(mg), true_mg) pow_vec = f_vec.copy() pow_vec **= power assert all_almost_equal(pow_vec(points), true_arr) assert all_almost_equal(pow_vec(mg), true_mg) pow_vec(points, out=out_arr) pow_vec(mg, out=out_mg) assert all_almost_equal(out_arr, true_arr) assert all_almost_equal(out_mg, true_mg)
def test_fspace_power(power): rect, points, mg = _standard_setup_2d() point = points.T[0] out_arr = np.empty(5) out_mg = np.empty((2, 3)) fspace = FunctionSpace(rect) # Not vectorized true_novec = func_2d_novec(point) ** power f_novec = fspace.element(func_2d_novec, vectorized=False) pow_novec = f_novec ** power assert almost_equal(pow_novec(point), true_novec) pow_novec = f_novec.copy() pow_novec **= power assert almost_equal(pow_novec(point), true_novec) # Vectorized true_arr = func_2d_vec_oop(points) ** power true_mg = func_2d_vec_oop(mg) ** power f_vec = fspace.element(func_2d_vec_dual, vectorized=True) pow_vec = f_vec ** power assert all_almost_equal(pow_vec(points), true_arr) assert all_almost_equal(pow_vec(mg), true_mg) pow_vec = f_vec.copy() pow_vec **= power assert all_almost_equal(pow_vec(points), true_arr) assert all_almost_equal(pow_vec(mg), true_mg) pow_vec(points, out=out_arr) pow_vec(mg, out=out_mg) assert all_almost_equal(out_arr, true_arr) assert all_almost_equal(out_mg, true_mg)
def test_fspace_astype(): rspace = FunctionSpace(odl.Interval(0, 1)) cspace = FunctionSpace(odl.Interval(0, 1), field=odl.ComplexNumbers()) rspace_s = FunctionSpace(odl.Interval(0, 1), out_dtype='float32') cspace_s = FunctionSpace(odl.Interval(0, 1), out_dtype='complex64') assert rspace.astype('complex64') == cspace_s assert rspace.astype('complex128') == cspace assert rspace.astype('complex128') is rspace._complex_space assert rspace.astype('float32') == rspace_s assert rspace.astype('float64') is rspace._real_space assert cspace.astype('float32') == rspace_s assert cspace.astype('float64') == rspace assert cspace.astype('float64') is cspace._real_space assert cspace.astype('complex64') == cspace_s assert cspace.astype('complex128') is cspace._complex_space
def test_fspace_tens_eval(func_tens): """Test tensor-valued function evaluation.""" intv = odl.IntervalProd([0, 0], [1, 1]) fspace_tens = FunctionSpace(intv, out_dtype=(float, (2, 3))) points = _points(fspace_tens.domain, 4) mesh_shape = (4, 5) mesh = _meshgrid(fspace_tens.domain, mesh_shape) point = [0.5, 0.5] values_points_shape = (2, 3, 4) values_mesh_shape = (2, 3, 4, 5) value_point_shape = (2, 3) func_ref, func = func_tens true_result_points = np.array(func_ref(points)) true_result_mesh = np.array(func_ref(mesh)) true_result_point = np.array(func_ref(np.array(point)[:, None])).squeeze() func_elem = fspace_tens.element(func) result_points = func_elem(points) result_mesh = func_elem(mesh) result_point = func_elem(point) assert all_almost_equal(result_points, true_result_points) assert all_almost_equal(result_mesh, true_result_mesh) assert all_almost_equal(result_point, true_result_point) assert result_points.flags.writeable assert result_mesh.flags.writeable assert result_point.flags.writeable out_points = np.empty(values_points_shape, dtype=float) out_mesh = np.empty(values_mesh_shape, dtype=float) out_point = np.empty(value_point_shape, dtype=float) func_elem(points, out=out_points) func_elem(mesh, out=out_mesh) func_elem(point, out=out_point) assert all_almost_equal(out_points, true_result_points) assert all_almost_equal(out_mesh, true_result_mesh) assert all_almost_equal(out_point, true_result_point)
def test_fspace_vector_eval_complex(): rect, points, mg = _standard_setup_2d() fspace = FunctionSpace(rect, field=odl.ComplexNumbers()) f_novec = fspace.element(cfunc_2d_novec, vectorized=False) f_vec_oop = fspace.element(cfunc_2d_vec_oop, vectorized=True) f_vec_ip = fspace.element(cfunc_2d_vec_ip, vectorized=True) f_vec_dual = fspace.element(cfunc_2d_vec_dual, vectorized=True) true_arr = cfunc_2d_vec_oop(points) true_mg = cfunc_2d_vec_oop(mg) # Out-of-place assert f_novec([0.5, 1.5]) == cfunc_2d_novec([0.5, 1.5]) assert f_vec_oop([0.5, 1.5]) == cfunc_2d_novec([0.5, 1.5]) assert all_equal(f_vec_oop(points), true_arr) assert all_equal(f_vec_oop(mg), true_mg) # In-place standard implementation out_arr = np.empty((5, ), dtype='complex128') out_mg = np.empty((2, 3), dtype='complex128') f_vec_oop(points, out=out_arr) f_vec_oop(mg, out=out_mg) assert all_equal(out_arr, true_arr) assert all_equal(out_mg, true_mg) with pytest.raises(TypeError): # ValueError: invalid vectorized input f_vec_oop(points[0]) # In-place-only out_arr = np.empty((5, ), dtype='complex128') out_mg = np.empty((2, 3), dtype='complex128') f_vec_ip(points, out=out_arr) f_vec_ip(mg, out=out_mg) assert all_equal(out_arr, true_arr) assert all_equal(out_mg, true_mg) # Standard out-of-place evaluation assert f_vec_ip([0.5, 1.5]) == cfunc_2d_novec([0.5, 1.5]) assert all_equal(f_vec_ip(points), true_arr) assert all_equal(f_vec_ip(mg), true_mg) # Dual use assert f_vec_dual([0.5, 1.5]) == cfunc_2d_novec([0.5, 1.5]) assert all_equal(f_vec_dual(points), true_arr) assert all_equal(f_vec_dual(mg), true_mg) out_arr = np.empty((5, ), dtype='complex128') out_mg = np.empty((2, 3), dtype='complex128') f_vec_dual(points, out=out_arr) f_vec_dual(mg, out=out_mg) assert all_equal(out_arr, true_arr) assert all_equal(out_mg, true_mg)
def test_fspace_vector_assign(): fspace = FunctionSpace(odl.Interval(0, 1)) f_novec = fspace.element(func_1d_oop, vectorized=False) f_vec_ip = fspace.element(func_1d_ip, vectorized=True) f_vec_dual = fspace.element(func_1d_dual, vectorized=True) f_out = fspace.element() f_out.assign(f_novec) assert f_out == f_novec f_out = fspace.element() f_out.assign(f_vec_ip) assert f_out == f_vec_ip f_out = fspace.element() f_out.assign(f_vec_dual) assert f_out == f_vec_dual
def test_fspace_init(): """Check if all initialization patterns work.""" intv = odl.IntervalProd(0, 1) FunctionSpace(intv) FunctionSpace(intv, out_dtype=float) FunctionSpace(intv, out_dtype=complex) FunctionSpace(intv, out_dtype=(float, (2, 3))) str3 = odl.Strings(3) FunctionSpace(str3, out_dtype=int) # Make sure repr shows something assert repr(FunctionSpace(intv, out_dtype=(float, (2, 3))))
def test_fspace_vector_assign(): fspace = FunctionSpace(odl.IntervalProd(0, 1)) f_novec = fspace.element(func_1d_oop, vectorized=False) f_vec_ip = fspace.element(func_1d_ip, vectorized=True) f_vec_dual = fspace.element(func_1d_dual, vectorized=True) f_out = fspace.element() f_out.assign(f_novec) assert f_out == f_novec f_out = fspace.element() f_out.assign(f_vec_ip) assert f_out == f_vec_ip f_out = fspace.element() f_out.assign(f_vec_dual) assert f_out == f_vec_dual
def test_fspace_elem_arithmetic(odl_arithmetic_op, out_shape): """Test arithmetic of fspace elements.""" op = odl_arithmetic_op intv = odl.IntervalProd([1, 0], [2, 1]) fspace = FunctionSpace(intv, out_dtype=(float, out_shape)) points = _points(fspace.domain, 4) ndim = len(out_shape) if ndim == 0: f_elem1 = fspace.element(func_nd_oop) f_elem2 = fspace.element(func_nd_other) elif ndim == 1: f_elem1 = fspace.element(func_vec_nd_oop) f_elem2 = fspace.element(func_vec_nd_other) elif ndim == 2: f_elem1 = fspace.element(func_tens_oop) f_elem2 = fspace.element(func_tens_other) else: assert False result1 = f_elem1(points) result1_cpy = result1.copy() result2 = f_elem2(points) true_result_func = op(result1, result2) true_result_scal = op(result1_cpy, -2.0) f_elem1_cpy = f_elem1.copy() func_arith_func = op(f_elem1, f_elem2) func_arith_scal = op(f_elem1_cpy, -2.0) assert all_almost_equal(func_arith_func(points), true_result_func) assert all_almost_equal(func_arith_scal(points), true_result_scal) out_arr_func = np.empty(out_shape + (4, )) out_arr_scal = np.empty(out_shape + (4, )) func_arith_func(points, out=out_arr_func) func_arith_scal(points, out=out_arr_scal) assert all_almost_equal(out_arr_func, true_result_func) assert all_almost_equal(out_arr_scal, true_result_scal)
def test_fspace_scal_elem_with_param_eval(func_param_nd): """Check evaluation of scalar-valued function elements with parameters.""" intv = odl.IntervalProd([0, 0], [1, 1]) fspace_scal = FunctionSpace(intv) points = _points(fspace_scal.domain, 3) mesh_shape = (2, 3) mesh = _meshgrid(fspace_scal.domain, mesh_shape) func_ref, func = func_param_nd true_values_points = func_ref(points, c=2.5) true_values_mesh = func_ref(mesh, c=2.5) func_elem = fspace_scal.element(func) # Out of place result_points = func_elem(points, c=2.5) result_mesh = func_elem(mesh, c=2.5) assert all_almost_equal(result_points, true_values_points) assert all_almost_equal(result_mesh, true_values_mesh) # In place out_points = np.empty(3, dtype=fspace_scal.scalar_out_dtype) out_mesh = np.empty(mesh_shape, dtype=fspace_scal.scalar_out_dtype) func_elem(points, out=out_points, c=2.5) func_elem(mesh, out=out_mesh, c=2.5) assert all_almost_equal(out_points, true_values_points) assert all_almost_equal(out_mesh, true_values_mesh) # Complex output fspace_complex = FunctionSpace(intv, out_dtype=complex) true_values_points = func_ref(points, c=2j) true_values_mesh = func_ref(mesh, c=2j) func_elem = fspace_complex.element(func) result_points = func_elem(points, c=2j) result_mesh = func_elem(mesh, c=2j) assert all_almost_equal(result_points, true_values_points) assert all_almost_equal(result_mesh, true_values_mesh)
def test_fspace_lincomb_scalar(a, b): """Check linear combination in function spaces. Note: Special cases and more alignment options are tested later in the special methods like ``__add__``. """ intv = odl.IntervalProd([0, 0], [1, 1]) fspace = FunctionSpace(intv) points = _points(fspace.domain, 4) true_result = a * func_nd_oop(points) + b * func_nd_bcast_ref(points) # Non-vectorized evaluation, checking with `out` array and without. f_elem1_novec = fspace.element(func_nd_oop, vectorized=False) f_elem2_novec = fspace.element(func_nd_bcast_oop, vectorized=False) out_novec = fspace.element(vectorized=False) fspace.lincomb(a, f_elem1_novec, b, f_elem2_novec, out_novec) assert all_equal(out_novec(points), true_result) out_arr = np.empty(4) out_novec(points, out=out_arr) assert all_equal(out_arr, true_result) # Vectorized evaluation with definition from out-of-place (oop), # in-place (ip) and dual-use (dual) versions of Python functions. # Checking evaluation with `out` array and without. # out-of-place f_elem1_oop = fspace.element(func_nd_oop) f_elem2_oop = fspace.element(func_nd_bcast_oop) out_oop = fspace.element() fspace.lincomb(a, f_elem1_oop, b, f_elem2_oop, out_oop) assert all_equal(out_oop(points), true_result) out_arr = np.empty(4) out_oop(points, out=out_arr) assert all_equal(out_arr, true_result) # in-place f_elem1_ip = fspace.element(func_nd_ip) f_elem2_ip = fspace.element(func_nd_bcast_ip) out_ip = fspace.element() fspace.lincomb(a, f_elem1_ip, b, f_elem2_ip, out_ip) assert all_equal(out_ip(points), true_result) out_arr = np.empty(4) out_ip(points, out=out_arr) assert all_equal(out_arr, true_result) # dual f_elem1_dual = fspace.element(func_nd_dual) f_elem2_dual = fspace.element(func_nd_bcast_dual) out_dual = fspace.element() fspace.lincomb(a, f_elem1_dual, b, f_elem2_dual, out_dual) assert all_equal(out_dual(points), true_result) out_arr = np.empty(4) out_dual(points, out=out_arr) assert all_equal(out_arr, true_result) # Check mixing vectorized and non-vectorized functions out = fspace.element() fspace.lincomb(a, f_elem1_oop, b, f_elem2_novec, out) assert all_equal(out(points), true_result) out_arr = np.empty(4) out(points, out=out_arr) assert all_equal(out_arr, true_result) # Alignment options # out = a * out + b * f2, out = f1.copy() -> same as before out = f_elem1_oop.copy() fspace.lincomb(a, out, b, f_elem2_oop, out) true_result_aligned = true_result assert all_equal(out(points), true_result_aligned) # out = a * f1 + b * out, out = f2.copy() -> same as before out = f_elem2_oop.copy() fspace.lincomb(a, f_elem1_oop, b, out, out) true_result_aligned = true_result assert all_equal(out(points), true_result_aligned) # out = a * out + b * out out = f_elem1_oop.copy() fspace.lincomb(a, out, b, out, out) true_result_aligned = (a + b) * f_elem1_oop(points) assert all_equal(out(points), true_result_aligned) # out = a * f1 + b * f1 out = fspace.element() fspace.lincomb(a, f_elem1_oop, b, f_elem1_oop, out) true_result_aligned = (a + b) * f_elem1_oop(points) assert all_equal(out(points), true_result_aligned)
def test_fspace_elem_copy(out_shape): """Check copying of fspace elements.""" fspace = FunctionSpace(odl.IntervalProd(0, 1), out_dtype=(float, out_shape)) ndim = len(out_shape) if ndim == 0: f_oop = fspace.element(func_nd_oop) f_ip = fspace.element(func_nd_ip) f_dual = fspace.element(func_nd_dual) elif ndim == 1: f_oop = fspace.element(func_vec_nd_oop) f_ip = fspace.element(func_vec_nd_ip) f_dual = fspace.element(func_vec_nd_dual) elif ndim == 2: f_oop = fspace.element(func_tens_oop) f_ip = fspace.element(func_tens_ip) f_dual = fspace.element(func_tens_dual) else: assert False f_out = f_oop.copy() assert f_out == f_oop f_out = f_ip.copy() assert f_out == f_ip f_out = f_dual.copy() assert f_out == f_dual
def fspace_scal(domain_ndim, out_dtype): """Fixture returning a function space with given properties.""" domain = odl.IntervalProd([0] * domain_ndim, [1] * domain_ndim) return FunctionSpace(domain, out_dtype=out_dtype)
def test_fspace_vector_init(): # 1d, real intv = odl.Interval(0, 1) fspace = FunctionSpace(intv) fspace.element(func_1d_oop) fspace.element(func_1d_oop, vectorized=False) fspace.element(func_1d_oop, vectorized=True) fspace.element(func_1d_ip, vectorized=True) fspace.element(func_1d_dual, vectorized=True) # 2d, real rect = odl.Rectangle([0, 0], [1, 2]) fspace = FunctionSpace(rect) fspace.element(func_2d_novec, vectorized=False) fspace.element(func_2d_vec_oop) fspace.element(func_2d_vec_oop, vectorized=True) fspace.element(func_2d_vec_ip, vectorized=True) fspace.element(func_2d_vec_dual, vectorized=True) # 2d, complex fspace = FunctionSpace(rect, field=odl.ComplexNumbers()) fspace.element(cfunc_2d_novec, vectorized=False) fspace.element(cfunc_2d_vec_oop) fspace.element(cfunc_2d_vec_oop, vectorized=True) fspace.element(cfunc_2d_vec_ip, vectorized=True) fspace.element(cfunc_2d_vec_dual, vectorized=True)
def test_fspace_lincomb(a, b): rect, points, mg = _standard_setup_2d() point = points.T[0] fspace = FunctionSpace(rect) # Note: Special cases and alignment are tested later in the magic methods # Not vectorized true_novec = a * func_2d_novec(point) + b * other_func_2d_novec(point) f_novec = fspace.element(func_2d_novec, vectorized=False) g_novec = fspace.element(other_func_2d_novec, vectorized=False) out_novec = fspace.element(vectorized=False) fspace.lincomb(a, f_novec, b, g_novec, out_novec) assert almost_equal(out_novec(point), true_novec) # Vectorized true_arr = (a * func_2d_vec_oop(points) + b * other_func_2d_vec_oop(points)) true_mg = (a * func_2d_vec_oop(mg) + b * other_func_2d_vec_oop(mg)) # Out-of-place f_vec_oop = fspace.element(func_2d_vec_oop, vectorized=True) g_vec_oop = fspace.element(other_func_2d_vec_oop, vectorized=True) out_vec = fspace.element() fspace.lincomb(a, f_vec_oop, b, g_vec_oop, out_vec) assert all_equal(out_vec(points), true_arr) assert all_equal(out_vec(mg), true_mg) assert almost_equal(out_vec(point), true_novec) out_arr = np.empty((5,), dtype=float) out_mg = np.empty((2, 3), dtype=float) out_vec(points, out=out_arr) out_vec(mg, out=out_mg) assert all_equal(out_arr, true_arr) assert all_equal(out_mg, true_mg) # In-place f_vec_ip = fspace.element(func_2d_vec_ip, vectorized=True) g_vec_ip = fspace.element(other_func_2d_vec_ip, vectorized=True) out_vec = fspace.element() fspace.lincomb(a, f_vec_ip, b, g_vec_ip, out_vec) assert all_equal(out_vec(points), true_arr) assert all_equal(out_vec(mg), true_mg) assert almost_equal(out_vec(point), true_novec) out_arr = np.empty((5,), dtype=float) out_mg = np.empty((2, 3), dtype=float) out_vec(points, out=out_arr) out_vec(mg, out=out_mg) assert all_equal(out_arr, true_arr) assert all_equal(out_mg, true_mg) # Dual use f_vec_dual = fspace.element(func_2d_vec_dual, vectorized=True) g_vec_dual = fspace.element(other_func_2d_vec_dual, vectorized=True) out_vec = fspace.element() fspace.lincomb(a, f_vec_dual, b, g_vec_dual, out_vec) assert all_equal(out_vec(points), true_arr) assert all_equal(out_vec(mg), true_mg) assert almost_equal(out_vec(point), true_novec) out_arr = np.empty((5,), dtype=float) out_mg = np.empty((2, 3), dtype=float) out_vec(points, out=out_arr) out_vec(mg, out=out_mg) assert all_equal(out_arr, true_arr) assert all_equal(out_mg, true_mg) # Mix of vectorized and non-vectorized -> manual vectorization fspace.lincomb(a, f_vec_dual, b, g_novec, out_vec) assert all_equal(out_vec(points), true_arr) assert all_equal(out_vec(mg), true_mg)