text:
# This reads in the load-time MPI constants. They were declared
# earlier with dummy values in the file
# `define_load_time_mpi_constants.jl`.

function read_load_time_mpi_constants()

if !Sys.iswindows()

    Consts.MPI_ANY_SOURCE[] = unsafe_load(cglobal((:MPICONSTANTS_ANY_SOURCE, libmpiconstants), Cint))
    Consts.MPI_ANY_TAG[] = unsafe_load(cglobal((:MPICONSTANTS_ANY_TAG, libmpiconstants), Cint))
    Consts.MPI_PROC_NULL[] = unsafe_load(cglobal((:MPICONSTANTS_PROC_NULL, libmpiconstants), Cint))
    Consts.MPI_ROOT[] = unsafe_load(cglobal((:MPICONSTANTS_ROOT, libmpiconstants), Cint))
    Consts.MPI_CART[] = unsafe_load(cglobal((:MPICONSTANTS_CART, libmpiconstants), Cint))
    Consts.MPI_DIST_GRAPH[] = unsafe_load(cglobal((:MPICONSTANTS_DIST_GRAPH, libmpiconstants), Cint))
    Consts.MPI_GRAPH[] = unsafe_load(cglobal((:MPICONSTANTS_GRAPH, libmpiconstants), Cint))
    Consts.MPI_CONGRUENT[] = unsafe_load(cglobal((:MPICONSTANTS_CONGRUENT, libmpiconstants), Cint))
    Consts.MPI_IDENT[] = unsafe_load(cglobal((:MPICONSTANTS_IDENT, libmpiconstants), Cint))
    Consts.MPI_SIMILAR[] = unsafe_load(cglobal((:MPICONSTANTS_SIMILAR, libmpiconstants), Cint))
    Consts.MPI_UNEQUAL[] = unsafe_load(cglobal((:MPICONSTANTS_UNEQUAL, libmpiconstants), Cint))
    Consts.MPI_KEYVAL_INVALID[] = unsafe_load(cglobal((:MPICONSTANTS_KEYVAL_INVALID, libmpiconstants), Cint))
    Consts.MPI_UNDEFINED[] = unsafe_load(cglobal((:MPICONSTANTS_UNDEFINED, libmpiconstants), Cint))
    Consts.MPI_APPNUM[] = unsafe_load(cglobal((:MPICONSTANTS_APPNUM, libmpiconstants), Cint))
    Consts.MPI_HOST[] = unsafe_load(cglobal((:MPICONSTANTS_HOST, libmpiconstants), Cint))
    Consts.MPI_IO[] = unsafe_load(cglobal((:MPICONSTANTS_IO, libmpiconstants), Cint))
    Consts.MPI_LASTUSEDCODE[] = unsafe_load(cglobal((:MPICONSTANTS_LASTUSEDCODE, libmpiconstants), Cint))
    Consts.MPI_TAG_UB[] = unsafe_load(cglobal((:MPICONSTANTS_TAG_UB, libmpiconstants), Cint))
    Consts.MPI_UNIVERSE_SIZE[] = unsafe_load(cglobal((:MPICONSTANTS_UNIVERSE_SIZE, libmpiconstants), Cint))
    Consts.MPI_WIN_BASE[] = unsafe_load(cglobal((:MPICONSTANTS_WIN_BASE, libmpiconstants), Cint))
    Consts.MPI_WIN_CREATE_FLAVOR[] = unsafe_load(cglobal((:MPICONSTANTS_WIN_CREATE_FLAVOR, libmpiconstants), Cint))
    Consts.MPI_WIN_DISP_UNIT[] = unsafe_load(cglobal((:MPICONSTANTS_WIN_DISP_UNIT, libmpiconstants), Cint))
    Consts.MPI_WIN_MODEL[] = unsafe_load(cglobal((:MPICONSTANTS_WIN_MODEL, libmpiconstants), Cint))
    Consts.MPI_WIN_SIZE[] = unsafe_load(cglobal((:MPICONSTANTS_WIN_SIZE, libmpiconstants), Cint))
    Consts.MPI_WTIME_IS_GLOBAL[] = unsafe_load(cglobal((:MPICONSTANTS_WTIME_IS_GLOBAL, libmpiconstants), Cint))
    Consts.MPI_COMBINER_CONTIGUOUS[] = unsafe_load(cglobal((:MPICONSTANTS_COMBINER_CONTIGUOUS, libmpiconstants), Cint))
    Consts.MPI_COMBINER_DARRAY[] = unsafe_load(cglobal((:MPICONSTANTS_COMBINER_DARRAY, libmpiconstants), Cint))
    Consts.MPI_COMBINER_DUP[] = unsafe_load(cglobal((:MPICONSTANTS_COMBINER_DUP, libmpiconstants), Cint))
    Consts.MPI_COMBINER_F90_COMPLEX[] = unsafe_load(cglobal((:MPICONSTANTS_COMBINER_F90_COMPLEX, libmpiconstants), Cint))
    Consts.MPI_COMBINER_F90_INTEGER[] = unsafe_load(cglobal((:MPICONSTANTS_COMBINER_F90_INTEGER, libmpiconstants), Cint))
    Consts.MPI_COMBINER_F90_REAL[] = unsafe_load(cglobal((:MPICONSTANTS_COMBINER_F90_REAL, libmpiconstants), Cint))
    Consts.MPI_COMBINER_HINDEXED[] = unsafe_load(cglobal((:MPICONSTANTS_COMBINER_HINDEXED, libmpiconstants), Cint))
    Consts.MPI_COMBINER_HINDEXED_BLOCK[] = unsafe_load(cglobal((:MPICONSTANTS_COMBINER_HINDEXED_BLOCK, libmpiconstants), Cint))
    Consts.MPI_COMBINER_HVECTOR[] = unsafe_load(cglobal((:MPICONSTANTS_COMBINER_HVECTOR, libmpiconstants), Cint))
    Consts.MPI_COMBINER_INDEXED[] = unsafe_load(cglobal((:MPICONSTANTS_COMBINER_INDEXED, libmpiconstants), Cint))
    Consts.MPI_COMBINER_INDEXED_BLOCK[] = unsafe_load(cglobal((:MPICONSTANTS_COMBINER_INDEXED_BLOCK, libmpiconstants), Cint))
    Consts.MPI_COMBINER_NAMED[] = unsafe_load(cglobal((:MPICONSTANTS_COMBINER_NAMED, libmpiconstants), Cint))
    Consts.MPI_COMBINER_RESIZED[] = unsafe_load(cglobal((:MPICONSTANTS_COMBINER_RESIZED, libmpiconstants), Cint))
    Consts.MPI_COMBINER_STRUCT[] = unsafe_load(cglobal((:MPICONSTANTS_COMBINER_STRUCT, libmpiconstants), Cint))
    Consts.MPI_COMBINER_SUBARRAY[] = unsafe_load(cglobal((:MPICONSTANTS_COMBINER_SUBARRAY, libmpiconstants), Cint))
    Consts.MPI_COMBINER_VECTOR[] = unsafe_load(cglobal((:MPICONSTANTS_COMBINER_VECTOR, libmpiconstants), Cint))
    Consts.MPI_COMM_TYPE_SHARED[] = unsafe_load(cglobal((:MPICONSTANTS_COMM_TYPE_SHARED, libmpiconstants), Cint))
    Consts.MPI_DISTRIBUTE_BLOCK[] = unsafe_load(cglobal((:MPICONSTANTS_DISTRIBUTE_BLOCK, libmpiconstants), Cint))
    Consts.MPI_DISTRIBUTE_CYCLIC[] = unsafe_load(cglobal((:MPICONSTANTS_DISTRIBUTE_CYCLIC, libmpiconstants), Cint))
    Consts.MPI_DISTRIBUTE_NONE[] = unsafe_load(cglobal((:MPICONSTANTS_DISTRIBUTE_NONE, libmpiconstants), Cint))
    Consts.MPI_ERR_ACCESS[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_ACCESS, libmpiconstants), Cint))
    Consts.MPI_ERR_AMODE[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_AMODE, libmpiconstants), Cint))
    Consts.MPI_ERR_ARG[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_ARG, libmpiconstants), Cint))
    Consts.MPI_ERR_ASSERT[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_ASSERT, libmpiconstants), Cint))
    Consts.MPI_ERR_BAD_FILE[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_BAD_FILE, libmpiconstants), Cint))
    Consts.MPI_ERR_BASE[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_BASE, libmpiconstants), Cint))
    Consts.MPI_ERR_BUFFER[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_BUFFER, libmpiconstants), Cint))
    Consts.MPI_ERR_COMM[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_COMM, libmpiconstants), Cint))
    Consts.MPI_ERR_CONVERSION[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_CONVERSION, libmpiconstants), Cint))
    Consts.MPI_ERR_COUNT[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_COUNT, libmpiconstants), Cint))
    Consts.MPI_ERR_DIMS[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_DIMS, libmpiconstants), Cint))
    Consts.MPI_ERR_DISP[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_DISP, libmpiconstants), Cint))
    Consts.MPI_ERR_DUP_DATAREP[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_DUP_DATAREP, libmpiconstants), Cint))
    Consts.MPI_ERR_FILE[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_FILE, libmpiconstants), Cint))
    Consts.MPI_ERR_FILE_EXISTS[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_FILE_EXISTS, libmpiconstants), Cint))
    Consts.MPI_ERR_FILE_IN_USE[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_FILE_IN_USE, libmpiconstants), Cint))
    Consts.MPI_ERR_GROUP[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_GROUP, libmpiconstants), Cint))
    Consts.MPI_ERR_INFO[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_INFO, libmpiconstants), Cint))
    Consts.MPI_ERR_INFO_KEY[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_INFO_KEY, libmpiconstants), Cint))
    Consts.MPI_ERR_INFO_NOKEY[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_INFO_NOKEY, libmpiconstants), Cint))
    Consts.MPI_ERR_INFO_VALUE[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_INFO_VALUE, libmpiconstants), Cint))
    Consts.MPI_ERR_INTERN[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_INTERN, libmpiconstants), Cint))
    Consts.MPI_ERR_IN_STATUS[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_IN_STATUS, libmpiconstants), Cint))
    Consts.MPI_ERR_IO[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_IO, libmpiconstants), Cint))
    Consts.MPI_ERR_KEYVAL[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_KEYVAL, libmpiconstants), Cint))
    Consts.MPI_ERR_LASTCODE[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_LASTCODE, libmpiconstants), Cint))
    Consts.MPI_ERR_LOCKTYPE[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_LOCKTYPE, libmpiconstants), Cint))
    Consts.MPI_ERR_NAME[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_NAME, libmpiconstants), Cint))
    Consts.MPI_ERR_NOT_SAME[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_NOT_SAME, libmpiconstants), Cint))
    Consts.MPI_ERR_NO_MEM[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_NO_MEM, libmpiconstants), Cint))
    Consts.MPI_ERR_NO_SPACE[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_NO_SPACE, libmpiconstants), Cint))
    Consts.MPI_ERR_NO_SUCH_FILE[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_NO_SUCH_FILE, libmpiconstants), Cint))
    Consts.MPI_ERR_OP[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_OP, libmpiconstants), Cint))
    Consts.MPI_ERR_OTHER[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_OTHER, libmpiconstants), Cint))
    Consts.MPI_ERR_PENDING[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_PENDING, libmpiconstants), Cint))
    Consts.MPI_ERR_PORT[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_PORT, libmpiconstants), Cint))
    Consts.MPI_ERR_QUOTA[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_QUOTA, libmpiconstants), Cint))
    Consts.MPI_ERR_RANK[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_RANK, libmpiconstants), Cint))
    Consts.MPI_ERR_READ_ONLY[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_READ_ONLY, libmpiconstants), Cint))
    Consts.MPI_ERR_REQUEST[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_REQUEST, libmpiconstants), Cint))
    Consts.MPI_ERR_RMA_ATTACH[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_RMA_ATTACH, libmpiconstants), Cint))
    Consts.MPI_ERR_RMA_CONFLICT[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_RMA_CONFLICT, libmpiconstants), Cint))
    Consts.MPI_ERR_RMA_FLAVOR[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_RMA_FLAVOR, libmpiconstants), Cint))
    Consts.MPI_ERR_RMA_RANGE[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_RMA_RANGE, libmpiconstants), Cint))
    Consts.MPI_ERR_RMA_SHARED[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_RMA_SHARED, libmpiconstants), Cint))
    Consts.MPI_ERR_RMA_SYNC[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_RMA_SYNC, libmpiconstants), Cint))
    Consts.MPI_ERR_ROOT[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_ROOT, libmpiconstants), Cint))
    Consts.MPI_ERR_SERVICE[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_SERVICE, libmpiconstants), Cint))
    Consts.MPI_ERR_SIZE[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_SIZE, libmpiconstants), Cint))
    Consts.MPI_ERR_SPAWN[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_SPAWN, libmpiconstants), Cint))
    Consts.MPI_ERR_TAG[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_TAG, libmpiconstants), Cint))
    Consts.MPI_ERR_TOPOLOGY[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_TOPOLOGY, libmpiconstants), Cint))
    Consts.MPI_ERR_TRUNCATE[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_TRUNCATE, libmpiconstants), Cint))
    Consts.MPI_ERR_TYPE[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_TYPE, libmpiconstants), Cint))
    Consts.MPI_ERR_UNKNOWN[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_UNKNOWN, libmpiconstants), Cint))
    Consts.MPI_ERR_UNSUPPORTED_DATAREP[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_UNSUPPORTED_DATAREP, libmpiconstants), Cint))
    Consts.MPI_ERR_UNSUPPORTED_OPERATION[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_UNSUPPORTED_OPERATION, libmpiconstants), Cint))
    Consts.MPI_ERR_WIN[] = unsafe_load(cglobal((:MPICONSTANTS_ERR_WIN, libmpiconstants), Cint))
    # We special-case MPI_SUCCESS which is required to be 0
    # Consts.MPI_SUCCESS[] = unsafe_load(cglobal((:MPICONSTANTS_SUCCESS, libmpiconstants), Cint))
    @assert unsafe_load(cglobal((:MPICONSTANTS_SUCCESS, libmpiconstants), Cint)) == Consts.MPI_SUCCESS[]
    Consts.MPI_LOCK_EXCLUSIVE[] = unsafe_load(cglobal((:MPICONSTANTS_LOCK_EXCLUSIVE, libmpiconstants), Cint))
    Consts.MPI_LOCK_SHARED[] = unsafe_load(cglobal((:MPICONSTANTS_LOCK_SHARED, libmpiconstants), Cint))
    Consts.MPI_MODE_APPEND[] = unsafe_load(cglobal((:MPICONSTANTS_MODE_APPEND, libmpiconstants), Cint))
    Consts.MPI_MODE_CREATE[] = unsafe_load(cglobal((:MPICONSTANTS_MODE_CREATE, libmpiconstants), Cint))
    Consts.MPI_MODE_DELETE_ON_CLOSE[] = unsafe_load(cglobal((:MPICONSTANTS_MODE_DELETE_ON_CLOSE, libmpiconstants), Cint))
    Consts.MPI_MODE_EXCL[] = unsafe_load(cglobal((:MPICONSTANTS_MODE_EXCL, libmpiconstants), Cint))
    Consts.MPI_MODE_NOCHECK[] = unsafe_load(cglobal((:MPICONSTANTS_MODE_NOCHECK, libmpiconstants), Cint))
    Consts.MPI_MODE_NOPRECEDE[] = unsafe_load(cglobal((:MPICONSTANTS_MODE_NOPRECEDE, libmpiconstants), Cint))
    Consts.MPI_MODE_NOPUT[] = unsafe_load(cglobal((:MPICONSTANTS_MODE_NOPUT, libmpiconstants), Cint))
    Consts.MPI_MODE_NOSTORE[] = unsafe_load(cglobal((:MPICONSTANTS_MODE_NOSTORE, libmpiconstants), Cint))
    Consts.MPI_MODE_NOSUCCEED[] = unsafe_load(cglobal((:MPICONSTANTS_MODE_NOSUCCEED, libmpiconstants), Cint))
    Consts.MPI_MODE_RDONLY[] = unsafe_load(cglobal((:MPICONSTANTS_MODE_RDONLY, libmpiconstants), Cint))
    Consts.MPI_MODE_RDWR[] = unsafe_load(cglobal((:MPICONSTANTS_MODE_RDWR, libmpiconstants), Cint))
    Consts.MPI_MODE_SEQUENTIAL[] = unsafe_load(cglobal((:MPICONSTANTS_MODE_SEQUENTIAL, libmpiconstants), Cint))
    Consts.MPI_MODE_UNIQUE_OPEN[] = unsafe_load(cglobal((:MPICONSTANTS_MODE_UNIQUE_OPEN, libmpiconstants), Cint))
    Consts.MPI_MODE_WRONLY[] = unsafe_load(cglobal((:MPICONSTANTS_MODE_WRONLY, libmpiconstants), Cint))
    Consts.MPI_ORDER_C[] = unsafe_load(cglobal((:MPICONSTANTS_ORDER_C, libmpiconstants), Cint))
    Consts.MPI_ORDER_FORTRAN[] = unsafe_load(cglobal((:MPICONSTANTS_ORDER_FORTRAN, libmpiconstants), Cint))
    Consts.MPI_SEEK_CUR[] = unsafe_load(cglobal((:MPICONSTANTS_SEEK_CUR, libmpiconstants), Cint))
    Consts.MPI_SEEK_END[] = unsafe_load(cglobal((:MPICONSTANTS_SEEK_END, libmpiconstants), Cint))
    Consts.MPI_SEEK_SET[] = unsafe_load(cglobal((:MPICONSTANTS_SEEK_SET, libmpiconstants), Cint))
    Consts.MPI_THREAD_SINGLE[] = unsafe_load(cglobal((:MPICONSTANTS_THREAD_SINGLE, libmpiconstants), Cint))
    Consts.MPI_THREAD_FUNNELED[] = unsafe_load(cglobal((:MPICONSTANTS_THREAD_FUNNELED, libmpiconstants), Cint))
    Consts.MPI_THREAD_SERIALIZED[] = unsafe_load(cglobal((:MPICONSTANTS_THREAD_SERIALIZED, libmpiconstants), Cint))
    Consts.MPI_THREAD_MULTIPLE[] = unsafe_load(cglobal((:MPICONSTANTS_THREAD_MULTIPLE, libmpiconstants), Cint))
    Consts.MPI_TYPECLASS_COMPLEX[] = unsafe_load(cglobal((:MPICONSTANTS_TYPECLASS_COMPLEX, libmpiconstants), Cint))
    Consts.MPI_TYPECLASS_INTEGER[] = unsafe_load(cglobal((:MPICONSTANTS_TYPECLASS_INTEGER, libmpiconstants), Cint))
    Consts.MPI_TYPECLASS_REAL[] = unsafe_load(cglobal((:MPICONSTANTS_TYPECLASS_REAL, libmpiconstants), Cint))

    Consts.MPI_ARGV_NULL[] = unsafe_load(cglobal((:MPICONSTANTS_ARGV_NULL, libmpiconstants), Ptr{Ptr{Cchar}}))
    Consts.MPI_ARGVS_NULL[] = unsafe_load(cglobal((:MPICONSTANTS_ARGVS_NULL, libmpiconstants), Ptr{Ptr{Ptr{Cchar}}}))
    # MPI_UNWEIGHTED[] = unsafe_load(cglobal((:MPICONSTANTS_UNWEIGHTED, libmpiconstants), Ptr{Cint}))
    # MPI_WEIGHTS_EMPTY[] = unsafe_load(cglobal((:MPICONSTANTS_WEIGHTS_EMPTY, libmpiconstants), Ptr{Cint}))
    Consts.MPI_BOTTOM[] = unsafe_load(cglobal((:MPICONSTANTS_BOTTOM, libmpiconstants), Ptr{Cvoid}))
    Consts.MPI_IN_PLACE[] = unsafe_load(cglobal((:MPICONSTANTS_IN_PLACE, libmpiconstants), Ptr{Cvoid}))

    Consts.MPI_COMM_NULL[] = unsafe_load(cglobal((:MPICONSTANTS_COMM_NULL , libmpiconstants), MPI_Comm))
    Consts.MPI_COMM_SELF[] = unsafe_load(cglobal((:MPICONSTANTS_COMM_SELF , libmpiconstants), MPI_Comm))
    Consts.MPI_COMM_WORLD[] = unsafe_load(cglobal((:MPICONSTANTS_COMM_WORLD, libmpiconstants), MPI_Comm))

    Consts.MPI_COMM_DUP_FN[] = unsafe_load(cglobal((:MPICONSTANTS_COMM_DUP_FN, libmpiconstants), MPI_Comm_copy_attr_function))

    Consts.MPI_COMM_NULL_COPY_FN[] = unsafe_load(cglobal((:MPICONSTANTS_COMM_NULL_COPY_FN, libmpiconstants), MPI_Comm_copy_attr_function))

    Consts.MPI_COMM_NULL_DELETE_FN[] = unsafe_load(cglobal((:MPICONSTANTS_COMM_NULL_DELETE_FN, libmpiconstants), MPI_Comm_delete_attr_function))

    Consts.MPI_NULL_COPY_FN[] = unsafe_load(cglobal((:MPICONSTANTS_NULL_COPY_FN, libmpiconstants), MPI_Copy_function))

    Consts.MPI_2DOUBLE_PRECISION[] = unsafe_load(cglobal((:MPICONSTANTS_2DOUBLE_PRECISION, libmpiconstants), MPI_Datatype))
    Consts.MPI_2INT[] = unsafe_load(cglobal((:MPICONSTANTS_2INT, libmpiconstants), MPI_Datatype))
    Consts.MPI_2INTEGER[] = unsafe_load(cglobal((:MPICONSTANTS_2INTEGER, libmpiconstants), MPI_Datatype))
    Consts.MPI_2REAL[] = unsafe_load(cglobal((:MPICONSTANTS_2REAL, libmpiconstants), MPI_Datatype))
    Consts.MPI_AINT[] = unsafe_load(cglobal((:MPICONSTANTS_AINT, libmpiconstants), MPI_Datatype))
    Consts.MPI_BYTE[] = unsafe_load(cglobal((:MPICONSTANTS_BYTE, libmpiconstants), MPI_Datatype))
    Consts.MPI_CHAR[] = unsafe_load(cglobal((:MPICONSTANTS_CHAR, libmpiconstants), MPI_Datatype))
    Consts.MPI_CHARACTER[] = unsafe_load(cglobal((:MPICONSTANTS_CHARACTER, libmpiconstants), MPI_Datatype))
    Consts.MPI_COMPLEX[] = unsafe_load(cglobal((:MPICONSTANTS_COMPLEX, libmpiconstants), MPI_Datatype))
    Consts.MPI_COMPLEX16[] = unsafe_load(cglobal((:MPICONSTANTS_COMPLEX16, libmpiconstants), MPI_Datatype))
    # MPI_COMPLEX32[] = unsafe_load(cglobal((:MPICONSTANTS_COMPLEX32, libmpiconstants), MPI_Datatype))
    Consts.MPI_COMPLEX8[] = unsafe_load(cglobal((:MPICONSTANTS_COMPLEX8, libmpiconstants), MPI_Datatype))
    Consts.MPI_COUNT[] = unsafe_load(cglobal((:MPICONSTANTS_COUNT, libmpiconstants), MPI_Datatype))
    Consts.MPI_CXX_BOOL[] = unsafe_load(cglobal((:MPICONSTANTS_CXX_BOOL, libmpiconstants), MPI_Datatype))
    Consts.MPI_CXX_DOUBLE_COMPLEX[] = unsafe_load(cglobal((:MPICONSTANTS_CXX_DOUBLE_COMPLEX, libmpiconstants), MPI_Datatype))
    Consts.MPI_CXX_FLOAT_COMPLEX[] = unsafe_load(cglobal((:MPICONSTANTS_CXX_FLOAT_COMPLEX, libmpiconstants), MPI_Datatype))
    Consts.MPI_CXX_LONG_DOUBLE_COMPLEX[] = unsafe_load(cglobal((:MPICONSTANTS_CXX_LONG_DOUBLE_COMPLEX, libmpiconstants), MPI_Datatype))
    Consts.MPI_C_BOOL[] = unsafe_load(cglobal((:MPICONSTANTS_C_BOOL, libmpiconstants), MPI_Datatype))
    Consts.MPI_C_COMPLEX[] = unsafe_load(cglobal((:MPICONSTANTS_C_COMPLEX, libmpiconstants), MPI_Datatype))
    Consts.MPI_C_DOUBLE_COMPLEX[] = unsafe_load(cglobal((:MPICONSTANTS_C_DOUBLE_COMPLEX, libmpiconstants), MPI_Datatype))
    Consts.MPI_C_FLOAT_COMPLEX[] = unsafe_load(cglobal((:MPICONSTANTS_C_FLOAT_COMPLEX, libmpiconstants), MPI_Datatype))
    Consts.MPI_C_LONG_DOUBLE_COMPLEX[] = unsafe_load(cglobal((:MPICONSTANTS_C_LONG_DOUBLE_COMPLEX, libmpiconstants), MPI_Datatype))
    Consts.MPI_DATATYPE_NULL[] = unsafe_load(cglobal((:MPICONSTANTS_DATATYPE_NULL, libmpiconstants), MPI_Datatype))
    Consts.MPI_DOUBLE[] = unsafe_load(cglobal((:MPICONSTANTS_DOUBLE, libmpiconstants), MPI_Datatype))
    Consts.MPI_DOUBLE_COMPLEX[] = unsafe_load(cglobal((:MPICONSTANTS_DOUBLE_COMPLEX, libmpiconstants), MPI_Datatype))
    Consts.MPI_DOUBLE_INT[] = unsafe_load(cglobal((:MPICONSTANTS_DOUBLE_INT, libmpiconstants), MPI_Datatype))
    Consts.MPI_DOUBLE_PRECISION[] = unsafe_load(cglobal((:MPICONSTANTS_DOUBLE_PRECISION, libmpiconstants), MPI_Datatype))
    Consts.MPI_FLOAT[] = unsafe_load(cglobal((:MPICONSTANTS_FLOAT, libmpiconstants), MPI_Datatype))
    Consts.MPI_FLOAT_INT[] = unsafe_load(cglobal((:MPICONSTANTS_FLOAT_INT, libmpiconstants), MPI_Datatype))
    Consts.MPI_INT[] = unsafe_load(cglobal((:MPICONSTANTS_INT, libmpiconstants), MPI_Datatype))
    Consts.MPI_INT16_T[] = unsafe_load(cglobal((:MPICONSTANTS_INT16_T, libmpiconstants), MPI_Datatype))
    Consts.MPI_INT32_T[] = unsafe_load(cglobal((:MPICONSTANTS_INT32_T, libmpiconstants), MPI_Datatype))
    Consts.MPI_INT64_T[] = unsafe_load(cglobal((:MPICONSTANTS_INT64_T, libmpiconstants), MPI_Datatype))
    Consts.MPI_INT8_T[] = unsafe_load(cglobal((:MPICONSTANTS_INT8_T, libmpiconstants), MPI_Datatype))
    Consts.MPI_INTEGER[] = unsafe_load(cglobal((:MPICONSTANTS_INTEGER, libmpiconstants), MPI_Datatype))
    Consts.MPI_INTEGER1[] = unsafe_load(cglobal((:MPICONSTANTS_INTEGER1, libmpiconstants), MPI_Datatype))
    Consts.MPI_INTEGER2[] = unsafe_load(cglobal((:MPICONSTANTS_INTEGER2, libmpiconstants), MPI_Datatype))
    Consts.MPI_INTEGER4[] = unsafe_load(cglobal((:MPICONSTANTS_INTEGER4, libmpiconstants), MPI_Datatype))
    Consts.MPI_INTEGER8[] = unsafe_load(cglobal((:MPICONSTANTS_INTEGER8, libmpiconstants), MPI_Datatype))
    Consts.MPI_LOGICAL[] = unsafe_load(cglobal((:MPICONSTANTS_LOGICAL, libmpiconstants), MPI_Datatype))
    Consts.MPI_LONG[] = unsafe_load(cglobal((:MPICONSTANTS_LONG, libmpiconstants), MPI_Datatype))
    Consts.MPI_LONG_DOUBLE[] = unsafe_load(cglobal((:MPICONSTANTS_LONG_DOUBLE, libmpiconstants), MPI_Datatype))
    Consts.MPI_LONG_DOUBLE_INT[] = unsafe_load(cglobal((:MPICONSTANTS_LONG_DOUBLE_INT, libmpiconstants), MPI_Datatype))
    Consts.MPI_LONG_INT[] = unsafe_load(cglobal((:MPICONSTANTS_LONG_INT, libmpiconstants), MPI_Datatype))
    Consts.MPI_LONG_LONG[] = unsafe_load(cglobal((:MPICONSTANTS_LONG_LONG, libmpiconstants), MPI_Datatype))
    Consts.MPI_LONG_LONG_INT[] = unsafe_load(cglobal((:MPICONSTANTS_LONG_LONG_INT, libmpiconstants), MPI_Datatype))
    Consts.MPI_OFFSET[] = unsafe_load(cglobal((:MPICONSTANTS_OFFSET, libmpiconstants), MPI_Datatype))
    Consts.MPI_PACKED[] = unsafe_load(cglobal((:MPICONSTANTS_PACKED, libmpiconstants), MPI_Datatype))
    Consts.MPI_REAL[] = unsafe_load(cglobal((:MPICONSTANTS_REAL, libmpiconstants), MPI_Datatype))
    # MPI_REAL16[] = unsafe_load(cglobal((:MPICONSTANTS_REAL16, libmpiconstants), MPI_Datatype))
    Consts.MPI_REAL4[] = unsafe_load(cglobal((:MPICONSTANTS_REAL4, libmpiconstants), MPI_Datatype))
    Consts.MPI_REAL8[] = unsafe_load(cglobal((:MPICONSTANTS_REAL8, libmpiconstants), MPI_Datatype))
    Consts.MPI_SHORT[] = unsafe_load(cglobal((:MPICONSTANTS_SHORT, libmpiconstants), MPI_Datatype))
    Consts.MPI_SHORT_INT[] = unsafe_load(cglobal((:MPICONSTANTS_SHORT_INT, libmpiconstants), MPI_Datatype))
    Consts.MPI_SIGNED_CHAR[] = unsafe_load(cglobal((:MPICONSTANTS_SIGNED_CHAR, libmpiconstants), MPI_Datatype))
    Consts.MPI_UINT16_T[] = unsafe_load(cglobal((:MPICONSTANTS_UINT16_T, libmpiconstants), MPI_Datatype))
    Consts.MPI_UINT32_T[] = unsafe_load(cglobal((:MPICONSTANTS_UINT32_T, libmpiconstants), MPI_Datatype))
    Consts.MPI_UINT64_T[] = unsafe_load(cglobal((:MPICONSTANTS_UINT64_T, libmpiconstants), MPI_Datatype))
    Consts.MPI_UINT8_T[] = unsafe_load(cglobal((:MPICONSTANTS_UINT8_T, libmpiconstants), MPI_Datatype))
    Consts.MPI_UNSIGNED[] = unsafe_load(cglobal((:MPICONSTANTS_UNSIGNED, libmpiconstants), MPI_Datatype))
    Consts.MPI_UNSIGNED_CHAR[] = unsafe_load(cglobal((:MPICONSTANTS_UNSIGNED_CHAR, libmpiconstants), MPI_Datatype))
    Consts.MPI_UNSIGNED_LONG[] = unsafe_load(cglobal((:MPICONSTANTS_UNSIGNED_LONG, libmpiconstants), MPI_Datatype))
    Consts.MPI_UNSIGNED_LONG_LONG[] = unsafe_load(cglobal((:MPICONSTANTS_UNSIGNED_LONG_LONG, libmpiconstants), MPI_Datatype))
    Consts.MPI_UNSIGNED_SHORT[] = unsafe_load(cglobal((:MPICONSTANTS_UNSIGNED_SHORT, libmpiconstants), MPI_Datatype))
    Consts.MPI_WCHAR[] = unsafe_load(cglobal((:MPICONSTANTS_WCHAR, libmpiconstants), MPI_Datatype))

    Consts.MPI_NULL_DELETE_FN[] = unsafe_load(cglobal((:MPICONSTANTS_NULL_DELETE_FN, libmpiconstants), MPI_Delete_function))

    Consts.MPI_ERRHANDLER_NULL[] = unsafe_load(cglobal((:MPICONSTANTS_ERRHANDLER_NULL, libmpiconstants), MPI_Errhandler))
    Consts.MPI_ERRORS_ARE_FATAL[] = unsafe_load(cglobal((:MPICONSTANTS_ERRORS_ARE_FATAL, libmpiconstants), MPI_Errhandler))
    Consts.MPI_ERRORS_RETURN[] = unsafe_load(cglobal((:MPICONSTANTS_ERRORS_RETURN, libmpiconstants), MPI_Errhandler))

    Consts.MPI_FILE_NULL[] = unsafe_load(cglobal((:MPICONSTANTS_FILE_NULL, libmpiconstants), MPI_File))

    Consts.MPI_GROUP_EMPTY[] = unsafe_load(cglobal((:MPICONSTANTS_GROUP_EMPTY, libmpiconstants), MPI_Group))
    Consts.MPI_GROUP_NULL[] = unsafe_load(cglobal((:MPICONSTANTS_GROUP_NULL, libmpiconstants), MPI_Group))

    Consts.MPI_INFO_ENV[] = unsafe_load(cglobal((:MPICONSTANTS_INFO_ENV, libmpiconstants), MPI_Info))
    Consts.MPI_INFO_NULL[] = unsafe_load(cglobal((:MPICONSTANTS_INFO_NULL, libmpiconstants), MPI_Info))

    Consts.MPI_MESSAGE_NO_PROC[] = unsafe_load(cglobal((:MPICONSTANTS_MESSAGE_NO_PROC, libmpiconstants), MPI_Message))
    Consts.MPI_MESSAGE_NULL[] = unsafe_load(cglobal((:MPICONSTANTS_MESSAGE_NULL, libmpiconstants), MPI_Message))

    Consts.MPI_DISPLACEMENT_CURRENT[] = unsafe_load(cglobal((:MPICONSTANTS_DISPLACEMENT_CURRENT, libmpiconstants), MPI_Offset))

    Consts.MPI_BAND[] = unsafe_load(cglobal((:MPICONSTANTS_BAND, libmpiconstants), MPI_Op))
    Consts.MPI_BOR[] = unsafe_load(cglobal((:MPICONSTANTS_BOR, libmpiconstants), MPI_Op))
    Consts.MPI_BXOR[] = unsafe_load(cglobal((:MPICONSTANTS_BXOR, libmpiconstants), MPI_Op))
    Consts.MPI_LAND[] = unsafe_load(cglobal((:MPICONSTANTS_LAND, libmpiconstants), MPI_Op))
    Consts.MPI_LOR[] = unsafe_load(cglobal((:MPICONSTANTS_LOR, libmpiconstants), MPI_Op))
    Consts.MPI_LXOR[] = unsafe_load(cglobal((:MPICONSTANTS_LXOR, libmpiconstants), MPI_Op))
    Consts.MPI_MAX[] = unsafe_load(cglobal((:MPICONSTANTS_MAX, libmpiconstants), MPI_Op))
    Consts.MPI_MAXLOC[] = unsafe_load(cglobal((:MPICONSTANTS_MAXLOC, libmpiconstants), MPI_Op))
    Consts.MPI_MIN[] = unsafe_load(cglobal((:MPICONSTANTS_MIN, libmpiconstants), MPI_Op))
    Consts.MPI_MINLOC[] = unsafe_load(cglobal((:MPICONSTANTS_MINLOC, libmpiconstants), MPI_Op))
    Consts.MPI_NO_OP[] = unsafe_load(cglobal((:MPICONSTANTS_NO_OP, libmpiconstants), MPI_Op))
    Consts.MPI_OP_NULL[] = unsafe_load(cglobal((:MPICONSTANTS_OP_NULL, libmpiconstants), MPI_Op))
    Consts.MPI_PROD[] = unsafe_load(cglobal((:MPICONSTANTS_PROD, libmpiconstants), MPI_Op))
    Consts.MPI_REPLACE[] = unsafe_load(cglobal((:MPICONSTANTS_REPLACE, libmpiconstants), MPI_Op))
    Consts.MPI_SUM[] = unsafe_load(cglobal((:MPICONSTANTS_SUM, libmpiconstants), MPI_Op))

    Consts.MPI_REQUEST_NULL[] = unsafe_load(cglobal((:MPICONSTANTS_REQUEST_NULL, libmpiconstants), MPI_Request))

    Consts.MPI_STATUS_IGNORE[] = unsafe_load(cglobal((:MPICONSTANTS_STATUS_IGNORE, libmpiconstants), Ptr{MPI_Status}))
    Consts.MPI_STATUSES_IGNORE[] = unsafe_load(cglobal((:MPICONSTANTS_STATUSES_IGNORE, libmpiconstants), Ptr{MPI_Status}))

    Consts.MPI_TYPE_DUP_FN[] = unsafe_load(cglobal((:MPICONSTANTS_TYPE_DUP_FN, libmpiconstants), MPI_Type_copy_attr_function))

    Consts.MPI_TYPE_NULL_COPY_FN[] = unsafe_load(cglobal((:MPICONSTANTS_TYPE_NULL_COPY_FN, libmpiconstants), MPI_Type_copy_attr_function))

    Consts.MPI_TYPE_NULL_DELETE_FN[] = unsafe_load(cglobal((:MPICONSTANTS_TYPE_NULL_DELETE_FN, libmpiconstants), MPI_Type_delete_attr_function))

    Consts.MPI_WIN_NULL[] = unsafe_load(cglobal((:MPICONSTANTS_WIN_NULL, libmpiconstants), MPI_Win))

    Consts.MPI_WIN_DUP_FN[] = unsafe_load(cglobal((:MPICONSTANTS_WIN_DUP_FN, libmpiconstants), MPI_Win_copy_attr_function))
    Consts.MPI_WIN_NULL_COPY_FN[] = unsafe_load(cglobal((:MPICONSTANTS_WIN_NULL_COPY_FN, libmpiconstants), MPI_Win_copy_attr_function))

    Consts.MPI_WIN_NULL_DELETE_FN[] = unsafe_load(cglobal((:MPICONSTANTS_WIN_NULL_DELETE_FN, libmpiconstants), MPI_Win_delete_attr_function))

