#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */

/* Variables and functions */
long calcModExp(long, long, long);
scalar_t__ checkModExpNum(long);
scalar_t__ isPossibleLongSquareOverflow(long);
scalar_t__ pow(int, int);
int /*<<< orphan*/ printFeedback(long);
int /*<<< orphan*/ printf(char *, ...);
long safeScanModExpArg();
void modexp() {
  long num, exp, modNum;
  while (1) {
    while (1) {
      printf("Enter your a: ");
      num = safeScanModExpArg();
      if (checkModExpNum(num)) {
        if (isPossibleLongSquareOverflow(num)) {
          printf("\033[1m\033[31m"
                 "[ERROR]: Cannot compute solution with a = %ld as it\nwould "
                 "result in multiplicative overflow.\n"
                 "\033[0m",
                 num);
          printf("\033[1m\033[31m"
                 "Try using a smaller number for a such that a^2 does not "
                 "exceed\n%ld.\n"
                 "\033[0m",
                 (long)pow(2, (8 * sizeof(long) - 1)) - 1);
          continue;
        } else {
          break;
        }
      }
      printFeedback(num);
    }
    while (1) {
      printf("Enter your k: ");
      exp = safeScanModExpArg();
      if (checkModExpNum(exp))
        break;
      printFeedback(exp);
    }
    while (1) {
      printf("Enter your n: ");
      modNum = safeScanModExpArg();
      if (checkModExpNum(modNum)) {
        if (isPossibleLongSquareOverflow(modNum)) {
          printf("\033[1m\033[31m"
                 "[ERROR]: Cannot compute solution with n = %ld as it\nwould "
                 "result in multiplicative overflow.\n"
                 "\033[0m",
                 num);
          printf("\033[1m\033[31m"
                 "Try using a smaller number for n such that n^2 does not "
                 "exceed\n%ld.\n"
                 "\033[0m",
                 (long)pow(2, (8 * sizeof(long) - 1)) - 1);
          continue;
        }
        if (modNum == 0) {
          printf("\033[1m\033[31m"
                 "[ERROR]: n cannot be 0! Retry using a valid integer.\n"
                 "\033[0m");
          continue;
        }
        break;
      }
      printFeedback(modNum);
    }
    printf("\na = %ld, k = %ld, n = %ld\n\n", num, exp, modNum);
    printf("\nSolving x ≡ (%ld^%ld) mod %ld...\n\n", num, exp, modNum);
    printf("\033[1m\033[32m"
           "\nThe answer is x = %ld.\n\n"
           "\033[0m",
           calcModExp(num, exp, modNum));
  }
}


