<commit_before>/*
 * File:  complet.cpp
 * Copyright (C) 2008 The Institute for System Programming of the Russian Academy of Sciences (ISP RAS)
 *
 * This file implements some kind of tab-completion using readline facilities. It can be used either with libedit
 * or readline libraries or, in fact, any other library that respects the same completion mechanism.
 *
 */

#ifdef ENABLE_LIBEDIT

#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <readline.h>
#include "term_ile.h"

// table of chains, which contains all possible alternatives to match
#define MAX_CHAINS 32
const char *chain_table[][13][11] =
{
    {{"UPDATE", NULL}, {"insert", NULL}, {"@any", NULL}, {"into", "preceding", "following", NULL}, {NULL}},
    {{"UPDATE", NULL}, {"delete", "delete_undeep", NULL}, {NULL}},
    {{"UPDATE", NULL}, {"replace", NULL}, {"@any", NULL}, {"in", NULL}, {"@any", NULL}, {"with", NULL}, {"@any", NULL}, {NULL},},
    {{"UPDATE", NULL}, {"replace", NULL}, {"@any", NULL}, {"as", NULL}, {"@any", NULL}, {"in", NULL}, {"@any", NULL},
        {"with", NULL}, {NULL},},
    {{"UPDATE", NULL}, {"rename", NULL}, {"@any", NULL}, {"on", NULL}, {NULL}},
    {{"LOAD", NULL}, {"@file", NULL}, {NULL}},
    {{"LOAD", NULL}, {"STDIN", NULL}, {NULL}},
    {{"LOAD", "DROP", NULL}, {"MODULE", NULL}, {NULL}},
    {{"LOAD", NULL}, {"OR", NULL}, {"REPLACE", NULL}, {"MODULE", NULL}, {NULL}},
    {{"CREATE", "DROP", NULL}, {"DOCUMENT", NULL}, {"@any", NULL}, {"IN", NULL}, {"COLLECTION", NULL}, {NULL}},
    {{"CREATE", "DROP", NULL}, {"DOCUMENT", NULL}, {NULL}},
    {{"CREATE", "DROP", NULL}, {"COLLECTION", NULL}, {NULL}},
    {{"CREATE", NULL}, {"INDEX", NULL}, {"@any", NULL}, {"ON", NULL}, {"@any", NULL}, {"BY", NULL}, {"@any", NULL},
        {"AS", NULL}, {NULL}},
    {{"DROP", NULL}, {"USER", NULL}, {NULL}},
    {{"CREATE", "ALTER", NULL}, {"USER", NULL}, {"@any", NULL}, {"WITH", NULL}, {"PASSWORD", NULL}, {NULL},},
    {{"CREATE", NULL}, {"FULL-TEXT", NULL}, {"INDEX", NULL}, {"@any", NULL}, {"ON", NULL}, {"@any", NULL}, {"TYPE", NULL}, {NULL}},
    {{"CREATE", NULL}, {"TRIGGER", NULL}, {"@any", NULL}, {"BEFORE", "AFTER", NULL},
        {"INSERT", "DELETE", "REPLACE", NULL}, {"ON", NULL}, {"@any", NULL},
        {"FOR", NULL}, {"EACH", NULL}, {"NODE", "STATEMENT", NULL}, {"DO", NULL}, {NULL}},
    {{"CREATE", NULL}, {"ROLE", NULL}, {NULL}},
    {{"RENAME", NULL}, {"COLLECTION", NULL}, {"@any", NULL}, {"INTO", NULL}, {NULL}},
    {{"GRANT", NULL}, {"@any", NULL}, {"ON", NULL}, {"DOCUMENT", "COLLECTION", NULL}, {"@any", NULL}, {"TO", NULL}, {NULL}},
    {{"GRANT", NULL}, {"@any", NULL}, {"ON", NULL}, {"DATABASE", NULL}, {"TO", NULL}, {NULL}},
    {{"GRANT", NULL}, {"@any", NULL}, {"TO", NULL}, {NULL}},
    {{"REVOKE", NULL}, {"@any", NULL}, {"ON", NULL}, {"DOCUMENT", "COLLECTION", NULL}, {"@any", NULL}, {"FROM", NULL}, {NULL}},
    {{"REVOKE", NULL}, {"@any", NULL}, {"ON", NULL}, {"DATABASE", NULL}, {"FROM", NULL}, {NULL}},
    {{"REVOKE", NULL}, {"@any", NULL}, {"FROM", NULL}, {NULL}},
    {{"RETRIEVE", NULL}, {"METADATA", NULL}, {"FOR", NULL}, {"DOCUMENTS", NULL}, {"IN", NULL}, {"COLLECTION", NULL}, {NULL}},
    {{"RETRIEVE", NULL}, {"METADATA", NULL}, {"FOR", NULL}, {"DOCUMENTS", "COLLECTIONS", NULL}, {"WITH", NULL}, {"STATISTICS", NULL}, {NULL}},
    {{"RETRIEVE", NULL}, {"DESCRIPTIVE", NULL}, {"SCHEMA", NULL}, {"FOR", NULL}, {"DOCUMENT", NULL}, {"@any", NULL}, {"IN", NULL}, {"COLLECTION", NULL}, {NULL}},
    {{"RETRIEVE", NULL}, {"DESCRIPTIVE", NULL}, {"SCHEMA", NULL}, {"FOR", NULL}, {"COLLECTION", NULL}, {NULL}},
    {{"\\set", "\\unset", NULL}, {"AUTOCOMMIT", "ON_ERROR_STOP", "DEBUG", "TRANSACTION_READ_ONLY", "QUERY_TIMEOUT=", "LOG_LESS_MODE", NULL}, {NULL}},
    {{"\\set?", "\\unset?", "\\?", "\\commit", "\\rollback", "\\showtime", "\\quit", "\\commit", "\\rollback",
        "\\showtime", NULL}, {NULL}},
    {{"\\ac", "\\nac", "\\ro", "\\upd", "\\ll", "\\fl", "\\q", NULL}, {NULL}}
};

// we use this global param to tell generator how to complete matches
// Values are:
//      const_comp_generator -- const string
//      fromchain_comp_generator -- compatible chain array
static void *complete_param;

// determines global position of our lookup in chains
static int global_pos = 0;

// creates duplicate of string
// conv == 0 leave string as it is
// conv == 1 convert to upper-case
// conv == 2 convert to lower-case
static
char *str_dup(const char *str, int conv)
{
    int i, text_len;
    char *res;

    if (str == NULL)
        return NULL;

    text_len = strlen(str);
    res = (char *)malloc(text_len + 1);
    if (res == NULL)
        return NULL;

    if (conv)
    {
        for (i = 0; i < text_len; i++)
            res[i] = (char)((conv == 1) ? toupper(str[i]) : tolower(str[i]));
        res[text_len] = '\0';
    }
    else
        strcpy(res, str);

    return res;
}

// this function gives us the next word
// semantics similar to strtok: first call with buf as string
// all other calls on the same string must be with NULL
// returns NULL if cannot find the next word
static
char *get_word(const char *buf)
{
    static const char *inbuf = NULL;
    static int pos = 0;
    unsigned int i, start, end, inquotes = 0;
    char *res = NULL;

    // consider it first call
    if (buf != NULL)
    {
        pos = 0;
        inbuf = buf;
    }

    // no string? then return nothing
    if (inbuf == NULL)
        return NULL;

    // restore position
    i = pos;

    // first skip any spaces
    for (; i < strlen(inbuf) && isspace(inbuf[i]); i++)
        ;

    // nothing found
    if (i == strlen(inbuf))
        return NULL;

    // then try to find  end of word; start would be i
    start = i;
    for (; i < strlen(inbuf); i++)
    {
        if (inbuf[i] == '"')
            inquotes = !inquotes;
        if (isspace(inbuf[i]) && inquotes == 0)
            break;
    }

    end = i - 1;

    res = (char *)malloc(end - start + 2);
    if (res == NULL)
        return NULL;

    strncpy(res, inbuf + start, end - start + 1);
    res[end - start + 1] = '\0';

    // save current position
    pos = i;

    return res;
}

// generates single match with const specified in complete_param
// to be called from libedit
static
char *const_comp_generator(const char *text, int state)
{
    // first time return constant, then return NULL
    if (state == 0)
        return str_dup((char *)complete_param, 0);
    else
        return NULL;
}

// resets chains found flag
static
void reset_chains(int *chains, int count)
{
    int i;

    for (i = 0; i < count; i++)
        chains[i] = 1;
}

// find next chain that is set in found chains flag
// start searching from specified start
static
int find_next_set_chain(int *chains, int count, int start)
{
    int i, res = -1;

    for (i = start + 1; i < count; i++)
        if (chains[i])
    {
        res = i;
        break;
    }

    return res;
}

// generates matches from possible chains detemined at some previous steps
// chains must be passed via complete_param parameter
// to be called from libedit
static
char *fromchain_comp_generator(const char *text, int state)
{
    static int curr_chain = 0, curr_pos_chain = 0, curr_pos_chain_chain = 0;
    static int returned_smth = 0, can_file_comp = 0, text_len, state_to_rlfnc = 0;
    const char **chain;
    static char *uptext, *lotext; // copy of text with toupper, tolower
    char *file_res = NULL, *q_file_res = NULL; // result from filename generator and quoted result (to se_term)

    // for the first time set some params
    if (state == 0)
    {
        curr_chain = find_next_set_chain((int *)complete_param, MAX_CHAINS, -1);
        curr_pos_chain = global_pos;
        curr_pos_chain_chain = 0;
        can_file_comp = 0;
        returned_smth = 0;
        state_to_rlfnc = 0;
        file_res = NULL;

        // get upped text string
        uptext = str_dup(text, 1);
        lotext = str_dup(text, 2);
        text_len = strlen(uptext);
    }

    // if we have something to find then try give another match
    while (curr_chain != -1)
    {
        // get subchain in current_chain
        chain = chain_table[curr_chain][curr_pos_chain];
        if (chain[curr_pos_chain_chain] == NULL)
        {
            curr_chain = find_next_set_chain((int *)complete_param, MAX_CHAINS, curr_chain);
            curr_pos_chain = global_pos;
            curr_pos_chain_chain = 0;
        }
        else if (strcmp(chain[curr_pos_chain_chain], "@any") &&
                 strcmp(chain[curr_pos_chain_chain], "@file") &&
                 (strncmp(uptext, chain[curr_pos_chain_chain], text_len) == 0 ||
                  strncmp(lotext, chain[curr_pos_chain_chain], text_len) == 0))
        {
            returned_smth = 1;
            return str_dup(chain[curr_pos_chain_chain++], 0);
        }
        else
        {
            if (strcmp(chain[curr_pos_chain_chain], "@file") == 0) can_file_comp = 1;
            curr_pos_chain_chain++;
        }
    }

    // nothing to match
    // if we can file-complete here then do it
    if (can_file_comp)
    {
        if (text[0] == '"')
            text++;

        file_res = rl_filename_completion_function(text, state_to_rlfnc);
        state_to_rlfnc = 1;
        if (file_res)
        {
            if ((q_file_res = (char *)malloc(strlen(file_res) + 3)))
            {
                sprintf(q_file_res, "\"%s\"", file_res);
                returned_smth = 1;
                free(file_res);
                return q_file_res;
            }
        }
    }

    // if haven't found any matches return "" to turn off filename completion
    if (!returned_smth)
    {
        returned_smth = 1;
        rl_completion_append_character = '\0'; // to disable matching
        return str_dup("", 0);
    }

    free(uptext);
    free(lotext);

    return NULL;
}

// determine what chains match current word
static
int determine_chains(const char *word, int *chains, int count)
{
    int i, j, found;
    const char **chain;
    char *upword, *loword;

    upword = str_dup(word, 1);
    loword = str_dup(word, 2);

    for (i = 0; i < count; i++)
    {
        if (chains[i] == 0)
            continue;

        chain = chain_table[i][global_pos];
        if (chain[0] == NULL) // end of chain; get rid of it
            chains[i] = 0;
        else if (strcmp(chain[0], "@any") == 0 ||
                 strcmp(chain[0], "@file") == 0) // chain matches any word; let it stay
            continue;
        else
        {
            j = 0;
            while (chain[j] != NULL)
            {
                if (strcmp(upword, chain[j]) == 0||
                    strcmp(loword, chain[j]) == 0)
                    break;

                j++;
            }

            if (chain[j] == NULL) // chain doesn't match
                chains[i] = 0;
        }
        if (chains[i] == 1) // chains stays
            found = 1;
    }

    free(upword);
    free(loword);

    return found;
}

char **term_complet(const char *text, int start, int end)
{
    const char *saved_query_buf;
    char *word, *total_query;
    int possible_chains[MAX_CHAINS];
    char **matches = NULL;
    int found = 1;

    // starting from beginning of chains
    global_pos = 0;
    reset_chains(possible_chains, MAX_CHAINS);

    // first we must take query saved in term buffer so we won't be
    // confused with multiline queries
    saved_query_buf = get_query_from_term_buffer();
    total_query = (char *)malloc(strlen(saved_query_buf) + start + 1);
    if (total_query == NULL)
    {
        complete_param = (void *)"";
        return rl_completion_matches(text, const_comp_generator);
    }

    strcpy(total_query, saved_query_buf);
    strncat(total_query, rl_line_buffer, start);

    // try to analyze from first word to determine the possible query chain
    word = get_word(total_query);
    while (word != NULL)
    {
        found = determine_chains(word, possible_chains, MAX_CHAINS);

        // shift position
        global_pos++;

        // nothing found
        if (found == 0)
            break;

        word = get_word(NULL);
    }

    rl_completion_append_character = ' '; // to add space after match
    if (!found)
    {
        complete_param = (void *)"";
        matches = rl_completion_matches(text, const_comp_generator);
    }
    else
    {
        complete_param = possible_chains;
        matches = rl_completion_matches(text, fromchain_comp_generator);
    }

    return matches;
}

