// File: /workspace/github_c_makefile_star2_O2/BernardTatin[P]s7sh/s7.c
// Function: g_expt
static s7_pointer g_expt(s7_scheme *sc, s7_pointer args)
    {
#define H_expt "(expt z1 z2) returns z1^z2"
#define Q_expt sc->pcl_n
        s7_pointer n, pw;

        n = car(args);
        if (!s7_is_number(n))
            return(method_or_bust_with_type(sc, n, sc->expt_symbol, args, a_number_string, 1));

        pw = cadr(args);
        if (!s7_is_number(pw))
            return(method_or_bust_with_type(sc, pw, sc->expt_symbol, args, a_number_string, 2));

        /* this provides more than 2 args to expt:
         *  if (is_not_null(cddr(args)))
         *    return(g_expt(sc, list_2(sc, car(args), g_expt(sc, cdr(args)))));
         * but it's unusual in scheme to process args in reverse order, and the
         * syntax by itself is ambiguous (does (expt 2 2 3) = 256 or 64?)
         */

        if (s7_is_zero(n))
        {
            if (s7_is_zero(pw))
            {
                if ((s7_is_integer(n)) && (s7_is_integer(pw)))       /* (expt 0 0) -> 1 */
                    return(small_int(1));
                return(real_zero);                                   /* (expt 0.0 0) -> 0.0 */
            }

            if (s7_is_real(pw))
            {
                if (s7_is_negative(pw))                              /* (expt 0 -1) */
                    return(division_by_zero_error(sc, sc->expt_symbol, args));
                /* (Clisp gives divide-by-zero error here, Guile returns inf.0) */

                if ((!s7_is_rational(pw)) &&                         /* (expt 0 most-positive-fixnum) */
                        (is_NaN(s7_real(pw))))                           /* (expt 0 +nan.0) */
                    return(pw);
            }
            else
            {                                                      /* (expt 0 a+bi) */
                if (real_part(pw) < 0.0)                             /* (expt 0 -1+i) */
                    return(division_by_zero_error(sc, sc->expt_symbol, args));
                if ((is_NaN(real_part(pw))) ||                       /* (expt 0 0+1/0i) */
                        (is_NaN(imag_part(pw))))
                    return(real_NaN);
            }

            if ((s7_is_integer(n)) && (s7_is_integer(pw)))           /* pw != 0, (expt 0 2312) */
                return(small_int(0));
            return(real_zero);                                       /* (expt 0.0 123123) */
        }

        if (s7_is_one(pw))
        {
            if (s7_is_integer(pw))                                   /* (expt x 1) */
                return(n);
            if (is_rational(n))                                      /* (expt ratio 1.0) */
                return(make_real(sc, rational_to_double(sc, n)));
            return(n);
        }

        if (is_t_integer(pw))
        {
            s7_int y;
            y = integer(pw);
            if (y == 0)
            {
                if (is_rational(n))                                 /* (expt 3 0) */
                    return(small_int(1));
                if ((is_NaN(s7_real_part(n))) ||                    /* (expt 1/0 0) -> NaN */
                        (is_NaN(s7_imag_part(n))))                      /* (expt (complex 0 1/0) 0) -> NaN */
                    return(n);
                return(real_one);                                   /* (expt 3.0 0) */
            }

            switch (type(n))
            {
                case T_INTEGER:
                    {
                        s7_int x;
                        x = s7_integer(n);
                        if (x == 1)                                       /* (expt 1 y) */
                            return(n);

                        if (x == -1)
                        {
                            if (y == s7_int_min)                          /* (expt -1 most-negative-fixnum) */
                                return(small_int(1));

                            if (s7_int_abs(y) & 1)                        /* (expt -1 odd-int) */
                                return(n);
                            return(small_int(1));                         /* (expt -1 even-int) */
                        }

                        if (y == s7_int_min)                              /* (expt x most-negative-fixnum) */
                            return(small_int(0));
                        if (x == s7_int_min)                              /* (expt most-negative-fixnum y) */
                            return(make_real(sc, pow((double)x, (double)y)));

                        if (int_pow_ok(x, s7_int_abs(y)))
                        {
                            if (y > 0)
                                return(make_integer(sc, int_to_int(x, y)));
                            return(s7_make_ratio(sc, 1, int_to_int(x, -y)));
                        }
                    }
                    break;

                case T_RATIO:
                    {
                        s7_int nm, dn;

                        nm = numerator(n);
                        dn = denominator(n);

                        if (y == s7_int_min)
                        {
                            if (s7_int_abs(nm) > dn)
                                return(small_int(0));              /* (expt 4/3 most-negative-fixnum) -> 0? */
                            return(real_infinity);               /* (expt 3/4 most-negative-fixnum) -> inf? */
                        }

                        if ((int_pow_ok(nm, s7_int_abs(y))) &&
                                (int_pow_ok(dn, s7_int_abs(y))))
                        {
                            if (y > 0)
                                return(s7_make_ratio(sc, int_to_int(nm, y), int_to_int(dn, y)));
                            return(s7_make_ratio(sc, int_to_int(dn, -y), int_to_int(nm, -y)));
                        }
                    }
                    break;
                    /* occasionally int^rat can be int32_t but it happens so infrequently it's probably not worth checking
                     *  one possibly easy case: (expt 1 1/2) -> 1 (-1?) etc
                     */

                case T_REAL:
                    /* (expt -1.0 most-positive-fixnum) should be -1.0
                     * (expt -1.0 (+ (expt 2 53) 1)) -> -1.0
                     * (expt -1.0 (- 1 (expt 2 54))) -> -1.0
                     */
                    if (real(n) == -1.0)
                    {
                        if (y == s7_int_min)
                            return(real_one);

                        if (s7_int_abs(y) & 1)
                            return(n);
                        return(real_one);
                    }
                    break;

                case T_COMPLEX:
#if HAVE_COMPLEX_NUMBERS
                    if ((s7_real_part(n) == 0.0) &&
                            ((s7_imag_part(n) == 1.0) ||
                             (s7_imag_part(n) == -1.0)))
                    {
                        bool yp, np;
                        yp = (y > 0);
                        np = (s7_imag_part(n) > 0.0);
                        switch (s7_int_abs(y) % 4)
                        {
                            case 0: return(real_one);
                            case 1: return(s7_make_complex(sc, 0.0, (yp == np) ? 1.0 : -1.0));
                            case 2: return(make_real(sc, -1.0));
                            case 3: return(s7_make_complex(sc, 0.0, (yp == np) ? -1.0 : 1.0));
                        }
                    }
#else
                    return(out_of_range(sc, sc->expt_symbol, small_int(2), n, no_complex_numbers_string));
#endif
                    break;
            }
        }

        if ((s7_is_real(n)) &&
                (s7_is_real(pw)))
        {
            s7_double x, y;

            if ((is_t_ratio(pw)) &&
                    (numerator(pw) == 1))
            {
                if (denominator(pw) == 2)
                    return(g_sqrt(sc, args));
                if (denominator(pw) == 3)
                    return(make_real(sc, cbrt(s7_real(n)))); /* (expt 27 1/3) should be 3, not 3.0... */

                /* but: (expt 512/729 1/3) -> 0.88888888888889, and 4 -> sqrt(sqrt...) etc? */
            }

            x = s7_real(n);
            y = s7_real(pw);

            if (is_NaN(x)) return(n);
            if (is_NaN(y)) return(pw);
            if (y == 0.0) return(real_one);

            if (x > 0.0)
                return(make_real(sc, pow(x, y)));      /* tricky cases abound here: (expt -1 1/9223372036854775807) */
        }

        /* (expt 0+i 1e+16) = 0.98156860153485-0.19111012657867i ?
         * (expt 0+i 1+1/0i) = 0.0 ??
         */
        return(s7_from_c_complex(sc, cpow(s7_to_c_complex(n), s7_to_c_complex(pw))));
    }

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movq %rsi, %r12
movq 0x8(%rsi), %r14
movb (%r14), %bl
movzbl %bl, %r15d
movl %r15d, %r13d
leaq 0xc6237(%rip), %rax     # 0x119970
cmpb $0x0, (%r13,%rax)
je 0x5379b
movq 0x10(%r12), %rcx
movq 0x8(%rcx), %rsi
movzbl (%rsi), %ebp
cmpb $0x0, (%rbp,%rax)
je 0x537b2
movq %rsi, 0x10(%rsp)
movq %rdi, 0x8(%rsp)
movq %r14, %rdi
callq 0xc77c4
testb %al, %al
je 0x537da
movq 0x10(%rsp), %rdi
callq 0xc77c4
testb %al, %al
je 0x53820
cmpb $0xb, %bl
jne 0x53955
cmpb $0xb, %bpl
jne 0x53955
movq 0xc21c2(%rip), %r14     # 0x115958
jmp 0x53d30
movq 0xed8(%rdi), %rdx
movq 0xd0bf7(%rip), %r8      # 0x1243a0
pushq $0x1
popq %r9
movq %r14, %rsi
jmp 0x537c4
movq 0xed8(%rdi), %rdx
movq 0xd0be0(%rip), %r8      # 0x1243a0
pushq $0x2
popq %r9
movq %r12, %rcx
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0xcf9a
movq 0x10(%rsp), %rdi
callq 0x79edb
testb %al, %al
je 0x5384e
cmpl $0xb, %ebp
movq 0x8(%rsp), %rdx
je 0x53d30
leaq 0xc61f3(%rip), %rax     # 0x1199f0
cmpb $0x1, (%r13,%rax)
jne 0x53d30
movq 0x8(%r14), %rax
cmpb $0xb, %bl
jne 0x539a4
cvtsi2sd %rax, %xmm0
jmp 0x53ce2
leaq 0xc6189(%rip), %rax     # 0x1199b0
cmpb $0x1, (%rbp,%rax)
jne 0x538c1
movq 0x10(%rsp), %rdi
callq 0xa5cc2
testb %al, %al
je 0x538f7
movq 0x8(%rsp), %rdi
jmp 0x538da
cmpl $0xb, %ebp
movq 0x10(%rsp), %rdx
jne 0x53bc2
movq 0x8(%rdx), %r8
testq %r8, %r8
je 0x53961
addl $-0xb, %r15d
cmpl $0x3, %r15d
ja 0x53bc2
leaq 0x80196(%rip), %rax     # 0xd3a14
movslq (%rax,%r15,4), %rcx
addq %rax, %rcx
jmpq *%rcx
movq 0x8(%r14), %r15
cmpq $0x1, %r15
je 0x53d30
cmpq $-0x1, %r15
jne 0x53b42
movl 0xc6183(%rip), %eax     # 0x119a28
shlq $0x3f, %rax
cmpq %rax, %r8
je 0x5378f
testb $0x1, %r8b
je 0x5378f
jmp 0x53d30
movq 0x10(%rsp), %rax
movsd 0x8(%rax), %xmm0
xorpd %xmm1, %xmm1
ucomisd %xmm0, %xmm1
movq 0x8(%rsp), %rdi
jbe 0x53926
movq 0xed8(%rdi), %rsi
movq %r12, %rdx
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0xc1ff
leaq 0xc60f2(%rip), %rax     # 0x1199f0
cmpb $0x0, (%rbp,%rax)
movq 0x10(%rsp), %rax
jne 0x5393f
movq %rax, %rdi
callq 0xc42a
ucomisd %xmm0, %xmm0
jp 0x53e5c
movb (%r14), %bl
movq 0x10(%rsp), %rax
jmp 0x5393f
ucomisd %xmm0, %xmm0
jp 0x53e50
movsd 0x10(%rax), %xmm0
ucomisd %xmm0, %xmm0
jp 0x53e50
cmpb $0xb, %bl
jne 0x53955
cmpb $0xb, (%rax)
jne 0x53955
movq 0xc2000(%rip), %r14     # 0x115950
jmp 0x53d30
movq 0xc62fc(%rip), %r14     # 0x119c58
jmp 0x53d30
leaq 0xc6088(%rip), %rax     # 0x1199f0
cmpb $0x1, (%r13,%rax)
je 0x5378f
movq %r14, %rdi
callq 0xcbc9
ucomisd %xmm0, %xmm0
jp 0x53d30
cmpb $0xe, %bl
jne 0x53c63
movsd 0x10(%r14), %xmm0
ucomisd %xmm0, %xmm0
jnp 0x53c63
jmp 0x53d30
movq %rax, 0x38(%rsp)
fildll 0x38(%rsp)
movq 0x10(%r14), %rax
movq %rax, 0x40(%rsp)
fildll 0x40(%rsp)
fdivrp %st, %st(1)
fstpl 0x30(%rsp)
movsd 0x30(%rsp), %xmm0
jmp 0x53ce2
movsd 0x8(%r14), %xmm0
ucomisd 0x7e677(%rip), %xmm0    # 0xd2050
jne 0x53bc2
jp 0x53bc2
movl 0xc603d(%rip), %eax     # 0x119a28
shlq $0x3f, %rax
cmpq %rax, %r8
je 0x53c63
testb $0x1, %r8b
je 0x53c63
jmp 0x53d30
movq %r14, %rdi
movq %r8, %rbx
callq 0xcbc9
movq 0x10(%rsp), %rdx
movq 0x8(%rsp), %rdi
xorpd %xmm1, %xmm1
ucomisd %xmm1, %xmm0
jne 0x53bc2
jp 0x53bc2
movq %rbx, %rsi
movsd 0x10(%r14), %xmm0
ucomisd 0x7e5ef(%rip), %xmm0    # 0xd2030
jne 0x53a45
jnp 0x53a59
ucomisd 0x7e603(%rip), %xmm0    # 0xd2050
jne 0x53bc2
jp 0x53bc2
movq %rsi, %rax
negq %rax
cmovsq %rsi, %rax
andl $0x3, %eax
leaq 0x7ffb7(%rip), %rcx     # 0xd3a24
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
ucomisd %xmm1, %xmm0
seta %al
testq %rsi, %rsi
setg %cl
xorb %al, %cl
je 0x53da3
movsd 0x7e5bd(%rip), %xmm1    # 0xd2050
jmp 0x53dab
movq 0x8(%r14), %r15
movq 0x10(%r14), %rcx
movl 0xc5f82(%rip), %eax     # 0x119a28
shlq $0x3f, %rax
cmpq %rax, %r8
jne 0x53ace
movq %r15, %rax
negq %rax
cmovsq %r15, %rax
cmpq %rcx, %rax
jg 0x53949
movq 0xc93d7(%rip), %r14     # 0x11cea0
jmp 0x53d30
movq %rcx, 0x18(%rsp)
movq %r8, %rax
negq %rax
movq %r8, %rsi
movq %rax, 0x20(%rsp)
cmovnsq %rax, %rsi
movq %r15, %rdi
movq %r8, 0x28(%rsp)
movq %rsi, %rbx
callq 0xc7ab2
movq 0x10(%rsp), %rdx
testb %al, %al
je 0x53bc2
movq 0x18(%rsp), %rdi
movq %rbx, %rsi
callq 0xc7ab2
movq 0x28(%rsp), %rbx
movq 0x10(%rsp), %rdx
testb %al, %al
je 0x53bc2
testq %rbx, %rbx
jle 0x53db4
movq %r15, %rdi
movq %rbx, %rsi
callq 0xc7aef
movq %rax, %r14
movq 0x18(%rsp), %rdi
jmp 0x53dcc
movl 0xc5ee0(%rip), %eax     # 0x119a28
shlq $0x3f, %rax
cmpq %rax, %r8
je 0x53949
cmpq %rax, %r15
jne 0x53b69
cvtsi2sd %r15, %xmm0
cvtsi2sd %r8, %xmm1
jmp 0x53c79
movq %r8, %rax
negq %rax
movq %r8, %rbx
movq %r8, %rsi
movq %rax, 0x18(%rsp)
cmovnsq %rax, %rsi
movq %r15, %rdi
callq 0xc7ab2
movq 0x10(%rsp), %rdx
testb %al, %al
je 0x53bc2
movq %rbx, %rsi
movq %r15, %rdi
testq %rbx, %rbx
jle 0x53df2
callq 0xc7aef
movq %rax, %r15
cmpq $0x7ff, %rax            # imm = 0x7FF
ja 0x53e06
leaq 0xc1d97(%rip), %rax     # 0x115950
movq (%rax,%r15,8), %r14
jmp 0x53d30
leaq 0xc5de7(%rip), %rax     # 0x1199b0
cmpb $0x1, (%r13,%rax)
jne 0x53c80
cmpb $0x1, (%rbp,%rax)
jne 0x53c80
cmpl $0xc, %ebp
jne 0x53c1b
cmpq $0x1, 0x8(%rdx)
jne 0x53c1b
movq 0x10(%rdx), %rax
cmpq $0x3, %rax
je 0x53cd0
cmpq $0x2, %rax
jne 0x53c1b
movq 0x8(%rsp), %rdi
movq %r12, %rsi
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x53460
movq %r14, %rdi
movq %rdx, %rbx
callq 0xc42a
movsd %xmm0, 0x18(%rsp)
movq %rbx, %rdi
callq 0xc42a
movsd 0x18(%rsp), %xmm2
ucomisd %xmm2, %xmm2
jp 0x53d30
movapd %xmm0, %xmm1
ucomisd %xmm0, %xmm0
jp 0x53e5c
xorpd %xmm0, %xmm0
ucomisd %xmm0, %xmm1
movq 0x10(%rsp), %rdx
jne 0x53c6f
jp 0x53c6f
movq 0xd07fe(%rip), %r14     # 0x124468
jmp 0x53d30
ucomisd %xmm0, %xmm2
jbe 0x53c80
movapd %xmm2, %xmm0
callq 0x8160
jmp 0x53cdd
movq %r14, %rdi
movq %rdx, %rbx
callq 0xc779f
movsd %xmm0, 0x10(%rsp)
movsd %xmm1, 0x18(%rsp)
movq %rbx, %rdi
callq 0xc779f
movapd %xmm0, %xmm2
movapd %xmm1, %xmm3
movsd 0x10(%rsp), %xmm0
movsd 0x18(%rsp), %xmm1
callq 0x81f0
movq 0x8(%rsp), %rdi
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0xc152
movq %r14, %rdi
callq 0xc42a
callq 0x8570
movq 0x8(%rsp), %rdx
movq 0x90(%rdx), %rax
cmpq 0x98(%rdx), %rax
ja 0x53d14
movq 0x8(%rsp), %rdi
movsd %xmm0, 0x10(%rsp)
callq 0x9c27
movsd 0x10(%rsp), %xmm0
movq 0x8(%rsp), %rdx
movq 0x90(%rdx), %rax
leaq -0x8(%rax), %rcx
movq %rcx, 0x90(%rdx)
movq -0x8(%rax), %r14
movq $0xd, (%r14)
movsd %xmm0, 0x8(%r14)
movq %r14, %rax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x90(%rdi), %rax
cmpq 0x98(%rdi), %rax
ja 0x53d68
movq 0x8(%rsp), %rdi
callq 0x9c27
movq 0x8(%rsp), %rdi
movq 0x90(%rdi), %rax
leaq -0x8(%rax), %rcx
movq %rcx, 0x90(%rdi)
movq -0x8(%rax), %r14
movq $0xd, (%r14)
movabsq $-0x4010000000000000, %rax # imm = 0xBFF0000000000000
movq %rax, 0x8(%r14)
jmp 0x53d30
ucomisd %xmm1, %xmm0
seta %al
testq %rsi, %rsi
setg %cl
xorb %al, %cl
je 0x53a8b
movsd 0x7e285(%rip), %xmm1    # 0xd2030
xorpd %xmm0, %xmm0
jmp 0x53cbd
movq 0x18(%rsp), %rdi
movq 0x20(%rsp), %rbx
movq %rbx, %rsi
callq 0xc7aef
movq %rax, %r14
movq %r15, %rdi
movq %rbx, %rsi
callq 0xc7aef
movq 0x8(%rsp), %rdi
movq %r14, %rsi
movq %rax, %rdx
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0xbd87
movq 0x18(%rsp), %rsi
callq 0xc7aef
pushq $0x1
popq %rsi
movq 0x8(%rsp), %rdi
jmp 0x53ddc
movq 0x8(%rsp), %rdx
movq 0x90(%rdx), %rax
cmpq 0x98(%rdx), %rax
ja 0x53e31
movq 0x8(%rsp), %rdi
callq 0x9c27
movq 0x8(%rsp), %rdx
movq 0x90(%rdx), %rax
leaq -0x8(%rax), %rcx
movq %rcx, 0x90(%rdx)
movq -0x8(%rax), %r14
movq $0xb, (%r14)
movq %r15, 0x8(%r14)
jmp 0x53d30
movq 0xc9041(%rip), %r14     # 0x11ce98
jmp 0x53d30
movq 0x10(%rsp), %r14
jmp 0x53d30