// File: ChanTsune[P]py_string/./py_string.hpp
// Function: std::tuple<int, int, int, int> py::util::adjust_index<int>(py::null_allow::null_allow<int>, py::null_allow::null_allow<int>, py::null_allow::null_allow<int>, int)
inline std::tuple<T, T, T, T> adjust_index(optional<T> _start,
                                             optional<T> _stop,
                                             optional<T> _step, T _length)
  {
    T start, stop, step = _step.value_or(1), upper, lower;
    T step_sign = sign(step);
    bool step_is_negative = step_sign < 0;
    /* Find lower and upper bounds for start and stop. */
    if (step_is_negative) {
      lower = -1;
      upper = _length + lower;
    } else {
      lower = 0;
      upper = _length;
    }
    // Compute start.
    if (_start.has_value()) {
      start = _start.value();
      if (sign(start) < 0) {
        start += _length;

        if (start < lower /* Py_LT */) {
          start = lower;
        }
      } else {
        if (start > upper /* Py_GT */) {
          start = upper;
        }
      }
    } else {
      start = step_is_negative ? upper : lower;
    }
    // Compute stop.
    if (_stop.has_value()) {
      stop = _stop.value();

      if (sign(stop) < 0) {
        stop += _length;
        if (stop < lower /* Py_LT */) {
          stop = lower;
        }
      } else {
        if (stop > upper /* Py_GT */) {
          stop = upper;
        }
      }
    } else {
      stop = step_is_negative ? lower : upper;
    }
    T len = 0;
    if (step < 0) {
      if (stop < start) {
        len = (start - stop - 1) / (-step) + 1;
      }
    } else {
      if (start < stop) {
        len = (stop - start - 1) / step + 1;
      }
    }
    return std::make_tuple(start, stop, step, len);
  }

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x58(%rbp)
movq %rdi, %rax
movq %rax, -0x50(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movq %rcx, -0x20(%rbp)
movl %r8d, -0x24(%rbp)
movl $0x1, -0x34(%rbp)
leaq -0x20(%rbp), %rdi
leaq -0x34(%rbp), %rsi
callq 0x2b930
movl %eax, -0x30(%rbp)
movl -0x30(%rbp), %edi
callq 0x2b970
movl %eax, -0x40(%rbp)
cmpl $0x0, -0x40(%rbp)
setl %al
andb $0x1, %al
movb %al, -0x41(%rbp)
testb $0x1, -0x41(%rbp)
je 0x2af9d
movl $0xffffffff, -0x3c(%rbp) # imm = 0xFFFFFFFF
movl -0x24(%rbp), %eax
addl -0x3c(%rbp), %eax
movl %eax, -0x38(%rbp)
jmp 0x2afaa
movl $0x0, -0x3c(%rbp)
movl -0x24(%rbp), %eax
movl %eax, -0x38(%rbp)
leaq -0x10(%rbp), %rdi
callq 0x2ae70
testb $0x1, %al
jne 0x2afb9
jmp 0x2affd
leaq -0x10(%rbp), %rdi
callq 0x2b9a0
movl %eax, -0x28(%rbp)
movl -0x28(%rbp), %edi
callq 0x2b970
cmpl $0x0, %eax
jge 0x2afeb
movl -0x24(%rbp), %eax
addl -0x28(%rbp), %eax
movl %eax, -0x28(%rbp)
movl -0x28(%rbp), %eax
cmpl -0x3c(%rbp), %eax
jge 0x2afe9
movl -0x3c(%rbp), %eax
movl %eax, -0x28(%rbp)
jmp 0x2affb
movl -0x28(%rbp), %eax
cmpl -0x38(%rbp), %eax
jle 0x2aff9
movl -0x38(%rbp), %eax
movl %eax, -0x28(%rbp)
jmp 0x2affb
jmp 0x2b017
testb $0x1, -0x41(%rbp)
je 0x2b00b
movl -0x38(%rbp), %eax
movl %eax, -0x5c(%rbp)
jmp 0x2b011
movl -0x3c(%rbp), %eax
movl %eax, -0x5c(%rbp)
movl -0x5c(%rbp), %eax
movl %eax, -0x28(%rbp)
leaq -0x18(%rbp), %rdi
callq 0x2ae70
testb $0x1, %al
jne 0x2b026
jmp 0x2b06a
leaq -0x18(%rbp), %rdi
callq 0x2b9a0
movl %eax, -0x2c(%rbp)
movl -0x2c(%rbp), %edi
callq 0x2b970
cmpl $0x0, %eax
jge 0x2b058
movl -0x24(%rbp), %eax
addl -0x2c(%rbp), %eax
movl %eax, -0x2c(%rbp)
movl -0x2c(%rbp), %eax
cmpl -0x3c(%rbp), %eax
jge 0x2b056
movl -0x3c(%rbp), %eax
movl %eax, -0x2c(%rbp)
jmp 0x2b068
movl -0x2c(%rbp), %eax
cmpl -0x38(%rbp), %eax
jle 0x2b066
movl -0x38(%rbp), %eax
movl %eax, -0x2c(%rbp)
jmp 0x2b068
jmp 0x2b084
testb $0x1, -0x41(%rbp)
je 0x2b078
movl -0x3c(%rbp), %eax
movl %eax, -0x60(%rbp)
jmp 0x2b07e
movl -0x38(%rbp), %eax
movl %eax, -0x60(%rbp)
movl -0x60(%rbp), %eax
movl %eax, -0x2c(%rbp)
movl $0x0, -0x48(%rbp)
cmpl $0x0, -0x30(%rbp)
jge 0x2b0b2
movl -0x2c(%rbp), %eax
cmpl -0x28(%rbp), %eax
jge 0x2b0b0
movl -0x28(%rbp), %eax
subl -0x2c(%rbp), %eax
subl $0x1, %eax
xorl %ecx, %ecx
subl -0x30(%rbp), %ecx
cltd
idivl %ecx
addl $0x1, %eax
movl %eax, -0x48(%rbp)
jmp 0x2b0cf
movl -0x28(%rbp), %eax
cmpl -0x2c(%rbp), %eax
jge 0x2b0cd
movl -0x2c(%rbp), %eax
subl -0x28(%rbp), %eax
subl $0x1, %eax
cltd
idivl -0x30(%rbp)
addl $0x1, %eax
movl %eax, -0x48(%rbp)
jmp 0x2b0cf
movq -0x58(%rbp), %rdi
leaq -0x28(%rbp), %rsi
leaq -0x2c(%rbp), %rdx
leaq -0x30(%rbp), %rcx
leaq -0x48(%rbp), %r8
callq 0x2b9b0
movq -0x50(%rbp), %rax
addq $0x60, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
nopl (%rax)