#endif /* #ifdef ENABLE_LIBEDIT */
<commit_msg>small term imp<commit_after>/*
 * File:  complet.cpp
 * Copyright (C) 2008 The Institute for System Programming of the Russian Academy of Sciences (ISP RAS)
 *
 * This file implements some kind of tab-completion using readline facilities. It can be used either with libedit
 * or readline libraries or, in fact, any other library that respects the same completion mechanism.
 *
 */

#ifdef ENABLE_LIBEDIT

#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <readline.h>
#include "term_ile.h"

// table of chains, which contains all possible alternatives to match
#define MAX_CHAINS 33
const char *chain_table[][13][11] =
{
    {{"UPDATE", NULL}, {"insert", NULL}, {"@any", NULL}, {"into", "preceding", "following", NULL}, {NULL}},
    {{"UPDATE", NULL}, {"delete", "delete_undeep", NULL}, {NULL}},
    {{"UPDATE", NULL}, {"replace", NULL}, {"@any", NULL}, {"in", NULL}, {"@any", NULL}, {"with", NULL}, {"@any", NULL}, {NULL},},
    {{"UPDATE", NULL}, {"replace", NULL}, {"@any", NULL}, {"as", NULL}, {"@any", NULL}, {"in", NULL}, {"@any", NULL},
        {"with", NULL}, {NULL},},
    {{"UPDATE", NULL}, {"rename", NULL}, {"@any", NULL}, {"on", NULL}, {NULL}},
    {{"LOAD", NULL}, {"@file", NULL}, {NULL}},
    {{"LOAD", NULL}, {"STDIN", NULL}, {NULL}},
    {{"LOAD", NULL}, {"MODULE", NULL}, {"@file", NULL}},
    {{"DROP", NULL}, {"MODULE", NULL}, {NULL}},
    {{"LOAD", NULL}, {"OR", NULL}, {"REPLACE", NULL}, {"MODULE", NULL}, {"@file", NULL}, {NULL}},
    {{"CREATE", "DROP", NULL}, {"DOCUMENT", NULL}, {"@any", NULL}, {"IN", NULL}, {"COLLECTION", NULL}, {NULL}},
    {{"CREATE", "DROP", NULL}, {"DOCUMENT", NULL}, {NULL}},
    {{"CREATE", "DROP", NULL}, {"COLLECTION", NULL}, {NULL}},
    {{"CREATE", NULL}, {"INDEX", NULL}, {"@any", NULL}, {"ON", NULL}, {"@any", NULL}, {"BY", NULL}, {"@any", NULL},
        {"AS", NULL}, {NULL}},
    {{"DROP", NULL}, {"USER", NULL}, {NULL}},
    {{"CREATE", "ALTER", NULL}, {"USER", NULL}, {"@any", NULL}, {"WITH", NULL}, {"PASSWORD", NULL}, {NULL},},
    {{"CREATE", NULL}, {"FULL-TEXT", NULL}, {"INDEX", NULL}, {"@any", NULL}, {"ON", NULL}, {"@any", NULL}, {"TYPE", NULL}, {NULL}},
    {{"CREATE", NULL}, {"TRIGGER", NULL}, {"@any", NULL}, {"BEFORE", "AFTER", NULL},
        {"INSERT", "DELETE", "REPLACE", NULL}, {"ON", NULL}, {"@any", NULL},
        {"FOR", NULL}, {"EACH", NULL}, {"NODE", "STATEMENT", NULL}, {"DO", NULL}, {NULL}},
    {{"CREATE", NULL}, {"ROLE", NULL}, {NULL}},
    {{"RENAME", NULL}, {"COLLECTION", NULL}, {"@any", NULL}, {"INTO", NULL}, {NULL}},
    {{"GRANT", NULL}, {"@any", NULL}, {"ON", NULL}, {"DOCUMENT", "COLLECTION", NULL}, {"@any", NULL}, {"TO", NULL}, {NULL}},
    {{"GRANT", NULL}, {"@any", NULL}, {"ON", NULL}, {"DATABASE", NULL}, {"TO", NULL}, {NULL}},
    {{"GRANT", NULL}, {"@any", NULL}, {"TO", NULL}, {NULL}},
    {{"REVOKE", NULL}, {"@any", NULL}, {"ON", NULL}, {"DOCUMENT", "COLLECTION", NULL}, {"@any", NULL}, {"FROM", NULL}, {NULL}},
    {{"REVOKE", NULL}, {"@any", NULL}, {"ON", NULL}, {"DATABASE", NULL}, {"FROM", NULL}, {NULL}},
    {{"REVOKE", NULL}, {"@any", NULL}, {"FROM", NULL}, {NULL}},
    {{"RETRIEVE", NULL}, {"METADATA", NULL}, {"FOR", NULL}, {"DOCUMENTS", NULL}, {"IN", NULL}, {"COLLECTION", NULL}, {NULL}},
    {{"RETRIEVE", NULL}, {"METADATA", NULL}, {"FOR", NULL}, {"DOCUMENTS", "COLLECTIONS", NULL}, {"WITH", NULL}, {"STATISTICS", NULL}, {NULL}},
    {{"RETRIEVE", NULL}, {"DESCRIPTIVE", NULL}, {"SCHEMA", NULL}, {"FOR", NULL}, {"DOCUMENT", NULL}, {"@any", NULL}, {"IN", NULL}, {"COLLECTION", NULL}, {NULL}},
    {{"RETRIEVE", NULL}, {"DESCRIPTIVE", NULL}, {"SCHEMA", NULL}, {"FOR", NULL}, {"COLLECTION", NULL}, {NULL}},
    {{"\\set", "\\unset", NULL}, {"AUTOCOMMIT", "ON_ERROR_STOP", "DEBUG", "TRANSACTION_READ_ONLY", "QUERY_TIMEOUT=", "LOG_LESS_MODE", NULL}, {NULL}},
    {{"\\set?", "\\unset?", "\\?", "\\commit", "\\rollback", "\\showtime", "\\quit", "\\commit", "\\rollback",
        "\\showtime", NULL}, {NULL}},
    {{"\\ac", "\\nac", "\\ro", "\\upd", "\\ll", "\\fl", "\\q", NULL}, {NULL}}
};

// we use this global param to tell generator how to complete matches
// Values are:
//      const_comp_generator -- const string
//      fromchain_comp_generator -- compatible chain array
static void *complete_param;

// determines global position of our lookup in chains
static int global_pos = 0;

// creates duplicate of string
// conv == 0 leave string as it is
// conv == 1 convert to upper-case
// conv == 2 convert to lower-case
static
char *str_dup(const char *str, int conv)
{
    int i, text_len;
    char *res;

    if (str == NULL)
        return NULL;

    text_len = strlen(str);
    res = (char *)malloc(text_len + 1);
    if (res == NULL)
        return NULL;

    if (conv)
    {
        for (i = 0; i < text_len; i++)
            res[i] = (char)((conv == 1) ? toupper(str[i]) : tolower(str[i]));
        res[text_len] = '\0';
    }
    else
        strcpy(res, str);

    return res;
}

// this function gives us the next word
// semantics similar to strtok: first call with buf as string
// all other calls on the same string must be with NULL
// returns NULL if cannot find the next word
static
char *get_word(const char *buf)
{
    static const char *inbuf = NULL;
    static int pos = 0;
    unsigned int i, start, end, inquotes = 0;
    char *res = NULL;

    // consider it first call
    if (buf != NULL)
    {
        pos = 0;
        inbuf = buf;
    }

    // no string? then return nothing
    if (inbuf == NULL)
        return NULL;

    // restore position
    i = pos;

    // first skip any spaces
    for (; i < strlen(inbuf) && isspace(inbuf[i]); i++)
        ;

    // nothing found
    if (i == strlen(inbuf))
        return NULL;

    // then try to find  end of word; start would be i
    start = i;
    for (; i < strlen(inbuf); i++)
    {
        if (inbuf[i] == '"')
            inquotes = !inquotes;
        if (isspace(inbuf[i]) && inquotes == 0)
            break;
    }

    end = i - 1;

    res = (char *)malloc(end - start + 2);
    if (res == NULL)
        return NULL;

    strncpy(res, inbuf + start, end - start + 1);
    res[end - start + 1] = '\0';

    // save current position
    pos = i;

    return res;
}

// generates single match with const specified in complete_param
// to be called from libedit
static
char *const_comp_generator(const char *text, int state)
{
    // first time return constant, then return NULL
    if (state == 0)
        return str_dup((char *)complete_param, 0);
    else
        return NULL;
}

// resets chains found flag
static
void reset_chains(int *chains, int count)
{
    int i;

    for (i = 0; i < count; i++)
        chains[i] = 1;
}

// find next chain that is set in found chains flag
// start searching from specified start
static
int find_next_set_chain(int *chains, int count, int start)
{
    int i, res = -1;

    for (i = start + 1; i < count; i++)
        if (chains[i])
    {
        res = i;
        break;
    }

    return res;
}

// generates matches from possible chains detemined at some previous steps
// chains must be passed via complete_param parameter
// to be called from libedit
static
char *fromchain_comp_generator(const char *text, int state)
{
    static int curr_chain = 0, curr_pos_chain = 0, curr_pos_chain_chain = 0;
    static int returned_smth = 0, can_file_comp = 0, text_len, state_to_rlfnc = 0;
    const char **chain;
    static char *uptext, *lotext; // copy of text with toupper, tolower
    char *file_res = NULL, *q_file_res = NULL; // result from filename generator and quoted result (to se_term)

    // for the first time set some params
    if (state == 0)
    {
        curr_chain = find_next_set_chain((int *)complete_param, MAX_CHAINS, -1);
        curr_pos_chain = global_pos;
        curr_pos_chain_chain = 0;
        can_file_comp = 0;
        returned_smth = 0;
        state_to_rlfnc = 0;
        file_res = NULL;

        // get upped text string
        uptext = str_dup(text, 1);
        lotext = str_dup(text, 2);
        text_len = strlen(uptext);
    }

    // if we have something to find then try give another match
    while (curr_chain != -1)
    {
        // get subchain in current_chain
        chain = chain_table[curr_chain][curr_pos_chain];
        if (chain[curr_pos_chain_chain] == NULL)
        {
            curr_chain = find_next_set_chain((int *)complete_param, MAX_CHAINS, curr_chain);
            curr_pos_chain = global_pos;
            curr_pos_chain_chain = 0;
        }
        else if (strcmp(chain[curr_pos_chain_chain], "@any") &&
                 strcmp(chain[curr_pos_chain_chain], "@file") &&
                 (strncmp(uptext, chain[curr_pos_chain_chain], text_len) == 0 ||
                  strncmp(lotext, chain[curr_pos_chain_chain], text_len) == 0))
        {
            returned_smth = 1;
            return str_dup(chain[curr_pos_chain_chain++], 0);
        }
        else
        {
            if (strcmp(chain[curr_pos_chain_chain], "@file") == 0) can_file_comp = 1;
            curr_pos_chain_chain++;
        }
    }

    // nothing to match
    // if we can file-complete here then do it
    if (can_file_comp)
    {
        if (text[0] == '"')
            text++;

        file_res = rl_filename_completion_function(text, state_to_rlfnc);
        state_to_rlfnc = 1;
        if (file_res)
        {
            if ((q_file_res = (char *)malloc(strlen(file_res) + 3)))
            {
                sprintf(q_file_res, "\"%s\"", file_res);
                returned_smth = 1;
                free(file_res);
                return q_file_res;
            }
        }
    }

    // if haven't found any matches return "" to turn off filename completion
    if (!returned_smth)
    {
        returned_smth = 1;
        rl_completion_append_character = '\0'; // to disable matching
        return str_dup("", 0);
    }

    free(uptext);
    free(lotext);

    return NULL;
}

// determine what chains match current word
static
int determine_chains(const char *word, int *chains, int count)
{
    int i, j, found;
    const char **chain;
    char *upword, *loword;

    upword = str_dup(word, 1);
    loword = str_dup(word, 2);

    for (i = 0; i < count; i++)
    {
        if (chains[i] == 0)
            continue;

        chain = chain_table[i][global_pos];
        if (chain[0] == NULL) // end of chain; get rid of it
            chains[i] = 0;
        else if (strcmp(chain[0], "@any") == 0 ||
                 strcmp(chain[0], "@file") == 0) // chain matches any word; let it stay
            continue;
        else
        {
            j = 0;
            while (chain[j] != NULL)
            {
                if (strcmp(upword, chain[j]) == 0||
                    strcmp(loword, chain[j]) == 0)
                    break;

                j++;
            }

            if (chain[j] == NULL) // chain doesn't match
                chains[i] = 0;
        }
        if (chains[i] == 1) // chains stays
            found = 1;
    }

    free(upword);
    free(loword);

    return found;
}

