__declspec(naked) __int32 __fastcall powi(__int32 base, __int32 exp) { __asm { ... } }base: [-46340, 46340] (int-truncation of the sqrt of MAX_INT)
exp: [-19, 19] (highest power of 3, that does not overflow the int type)

Possible Use-Cases:
Allocation of N-dimensional arrays, with N^M elements.
--
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/fbfec82c-5416-4c96-b53b-ef3d4309b613%40isocpp.org.
Even better, an operator for it instead (e.g. ^^, as ** introduces ambiguities).

As you can see, powi does experience a gradual increase in execution length with the increasing exponents (since it needs to do at worst [if an implementation were to use a simple linear approach, O(n) multiplications]).
While the normal method does appear to be O(1), the execution lengths for floating-point operations are significant enough to negate those benefits with the ranges of 32 and 64-bit integer types.
Also below, I have included the collected data, which was gathered using "std::chrono::high_resolution_clock::now()" surrounding for-loops executing the functions within the base-value ranges for each exponent.
Power STL Custom -19 152.4881 5.922077 -18 156.3487 5.497594 -17 141.8481 5.546061 -16 145.8614 5.683295 -15 145.8326 6.041384 -14 149.2215 5.701708 -13 145.5323 5.59141 -12 149.3403 5.602157 -11 146.3427 5.974374 -10 152.5245 6.180647 -9 146.4068 5.772337 -8 143.3287 5.782097 -7 152.735 5.678149 -6 146.4267 5.743723 -5 145.5064 5.750488 -4 150.1708 5.772985 -3 142.524 6.569755 -2 140.4772 5.600695 -1 143.6424 6.281142 0 107.1507 3.854533 1 140.658 6.386001 2 147.3853 6.076429 3 146.9267 8.102243 4 141.4524 6.984409 5 136.9645 10.44516 6 139.3443 8.883989 7 142.125 7.988396 8 141.0955 7.625333 9 140.6131 12.97227 10 138.1168 11.3224 11 143.1305 10.61643 12 139.4992 10.38626 13 141.5211 11.2896 14 141.0866 10.22915 15 140.7223 9.948738 16 139.7512 9.173968 17 138.1409 15.03408 18 141.6834 13.97868 19 153.7554 14.77899
The case you pointed out of using the double-type of the return for 'pow(int, int)' would be a major concern. Perhaps a workaround would be the requirement of an explicit template? i.e. "double x = std::pow(10, 20);" would use overload 7, whereas "std::pow<int, int>(10, 20)" would return int? Alternatively, as Jake Arkinstall suggested, a new syntax for 'pow' as 'power' might be in order, in which case, such contingencies wouldn't be as large a concern. I would also argue that the above code segment is poor practice, as it is relying upon the pow function to convert the two integers to doubles. More explicit typing would be preferred in most coding environments. Another solution, as is implemented with powl and powf, is to use a single-letter abbreviation to explicitly define the types used. i.e. powi.As for the graph; I mentioned in a reply to my original posting that I have since found an issue with the testing method I used for graphing the execution times for pow and powi. I have since done other tests as shown below [avg. of 20000 runs for powi, and 500 for pow (since the execution is longer, I decided to neglect the sample-count somewhat)]:
As you can see, powi does experience a gradual increase in execution length with the increasing exponents (since it needs to do at worst [if an implementation were to use a simple linear approach, O(n) multiplications]).
__declspec(naked) __int32 __fastcall powi(__int32 base, __int32 exponent) {
__asm {
// No Stack Usage
/*------- Prolog ---------*/
//push ebp
//mov ebp, esp
//sub esp, __LOCAL_SIZE
/*------------------------*/
// Entry Register Values
//------------------------
// EAX = UNDEFINED
// EBX = UNDEFINED
// ECX = base
// EDX = exponent
// ESI = UNDEFINED
// EDI = UNDEFINED
//------------------------
// eax = 0
xor eax, eax;
// if(exponent == 0) { return 1; }
test edx, edx;
jnz if_zero_exp;
inc eax; // Set eax to 1
jmp powi_exit;
if_zero_exp:
// if(base == 0) { return 0; }
test ecx, ecx;
jz powi_exit;
// ebx = base
// ecx = exponent
mov ebx, ecx;
mov ecx, edx;
// ecx = abs(exponent)
// edx = sign(exponent)
sar edx, 31;
xor ecx, edx;
sub ecx, edx;
// Create a copy of the base, and move it to a temporary register
mov esi, ebx;
/* find abs(base) */
mov eax, ebx; // Copy the base to the accumulator
sar eax, 31; // Fill with sign bit
xor ebx, eax; // Not the value, if sign bit is set
sub ebx, eax; // Subtract the sign bit, giving the absolute value
// Return the copy to the accumulator
mov eax, esi;
// EAX = base
// EBX = abs(base)
// ECX = abs(exponent)
// EDX = sign(exponent)
// if exponent is negative
/*=========================================================*/
test edx, edx;
jz if_exp_sign_eq_0;
// if abs(base) == 1
/*----------------------------*/
cmp ebx, 1;
jg if_base_gt_1;
// ecx = exponent & 1
and ecx, ebx;
// eax = exponent & 1 ? (base < 0 ? -1 : 1) : 0
imul ecx;
// ecx = exponent & 1 ? 0 : 1
xor ecx, ebx;
// eax = exponent & 1 ? (base < 0 ? -1 : 1) : 1
add eax, ecx;
// Return exponent & 1 ? (base < 0 ? -1 : 1) : 1
jmp powi_exit;
if_base_gt_1:
/*----------------------------*/
// Return 0
xor eax, eax;
jmp powi_exit;
if_exp_sign_eq_0:
/*=========================================================*/
/* if exponent == 1, return base */
dec ecx;
jz powi_exit;
// If base == 2
//cmp ebx, 2;
//jne if_base_2;
// sal eax, cl;
// ret;
//if_base_2:
/* Exponentiate the multiplication */
mov ebx, eax;
multiply:
shr ecx, 1; // Shift and check the first bit of the loop counter
jnc noMulByEBX
imul ebx; // Multiply by the current multiplier
noMulByEBX:
imul ebx, ebx; // Square the multiplier
test ecx, ecx; // Test if this was the last itteration
jnz multiply;
/* Exit the function, returning the value of eax */
powi_exit :
// No stack usage
/*------- Epilog ---------*/
//mov esp, ebp;
//pop ebp;
/*------------------------*/
ret;
}
}
--
You received this message because you are subscribed to a topic in the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this topic, visit https://groups.google.com/a/isocpp.org/d/topic/std-proposals/y9qMRNKrS2E/unsubscribe.
To unsubscribe from this group and all its topics, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
To view this discussion on the web visit https://groups.google.com/a/isocpp.org/d/msgid/std-proposals/7801bc16-e087-43ed-ab4f-5b5f907c125f%40isocpp.org.