Plot Sin (x) for - π or negative x-axis

Hi all,

I wonder why the sin(x) function can’t be plot for the domain of or the negative x-axis.

This is my code:

using Plots, LaTeXStrings
gr()

function pitick(start, stop, denom; mode=:text)
    a = Int(cld(start, π/denom))
    b = Int(fld(stop, π/denom))
    tick = range(a*π/denom, b*π/denom; step=π/denom)
    ticklabel = piticklabel.((a:b) .// denom, Val(mode))
    tick, ticklabel
end

function piticklabel(x::Rational, ::Val{:text})
    iszero(x) && return "0"
    S = x < 0 ? "-" : ""
    n, d = abs(numerator(x)), denominator(x)
    N = n == 1 ? "" : repr(n)
    d == 1 && return S * N * "π"
    S * N * "π/" * repr(d)
end

function piticklabel(x::Rational, ::Val{:latex})
    iszero(x) && return L"0"
    S = x < 0 ? "-" : ""
    n, d = abs(numerator(x)), denominator(x)
    N = n == 1 ? "" : repr(n)
    d == 1 && return L"%$S%$N\pi"
    L"%$S\frac{%$N\pi}{%$d}"
end

a, b = -π, 2π/3

f(x) = (sin.(x))^(2/3)

plot(f, a, b; xtick=pitick(a, b, 4; mode=:latex), framestyle=:zerolines,
	legend=:outerright, label=L"f(x) = (\sin \ x)^{2/3}", 
	size=(720, 360), tickfontsize=10)

You can’t raise a negative real number to a non-integer power:

julia> sin(-1.)
-0.8414709848078965

julia> ans^(2/3)
ERROR: DomainError with -0.8414709848078965:
Exponentiation yielding a complex result requires a complex argument.
Replace x^y with (x+0im)^y, Complex(x)^y, or similar.

Like this:

f(x) = Complex(sin.(x))^(2/3)

or

f(x) =(sin.(x+0im))^(2/3)

they are still not working

I think you need something like f(x) = real((complex(sin.(x)))^(2/3)) which makes a plot. I’m not sure if it’s the plot you want, but it plots over the negative part of the x axis.

Just use f(x) = cbrt(sin(x))^2 to compute the 2/3 power in a way that works for negative numbers (and is faster to boot). (Not sure why you have a dot here. If you want to apply f elementwise to a vector just do f.(x).)

That’s what the cbrt function is for, whereas converting to complex chooses a different branch cut that you may not want here:

julia> cbrt(-1)
-1.0

julia> complex(-1)^(1//3)
0.5 + 0.8660254037844386im

julia> cbrt(-1)^2
1.0

julia> complex(-1)^(2//3)
-0.4999999999999999 + 0.8660254037844387im
2 Likes

I think you also need an extra dot for consistency

f(x) = (sin.(x)) .^ (2/3)

Or no dots at all and apply it element-wise by broadcasting, as Steven says.

(And then the other change)
It would be best to put the full error message and a minimal example!

Simpler to just define f with no dots and then apply it elementwise as f.(x) as needed. Define scalar functions as scalar operations.

And plot(f, a, b) takes a scalar function, so the dots are irrelevant.

3 Likes

It is a great solution,

but the question is, how about if the function is

f(x) = sin(x)^(2/5)

You could use

# return the real x^p (if it exists)
realpow(x::Real, p::Rational) =
    isodd(p.den) || x ≥ 0 ? copysign(abs(x)^(1//p.den), x)^p.num : throw(DomainError())

and then call realpow(sin(x), 2//5).

(In general, most math libraries in any language tend not to provide this kind of function, as far as I can tell, because it is a nonstandard branch cut for the x^(1/n) power.)

I do think that we should provide an nthroot function that works for negative x and odd n. IIRC IEEE 2018 recommends it.

4 Likes

Ah, I forgot about the nthroot function. (realpow seems more general, and is only possible because we have a Rational type.)

Filed nthroot function · Issue #47565 · JuliaLang/julia · GitHub

3 Likes

So if one want to plot \sin(x^{7/5}) we can use nthroot?

Yes, if that’s what you mean by x^{7/5} (for negative x, the real 5th root, computed by nthroot(x, 5) is different from the principal nth root, computed by complex(x)^(1//5)).