char **term_complet(const char *text, int start, int end)
{
    const char *saved_query_buf;
    char *word, *total_query;
    int possible_chains[MAX_CHAINS];
    char **matches = NULL;
    int found = 1;

    // starting from beginning of chains
    global_pos = 0;
    reset_chains(possible_chains, MAX_CHAINS);

    // first we must take query saved in term buffer so we won't be
    // confused with multiline queries
    saved_query_buf = get_query_from_term_buffer();
    total_query = (char *)malloc(strlen(saved_query_buf) + start + 1);
    if (total_query == NULL)
    {
        complete_param = (void *)"";
        return rl_completion_matches(text, const_comp_generator);
    }

    strcpy(total_query, saved_query_buf);
    strncat(total_query, rl_line_buffer, start);

    // try to analyze from first word to determine the possible query chain
    word = get_word(total_query);
    while (word != NULL)
    {
        found = determine_chains(word, possible_chains, MAX_CHAINS);

        // shift position
        global_pos++;

        // nothing found
        if (found == 0)
            break;

        word = get_word(NULL);
    }

    rl_completion_append_character = ' '; // to add space after match
    if (!found)
    {
        complete_param = (void *)"";
        matches = rl_completion_matches(text, const_comp_generator);
    }
    else
    {
        complete_param = possible_chains;
        matches = rl_completion_matches(text, fromchain_comp_generator);
    }

    return matches;
}

#endif /* #ifdef ENABLE_LIBEDIT */
<|endoftext|>


<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#define EIGEN_NO_STATIC_ASSERT

#include "main.h"

template<typename MatrixType> void adjoint(const MatrixType& m)
{
  /* this test covers the following files:
     Transpose.h Conjugate.h Dot.h
  */
  typedef typename MatrixType::Index Index;
  typedef typename MatrixType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;
  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType;

  Index rows = m.rows();
  Index cols = m.cols();

  MatrixType m1 = MatrixType::Random(rows, cols),
             m2 = MatrixType::Random(rows, cols),
             m3(rows, cols),
             mzero = MatrixType::Zero(rows, cols),
             identity = SquareMatrixType::Identity(rows, rows),
             square = SquareMatrixType::Random(rows, rows);
  VectorType v1 = VectorType::Random(rows),
             v2 = VectorType::Random(rows),
             v3 = VectorType::Random(rows),
             vzero = VectorType::Zero(rows);

  Scalar s1 = internal::random<Scalar>(),
         s2 = internal::random<Scalar>();

  // check basic compatibility of adjoint, transpose, conjugate
  VERIFY_IS_APPROX(m1.transpose().conjugate().adjoint(),    m1);
  VERIFY_IS_APPROX(m1.adjoint().conjugate().transpose(),    m1);

  // check multiplicative behavior
  VERIFY_IS_APPROX((m1.adjoint() * m2).adjoint(),           m2.adjoint() * m1);
  VERIFY_IS_APPROX((s1 * m1).adjoint(),                     internal::conj(s1) * m1.adjoint());

  // check basic properties of dot, norm, norm2
  typedef typename NumTraits<Scalar>::Real RealScalar;

  RealScalar ref = NumTraits<Scalar>::IsInteger ? 0 : std::max((s1 * v1 + s2 * v2).norm(),v3.norm());
  VERIFY(test_isApproxWithRef((s1 * v1 + s2 * v2).dot(v3),     internal::conj(s1) * v1.dot(v3) + internal::conj(s2) * v2.dot(v3), ref));
  VERIFY(test_isApproxWithRef(v3.dot(s1 * v1 + s2 * v2),       s1*v3.dot(v1)+s2*v3.dot(v2), ref));
  VERIFY_IS_APPROX(internal::conj(v1.dot(v2)),               v2.dot(v1));
  VERIFY_IS_APPROX(internal::real(v1.dot(v1)),                v1.squaredNorm());
  if(!NumTraits<Scalar>::IsInteger)
    VERIFY_IS_APPROX(v1.squaredNorm(),                v1.norm() * v1.norm());
  VERIFY_IS_MUCH_SMALLER_THAN(internal::abs(vzero.dot(v1)),  static_cast<RealScalar>(1));

  // check compatibility of dot and adjoint

  ref = NumTraits<Scalar>::IsInteger ? 0 : std::max(std::max(v1.norm(),v2.norm()),std::max((square * v2).norm(),(square.adjoint() * v1).norm()));
  VERIFY(test_isApproxWithRef(v1.dot(square * v2), (square.adjoint() * v1).dot(v2), ref));

  // like in testBasicStuff, test operator() to check const-qualification
  Index r = internal::random<Index>(0, rows-1),
      c = internal::random<Index>(0, cols-1);
  VERIFY_IS_APPROX(m1.conjugate()(r,c), internal::conj(m1(r,c)));
  VERIFY_IS_APPROX(m1.adjoint()(c,r), internal::conj(m1(r,c)));

  if(!NumTraits<Scalar>::IsInteger)
  {
    // check that Random().normalized() works: tricky as the random xpr must be evaluated by
    // normalized() in order to produce a consistent result.
    VERIFY_IS_APPROX(VectorType::Random(rows).normalized().norm(), RealScalar(1));
  }

  // check inplace transpose
  m3 = m1;
  m3.transposeInPlace();
  VERIFY_IS_APPROX(m3,m1.transpose());
  m3.transposeInPlace();
  VERIFY_IS_APPROX(m3,m1);

  // check inplace adjoint
  m3 = m1;
  m3.adjointInPlace();
  VERIFY_IS_APPROX(m3,m1.adjoint());
  m3.transposeInPlace();
  VERIFY_IS_APPROX(m3,m1.conjugate());

  // check mixed dot product
  typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealVectorType;
  RealVectorType rv1 = RealVectorType::Random(rows);
  VERIFY_IS_APPROX(v1.dot(rv1.template cast<Scalar>()), v1.dot(rv1));
  VERIFY_IS_APPROX(rv1.template cast<Scalar>().dot(v1), rv1.dot(v1));
}

void test_adjoint()
{
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1( adjoint(Matrix<float, 1, 1>()) );
    CALL_SUBTEST_2( adjoint(Matrix3d()) );
    CALL_SUBTEST_3( adjoint(Matrix4f()) );
    CALL_SUBTEST_4( adjoint(MatrixXcf(internal::random<int>(1,50), internal::random<int>(1,50))) );
    CALL_SUBTEST_5( adjoint(MatrixXi(internal::random<int>(1,50), internal::random<int>(1,50))) );
    CALL_SUBTEST_6( adjoint(MatrixXf(internal::random<int>(1,50), internal::random<int>(1,50))) );
  }
  // test a large matrix only once
  CALL_SUBTEST_7( adjoint(Matrix<float, 100, 100>()) );

#ifdef EIGEN_TEST_PART_4
  {
    MatrixXcf a(10,10), b(10,10);
    VERIFY_RAISES_ASSERT(a = a.transpose());
    VERIFY_RAISES_ASSERT(a = a.transpose() + b);
    VERIFY_RAISES_ASSERT(a = b + a.transpose());
    VERIFY_RAISES_ASSERT(a = a.conjugate().transpose());
    VERIFY_RAISES_ASSERT(a = a.adjoint());
    VERIFY_RAISES_ASSERT(a = a.adjoint() + b);
    VERIFY_RAISES_ASSERT(a = b + a.adjoint());

    // no assertion should be triggered for these cases:
    a.transpose() = a.transpose();
    a.transpose() += a.transpose();
    a.transpose() += a.transpose() + b;
    a.transpose() = a.adjoint();
    a.transpose() += a.adjoint();
    a.transpose() += a.adjoint() + b;
  }
#endif
}

<commit_msg>add test for normalize() and normalized()<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#define EIGEN_NO_STATIC_ASSERT

#include "main.h"

template<typename MatrixType> void adjoint(const MatrixType& m)
{
  /* this test covers the following files:
     Transpose.h Conjugate.h Dot.h
  */
  typedef typename MatrixType::Index Index;
  typedef typename MatrixType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;
  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, 1> VectorType;
  typedef Matrix<Scalar, MatrixType::RowsAtCompileTime, MatrixType::RowsAtCompileTime> SquareMatrixType;

  Index rows = m.rows();
  Index cols = m.cols();

  MatrixType m1 = MatrixType::Random(rows, cols),
             m2 = MatrixType::Random(rows, cols),
             m3(rows, cols),
             mzero = MatrixType::Zero(rows, cols),
             identity = SquareMatrixType::Identity(rows, rows),
             square = SquareMatrixType::Random(rows, rows);
  VectorType v1 = VectorType::Random(rows),
             v2 = VectorType::Random(rows),
             v3 = VectorType::Random(rows),
             vzero = VectorType::Zero(rows);

  Scalar s1 = internal::random<Scalar>(),
         s2 = internal::random<Scalar>();

  // check basic compatibility of adjoint, transpose, conjugate
  VERIFY_IS_APPROX(m1.transpose().conjugate().adjoint(),    m1);
  VERIFY_IS_APPROX(m1.adjoint().conjugate().transpose(),    m1);

  // check multiplicative behavior
  VERIFY_IS_APPROX((m1.adjoint() * m2).adjoint(),           m2.adjoint() * m1);
  VERIFY_IS_APPROX((s1 * m1).adjoint(),                     internal::conj(s1) * m1.adjoint());

  // check basic properties of dot, norm, norm2
  typedef typename NumTraits<Scalar>::Real RealScalar;

  RealScalar ref = NumTraits<Scalar>::IsInteger ? RealScalar(0) : std::max((s1 * v1 + s2 * v2).norm(),v3.norm());
  VERIFY(test_isApproxWithRef((s1 * v1 + s2 * v2).dot(v3),     internal::conj(s1) * v1.dot(v3) + internal::conj(s2) * v2.dot(v3), ref));
  VERIFY(test_isApproxWithRef(v3.dot(s1 * v1 + s2 * v2),       s1*v3.dot(v1)+s2*v3.dot(v2), ref));
  VERIFY_IS_APPROX(internal::conj(v1.dot(v2)),               v2.dot(v1));
  VERIFY_IS_APPROX(internal::real(v1.dot(v1)),                v1.squaredNorm());
  if(!NumTraits<Scalar>::IsInteger) {
    VERIFY_IS_APPROX(v1.squaredNorm(),                v1.norm() * v1.norm());
    // check normalized() and normalize()
    VERIFY_IS_APPROX(v1, v1.norm() * v1.normalized());
    // normalize() returns a reference to *this
    v3 = v1;
    VERIFY_IS_APPROX(v1, v1.norm() * v3.normalize());
    VERIFY_IS_APPROX(v3, v1.normalized());
    VERIFY_IS_APPROX(v3.norm(), RealScalar(1));
  }
  VERIFY_IS_MUCH_SMALLER_THAN(internal::abs(vzero.dot(v1)),  static_cast<RealScalar>(1));

  // check compatibility of dot and adjoint

  ref = NumTraits<Scalar>::IsInteger ? 0 : std::max(std::max(v1.norm(),v2.norm()),std::max((square * v2).norm(),(square.adjoint() * v1).norm()));
  VERIFY(test_isApproxWithRef(v1.dot(square * v2), (square.adjoint() * v1).dot(v2), ref));

  // like in testBasicStuff, test operator() to check const-qualification
  Index r = internal::random<Index>(0, rows-1),
      c = internal::random<Index>(0, cols-1);
  VERIFY_IS_APPROX(m1.conjugate()(r,c), internal::conj(m1(r,c)));
  VERIFY_IS_APPROX(m1.adjoint()(c,r), internal::conj(m1(r,c)));

  if(!NumTraits<Scalar>::IsInteger)
  {
    // check that Random().normalized() works: tricky as the random xpr must be evaluated by
    // normalized() in order to produce a consistent result.
    VERIFY_IS_APPROX(VectorType::Random(rows).normalized().norm(), RealScalar(1));
  }

  // check inplace transpose
  m3 = m1;
  m3.transposeInPlace();
  VERIFY_IS_APPROX(m3,m1.transpose());
  m3.transposeInPlace();
  VERIFY_IS_APPROX(m3,m1);

  // check inplace adjoint
  m3 = m1;
  m3.adjointInPlace();
  VERIFY_IS_APPROX(m3,m1.adjoint());
  m3.transposeInPlace();
  VERIFY_IS_APPROX(m3,m1.conjugate());

  // check mixed dot product
  typedef Matrix<RealScalar, MatrixType::RowsAtCompileTime, 1> RealVectorType;
  RealVectorType rv1 = RealVectorType::Random(rows);
  VERIFY_IS_APPROX(v1.dot(rv1.template cast<Scalar>()), v1.dot(rv1));
  VERIFY_IS_APPROX(rv1.template cast<Scalar>().dot(v1), rv1.dot(v1));
}

void test_adjoint()
{
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1( adjoint(Matrix<float, 1, 1>()) );
    CALL_SUBTEST_2( adjoint(Matrix3d()) );
    CALL_SUBTEST_3( adjoint(Matrix4f()) );
    CALL_SUBTEST_4( adjoint(MatrixXcf(internal::random<int>(1,50), internal::random<int>(1,50))) );
    CALL_SUBTEST_5( adjoint(MatrixXi(internal::random<int>(1,50), internal::random<int>(1,50))) );
    CALL_SUBTEST_6( adjoint(MatrixXf(internal::random<int>(1,50), internal::random<int>(1,50))) );
  }
  // test a large matrix only once
  CALL_SUBTEST_7( adjoint(Matrix<float, 100, 100>()) );

