std::sqrt(std::valarray)(3)

πŸ“¦ version 2024.07.05, in nixpkgs unstable, opensuse-leap 16.0

std::sqrt(std::valarray) πŸ’…βœ¨

okay so this is the C++ Standard Libary manual page for std::sqrt(std::valarray), and yes the title ate. It's giving "math but make it valarray." We're keeping every detail, no cap. 🫢


πŸŽ€ NAME πŸŽ€

std::sqrt(std::valarray) β€” literally std::sqrt(std::valarray). The name and the thing are the same, iconic behavior. πŸ’…


✨ Synopsis ✨

Defined in header <valarray>
template< class T >
valarray<T> sqrt( const valarray<T>& va );

For each element in va, it computes the square root of the value of the element. Roots, one per element, no extra drama. 🌸


πŸ’– Parameters πŸ’–

  • va β€” the value array you're applying the operation to. It's giving "hand me the array, I'll handle the roots." 🧚

🌸 Return value 🌸

A value array containing the square roots of the values in va. That's the whole return vibe. ✨


πŸ¦‹ Notes πŸ¦‹

Unqualified function (sqrt) is used to perform the computation. If such function is not available, std::sqrt is used due to argument-dependent lookup. lowkey fancy, highkey true. πŸ’œ

The function can be implemented with the return type different from std::valarray. In this case, the replacement type has the following properties:

  • All const member functions of std::valarray are provided.
  • std::valarray, std::slice_array, std::gslice_array, std::mask_array and std::indirect_array can be constructed from the replacement type.
  • For every function taking a const std::valarray<T>& except begin() and end() (since C++11), identical functions taking the replacement types shall be added;
  • For every function taking two const std::valarray<T>& arguments, identical functions taking every combination of const std::valarray<T>& and replacement types shall be added.
  • The return type does not add more than two levels of template nesting over the most deeply-nested argument type.

🧚 Possible implementation 🧚

Here's one possible implementation, bestie β€” yes, this is fr fr one way to do it:

template<class T>
valarray<T> sqrt(const valarray<T>& va)
{
    valarray<T> other = va;
    for (T& i : other)
        i = sqrt(i);

    return other; // proxy object may be returned
}

πŸ“ Example πŸ“

This example finds all three roots β€” two of which can be complex conjugates β€” of several Cubic equations at once. It's a lot, but it ate. πŸ’…

The tiny // Run this code bit is your cue to hit run, bestie:

#include <cassert>
#include <complex>
#include <cstddef>
#include <iostream>
#include <numbers>
#include <valarray>

using CD = std::complex<double>;
using VA = std::valarray<CD>;

// return all n complex roots out of a given complex number x
VA root(CD x, unsigned n)
{
    const double mag = std::pow(std::abs(x), 1.0 / n);
    const double step = 2.0 * std::numbers::pi / n;
    double phase = std::arg(x) / n;
    VA v(n);
    for (std::size_t i{}; i != n; ++i, phase += step)
        v[i] = std::polar(mag, phase);
    return v;
}

// return n complex roots of each element in v; in the output valarray first
// goes the sequence of all n roots of v[0], then all n roots of v[1], etc.
VA root(VA v, unsigned n)
{
    VA o(v.size() * n);
    VA t(n);
    for (std::size_t i = 0; i != v.size(); ++i)
    {
        t = root(v[i], n);
        for (unsigned j = 0; j != n; ++j)
            o[n * i + j] = t[j];
    }
    return o;
}

// floating-point numbers comparator that tolerates given rounding error
inline bool is_equ(CD x, CD y, double tolerance = 0.000'000'001)
{
    return std::abs(std::abs(x) - std::abs(y)) < tolerance;
}

