#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 */
typedef int /*<<< orphan*/ seq;

/* Variables and functions */
int /*<<< orphan*/ display_tupples(int *, int, int);
int /*<<< orphan*/ free(int *);
int *get_2_tupples(int *, int *);
int /*<<< orphan*/ get_all_solutions(int *, int, int, int);
int *get_next_size_tupples(int *, int *, int, int, int, int *);
int /*<<< orphan*/ printf(char *, int);
int main() {
  int seq[16] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
  int tupple_array_size = 0;
  int cardinality = 2;
  int *tupples_n = get_2_tupples(seq, &tupple_array_size);
  int *tupples_nplus1 = NULL;
  int *final_tupples = NULL;
  int sum = 0;
  int final_cardinality = 4;
  int num_tupples_in_sol = 4;
  int seq_sz = sizeof(seq) / sizeof(seq[0]);
  for (int i = 0; i < seq_sz; i++) {
    sum += seq[i];
  }
  sum /= final_cardinality;
  printf("Sum = %d\n", sum);
  printf("Cardinality = %d\n", cardinality);
  display_tupples(tupples_n, tupple_array_size, cardinality);
  while (cardinality != final_cardinality) {
    tupples_nplus1 =
        get_next_size_tupples(seq, tupples_n, tupple_array_size, cardinality,
                              sum, &tupple_array_size);
    free(tupples_n);
    tupples_n = tupples_nplus1;
    cardinality++;
    printf("Cardinality = %d\n", cardinality);
    display_tupples(tupples_n, tupple_array_size, cardinality);
  }
  get_all_solutions(tupples_nplus1, tupple_array_size, final_cardinality,
                    num_tupples_in_sol);
  if (tupples_nplus1) {
    free(tupples_nplus1);
  }
}