#ifdef EIGEN_TEST_PART_4
  {
    MatrixXcf a(10,10), b(10,10);
    VERIFY_RAISES_ASSERT(a = a.transpose());
    VERIFY_RAISES_ASSERT(a = a.transpose() + b);
    VERIFY_RAISES_ASSERT(a = b + a.transpose());
    VERIFY_RAISES_ASSERT(a = a.conjugate().transpose());
    VERIFY_RAISES_ASSERT(a = a.adjoint());
    VERIFY_RAISES_ASSERT(a = a.adjoint() + b);
    VERIFY_RAISES_ASSERT(a = b + a.adjoint());

    // no assertion should be triggered for these cases:
    a.transpose() = a.transpose();
    a.transpose() += a.transpose();
    a.transpose() += a.transpose() + b;
    a.transpose() = a.adjoint();
    a.transpose() += a.adjoint();
    a.transpose() += a.adjoint() + b;
  }
#endif
}

<|endoftext|>


<commit_before>#include <engpar_support.h>
#include <engpar.h>
#include <engpar_input.h>
#include <binGraph.h>
#include <cstring>
#include "buildGraphs.h"

bool cmpebin(char* str) {
  return strlen(str)>4&&strcmp(str+strlen(str)-5,".ebin")==0;
}

int main(int argc, char* argv[]) {
  MPI_Init(&argc,&argv);
  EnGPar_Initialize();
  EnGPar_Open_Log();

  if ( argc!=1 &&argc!= 2 && argc!=3) {
    if ( !PCU_Comm_Self() ) {
      printf("Usage: %s <graph>\n", argv[0]);
      printf("Usage: %s <bgd_prefix> [second edge type]\n", argv[0]);
      printf("Usage: %s\n",argv[0]);
    }
    EnGPar_Finalize();
    assert(false);
  }
  agi::Ngraph* g=NULL;
  if (argc==1) {
    g= buildEmptyGraph();
  }
  else if (cmpebin(argv[1]))
    g= agi::createBinGraph(argv[1]);
  else {
    g = agi::createEmptyGraph();
    g->loadFromFile(argv[1]);
  }

  if (g->hasCoords()) {
    std::string filename = "before";
    agi::writeVTK(g,filename.c_str());
  }
  engpar::evaluatePartition(g);

  engpar::Input* input = new engpar::Input(g);
  input->priorities.push_back(0);
  input->tolerances.push_back(1.1);
  if (argc==3) {
    input->priorities.push_back(1);
    input->tolerances.push_back(1.1);
  }
  input->priorities.push_back(-1);
  input->tolerances.push_back(1.1);

  input->step_factor=.1;
  if (g->isHyper())
    input->useDistanceQueue=true;
  else
    input->useDistanceQueue=false;
  //Create the balancer
  agi::Balancer* balancer = engpar::makeBalancer(input,2);
  balancer->balance(1.1);

  engpar::evaluatePartition(g);
  //Destroy balancer
  delete balancer;

  //Ensure the graph is still valid
  agi::checkValidity(g);

  if (g->hasCoords()) {
    std::string filename = "after";
    agi::writeVTK(g,filename.c_str());
  }

  //Migration of original data structure
  if (argc>2) {
    g->getPartition();

  }

  //Destroy graph
  agi::destroyGraph(g);

  PCU_Barrier();
  if (!PCU_Comm_Self())
    printf("\nAll tests passed\n");

  EnGPar_Finalize();
  MPI_Finalize();
}
<commit_msg>add a constraint on balancing<commit_after>#include <engpar_support.h>
#include <engpar.h>
#include <engpar_input.h>
#include <binGraph.h>
#include <cstring>
#include "buildGraphs.h"

bool cmpebin(char* str) {
  return strlen(str)>4&&strcmp(str+strlen(str)-5,".ebin")==0;
}

int main(int argc, char* argv[]) {
  MPI_Init(&argc,&argv);
  EnGPar_Initialize();
  EnGPar_Open_Log();

  if ( argc!=1 &&argc!= 2 && argc!=3) {
    if ( !PCU_Comm_Self() ) {
      printf("Usage: %s <graph>\n", argv[0]);
      printf("Usage: %s <bgd_prefix> [second edge type]\n", argv[0]);
      printf("Usage: %s\n",argv[0]);
    }
    EnGPar_Finalize();
    assert(false);
  }
  agi::Ngraph* g=NULL;
  if (argc==1) {
    g= buildEmptyGraph();
  }
  else if (cmpebin(argv[1]))
    g= agi::createBinGraph(argv[1]);
  else {
    g = agi::createEmptyGraph();
    g->loadFromFile(argv[1]);
  }

  if (g->hasCoords()) {
    std::string filename = "before";
    agi::writeVTK(g,filename.c_str());
  }
  engpar::evaluatePartition(g);

  engpar::Input* input = new engpar::Input(g);
  input->priorities.push_back(0);
  input->tolerances.push_back(1.1);
  if (argc==3) {
    input->priorities.push_back(1);
    input->tolerances.push_back(1.1);
  }
  input->priorities.push_back(-1);
  input->tolerances.push_back(1.1);

  input->step_factor=.1;
  if (g->isHyper())
    input->useDistanceQueue=true;
  else
    input->useDistanceQueue=false;
  //Create the balancer
  agi::Balancer* balancer = engpar::makeBalancer(input,2);
  balancer->balance(1.1);

  engpar::evaluatePartition(g);
  //Destroy balancer
  delete balancer;

  //Ensure the graph is still valid
  agi::checkValidity(g);

  //Ensure the graph was balanced to the target tolerance
  assert(engpar::EnGPar_Get_Imbalance(engpar::getWeight(g,-1))<1.2);
  assert(engpar::EnGPar_Get_Imbalance(engpar::getWeight(g,0))<1.2);

  if (g->hasCoords()) {
    std::string filename = "after";
    agi::writeVTK(g,filename.c_str());
  }

  //Migration of original data structure
  if (argc>2) {
    g->getPartition();
  }

  //Destroy graph
  agi::destroyGraph(g);

  PCU_Barrier();
  if (!PCU_Comm_Self())
    printf("\nAll tests passed\n");

  EnGPar_Finalize();
  MPI_Finalize();
}
<|endoftext|>


<commit_before>////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2013 - 2014, Göteborg Bit Factory.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// http://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////

#include <cmake.h>
#include <test.h>
#include <Dates.h>
#include <Context.h>

Context context;

////////////////////////////////////////////////////////////////////////////////
void testInit (UnitTest& t, const std::string& value, Variant& var)
{
  try
  {
    namedDates (value, var);
    t.pass (value + " --> valid");
  }

  catch (const std::string& e)
  {
    t.fail (value + " --> valid");
    t.diag (e);
  }

  catch (...)
  {
    t.fail (value + " --> valid");
  }
}

////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{
  UnitTest t (87);

  Variant sunday;    testInit (t, "sunday",    sunday);
  Variant monday;    testInit (t, "monday",    monday);
  Variant tuesday;   testInit (t, "tuesday",   tuesday);
  Variant wednesday; testInit (t, "wednesday", wednesday);
  Variant thursday;  testInit (t, "thursday",  thursday);
  Variant friday;    testInit (t, "friday",    friday);
  Variant saturday;  testInit (t, "saturday",  saturday);

  Variant sun; testInit (t, "sun", sun);
  Variant mon; testInit (t, "mon", mon);
  Variant tue; testInit (t, "tue", tue);
  Variant wed; testInit (t, "wed", wed);
  Variant thu; testInit (t, "thu", thu);
  Variant fri; testInit (t, "fri", fri);
  Variant sat; testInit (t, "sat", sat);

  t.ok (sunday    == sun, "sunday == sun");
  t.ok (monday    == mon, "monday == mon");
  t.ok (tuesday   == tue, "tuesday == tue");
  t.ok (wednesday == wed, "wednesday == wed");
  t.ok (thursday  == thu, "thursday == thu");
  t.ok (friday    == fri, "friday == fri");
  t.ok (saturday  == sat, "saturday == sat");

  Variant january;   testInit (t, "january",   january);
  Variant february;  testInit (t, "february",  february);
  Variant march;     testInit (t, "march",     march);
  Variant april;     testInit (t, "april",     april);
  Variant may;       testInit (t, "may",       may);
  Variant june;      testInit (t, "june",      june);
  Variant july;      testInit (t, "july",      july);
  Variant august;    testInit (t, "august",    august);
  Variant september; testInit (t, "september", september);
  Variant october;   testInit (t, "october",   october);
  Variant november;  testInit (t, "november",  november);
  Variant december;  testInit (t, "december",  december);

  Variant jan; testInit (t, "jan", jan);
  Variant feb; testInit (t, "feb", feb);
  Variant mar; testInit (t, "mar", mar);
  Variant apr; testInit (t, "apr", apr);
  Variant jun; testInit (t, "jun", jun);
  Variant jul; testInit (t, "jul", jul);
  Variant aug; testInit (t, "aug", aug);
  Variant sep; testInit (t, "sep", sep);
  Variant oct; testInit (t, "oct", oct);
  Variant nov; testInit (t, "nov", nov);
  Variant dec; testInit (t, "dec", dec);

  t.ok (january   == jan, "january == jan");
  t.ok (february  == feb, "february == feb");
  t.ok (march     == mar, "march == mar");
  t.ok (april     == apr, "april == apr");
  // May has only three letters.
  t.ok (june      == jun, "june == jun");
  t.ok (july      == jul, "july == jul");
  t.ok (august    == aug, "august == aug");
  t.ok (september == sep, "september == sep");
  t.ok (october   == oct, "october == oct");
  t.ok (november  == nov, "november == nov");
  t.ok (december  == dec, "december == dec");

  // Simply instantiate these for now.  Test later.
  Variant now;          testInit (t, "now", now);
  Variant today;        testInit (t, "today", today);
  Variant sod;          testInit (t, "sod", sod);
  Variant yesterday;    testInit (t, "yesterday", yesterday);
  Variant tomorrow;     testInit (t, "tomorrow", tomorrow);
  Variant eod;          testInit (t, "eod", eod);
  Variant soy;          testInit (t, "soy", soy);
  Variant eoy;          testInit (t, "eoy", eoy);
  Variant socm;         testInit (t, "socm", socm);
  Variant eocm;         testInit (t, "eocm", eocm);
  Variant som;          testInit (t, "som", som);
  Variant eom;          testInit (t, "eom", eom);
  Variant later;        testInit (t, "later", later);
  Variant someday;      testInit (t, "someday", someday);
  Variant easter;       testInit (t, "easter", easter);
  Variant eastermonday; testInit (t, "eastermonday", eastermonday);
  Variant ascension;    testInit (t, "ascension", ascension);
  Variant pentecost;    testInit (t, "pentecost", pentecost);
  Variant goodfriday;   testInit (t, "goodfriday", goodfriday);
  Variant pi;           testInit (t, "pi", pi);
  Variant var_true;     testInit (t, "true", var_true);
  Variant var_false;    testInit (t, "false", var_false);

  t.ok (now >= today,          "now >= today");
  t.ok (sod == today,          "sod == today");
  t.ok (sod < eod,             "sod < eod");
  t.ok (yesterday < today,     "yesterday < today");
  t.ok (today < tomorrow,      "today < tomorrow");
  t.ok (socm < eocm,           "socm < eocm");
  t.ok (now < later,           "now < later");
  t.ok (now < someday,         "now < someday");
  t.ok (goodfriday < easter,   "goodfriday < easter");
  t.ok (easter < eastermonday, "easter < eastermonday");

  return 0;
}

////////////////////////////////////////////////////////////////////////////////
<commit_msg>Unit Tests<commit_after>////////////////////////////////////////////////////////////////////////////////
//
// Copyright 2013 - 2014, Göteborg Bit Factory.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
// http://www.opensource.org/licenses/mit-license.php
//
////////////////////////////////////////////////////////////////////////////////

#include <cmake.h>
#include <test.h>
#include <Dates.h>
#include <Context.h>

Context context;

////////////////////////////////////////////////////////////////////////////////
void testInit (UnitTest& t, const std::string& value, Variant& var)
{
  try
  {
    namedDates (value, var);
    t.pass (value + " --> valid");
  }

  catch (const std::string& e)
  {
    t.fail (value + " --> valid");
    t.diag (e);
  }

  catch (...)
  {
    t.fail (value + " --> valid");
  }
}

