|
15 | 15 | #include <complex> |
16 | 16 | #include <cstddef> |
17 | 17 | #include <cstdint> |
| 18 | +#include <type_traits> |
18 | 19 | #include <utility> |
19 | 20 | #include <vector> |
20 | 21 |
|
@@ -218,6 +219,32 @@ BOOST_AUTO_TEST_CASE(squared_norm_sums_squares) { |
218 | 219 | BOOST_CHECK_EQUAL(TA::squared_norm(x), 9.0); |
219 | 220 | } |
220 | 221 |
|
| 222 | +// A squared norm is sum |z|^2 -- real and non-negative -- not the complex |
| 223 | +// sum z^2. Summing z*z would give (3+4i)^2 + (1-2i)^2 = (-7+24i) + (-3-4i) |
| 224 | +// = -10+20i here; the magnitudes give 25 + 5 = 30. The return type is |
| 225 | +// likewise the real scalar type, not the element type. |
| 226 | +BOOST_AUTO_TEST_CASE(squared_norm_of_complex_sums_magnitudes) { |
| 227 | + using Z = std::complex<double>; |
| 228 | + using ZInner = TA::ArenaTensor<Z, TA::Range>; |
| 229 | + |
| 230 | + // CellBuf above is specific to `Inner` (double cells); size and align a |
| 231 | + // buffer for a complex cell the same way. |
| 232 | + const std::size_t total = ZInner::cell_size(2); |
| 233 | + const std::size_t algn = ZInner::cell_alignment(); |
| 234 | + std::vector<std::byte> bytes(total + algn, std::byte{0}); |
| 235 | + auto base = reinterpret_cast<std::uintptr_t>(bytes.data()); |
| 236 | + auto* aligned = reinterpret_cast<std::byte*>((base + algn - 1) & ~(algn - 1)); |
| 237 | + |
| 238 | + ZInner x = TA::detail::make_arena_tensor_in<Z>(aligned, TA::Range{2}); |
| 239 | + x.data()[0] = Z(3.0, 4.0); |
| 240 | + x.data()[1] = Z(1.0, -2.0); |
| 241 | + |
| 242 | + const auto sq = TA::squared_norm(x); |
| 243 | + static_assert(std::is_same_v<std::remove_const_t<decltype(sq)>, double>, |
| 244 | + "squared_norm must return the real scalar type"); |
| 245 | + BOOST_CHECK_CLOSE(sq, 30.0, 1e-12); |
| 246 | +} |
| 247 | + |
221 | 248 | BOOST_AUTO_TEST_CASE(in_place_cpos_no_op_on_null) { |
222 | 249 | Inner null; |
223 | 250 | TA::zero(null); |
|
0 commit comments