x86 assembly (clang, -O0):
<main>:
push   %rbp
mov    %rsp,%rbp
sub    $0x90,%rsp
movl   $0x0,-0x4(%rbp)
lea    -0x50(%rbp),%rdi
lea    0xe73(%rip),%rsi
mov    $0x40,%edx
call   1060 <memcpy@plt>
movl   $0x0,-0x54(%rbp)
movl   $0x2,-0x58(%rbp)
lea    -0x50(%rbp),%rdi
lea    -0x54(%rbp),%rsi
call   1070 <get_2_tupples@plt>
mov    %rax,-0x60(%rbp)
movq   $0x0,-0x68(%rbp)
movq   $0x0,-0x70(%rbp)
movl   $0x0,-0x74(%rbp)
movl   $0x4,-0x78(%rbp)
movl   $0x4,-0x7c(%rbp)
movl   $0x10,-0x80(%rbp)
movl   $0x0,-0x84(%rbp)
mov    -0x84(%rbp),%eax
cmp    -0x80(%rbp),%eax
jge    1220 <main+0xb0>
movslq -0x84(%rbp),%rax
mov    -0x50(%rbp,%rax,4),%eax
add    -0x74(%rbp),%eax
mov    %eax,-0x74(%rbp)
mov    -0x84(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x84(%rbp)
jmp    11ec <main+0x7c>
mov    -0x78(%rbp),%ecx
mov    -0x74(%rbp),%eax
cltd
idiv   %ecx
mov    %eax,-0x74(%rbp)
mov    -0x74(%rbp),%esi
lea    0xe0a(%rip),%rdi
call   1040 <printf@plt>
mov    -0x58(%rbp),%esi
lea    0xe05(%rip),%rdi
call   1040 <printf@plt>
mov    -0x60(%rbp),%rdi
mov    -0x54(%rbp),%esi
mov    -0x58(%rbp),%edx
call   1080 <display_tupples@plt>
mov    -0x58(%rbp),%eax
cmp    -0x78(%rbp),%eax
je     12c1 <main+0x151>
lea    -0x50(%rbp),%rdi
mov    -0x60(%rbp),%rsi
mov    -0x54(%rbp),%edx
mov    -0x58(%rbp),%ecx
mov    -0x74(%rbp),%r8d
lea    -0x54(%rbp),%r9
call   1050 <get_next_size_tupples@plt>
mov    %rax,-0x68(%rbp)
mov    -0x60(%rbp),%rdi
call   1030 <free@plt>
mov    -0x68(%rbp),%rax
mov    %rax,-0x60(%rbp)
mov    -0x58(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x58(%rbp)
mov    -0x58(%rbp),%esi
lea    0xda2(%rip),%rdi
call   1040 <printf@plt>
mov    -0x60(%rbp),%rdi
mov    -0x54(%rbp),%esi
mov    -0x58(%rbp),%edx
call   1080 <display_tupples@plt>
jmp    1259 <main+0xe9>
mov    -0x68(%rbp),%rdi
mov    -0x54(%rbp),%esi
mov    -0x78(%rbp),%edx
mov    -0x7c(%rbp),%ecx
call   1090 <get_all_solutions@plt>
cmpq   $0x0,-0x68(%rbp)
je     12e7 <main+0x177>
mov    -0x68(%rbp),%rdi
call   1030 <free@plt>
mov    -0x4(%rbp),%eax
add    $0x90,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<main>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
sub    $0x58,%rsp
movaps 0xebb(%rip),%xmm0
movaps %xmm0,0x40(%rsp)
movaps 0xe9f(%rip),%xmm0
movaps %xmm0,0x30(%rsp)
movaps 0xe83(%rip),%xmm0
movaps %xmm0,0x20(%rsp)
movaps 0xe67(%rip),%xmm0
movaps %xmm0,0x10(%rsp)
movl   $0x0,0xc(%rsp)
lea    0x10(%rsp),%r15
lea    0xc(%rsp),%r14
mov    %r15,%rdi
mov    %r14,%rsi
call   1060 <get_2_tupples@plt>
movdqa 0x10(%rsp),%xmm0
movdqa 0x20(%rsp),%xmm1
paddd  0x40(%rsp),%xmm1
paddd  0x30(%rsp),%xmm0
mov    %rax,%rbx
paddd  %xmm1,%xmm0
pshufd $0xee,%xmm0,%xmm1
paddd  %xmm0,%xmm1
pshufd $0x55,%xmm1,%xmm0
paddd  %xmm1,%xmm0
movd   %xmm0,%eax
lea    0x3(%rax),%ebp
test   %eax,%eax
cmovns %eax,%ebp
sar    $0x2,%ebp
lea    0xe3e(%rip),%rdi
mov    %ebp,%esi
call   1040 <printf@plt>
lea    0xe3a(%rip),%r12
mov    %r12,%rdi
mov    $0x2,%esi
call   1040 <printf@plt>
mov    0xc(%rsp),%esi
mov    %rbx,%rdi
mov    $0x2,%edx
call   1070 <display_tupples@plt>
mov    0xc(%rsp),%edx
mov    %r15,%rdi
mov    %rbx,%rsi
mov    $0x2,%ecx
mov    %ebp,%r8d
mov    %r14,%r9
call   1050 <get_next_size_tupples@plt>
mov    %rax,%r13
mov    %rbx,%rdi
call   1030 <free@plt>
mov    %r12,%rdi
mov    $0x3,%esi
call   1040 <printf@plt>
mov    0xc(%rsp),%esi
mov    %r13,%rdi
mov    $0x3,%edx
call   1070 <display_tupples@plt>
mov    0xc(%rsp),%edx
mov    %r15,%rdi
mov    %r13,%rsi
mov    $0x3,%ecx
mov    %ebp,%r8d
mov    %r14,%r9
call   1050 <get_next_size_tupples@plt>
mov    %rax,%rbx
mov    %r13,%rdi
call   1030 <free@plt>
mov    %r12,%rdi
mov    $0x4,%esi
call   1040 <printf@plt>
mov    0xc(%rsp),%esi
mov    %rbx,%rdi
mov    $0x4,%edx
call   1070 <display_tupples@plt>
mov    0xc(%rsp),%esi
mov    %rbx,%rdi
mov    $0x4,%edx
mov    $0x4,%ecx
call   1080 <get_all_solutions@plt>
test   %rbx,%rbx
je     12d7 <main+0x177>
mov    %rbx,%rdi
call   1030 <free@plt>
xor    %eax,%eax
add    $0x58,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret

LLVM IR (-O0):
@__const.main.seq = [16 x i32] [i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16]
@.str = [10 x i8] c"Sum = %d\0A\00"
@.str.1 = [18 x i8] c"Cardinality = %d\0A\00"
define i32 @main() {
%1 = alloca i32
%2 = alloca [16 x i32]
%3 = alloca i32
%4 = alloca i32
%5 = alloca i32*
%6 = alloca i32*
%7 = alloca i32*
%8 = alloca i32
%9 = alloca i32
%10 = alloca i32
%11 = alloca i32
%12 = alloca i32
store i32 0, i32* %1
%13 = bitcast [16 x i32]* %2 to i8*
store i32 0, i32* %3
store i32 2, i32* %4
%14 = getelementptr inbounds [16 x i32], [16 x i32]* %2, i64 0, i64 0
%15 = call i32* @get_2_tupples(i32* %14, i32* %3)
store i32* %15, i32** %5
store i32* null, i32** %6
store i32* null, i32** %7
store i32 0, i32* %8
store i32 4, i32* %9
store i32 4, i32* %10
store i32 16, i32* %11
store i32 0, i32* %12
br label %16
16: ; preds = %27, %0
%17 = load i32, i32* %12
%18 = load i32, i32* %11
%19 = icmp slt i32 %17, %18
br i1 %19, label %20, label %30
20: ; preds = %16
%21 = load i32, i32* %12
%22 = sext i32 %21 to i64
%23 = getelementptr inbounds [16 x i32], [16 x i32]* %2, i64 0, i64 %22
%24 = load i32, i32* %23
%25 = load i32, i32* %8
%26 = add nsw i32 %25, %24
store i32 %26, i32* %8
br label %27
27: ; preds = %20
%28 = load i32, i32* %12
%29 = add nsw i32 %28, 1
store i32 %29, i32* %12
br label %16
30: ; preds = %16
%31 = load i32, i32* %9
%32 = load i32, i32* %8
%33 = sdiv i32 %32, %31
store i32 %33, i32* %8
%34 = load i32, i32* %8
%35 = call i32 @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str, i64 0, i64 0), i32 %34)
%36 = load i32, i32* %4
%37 = call i32 @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str.1, i64 0, i64 0), i32 %36)
%38 = load i32*, i32** %5
%39 = load i32, i32* %3
%40 = load i32, i32* %4
%41 = call i32 @display_tupples(i32* %38, i32 %39, i32 %40)
br label %42
42: ; preds = %46, %30
%43 = load i32, i32* %4
%44 = load i32, i32* %9
%45 = icmp ne i32 %43, %44
br i1 %45, label %46, label %64
46: ; preds = %42
%47 = getelementptr inbounds [16 x i32], [16 x i32]* %2, i64 0, i64 0
%48 = load i32*, i32** %5
%49 = load i32, i32* %3
%50 = load i32, i32* %4
%51 = load i32, i32* %8
%52 = call i32* @get_next_size_tupples(i32* %47, i32* %48, i32 %49, i32 %50, i32 %51, i32* %3)
store i32* %52, i32** %6
%53 = load i32*, i32** %5
%54 = call i32 @free(i32* %53)
%55 = load i32*, i32** %6
store i32* %55, i32** %5
%56 = load i32, i32* %4
%57 = add nsw i32 %56, 1
store i32 %57, i32* %4
%58 = load i32, i32* %4
%59 = call i32 @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str.1, i64 0, i64 0), i32 %58)
%60 = load i32*, i32** %5
%61 = load i32, i32* %3
%62 = load i32, i32* %4
%63 = call i32 @display_tupples(i32* %60, i32 %61, i32 %62)
br label %42
64: ; preds = %42
%65 = load i32*, i32** %6
%66 = load i32, i32* %3
%67 = load i32, i32* %9
%68 = load i32, i32* %10
%69 = call i32 @get_all_solutions(i32* %65, i32 %66, i32 %67, i32 %68)
%70 = load i32*, i32** %6
%71 = icmp ne i32* %70, null
br i1 %71, label %72, label %75
72: ; preds = %64
%73 = load i32*, i32** %6
%74 = call i32 @free(i32* %73)
br label %75
75: ; preds = %72, %64
%76 = load i32, i32* %1
ret i32 %76
}