////////////////////////////////////////////////////////////////////////////////
int main (int argc, char** argv)
{
  UnitTest t (87);

  Variant sunday;    testInit (t, "sunday",    sunday);
  Variant monday;    testInit (t, "monday",    monday);
  Variant tuesday;   testInit (t, "tuesday",   tuesday);
  Variant wednesday; testInit (t, "wednesday", wednesday);
  Variant thursday;  testInit (t, "thursday",  thursday);
  Variant friday;    testInit (t, "friday",    friday);
  Variant saturday;  testInit (t, "saturday",  saturday);

  Variant sun; testInit (t, "sun", sun);
  Variant mon; testInit (t, "mon", mon);
  Variant tue; testInit (t, "tue", tue);
  Variant wed; testInit (t, "wed", wed);
  Variant thu; testInit (t, "thu", thu);
  Variant fri; testInit (t, "fri", fri);
  Variant sat; testInit (t, "sat", sat);

  t.ok (sunday    == sun, "sunday == sun");
  t.ok (monday    == mon, "monday == mon");
  t.ok (tuesday   == tue, "tuesday == tue");
  t.ok (wednesday == wed, "wednesday == wed");
  t.ok (thursday  == thu, "thursday == thu");
  t.ok (friday    == fri, "friday == fri");
  t.ok (saturday  == sat, "saturday == sat");

  Variant january;   testInit (t, "january",   january);
  Variant february;  testInit (t, "february",  february);
  Variant march;     testInit (t, "march",     march);
  Variant april;     testInit (t, "april",     april);
  Variant may;       testInit (t, "may",       may);
  Variant june;      testInit (t, "june",      june);
  Variant july;      testInit (t, "july",      july);
  Variant august;    testInit (t, "august",    august);
  Variant september; testInit (t, "september", september);
  Variant october;   testInit (t, "october",   october);
  Variant november;  testInit (t, "november",  november);
  Variant december;  testInit (t, "december",  december);

  Variant jan; testInit (t, "jan", jan);
  Variant feb; testInit (t, "feb", feb);
  Variant mar; testInit (t, "mar", mar);
  Variant apr; testInit (t, "apr", apr);
  Variant jun; testInit (t, "jun", jun);
  Variant jul; testInit (t, "jul", jul);
  Variant aug; testInit (t, "aug", aug);
  Variant sep; testInit (t, "sep", sep);
  Variant oct; testInit (t, "oct", oct);
  Variant nov; testInit (t, "nov", nov);
  Variant dec; testInit (t, "dec", dec);

  t.ok (january   == jan, "january == jan");
  t.ok (february  == feb, "february == feb");
  t.ok (march     == mar, "march == mar");
  t.ok (april     == apr, "april == apr");
  // May has only three letters.
  t.ok (june      == jun, "june == jun");
  t.ok (july      == jul, "july == jul");
  t.ok (august    == aug, "august == aug");
  t.ok (september == sep, "september == sep");
  t.ok (october   == oct, "october == oct");
  t.ok (november  == nov, "november == nov");
  t.ok (december  == dec, "december == dec");

  // Simply instantiate these for now.  Test later.
  Variant now;          testInit (t, "now", now);
  Variant today;        testInit (t, "today", today);
  Variant sod;          testInit (t, "sod", sod);
  Variant yesterday;    testInit (t, "yesterday", yesterday);
  Variant tomorrow;     testInit (t, "tomorrow", tomorrow);
  Variant eod;          testInit (t, "eod", eod);
  Variant soy;          testInit (t, "soy", soy);
  Variant eoy;          testInit (t, "eoy", eoy);
  Variant socm;         testInit (t, "socm", socm);
  Variant eocm;         testInit (t, "eocm", eocm);
  Variant som;          testInit (t, "som", som);
  Variant eom;          testInit (t, "eom", eom);
  Variant later;        testInit (t, "later", later);
  Variant someday;      testInit (t, "someday", someday);
  Variant easter;       testInit (t, "easter", easter);
  Variant eastermonday; testInit (t, "eastermonday", eastermonday);
  Variant ascension;    testInit (t, "ascension", ascension);
  Variant pentecost;    testInit (t, "pentecost", pentecost);
  Variant goodfriday;   testInit (t, "goodfriday", goodfriday);
  Variant pi;           testInit (t, "pi", pi);
  Variant var_true;     testInit (t, "true", var_true);
  Variant var_false;    testInit (t, "false", var_false);

  t.ok (now >= today,          "now >= today");
  t.ok (sod == tomorrow,       "sod == tomorrow");
  t.ok (sod > eod,             "sod > eod");
  t.ok (yesterday < today,     "yesterday < today");
  t.ok (today < tomorrow,      "today < tomorrow");
  t.ok (socm < eocm,           "socm < eocm");
  t.ok (now < later,           "now < later");
  t.ok (now < someday,         "now < someday");
  t.ok (goodfriday < easter,   "goodfriday < easter");
  t.ok (easter < eastermonday, "easter < eastermonday");

  return 0;
}

////////////////////////////////////////////////////////////////////////////////
<|endoftext|>


<commit_before>#include <gmi_mesh.h>
#include <gmi_sim.h>
#include <apfMDS.h>
#include <apfMesh2.h>
#include <apfConvert.h>
#include <apf.h>
#include <PCU.h>
#include <SimUtil.h>
#include <cassert>
#include <cstdlib>

#define INTERIORTAG 0
#define BOTTOMTAG 1
#define TOPTAG 2
#define PERIMETERTAG 3
#define BOTTOM_PERIMETERTAG 4
#define TOP_PERIMETERTAG 5
#define TOPFACE 1
#define BOTTOMFACE 2
#define PERIMETERFACE 3

#define VTX_TYPE_NAME "vertex_type"

unsigned getElmType(int numVtxPerElm) {
  if (numVtxPerElm == 4) {
    return apf::Mesh::TET;
  } else {
    fprintf(stderr, "unknown element type in %s\n", __func__);
    exit(EXIT_FAILURE);
  }
}

void readHeader(FILE* f, unsigned& nodes, unsigned& elms, unsigned& numVtxPerElm) {
  fscanf(f,"%d %d %d", &nodes, &elms, &numVtxPerElm);
}

void readCoords(FILE* f, unsigned numvtx, double* coordinates) {
  const double huge = 1024*1024;
  double min[3] = {huge,huge,huge};
  double max[3] = {-huge,-huge,-huge};
  for(unsigned i=0; i<numvtx; i++) {
    for(unsigned j=0; j<3; j++) {
      double pos = 0;
      fscanf(f, "%lf", &pos);
      coordinates[i*3+j] = pos;
      if( pos < min[j] )
        min[j] = pos;
      if( pos > max[j] )
        max[j] = pos;
    }
  }
  char d[3] = {'x','y','z'};
  fprintf(stderr, "boundary of the domain:\n");
  for(unsigned i=0; i<3; i++)
    fprintf(stderr, "%c %lf %lf \n", d[i], min[i], max[i]);
}

void readElements(FILE* f, unsigned numelms, int numVtxPerElm, int* elements) {
  unsigned i;
  std::map<int, int> count;
  for (i = 0; i < numelms*numVtxPerElm; i++) {
    int vtxid;
    fscanf(f, "%u", &vtxid);
    elements[i] = --vtxid; //export from matlab using 1-based indices
    count[elements[i]]++;
  }
  fprintf(stderr, "Number of vertices used %lu\n", count.size());
}

struct MeshInfo {
  double* coords;
  int* elements;
  unsigned elementType;
  unsigned numVerts;
  unsigned numElms;
  unsigned numVtxPerElm;
};

void readMesh(const char* meshfilename, MeshInfo& mesh) {
  FILE* f = fopen(meshfilename, "r");
  assert(f);
  readHeader(f,mesh.numVerts,mesh.numElms,mesh.numVtxPerElm);
  fprintf(stderr, "numVerts %u numElms %u numVtxPerElm %u\n",
      mesh.numVerts, mesh.numElms, mesh.numVtxPerElm);
  mesh.coords = new double[mesh.numVerts*3];
  readCoords(f, mesh.numVerts, mesh.coords);
  mesh.elements = new int [mesh.numElms*mesh.numVtxPerElm];
  readElements(f, mesh.numElms, mesh.numVtxPerElm, mesh.elements);
  mesh.elementType = getElmType(mesh.numVtxPerElm);
  fclose(f);
}

int* readVtxClassification(const char* fname, unsigned numvtx) {
  FILE* f = fopen(fname, "r");
  assert(f);
  unsigned n;
  fscanf(f,"%u", &n);
  assert( n == numvtx );
  int* vtx_type_int = new int[numvtx];
  for(unsigned i = 0; i< numvtx; i++) {
    fscanf(f, "%d", &vtx_type_int[i]);
    assert(vtx_type_int[i] >= INTERIORTAG && vtx_type_int[i] <= TOP_PERIMETERTAG);
  }
  return vtx_type_int;
}

apf::MeshTag* attachVtxClassification(apf::Mesh2* mesh, apf::GlobalToVert& vtxMap,
    unsigned numVerts, int* vtxClass) {
  apf::MeshTag* vtxTag = mesh->createIntTag(VTX_TYPE_NAME, 1);
  for(unsigned i=0; i<numVerts; i++)
    mesh->setIntTag(vtxMap[i], vtxTag, &(vtxClass[i]));
  delete [] vtxClass;
  return vtxTag;
}

bool isClassifiedOnBoundary(apf::Mesh2* mesh, apf::MeshEntity* face) {
  int numAdjElms = mesh->countUpward(face);
  assert( numAdjElms > 0 );
  if( numAdjElms == 2 )
    return false; // both regions exist -> interior
  else
    return true; // only one region -> exterior
}

/** \brief just get the first geometric model region - hack
*/
apf::ModelEntity* getMdlRgn(gmi_model* model) {
  gmi_iter* it = gmi_begin(model, 3);
  gmi_ent* rgn = gmi_next(model, it);
  assert(rgn);
  gmi_end(model, it);
  return (apf::ModelEntity*)rgn;
}

apf::ModelEntity* getMdlFace(apf::Mesh2* mesh, int tag) {
  apf::ModelEntity* face = mesh->findModelEntity(2,tag);
  assert(face);
  return face;
}

/* returns -1 for an interior face
 *          0 for a boundary face with at least one vertex with an interior tag
 *          1 for a marked boundary face
 */
int setModelClassification(gmi_model* model,
    apf::Mesh2* mesh,
    std::map<int,int> vtx_type_num,
    apf::MeshEntity* face,
    std::map<int,int>& faceClass) {
  if( ! isClassifiedOnBoundary(mesh,face) ) {
    mesh->setModelEntity(face,getMdlRgn(model));
    return -1;
  }
  //this is a boundary face
  assert(vtx_type_num.at(INTERIORTAG) == 0);
  //we only need to mark vertex that in on the boundary
  if(vtx_type_num[PERIMETERTAG]!=0) {
    //if perimeter point exist it's on the perimeter
    faceClass[PERIMETERFACE]++;
    mesh->setModelEntity(face,getMdlFace(mesh,PERIMETERFACE));
  }
  else {
    if((vtx_type_num[BOTTOMTAG] + vtx_type_num[BOTTOM_PERIMETERTAG]) == 3) {
      /*include vtx_type_num[BOTTOMTAG]=3;
        vtx_type_num[BOTTOMTAG]=2, vtx_type_num[BOTTOM_PERIMETERTAG])=1;
        vtx_type_num[BOTTOMTAG]=1, vtx_type_num[BOTTOM_PERIMETERTAG])=2;
        vtx_type_num[BOTTOM_PERIMETERTAG])=3;*/
      faceClass[BOTTOMFACE]++;
      mesh->setModelEntity(face,getMdlFace(mesh,BOTTOMFACE));
    }
    else {
      if((vtx_type_num[TOPTAG] + vtx_type_num[TOP_PERIMETERTAG]) == 3) {
        /*include vtx_type_num[TOPTAG]=3;
          vtx_type_num[TOPTAG]=2, vtx_type_num[TOP_PERIMETERTAG])=1;
          vtx_type_num[TOPTAG]=1, vtx_type_num[TOP_PERIMETERTAG])=2;
          vtx_type_num[BOTTOM_PERIMETERTAG])=3;*/
        faceClass[TOPFACE]++;
        mesh->setModelEntity(face,getMdlFace(mesh,TOPFACE));
      }
      else {
        faceClass[PERIMETERFACE]++;
        mesh->setModelEntity(face,getMdlFace(mesh,PERIMETERFACE));
      }
    }
  }
  return 1;
}

void setFaceClassification(gmi_model* model, apf::Mesh2* mesh, apf::MeshTag* vtxType) {
  int numbdryfaces = 0;
  int markedfaces = 0;
  int skippedfaces = 0;
  std::map<int,int> faceClass;

  apf::MeshIterator* it = mesh->begin(2);
  apf::MeshEntity* face;
  while( (face = mesh->iterate(it)) ) {
    apf::Downward verts;
    int n = mesh->getDownward(face, 0, verts);
    assert(n == 3);

    std::map<int, int> vtx_type_num;
    for(int i=INTERIORTAG; i<=TOP_PERIMETERTAG; i++)
      vtx_type_num[i] = 0;
    for(int i=0; i<3; i++){
      int value;
      mesh->getIntTag(verts[i], vtxType, &value);
      assert(value >= INTERIORTAG && value <= TOP_PERIMETERTAG);
      vtx_type_num[value]++;
    }
    int counttaggedvtx = 0;
    for(int i=INTERIORTAG; i<=TOP_PERIMETERTAG; i++)
      counttaggedvtx += vtx_type_num[i];
    assert(counttaggedvtx==3);
    int isSet = setModelClassification(model, mesh, vtx_type_num, face, faceClass);
    if( isSet == 1 )
      markedfaces++;
    if(isSet == 0)
      skippedfaces++;
    if( isSet == 0 || isSet == 1 )
      numbdryfaces++;
  }
  mesh->end(it);

  fprintf(stderr, "num boundary faces %d\n", numbdryfaces);
  fprintf(stderr, "num marked faces %d\n", markedfaces);
  fprintf(stderr, "num skipped faces %d\n", skippedfaces);
  int totmarkedfaces=0;
  for(int i=1; i<4; i++) {
    fprintf(stderr,"%d: %d\n", i, faceClass[i]);
    totmarkedfaces += faceClass[i];
  }
  assert(numbdryfaces == totmarkedfaces);
}

