#include "def.h"
#include "macro.h"


/* c = c +  s_b * f */
INT mms_null__(OP b, OP c, OP f)
{
    INT erg = OK;
    CTTTTO(INTEGER,HASHTABLE,PARTITION,SCHUR,"mms_null__(1)",b);
    CTTO(SCHUR,HASHTABLE,"mms_null__(2)",c);
    erg += mxx_null__(b,c,f);
    ENDR("mms_null");
}


INT mms_integer_partition_(OP a, OP b, OP c, OP f)
{
    INT erg = OK;
    CTO(INTEGER,"mms_integer_partition_(1)",a);
    CTO(PARTITION,"mms_integer_partition_(2)",b);
    CTTO(SCHUR,HASHTABLE,"mms_integer_partition_(3)",c);
    erg += mps_integer_partition_(a,b,c,f);
    ENDR("mms_integer_partition_");
}


INT mms_integer__(OP a, OP b, OP c, OP f)
{
    INT erg = OK;
    CTO(INTEGER,"mms_integer__(1)",a);
    CTTTO(PARTITION,SCHUR,HASHTABLE,"mms_integer__(2)",b);
    CTTO(SCHUR,HASHTABLE,"mms_integer__(3)",c);

    if (S_I_I(a) == 0)
        erg += mms_null__(b,c,f);
    else if (S_O_K(b) == INTEGER) {
        OP ff;
        ff = CALLOCOBJECT();
        erg += first_partition(b,ff);
        erg += mms_integer_partition_(ff,b,c,f);
        FREEALL(ff);
        }
    else if (S_O_K(b) == PARTITION) {
        erg += mms_integer_partition_(a,b,c,f);
        }
    else /* SCHUR   HASHTABLE */ {
        M_FORALL_MONOMIALS_IN_B(a,b,c,f,mms_integer_partition_);
        }

    ENDR("mms_integer__");
}


INT mms_partition_partition_(OP a, OP b, OP c, OP f)
{
    INT erg = OK;
    CTO(PARTITION,"mms_partition_partition_(1)",a);
    CTTTO(PARTITION,SCHUR,HASHTABLE,"mms_partition_partition_(2)",b);
    CTTO(SCHUR,HASHTABLE,"mms_partition_partition_(3)",c);
    if (S_PA_LI(a) == 0) {
        erg += mms_null__(b,c,f);
        }
    else if  (S_PA_LI(a) == 1) {
        erg += mms_integer_partition_(S_PA_I(a,0),b,c,f);
        }
    else {
        if (S_O_K(c) == HASHTABLE)
            {
            erg += cc_muir_mms_partition_partition_(a,b,c,f);
            }
        else {
            OP d;
            d = CALLOCOBJECT();
            init_hashtable(d);
            erg += cc_muir_mms_partition_partition_(a,b,d,f);
            t_HASHTABLE_SCHUR(d,d);
            insert_list(d,c,add_koeff,comp_monomschur);
            }
        }
    ENDR("mms_partition_partition_");
}


INT mms_partition__(OP a, OP b, OP c, OP f)
{
    INT erg = OK;
    CTO(PARTITION,"mms_partition__(1)",a);
    CTTTO(PARTITION,SCHUR,HASHTABLE,"mms_partition__(2)",b);
    CTTO(SCHUR,HASHTABLE,"mms_partition__(3)",c);
    if (S_O_K(b) == PARTITION)
        erg += mms_partition_partition_(a,b,c,f);
    else {
        M_FORALL_MONOMIALS_IN_B(a,b,c,f,mms_partition_partition_);
        }
    ENDR("mms_partition__");
}


INT mms_hashtable__(OP a, OP b, OP c, OP f)
{
    INT erg = OK;
    CTO(HASHTABLE,"mms_hashtable__(1)",a);
    CTTTO(PARTITION,SCHUR,HASHTABLE,"mms_hashtable__(2)",b);
    CTTO(SCHUR,HASHTABLE,"mms_hashtable__(3)",c);
    M_FORALL_MONOMIALS_IN_A(a,b,c,f,mms_partition__);
    ENDR("mms_hashtable__");
}


INT mms_hashtable_partition_(OP a, OP b, OP c, OP f)
{
    INT erg = OK;
    CTO(HASHTABLE,"mms_hashtable_partition_(1)",a);
    CTO(PARTITION,"mms_hashtable_partition_(2)",b);
    CTTO(SCHUR,HASHTABLE,"mms_hashtable_partition_(3)",c);
    M_FORALL_MONOMIALS_IN_A(a,b,c,f,mms_partition_partition_);
    ENDR("mms_hashtable_partition_");
}


INT mms_monomial__(OP a, OP b, OP c, OP f)
{
    INT erg = OK;
    CTO(MONOMIAL,"mms_monomial__(1)",a);
    CTTTO(PARTITION,SCHUR,HASHTABLE,"mms_monomial__(2)",b);
    CTTO(SCHUR,HASHTABLE,"mms_monomial__(3)",c);
    M_FORALL_MONOMIALS_IN_A(a,b,c,f,mms_partition__);
    ENDR("mms_monomial__");
}


INT mms___(OP a, OP b, OP c, OP f)
{
    INT erg = OK;
    CTTTTO(INTEGER,PARTITION,MONOMIAL,HASHTABLE,"mms___(1)",a);
    CTTTO(PARTITION,SCHUR,HASHTABLE,"mms___(2)",b);
    CTTO(SCHUR,HASHTABLE,"mms___(3)",c);
    if (S_O_K(a) == INTEGER)
        {
        erg += mms_integer__(a,b,c,f);
        goto ende;
        }
    else if (S_O_K(a) == PARTITION)
        {
        erg += mms_partition__(a,b,c,f);
        goto ende;
        }
    else if (S_O_K(a) == HASHTABLE)
        {
        erg += mms_hashtable__(a,b,c,f);
        goto ende;
        }
    else if (S_O_K(a) == MONOMIAL)
        {
        erg += mms_monomial__(a,b,c,f);
        goto ende;
        }
ende:
    ENDR("mms___");
}


INT mult_monomial_schur(OP a, OP b, OP c)
{
    INT erg = OK;
    INT t=0;
    CTTTTO(INTEGER,MONOMIAL,PARTITION,HASHTABLE,"mult_monomial_schur(1)",a);
    CTTTTO(INTEGER,SCHUR,PARTITION,HASHTABLE,"mult_monomial_schur(2)",b);
    CTTTO(EMPTY,SCHUR,HASHTABLE,"mult_monomial_schur(3)",c);

    if (S_O_K(c) == EMPTY) {
        t=1;
        init_hashtable(c);
        }
    erg += mms___(a,b,c,cons_eins);

    if (t==1) erg += t_HASHTABLE_SCHUR(c,c);

    CTTO(SCHUR,HASHTABLE,"mult_monomial_schur(3-ende)",c);
    ENDR("mult_monomial_schur");
}
