/*
 * Eligis Confidential
 *
 * (c) Copyright Eligis. 1988-2022
 * The source code for this program is not published or otherwise
 * divested of its trade secrets.
 */

/**
 * @file fib20.c.
 * @brief OpenLisp compiled code generated on 2022/12/13.
 * from 'fib20.lsp'. DO NOT EDIT!!
 * @version 11.7.0
 * @author C. Jullien
 * @copyright Eligis, 1988-2022
 */

/*
 * WARNING! This generated code is neither GPL nor LGPL.
 * It requires a commercial license to be used.
 */

#include "openlisp.h"
#include "module.h"
#include "cbackend.h"
#include "lap.h"
#include "fib20.h"

#if defined(__GNUC__)
#if (__GNUC__ > 4)                                \
    || ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) \
    || defined(__clang__)
#pragma GCC diagnostic ignored "-Wunused-but-set-variable"
#pragma GCC diagnostic ignored "-Wclobbered"
#endif /* GCC >= 4.6 */
#endif /* __GNUC__ */

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
#pragma warning(disable : 4702) /* unreachable code  */
#pragma warning(disable : 6011) /* Dereferencing NULL */
#pragma auto_inline(on)
#endif /* _MSC_VER */

#if defined(__POCC__)
#pragma warn(disable : 1814) /* Local never used     */
#pragma warn(disable : 2115) /* Init. but never used */
#pragma warn(disable : 2128) /* reference removed    */
#endif /* __POCC__ */

/**
 * olfib_00 [SUBR1].
 * Corresponds to 'fib' lisp code.
 * @return object
 */
static POINTER 
OLDEFCOMPILED1(olfib_00, p1) {
        POINTER a1;
        POINTER VOLATILE a2;

        ollapenter(SN_OLFIB_00);
        a1 = p1;
        if (eq(a1, olmakefix(1))) goto _l004;
        if (!eq(a1, olmakefix(2))) goto _l003;
        ollapleave(SN_OLFIB_00);
        return olmakefix(1);
_l003:
        a1 = ollapgsub1(a1);
        a2 = olfib_00(a1);
        a1 = ollapgsub(p1, olmakefix(2));
        a1 = olfib_00(a1);
        a1 = ollapgadd(a2, a1);
_l004:
        ollapleave(SN_OLFIB_00);
        return a1;
}

/**
 * olGF_gfib_i_01 [SUBR1].
 * Corresponds to 'ilos::GF$gfib$i' lisp code.
 * @return object
 */
static POINTER 
OLDEFCOMPILED1(olGF_gfib_i_01, p1) {
        POINTER a1;
        POINTER VOLATILE a2;

        ollapenter(SN_OLGF_GFIB_I_01);
        a1 = p1;
        if (eq(a1, olmakefix(1))) goto _l004;
        if (!eq(a1, olmakefix(2))) goto _l003;
        ollapleave(SN_OLGF_GFIB_I_01);
        return olmakefix(1);
_l003:
        a1 = ollapsub(a1, olmakefix(1));
        olpush(symbfn(oldata003));
        olpush(a1);
        a2 = olcallgeneric(2);
        oladjstk(2);
        a1 = ollapsub(p1, olmakefix(2));
        olpush(symbfn(oldata003));
        olpush(a1);
        a1 = olcallgeneric(2);
        oladjstk(2);
        a1 = ollapgadd(a2, a1);
_l004:
        ollapleave(SN_OLGF_GFIB_I_01);
        return a1;
}

/**
 * olmatrix___02 [SUBR2].
 * Corresponds to 'matrix-*' lisp code.
 * @return object
 */
static POINTER 
OLDEFCOMPILED2(olmatrix___02, p1, p2) {
        POINTER a1;
        POINTER VOLATILE a2;
        POINTER VOLATILE a3;

        ollapenter(SN_OLMATRIX___02);
        a2 = ollapelti(p1, 0);
        a1 = ollapelti(p2, 0);
        a2 = ollapgmul(a2, a1);
        a3 = ollapelti(p1, 1);
        a1 = ollapelti(p2, 2);
        a1 = ollapgmul(a3, a1);
        a1 = ollapgadd(a2, a1);
        olpush(a1);
        a2 = ollapelti(p1, 0);
        a1 = ollapelti(p2, 1);
        a2 = ollapgmul(a2, a1);
        a3 = ollapelti(p1, 1);
        a1 = ollapelti(p2, 3);
        a1 = ollapgmul(a3, a1);
        a1 = ollapgadd(a2, a1);
        olpush(a1);
        a2 = ollapelti(p1, 2);
        a1 = ollapelti(p2, 0);
        a2 = ollapgmul(a2, a1);
        a3 = ollapelti(p1, 3);
        a1 = ollapelti(p2, 2);
        a1 = ollapgmul(a3, a1);
        a1 = ollapgadd(a2, a1);
        olpush(a1);
        a2 = ollapelti(p1, 2);
        a1 = ollapelti(p2, 1);
        a2 = ollapgmul(a2, a1);
        a3 = ollapelti(p1, 3);
        a1 = ollapelti(p2, 3);
        a1 = ollapgmul(a3, a1);
        a1 = ollapgadd(a2, a1);
        olpush(a1);
        a1 = olvector(4);
        oladjstk(4);
        ollapleave(SN_OLMATRIX___02);
        return a1;
}

/**
 * olmatrix_power_03 [SUBR2].
 * Corresponds to 'matrix-power' lisp code.
 * @return object
 */