/** \brief set the mesh region classification
  \details hacked to set the classification to the same geometric model region
*/
void setRgnClassification(gmi_model* model, apf::Mesh2* mesh) {
  apf::ModelEntity* mdlRgn = getMdlRgn(model);
  apf::MeshIterator* it = mesh->begin(3);
  apf::MeshEntity* rgn;
  while( (rgn = mesh->iterate(it)) )
    mesh->setModelEntity(rgn,mdlRgn);
  mesh->end(it);
}

void setClassification(gmi_model* model, apf::Mesh2* mesh, apf::MeshTag* t) {
  setRgnClassification(model,mesh);
  setFaceClassification(model,mesh,t);
  //setEdgeClassification(model,mesh,t);
  //setVtxClassification(model,mesh,t);
}

int main(int argc, char** argv)
{
  if( argc < 5 ) {
    printf("Usage: %s <GeomSim model .smd> <ascii mesh> <vertex classification> <output mesh> [<vertex field>...]\n",
        argv[0]);
    return 0;
  }

  MPI_Init(&argc,&argv);
  PCU_Comm_Init();
  SimUtil_start();
  Sim_readLicenseFile(NULL);
  gmi_sim_start();
  gmi_register_mesh();
  gmi_register_sim();

  gmi_model* model = gmi_load(argv[1]);

  MeshInfo m;
  readMesh(argv[2],m);

  const int dim = 3;
  apf::Mesh2* mesh = apf::makeEmptyMdsMesh(model, dim, false);
  apf::GlobalToVert outMap;
  apf::construct(mesh, m.elements, m.numElms, m.elementType, outMap);
  delete [] m.elements;
  apf::alignMdsRemotes(mesh);
  apf::deriveMdsModel(mesh);
  apf::setCoords(mesh, m.coords, m.numVerts, outMap);
  delete [] m.coords;
  int* vc = readVtxClassification(argv[3], m.numVerts);
  apf::MeshTag* vtxClass = attachVtxClassification(mesh, outMap, m.numVerts, vc);
  setClassification(model,mesh,vtxClass);
  outMap.clear();
  fprintf(stderr,"calling verify... flamesuit on\n");
  mesh->verify();
  mesh->writeNative(argv[3]);
  //apf::writeVtkFiles("after", mesh);

  mesh->destroyNative();
  apf::destroyMesh(mesh);
  gmi_destroy(model);
  gmi_sim_stop();
  Sim_unregisterAllKeys();
  SimUtil_stop();
  PCU_Comm_Free();
  MPI_Finalize();
}
<commit_msg>set mesh edge classification<commit_after>#include <gmi_mesh.h>
#include <gmi_sim.h>
#include <apfMDS.h>
#include <apfMesh2.h>
#include <apfConvert.h>
#include <apf.h>
#include <PCU.h>
#include <SimUtil.h>
#include <cassert>
#include <cstdlib>

#define INTERIORTAG 0
#define BOTTOMTAG 1
#define TOPTAG 2
#define PERIMETERTAG 3
#define BOTTOM_PERIMETERTAG 4
#define TOP_PERIMETERTAG 5
#define TOPFACE 1
#define BOTTOMFACE 2
#define PERIMETERFACE 3

#define VTX_TYPE_NAME "vertex_type"

unsigned getElmType(int numVtxPerElm) {
  if (numVtxPerElm == 4) {
    return apf::Mesh::TET;
  } else {
    fprintf(stderr, "unknown element type in %s\n", __func__);
    exit(EXIT_FAILURE);
  }
}

void readHeader(FILE* f, unsigned& nodes, unsigned& elms, unsigned& numVtxPerElm) {
  fscanf(f,"%d %d %d", &nodes, &elms, &numVtxPerElm);
}

void readCoords(FILE* f, unsigned numvtx, double* coordinates) {
  const double huge = 1024*1024;
  double min[3] = {huge,huge,huge};
  double max[3] = {-huge,-huge,-huge};
  for(unsigned i=0; i<numvtx; i++) {
    for(unsigned j=0; j<3; j++) {
      double pos = 0;
      fscanf(f, "%lf", &pos);
      coordinates[i*3+j] = pos;
      if( pos < min[j] )
        min[j] = pos;
      if( pos > max[j] )
        max[j] = pos;
    }
  }
  char d[3] = {'x','y','z'};
  fprintf(stderr, "boundary of the domain:\n");
  for(unsigned i=0; i<3; i++)
    fprintf(stderr, "%c %lf %lf \n", d[i], min[i], max[i]);
}

void readElements(FILE* f, unsigned numelms, int numVtxPerElm, int* elements) {
  unsigned i;
  std::map<int, int> count;
  for (i = 0; i < numelms*numVtxPerElm; i++) {
    int vtxid;
    fscanf(f, "%u", &vtxid);
    elements[i] = --vtxid; //export from matlab using 1-based indices
    count[elements[i]]++;
  }
  fprintf(stderr, "Number of vertices used %lu\n", count.size());
}

struct MeshInfo {
  double* coords;
  int* elements;
  unsigned elementType;
  unsigned numVerts;
  unsigned numElms;
  unsigned numVtxPerElm;
};

void readMesh(const char* meshfilename, MeshInfo& mesh) {
  FILE* f = fopen(meshfilename, "r");
  assert(f);
  readHeader(f,mesh.numVerts,mesh.numElms,mesh.numVtxPerElm);
  fprintf(stderr, "numVerts %u numElms %u numVtxPerElm %u\n",
      mesh.numVerts, mesh.numElms, mesh.numVtxPerElm);
  mesh.coords = new double[mesh.numVerts*3];
  readCoords(f, mesh.numVerts, mesh.coords);
  mesh.elements = new int [mesh.numElms*mesh.numVtxPerElm];
  readElements(f, mesh.numElms, mesh.numVtxPerElm, mesh.elements);
  mesh.elementType = getElmType(mesh.numVtxPerElm);
  fclose(f);
}

int* readVtxClassification(const char* fname, unsigned numvtx) {
  FILE* f = fopen(fname, "r");
  assert(f);
  unsigned n;
  fscanf(f,"%u", &n);
  assert( n == numvtx );
  int* vtx_type_int = new int[numvtx];
  for(unsigned i = 0; i< numvtx; i++) {
    fscanf(f, "%d", &vtx_type_int[i]);
    assert(vtx_type_int[i] >= INTERIORTAG && vtx_type_int[i] <= TOP_PERIMETERTAG);
  }
  return vtx_type_int;
}

apf::MeshTag* attachVtxClassification(apf::Mesh2* mesh, apf::GlobalToVert& vtxMap,
    unsigned numVerts, int* vtxClass) {
  apf::MeshTag* vtxTag = mesh->createIntTag(VTX_TYPE_NAME, 1);
  for(unsigned i=0; i<numVerts; i++)
    mesh->setIntTag(vtxMap[i], vtxTag, &(vtxClass[i]));
  delete [] vtxClass;
  return vtxTag;
}

bool isClassifiedOnBoundary(apf::Mesh2* mesh, apf::MeshEntity* face) {
  int numAdjElms = mesh->countUpward(face);
  assert( numAdjElms > 0 );
  if( numAdjElms == 2 )
    return false; // both regions exist -> interior
  else
    return true; // only one region -> exterior
}

/** \brief just get the first geometric model region - hack
*/
apf::ModelEntity* getMdlRgn(gmi_model* model) {
  gmi_iter* it = gmi_begin(model, 3);
  gmi_ent* rgn = gmi_next(model, it);
  assert(rgn);
  gmi_end(model, it);
  return (apf::ModelEntity*)rgn;
}

apf::ModelEntity* getMdlFace(apf::Mesh2* mesh, int tag) {
  apf::ModelEntity* face = mesh->findModelEntity(2,tag);
  assert(face);
  return face;
}

/** \brief brute force serach to find the intersection
 * \details models don't have that many edges bounding each face.... right???
 */
gmi_ent* getCommonEdge(gmi_set* a, gmi_set* b) {
  gmi_ent* match;
  unsigned found = 0;
  for(int i=0; i<a->n; i++) {
    for(int j=0; j<b->n; j++) {
      if( a->e[i] == b->e[j] ) {
        assert(!found);
        found++;
        match = a->e[i];
      }
    }
  }
  return match;
}

/** \brief get the model edge that bounds the model faces with the given tags
*/
apf::ModelEntity* getMdlEdge(apf::Mesh2* mesh, int faceTagA, int faceTagB) {
  gmi_model* model = mesh->getModel();
  gmi_ent* faceA = (gmi_ent*) getMdlFace(mesh,faceTagA);
  gmi_set* faceAedges = gmi_adjacent(model, faceA, 1);
  assert(faceAedges->n);
  gmi_ent* faceB = (gmi_ent*) getMdlFace(mesh,faceTagB);
  gmi_set* faceBedges = gmi_adjacent(model, faceB, 1);
  assert(faceBedges->n);
  gmi_ent* edge = getCommonEdge(faceAedges,faceBedges);
  assert(edge);
  gmi_free_set(faceAedges);
  gmi_free_set(faceBedges);
  return (apf::ModelEntity*) edge;
}

/* returns -1 for an interior face
 *          0 for a boundary face with at least one vertex with an interior tag
 *          1 for a marked boundary face
 */
int setModelClassification(gmi_model* model,
    apf::Mesh2* mesh,
    std::map<int,int> vtx_type_num,
    apf::MeshEntity* face,
    std::map<int,int>& faceClass) {
  if( ! isClassifiedOnBoundary(mesh,face) ) {
    mesh->setModelEntity(face,getMdlRgn(model));
    return -1;
  }
  //this is a boundary face
  assert(vtx_type_num.at(INTERIORTAG) == 0);
  //we only need to mark vertex that in on the boundary
  if(vtx_type_num[PERIMETERTAG]!=0) {
    //if perimeter point exist it's on the perimeter
    faceClass[PERIMETERFACE]++;
    mesh->setModelEntity(face,getMdlFace(mesh,PERIMETERFACE));
  }
  else {
    if((vtx_type_num[BOTTOMTAG] + vtx_type_num[BOTTOM_PERIMETERTAG]) == 3) {
      /*include vtx_type_num[BOTTOMTAG]=3;
        vtx_type_num[BOTTOMTAG]=2, vtx_type_num[BOTTOM_PERIMETERTAG])=1;
        vtx_type_num[BOTTOMTAG]=1, vtx_type_num[BOTTOM_PERIMETERTAG])=2;
        vtx_type_num[BOTTOM_PERIMETERTAG])=3;*/
      faceClass[BOTTOMFACE]++;
      mesh->setModelEntity(face,getMdlFace(mesh,BOTTOMFACE));
    }
    else {
      if((vtx_type_num[TOPTAG] + vtx_type_num[TOP_PERIMETERTAG]) == 3) {
        /*include vtx_type_num[TOPTAG]=3;
          vtx_type_num[TOPTAG]=2, vtx_type_num[TOP_PERIMETERTAG])=1;
          vtx_type_num[TOPTAG]=1, vtx_type_num[TOP_PERIMETERTAG])=2;
          vtx_type_num[BOTTOM_PERIMETERTAG])=3;*/
        faceClass[TOPFACE]++;
        mesh->setModelEntity(face,getMdlFace(mesh,TOPFACE));
      }
      else {
        faceClass[PERIMETERFACE]++;
        mesh->setModelEntity(face,getMdlFace(mesh,PERIMETERFACE));
      }
    }
  }
  return 1;
}

void setFaceClassification(gmi_model* model, apf::Mesh2* mesh, apf::MeshTag* vtxType) {
  int numbdryfaces = 0;
  int markedfaces = 0;
  int skippedfaces = 0;
  std::map<int,int> faceClass;

  apf::MeshIterator* it = mesh->begin(2);
  apf::MeshEntity* face;
  while( (face = mesh->iterate(it)) ) {
    apf::Downward verts;
    int n = mesh->getDownward(face, 0, verts);
    assert(n == 3);

    std::map<int, int> vtx_type_num;
    for(int i=INTERIORTAG; i<=TOP_PERIMETERTAG; i++)
      vtx_type_num[i] = 0;
    for(int i=0; i<3; i++){
      int value;
      mesh->getIntTag(verts[i], vtxType, &value);
      assert(value >= INTERIORTAG && value <= TOP_PERIMETERTAG);
      vtx_type_num[value]++;
    }
    int counttaggedvtx = 0;
    for(int i=INTERIORTAG; i<=TOP_PERIMETERTAG; i++)
      counttaggedvtx += vtx_type_num[i];
    assert(counttaggedvtx==3);
    int isSet = setModelClassification(model, mesh, vtx_type_num, face, faceClass);
    if( isSet == 1 )
      markedfaces++;
    if(isSet == 0)
      skippedfaces++;
    if( isSet == 0 || isSet == 1 )
      numbdryfaces++;
  }
  mesh->end(it);

  fprintf(stderr, "num boundary faces %d\n", numbdryfaces);
  fprintf(stderr, "num marked faces %d\n", markedfaces);
  fprintf(stderr, "num skipped faces %d\n", skippedfaces);
  int totmarkedfaces=0;
  for(int i=1; i<4; i++) {
    fprintf(stderr,"%d: %d\n", i, faceClass[i]);
    totmarkedfaces += faceClass[i];
  }
  assert(numbdryfaces == totmarkedfaces);
}

