@@ -335,11 +335,6 @@ function invmod(n::T) where {T<:BitInteger}
335
335
end
336
336
337
337
# ^ for any x supporting *
338
- function to_power_type (x:: Number )
339
- T = promote_type (typeof (x), typeof (x* x))
340
- convert (T, x)
341
- end
342
- to_power_type (x) = oftype (x* x, x)
343
338
@noinline throw_domerr_powbysq (:: Any , p) = throw (DomainError (p, LazyString (
344
339
" Cannot raise an integer x to a negative power " , p, " ." ,
345
340
" \n Convert input to float." )))
@@ -355,12 +350,23 @@ to_power_type(x) = oftype(x*x, x)
355
350
" or write float(x)^" , p, " or Rational.(x)^" , p, " ." )))
356
351
# The * keyword supports `*=checked_mul` for `checked_pow`
357
352
@assume_effects :terminates_locally function power_by_squaring (x_, p:: Integer ; mul= * )
358
- x = to_power_type (x_)
353
+ x_squared_ = x_ * x_
354
+ x_squared_type = typeof (x_squared_)
355
+ T = if x_ isa Number
356
+ promote_type (typeof (x_), x_squared_type)
357
+ else
358
+ x_squared_type
359
+ end
360
+ x = convert (T, x_)
361
+ square_is_useful = mul === *
359
362
if p == 1
360
363
return copy (x)
361
364
elseif p == 0
362
365
return one (x)
363
366
elseif p == 2
367
+ if square_is_useful # avoid performing the same multiplication a second time when possible
368
+ return convert (T, x_squared_)
369
+ end
364
370
return mul (x, x)
365
371
elseif p < 0
366
372
isone (x) && return copy (x)
@@ -369,6 +375,11 @@ to_power_type(x) = oftype(x*x, x)
369
375
end
370
376
t = trailing_zeros (p) + 1
371
377
p >>= t
378
+ if square_is_useful # avoid performing the same multiplication a second time when possible
379
+ if (t -= 1 ) > 0
380
+ x = convert (T, x_squared_)
381
+ end
382
+ end
372
383
while (t -= 1 ) > 0
373
384
x = mul (x, x)
374
385
end
0 commit comments