int main()
{
    // input coefficients for polynomial xΒ³ + pΒ·x + q
    const VA p{1, 2, 3, 4, 5, 6, 7, 8};
    const VA q{1, 2, 3, 4, 5, 6, 7, 8};

    // the solver
    const VA d = std::sqrt(std::pow(q / 2, 2) + std::pow(p / 3, 3));
    const VA u = root(-q / 2 + d, 3);
    const VA n = root(-q / 2 - d, 3);

    // allocate memory for roots: 3 * number of input cubic polynomials
    VA x[3];
    for (std::size_t t = 0; t != 3; ++t)
        x[t].resize(p.size());

    auto is_proper_root = [](CD a, CD b, CD p) { return is_equ(a * b + p / 3.0, 0.0); };

    // sieve out 6 out of 9 generated roots, leaving only 3 proper roots (per polynomial)
    for (std::size_t i = 0; i != p.size(); ++i)
        for (std::size_t j = 0, r = 0; j != 3; ++j)
            for (std::size_t k = 0; k != 3; ++k)
                if (is_proper_root(u[3 * i + j], n[3 * i + k], p[i]))
                    x[r++][i] = u[3 * i + j] + n[3 * i + k];

    std::cout << "Depressed cubic equation:   Root 1: \t\t Root 2: \t\t Root 3:\n";
    for (std::size_t i = 0; i != p.size(); ++i)
    {
        std::cout << "xΒ³ + " << p[i] << "Β·x + " << q[i] << " = 0  "
                  << std::fixed << x[0][i] << "  " << x[1][i] << "  " << x[2][i]
                  << std::defaultfloat << '\n';

        assert(is_equ(std::pow(x[0][i], 3) + x[0][i] * p[i] + q[i], 0.0));
        assert(is_equ(std::pow(x[1][i], 3) + x[1][i] * p[i] + q[i], 0.0));
        assert(is_equ(std::pow(x[2][i], 3) + x[2][i] * p[i] + q[i], 0.0));
    }
}

πŸ’… Output πŸ’…

Depressed cubic equation:   Root 1:              Root 2:              Root 3:
xΒ³ + (1,0)Β·x + (1,0) = 0  (-0.682328,0.000000)  (0.341164,1.161541)  (0.341164,-1.161541)
xΒ³ + (2,0)Β·x + (2,0) = 0  (-0.770917,0.000000)  (0.385458,1.563885)  (0.385458,-1.563885)
xΒ³ + (3,0)Β·x + (3,0) = 0  (-0.817732,0.000000)  (0.408866,1.871233)  (0.408866,-1.871233)
xΒ³ + (4,0)Β·x + (4,0) = 0  (-0.847708,0.000000)  (0.423854,2.130483)  (0.423854,-2.130483)
xΒ³ + (5,0)Β·x + (5,0) = 0  (-0.868830,0.000000)  (0.434415,2.359269)  (0.434415,-2.359269)
xΒ³ + (6,0)Β·x + (6,0) = 0  (-0.884622,0.000000)  (0.442311,2.566499)  (0.442311,-2.566499)
xΒ³ + (7,0)Β·x + (7,0) = 0  (-0.896922,0.000000)  (0.448461,2.757418)  (0.448461,-2.757418)
xΒ³ + (8,0)Β·x + (8,0) = 0  (-0.906795,0.000000)  (0.453398,2.935423)  (0.453398,-2.935423)

πŸ”₯ See also πŸ”₯

  • pow(std::valarray) β€” applies the function std::pow to two valarrays or a valarray and a value (function template)
  • sqrt, sqrtf, sqrtl β€” computes square root (\(\small{\sqrt{x}}\) √ x) (function); the listing has (C++11) and (C++11) markers next to it
  • sqrt(std::complex) β€” complex square root in the range of the right half-plane (function template)

πŸ‘‘ Hidden category πŸ‘‘

  • Pages with unreviewed LWG DR marker

mwah πŸ’‹ β€” source: http://cppreference.com, version/date: 2024.06.10, and this is the std::sqrt(std::valarray)(3) page. byeee 🫢

πŸ“¦ where this page comes from