55
66Inverse of `sqrt(x)` for non-negative `x`.
77"""
8- square (x) = x^ 2
9- function square (x:: Real )
10- x < zero (x) && throw (DomainError (x, " `square` is defined as the inverse of `sqrt` and can only be evaluated for non-negative values" ))
8+ function square (x)
9+ if is_real_type (typeof (x)) && x < zero (x)
10+ throw (DomainError (x, " `square` is defined as the inverse of `sqrt` and can only be evaluated for non-negative values" ))
11+ end
1112 return x^ 2
1213end
1314
1415
15- function invpow2 (x:: Real , p:: Integer )
16- if x ≥ zero (x) || isodd (p)
17- copysign (abs (x)^ inv (p), x)
16+ function invpow_arg2 (x:: Number , p:: Real )
17+ if is_real_type (typeof (x))
18+ x ≥ zero (x) ? x^ inv (p) : # x > 0 - trivially invertible
19+ isinteger (p) && isodd (Integer (p)) ? copysign (abs (x)^ inv (p), x) : # p odd - invertible even for x < 0
20+ throw (DomainError (x, " inverse for x^$p is not defined at $x " ))
1821 else
19- throw (DomainError (x, " inverse for x^$p is not defined at $x " ))
20- end
21- end
22- function invpow2 (x:: Real , p:: Real )
23- if x ≥ zero (x)
24- x^ inv (p)
25- else
26- throw (DomainError (x, " inverse for x^$p is not defined at $x " ))
27- end
28- end
29- function invpow2 (x, p:: Real )
30- # complex x^p is only invertible for p = 1/n
31- if isinteger (inv (p))
32- x^ inv (p)
33- else
34- throw (DomainError (x, " inverse for x^$p is not defined at $x " ))
22+ # complex x^p is invertible only for p = 1/n
23+ isinteger (inv (p)) ? x^ inv (p) : throw (DomainError (x, " inverse for x^$p is not defined at $x " ))
3524 end
3625end
3726
38- function invpow1 (b:: Real , x:: Real )
27+ function invpow_arg1 (b:: Real , x:: Real )
3928 if b ≥ zero (b) && x ≥ zero (x)
4029 log (b, x)
4130 else
4231 throw (DomainError (x, " inverse for $b ^x is not defined at $x " ))
4332 end
4433end
4534
46- function invlog1 (b:: Real , x:: Real )
35+ function invlog_arg1 (b:: Real , x:: Real )
4736 if b ≥ zero (b)
4837 b^ x
4938 else
5039 throw (DomainError (x, " inverse for log($b , x) is not defined at $x " ))
5140 end
5241end
53- invlog1 (b , x) = b^ x
42+ invlog_arg1 (b :: Number , x:: Number ) = b^ x
5443
55- invlog2 (b , x) = x^ inv (b)
44+ invlog_arg2 (b :: Number , x:: Number ) = x^ inv (b)
5645
5746
58- function invdivrem ((q, r), divisor)
47+ function invdivrem ((q, r):: NTuple{2,Number} , divisor:: Number )
5948 res = muladd (q, divisor, r)
6049 if abs (r) ≤ abs (divisor) && (iszero (r) || sign (r) == sign (res))
6150 res
@@ -64,10 +53,18 @@ function invdivrem((q, r), divisor)
6453 end
6554end
6655
67- function invfldmod ((q, r), divisor)
56+ function invfldmod ((q, r):: NTuple{2,Number} , divisor:: Number )
6857 if abs (r) ≤ abs (divisor) && (iszero (r) || sign (r) == sign (divisor))
6958 muladd (q, divisor, r)
7059 else
7160 throw (DomainError ((q, r), " inverse for fldmod(x) is not defined at this point" ))
7261 end
7362end
63+
64+
65+ # check if T is a real-Number type
66+ # this is not the same as T <: Real which immediately excludes custom Number subtypes such as unitful numbers
67+ # also, isreal(x) != is_real_type(typeof(x)): the former is true for complex numbers with zero imaginary part
68+ @inline is_real_type (@nospecialize _:: Type{<:Real} ) = true
69+ @inline is_real_type (:: Type{T} ) where {T<: Number } = real (T) == T
70+ @inline is_real_type (@nospecialize _:: Type ) = false
0 commit comments