x86 assembly (clang, -O0):
<modexp>:
push   %rbp
mov    %rsp,%rbp
sub    $0x20,%rsp
jmp    117d <modexp+0xd>
lea    0xe7c(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
mov    $0x0,%al
call   1080 <safeScanModExpArg@plt>
mov    %rax,-0x8(%rbp)
mov    -0x8(%rbp),%rdi
call   1030 <checkModExpNum@plt>
cmp    $0x0,%rax
je     11fc <modexp+0x8c>
mov    -0x8(%rbp),%rdi
call   1050 <isPossibleLongSquareOverflow@plt>
cmp    $0x0,%rax
je     11f7 <modexp+0x87>
mov    -0x8(%rbp),%rsi
lea    0xe48(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
mov    $0x2,%edi
mov    $0x3f,%esi
call   1070 <pow@plt>
mov    %rax,%rsi
sub    $0x1,%rsi
lea    0xe8f(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
jmp    117d <modexp+0xd>
jmp    120a <modexp+0x9a>
mov    -0x8(%rbp),%rdi
call   1060 <printFeedback@plt>
jmp    117d <modexp+0xd>
jmp    120f <modexp+0x9f>
lea    0xeb6(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
mov    $0x0,%al
call   1080 <safeScanModExpArg@plt>
mov    %rax,-0x10(%rbp)
mov    -0x10(%rbp),%rdi
call   1030 <checkModExpNum@plt>
cmp    $0x0,%rax
je     1240 <modexp+0xd0>
jmp    124e <modexp+0xde>
mov    -0x10(%rbp),%rdi
call   1060 <printFeedback@plt>
jmp    120f <modexp+0x9f>
jmp    1253 <modexp+0xe3>
lea    0xe81(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
mov    $0x0,%al
call   1080 <safeScanModExpArg@plt>
mov    %rax,-0x18(%rbp)
mov    -0x18(%rbp),%rdi
call   1030 <checkModExpNum@plt>
cmp    $0x0,%rax
je     12f0 <modexp+0x180>
mov    -0x18(%rbp),%rdi
call   1050 <isPossibleLongSquareOverflow@plt>
cmp    $0x0,%rax
je     12cd <modexp+0x15d>
mov    -0x8(%rbp),%rsi
lea    0xe4d(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
mov    $0x2,%edi
mov    $0x3f,%esi
call   1070 <pow@plt>
mov    %rax,%rsi
sub    $0x1,%rsi
lea    0xe94(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
jmp    1253 <modexp+0xe3>
cmpq   $0x0,-0x18(%rbp)
jne    12eb <modexp+0x17b>
lea    0xec8(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
jmp    1253 <modexp+0xe3>
jmp    12fe <modexp+0x18e>
mov    -0x18(%rbp),%rdi
call   1060 <printFeedback@plt>
jmp    1253 <modexp+0xe3>
mov    -0x8(%rbp),%rsi
mov    -0x10(%rbp),%rdx
mov    -0x18(%rbp),%rcx
lea    0xed9(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
mov    -0x8(%rbp),%rsi
mov    -0x10(%rbp),%rdx
mov    -0x18(%rbp),%rcx
lea    0xedc(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
mov    -0x8(%rbp),%rdi
mov    -0x10(%rbp),%rsi
mov    -0x18(%rbp),%rdx
call   1090 <calcModExp@plt>
mov    %rax,%rsi
lea    0xee0(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
jmp    1178 <modexp+0x8>

x86 assembly (clang, -O2):
<modexp>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
push   %rax
lea    0xe7e(%rip),%r15
lea    0xf43(%rip),%r12
lea    0xf4b(%rip),%rbx
lea    0xf53(%rip),%rbp
lea    0xfb7(%rip),%r13
jmp    11a8 <modexp+0x38>
mov    %r14,%rdi
call   1060 <printFeedback@plt>
mov    %r15,%rdi
xor    %eax,%eax
call   1040 <printf@plt>
xor    %eax,%eax
call   1080 <safeScanModExpArg@plt>
mov    %rax,%r14
mov    %rax,%rdi
call   1030 <checkModExpNum@plt>
test   %rax,%rax
je     11a0 <modexp+0x30>
mov    %r14,%rdi
call   1050 <isPossibleLongSquareOverflow@plt>
test   %rax,%rax
je     1218 <modexp+0xa8>
lea    0xe32(%rip),%rdi
mov    %r14,%rsi
xor    %eax,%eax
call   1040 <printf@plt>
mov    $0x2,%edi
mov    $0x3f,%esi
call   1070 <pow@plt>
lea    -0x1(%rax),%rsi
lea    0xe79(%rip),%rdi
xor    %eax,%eax
call   1040 <printf@plt>
jmp    11a8 <modexp+0x38>
nopw   0x0(%rax,%rax,1)
mov    %r15,%rdi
call   1060 <printFeedback@plt>
mov    %r12,%rdi
xor    %eax,%eax
call   1040 <printf@plt>
xor    %eax,%eax
call   1080 <safeScanModExpArg@plt>
mov    %rax,%r15
mov    %rax,%rdi
call   1030 <checkModExpNum@plt>
test   %rax,%rax
je     1210 <modexp+0xa0>
jmp    1248 <modexp+0xd8>
nopl   0x0(%rax,%rax,1)
mov    %r12,%rdi
call   1060 <printFeedback@plt>
mov    %rbx,%rdi
xor    %eax,%eax
call   1040 <printf@plt>
xor    %eax,%eax
call   1080 <safeScanModExpArg@plt>
mov    %rax,%r12
mov    %rax,%rdi
call   1030 <checkModExpNum@plt>
test   %rax,%rax
je     1240 <modexp+0xd0>
mov    %r12,%rdi
call   1050 <isPossibleLongSquareOverflow@plt>
test   %rax,%rax
je     12b0 <modexp+0x140>
mov    %rbp,%rdi
mov    %r14,%rsi
xor    %eax,%eax
call   1040 <printf@plt>
mov    $0x2,%edi
mov    $0x3f,%esi
call   1070 <pow@plt>
lea    -0x1(%rax),%rsi
mov    %r13,%rdi
xor    %eax,%eax
call   1040 <printf@plt>
jmp    1248 <modexp+0xd8>
cs nopw 0x0(%rax,%rax,1)
nopl   0x0(%rax)
test   %r12,%r12
jne    12d0 <modexp+0x160>
lea    0xeeb(%rip),%rdi
xor    %eax,%eax
call   1040 <printf@plt>
jmp    1248 <modexp+0xd8>
cs nopw 0x0(%rax,%rax,1)
nop
lea    0xf13(%rip),%rdi
mov    %r14,%rsi
mov    %r15,%rdx
mov    %r12,%rcx
xor    %eax,%eax
call   1040 <printf@plt>
lea    0xf19(%rip),%rdi
mov    %r14,%rsi
mov    %r15,%rdx
mov    %r12,%rcx
xor    %eax,%eax
call   1040 <printf@plt>
mov    %r14,%rdi
mov    %r15,%rsi
mov    %r12,%rdx
call   1090 <calcModExp@plt>
lea    0xf1a(%rip),%rdi
mov    %rax,%rsi
xor    %eax,%eax
call   1040 <printf@plt>
lea    0xcdc(%rip),%r15
lea    0xda1(%rip),%r12
jmp    11a8 <modexp+0x38>

LLVM IR (-O0):
@.str = [15 x i8] c"Enter your a: \00"
@.str.1 = [107 x i8] c"\1B[1m\1B[31m[ERROR]: Cannot compute solution with a = %ld as it\0Awould result in multiplicative overflow.\0A\1B[0m\00"
@.str.2 = [82 x i8] c"\1B[1m\1B[31mTry using a smaller number for a such that a^2 does not exceed\0A%ld.\0A\1B[0m\00"
@.str.3 = [15 x i8] c"Enter your k: \00"
@.str.4 = [15 x i8] c"Enter your n: \00"
@.str.5 = [107 x i8] c"\1B[1m\1B[31m[ERROR]: Cannot compute solution with n = %ld as it\0Awould result in multiplicative overflow.\0A\1B[0m\00"
@.str.6 = [82 x i8] c"\1B[1m\1B[31mTry using a smaller number for n such that n^2 does not exceed\0A%ld.\0A\1B[0m\00"
@.str.7 = [67 x i8] c"\1B[1m\1B[31m[ERROR]: n cannot be 0! Retry using a valid integer.\0A\1B[0m\00"
@.str.8 = [29 x i8] c"\0Aa = %ld, k = %ld, n = %ld\0A\0A\00"
@.str.9 = [38 x i8] c"\0ASolving x \E2\89\A1 (%ld^%ld) mod %ld...\0A\0A\00"
@.str.10 = [39 x i8] c"\1B[1m\1B[32m\0AThe answer is x = %ld.\0A\0A\1B[0m\00"
define void @modexp() {
%1 = alloca i64
%2 = alloca i64
%3 = alloca i64
br label %4
4: ; preds = %0, %62
br label %5
5: ; preds = %4, %15, %22
%6 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str, i64 0, i64 0))
%7 = call i64 (...) @safeScanModExpArg()
store i64 %7, i64* %1
%8 = load i64, i64* %1
%9 = call i64 @checkModExpNum(i64 %8)
%10 = icmp ne i64 %9, 0
br i1 %10, label %11, label %22
11: ; preds = %5
%12 = load i64, i64* %1
%13 = call i64 @isPossibleLongSquareOverflow(i64 %12)
%14 = icmp ne i64 %13, 0
br i1 %14, label %15, label %21
15: ; preds = %11
%16 = load i64, i64* %1
%17 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([107 x i8], [107 x i8]* @.str.1, i64 0, i64 0), i64 %16)
%18 = call i64 @pow(i32 2, i32 63)
%19 = sub nsw i64 %18, 1
%20 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([82 x i8], [82 x i8]* @.str.2, i64 0, i64 0), i64 %19)
br label %5
21: ; preds = %11
br label %25
22: ; preds = %5
%23 = load i64, i64* %1
%24 = call i32 @printFeedback(i64 %23)
br label %5
25: ; preds = %21
br label %26
26: ; preds = %25, %33
%27 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.3, i64 0, i64 0))
%28 = call i64 (...) @safeScanModExpArg()
store i64 %28, i64* %2
%29 = load i64, i64* %2
%30 = call i64 @checkModExpNum(i64 %29)
%31 = icmp ne i64 %30, 0
br i1 %31, label %32, label %33
32: ; preds = %26
br label %36
33: ; preds = %26
%34 = load i64, i64* %2
%35 = call i32 @printFeedback(i64 %34)
br label %26
36: ; preds = %32
br label %37
37: ; preds = %36, %47, %56, %59
%38 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([15 x i8], [15 x i8]* @.str.4, i64 0, i64 0))
%39 = call i64 (...) @safeScanModExpArg()
store i64 %39, i64* %3
%40 = load i64, i64* %3
%41 = call i64 @checkModExpNum(i64 %40)
%42 = icmp ne i64 %41, 0
br i1 %42, label %43, label %59
43: ; preds = %37
%44 = load i64, i64* %3
%45 = call i64 @isPossibleLongSquareOverflow(i64 %44)
%46 = icmp ne i64 %45, 0
br i1 %46, label %47, label %53
47: ; preds = %43
%48 = load i64, i64* %1
%49 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([107 x i8], [107 x i8]* @.str.5, i64 0, i64 0), i64 %48)
%50 = call i64 @pow(i32 2, i32 63)
%51 = sub nsw i64 %50, 1
%52 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([82 x i8], [82 x i8]* @.str.6, i64 0, i64 0), i64 %51)
br label %37
53: ; preds = %43
%54 = load i64, i64* %3
%55 = icmp eq i64 %54, 0
br i1 %55, label %56, label %58
56: ; preds = %53
%57 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([67 x i8], [67 x i8]* @.str.7, i64 0, i64 0))
br label %37
58: ; preds = %53
br label %62
59: ; preds = %37
%60 = load i64, i64* %3
%61 = call i32 @printFeedback(i64 %60)
br label %37
62: ; preds = %58
%63 = load i64, i64* %1
%64 = load i64, i64* %2
%65 = load i64, i64* %3
%66 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([29 x i8], [29 x i8]* @.str.8, i64 0, i64 0), i64 %63, i64 %64, i64 %65)
%67 = load i64, i64* %1
%68 = load i64, i64* %2
%69 = load i64, i64* %3
%70 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([38 x i8], [38 x i8]* @.str.9, i64 0, i64 0), i64 %67, i64 %68, i64 %69)
%71 = load i64, i64* %1
%72 = load i64, i64* %2
%73 = load i64, i64* %3
%74 = call i64 @calcModExp(i64 %71, i64 %72, i64 %73)
%75 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([39 x i8], [39 x i8]* @.str.10, i64 0, i64 0), i64 %74)
br label %4
}

