#ifndef plethysm_h__
#define plethysm_h__

#include "straighten_core.h"
#include "straighten.h"
#ifdef _STRAIGHTEN_USING_LINUX
#include "lapacke.h"
#else
#include "OpenBLAS/lapacke.h"
//#include "OpenBLAS/cblas.h"
#endif

FORCE_INLINE int sstd_index_order_column_factorial_r(const void *arg1, const void *arg2, void *arg) {
    uint32_t lhs = ((uint32_t *)arg1)[0];
    uint32_t rhs = ((uint32_t *)arg2)[0];
    uint64_t * sstd_column_factorial = (uint64_t*)arg;
    
    return (sstd_column_factorial[lhs] < sstd_column_factorial[rhs]) - (sstd_column_factorial[lhs] > sstd_column_factorial[rhs]);
}

FORCE_INLINE int sstd_index_order_column_factorial_s(void *arg, const void *arg1, const void *arg2) {
    uint32_t lhs = ((uint32_t *)arg1)[0];
    uint32_t rhs = ((uint32_t *)arg2)[0];
    uint64_t * sstd_column_factorial = (uint64_t*)arg;
    
    return (sstd_column_factorial[lhs] < sstd_column_factorial[rhs]) - (sstd_column_factorial[lhs] > sstd_column_factorial[rhs]);
}

uint32_t load_foulkes(uint32_t outer, uint32_t inner, uint32_t ** partitions, uint32_t ** plethysms);

void isotypic_to_string_full(char * str, uint32_t * shape, uint32_t shape_length, uint32_t dimension, struct tableau * isotypic_basis, struct shape_data_c * s_data);

void store_isotypic_full(uint32_t outer, uint32_t inner, struct shape_data_c * s_data, uint32_t dimension, struct tableau * isotypic_basis);

void store_isotypic(uint32_t outer, uint32_t inner, struct shape_data_c * s_data, uint32_t dimension, uint32_t optimal_sstd_lower_bound, uint32_t * isotypic_basis_index);

int32_t load_isotypic(uint32_t outer, uint32_t inner, struct shape_data_c * s_data, uint32_t * dimension, uint32_t * optimal_sstd_lower_bound, uint32_t ** isotypic_basis_index);

void construct_isotypic_basis_all(uint32_t outer, uint32_t inner, int use_lower_bound);

uint32_t construct_isotypic_basis(struct sstd_data_c * sstd_data, struct shape_data_c * s_data, uint32_t dimension, uint32_t * optimal_rcoeff_sstd_index, uint32_t * isotypic_basis_index);

uint32_t construct_isotypic_basis_investigate(struct sstd_data_c * sstd_data, struct shape_data_c * s_data, uint32_t dimension, uint32_t * optimal_rcoeff_sstd_index, uint32_t * isotypic_basis_index);

void load_check_isotypic_basis(struct sstd_data_c * sstd_data, struct shape_data_c * s_data, int dimension, uint32_t * isotypic_basis_index, int64_t * isotypic_basis);

void barreis_gauss_elim_mpz_inplace(mpz_t* g_elim, int g_rows, int g_cols);

#endif  //plethysm_h__