ideas icon indicating copy to clipboard operation
ideas copied to clipboard

Добавить SQR функция , возведение на квадрата.

Open raidenluikang opened this issue 6 months ago • 13 comments

Старый добрый язык Паскале был стандартный функция 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 баг в ядре языка

raidenluikang avatar Jun 26 '25 12:06 raidenluikang

То есть hypot вас не устраивает?

dist = hypot( a.x - b.x, a.y - b.y );

Или вы думаете что компилятор который умеет constexpr не осилит такое?

x2=pow(x,2);

kov-serg avatar Jun 26 '25 12:06 kov-serg

hypot  --> не знал что  есть такая функция. 
pow(x,2)  --> возвращает всегда вещественное число.

У эти обоих возвращает вещественное число. просто возведение в квадрат любой целочисленной тип нет в стандарте.

raidenluikang avatar Jul 02 '25 07:07 raidenluikang

Никто не запрещает в своём 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; }
}

kov-serg avatar Jul 02 '25 09:07 kov-serg

Миллионы разные математические функции добавляет в стандарте , который 90% люди даже не слыхал названий).

Но один sqr функция почему то требует самим писать.

Вот добавили же std::midpoint , где вычисляет (a+b)/2 (знаю, что там было проблема в выражений (a+b)/2 для очень больших чисел ).

raidenluikang avatar Jul 02 '25 09:07 raidenluikang

Так сложные вычисления следует локолизовать от остальных частей и завести вспомогательные себе там функции для удобства. Более того квадрат там не самая страшная трагедия. А вот спец фукции в отличии очень хорошо что не надо вручную заводить, в отличии от квадрат логарифм гамма функции с наскока не написать. Больше напрягает что нет стандартных числел произвольной длинны.

ps: иногда приходится отказываться от выражений и заводить вспомогательные переменные и преобразовывать выражение в последовательность вызывов функций и потом это оборачивать в метод. Если часто не лазить в реализацию то это никак не мешает. И еще некоторые вычисления без внешних пояснений понять сразу не удастся, даже с 10го раза. Поэтому проще привести ссылку на описание вычислений, на человеческом языке.

kov-serg avatar Jul 02 '25 10:07 kov-serg

ну хотя бы,


template <std::integral T> 
constexpr 
/*detect T*T match type>*/  square( const T & x ) noexcept 
{
        return x * x;
}

добавить. Там для квадрата нужен найти подходящий тип. Например, T - short, то для квадрата нужен int, or unsigned int.

raidenluikang avatar Nov 01 '25 13:11 raidenluikang

А кто мешает добавить необходимые вспомогательные функции самостоятельно?

#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;
}

kov-serg avatar Nov 01 '25 17:11 kov-serg

Вопрос ведь в том, что почему такая базовая функция реализуется каждым самостоятельно, когда она уже может быть добавлена в стандартную библиотеку.

GitSparTV avatar Nov 01 '25 17:11 GitSparTV

Потому что слишком много вариантов и всем не угодишь. Вот почему нет FFT потому как там столько вариаций и точек кастомизации что забодаешся объяснять в документации как этим пользоваться. Несмотря на то что в каждом конкретном случае всё реализуется довольно просто.

kov-serg avatar Nov 02 '25 09:11 kov-serg

Вот почему нет FFT

:( а вот fft нужен почти в каждом втором проекте, и постоянно танцы с лицензиями и оптимизациями под конкретные типы данных и платформы... Было бы классно иметь его как часть стандартной библиотеки с оптимизациями от вендора железа.

sergii-rybin-tfs avatar Nov 03 '25 11:11 sergii-rybin-tfs

В идеале нужна "фаза синтезкода" которая сгенерирует оптимизированный код по заданным условиям и ограничениям под конкретную задачу ( можно дже в обычный c ;) ) А городить это на шаблонах в c++ бесполезная трата времени ибо кпд около нулевое получается. Да и потом объяснить то как таким монстром пользоваться придётся очень долго, а в случае внесения изменений будет боль и страдания.

kov-serg avatar Nov 03 '25 12:11 kov-serg

nvidia чтото подобное пытается сделать в своём компиляторе.

sergii-rybin-tfs avatar Nov 03 '25 14:11 sergii-rybin-tfs

Нет там совсем другое. Имеется ввиду фаза которая сейчас заполняется ИИ. А раньше заполнялась шаблонами/визардами и perl-ом ;) А именно генерация типового, но оптимизированного кода под известные ограничения. То есть методы для генерации и преобразования исходных кодов и пояснения/документации к нему. При этом это отимизационная задача (в общем случае) и решать её на императивных шаблонах c++ когда требуется декларативное описание не вариант.

kov-serg avatar Nov 03 '25 15:11 kov-serg