static POINTER 
OLDEFCOMPILED2(olmatrix_power_03, p1, p2) {
        POINTER a1;
        POINTER VOLATILE a2;
        POINTER VOLATILE a3;
        POINTER * CONST OLRESTRICT top = olfstack;

        ollapenter(SN_OLMATRIX_POWER_03);
_tailrec:
        a1 = p2;
        if (!eq(a1, olmakefix(0))) goto _l001;
        ollapleave(SN_OLMATRIX_POWER_03);
        return oldata008;
_l001:
        if (!eq(a1, olmakefix(1))) goto _l003;
        ollapleave(SN_OLMATRIX_POWER_03);
        return p1;
_l003:
        a1 = olmod(a1, olmakefix(2));
        if (!eq(a1, olmakefix(0))) goto _l005;
        a2 = p1;
        a1 = olmatrix___02(a2, p1);
        olpush(a1);
        a1 = oldiv(p2, olmakefix(2));
        olpush(a1);
        /* recurse with 2 arguments on stack */
        p2 = *(olfstack + 0);
        p1 = *(olfstack + 1);
        olfstack = top;
        goto _tailrec;
_l005:
        a2 = p1;
        a3 = p1;
        a1 = olmatrix___02(a3, p1);
        olpush(a1);
        a1 = ollapgsub1(p2);
        a1 = oldiv(a1, olmakefix(2));
        a1 = olmatrix_power_03(olxspmov(0), a1);
        oladjstk(1);
        a1 = olmatrix___02(a2, a1);
        ollapleave(SN_OLMATRIX_POWER_03);
        return a1;
}

/**
 * olfibm_04 [SUBR1].
 * Corresponds to 'fibm' lisp code.
 * @return object
 */
OLINLINE static POINTER 
OLDEFCOMPILED1(olfibm_04, p1) {
        POINTER a1;
        POINTER VOLATILE a2;

        ollapenter(SN_OLFIBM_04);
        a1 = ollapglt(p1, olmakefix(2));
        if (null(a1)) goto _l001;
        ollapleave(SN_OLFIBM_04);
        return olmakefix(1);
_l001:
        a2 = cval(oldata010);
        a1 = ollapgsub1(p1);
        a1 = olmatrix_power_03(a2, a1);
        a1 = ollapelti(a1, 0);
        ollapleave(SN_OLFIBM_04);
        return a1;
}

#if defined(_MSC_VER) && (_MSC_VER >= 1200)
#pragma warning(disable : 4125) /* octal char followed by number   */
#pragma warning(disable : 4566) /* for UNICODE characters          */
#pragma warning(disable : 4428) /* for UNICODE characters          */
#pragma warning(disable : 4343) /* disable warning for next pragma */
#pragma optimize("gs", off)     /* don't optimize init routine     */
#endif /* _MSC_VER */

OLEXPORT void
OLDEFCOMPILEDN(olfib20init, initflag) {
        POINTER VOLATILE a1 = NULLPTR;
        POINTER VOLATILE a2 = NULLPTR;

        if (initflag == 0) {
                return;
        }

        olentermodule(LCSTR("fib20.c"), 11.7);
        (void)olidentity(a1);
        (void)olidentity(a2);

#if defined(OLLAPTIMETRACE)
        ollapttinit(SN_OLFIBM_04);
        ollapttinit(SN_OLFIB_00);
        ollapttinit(SN_OLGF_GFIB_I_01);
        ollapttinit(SN_OLMATRIX_POWER_03);
        ollapttinit(SN_OLMATRIX___02);
#endif /* OLLAPTIMETRACE */

        (void)olfentry((PFUN)olfib_00, SUBR1, SN_OLFIB_00);
        olpush(olsymbdefgeneric);
        olpush(olusersymbol(LCSTR("gfib")));
        a1 = olcons(olusersymbol(LCSTR("n")), nil);
        olpush(a1);
        a1 = ollist(3);
        oladjstk(3);
        (void)olevalenv(a1, OLNULLENV);
        (void)olfentry((PFUN)olGF_gfib_i_01, SUBR1, SN_OLGF_GFIB_I_01);
        oldata003 = olusersymbol(LCSTR("gfib"));
        oladdcplist(oldata003);
        olpush(olsymbdefmethod);
        olpush(oldata003);
        a1 = olcons(olusersymbol(LCSTR("<integer>")), nil);
        a1 = olcons(olusersymbol(LCSTR("n")), a1);
        a1 = olcons(a1, nil);
        olpush(a1);
        a1 = ollist(3);
        oladjstk(3);
        olpush(a1);
        olpush(olusersymbol(LCSTR("ilos::GF$gfib$i")));
        a1 = olnconc(2);
        oladjstk(2);
        (void)olevalenv(a1, OLNULLENV);
        a1 = olevalbuffer(LCSTR("#(1 1 1 0)"));
        a2 = olusersymbol(LCSTR("matrix"));
        cval(a2) = a1;
        (void)olfentry((PFUN)olmatrix___02, SUBR2, SN_OLMATRIX___02);
        (void)olfentry((PFUN)olmatrix_power_03, SUBR2, SN_OLMATRIX_POWER_03);
        oldata008 = olevalbuffer(LCSTR("#(1 0 0 1)"));
        oladdcplist(oldata008);
        (void)olfentry((PFUN)olfibm_04, SUBR1, SN_OLFIBM_04);
        oldata010 = olusersymbol(LCSTR("matrix"));

        olleavemodule();
}