else # if Sys.iswindows()

    # MicrosoftMPI only supports the standard MPI 2.0, so not all
    # constants are available. (Julia generally supports MPI 3.1.)

    Consts.MPI_ANY_SOURCE[] = Cint(-2)
    Consts.MPI_ANY_TAG[] = Cint(-1)
    Consts.MPI_PROC_NULL[] = Cint(-1)
    Consts.MPI_ROOT[] = Cint(-3)
    Consts.MPI_CART[] = Cint(2)
    Consts.MPI_DIST_GRAPH[] = Cint(3)
    Consts.MPI_GRAPH[] = Cint(1)
    Consts.MPI_CONGRUENT[] = Cint(1)
    Consts.MPI_IDENT[] = Cint(0)
    Consts.MPI_SIMILAR[] = Cint(2)
    Consts.MPI_UNEQUAL[] = Cint(3)
    Consts.MPI_KEYVAL_INVALID[] = Cint(0x24000000)
    Consts.MPI_UNDEFINED[] = Cint(-32766)
    Consts.MPI_APPNUM[] = Cint(0x6440000d)
    Consts.MPI_HOST[] = Cint(0x64400003)
    Consts.MPI_IO[] = Cint(0x64400005)
    Consts.MPI_LASTUSEDCODE[] = Cint(0x6440000b)
    Consts.MPI_TAG_UB[] = Cint(0x64400001)
    Consts.MPI_UNIVERSE_SIZE[] = Cint(0x64400009)
    Consts.MPI_WIN_BASE[] = Cint(0x66000001)
    Consts.MPI_WIN_CREATE_FLAVOR[] = Cint(0x66000007)
    Consts.MPI_WIN_DISP_UNIT[] = Cint(0x66000005)
    Consts.MPI_WIN_MODEL[] = Cint(0x66000009)
    Consts.MPI_WIN_SIZE[] = Cint(0x66000003)
    Consts.MPI_WTIME_IS_GLOBAL[] = Cint(0x64400007)
    Consts.MPI_COMBINER_CONTIGUOUS[] = Cint(3)
    Consts.MPI_COMBINER_DARRAY[] = Cint(14)
    Consts.MPI_COMBINER_DUP[] = Cint(2)
    Consts.MPI_COMBINER_F90_COMPLEX[] = Cint(16)
    Consts.MPI_COMBINER_F90_INTEGER[] = Cint(17)
    Consts.MPI_COMBINER_F90_REAL[] = Cint(15)
    Consts.MPI_COMBINER_HINDEXED[] = Cint(9)
    # Consts.MPI_COMBINER_HINDEXED_BLOCK[] = nothing
    Consts.MPI_COMBINER_HVECTOR[] = Cint(6)
    Consts.MPI_COMBINER_INDEXED[] = Cint(7)
    Consts.MPI_COMBINER_INDEXED_BLOCK[] = Cint(10)
    Consts.MPI_COMBINER_NAMED[] = Cint(1)
    Consts.MPI_COMBINER_RESIZED[] = Cint(18)
    Consts.MPI_COMBINER_STRUCT[] = Cint(12)
    Consts.MPI_COMBINER_SUBARRAY[] = Cint(13)
    Consts.MPI_COMBINER_VECTOR[] = Cint(4)
    Consts.MPI_COMM_TYPE_SHARED[] = Cint(1)
    Consts.MPI_DISTRIBUTE_BLOCK[] = Cint(121)
    Consts.MPI_DISTRIBUTE_CYCLIC[] = Cint(122)
    Consts.MPI_DISTRIBUTE_NONE[] = Cint(123)
    Consts.MPI_ERR_ACCESS[] = Cint(20)
    Consts.MPI_ERR_AMODE[] = Cint(21)
    Consts.MPI_ERR_ARG[] = Cint(12)
    Consts.MPI_ERR_ASSERT[] = Cint(53)
    Consts.MPI_ERR_BAD_FILE[] = Cint(22)
    Consts.MPI_ERR_BASE[] = Cint(46)
    Consts.MPI_ERR_BUFFER[] = Cint(1)
    Consts.MPI_ERR_COMM[] = Cint(5)
    Consts.MPI_ERR_CONVERSION[] = Cint(23)
    Consts.MPI_ERR_COUNT[] = Cint(2)
    Consts.MPI_ERR_DIMS[] = Cint(11)
    Consts.MPI_ERR_DISP[] = Cint(52)
    Consts.MPI_ERR_DUP_DATAREP[] = Cint(24)
    Consts.MPI_ERR_FILE[] = Cint(27)
    Consts.MPI_ERR_FILE_EXISTS[] = Cint(25)
    Consts.MPI_ERR_FILE_IN_USE[] = Cint(26)
    Consts.MPI_ERR_GROUP[] = Cint(8)
    Consts.MPI_ERR_INFO[] = Cint(28)
    Consts.MPI_ERR_INFO_KEY[] = Cint(29)
    Consts.MPI_ERR_INFO_NOKEY[] = Cint(31)
    Consts.MPI_ERR_INFO_VALUE[] = Cint(30)
    Consts.MPI_ERR_INTERN[] = Cint(16)
    Consts.MPI_ERR_IN_STATUS[] = Cint(17)
    Consts.MPI_ERR_IO[] = Cint(32)
    Consts.MPI_ERR_KEYVAL[] = Cint(48)
    Consts.MPI_ERR_LASTCODE[] = Cint(0x3fffffff)
    Consts.MPI_ERR_LOCKTYPE[] = Cint(47)
    Consts.MPI_ERR_NAME[] = Cint(33)
    Consts.MPI_ERR_NOT_SAME[] = Cint(35)
    Consts.MPI_ERR_NO_MEM[] = Cint(34)
    Consts.MPI_ERR_NO_SPACE[] = Cint(36)
    Consts.MPI_ERR_NO_SUCH_FILE[] = Cint(37)
    Consts.MPI_ERR_OP[] = Cint(9)
    Consts.MPI_ERR_OTHER[] = Cint(15)
    Consts.MPI_ERR_PENDING[] = Cint(18)
    Consts.MPI_ERR_PORT[] = Cint(38)
    Consts.MPI_ERR_QUOTA[] = Cint(39)
    Consts.MPI_ERR_RANK[] = Cint(6)
    Consts.MPI_ERR_READ_ONLY[] = Cint(40)
    Consts.MPI_ERR_REQUEST[] = Cint(19)
    # Consts.MPI_ERR_RMA_ATTACH[] = nothing
    Consts.MPI_ERR_RMA_CONFLICT[] = Cint(49)
    # Consts.MPI_ERR_RMA_FLAVOR[] = nothing
    # Consts.MPI_ERR_RMA_RANGE[] = nothing
    # Consts.MPI_ERR_RMA_SHARED[] = nothing
    Consts.MPI_ERR_RMA_SYNC[] = Cint(50)
    Consts.MPI_ERR_ROOT[] = Cint(7)
    Consts.MPI_ERR_SERVICE[] = Cint(41)
    Consts.MPI_ERR_SIZE[] = Cint(51)
    # Consts.MPI_ERR_SPAWN[] = nothing
    Consts.MPI_ERR_TAG[] = Cint(4)
    Consts.MPI_ERR_TOPOLOGY[] = Cint(10)
    Consts.MPI_ERR_TRUNCATE[] = Cint(14)
    Consts.MPI_ERR_TYPE[] = Cint(3)
    Consts.MPI_ERR_UNKNOWN[] = Cint(13)
    # Consts.MPI_ERR_UNSUPPORTED_DATAREP[] = nothing
    # Consts.MPI_ERR_UNSUPPORTED_OPERATION[] = nothing
    Consts.MPI_ERR_WIN[] = Cint(45)
    # We special-case MPI_SUCCESS which is required to be 0
    # Consts.MPI_SUCCESS[] = Cint(0)
    @assert Consts.MPI_SUCCESS[] == 0
    Consts.MPI_LOCK_EXCLUSIVE[] = Cint(234)
    Consts.MPI_LOCK_SHARED[] = Cint(235)
    Consts.MPI_MODE_APPEND[] = Cint(0x00000080)
    Consts.MPI_MODE_CREATE[] = Cint(0x00000001)
    Consts.MPI_MODE_DELETE_ON_CLOSE[] = Cint(0x00000010)
    Consts.MPI_MODE_EXCL[] = Cint(0x00000040)
    Consts.MPI_MODE_NOCHECK[] = Cint(1024)
    Consts.MPI_MODE_NOPRECEDE[] = Cint(8192)
    Consts.MPI_MODE_NOPUT[] = Cint(4096)
    Consts.MPI_MODE_NOSTORE[] = Cint(2048)
    Consts.MPI_MODE_NOSUCCEED[] = Cint(16384)
    Consts.MPI_MODE_RDONLY[] = Cint(0x00000002)
    Consts.MPI_MODE_RDWR[] = Cint(0x00000008)
    Consts.MPI_MODE_SEQUENTIAL[] = Cint(0x00000100)
    Consts.MPI_MODE_UNIQUE_OPEN[] = Cint(0x00000020)
    Consts.MPI_MODE_WRONLY[] = Cint(0x00000004)
    Consts.MPI_ORDER_C[] = Cint(56)
    Consts.MPI_ORDER_FORTRAN[] = Cint(57)
    Consts.MPI_SEEK_CUR[] = Cint(602)
    Consts.MPI_SEEK_END[] = Cint(604)
    Consts.MPI_SEEK_SET[] = Cint(600)
    Consts.MPI_THREAD_SINGLE[] = Cint(0)
    Consts.MPI_THREAD_FUNNELED[] = Cint(1)
    Consts.MPI_THREAD_SERIALIZED[] = Cint(2)
    Consts.MPI_THREAD_MULTIPLE[] = Cint(3)
    Consts.MPI_TYPECLASS_COMPLEX[] = Cint(3)
    Consts.MPI_TYPECLASS_INTEGER[] = Cint(2)
    Consts.MPI_TYPECLASS_REAL[] = Cint(1)

    Consts.MPI_ARGV_NULL[] = Ptr{Ptr{Cchar}}(0)
    Consts.MPI_ARGVS_NULL[] = Ptr{Ptr{Ptr{Cchar}}}(0)
    # MPI_UNWEIGHTED[] = nothing
    # MPI_WEIGHTS_EMPTY[] = nothing
    Consts.MPI_BOTTOM[] = Ptr{Cvoid}(0)
    Consts.MPI_IN_PLACE[] = Ptr{Cvoid}(-1)

    Consts.MPI_COMM_NULL[] = MPI_Comm(0x04000000)
    Consts.MPI_COMM_SELF[] = MPI_Comm(0x44000001)
    Consts.MPI_COMM_WORLD[] = MPI_Comm(0x44000000)

    Consts.MPI_COMM_DUP_FN[] = MPI_Comm_copy_attr_function(cglobal((:MPIR_Dup_fn, libmpi)))

    Consts.MPI_COMM_NULL_COPY_FN[] = MPI_Comm_copy_attr_function(0)

    Consts.MPI_COMM_NULL_DELETE_FN[] = MPI_Comm_delete_attr_function(0)

    Consts.MPI_NULL_COPY_FN[] = MPI_Copy_function(0)

    Consts.MPI_2DOUBLE_PRECISION[] = MPI_Datatype(0x4c001023)
    Consts.MPI_2INT[] = MPI_Datatype(0x4c000816)
    Consts.MPI_2INTEGER[] = MPI_Datatype(0x4c000820)
    Consts.MPI_2REAL[] = MPI_Datatype(0x4c000821)
    Consts.MPI_AINT[] = Sys.ARCH ≡ :x86_64 ? MPI_Datatype(0x4c00083b) : MPI_Datatype(0x4c00043b)
    Consts.MPI_BYTE[] = MPI_Datatype(0x4c00010d)
    Consts.MPI_CHAR[] = MPI_Datatype(0x4c000101)
    Consts.MPI_CHARACTER[] = MPI_Datatype(0x4c00011a)
    Consts.MPI_COMPLEX[] = MPI_Datatype(0x4c00081e)
    Consts.MPI_COMPLEX16[] = MPI_Datatype(0x4c00102a)
    # MPI_COMPLEX32[] = nothing
    Consts.MPI_COMPLEX8[] = MPI_Datatype(0x4c000828)
    Consts.MPI_COUNT[] = MPI_Datatype(0x4c000845)
    Consts.MPI_CXX_BOOL[] = MPI_Datatype(0x4c000133)
    Consts.MPI_CXX_DOUBLE_COMPLEX[] = MPI_Datatype(0x4c001035)
    Consts.MPI_CXX_FLOAT_COMPLEX[] = MPI_Datatype(0x4c000834)
    Consts.MPI_CXX_LONG_DOUBLE_COMPLEX[] = MPI_Datatype(0x4c002036)
    Consts.MPI_C_BOOL[] = MPI_Datatype(0x4c000117)
    Consts.MPI_C_COMPLEX[] = MPI_Datatype(0x4c000812)
    Consts.MPI_C_DOUBLE_COMPLEX[] = MPI_Datatype(0x4c001014)
    Consts.MPI_C_FLOAT_COMPLEX[] = MPI_Datatype(0x4c000813)
    Consts.MPI_C_LONG_DOUBLE_COMPLEX[] = MPI_Datatype(0x4c001015)
    Consts.MPI_DATATYPE_NULL[] = MPI_Datatype(0x0c000000)
    Consts.MPI_DOUBLE[] = MPI_Datatype(0x4c00080b)
    Consts.MPI_DOUBLE_COMPLEX[] = MPI_Datatype(0x4c001022)
    Consts.MPI_DOUBLE_INT[] = MPI_Datatype(0x8c000001)
    Consts.MPI_DOUBLE_PRECISION[] = MPI_Datatype(0x4c00081f)
    Consts.MPI_FLOAT[] = MPI_Datatype(0x4c00040a)
    Consts.MPI_FLOAT_INT[] = MPI_Datatype(0x8c000000)
    Consts.MPI_INT[] = MPI_Datatype(0x4c000405)
    Consts.MPI_INT16_T[] = MPI_Datatype(0x4c000234)
    Consts.MPI_INT32_T[] = MPI_Datatype(0x4c000435)
    Consts.MPI_INT64_T[] = MPI_Datatype(0x4c000836)
    Consts.MPI_INT8_T[] = MPI_Datatype(0x4c000133)
    Consts.MPI_INTEGER[] = MPI_Datatype(0x4c00041b)
    Consts.MPI_INTEGER1[] = MPI_Datatype(0x4c00012d)
    Consts.MPI_INTEGER2[] = MPI_Datatype(0x4c00022f)
    Consts.MPI_INTEGER4[] = MPI_Datatype(0x4c000430)
    Consts.MPI_INTEGER8[] = MPI_Datatype(0x4c000831)
    Consts.MPI_LOGICAL[] = MPI_Datatype(0x4c00041d)
    Consts.MPI_LONG[] = MPI_Datatype(0x4c000407)
    Consts.MPI_LONG_DOUBLE[] = MPI_Datatype(0x4c00080c)
    Consts.MPI_LONG_DOUBLE_INT[] = MPI_Datatype(0x8c000004)
    Consts.MPI_LONG_INT[] = MPI_Datatype(0x8c000002)
    Consts.MPI_LONG_LONG[] = MPI_Datatype(0x4c000809)
    Consts.MPI_LONG_LONG_INT[] = MPI_Datatype(0x4c000809)
    Consts.MPI_OFFSET[] = MPI_Datatype(0x4c000844)
    Consts.MPI_PACKED[] = MPI_Datatype(0x4c00010f)
    Consts.MPI_REAL[] = MPI_Datatype(0x4c00041c)
    # MPI_REAL16[] = nothing
    Consts.MPI_REAL4[] = MPI_Datatype(0x4c000427)
    Consts.MPI_REAL8[] = MPI_Datatype(0x4c000829)
    Consts.MPI_SHORT[] = MPI_Datatype(0x4c000203)
    Consts.MPI_SHORT_INT[] = MPI_Datatype(0x8c000003)
    Consts.MPI_SIGNED_CHAR[] = MPI_Datatype(0x4c000118)
    Consts.MPI_UINT16_T[] = MPI_Datatype(0x4c000238)
    Consts.MPI_UINT32_T[] = MPI_Datatype(0x4c000439)
    Consts.MPI_UINT64_T[] = MPI_Datatype(0x4c00083a)
    Consts.MPI_UINT8_T[] = MPI_Datatype(0x4c000137)
    Consts.MPI_UNSIGNED[] = MPI_Datatype(0x4c000406)
    Consts.MPI_UNSIGNED_CHAR[] = MPI_Datatype(0x4c000102)
    Consts.MPI_UNSIGNED_LONG[] = MPI_Datatype(0x4c000408)
    Consts.MPI_UNSIGNED_LONG_LONG[] = MPI_Datatype(0x4c000819)
    Consts.MPI_UNSIGNED_SHORT[] = MPI_Datatype(0x4c000204)
    Consts.MPI_WCHAR[] = MPI_Datatype(0x4c00040e)

    Consts.MPI_NULL_DELETE_FN[] = MPI_Delete_function(0)

    Consts.MPI_ERRHANDLER_NULL[] = MPI_Errhandler(0x14000000)
    Consts.MPI_ERRORS_ARE_FATAL[] = MPI_Errhandler(0x54000000)
    Consts.MPI_ERRORS_RETURN[] = MPI_Errhandler(0x54000001)

    Consts.MPI_FILE_NULL[] = MPI_File(0)

    Consts.MPI_GROUP_EMPTY[] = MPI_Group(0x48000000)
    Consts.MPI_GROUP_NULL[] = MPI_Group(0x08000000)

    # Consts.MPI_INFO_ENV[] = nothing
    Consts.MPI_INFO_NULL[] = MPI_Info(0x1c000000)

    Consts.MPI_MESSAGE_NO_PROC[] = MPI_Message(0x6c000000)
    Consts.MPI_MESSAGE_NULL[] = MPI_Message(0x2c000000)

    Consts.MPI_DISPLACEMENT_CURRENT[] = MPI_Offset(-54278278)

    Consts.MPI_BAND[] = MPI_Op(0x58000006)
    Consts.MPI_BOR[] = MPI_Op(0x58000008)
    Consts.MPI_BXOR[] = MPI_Op(0x5800000a)
    Consts.MPI_LAND[] = MPI_Op(0x58000005)
    Consts.MPI_LOR[] = MPI_Op(0x58000007)
    Consts.MPI_LXOR[] = MPI_Op(0x58000009)
    Consts.MPI_MAX[] = MPI_Op(0x58000001)
    Consts.MPI_MAXLOC[] = MPI_Op(0x5800000c)
    Consts.MPI_MIN[] = MPI_Op(0x58000002)
    Consts.MPI_MINLOC[] = MPI_Op(0x5800000b)
    Consts.MPI_NO_OP[] = MPI_Op(0x5800000e)
    Consts.MPI_OP_NULL[] = MPI_Op(0x18000000)
    Consts.MPI_PROD[] = MPI_Op(0x58000004)
    Consts.MPI_REPLACE[] = MPI_Op(0x5800000d)
    Consts.MPI_SUM[] = MPI_Op(0x58000003)

    Consts.MPI_REQUEST_NULL[] = MPI_Request(0x2c000000)

    Consts.MPI_STATUS_IGNORE[] = Ptr{MPI_Status}(1)
    Consts.MPI_STATUSES_IGNORE[] = Ptr{MPI_Status}(1)

    Consts.MPI_TYPE_DUP_FN[] = MPI_Type_copy_attr_function(cglobal((:MPIR_Dup_fn, libmpi)))

    Consts.MPI_TYPE_NULL_COPY_FN[] = MPI_Type_copy_attr_function(0)

    Consts.MPI_TYPE_NULL_DELETE_FN[] = MPI_Type_delete_attr_function(0)

    Consts.MPI_WIN_NULL[] = MPI_Win(0x20000000)

    Consts.MPI_WIN_DUP_FN[] = MPI_Win_copy_attr_function(cglobal((:MPIR_Dup_fn, libmpi)))
    Consts.MPI_WIN_NULL_COPY_FN[] = MPI_Win_copy_attr_function(0)

    Consts.MPI_WIN_NULL_DELETE_FN[] = MPI_Win_delete_attr_function(0)

