// File: roberto-bayardo[P]google-extremal-sets/all-maximal-sets-cardinality.cc
// Function: google_extremal_sets::AllMaximalSetsCardinality::FindAllMaximalSets(google_extremal_sets::DataSourceIterator*, unsigned int, unsigned int, google_extremal_sets::OutputModeEnum)
bool AllMaximalSetsCardinality::FindAllMaximalSets(
    DataSourceIterator* data,
    uint32_t max_item_id,
    uint32_t max_items_in_ram,
    OutputModeEnum output_mode) {
  Init();

  // The index_us vector contains the previous itemsets whose
  // cardinality is the same as the current itemset. We delay their
  // indexing until they can potentially be subsumed; that is, when
  // the data iterator reaches itemsets with a higher cardinality.
  std::vector<SetProperties*> index_us;

  // Vars set by the data source iterator.
  int result;
  uint32_t set_id;
  std::vector<uint32_t> current_set;

  // This outer loop supports multiple passes over the data in the
  // case where the dataset exceeds the bound on max_items_in_ram. As
  // long as resume_offset == 0, we will continue retaining itemsets
  // in RAM. Otherwise itemsets from the data iterator will be used
  // only to perform subsumption checks against existing candidates,
  // and will be indexed during a subsequent pass.
  off_t resume_offset = 0;
  do {  // while (resume_offset != 0)
    if (!PrepareForDataScan(data, max_item_id, resume_offset))
      return false;  // IO error
    resume_offset = 0;
    uint32_t items_in_ram = 0;
    int current_set_size = -1;

    // This loop scans the input data from beginning to end.
    while ((result = data->Next(&set_id, &current_set)) > 0) {
      DeleteSubsumedCandidates(current_set);

      // If current_set has higher cardinality than the itemsets within
      // index_us, we move them from index_us into the candidate index.
      if (current_set.size() != static_cast<uint32_t>(current_set_size)) {
        IndexSets(index_us);
        index_us.clear();
        current_set_size = current_set.size();
      }

      if (resume_offset == 0) {
        // Copy the current_set into RAM and place a pointer to it in index_us.
        index_us.push_back(SetProperties::Create(set_id, current_set));
        items_in_ram += current_set.size();
        ++input_sets_count_;

        // Check if we've exceeded the RAM limit and if so stop
        // retaining any further itemsets in memory until the next
        // scan.
        if (items_in_ram >= max_items_in_ram) {
          resume_offset = data->Tell();
          std::cerr << "; Halting indexing at input set number "
                    << input_sets_count_ << " with id " << set_id << std::endl;
          // Force the sets in index_us to get added to the index.
          current_set_size = -1;
        }
      }  // if (resume_offset = 0)
    }  // while ((result = data->Next())

    if (result != 0)  // IO error
      return false;

    // At this point, any remaining candidate set and any remaining set
    // in index_us is maximal!
    DumpMaximalSets(&index_us, output_mode);
  } while (resume_offset != 0);

  return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xd0, %rsp
movq %rdi, -0x10(%rbp)
movq %rsi, -0x18(%rbp)
movl %edx, -0x1c(%rbp)
movl %ecx, -0x20(%rbp)
movl %r8d, -0x24(%rbp)
movq -0x10(%rbp), %rdi
movq %rdi, -0x90(%rbp)
callq 0x28c0
leaq -0x40(%rbp), %rdi
callq 0x2ed0
leaq -0x60(%rbp), %rdi
callq 0x2ef0
movq $0x0, -0x68(%rbp)
movq -0x90(%rbp), %rdi
movq -0x18(%rbp), %rsi
movl -0x1c(%rbp), %edx
movq -0x68(%rbp), %rcx
callq 0x28f0
movb %al, -0x91(%rbp)
jmp 0x2666
movb -0x91(%rbp), %al
testb $0x1, %al
jne 0x26a5
jmp 0x2672
movb $0x0, -0x1(%rbp)
movl $0x1, -0x78(%rbp)
jmp 0x2894
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x70(%rbp)
movl %eax, -0x74(%rbp)
leaq -0x60(%rbp), %rdi
callq 0x2f80
leaq -0x40(%rbp), %rdi
callq 0x2fe0
jmp 0x28b4
movq $0x0, -0x68(%rbp)
movl $0x0, -0x7c(%rbp)
movl $0xffffffff, -0x80(%rbp) # imm = 0xFFFFFFFF
movq -0x18(%rbp), %rdi
leaq -0x48(%rbp), %rsi
leaq -0x60(%rbp), %rdx
callq 0x5c40
movl %eax, -0x98(%rbp)
jmp 0x26d4
movl -0x98(%rbp), %eax
movl %eax, -0x44(%rbp)
cmpl $0x0, %eax
jle 0x2854
movq -0x90(%rbp), %rdi
leaq -0x60(%rbp), %rsi
callq 0x29a0
jmp 0x26f8
leaq -0x60(%rbp), %rdi
callq 0x2f10
movl -0x80(%rbp), %ecx
cmpq %rcx, %rax
je 0x2730
movq -0x90(%rbp), %rdi
leaq -0x40(%rbp), %rsi
callq 0x2b30
jmp 0x271b
leaq -0x40(%rbp), %rdi
callq 0x2f30
leaq -0x60(%rbp), %rdi
callq 0x2f10
movl %eax, -0x80(%rbp)
cmpq $0x0, -0x68(%rbp)
jne 0x284f
movl -0x48(%rbp), %edi
leaq -0x60(%rbp), %rsi
callq 0x7590
movq %rax, -0xa0(%rbp)
jmp 0x2750
movq -0xa0(%rbp), %rax
movq %rax, -0x88(%rbp)
leaq -0x40(%rbp), %rdi
leaq -0x88(%rbp), %rsi
callq 0x2f50
jmp 0x2770
leaq -0x60(%rbp), %rdi
callq 0x2f10
movq %rax, %rdx
movq -0x90(%rbp), %rax
movl -0x7c(%rbp), %ecx
addq %rdx, %rcx
movl %ecx, -0x7c(%rbp)
movq 0x8(%rax), %rcx
addq $0x1, %rcx
movq %rcx, 0x8(%rax)
movl -0x7c(%rbp), %eax
cmpl -0x20(%rbp), %eax
jb 0x284d
movq -0x18(%rbp), %rdi
callq 0x5c20
movq %rax, -0xa8(%rbp)
jmp 0x27b6
movq -0xa8(%rbp), %rax
movq %rax, -0x68(%rbp)
movq 0xa828(%rip), %rdi      # 0xcff0
leaq 0x5835(%rip), %rsi      # 0x8004
callq 0x2200
movq %rax, -0xb0(%rbp)
jmp 0x27dd
movq -0xb0(%rbp), %rdi
movq -0x90(%rbp), %rax
movq 0x8(%rax), %rsi
callq 0x23a0
movq %rax, -0xb8(%rbp)
jmp 0x27fd
movq -0xb8(%rbp), %rdi
leaq 0x5821(%rip), %rsi      # 0x802c
callq 0x2200
movq %rax, -0xc0(%rbp)
jmp 0x2819
movq -0xc0(%rbp), %rdi
movl -0x48(%rbp), %esi
callq 0x22e0
movq %rax, -0xc8(%rbp)
jmp 0x2831
movq -0xc8(%rbp), %rdi
movq 0xa779(%rip), %rsi      # 0xcfb8
callq 0x2240
jmp 0x2846
movl $0xffffffff, -0x80(%rbp) # imm = 0xFFFFFFFF
jmp 0x284f
jmp 0x26bb
cmpl $0x0, -0x44(%rbp)
je 0x2867
movb $0x0, -0x1(%rbp)
movl $0x1, -0x78(%rbp)
jmp 0x2894
movq -0x90(%rbp), %rdi
movl -0x24(%rbp), %edx
leaq -0x40(%rbp), %rsi
callq 0x2c00
jmp 0x287c
jmp 0x287e
cmpq $0x0, -0x68(%rbp)
jne 0x2647
movb $0x1, -0x1(%rbp)
movl $0x1, -0x78(%rbp)
leaq -0x60(%rbp), %rdi
callq 0x2f80
leaq -0x40(%rbp), %rdi
callq 0x2fe0
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0xd0, %rsp
popq %rbp
retq
movq -0x70(%rbp), %rdi
callq 0x2370
nopl (%rax)