LLVM IR (-O2):
@__const.main.seq = [16 x i32] [i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 8, i32 9, i32 10, i32 11, i32 12, i32 13, i32 14, i32 15, i32 16]
@.str = [10 x i8] c"Sum = %d\0A\00"
@.str.1 = [18 x i8] c"Cardinality = %d\0A\00"
define i32 @main() {
%1 = alloca <16 x i32>
%2 = alloca i32
%3 = bitcast <16 x i32>* %1 to i8*
%4 = bitcast i32* %2 to i8*
store i32 0, i32* %2
%5 = getelementptr inbounds <16 x i32>, <16 x i32>* %1, i64 0, i64 0
%6 = call i32* @get_2_tupples(i32* %5, i32* %2)
%7 = load <16 x i32>, <16 x i32>* %1
%8 = call i32 @llvm.vector.reduce.add.v16i32(<16 x i32> %7)
%9 = sdiv i32 %8, 4
%10 = call i32 @printf(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @.str, i64 0, i64 0), i32 %9)
%11 = call i32 @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str.1, i64 0, i64 0), i32 2)
%12 = load i32, i32* %2
%13 = call i32 @display_tupples(i32* %6, i32 %12, i32 2)
%14 = load i32, i32* %2
%15 = call i32* @get_next_size_tupples(i32* %5, i32* %6, i32 %14, i32 2, i32 %9, i32* %2)
%16 = call i32 @free(i32* %6)
%17 = call i32 @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str.1, i64 0, i64 0), i32 3)
%18 = load i32, i32* %2
%19 = call i32 @display_tupples(i32* %15, i32 %18, i32 3)
%20 = load i32, i32* %2
%21 = call i32* @get_next_size_tupples(i32* %5, i32* %15, i32 %20, i32 3, i32 %9, i32* %2)
%22 = call i32 @free(i32* %15)
%23 = call i32 @printf(i8* getelementptr inbounds ([18 x i8], [18 x i8]* @.str.1, i64 0, i64 0), i32 4)
%24 = load i32, i32* %2
%25 = call i32 @display_tupples(i32* %21, i32 %24, i32 4)
%26 = load i32, i32* %2
%27 = call i32 @get_all_solutions(i32* %21, i32 %26, i32 4, i32 4)
%28 = icmp eq i32* %21, null
br i1 %28, label %31, label %29
29: ; preds = %0
%30 = call i32 @free(i32* %21)
br label %31
31: ; preds = %29, %0
ret i32 0
}