LLVM IR (-O2):
@.str = [15 x i8] c"Enter your a: \00"
@.str.1 = [107 x i8] c"\1B[1m\1B[31m[ERROR]: Cannot compute solution with a = %ld as it\0Awould result in multiplicative overflow.\0A\1B[0m\00"
@.str.2 = [82 x i8] c"\1B[1m\1B[31mTry using a smaller number for a such that a^2 does not exceed\0A%ld.\0A\1B[0m\00"
@.str.3 = [15 x i8] c"Enter your k: \00"
@.str.4 = [15 x i8] c"Enter your n: \00"
@.str.5 = [107 x i8] c"\1B[1m\1B[31m[ERROR]: Cannot compute solution with n = %ld as it\0Awould result in multiplicative overflow.\0A\1B[0m\00"
@.str.6 = [82 x i8] c"\1B[1m\1B[31mTry using a smaller number for n such that n^2 does not exceed\0A%ld.\0A\1B[0m\00"
@.str.7 = [67 x i8] c"\1B[1m\1B[31m[ERROR]: n cannot be 0! Retry using a valid integer.\0A\1B[0m\00"
@.str.8 = [29 x i8] c"\0Aa = %ld, k = %ld, n = %ld\0A\0A\00"
@.str.9 = [38 x i8] c"\0ASolving x \E2\89\A1 (%ld^%ld) mod %ld...\0A\0A\00"
@.str.10 = [39 x i8] c"\1B[1m\1B[32m\0AThe answer is x = %ld.\0A\0A\1B[0m\00"
define void @modexp() {
br label %1
1: ; preds = %55, %0
%2 = tail call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([15 x i8], [15 x i8]* @.str, i64 0, i64 0))
%3 = tail call i64 (...) @safeScanModExpArg()
%4 = tail call i64 @checkModExpNum(i64 %3)
%5 = icmp eq i64 %4, 0
br i1 %5, label %19, label %6
6: ; preds = %1
%7 = tail call i64 @isPossibleLongSquareOverflow(i64 %3)
%8 = icmp eq i64 %7, 0
br i1 %8, label %9, label %14
9: ; preds = %6
%10 = tail call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([15 x i8], [15 x i8]* @.str.3, i64 0, i64 0))
%11 = tail call i64 (...) @safeScanModExpArg()
%12 = tail call i64 @checkModExpNum(i64 %11)
%13 = icmp eq i64 %12, 0
br i1 %13, label %23, label %21
14: ; preds = %6
%15 = tail call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([107 x i8], [107 x i8]* @.str.1, i64 0, i64 0), i64 %3)
%16 = tail call i64 @pow(i32 2, i32 63)
%17 = add nsw i64 %16, -1
%18 = tail call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([82 x i8], [82 x i8]* @.str.2, i64 0, i64 0), i64 %17)
br label %55
19: ; preds = %1
%20 = tail call i32 @printFeedback(i64 %3)
br label %55
21: ; preds = %23, %9
%22 = phi i64 [ %11, %9 ], [ %27, %23 ]
br label %30
23: ; preds = %9, %23
%24 = phi i64 [ %27, %23 ], [ %11, %9 ]
%25 = tail call i32 @printFeedback(i64 %24)
%26 = tail call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([15 x i8], [15 x i8]* @.str.3, i64 0, i64 0))
%27 = tail call i64 (...) @safeScanModExpArg()
%28 = tail call i64 @checkModExpNum(i64 %27)
%29 = icmp eq i64 %28, 0
br i1 %29, label %23, label %21
30: ; preds = %43, %21
%31 = tail call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([15 x i8], [15 x i8]* @.str.4, i64 0, i64 0))
%32 = tail call i64 (...) @safeScanModExpArg()
%33 = tail call i64 @checkModExpNum(i64 %32)
%34 = icmp eq i64 %33, 0
br i1 %34, label %48, label %35
35: ; preds = %30
%36 = tail call i64 @isPossibleLongSquareOverflow(i64 %32)
%37 = icmp eq i64 %36, 0
br i1 %37, label %44, label %38
38: ; preds = %35
%39 = tail call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([107 x i8], [107 x i8]* @.str.5, i64 0, i64 0), i64 %3)
%40 = tail call i64 @pow(i32 2, i32 63)
%41 = add nsw i64 %40, -1
%42 = tail call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([82 x i8], [82 x i8]* @.str.6, i64 0, i64 0), i64 %41)
br label %43
43: ; preds = %38, %46, %48
br label %30
44: ; preds = %35
%45 = icmp eq i64 %32, 0
br i1 %45, label %46, label %50
46: ; preds = %44
%47 = tail call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([67 x i8], [67 x i8]* @.str.7, i64 0, i64 0))
br label %43
48: ; preds = %30
%49 = tail call i32 @printFeedback(i64 %32)
br label %43
50: ; preds = %44
%51 = tail call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([29 x i8], [29 x i8]* @.str.8, i64 0, i64 0), i64 %3, i64 %22, i64 %32)
%52 = tail call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([38 x i8], [38 x i8]* @.str.9, i64 0, i64 0), i64 %3, i64 %22, i64 %32)
%53 = tail call i64 @calcModExp(i64 %3, i64 %22, i64 %32)
%54 = tail call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([39 x i8], [39 x i8]* @.str.10, i64 0, i64 0), i64 %53)
br label %55
55: ; preds = %50, %14, %19
br label %1
}