/** \brief set the mesh region classification
  \details hacked to set the classification to the same geometric model region
*/
void setRgnClassification(gmi_model* model, apf::Mesh2* mesh) {
  apf::ModelEntity* mdlRgn = getMdlRgn(model);
  apf::MeshIterator* it = mesh->begin(3);
  apf::MeshEntity* rgn;
  while( (rgn = mesh->iterate(it)) )
    mesh->setModelEntity(rgn,mdlRgn);
  mesh->end(it);
}

void getMeshEdgeTags(apf::Mesh2* mesh, apf::MeshEntity* edge,
    apf::MeshTag* t, int* tags) {
  apf::Downward verts;
  int n = mesh->getDownward(edge, 0, verts);
  assert(n == 2);

  for(int i=0; i<2; i++){
    int value;
    mesh->getIntTag(verts[i], t, &value);
    assert(value >= INTERIORTAG && value <= TOP_PERIMETERTAG);
    tags[i] = value;
  }
}

/** \brief set the mesh region classification
  \details hacked to set the classification to the same geometric model region
*/
void setEdgeClassification(gmi_model* model, apf::Mesh2* mesh, apf::MeshTag* t) {
  apf::ModelEntity* mdlRgn = getMdlRgn(model);
  apf::ModelEntity* mdlBotEdge = getMdlEdge(mesh,BOTTOMFACE,PERIMETERFACE);
  apf::ModelEntity* mdlTopEdge = getMdlEdge(mesh,TOPFACE,PERIMETERFACE);
  apf::ModelEntity* mdlTopFace = getMdlFace(mesh,TOPFACE);
  apf::ModelEntity* mdlBotFace = getMdlFace(mesh,BOTTOMFACE);
  apf::ModelEntity* mdlPerFace = getMdlFace(mesh,PERIMETERFACE);
  apf::MeshIterator* it = mesh->begin(1);
  apf::MeshEntity* edge;
  while( (edge = mesh->iterate(it)) ) {
    int tags[2];
    getMeshEdgeTags(mesh,edge,t,tags);
    // classified on model region
    if( tags[0] == INTERIORTAG || tags[1] == INTERIORTAG )
      mesh->setModelEntity(edge,mdlRgn);
    // classified on bottom perimeter
    else if( tags[0] == BOTTOM_PERIMETERTAG && tags[1] == BOTTOM_PERIMETERTAG )
      mesh->setModelEntity(edge,mdlBotEdge);
    // classified on top perimeter
    else if( tags[0] == TOP_PERIMETERTAG && tags[1] == TOP_PERIMETERTAG )
      mesh->setModelEntity(edge,mdlTopEdge);
    // classified on top face
    else if( tags[0] == TOPTAG || tags[1] == TOPTAG )
      mesh->setModelEntity(edge,mdlTopFace);
    // classified on bottom face
    else if( tags[0] == BOTTOMTAG || tags[1] == BOTTOMTAG )
      mesh->setModelEntity(edge,mdlBotFace);
    // classified on perimeter face
    else if( tags[0] == PERIMETERTAG || tags[1] == PERIMETERTAG )
      mesh->setModelEntity(edge,mdlPerFace);
    else {
      fprintf(stderr, "classification of edges fell through the conditional...exiting\n");
      exit(EXIT_FAILURE);
    }
  }
  mesh->end(it);
}

void setClassification(gmi_model* model, apf::Mesh2* mesh, apf::MeshTag* t) {
  setRgnClassification(model,mesh);
  setFaceClassification(model,mesh,t);
  setEdgeClassification(model,mesh,t);
  //setVtxClassification(model,mesh,t);
}

int main(int argc, char** argv)
{
  if( argc < 5 ) {
    printf("Usage: %s <GeomSim model .smd> <ascii mesh> <vertex classification> <output mesh> [<vertex field>...]\n",
        argv[0]);
    return 0;
  }

  MPI_Init(&argc,&argv);
  PCU_Comm_Init();
  SimUtil_start();
  Sim_readLicenseFile(NULL);
  gmi_sim_start();
  gmi_register_mesh();
  gmi_register_sim();

  gmi_model* model = gmi_load(argv[1]);

  MeshInfo m;
  readMesh(argv[2],m);

  const int dim = 3;
  apf::Mesh2* mesh = apf::makeEmptyMdsMesh(model, dim, false);
  apf::GlobalToVert outMap;
  apf::construct(mesh, m.elements, m.numElms, m.elementType, outMap);
  delete [] m.elements;
  apf::alignMdsRemotes(mesh);
  apf::deriveMdsModel(mesh);
  apf::setCoords(mesh, m.coords, m.numVerts, outMap);
  delete [] m.coords;
  int* vc = readVtxClassification(argv[3], m.numVerts);
  apf::MeshTag* vtxClass = attachVtxClassification(mesh, outMap, m.numVerts, vc);
  setClassification(model,mesh,vtxClass);
  outMap.clear();
  fprintf(stderr,"calling verify... flamesuit on\n");
  mesh->verify();
  mesh->writeNative(argv[3]);
  //apf::writeVtkFiles("after", mesh);

  mesh->destroyNative();
  apf::destroyMesh(mesh);
  gmi_destroy(model);
  gmi_sim_stop();
  Sim_unregisterAllKeys();
  SimUtil_stop();
  PCU_Comm_Free();
  MPI_Finalize();
}
<|endoftext|>


<commit_before>#include "laplace.hpp"

#include <gtest/gtest.h>

#include <boost/random/mersenne_twister.hpp>

using namespace MultidimensionalArray;
using namespace ProbabilityDistributions;

TEST(LaplacelTest, Likelihood) {
  boost::random::mt19937 rng;
  const unsigned int n_samples = 100;
  Laplace<double> dist(0, 1);
  Array<double> samples;
  dist.sample(samples, n_samples, rng);

  double likelihood1 = dist.log_likelihood(samples);

  dist.MLE(samples);

  double likelihood2 = dist.log_likelihood(samples);

  EXPECT_GE(likelihood2, likelihood1);

  EXPECT_LT(0, dist.get_b());
}

TEST(LaplaceTest, Samples) {
  boost::random::mt19937 rng;
  const unsigned int n_samples = 100;
  Laplace<double> dist(0, 1);
  Array<double> samples;
  dist.sample(samples, n_samples, rng);
  for (size_t i = 0; i < n_samples; i++) {
    EXPECT_LT(-10, samples(i,0));
    EXPECT_GT(10, samples(i,0));
  }
}
<commit_msg>Fixed typo in test.<commit_after>#include "laplace.hpp"

#include <gtest/gtest.h>

#include <boost/random/mersenne_twister.hpp>

using namespace MultidimensionalArray;
using namespace ProbabilityDistributions;

TEST(LaplaceTest, Likelihood) {
  boost::random::mt19937 rng;
  const unsigned int n_samples = 100;
  Laplace<double> dist(0, 1);
  Array<double> samples;
  dist.sample(samples, n_samples, rng);

  double likelihood1 = dist.log_likelihood(samples);

  dist.MLE(samples);

  double likelihood2 = dist.log_likelihood(samples);

  EXPECT_GE(likelihood2, likelihood1);

  EXPECT_LT(0, dist.get_b());
}

TEST(LaplaceTest, Samples) {
  boost::random::mt19937 rng;
  const unsigned int n_samples = 100;
  Laplace<double> dist(0, 1);
  Array<double> samples;
  dist.sample(samples, n_samples, rng);
  for (size_t i = 0; i < n_samples; i++) {
    EXPECT_LT(-10, samples(i,0));
    EXPECT_GT(10, samples(i,0));
  }
}
<|endoftext|>


<commit_before>#include <cassert>
#include <csetjmp>
#include <cstdlib>
#include <cstdio>
#include <cstring>

#include "CuTest.h"
#include "posit.h"

static POSIT_STYPE add_table[4][4] = {
//       0     1   inf    -1
    { 0b00, 0b01, 0b10, 0b11 }, // 0
    { 0b01, 0b01, 0b10, 0b00 }, // 1
    { 0b10, 0b10,   -1, 0b10 }, // inf
    { 0b11, 0b00, 0b10, 0b11 }, // -1
};

static POSIT_STYPE sub_table[4][4] = {
//       0     1   inf    -1
    { 0b00, 0b01, 0b10, 0b11 }, // 0
    { 0b11, 0b00, 0b10, 0b11 }, // 1
    { 0b10, 0b10,   -1, 0b10 }, // inf
    { 0b01, 0b01, 0b10, 0b00 }, // -1
};

static POSIT_STYPE mul_table[4][4] = {
//       0     1   inf    -1
    { 0b00, 0b00,   -1, 0b00 }, // 0
    { 0b00, 0b01, 0b10, 0b11 }, // 1
    {   -1, 0b10, 0b10, 0b10 }, // inf
    { 0b00, 0b11, 0b10, 0b01 }, // -1
};

static POSIT_STYPE div_table[4][4] = {
//       0     1   inf    -1
    {   -1, 0b10, 0b10, 0b10 }, // 0
    { 0b00, 0b01, 0b10, 0b11 }, // 1
    { 0b00, 0b00,   -1, 0b00 }, // inf
    { 0b00, 0b11, 0b10, 0b01 }, // -1
};

static void TestP2Zero(CuTest* tc)
{
    Posit p = Posit(2, 0);
    Posit zero = p.zero();
    Posit inf = p.inf();
    Posit neg = p.neg();
    Posit rec = p.rec();

    CuAssertTrue(tc, p.isZero());
    CuAssertTrue(tc, !p.isInf());
    CuAssertTrue(tc, !p.isNeg());
    CuAssertTrue(tc, p.nbits() == 2);
    CuAssertTrue(tc, p.rs() == 1);
    CuAssertTrue(tc, p.es() == 0);
    CuAssertTrue(tc, p.fs() == 0);
    CuAssertTrue(tc, p.eq(zero));
    CuAssertTrue(tc, !p.eq(inf));
    CuAssertTrue(tc, p.eq(neg));
    CuAssertTrue(tc, rec.isInf());
}

static void TestP2Add(CuTest* tc)
{
    Posit a = Posit(2, 0);
    Posit b = Posit(2, 0);

    for (int i = 0; i < 4; i++) {
        a.setBits(i);
        for (int j = 0; j < 4; j++) {
            b.setBits(j);

            Posit c = a.add(b);

            if (add_table[i][j] == -1) {
                CuAssertTrue(tc, c.isNan());
            } else {
                CuAssertTrue(tc, !c.isNan());
                CuAssertTrue(tc, c.getBits() == (POSIT_UTYPE)add_table[j][i]);
            }
        }
    }
}

static void TestP2Sub(CuTest* tc)
{
    Posit a = Posit(2, 0);
    Posit b = Posit(2, 0);

    for (int i = 0; i < 4; i++) {
        a.setBits(i);
        for (int j = 0; j < 4; j++) {
            b.setBits(j);

            Posit c = a.sub(b);

            if (sub_table[i][j] == -1) {
                CuAssertTrue(tc, c.isNan());
            } else {
                CuAssertTrue(tc, !c.isNan());
                CuAssertTrue(tc, c.getBits() == (POSIT_UTYPE)sub_table[j][i]);
            }
        }
    }
}

static void TestP2Mul(CuTest* tc)
{
    Posit a = Posit(2, 0);
    Posit b = Posit(2, 0);

    for (int i = 0; i < 4; i++) {
        a.setBits(i);
        for (int j = 0; j < 4; j++) {
            b.setBits(j);

            Posit c = a.mul(b);

            if (mul_table[i][j] == -1) {
                CuAssertTrue(tc, c.isNan());
            } else {
                CuAssertTrue(tc, !c.isNan());
                CuAssertTrue(tc, c.getBits() == (POSIT_UTYPE)mul_table[j][i]);
            }
        }
    }
}

static void TestP2Div(CuTest* tc)
{
    Posit a = Posit(2, 0);
    Posit b = Posit(2, 0);

    for (int i = 0; i < 4; i++) {
        a.setBits(i);
        for (int j = 0; j < 4; j++) {
            b.setBits(j);

            Posit c = a.div(b);

            if (div_table[i][j] == -1) {
                CuAssertTrue(tc, c.isNan());
            } else {
                CuAssertTrue(tc, !c.isNan());
                CuAssertTrue(tc, c.getBits() == (POSIT_UTYPE)div_table[j][i]);
            }
        }
    }
}

CuSuite* TestP2GetSuite(void)
{
	CuSuite* suite = CuSuiteNew();

	SUITE_ADD_TEST(suite, TestP2Zero);
	SUITE_ADD_TEST(suite, TestP2Add);
	SUITE_ADD_TEST(suite, TestP2Sub);
	SUITE_ADD_TEST(suite, TestP2Mul);
	SUITE_ADD_TEST(suite, TestP2Div);

	return suite;
}
<commit_msg>test: put common code in macro for 2 arg ops<commit_after>#include <cassert>
#include <csetjmp>
#include <cstdlib>
#include <cstdio>
#include <cstring>

#include "CuTest.h"
#include "posit.h"

