Добавить SQR функция , возведение на квадрата.
Старый добрый язык Паскале был стандартный функция sqr возведение в квадрат, почему в языке C++ до сих пор это нет?
Написать постоянно вот так не удобно :
struct point { double x, y ;}
point a, b ;
/// ...
double dist = sqrt ( (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y) );
если был бы sqr то этот код будет меньше и читабельнее:
double dist = sqrt ( sqr(a.x - b.x) + sqr(a.y - b.y) );
Хотя , может возникнет проблема со схожести название уже существующий sqrt , и здесь легко можно запутаться.
Полезные ссылки:
- https://quick-bench.com/ - онлайн бенчмарк, поможет вам продемонстрировать эффективность вашего подхода
- https://godbolt.org/ - онлайн дизассемблер
- https://eel.is/c++draft/ - черновик стандарта C++ с возможностью ссылаться на конкретные параграфы
- https://wg21.link/ - универсальная ссылка на международные proposal или баги в С++, например https://wg21.link/P1000 ссылается на документ P1000, а https://wg21.link/cwg100 на 100 баг в ядре языка
То есть hypot вас не устраивает?
dist = hypot( a.x - b.x, a.y - b.y );
Или вы думаете что компилятор который умеет constexpr не осилит такое?
x2=pow(x,2);
hypot --> не знал что есть такая функция.
pow(x,2) --> возвращает всегда вещественное число.
У эти обоих возвращает вещественное число. просто возведение в квадрат любой целочисленной тип нет в стандарте.
Никто не запрещает в своём namespace объявить, более того для не вещественных чисел могут быть варианты.
namespace my {
template<class T>T sqr(const T& x) { return x*x; }
template<class T>T conj(const T& x);
template<class T>T norm(const T& x) { return conj(x)*x; }
}
Миллионы разные математические функции добавляет в стандарте , который 90% люди даже не слыхал названий).
Но один sqr функция почему то требует самим писать.
Вот добавили же std::midpoint , где вычисляет (a+b)/2 (знаю, что там было проблема в выражений (a+b)/2 для очень больших чисел ).
Так сложные вычисления следует локолизовать от остальных частей и завести вспомогательные себе там функции для удобства. Более того квадрат там не самая страшная трагедия. А вот спец фукции в отличии очень хорошо что не надо вручную заводить, в отличии от квадрат логарифм гамма функции с наскока не написать. Больше напрягает что нет стандартных числел произвольной длинны.
ps: иногда приходится отказываться от выражений и заводить вспомогательные переменные и преобразовывать выражение в последовательность вызывов функций и потом это оборачивать в метод. Если часто не лазить в реализацию то это никак не мешает. И еще некоторые вычисления без внешних пояснений понять сразу не удастся, даже с 10го раза. Поэтому проще привести ссылку на описание вычислений, на человеческом языке.
ну хотя бы,
template <std::integral T>
constexpr
/*detect T*T match type>*/ square( const T & x ) noexcept
{
return x * x;
}
добавить. Там для квадрата нужен найти подходящий тип. Например, T - short, то для квадрата нужен int, or unsigned int.
А кто мешает добавить необходимые вспомогательные функции самостоятельно?
#include <iostream>
#include <complex>
#include <vector>
namespace my {
using complex=std::complex<double>;
int sqr(int x) { return x*x; }
double sqr(double x) { return std::norm(x); }
double sqr(complex z) { return std::norm(z); }
int sqr(const std::vector<int> &v) { int s=0; for(auto x:v) s+=x*x; return s; }
double sqr(const std::vector<double> &v) { double s=0; for(auto x:v) s+=x*x; return s; }
double sqr(const std::vector<complex> &v) { double s=0; for(auto x:v) s+=std::norm(x); return s; }
template<int n>int sqr(const int (&v)[n]) { int s=0; for(auto x:v) s+=x*x; return s; }
template<int n>double sqr(const double (&v)[n]) { double s=0; for(auto x:v) s+=x*x; return s; }
template<int n>double sqr(const complex (&v)[n]) { double s=0; for(auto x:v) s+=std::norm(x); return s; }
}
int main(int argc, char **argv) {
using namespace my;
complex i(0,1);
complex x[]={ 3.0+i, 4.0*i };
std::cout << sqr(x) << std::endl;
return 0;
}
Вопрос ведь в том, что почему такая базовая функция реализуется каждым самостоятельно, когда она уже может быть добавлена в стандартную библиотеку.
Потому что слишком много вариантов и всем не угодишь. Вот почему нет FFT потому как там столько вариаций и точек кастомизации что забодаешся объяснять в документации как этим пользоваться. Несмотря на то что в каждом конкретном случае всё реализуется довольно просто.
Вот почему нет FFT
:( а вот fft нужен почти в каждом втором проекте, и постоянно танцы с лицензиями и оптимизациями под конкретные типы данных и платформы... Было бы классно иметь его как часть стандартной библиотеки с оптимизациями от вендора железа.
В идеале нужна "фаза синтезкода" которая сгенерирует оптимизированный код по заданным условиям и ограничениям под конкретную задачу ( можно дже в обычный c ;) ) А городить это на шаблонах в c++ бесполезная трата времени ибо кпд около нулевое получается. Да и потом объяснить то как таким монстром пользоваться придётся очень долго, а в случае внесения изменений будет боль и страдания.
nvidia чтото подобное пытается сделать в своём компиляторе.
Нет там совсем другое. Имеется ввиду фаза которая сейчас заполняется ИИ. А раньше заполнялась шаблонами/визардами и perl-ом ;) А именно генерация типового, но оптимизированного кода под известные ограничения. То есть методы для генерации и преобразования исходных кодов и пояснения/документации к нему. При этом это отимизационная задача (в общем случае) и решать её на императивных шаблонах c++ когда требуется декларативное описание не вариант.