Как использовать boost::compute::atan2?
Я хотел бы вычислить фазу комплексного числа, используя boost::compute
вот моя попытка, я ожидаю, что результат будет равен atan2(0.5f):
namespace bc = boost::compute;
bc::vector<std::complex<float>> vec{ {1.0f, 2.0f} };
bc::vector<float> result(1);
bc::transform(vec.begin(), vec.end(), result.begin(), bc::atan2<float>());
но я получаю ошибку компиляции, утверждая, что "не унарная функция вызвала один аргумент"
3 ответа
Я нашел способ заставить это работать.
1 этап: выделить 2 вектора:
bc::vector<std::complex<float>> vec{ {1.0f, 2.0f}, {3.0f, 4.0f}, {5.0f, 6.0f} };
bc::vector<float> result(3);
2 этап: интерпретировать сложный вектор как итератор плавающего буфера
buffer_iterator
Это очень полезно, когда у вас есть строго типизированный вектор, и вы хотите передать его алгоритму другого типа.
auto beginf = bc::make_buffer_iterator<float>(vec.get_buffer(), 0);
auto endf = bc::make_buffer_iterator<float>(vec.get_buffer(), 6); // note end point to final index + 1
Этап 3: определить пошаговые итераторы, чтобы мы могли использовать тот же буфер, что и аргумент для tan2. каждый итератор выполняет итерации буферов с шагом в 2 индекса, и они обеспечивают tan2 с чередованным доступом к буферу:
auto begin_a = bc::make_strided_iterator(beginf + 1, 2); // access imaginary part
auto end_a = bc::make_strided_iterator_end(beginf + 1, endf , 2);
auto begin_b = bc::make_strided_iterator(beginf, 2); // access real part
наконец, вызовите transform:
bc::transform(begin_a, end_a, begin_b, result.begin(), bc::atan2<float>()); // atan(b/a)
bc::system::default_queue().finish();
boost::compute
"s atan2
казалось бы, двоичная функция так же, как std::atan2
,
Я предполагаю, что вы пытаетесь получить фазовый угол вашего комплексного числа? Стандартная функция C++ для этого будет std::arg()
- Я не вижу, чтобы это определялось в boost::compute
хотя я, возможно, пропустил это.
Если arg()
действительно отсутствует, вы совершенно правы, это реализовано с помощью atan2
- вам нужно будет извлечь мнимое (boost::compute::imag()
) и реальный (boost::compute::real()
) сначала компоненты, и передать их как отдельные аргументы atan2
,
Я думаю, что вы также можете использовать лямбда-выражения Boost.Compute для этого:
bc::vector<float2> input{ {1.0f, 2.0f}, {3.0f, 4.0f}, {5.0f, 6.0f} };
bc::vector<float> output(3);
using boost::compute::lambda::atan2;
using boost::compute::_1;
using boost::compute::lambda::get;
bc::transform(
float2_input.begin(),
float2_input.end(),
float_output.begin(),
atan2(get<1>(_1), get<0>(_1)),
queue
);
float2
в основном сложный в Boost.Compute. Вы также можете проверить test_lambda.cpp.