#define TEST_OP2(op)                                                           \
    Posit a = Posit(2, 0);                                                     \
    Posit b = Posit(2, 0);                                                     \
                                                                               \
    for (int i = 0; i < 4; i++) {                                              \
        a.setBits(i);                                                          \
        for (int j = 0; j < 4; j++) {                                          \
            b.setBits(j);                                                      \
                                                                               \
            Posit c = a.op(b);                                                 \
                                                                               \
            if (op ## _table[i][j] == -1) {                                    \
                CuAssertTrue(tc, c.isNan());                                   \
            } else {                                                           \
                CuAssertTrue(tc, !c.isNan());                                  \
                CuAssertTrue(tc, c.getBits() ==                                \
                                 (POSIT_UTYPE)op ## _table[j][i]);             \
            }                                                                  \
        }                                                                      \
    }

static POSIT_STYPE add_table[4][4] = {
//       0     1   inf    -1
    { 0b00, 0b01, 0b10, 0b11 }, // 0
    { 0b01, 0b01, 0b10, 0b00 }, // 1
    { 0b10, 0b10,   -1, 0b10 }, // inf
    { 0b11, 0b00, 0b10, 0b11 }, // -1
};

static POSIT_STYPE sub_table[4][4] = {
//       0     1   inf    -1
    { 0b00, 0b01, 0b10, 0b11 }, // 0
    { 0b11, 0b00, 0b10, 0b11 }, // 1
    { 0b10, 0b10,   -1, 0b10 }, // inf
    { 0b01, 0b01, 0b10, 0b00 }, // -1
};

static POSIT_STYPE mul_table[4][4] = {
//       0     1   inf    -1
    { 0b00, 0b00,   -1, 0b00 }, // 0
    { 0b00, 0b01, 0b10, 0b11 }, // 1
    {   -1, 0b10, 0b10, 0b10 }, // inf
    { 0b00, 0b11, 0b10, 0b01 }, // -1
};

static POSIT_STYPE div_table[4][4] = {
//       0     1   inf    -1
    {   -1, 0b10, 0b10, 0b10 }, // 0
    { 0b00, 0b01, 0b10, 0b11 }, // 1
    { 0b00, 0b00,   -1, 0b00 }, // inf
    { 0b00, 0b11, 0b10, 0b01 }, // -1
};

static void TestP2Zero(CuTest* tc)
{
    Posit p = Posit(2, 0);
    Posit zero = p.zero();
    Posit inf = p.inf();
    Posit neg = p.neg();
    Posit rec = p.rec();

    CuAssertTrue(tc, p.isZero());
    CuAssertTrue(tc, !p.isInf());
    CuAssertTrue(tc, !p.isNeg());
    CuAssertTrue(tc, p.nbits() == 2);
    CuAssertTrue(tc, p.rs() == 1);
    CuAssertTrue(tc, p.es() == 0);
    CuAssertTrue(tc, p.fs() == 0);
    CuAssertTrue(tc, p.eq(zero));
    CuAssertTrue(tc, !p.eq(inf));
    CuAssertTrue(tc, p.eq(neg));
    CuAssertTrue(tc, rec.isInf());
}

static void TestP2Add(CuTest* tc)
{
    TEST_OP2(add)
}

static void TestP2Sub(CuTest* tc)
{
    TEST_OP2(sub)
}

static void TestP2Mul(CuTest* tc)
{
    TEST_OP2(mul)
}

static void TestP2Div(CuTest* tc)
{
    TEST_OP2(div)
}

CuSuite* TestP2GetSuite(void)
{
	CuSuite* suite = CuSuiteNew();

	SUITE_ADD_TEST(suite, TestP2Zero);
	SUITE_ADD_TEST(suite, TestP2Add);
	SUITE_ADD_TEST(suite, TestP2Sub);
	SUITE_ADD_TEST(suite, TestP2Mul);
	SUITE_ADD_TEST(suite, TestP2Div);

	return suite;
}
<|endoftext|>


<commit_before>#include <rapidxml\rapidxml.hpp>
#include "Log4JEvent.h"

const char TagEvent_[] = "log4j:event";
const size_t TagEventSize_ = sizeof (TagEvent_) - 1U;

const char AttrLevel_[] = "level";
const size_t AttrLevelSize_ = sizeof (AttrLevel_) - 1U;

const char AttrLogger_[] = "logger";
const size_t AttrLoggerSize_ = sizeof (AttrLogger_) - 1U;

const char AttrThread_[] = "thread";
const size_t AttrThreadSize_ = sizeof (AttrThread_) - 1U;

const char AttrTimestamp_[] = "timestamp";
const size_t AttrTimestampSize_ = sizeof (AttrTimestamp_) - 1U;

const char TagMessage_[] = "log4j:message";
const size_t TagMessageSize_ = sizeof (TagMessage_) - 1U;

const char TagThrowable_[] = "log4j:throwable";
const size_t TagThrowableSize_ = sizeof (TagThrowable_) - 1U;

static FixedString GetValue_ (const rapidxml::xml_base<char> *source);
static int64_t ParseTimestamp_ (const char *value, const size_t valueSize);

FixedString Log4JEventLevel (const Log4JEvent log4JEvent)
{
    auto node = (rapidxml::xml_node<char> *) log4JEvent;
    auto xml = node->first_attribute (AttrLevel_, AttrLevelSize_);
    return GetValue_ (xml);
}

FixedString Log4JEventLogger (const Log4JEvent log4JEvent)
{
    auto node = (rapidxml::xml_node<char> *) log4JEvent;
    auto xml = node->first_attribute (AttrLogger_, AttrLoggerSize_);
    return GetValue_ (xml);
}

FixedString Log4JEventThread (const Log4JEvent log4JEvent)
{
    auto node = (rapidxml::xml_node<char> *) log4JEvent;
    auto xml = node->first_attribute (AttrThread_, AttrThreadSize_);
    return GetValue_ (xml);
}

FixedString Log4JEventTimestamp (const Log4JEvent log4JEvent)
{
    auto node = (rapidxml::xml_node<char> *) log4JEvent;
    auto xml = node->first_attribute (AttrTimestamp_, AttrTimestampSize_);
    return GetValue_ (xml);
}

int64_t Log4JEventTime (const Log4JEvent log4JEvent)
{
    auto node = (rapidxml::xml_node<char> *) log4JEvent;
    auto xml = node->first_attribute (AttrTimestamp_, AttrTimestampSize_);
    auto result = ParseTimestamp_ (xml->value (), xml->value_size ());

    return result;
}

FixedString Log4JEventMessage (const Log4JEvent log4JEvent)
{
    auto node = (rapidxml::xml_node<char> *) log4JEvent;
    auto xml = node->first_node (TagMessage_, TagMessageSize_);
    return GetValue_ (xml);
}

FixedString Log4JEventThrowable (const Log4JEvent log4JEvent)
{
    auto node = (rapidxml::xml_node<char> *) log4JEvent;
    auto xml = node->first_node (TagThrowable_, TagThrowableSize_);
    return GetValue_ (xml);
}

FixedString GetValue_ (const rapidxml::xml_base<char> *source)
{
    if (source)
    {
        auto value = source->value ();
        auto valueSize = source->value_size ();
        return FixedString { value, valueSize };
    }
    else
    {
        return FixedString { nullptr, 0UL };
    }
}

int64_t ParseTimestamp_ (const char *value, const size_t valueSize)
{
    int64_t result = 0L;

    for (size_t i = 0; i < valueSize; ++i)
    {
        int64_t digit = value[i] - '0';
        result = result * 10L + digit;
    }

    return result;
}

typedef struct Log4JEventSource_
{
    const rapidxml::xml_document<char> *Doc;
};

void Log4JEventSourceInitXmlString (Log4JEventSource **self, char *xmlString)
{
    auto doc = new rapidxml::xml_document<char> ();
    doc->parse<rapidxml::parse_fastest> (xmlString);

    auto result = (Log4JEventSource *) malloc (sizeof (Log4JEventSource));
    *result = { doc };

    *self = result;
}

void Log4JEventSourceDestroy (Log4JEventSource *self)
{
    delete self->Doc;

    *self = { nullptr };
    free (self);
}

Log4JEvent Log4JEventSourceFirst (const Log4JEventSource *self)
{
    auto node = self->Doc->first_node (TagEvent_, TagEventSize_);
    return node;
}

Log4JEvent Log4JEventSourceNext (const Log4JEventSource *self, const Log4JEvent event)
{
    auto node = (rapidxml::xml_node<char> *) event;
    auto nextNode = node->next_sibling (TagEvent_, TagEventSize_);
    return nextNode;
}
<commit_msg>Fixed Log4JEvent implementation potentially resulting in non-C function exports.<commit_after>#include <rapidxml\rapidxml.hpp>
extern "C"
{
#include "Log4JEvent.h"
}

const char TagEvent_[] = "log4j:event";
const size_t TagEventSize_ = sizeof (TagEvent_) - 1U;

const char AttrLevel_[] = "level";
const size_t AttrLevelSize_ = sizeof (AttrLevel_) - 1U;

const char AttrLogger_[] = "logger";
const size_t AttrLoggerSize_ = sizeof (AttrLogger_) - 1U;

const char AttrThread_[] = "thread";
const size_t AttrThreadSize_ = sizeof (AttrThread_) - 1U;

const char AttrTimestamp_[] = "timestamp";
const size_t AttrTimestampSize_ = sizeof (AttrTimestamp_) - 1U;

const char TagMessage_[] = "log4j:message";
const size_t TagMessageSize_ = sizeof (TagMessage_) - 1U;

const char TagThrowable_[] = "log4j:throwable";
const size_t TagThrowableSize_ = sizeof (TagThrowable_) - 1U;

static FixedString GetValue_ (const rapidxml::xml_base<char> *source);
static int64_t ParseTimestamp_ (const char *value, const size_t valueSize);

FixedString __cdecl Log4JEventLevel (const Log4JEvent log4JEvent)
{
    auto node = (rapidxml::xml_node<char> *) log4JEvent;
    auto xml = node->first_attribute (AttrLevel_, AttrLevelSize_);
    return GetValue_ (xml);
}

FixedString __cdecl Log4JEventLogger (const Log4JEvent log4JEvent)
{
    auto node = (rapidxml::xml_node<char> *) log4JEvent;
    auto xml = node->first_attribute (AttrLogger_, AttrLoggerSize_);
    return GetValue_ (xml);
}

FixedString __cdecl Log4JEventThread (const Log4JEvent log4JEvent)
{
    auto node = (rapidxml::xml_node<char> *) log4JEvent;
    auto xml = node->first_attribute (AttrThread_, AttrThreadSize_);
    return GetValue_ (xml);
}

FixedString __cdecl Log4JEventTimestamp (const Log4JEvent log4JEvent)
{
    auto node = (rapidxml::xml_node<char> *) log4JEvent;
    auto xml = node->first_attribute (AttrTimestamp_, AttrTimestampSize_);
    return GetValue_ (xml);
}

int64_t __cdecl Log4JEventTime (const Log4JEvent log4JEvent)
{
    auto node = (rapidxml::xml_node<char> *) log4JEvent;
    auto xml = node->first_attribute (AttrTimestamp_, AttrTimestampSize_);
    auto result = ParseTimestamp_ (xml->value (), xml->value_size ());

    return result;
}

FixedString __cdecl Log4JEventMessage (const Log4JEvent log4JEvent)
{
    auto node = (rapidxml::xml_node<char> *) log4JEvent;
    auto xml = node->first_node (TagMessage_, TagMessageSize_);
    return GetValue_ (xml);
}

FixedString __cdecl Log4JEventThrowable (const Log4JEvent log4JEvent)
{
    auto node = (rapidxml::xml_node<char> *) log4JEvent;
    auto xml = node->first_node (TagThrowable_, TagThrowableSize_);
    return GetValue_ (xml);
}

FixedString GetValue_ (const rapidxml::xml_base<char> *source)
{
    if (source)
    {
        auto value = source->value ();
        auto valueSize = source->value_size ();
        return FixedString { value, valueSize };
    }
    else
    {
        return FixedString { nullptr, 0UL };
    }
}

int64_t ParseTimestamp_ (const char *value, const size_t valueSize)
{
    int64_t result = 0L;

    for (size_t i = 0; i < valueSize; ++i)
    {
        int64_t digit = value[i] - '0';
        result = result * 10L + digit;
    }

    return result;
}

typedef struct Log4JEventSource_
{
    const rapidxml::xml_document<char> *Doc;
};

void __cdecl Log4JEventSourceInitXmlString (Log4JEventSource **self, char *xmlString)
{
    auto doc = new rapidxml::xml_document<char> ();
    doc->parse<rapidxml::parse_fastest> (xmlString);

    auto result = (Log4JEventSource *) malloc (sizeof (Log4JEventSource));
    *result = { doc };

    *self = result;
}

void __cdecl Log4JEventSourceDestroy (Log4JEventSource *self)
{
    delete self->Doc;

    *self = { nullptr };
    free (self);
}

Log4JEvent __cdecl Log4JEventSourceFirst (const Log4JEventSource *self)
{
    auto node = self->Doc->first_node (TagEvent_, TagEventSize_);
    return node;
}

Log4JEvent __cdecl Log4JEventSourceNext (const Log4JEventSource *self, const Log4JEvent event)
{
    auto node = (rapidxml::xml_node<char> *) event;
    auto nextNode = node->next_sibling (TagEvent_, TagEventSize_);
    return nextNode;
}
<|endoftext|>