end # if Sys.iswindows()

run_load_time_hooks()

end


text:
#=
P16 (**) Drop every N'th element from a list.
Example:
* (drop '(a b c d e f g h i k) 3)
(A B D E G H K)
=#

function my_drop(coll, n)
    function _my_drop(coll, count, temp)
        if isempty(coll)
            temp
        else
            if count == n
                _my_drop(coll[2:end], 1, temp)
            else
                _my_drop(coll[2:end], count + 1, vcat(temp, coll[1]))
            end
        end
    end
    _my_drop(coll, 1, [])
end

@assert my_drop([:a, :b, :c, :d, :e, :f, :g, :h, :i, :k], 3) == [:a, :b, :d, :e, :g, :h, :k]
@assert my_drop([:a, :b, :c, :d, :e], 2) == [:a, :c, :e]
@assert my_drop([:a, :b, :c, :d, :e], 1) == []

println("Tests passed: JL-16.jl")

ext: jl


text:
include("MatHeatDiffModule.jl")
include("FEMMHeatDiffModule.jl")
include("FEMMHeatDiffSurfModule.jl")
include("AlgoHeatDiffModule.jl")

max_stars_repo_name: PetrKryslUCSD/FinEtoolsHeatDiff

max_issues_repo_name: PetrKryslUCSD/FinEtoolsHeatDiff

max_forks_repo_name: PetrKryslUCSD/FinEtoolsHeatDiff


text:
"""
    GammaLikelihood(α::Real=1.0, l=exp)

Gamma likelihood with fixed shape `α`.

```math
    p(y|f) = \\operatorname{Gamma}(y | α, l(f))
```
On calling, this would return a gamma distribution with shape `α` and scale `l(f)`.
"""
struct GammaLikelihood{T<:Real,Tl<:AbstractLink} <: AbstractLikelihood
    α::T    # shape parameter
    invlink::Tl
end

GammaLikelihood(l) = GammaLikelihood(1.0, l)
GammaLikelihood(α::Real=1.0, l=exp) = GammaLikelihood(α, Link(l))

@functor GammaLikelihood

(l::GammaLikelihood)(f::Real) = Gamma(l.α, l.invlink(f))

(l::GammaLikelihood)(fs::AbstractVector{<:Real}) = Product(Gamma.(l.α, l.invlink.(fs)))


text:
using TimeSeries, MarketData
FactCheck.setstyle(:compact)
FactCheck.onlystats(true)

facts("construction with and without meta field") do

    nometa = TimeArray(cl.timestamp, cl.values, cl.colnames)

    context("default meta field to nothing") do
        @fact nometa.meta --> nothing
    end

    context("allow objects in meta field") do
        @fact mdata.meta --> "Apple"
    end
end

facts("get index operations preserve meta") do

    context("index by integer row") do
        @fact mdata[1].meta --> "Apple"
    end

    context("index by integer range") do
        @fact mdata[1:2].meta --> "Apple"
    end

    context("index by column name") do
        @fact mdata["Close"].meta --> "Apple"
    end

    context("index by date range") do
        @fact mdata[[Date(2000,1,3), Date(2000,1,14)]].meta --> "Apple"
    end
end

facts("split operations preserve meta") do

    context("when") do
        @fact when(mdata, dayofweek, 1).meta --> "Apple"
    end

    context("from") do
        @fact from(mdata, Date(2000,1,1)).meta --> "Apple"
    end

    context("to") do
        @fact to(mdata, Date(2000,1,1)).meta --> "Apple"
    end
end

facts("apply operations preserve meta") do

    context("lag") do
        @fact lag(mdata).meta --> "Apple"
    end

    context("lead") do
        @fact lead(mdata).meta --> "Apple"
    end

    context("percentchange") do
        @fact percentchange(mdata).meta --> "Apple"
    end

    context("moving") do
        @fact moving(mdata,mean,10).meta --> "Apple"
    end

    context("upto") do
        @fact upto(mdata,sum).meta --> "Apple"
    end
end

facts("combine operations preserve meta") do

    context("merge when both have identical meta") do
        @fact merge(cl, op).meta         --> "AAPL"
        @fact merge(cl, op, :left).meta  --> "AAPL"
        @fact merge(cl, op, :right).meta --> "AAPL"
        @fact merge(cl, op, :outer).meta --> "AAPL"
    end

    context("merged meta field value concatenates when both objects' meta field values are strings") do
        @fact merge(mdata, cl).meta         --> "Apple_AAPL"
        @fact merge(mdata, cl, :left).meta  --> "Apple_AAPL"
        @fact merge(mdata, cl, :right).meta --> "Apple_AAPL"
        @fact merge(mdata, cl, :outer).meta --> "Apple_AAPL"
    end

    context("merge when supplied with meta") do
        @fact merge(mdata, mdata, meta=47).meta         --> 47
        @fact merge(mdata, mdata, :left, meta=47).meta  --> 47
        @fact merge(mdata, mdata, :right, meta=47).meta --> 47
        @fact merge(mdata, mdata, :outer, meta=47).meta --> 47
        @fact merge(mdata, cl, meta=47).meta            --> 47
        @fact merge(mdata, cl, :left, meta=47).meta     --> 47
        @fact merge(mdata, cl, :right, meta=47).meta    --> 47
        @fact merge(mdata, cl, :outer, meta=47).meta    --> 47
    end

    context("merged meta field value for disparate types in meta field defaults to Void") do
        @fact merge(mdata, merge(cl, op, meta=47)).meta         --> Void
        @fact merge(mdata, merge(cl, op, meta=47), :left).meta  --> Void
        @fact merge(mdata, merge(cl, op, meta=47), :right).meta --> Void
        @fact merge(mdata, merge(cl, op, meta=47), :outer).meta --> Void
    end

    context("collapse") do
        @fact collapse(mdata, week, first).meta --> "Apple"
    end
end

facts("basecall operations preserve meta") do

    context("basecall") do
        @fact basecall(mdata, cumsum).meta --> "Apple"
    end
end

facts("mathematical and comparison operations preserve meta") do

    context(".+") do
        @fact (mdata .+ mdata).meta --> "Apple"
        @fact (mdata .+ cl).meta --> Void
    end

    context(".<") do
        @fact (mdata .< mdata).meta --> "Apple"
        @fact (mdata .< cl).meta --> Void
    end
end

facts("readwrite accepts meta argument") do

    context("Apple is present") do
        @fact mdata.meta --> "Apple"
    end
end


text:
using GLVisualize, Colors, GeometryTypes, Reactive, GLAbstraction, GLWindow
import GLVisualize: mm

if !isdefined(:runtests)
    window = glscreen()
end

const description = """
This example shows how easy it is to setup
a menu full of widgets which can be used
to configure a visualization interactively.
Click and slide around!
"""

function lorenz(t0, a, b, c, h)
    Point3f0(
        t0[1] + h * a * (t0[2] - t0[1]),
        t0[2] + h * (t0[1] * (b - t0[3]) - t0[2]),
        t0[3] + h * (t0[1] * t0[2] - c * t0[3]),
    )
end
# step through the `time`
function lorenz(array::Vector, a = 5.0 ,b = 2.0, c = 6.0, d = 0.01)
    t0 = Point3f0(0.1, 0, 0)
    for i = eachindex(array)
        t0 = lorenz(t0, a,b,c,d)
        array[i] = t0
    end
    array
end

primitives = GLNormalMesh[
    loadasset("cat.obj"),
    Sphere(Point3f0(0), 1f0),
    Pyramid(Point3f0(0), 1f0, 1f0),
    HyperRectangle(Vec3f0(0), Vec3f0(1))
]

w = Pair[
    :a => 24f0,
    :b => 10f0,
    :c => 6.0f0,
    :d => 0.01f0,
    :scale => 0.4,

    :colora => RGBA(0.7f0, 1f0, 0.5f0, 1f0),
    :colorb => RGBA(1f0, 0f0, 0f0, 1f0),
    :colornorm => Vec2f0(0, 1.2),

    :primitive => primitives
]

editarea, viewarea = x_partition_abs(window.area, 60mm)
editscreen = Screen(
    window, area = editarea,
    color = RGBA{Float32}(0.98, 0.98, 1, 1)
)
viewscreen = Screen(window, area = viewarea)
menu, w = GLVisualize.extract_edit_menu(w, editscreen, true)
_view(menu, editscreen, camera = :fixed_pixel)

n1, n2 = 18, 30
N = n1*n2

args = map(value, (w[:a], w[:b], w[:c], w[:d]))
v0 = lorenz(zeros(Point3f0, N), args...)
positions = foldp(lorenz, v0, w[:a], w[:b], w[:c], w[:d])
scales = map(Vec3f0, w[:scale])
rotations = map(diff, positions)
rotations = map(x-> push!(x, x[end]), rotations)
cmap = map((a,b)->[a,b], w[:colora], w[:colorb])

_view(visualize(
    (w[:primitive], positions),
    scale = scales, rotation = rotations,
    color_map = cmap, color_norm = w[:colornorm]
), viewscreen)

center!(viewscreen)

if !isdefined(:runtests)
    renderloop(window)
end


text:
"""
    GSDist <: ContinuousUnivariateDistribution

Generalized S-Distribution for approximating univariate distributions.

# Arguments
- `F₀`: the reference quantile.
- `x₀`: the value at the reference quantile.
- `α, g, k, γ`: parameters of the Generalized S-Distribution
- `dist`: the underlying probability distribution.
- `F`: the cdf of the distribution.
"""
struct GSDist <: ContinuousUnivariateDistribution
    F₀::Real
    x₀::Real
    α::Real
    g::Real
    k::Real
    γ::Real
    dist::Union{UnivariateDistribution, Nothing} # underlying distribution
    F::Union{Function, Nothing}                  # CDF
    function GSDist(F₀, x₀, α, g, k, γ, dist, F)
        F₀ < 0 || F₀ > 1 && throw(DomainError(F₀, "F₀ must be between 0 and 1"))
        α ≤ 0 && throw(DomainError(α, "α must be a positive real number"))
        g ≤ 0 && throw(DomainError(g, "g must be a positive real number"))
        k ≤ 0 && throw(DomainError(k, "k must be a positive real number"))
        γ ≤ 0 && throw(DomainError(γ, "γ must be a positive real number"))

        new(F₀, x₀, α, g, k, γ, dist, F)
    end
end
GSDist(F₀, x₀, α, g, k, γ) = GSDist(F₀, x₀, α, g, k, γ, nothing, nothing)
GSDist(F₀, x₀, α, g, k, γ, dist) = GSDist(F₀, x₀, α, g, k, γ, dist, _piecewise_cdf(α, g, k, γ, dist))

"""
    GSDist(dist::UnivariateDistribution, F₀::Real=0.5;
    n::Int=21, diff::Function=three_point_midpoint, h::Real=1.0)

# Arguments
- `dist::UnivariateDistribution`: a univariate distribution.
- `F₀::Real`: the reference quantile to center the distribution around.
- `n::Integer`: the number of points on the distribution to use for least squares fit.
- `diff::Function`: one of the finite difference methods for gradient approximation.
- `h::Real`: the denominator used in the diff function.
"""
function GSDist(dist::UnivariateDistribution, F₀::Real=0.5;
    n::Int=21, diff::Function=three_point_midpoint, h::Real=1.0)
    F₀ < 0 || F₀ > 1 && throw(DomainError(F₀, "F₀ must be between 0 and 1"))
    F₀ = Float64(F₀)

    l, u = extrema(dist)
    l = isinf(l) ? quantile(dist, 1e-6) : l
    u = isinf(u) ? quantile(dist, 1 - 1e-6) : u

    ql, qu = cdf.(dist, (l,u))

    q = range(ql, qu, length=n)
    X = typeof(dist) <: DiscreteUnivariateDistribution ? Set(quantile.(dist, q)) : quantile.(dist, q)

    FX = cdf.(dist, X)
    dF = y -> diff(x -> cdf(dist, x), y, h)
    fX = typeof(dist) <: DiscreteUnivariateDistribution ? dF.(X) : pdf.(dist, X)

    f = (t, p) -> p[1] * t.^p[2] .* (1.0 .- t.^p[3]).^p[4]

    p0 = [1, 0.5, 1, 0.5]
    fit = curve_fit(f, FX, fX, p0)
    p = coef(fit)

    F = _piecewise_cdf(p..., dist)

    GSDist(F₀, quantile(dist, F₀), p..., dist, F)
end

params(G::GSDist) = (G.α, G.g, G.k, G.γ)

function quantile(D::GSDist, p::Real)
    q = _gsd_quantile(p, D.F₀, D.x₀, D.α, D.g, D.k, D.γ)
    if isnan(q)
        @warn "Unable to calculate the quantile of the GSDist. Falling back to the quantile of the underlying distribution."
        quantile(D.dist, p)
    else
        q
    end
end

function mean(G::GSDist)
    m = _gsd_mean(G.F₀, G.x₀, G.α, G.g, G.k, G.γ)
    if isnan(m)
        @warn "Unable to calculate the mean of the GSDist. Falling back to the mean of the underlying distribution."
        mean(G.dist)
    else
        m
    end
end

function var(G::GSDist)
    m1 = mean(G)
    m2 = try
        _gsd_moment(G.F₀, G.x₀, G.α, G.g, G.k, G.γ; moment=2)
    catch y
        if isa(y, DomainError)
            @warn "Unable to calculate the variance of the GSDist. Falling back to the variance of the underlying distribution."
            return var(G.dist)
        end
    end
    m2 - m1^2
end

std(G::GSDist) = sqrt(var(G))

cdf(G::GSDist, x::Real) = G.F(x)

function pdf(G::GSDist, x::Real)
    F = cdf(G, x)
    α, g, k, γ = params(G)
    α * F^g * (1 - F^k)^γ
end

function logpdf(G::GSDist, x::Real)
    F = cdf(G, x)
    α, g, k, γ = params(G)
    log(α) + g*log(F) + γ * log(1 - F^k)
end

minimum(G::GSDist) = minimum(G.dist)
maximum(G::GSDist) = maximum(G.dist)

insupport(G::GSDist, x::Real) = minimum(G) ≤ x ≤ maximum(G)
insupport(G::GSDist, x::VecOrMat{<:Real}) = insupport.(G, x)

function mode(G::GSDist)
    α, g, k, γ = params(G)
    x = (g / (k*γ + g))^(1/k)
    quantile(G, x)
end

# skewness(G::GSDist) = _gsd_moment(G.F₀, G.x₀, G.α, G.g, G.k, G.γ; moment=3)
# kurtosis(G::GSDist) = _gsd_moment(G.F₀, G.x₀, G.α, G.g, G.k, G.γ; moment=4)
# entropy(G::GSDist, b::Real)
# mgf(G::GSDist, t::Any)
# cf(G::GSDist, t::Any)


text:
function ^(a::STaylor1{N,T}, n::Integer) where {N,T<:Real}
    n == 0 && return one(a)
    n == 1 && return a
    n == 2 && return square(a)
    n < 0 && return a^float(n)
    return power_by_squaring(a, n)
end

^(a::STaylor1{N,T}, b::STaylor1{N,T}) where {N,T<:Number} = exp(b*log(a))

function power_by_squaring(x::STaylor1{N,T}, p::Integer) where {N,T<:Number}
    p == 1 && return x
    p == 0 && return one(x)
    p == 2 && return square(x)
    t = trailing_zeros(p) + 1
    p >>= t

    while (t -= 1) > 0
        x = square(x)
    end

    y = x
    while p > 0
        t = trailing_zeros(p) + 1
        p >>= t
        while (t -= 1) ≥ 0
            x = square(x)
        end
        y *= x
    end

    return y
end

@generated function ^(a::STaylor1{N,T}, r::S) where {N, T<:Number, S<:Real}

    ex_calc = quote end
    append!(ex_calc.args, Any[nothing for i in 1:N])
    syms = Symbol[Symbol("c$i") for i in 1:N]
    ctuple = Expr(:tuple)
    for i = 1:N
        push!(ctuple.args, syms[i])
    end

    for i = 1:N
        push!(ex_calc.args, :($(syms[i]) = zero(T)))
    end

    expr_quote = quote
        iszero(r) && return one(a)
        r == 1 && return a
        r == 2 && return square(a)
        r == 1/2 && return sqrt(a)
        $ex_calc
    end

    c = STaylor1(zero(T), Val{N}())
    for k = 0:(N - 1)
        symk = syms[k + 1]
        temp_quote = quote
            # First non-zero coefficient
            l0 = findfirst(a)
            if l0 < 0
                $symk = zero(T)
            else
                # The first non-zero coefficient of the result; must be integer
                !isinteger(r*l0) && throw(ArgumentError(
                    """The 0th order Taylor1 coefficient must be non-zero
                    to raise the Taylor1 polynomial to a non-integer exponent."""))
                lnull = trunc(Int, r*l0)
                kprime = $k - lnull
                if (kprime < 0) || (lnull > N-1)
                    $symk = zero(T)
                else
                    # Relevant for positive integer r, to avoid round-off errors
                    if isinteger(r) && ($k > r*findlast(a))
                        $symk = zero(T)
                    else
                        if $k == lnull
                            $symk = a[l0]^r
                        else
                            # The recursion formula
                            if l0 + kprime ≤ (N - 1)
                                tup_in = $ctuple
                                $symk = r*kprime*tup_sel(lnull, tup_in)*a[l0 + kprime]
                            else
                                $symk = zero(T)
                            end
                            for i = 1:($k - lnull - 1)
                                if !((i + lnull) > (N - 1) || (l0 + kprime - i > (N - 1)))
                                    aux = r*(kprime - i) - i
                                    tup_in = $ctuple
                                    $symk += aux*tup_sel(i + lnull, tup_in)*a[l0 + kprime - i]
                                end
                            end
                            $symk /= kprime*a[l0]
                        end
                    end
                end
            end
        end
        one_tup = ntuple(i -> i == 1 ? one(T) : zero(T), Val{N}())
        expr_quote = quote
            $expr_quote
            if r == 0
                $ctuple = $one_tup
            elseif r == 1 # DO NOTHING
            elseif r == 2
                temp_st1 = square(STaylor1{N,T}($ctuple))
            elseif r == 0.5
                temp_st2 = sqrt(STaylor1{N,T}($ctuple))
            else
                $temp_quote
            end
        end
    end

    exout = :(($(syms[1]),))
    for i = 2:N
        push!(exout.args, syms[i])
    end

    return quote
               Base.@_inline_meta
               $expr_quote
               return STaylor1{N,T}($exout)
            end
end

@generated function square(a::STaylor1{N,T}) where {N, T<:Number}
    ex_calc = quote end
    append!(ex_calc.args, Any[nothing for i in 1:N])
    syms = Symbol[Symbol("c$i") for i in 1:N]

    sym = syms[1]
    ex_line = :($(syms[1]) = a[0]^2)
    ex_calc.args[1] = ex_line

    for k in 1:(N-1)
        kodd = k%2
        kend = div(k - 2 + kodd, 2)
        ex_line = :(a[0] * a[$k])
        @inbounds for i = 1:kend
            ex_line = :($ex_line + a[$i] * a[$(k-i)])
        end
        ex_line = :(2.0*($ex_line)) # float(2)* TODO: ADD BACK IN
        if kodd !== 1
            ex_line = :($ex_line +a[$(div(k,2))]^2)
        end
        ex_line = :($(syms[k+1]) = $ex_line)
        ex_calc.args[k+1] = ex_line
    end

    exout = :(($(syms[1]),))
    for i = 2:N
        push!(exout.args, syms[i])
    end
    return quote
               Base.@_inline_meta
               $ex_calc
               return STaylor1{N,T}($exout)
            end
end

@generated function inverse(a::STaylor1{N,T}) where {N,T<:Real}
    ex_calc = quote end
    append!(ex_calc.args, Any[nothing for i in 1:(2*N)])
    syms = Symbol[Symbol("c$i") for i in 1:N]

    exout = :(($(syms[1]),))
    for i = 2:N
        push!(exout.args, syms[i])
    end

    count = 1
    for n = 1:(N - 1)
        ex_calc.args[2*count - 1] = :(syms[n + 1] = zdivfpown[n - 1]/n)
        ex_calc.args[2*count] = :(zdivfpown *= zdivf)
        count += 1
    end

    return quote
               Base.@_inline_meta
               if a[0] != zero(T)
                   throw(ArgumentError(
                   """
                   Evaluation of Taylor1 series at 0 is non-zero. For high accuracy, revert
                   a Taylor1 series with first coefficient 0 and re-expand about f(0).
                   """))
               end
               z = copy(a)
               zdivf = z/a
               zdivfpown = zdivf
               S = eltype(zdivf)
               $ex_calc
               return STaylor1{N,T}($exout)
            end
end

function tup_sel(i, vargs)
    return vargs[i+1]
end

@generated function sqrt(a::STaylor1{N,T}) where {N,T<:Number}

    ex_calc = quote end
    append!(ex_calc.args, Any[nothing for i in 1:N])
    syms = Symbol[Symbol("c$i") for i in 1:N]
    ctuple = Expr(:tuple)
    for i = 1:N
        push!(ctuple.args, syms[i])
    end

    # First non-zero coefficient
    expr_quote = quote
        l0nz = findfirst(a)
        aux = zero(T)
        if l0nz < 0
            return zero(STaylor1{N,T})
        elseif l0nz%2 == 1 # l0nz must be pair
            throw(ArgumentError(
            """First non-vanishing Taylor1 coefficient must correspond
            to an **even power** in order to expand `sqrt` around 0."""))
        end

        # The last l0nz coefficients are set to zero.
        lnull = div(l0nz, 2)
    end

    for i = 1:N
        push!(ex_calc.args, :($(syms[i]) = zero(T)))
    end

    for i = 1:N
        switch_expr = :((lnull == $(i-1)) && ($(syms[i]) = sqrt(a[l0nz])))
        expr_quote = quote
            $expr_quote
            $switch_expr
        end
    end

    for k = 0:(N - 1)
        symk = syms[k + 1]
        temp_expr = quote
            if $k >= lnull + 1
                if $k == lnull
                    $symk = sqrt(a[2*lnull])
                else
                    kodd = ($k - lnull)%2
                    kend = div($k - lnull - 2 + kodd, 2)
                    imax = min(lnull + kend, N - 1)
                    imin = max(lnull + 1, $k + lnull - (N - 1))
                    if imin ≤ imax
                        tup_in = $ctuple
                        $symk = tup_sel(imin, tup_in)*tup_sel($k + lnull - imin, tup_in)
                    end
                    for i = (imin + 1):imax
                        tup_in = $ctuple
                        $symk += tup_sel(i, tup_in)*tup_sel($k + lnull - i, tup_in)
                    end
                    if $k + lnull ≤ (N - 1)
                        aux = a[$k + lnull] - 2*$symk
                    else
                        aux = -2*$symk
                    end
                    tup_in = $ctuple
                    if kodd == 0
                        aux -= tup_sel(kend + lnull + 1, tup_in)^2
                    end
                    $symk = aux/(2*tup_sel(lnull, tup_in))
                end
            end
        end
        expr_quote = quote
            $expr_quote
            $temp_expr
        end
    end

    exout = :(($(syms[1]),))
    for i = 2:N
        push!(exout.args, syms[i])
    end
    return quote
               Base.@_inline_meta
               $ex_calc
               $expr_quote
               return STaylor1{N,T}($exout)
            end
end


text:
### A Pluto.jl notebook ###
# v0.12.12

using Markdown
using InteractiveUtils

# This Pluto notebook uses @bind for interactivity. When running this notebook outside of Pluto, the following 'mock version' of @bind gives bound variables a default value (instead of an error).
macro bind(def, element)
    quote
        local el = $(esc(element))
        global $(esc(def)) = Core.applicable(Base.get, el) ? Base.get(el) : missing
        el
    end
end

# ╔═╡ 38ad5806-f5c2-11eb-1a4b-757cb20b199c
begin
	using Plots
	using PlutoUI
	using LinearAlgebra
	using DifferentialEquations
	using Statistics
	using CSV
	using DataFrames
end

# ╔═╡ a9dcf66c-00e1-11ec-2489-85a8bf50529f
Ns = 1:4;

# ╔═╡ e002f598-fcd6-11eb-0693-cd37b6731ddb
md"N $(@bind N Slider(Ns, show_value = true, default=2)) "

# ╔═╡ def9fb92-00e6-11ec-0ce0-8bf38dfba80b
dnis = range(0.0,stop=2*N,length=100);

# ╔═╡ e2864ca2-00eb-11ec-15af-13e2c905c2d9
md"De novo influx $(@bind dni Slider(dnis, show_value=true, default=0.0))"

# ╔═╡ edf4f43a-01c7-11ec-3f89-87267d95ba52
md"---
Produce Animations for R? $(@bind anims CheckBox(default=false))"

# ╔═╡ 634cae54-01c7-11ec-34df-9df3b4d9558d
md"---
Plot Equilibrium for all N? $(@bind plot_eq CheckBox(default=false))"

# ╔═╡ ff76b4b2-04e4-11ec-1e43-59b314d25a53
md"---"

# ╔═╡ c6b86160-04e5-11ec-050c-711567fe7ca8
csvN = [
	CSV.File("DataInput/1Gene_dni_eq_mutationload_prevalence.csv"),
	CSV.File("DataInput/2Genes_dni_eq_mutationload_prevalence.csv")
	]

# ╔═╡ 5ca4273e-01c8-11ec-078a-5798323bc39d
md"---"

# ╔═╡ b1a05bb4-00f0-11ec-1a54-13b82c896a6c
begin
	function plot_dni_bar(dni,dnis)
			p =plot(
				yaxis=false,
				legend=false,
				ylim=(0,2),
				ticks=false,
				grid=false,
				showaxis=false,
				xlabel="De novo influx"
			)

			plot!(p,dnis,fill(1.0,length(dnis)),color=:black)
			scatter!(p,[0.0,dnis[end]],[1.0,1.0],m = (1, :vline, 10),color=:black)
			scatter!(p,[dni],[1.35],m = (1, :vline, 7),color=:black)

			scatter!(p,[dni],[1.0],m = (1, :red, 12))

			annotate!(p,[
					(0,0.2,"0"),
					(dnis[end],0.2,"$(ceil(Int,dnis[end]))"),
					(dni,1.8,"$(round(dni,digits=2))")
					])

			return p
	end

	function plot_dni_bar(i)
			p =plot(
				yaxis=false,
				legend=false,
				ylim=(0,2),
				ticks=false,
				grid=false,
				showaxis=false,
				xlabel="De novo influx"
			)
			#black line
			plot!(p,range(0.0,stop=1.0,length=100),fill(1.0,100),color=:black)
			#start and end bar
			scatter!(p,[0.0,1.0],[1.0,1.0],m = (1, :vline, 10),color=:black)
			#red dot
			scatter!(p,[i/100],[1.0],m = (1, :red, 12))

			annotate!(p,[
					(0.0,0.2,"0"),
					(1.0,0.2,"2N")
					])

			return p
	end
end

# ╔═╡ 41c242fe-ff58-11eb-01b5-81fac3c399cd
begin
	L_guess(dni,N) = (2^N*dni)^(1/2)
	I_guess(dni,N) = dni/(2^N)
end

# ╔═╡ 18afc95a-fcca-11eb-2c88-792999cb5897
function R(μ)
	ν = 1-μ
	return [
		ν^2 ν^2/2 (ν^2)/4
		2*μ*ν (μ*ν+ν/2) (μ*ν/2+ν/2)
		μ^2 ((μ^2)/2+μ/2) ((μ^2)/4+μ/2+1/4)
	]
end

# ╔═╡ a445432e-fce7-11eb-33f3-b71379b6eddb
begin
	#Number of possible matings
	number_of_columns(N) = 2^(N-1) * (2^N + 1)
	#Numbere of all Configurations
	number_of_rows(N) = 3^N
end

# ╔═╡ c4fdb038-00f7-11ec-3011-c9183ec5fe36
function plot_histogram(r,N,fbins,ymax,xmax)
		h = histogram(
			vcat([r[i,:] for i ∈ 1:size(r)[1]]...),
			bins=range(
				0.0,
				stop=1,
				length=ceil(Integer,number_of_columns(N)*number_of_rows(N)*fbins)
				),
			ylim=(0,ymax),
			xlim=(0,xmax),
			ylabel = "Number of Outcomes",
			xlabel = "Probability of particular outcome",
			legend = false,
			title="N=$N"
			)
end

# ╔═╡ 73f9e942-01cc-11ec-3482-d58071c89d6e
begin
	LoadN(x,w) = sum(x.*w)
	LoadN_healthy(x,w,h) = sum(x.*w.*h)
	LoadN_ill(x,w,h) = sum(x.*w.*abs.(h.-1))
	PrevN(x,h) = 1-sum(x.*h)
end

# ╔═╡ 5e6f439c-fe8e-11eb-1e33-2f7be0eaadff
begin
	ham_weight(bitstring) = sum( c == '0' for c ∈ bitstring)
	Zeros(N) = ham_weight.([string(i,base=2,pad=N) for i ∈ 0:2^N-1])
end

# ╔═╡ 71df4b56-fe73-11eb-3559-55a35d29f37c
begin
	Prev(x) = 1-sum(x)

	Load(x,N,z) = 2*N - sum(z[i]*x[i] for i ∈ 1:2^N)

	function Load(x)
		N = Int(log(2,size(x,1)))
		z = Zeros(N)
		return Load(x,N,z)
	end
end

# ╔═╡ 95801cc2-ff37-11eb-28c2-b16f7958283a
function limit(arr,acc=10^(-3))
	last = length(arr)
	i = findlast([abs(arr[i-1]-arr[i]) > acc for i in 2:last])
	isnothing(i) ? (return arr[end]) : (return mean(view(arr,i:last)))
end

# ╔═╡ c0d9a06c-fe78-11eb-3776-1723db5d3551
mutation_rate(dni,N)=dni/(2*N)

# ╔═╡ 6b6402f6-fcde-11eb-0a18-63cc8c83fae8
begin
	function convert_index_to_number(i,j,m)
		# m = 2^N the Number healty configurations
		return Int((m/2)*(m+1)-1/2*(m-i)*(m-i+1)-(m-j))
	end
	convert_index_to_number((i,j),m) = convert_index_to_number(i,j,m)
end

# ╔═╡ 8e4d6f14-fdef-11eb-1e04-278b64849bff
function diff_eq(x,hR,t)
	m = size(x,1) #equals 2^N
	Σ = sum(x)^2
	return [
			sum(
				sum(
					(x[i]*x[j]/Σ)*hR[k,convert_index_to_number(i,j,m)]
				for j ∈ 1:m)
			for i ∈ 1:m)
		for k in 1:m] .- x
end

# ╔═╡ 670bcc9c-01d0-11ec-16a2-417c2d8d1924
function diff_eq_all(x,RHImn,t)
	r,H,I,m,n = RHImn
	Z = 1/(sum(x .* H)^2)
	return [
			Z * sum( H[i] &&
				sum( H[j] &&
					x[i]*x[j]*r[k,convert_index_to_number(I[i],I[j],n)]
				for j ∈ i:m)
			for i ∈ 1:m)
		for k in 1:m] .- x
end

# ╔═╡ 27cbec3a-01d3-11ec-01c1-a7495311e4af
index_in_healthy_only(i,H) = sum(view(H,1:i))

# ╔═╡ f7c16cac-fcde-11eb-1a1e-37cbc0e31289
function convert_number_to_index(n,N)
	#Number of healthy configurations
	M = 2^N
	#Number of possible matings
	N = number_of_rows(N)
	acc = 0
	for (i,m) ∈ enumerate(M:-1:1)
		n <= m + acc ? (return Int(i),Int(n-acc+i-1)) : acc += m
	end
	return Int(N), Int(N)
end

# ╔═╡ abb776ea-00cf-11ec-3d9a-dbb357f9883e
begin
	bit_string(i,N) = string(i,base=2,pad=N)
	ter_string(i,N) = string(i,base=3,pad=N)
	convert_index_to_bin_string(i,j,N) = "[" * bit_string(i-1,N) * "]x[" *  bit_string(j-1,N) * "]"
	convert_index_to_bin_string((i,j),N) = convert_index_to_bin_string(i,j,N)

	xticks_heatmap(N) = (1:number_of_columns(N),convert_index_to_bin_string.(
		[convert_number_to_index(i,N) for i in 1:number_of_columns(N)]
		,N))
	yticks_heatmap(N) = (1:number_of_rows(N),reverse(["[" * ter_string(i-1,N) * "]" for i in 1:number_of_rows(N)]))
end

# ╔═╡ 0eb45f48-ff58-11eb-2704-4f5dad08241b
begin
	plot_heatmap(r,N,ticks::Bool,dni,cmax) = heatmap(
		reverse(r,dims=1),
		color = :thermal,
		xticks = (ticks ? xticks_heatmap(N) : false),
		yticks = (ticks ? yticks_heatmap(N) : false),
		xmirror = true,
		clims = (0.0,cmax),
		title="N=$N"
		)

	function plot_heatmap(r,N,dni,dnis,cmax=1.0)
		plot(
			(N < 3 ? plot_heatmap(r,N,true,dni,cmax) : plot_heatmap(r,N,false,dni,cmax)),
			plot_dni_bar(dni,dnis),
			layout = grid(2, 1, heights=[0.79,0.2]),
			size=(700,500)
			)
	end
end

# ╔═╡ bedb15aa-fced-11eb-0f8c-6b0f1063b26f
begin
	get_binary_digit(num,digit) = floor(Int,mod(num/(2^(digit-1)),2))
	get_ternary_digit(num,digit) = floor(Int,mod(num/(3^(digit-1)),3))
	get_Nary_digit(num,digit,N) = floor(Int,mod(num/(N^(digit-1)),N))
end

# ╔═╡ 685cf83e-fce7-11eb-38ee-cb456fdbc26d
function generate_R(r,N)
	n, m = number_of_rows(N), number_of_columns(N)
	R = Matrix(undef, n, m)
	for col in 1:m
		i,j = convert_number_to_index(col,N)
		binsum = [get_binary_digit(i-1,k) + get_binary_digit(j-1,k) + 1 for k in 1:N]
		for row in 1:n
			tercol = [get_ternary_digit(row-1,k) + 1 for k in 1:N]
			R[row,col] = prod(r[a,b] for (a,b) in zip(tercol,binsum))
		end
	end
	return R
end

# ╔═╡ f3d2bb1c-00d0-11ec-3fc6-b7db47f9232e
R_all(N) = [generate_R(R(mutation_rate(dni,N)),N) for dni in range(0.0,stop=2*N,length=100)]

# ╔═╡ b1cb8c58-00e1-11ec-060f-7bc5f20723c6
All_R = [R_all(n) for n ∈ Ns];

# ╔═╡ 45ee92e0-00ee-11ec-2060-c791823a5884
let
	if anims
		anim = @animate for dni ∈ dnis

			r = All_R[N][round(Integer,dni*(length(dnis)-1)/(2*N) + 1)]

			plot(
				plot_histogram(r,N,0.1,1000,0.5),
				plot_dni_bar(dni,dnis),
				layout=grid(2, 1, heights=[0.79,0.2]),
				size=(700,500)
			)

		end
		gif(anim, "PlotOutput/MatingGridHist_N$N.gif", fps = 15)
	end
end

# ╔═╡ 478f641c-00ec-11ec-1f4a-cd703ab756d6
let
	if anims
		anim = @animate for dni ∈ dnis
			plot_heatmap(
				All_R[N][round(Integer,dni*(length(dnis)-1)/(2*N) + 1)],
				N,
				dni,
				dnis,
				2.0^(min(2-N,0))
			)
		end
		gif(anim, "PlotOutput/MatingGrid_N$N.gif", fps = 15)
	end
end

# ╔═╡ df0f60ec-fdf1-11eb-23e0-9f2747d9d223
begin
	ternary_list(N) = reverse.(Iterators.product(fill(0:2,N)...))[:]
	not_ill(tup) = 2 ∉ tup
	healthy_config_positions(N) = [not_ill(num) for num in ternary_list(N)]
end

# ╔═╡ acdef9b4-fdf3-11eb-0aaa-6de346bde1cd
function only_healthy(R,N)
	P = Matrix{Float64}(undef,2^N,number_of_columns(N))
	H = healthy_config_positions(N)
	j = 1
	for i ∈ 1:number_of_rows(N)
		if H[i]
			P[j,:] = R[i,:]
			j += 1
		end
	end
	return P
end

# ╔═╡ 7d72ff6e-03f4-11ec-1b98-8f66c650f673
parameter(r,N) = [
	r,
	healthy_config_positions(N),
	cumsum(healthy_config_positions(N)),
	3^N,
	2^N
]

# ╔═╡ 6811d1c2-fe6a-11eb-05f8-151a60d2bd0a
begin
	r = All_R[N][round(Integer,dni*(length(dnis)-1)/(2*N) + 1)]

	x₀ = zeros(3^N)
	x₀[1] = 0.99
	x₀[2] = 0.01
	tspan = (0.0,25.0)
	H = healthy_config_positions(N)

	prob = ODEProblem(diff_eq_all, x₀, tspan, parameter(r,N))
	sol = solve(prob)
end;

# ╔═╡ e2278904-37e3-11ec-07e6-578d2e0e155c
begin
	plot(sol,label=["X⁰" "X¹" "X²"])
	savefig("PlotOutput/OneSimulation_N=1_mu=025.pdf")
end

# ╔═╡ 19aeceb6-0bcd-11ec-2237-a19898d1df26
plot([[u[k] for u in sol.u] for k in 1:length(sol.u[1])])

# ╔═╡ 2dd78c3a-00e6-11ec-33a2-07189bcd1803
plot_heatmap(r,N,dni,dnis)

# ╔═╡ a01907ac-03ee-11ec-3f15-81f0a341a1bb
begin
	char_to_int(c) = Int(c)-48
	string_to_int(s) = sum(char_to_int(c) for c ∈ s)
	Load_weights(N) = string_to_int.([string(i-1,base=3,pad=N) for i=1:3^N])
end

# ╔═╡ 91604328-ff38-11eb-0441-595f7d6f456f
begin
	if plot_eq
		eq_Load = Matrix{Float64}(undef,length(Ns),100)
		eq_Load_ill = Matrix{Float64}(undef,length(Ns),100)
		eq_Prev = Matrix{Float64}(undef,length(Ns),100)
		Sol = Matrix{Any}(undef,length(Ns),100)

		for (col,N) ∈ enumerate(Ns)

			dnis = range(0.0,stop=2*N,length=100)
			H = healthy_config_positions(N)
			W = Load_weights(N)

			for (row,dni) in enumerate(dnis)

				r = All_R[N][round(Integer,(dni*99)/(2*N) + 1)]

				x₀ = zeros(3^N)
				x₀[1] = 0.99
				x₀[2] = 0.01
				tspan = (0.0,100.0)

				prob = ODEProblem(diff_eq_all, x₀, tspan, parameter(r,N))
				sol = solve(prob)

				Sol[col,row] = sol

				eq_Load[col,row] = limit(
					map(x->LoadN(x,W),sol.u)
				)
				eq_Load_ill[col,row] = limit(
					map(x->LoadN_ill(x,W,H),sol.u)
				)
				eq_Prev[col,row] = limit(
					map(x->PrevN(x,H),sol.u)
				)
			end
		end
	end
end;

# ╔═╡ d1a88f76-1176-11ec-2a61-8d9ea1b23669
S = [[limit([sol.u[i][j] for i in 1:length(sol)]) for j in 1:2] for sol in Sol[1,:]]

# ╔═╡ b519decc-153a-11ec-1969-3548bc3f7c2e
begin
	scatter([S[i][1] for i ∈ 1:length(S)],[S[i][2] for i ∈ 1:length(S)],legend=false,xlabel="X",ylabel="Y")
end

# ╔═╡ cd36088a-ff54-11eb-286c-d580e2400678
begin
	if plot_eq
		p = plot(range(0.0,stop=2*N,length=100),[eq_Load[N,:] .- eq_Load_ill[N,:], eq_Load_ill[N,:]],label=["Eqilibrium Mutation Load (healthy)" "Equilibrium Mutation Load (ill)"], legend=:topleft, xlabel="De novo influx",framestyle = :zerolines,title="N=$N")

#		if N <= 2
#			plot!(p,
#				csvN[N].dni,
#				[csvN[N].mut,csvN[N].prev],
#				label=["Mutation Load" "Prevalence"]
#			)
#		end
		savefig(p,"PlotOutput/LoadIll_Eq_N=$N.pdf")
		p
	end
end

# ╔═╡ 7ebab978-0029-11ec-3df4-830eaeff284e
let
	if plot_eq
		p = plot(legend=:bottomright,
			xlabel="De novo influx",
			framestyle = :zerolines,
			title="Eqilibrium Mutation Load"
		)

		for n in Ns

			plot!(p,
				range(0.0,stop=2*n,length=100),
				eq_Load[n,:],
				label="N=$n",
			)
		end

		line = 0.0:0.1:2*Ns[end]
		plot!(p,line,line,linestyle=:dash,color=:black,label="")

		savefig("PlotOutput/Eq_Mut_Load.pdf")

		p
	end
end

# ╔═╡ df9ca870-0029-11ec-1dfb-4f48880a6369
let
	if plot_eq
		p = plot(legend=:bottomright,
			xlabel="De novo influx",
			framestyle = :zerolines,
			title="Eqilibrium Prevalence"
		)

		for n in Ns

			plot!(p,
				range(0.0,stop=2*n,length=100),
				eq_Prev[n,:],
				label="N=$n",
			)
		end

		savefig("PlotOutput/Eq_Prev.pdf")

		p
	end
end

# ╔═╡ 9d10a26e-0413-11ec-2c72-cd5cc8eb0a0f
let
	cmax = 2.1 .^(- Ns .+ 1)

	anim = @animate for i ∈ 1:length(dnis)

		l = @layout [
			grid(1,length(Ns))
   	 		b{0.2h}
			]

		Hs = []

		for N ∈ Ns
			h = heatmap(
					reshape(reverse(Sol[N,i].u[end]),3^N,1),
					clim=(0,cmax[N]),
					axis = false,
					ticks = false,
					cbar = false
				)
			push!(Hs,h)
		end
		push!(Hs, plot_dni_bar(i))
		plot(Hs...,
			layout = l,
			size = (600,600),
			title=reshape(push!(["N=$N" for N ∈ Ns],""),1,length(Ns)+1)
			)
	end
	#gif(anim, "PlotOutput/DetailEvol_N=1,_,$(Ns[end]).gif", fps = 15)
end

# ╔═╡ 118c8ac8-fe6e-11eb-3ca8-8f13b3870c0d
let

	H = healthy_config_positions(N)
	H̄ = 1 .- H
	W = Load_weights(N)

	plot(
		sol.t,[
			map(x->LoadN(x,W), sol.u),
			map(x->LoadN(x .* H,W), sol.u),
			map(x->LoadN(x .* H̄,W), sol.u)
			#map(x->PrevN(x,healthy_config_positions(N)), sol.u)
			],
		label=["Total Mutation Load" "Load of Healthy Subpopulation" "Load of Ill Subpopulation"
		]
	)
	#hline!([limit(Load.(sol.u)),limit(Prev.(sol.u))])
end

# ╔═╡ 4176c240-03fe-11ec-3652-41d3308d1ebb
let
	Ns = 1:10
	ps=[]

	for N in Ns
		p = heatmap(
				reshape(reverse(healthy_config_positions(N)),3^N,1),
				c=cgrad([:black, :lightgray]),
				axis=false,
				ticks=false,
				cbar=false
				)
		push!(ps,p)
	end

	plot(ps...,
		layout = (1,Ns[end]),
		title=reshape(["$N" for N ∈ Ns],1,length(Ns)),
		size=(2400,1800)
		)

	savefig("PlotOutput/HealthyConfigPositionN=1,_,10.png")
end

# ╔═╡ 4b064d90-0650-11ec-1348-69242b2b875c
let
	Ns = 1:20
	q(n) = 1-(2^n)/(3^n)
	plot(Ns,q.(Ns))
end

# ╔═╡ Cell order:
# ╠═a9dcf66c-00e1-11ec-2489-85a8bf50529f
# ╠═def9fb92-00e6-11ec-0ce0-8bf38dfba80b
# ╠═b1cb8c58-00e1-11ec-060f-7bc5f20723c6
# ╠═6811d1c2-fe6a-11eb-05f8-151a60d2bd0a
# ╠═e2278904-37e3-11ec-07e6-578d2e0e155c
# ╠═91604328-ff38-11eb-0441-595f7d6f456f
# ╠═d1a88f76-1176-11ec-2a61-8d9ea1b23669
# ╠═b519decc-153a-11ec-1969-3548bc3f7c2e
# ╟─e002f598-fcd6-11eb-0693-cd37b6731ddb
# ╟─e2864ca2-00eb-11ec-15af-13e2c905c2d9
# ╠═118c8ac8-fe6e-11eb-3ca8-8f13b3870c0d
# ╠═19aeceb6-0bcd-11ec-2237-a19898d1df26
# ╟─2dd78c3a-00e6-11ec-33a2-07189bcd1803
# ╟─edf4f43a-01c7-11ec-3f89-87267d95ba52
# ╟─45ee92e0-00ee-11ec-2060-c791823a5884
# ╟─478f641c-00ec-11ec-1f4a-cd703ab756d6
# ╟─634cae54-01c7-11ec-34df-9df3b4d9558d
# ╠═cd36088a-ff54-11eb-286c-d580e2400678
# ╟─7ebab978-0029-11ec-3df4-830eaeff284e
# ╟─df9ca870-0029-11ec-1dfb-4f48880a6369
# ╟─9d10a26e-0413-11ec-2c72-cd5cc8eb0a0f
# ╟─ff76b4b2-04e4-11ec-1e43-59b314d25a53
# ╠═c6b86160-04e5-11ec-050c-711567fe7ca8
# ╟─5ca4273e-01c8-11ec-078a-5798323bc39d
# ╟─0eb45f48-ff58-11eb-2704-4f5dad08241b
# ╟─c4fdb038-00f7-11ec-3011-c9183ec5fe36
# ╠═b1a05bb4-00f0-11ec-1a54-13b82c896a6c
# ╟─41c242fe-ff58-11eb-01b5-81fac3c399cd
# ╠═18afc95a-fcca-11eb-2c88-792999cb5897
# ╟─abb776ea-00cf-11ec-3d9a-dbb357f9883e
# ╟─a445432e-fce7-11eb-33f3-b71379b6eddb
# ╠═685cf83e-fce7-11eb-38ee-cb456fdbc26d
# ╠═f3d2bb1c-00d0-11ec-3fc6-b7db47f9232e
# ╟─acdef9b4-fdf3-11eb-0aaa-6de346bde1cd
# ╟─8e4d6f14-fdef-11eb-1e04-278b64849bff
# ╠═670bcc9c-01d0-11ec-16a2-417c2d8d1924
# ╟─7d72ff6e-03f4-11ec-1b98-8f66c650f673
# ╟─71df4b56-fe73-11eb-3559-55a35d29f37c
# ╠═73f9e942-01cc-11ec-3482-d58071c89d6e
# ╟─5e6f439c-fe8e-11eb-1e33-2f7be0eaadff
# ╠═95801cc2-ff37-11eb-28c2-b16f7958283a
# ╠═c0d9a06c-fe78-11eb-3776-1723db5d3551
# ╟─6b6402f6-fcde-11eb-0a18-63cc8c83fae8
# ╟─27cbec3a-01d3-11ec-01c1-a7495311e4af
# ╠═f7c16cac-fcde-11eb-1a1e-37cbc0e31289
# ╟─bedb15aa-fced-11eb-0f8c-6b0f1063b26f
# ╟─df0f60ec-fdf1-11eb-23e0-9f2747d9d223
# ╟─a01907ac-03ee-11ec-3f15-81f0a341a1bb
# ╠═4176c240-03fe-11ec-3652-41d3308d1ebb
# ╠═4b064d90-0650-11ec-1348-69242b2b875c
# ╠═38ad5806-f5c2-11eb-1a4b-757cb20b199c

max_stars_repo_name: roccminton/PlutoNotebooks

max_issues_repo_name: roccminton/PlutoNotebooks

max_forks_repo_name: roccminton/PlutoNotebooks


text:
abstract type Canvas <: GraphicsArea end

origin(c::Canvas) = (origin_x(c), origin_y(c))
Base.size(c::Canvas) = (width(c), height(c))
pixel_size(c::Canvas) = (pixel_width(c), pixel_height(c))

pixel!(c::Canvas, pixel_x::Integer, pixel_y::Integer; color::UserColorType = :normal) = pixel!(c, pixel_x, pixel_y, color)

function points!(c::Canvas, x::Number, y::Number, color::UserColorType)
    origin_x(c) <= (xs = fscale(x, c.xscale)) <= origin_x(c) + width(c) || return c
    origin_y(c) <= (ys = fscale(y, c.yscale)) <= origin_y(c) + height(c) || return c
    pixel_x = (xs - origin_x(c)) / width(c) * pixel_width(c)
    pixel_y = pixel_height(c) - (ys - origin_y(c)) / height(c) * pixel_height(c)
    pixel!(c, floor(Int, pixel_x), floor(Int, pixel_y), color)
end

points!(c::Canvas, x::Number, y::Number; color::UserColorType = :normal) = points!(c, x, y, color)

function points!(c::Canvas, X::AbstractVector, Y::AbstractVector, color::UserColorType)
    length(X) == length(Y) || throw(DimensionMismatch("X and Y must be the same length"))
    for I in eachindex(X, Y)
        points!(c, X[I], Y[I], color)
    end
    c
end

function points!(c::Canvas, X::AbstractVector, Y::AbstractVector, color::AbstractVector{T}) where {T <: UserColorType}
    (length(X) == length(color) && length(X) == length(Y)) || throw(DimensionMismatch("X, Y, and color must be the same length"))
    for i in 1:length(X)
        points!(c, X[i], Y[i], color[i])
    end
    c
end

points!(c::Canvas, X::AbstractVector, Y::AbstractVector; color::UserColorType = :normal) = points!(c, X, Y, color)

# Implementation of the digital differential analyser (DDA)
function lines!(c::Canvas, x1::Number, y1::Number, x2::Number, y2::Number, color::UserColorType)
    x1 = fscale(x1, c.xscale)
    x2 = fscale(x2, c.xscale)
    y1 = fscale(y1, c.yscale)
    y2 = fscale(y2, c.yscale)

    mx = origin_x(c)
    Mx = origin_x(c) + width(c)
    (x1 < mx && x2 < mx) || (x1 > Mx && x2 > Mx) && return c

    my = origin_y(c)
    My = origin_y(c) + height(c)
    (y1 < my && y2 < my) || (y1 > My && y2 > My) && return c

    x2p(x) = (x - mx) / width(c) * pixel_width(c)
    y2p(y) = pixel_height(c) - (y - my) / height(c) * pixel_height(c)

    Δx = x2p(x2) - (cur_x = x2p(x1))
    Δy = y2p(y2) - (cur_y = y2p(y1))

    nsteps = abs(Δx) > abs(Δy) ? abs(Δx) : abs(Δy)
    nsteps = min(nsteps, typemax(Int32))  # hard limit

    δx = Δx / nsteps
    δy = Δy / nsteps

    px, Px = extrema([x2p(mx), x2p(Mx)])
    py, Py = extrema([y2p(my), y2p(My)])

    pixel!(c, floor(Int, cur_x), floor(Int, cur_y), color)
    max_num_iter = typemax(Int16)  # performance limit
    for _ = if nsteps > max_num_iter
        range(1, stop=nsteps, length=max_num_iter)
    else
        range(1, stop=nsteps, step=1)
    end
        cur_x += δx
        cur_y += δy
        (cur_y < py || cur_y > Py) && continue
        (cur_x < px || cur_x > Px) && continue
        pixel!(c, floor(Int, cur_x), floor(Int, cur_y), color)
    end
    c
end

lines!(c::Canvas, x1::Number, y1::Number, x2::Number, y2::Number; color::UserColorType = :normal) = lines!(c, x1, y1, x2, y2, color)

function lines!(c::Canvas, X::AbstractVector, Y::AbstractVector, color::UserColorType)
    length(X) == length(Y) || throw(DimensionMismatch("X and Y must be the same length"))
    for i in 1:(length(X)-1)
        if !(isfinite(X[i]) && isfinite(X[i+1]) && isfinite(Y[i]) && isfinite(Y[i+1]))
            continue
        end
        lines!(c, X[i], Y[i], X[i+1], Y[i+1], color)
    end
    c
end

lines!(c::Canvas, X::AbstractVector, Y::AbstractVector; color::UserColorType = :normal) = lines!(c, X, Y, color)

function get_canvas_dimensions_for_matrix(
    canvas::Type{T}, nrow::Int, ncol::Int, maxwidth::Int, maxheight::Int, width::Int, height::Int, margin::Int, padding::Int, out_stream::Union{Nothing,IO};
    extra_rows::Int = 0, extra_cols::Int = 0
) where {T <: Canvas}
    min_canvheight = ceil(Int, nrow / y_pixel_per_char(T))
    min_canvwidth  = ceil(Int, ncol / x_pixel_per_char(T))
    aspect_ratio = min_canvwidth / min_canvheight
    height_diff = extra_rows
    width_diff  = margin + padding + length(string(ncol)) + extra_cols

    term_height, term_width = out_stream === nothing ? displaysize() : displaysize(out_stream)
    maxheight = maxheight > 0 ? maxheight : term_height - height_diff
    maxwidth  = maxwidth > 0 ? maxwidth : term_width - width_diff

    if nrow == 0 && ncol == 0
        return (0, 0, maxwidth, maxheight)
    end

    # Check if the size of the plot should be derived from the matrix
    # Note: if both width and height are 0, it means that there are no
    #       constraints and the plot should resemble the structure of
    #       the matrix as close as possible
    if width == 0 && height == 0
        # If the interactive code did not take care of this then try
        # to plot the matrix in the correct aspect ratio (within specified bounds)
        if min_canvheight > min_canvwidth
            # long matrix (according to pixel density)
            height = min_canvheight
            width  = height * aspect_ratio
            if width > maxwidth
                width  = maxwidth
                height = width / aspect_ratio
            end
            if height > maxheight
                height = maxheight
                width  = min(height * aspect_ratio, maxwidth)
            end
        else
            # wide matrix
            width  = min_canvwidth
            height = width / aspect_ratio
            if height > maxheight
                height = maxheight
                width  = height * aspect_ratio
            end
            if width > maxwidth
                width = maxwidth
                height = min(width / aspect_ratio, maxheight)
            end
        end
    end
    if width == 0 && height > 0
        width  = min(height * aspect_ratio, maxwidth)
    elseif width > 0 && height == 0
        height = min(width / aspect_ratio, maxheight)
    end
    width  = round(Int, width)
    height = round(Int, height)

    (width, height, maxwidth, maxheight)
end


text:
struct FaST    <: MethodType
    α::Float64
    β::Float64
    γ::Float64

    local_weights::Vector{Float64}
    compute_weight_sum::Bool
end

function FaST(α::Float64, β::Float64, γ::Float64, compute_weight_sum::Bool)
    local_weights = Vector{Float64}(undef, 400)

    @simd for pos in 1:400
        @inbounds local_weights[pos] = max(pos^-α, 1.0e-100)
    end

    return FaST(α, β, γ, local_weights, compute_weight_sum)
end

@inline computeDocFreq(method::FaST, docFreq) = @. max(exp(-method.β * (docFreq.doc_freq / docFreq.nDocs) * 100.0), 1.0e-100)

@inline function frame_weight(method::FaST, pos, doc_freq)
    @inbounds return method.local_weights[pos] * doc_freq
end

gap_score(method::FaST, pos, doc_freq) = -1.0 * frame_weight(method, pos, doc_freq)
match_score(method::FaST, pos1, pos2, doc_freq, qw, cw) = (qw + cw) * exp(-method.γ * abs(pos1 - pos2))

@inline function sum_weight_positions(method::FaST, positions, start_idx, doc_freq)
    sum_fw = 0.0

    @inbounds for idx=start_idx:length(positions)
        sum_fw += frame_weight(method, positions[idx], doc_freq)
    end

    return sum_fw
end

function similarity(method::FaST, query::Vector{Pair{UInt32, Vector{Int16}}}, candidate::Vector{Pair{UInt32, Vector{Int16}}}, df_vec::Vector{Float64})
    q_idx = 1
    c_idx = 1

    sim = 0.0
    den = 0.0

    q_len = length(query) + 1
    c_len = length(candidate) + 1

    @inbounds while q_idx != q_len && c_idx != c_len
        q_func_id, q_positions = query[q_idx]
        c_func_id, c_positions = candidate[c_idx]

        if q_func_id == c_func_id
            # Query and candidate contain the same function. Align positions starting from the left
            doc_freq = df_vec[q_func_id]

            if length(q_positions) < length(c_positions)
                smallest_vec = q_positions
                longest_vec = c_positions
            else
                smallest_vec = c_positions
                longest_vec = q_positions
            end

            for j=1:length(smallest_vec)
                q_pos = q_positions[j]
                c_pos = c_positions[j]

                q_fw = frame_weight(method, q_pos, doc_freq)
                c_fw = frame_weight(method, c_pos, doc_freq)

                sim +=  match_score(method::FaST, q_pos, c_pos, doc_freq, q_fw, c_fw)
                den += (q_fw + c_fw)
                j+=1
            end

            sum_fw = sum_weight_positions(method, longest_vec, length(smallest_vec) + 1, doc_freq)
            sim -= sum_fw
            den += sum_fw

            q_idx +=1
            c_idx +=1
        else
            if q_func_id > c_func_id
                # c_func_id does not exist in the query
                cur_positions = c_positions
                doc_freq = df_vec[c_func_id]
                c_idx += 1
            else
                # q_func_id does not exist in the candidate
                cur_positions = q_positions
                doc_freq = df_vec[q_func_id]
                q_idx += 1
            end

            # Align to gaps to all positions
            sum_fw = sum_weight_positions(method, cur_positions, 1, doc_freq)
            sim -= sum_fw
            den += sum_fw
        end
    end

    @inbounds for j=q_idx:length(query)
        func_id, positions = query[j]
        doc_freq = df_vec[func_id]

        sum_fw = sum_weight_positions(method, positions, 1, doc_freq)
        sim -= sum_fw
        den += sum_fw
    end

    @inbounds for j=c_idx:length(candidate)
        func_id, positions = candidate[j]
        doc_freq = df_vec[func_id]

        sum_fw = sum_weight_positions(method, positions, 1, doc_freq)
        sim -= sum_fw
        den += sum_fw
    end

    return sim/den
end

@inline function sum_frame_weights(method::FaST, report::Report, df_vec::Vector{Float64})
    sum = 0.0

    for stack in report.stacks
        for (pos, func_id) in enumerate(stack)
            @inbounds sum += frame_weight(method, pos, df_vec[func_id])
        end
    end

    return sum
end

@inline function compute_final_similarity!(partial_similarities::Vector{Float64}, method::FaST, query::Report, candidates::Vector{Report}, df_vec::Vector{Float64})
    if method.compute_weight_sum
        q_weight_sum = sum_frame_weights(method, query, df_vec)

        Threads.@threads for idx in eachindex(partial_similarities)
            @inbounds sim = partial_similarities[idx]

            if sim == 0.0
                @inbounds partial_similarities[idx] = -1.0
            else
                @inbounds weight_sum = q_weight_sum + sum_frame_weights(method, candidates[idx], df_vec)

                # Correct similarities and then normalize it
                @inbounds partial_similarities[idx] = (sim - weight_sum) / weight_sum
            end
        end
    else
        q_weight_sum = query.stats.weight_sum

        for idx in eachindex(partial_similarities)
            @inbounds sim = partial_similarities[idx]

            if sim == 0.0
                @inbounds partial_similarities[idx] = -1.0
            else
                @inbounds weight_sum = q_weight_sum + candidates[idx].stats.weight_sum

                # Correct similarities and then normalize it
                @inbounds partial_similarities[idx] = (sim - weight_sum) / weight_sum
            end
        end
    end

    return partial_similarities
end

max_stars_repo_name: irving-muller/FaST

max_issues_repo_name: irving-muller/FaST

max_forks_repo_name: irving-muller/FaST


text:
mutable struct kvh_raw_imu_t <: LCMType
    utime::Int64
    packet_count::Int64
    delta_rotation::SVector{3, Float64}
    linear_acceleration::SVector{3, Float64}
end

@lcmtypesetup(kvh_raw_imu_t)


text:
# This file contains code that is conditionally evaluated in the IJulia modue.
# It provides an alternate "modal" handler functions.
# These handler functions read global state in the variable current_mode[] to
# execute conditionally small parts of code that are specific to DSLs (and Julia)
#
# To edit the code here, comment out the first line quoting the function or
# set of functions that you want to edit. This allows emacs to do normal indentation. Then uncomment
# these lines when finished editing.

# The code to insert in IJulia is contained in several quoted expressions.
# Here, we evaluate each of them in the IJulia module. We must hide the module
# name IJulia from the package manager.
function load_ijulia_handlers()
    themodule = eval(:(Main.IJulia))
    for code in (manage_handler_code, execute_request_code, complete_request_code)
        Core.eval(themodule, code)
    end
end

# This code defines the struct whose fields are functions that alter user
# input and the result data. An instance of this struct is created for each
# "mode" (overused word), i.e. Julia mode, Symata mode. The default mode,
# for Julia, is created here, as well as code to switch between modes and
# to install these alternative handlers.
manage_handler_code = quote
# fields are functions mapping strings to strings
struct JupyterMode
    modename::Symbol
    code_hook     # function that alters user input `code`
    helpcode_hook # function that alters user help request `hcode` (with '?' already stripped)
    output_hook   # function that alters reponse `result_data`.
    completion_hook # function to get completions
end

function completions_positions_julia_languge(codepart, inposition)
#    comps_, positions = REPLCompletions.completions(code[codestart:end], cursorpos-codestart+1)
    comps_, positions = REPLCompletions.completions(codepart, inposition)
    @static if isdefined(REPLCompletions, :completion_text)
        comps = REPLCompletions.completion_text.(comps_) # julia#26930
    else
        comps = comps_
    end
    return (comps, completions)
end

# default mode is plain-Julia mode.
const default_mode = JupyterMode(
    :julia,
    identity,   # code
    (hcode) -> Core.eval(Main, REPL.helpmode(hcode)),  # helpcode
    identity,  # output
    completions_positions_julia_languge
)

#  ijulia_modes contains all modes.
const ijulia_modes = Dict()

function install_ijulia_mode(modename::Symbol, mode::JupyterMode)
    ijulia_modes[modename] = mode
end

# plain-Julia mode
install_ijulia_mode(:julia, default_mode)

const current_language_mode = Ref(default_mode)

# Used to switch among modes
function set_ijulia_mode(modename::Symbol)
    if ! haskey(ijulia_modes, modename)
        throw(KeyError(modename))
    end
    current_language_mode[] = ijulia_modes[modename]
end

function get_current_ijulia_modename()
    return current_language_mode[].modename
end

# Set the handler. This is called from isymata.jl
function set_handler(handlername, handlerfunction)
    handlername_string = String(handlername)
    if ! haskey(handlers, handlername_string)
        throw(KeyError(handlername_string))
    end
    handlers[String(handlername)] = handlerfunction
end

end # quote manage_handler_code

execute_request_code = quote
function execute_request_modal(socket, msg)
    code = msg.content["code"]
    @vprintln("EXECUTING ", code)
    global execute_msg = msg
    global n, In, Out, ans
    stdio_bytes[] = 0
    silent = msg.content["silent"]
    store_history = get(msg.content, "store_history", !silent)
    empty!(execute_payloads)

    if !silent
        n += 1
        send_ipython(publish[],
                     msg_pub(msg, "execute_input",
                             Dict("execution_count" => n,
                                          "code" => code)))
    end

    silent = silent || REPL.ends_with_semicolon(code)
    if store_history
        In[n] = code
    end

    # "; ..." cells are interpreted as shell commands for run
    code = replace(code, r"^\s*;.*$" =>
                   m -> string(replace(m, r"^\s*;", "Base.repl_cmd(`"),
                               "`, ", stdout_name, ")"))

    # a cell beginning with "? ..." is interpreted as a help request
    hcode = replace(code, r"^\s*\?" => "")

    try
        for hook in preexecute_hooks
            invokelatest(hook)
        end

        ans = result = if hcode != code # help request
            current_language_mode[].helpcode_hook(hcode)
            result = nothing
        else
            #run the code!
            code = current_language_mode[].code_hook(code)
            occursin(magics_regex, code) ? magics_help(code) :
                include_string(current_module[], code, "In[$n]")
        end

        if silent
            result = nothing
        elseif result !== nothing
            if store_history
                Out[n] = result
            end
        end

        user_expressions = Dict()
        for (v,ex) in msg.content["user_expressions"]
            user_expressions[v] = invokelatest(parse, ex)
        end

        for hook in postexecute_hooks
            invokelatest(hook)
        end

        # flush pending stdio
        flush_all()

        undisplay(result) # dequeue if needed, since we display result in pyout
        invokelatest(display) # flush pending display requests

        if result !== nothing
            result_metadata = invokelatest(metadata, result)
            result_data = invokelatest(display_dict, current_language_mode[].output_hook(result))
            send_ipython(publish[],
                         msg_pub(msg, "execute_result",
                                 Dict("execution_count" => n,
                                              "metadata" => result_metadata,
                                              "data" => result_data)))

        end
        send_ipython(requests[],
                     msg_reply(msg, "execute_reply",
                               Dict("status" => "ok",
                                            "payload" => execute_payloads,
                                            "execution_count" => n,
                                            "user_expressions" => user_expressions)))
        empty!(execute_payloads)
    catch e
        bt = catch_backtrace()
        try
            # flush pending stdio
            flush_all()
            for hook in posterror_hooks
                invokelatest(hook)
            end
        catch
        end
        empty!(displayqueue) # discard pending display requests on an error
        content = error_content(e,bt)
        send_ipython(publish[], msg_pub(msg, "error", content))
        content["status"] = "error"
        content["execution_count"] = n
        send_ipython(requests[], msg_reply(msg, "execute_reply", content))
    end
end
end # quote execute_request_code

complete_request_code = quote
function complete_request_modal(socket, msg)
    code = msg.content["code"]
    cursor_chr = msg.content["cursor_pos"]
    cursorpos = chr2ind(msg, code, cursor_chr)
    if all(isspace, code[1:cursorpos])
        send_ipython(requests[], msg_reply(msg, "complete_reply",
                                 Dict("status" => "ok",
                                              "metadata" => Dict(),
                                              "matches" => String[],
                                              "cursor_start" => cursor_chr,
                                              "cursor_end" => cursor_chr)))
        return
    end

    codestart = find_parsestart(code, cursorpos)
    comps, positions = current_language_mode[].completion_hook(code[codestart:end], cursorpos-codestart+1)
    # comps_, positions = REPLCompletions.completions(code[codestart:end], cursorpos-codestart+1)
    # @static if isdefined(REPLCompletions, :completion_text)
    #     comps = REPLCompletions.completion_text.(comps_) # julia#26930
    # else
    #     comps = comps_
    # end

    # positions = positions .+ (codestart - 1) on Julia 0.7
    positions = (first(positions) + codestart - 1):(last(positions) + codestart - 1)
    metadata = Dict()
    if isempty(comps)
        # issue #530: REPLCompletions returns inconsistent results
        # for positions when no completions are found
        cursor_start = cursor_end = cursor_chr
    elseif isempty(positions) # true if comps to be inserted without replacement
        cursor_start = (cursor_end = ind2chr(msg, code, last(positions)))
    else
        cursor_start = ind2chr(msg, code, prevind(code, first(positions)))
        cursor_end = ind2chr(msg, code, last(positions))
        metadata["_jupyter_types_experimental"] = complete_types(comps)
    end
    send_ipython(requests[], msg_reply(msg, "complete_reply",
                                     Dict("status" => "ok",
                                                  "matches" => comps,
                                                  "metadata" => metadata,
                                                  "cursor_start" => cursor_start,
                                                  "cursor_end" => cursor_end)))
end

end # quote complete_request_code

nothing


text:
using Pkg

Pkg.add("Flux")

Pkg.add("MLDatasets")

using MLDatasets: BostonHousing

features = BostonHousing.features();

summary(features)
"13×506 Matrix{Float64}"

target = BostonHousing.targets();

using Flux

model = Dense(13,1)

model.weight

model.bias

target

features

using Flux: train!

Pkg.add("Printf")

using Printf

opt = Descent()

x_train = features[:,1:355]

x_test = features[:,356:506]

y_train = target[:,1:355]

y_test = target[:,356:506]

loss(x, y) = Flux.Losses.mse(model(x), y)

loss(x_train,y_train)

data = [(x_train,y_train)]

parameters = Flux.params(model)

# train!(loss, parameters, data, opt)

parameters

train!(loss, parameters, data, opt)

loss(x_train, y_train)

parameters

loss(x_test,y_test)

using BSON: @save

@save "mymodel.bson" model


text:
## General util TODO: Move to separate
type Counter
  X::Int64
end

GLOBAL_COUNTER = Counter(0)
inc(c::Counter) = c.X +=1
genint() = (inc(GLOBAL_COUNTER);GLOBAL_COUNTER.X-1)
restart_counter!() = GLOBAL_COUNTER.X = 0

isapprox(a, b; epsilon = DEFAULT_PREC) = abs(a - b) <= epsilon
≊ = isapprox
≊
## Arithmetic
## ==========
sqr{T <: Real}(x::T) = x * x

## =====================
## Probabilstic Utilities
rand_select(v::Vector) = v[rand(DiscreteUniform(1, length(v)))]
pnormalize{T <: Real}(v::Vector{T}) = (v/sum(v))::Vector{Float64}

## Type stuff
fields(X) = [getfield(X, field) for field in fieldnames(X)]

## Printing
fmt = "%.32f"
@eval dofmt(x) = @sprintf($fmt, x)


text:
using Flux: Dense

in_channel = 3
out_channel = 5
N = 4
adj = [0. 1. 0. 1.;
       1. 0. 1. 0.;
       0. 1. 0. 1.;
       1. 0. 1. 0.]

@testset "Test InnerProductDecoder layer" begin
   ipd = InnerProductDecoder(identity)
   Y = ipd(rand(1, N))
   @test size(Y) == (N, N)

   Y = ipd(rand(in_channel, N))
   @test size(Y) == (N, N)
end

@testset "Test VariationalEncoder layer" begin
    z_dim = 2
    gc = GCNConv(adj, in_channel=>out_channel)
    ve = VariationalEncoder(gc, out_channel, z_dim)
    X = rand(in_channel, N)
    Z = ve(X)
    @test size(Z) == (z_dim, N)
end

@testset "Test GAE model" begin
    gc = GCNConv(adj, in_channel=>out_channel)
    gae = GAE(gc)
    X = rand(in_channel, N)
    Y = gae(X)
    @test size(Y) == (N, N)
end

@testset "Test VGAE model" begin
    z_dim = 2
    gc = GCNConv(adj, in_channel=>out_channel)
    vgae = VGAE(gc, out_channel, z_dim)
    X = rand(in_channel, N)
    Y = vgae(X)
    @test size(Y) == (N, N)
end