# std::norm von std::complex benutzt std::sqrt????

• Ich habe Performance-Messungen angestellt und herausgefunden, warum `std::complex<double>` meinen Algorithmus langsam macht.

Es geht um die Funktion `std::norm(c)` , die eigentlich nichts anderes als `c.real()*c.real() + c.imag()*c.imag()` berechnet (des Quadrat der euklidischen Norm halt). Aus der Doku:

<a href= schrieb:

http://en.cppreference.com/w/cpp/numeric/complex/norm">The norm calculated by this function is also known as field norm or absolute square.

The Euclidean norm of a complex number is provided by `std::abs` , which is more costly to compute. In some situations, it may be replaced by `std::norm` , for example, if `abs(z1) > abs(z2)` then `norm(z1) > norm(z2)` .

Aus der Standardbibliothek vom GCC:

``````// 26.2.7/5: norm(__z) returns the squared magnitude of __z.
//     As defined, norm() is -not- a norm is the common mathematical
//     sense used in numerics.  The helper class _Norm_helper<> tries to
//     distinguish between builtin floating point and the rest, so as
//     to deliver an answer as close as possible to the real value.
template<bool>
struct _Norm_helper
{
template<typename _Tp>
static inline _Tp _S_do_it(const complex<_Tp>& __z)
{
const _Tp __x = __z.real();
const _Tp __y = __z.imag();
return __x * __x + __y * __y;
}
};

template<>
struct _Norm_helper<true>
{
template<typename _Tp>
static inline _Tp _S_do_it(const complex<_Tp>& __z)
{
_Tp __res = std::abs(__z);
return __res * __res;
}
};

template<typename _Tp>
inline _Tp
norm(const complex<_Tp>& __z)
{
return _Norm_helper<__is_floating<_Tp>::__value
&& !_GLIBCXX_FAST_MATH>::_S_do_it(__z);
}

// ...

// 26.2.7/3 abs(__z):  Returns the magnitude of __z.
template<typename _Tp>
inline _Tp
__complex_abs(const complex<_Tp>& __z)
{
_Tp __x = __z.real();
_Tp __y = __z.imag();
const _Tp __s = std::max(abs(__x), abs(__y));
if (__s == _Tp())  // well ...
return __s;
__x /= __s;
__y /= __s;
return __s * sqrt(__x * __x + __y * __y);
}

// ...

template<typename _Tp>
inline _Tp
abs(const complex<_Tp>& __z) { return __complex_abs(__z); }
``````

Mit anderen Worten, es werden zahlreiche Checks durchgeführt, unter anderem die Wurzel gezogen und am Schluss wieder quadriert.

Was soll das? Wer würde das je wollen? Wie schalte ich das ab? IEEE-Kompatibilität ist mir wichtig, deshalb kommt es für mich nicht in Frage, mit `--ffast-math` zu kompilieren. Das Makro `_GLIBCXX_FAST_MATH` ist leider nicht dafür vorgesehen, vom Benutzer gesetzt zu werden, da es im config-Header gesetzt wird.

• Eigentlich könnte mir das egal sein, da ich `norm` selten direkt verwende und mir eine eigene Funktion schreiben könnte.

Aber `operator/` benutzt `norm` . Und den brauche ich!

• Allein schon ein
beantwortet die Frage. Die Begründungen sind mir zwar fadenscheinig, aber so ist nun einmal der Stand der Dinge. Gut zu wissen, dann werde ich die GCC-Implementierung in Zukunft selber auch vermeiden.

baukomplex schrieb:

Eigentlich könnte mir das egal sein, da ich `norm` selten direkt verwende und mir eine eigene Funktion schreiben könnte.

Aber `operator/` benutzt `norm` . Und den brauche ich!

Dann musst du eben auch eine eigene Funktion dafür schreiben.

• SeppJ schrieb:

Allein schon ein
beantwortet die Frage. Die Begründungen sind mir zwar fadenscheinig, aber so ist nun einmal der Stand der Dinge.

Sorry, Filterblase!
Mir zeigt google ganz andere Sachen als Dir und auf der ersten Seite ist kein Link, der irgendwie zu Deinem Text passt. Möglicherweise wäre es eventuell unter Umständen manchmal keine völlig absurde Idee, in nichttrivialen Fällen das Linkziel statt der Suchanfrage zu posten.

Der GCC-Weg ist eigentlich, Oberkacke in die stdlib zu schreiben und dann den Compiler daraufhin anzupassen, daß er die Oberkacke wegoptimiert bzw nicht anwarnt.

• Nanu? Ich war mir eigentlich recht sicher, die Filterblase ausgeschaltet zu haben. Relevante Ergebnisse:
http://www.programdoc.com/1094_43623_1.htm
https://gcc.gnu.org/ml/gcc-patches/2009-03/msg00197.html

• SeppJ schrieb:

Nanu? Ich war mir eigentlich recht sicher, die Filterblase ausgeschaltet zu haben. Relevante Ergebnisse:
http://www.programdoc.com/1094_43623_1.htm
https://gcc.gnu.org/ml/gcc-patches/2009-03/msg00197.html

Der programdoc-Link kommt bei mir erst ganz unten auf der zweiten Seite, so weit schaue ich nie.

Die paar Begründungen (die für mich eher nach wilden Vermutungen tönen) nützen mir ausserdem nichts, ich will Lösungen.

Ist einen eigenen complex schreiben das beste, was ich machen kann?