Date: Tue, 25 Oct 2022 15:43:28 -0400

Hi Sebastian,

I just replied to Brian Bi elsewhere in this thread at the same time you

wrote that, and I think the reply applies here too.

What about just having std::cbrt(z) return whatever pow(z, 1/3) returns?

The idea is, just as sqrt() arbitrarily returns the positive root, cbrt()

can return whatever root as well. And then, just as it's trivial to get the

*other* root given sqrt()'s result (multiply by -1), it's also relatively

straightforward to get the other two roots given cbrt()'s result (rotate

+/- 120 deg in complex plane; as illustrated in de Moivre's formula). It

doesn't *really* matter which root is returned.

And then you'd get consistency with pow(), which is good.

Does that seem reasonable?

Jason

On Tue, Oct 25, 2022 at 3:29 PM Sebastian Wittmeier via Std-Proposals <

std-proposals_at_[hidden]> wrote:

> Hi Jason,

>

> ordering the roots per se is probably not the problem.

>

> But getting the root at the expected position is:

>

>

>

> If the first solution is identical to x=exp(z^(1/3)), i.e. -pi/3 < arg(z)

> <= pi/3

>

> then the next roots could continue counter-clockwise.

>

>

>

> Compared to the real function:

>

> The cbrt(positive double) would be always the first of three roots of this

> complex function.

>

> The cbrt(negative double) would be always the second of three roots

> defined this way.

>

> The cbrt(negative double) when presented to the function as (negative

> double - epsilon*i)

>

> would be always the third of three roots.

>

>

>

>

>

> So there are 6 possibilities:

>

> 1) define cbrt(complex) not at all

>

> 2) define cbrt(complex) as exp(z^(1/3))

>

> 3) define cbrt(complex) as the root with the largest real magnitude

>

> That is the same result as cbrt(double)

>

> 4a) define two functions cbrt_principal (2) and cbrt_maxreal (3)

>

> safer solution

>

> 4b) use a second parametercbrt(double, tag)

>

> with tag=complex::principal_root or complex::maxreal (type, enum, ...)

>

> 5) return a list of all three roots

>

> caller possibly would have to sort (see above, where the position of

> maxreal could be any of the three)

>

> 6) return the nth root by provided index

>

> could lead to several repeated calls to function, which is wasteful,

> especially if caller has to sort the results afterwards, when looking for

> (3)

>

>

> I think 4) is the nicest alternative of the ones presented.

>

> Some math / numerically oriented programming languages provide 5), most

> (all?) others provide 2), some (Julia) have the same discussion and stay

> for the moment at 1).

>

>

>

> Best,

>

> Sebastian

>

>

>

> -----Ursprüngliche Nachricht-----

> *Von:* Jason C via Std-Proposals <std-proposals_at_[hidden]>

> *Gesendet:* Di 25.10.2022 18:41

> *Betreff:* Re: [std-proposals] std::cbrt(std::complex)

> *An:* Dejan Milosavljevic <dmilos_at_[hidden]>;

> *CC:* Jason C <jason.cipriani_at_[hidden]>; std-proposals_at_[hidden];

> On Tue, Oct 25, 2022 at 12:30 PM Jason C <jason.cipriani_at_[hidden]> wrote:

>

> Perhaps

>

> template <typename T>

> std::tuple<std::complex<T>,std::complex<T>,std::complex<T> > cbrt

> (std::complex<T> const &c)

>

>

> Although... this then implies that the roots are ordered, and I'm pretty

> sure there's no predictable and consistent way to ensure some order of the

> returned roots given that there's no solid definition of ordering for

> complex number combined with realistic fp precision errors.

>

> I'm starting to think maybe my idea wasn't such a good one after all and

> this is probably too complicated to make its way into std; users would be

> better off choosing other implementations that meet their specific needs,

> probably.

>

> Jason

>

>

>

>

>

>

> On Tue, Oct 25, 2022 at 11:48 AM Dejan Milosavljevic <dmilos_at_[hidden]>

> wrote:

>

> Cubic root have three solutions.

> *What is the rule to uniquely pick the first one?*

> Rest of them we can have by multiply with cbrt( {+1,0} );

>

> My proposal for complex cbrt:

> template< typename T/*number like*/>

> std::complex<T> cbrt( std::complex<T> const& c, int index =0 /* which

> root to use is defined by ( index % 3) 0,1 or 2 */ );

>

> This might be too complex.

> Any idea to make it simple?

>

> On Tue, Oct 25, 2022 at 5:01 PM Jason C via Std-Proposals <

> std-proposals_at_[hidden]> wrote:

>

> <complex> is conspicuously missing cbrt().

>

> If I put together a proposal to add std::cbrt(std::complex) to <complex>,

> would there be any interest?

>

> Any thoughts?

>

> Jason

> --

> Std-Proposals mailing list

> Std-Proposals_at_[hidden]

> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

>

> --

> Std-Proposals mailing list

> Std-Proposals_at_[hidden]

> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

>

> --

> Std-Proposals mailing list

> Std-Proposals_at_[hidden]

> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

>

I just replied to Brian Bi elsewhere in this thread at the same time you

wrote that, and I think the reply applies here too.

What about just having std::cbrt(z) return whatever pow(z, 1/3) returns?

The idea is, just as sqrt() arbitrarily returns the positive root, cbrt()

can return whatever root as well. And then, just as it's trivial to get the

*other* root given sqrt()'s result (multiply by -1), it's also relatively

straightforward to get the other two roots given cbrt()'s result (rotate

+/- 120 deg in complex plane; as illustrated in de Moivre's formula). It

doesn't *really* matter which root is returned.

And then you'd get consistency with pow(), which is good.

Does that seem reasonable?

Jason

On Tue, Oct 25, 2022 at 3:29 PM Sebastian Wittmeier via Std-Proposals <

std-proposals_at_[hidden]> wrote:

> Hi Jason,

>

> ordering the roots per se is probably not the problem.

>

> But getting the root at the expected position is:

>

>

>

> If the first solution is identical to x=exp(z^(1/3)), i.e. -pi/3 < arg(z)

> <= pi/3

>

> then the next roots could continue counter-clockwise.

>

>

>

> Compared to the real function:

>

> The cbrt(positive double) would be always the first of three roots of this

> complex function.

>

> The cbrt(negative double) would be always the second of three roots

> defined this way.

>

> The cbrt(negative double) when presented to the function as (negative

> double - epsilon*i)

>

> would be always the third of three roots.

>

>

>

>

>

> So there are 6 possibilities:

>

> 1) define cbrt(complex) not at all

>

> 2) define cbrt(complex) as exp(z^(1/3))

>

> 3) define cbrt(complex) as the root with the largest real magnitude

>

> That is the same result as cbrt(double)

>

> 4a) define two functions cbrt_principal (2) and cbrt_maxreal (3)

>

> safer solution

>

> 4b) use a second parametercbrt(double, tag)

>

> with tag=complex::principal_root or complex::maxreal (type, enum, ...)

>

> 5) return a list of all three roots

>

> caller possibly would have to sort (see above, where the position of

> maxreal could be any of the three)

>

> 6) return the nth root by provided index

>

> could lead to several repeated calls to function, which is wasteful,

> especially if caller has to sort the results afterwards, when looking for

> (3)

>

>

> I think 4) is the nicest alternative of the ones presented.

>

> Some math / numerically oriented programming languages provide 5), most

> (all?) others provide 2), some (Julia) have the same discussion and stay

> for the moment at 1).

>

>

>

> Best,

>

> Sebastian

>

>

>

> -----Ursprüngliche Nachricht-----

> *Von:* Jason C via Std-Proposals <std-proposals_at_[hidden]>

> *Gesendet:* Di 25.10.2022 18:41

> *Betreff:* Re: [std-proposals] std::cbrt(std::complex)

> *An:* Dejan Milosavljevic <dmilos_at_[hidden]>;

> *CC:* Jason C <jason.cipriani_at_[hidden]>; std-proposals_at_[hidden];

> On Tue, Oct 25, 2022 at 12:30 PM Jason C <jason.cipriani_at_[hidden]> wrote:

>

> Perhaps

>

> template <typename T>

> std::tuple<std::complex<T>,std::complex<T>,std::complex<T> > cbrt

> (std::complex<T> const &c)

>

>

> Although... this then implies that the roots are ordered, and I'm pretty

> sure there's no predictable and consistent way to ensure some order of the

> returned roots given that there's no solid definition of ordering for

> complex number combined with realistic fp precision errors.

>

> I'm starting to think maybe my idea wasn't such a good one after all and

> this is probably too complicated to make its way into std; users would be

> better off choosing other implementations that meet their specific needs,

> probably.

>

> Jason

>

>

>

>

>

>

> On Tue, Oct 25, 2022 at 11:48 AM Dejan Milosavljevic <dmilos_at_[hidden]>

> wrote:

>

> Cubic root have three solutions.

> *What is the rule to uniquely pick the first one?*

> Rest of them we can have by multiply with cbrt( {+1,0} );

>

> My proposal for complex cbrt:

> template< typename T/*number like*/>

> std::complex<T> cbrt( std::complex<T> const& c, int index =0 /* which

> root to use is defined by ( index % 3) 0,1 or 2 */ );

>

> This might be too complex.

> Any idea to make it simple?

>

> On Tue, Oct 25, 2022 at 5:01 PM Jason C via Std-Proposals <

> std-proposals_at_[hidden]> wrote:

>

> <complex> is conspicuously missing cbrt().

>

> If I put together a proposal to add std::cbrt(std::complex) to <complex>,

> would there be any interest?

>

> Any thoughts?

>

> Jason

> --

> Std-Proposals mailing list

> Std-Proposals_at_[hidden]

> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

>

> --

> Std-Proposals mailing list

> Std-Proposals_at_[hidden]

> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

>

> --

> Std-Proposals mailing list

> Std-Proposals_at_[hidden]

> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals

>

Received on 2022-10-25 19:43:57