/*
 * This is a GENERATED FILE -- do not edit.
 * See known-functions.csv and buildtools/src/ParseFunctions.java
 */
/**
 * @file unity.h
 */

#include <stdio.h>              /* for NULL */
#include <stdlib.h>             /* for bsearch */
#include <string.h>             /* for strcmp */
#include <assert.h>

#define UNITY_INTERNAL 1
#include "function-definitions.h"
#include "known-syntaxes.h"

const FunctionDef function_definitions[] = {
  { "Common Logarithm (base 10)", "\\log" },
  { "Natural Logarithm", "\\ln" },
  { "Exponential", "\\exp" },
  { "Square root", "\\sqrt" },
  { "Sine", "\\sin" },
  { "Cosine", "\\cos" },
  { "Tangent", "\\tan" },
  { "Arc sine", "\\arcsin" },
  { "Arc cosine", "\\arccos" },
  { "Arc tangent", "\\arctan" },
  { "Hyperbolic sine", "\\sinh" },
  { "Hyperbolic cosine", "\\cosh" },
  { "Hyperbolic tangent", "\\tanh" },
};
const size_t n_function_definitions = sizeof(function_definitions)/sizeof(function_definitions[0]);

typedef struct { const char* abbrev; int idx; } StxMap;
/* Verify that the syntax name indexes match */
StxMap stx_0[] = { // syntax for UNITY_SYNTAX_FITS
  { "exp", 2},
  { "ln", 1},
  { "log", 0},
  { "sqrt", 3},
};
StxMap stx_1[] = { // syntax for UNITY_SYNTAX_OGIP
  { "acos", 8},
  { "asin", 7},
  { "atan", 9},
  { "cos", 5},
  { "cosh", 11},
  { "exp", 2},
  { "ln", 1},
  { "log", 0},
  { "sin", 4},
  { "sinh", 10},
  { "sqrt", 3},
  { "tan", 6},
  { "tanh", 12},
};
StxMap stx_2[] = { // syntax for UNITY_SYNTAX_CDS
};
StxMap stx_3[] = { // syntax for UNITY_SYNTAX_VOUNITS
  { "exp", 2},
  { "ln", 1},
  { "log", 0},
  { "sqrt", 3},
};

/* Lookup between integers and UnitySyntax */
static UnitySyntax stxIndexes[] = {
  UNITY_SYNTAX_FITS,
  UNITY_SYNTAX_OGIP,
  UNITY_SYNTAX_CDS,
  UNITY_SYNTAX_VOUNITS,
};
static const int n_syntaxes = 4;

typedef struct { StxMap* m; size_t len; } syntax_table_entry;
syntax_table_entry stxmaps[] = { 
  { stx_0, 4 }, // fits
  { stx_1, 13 }, // ogip
  { stx_2, 0 }, // cds
  { stx_3, 4 }, // vounits
};
// there are n_syntaxes elements in this array


static int stxmap_compare(const void* key, const void* test)
{
    return strcmp((char*)key, ((StxMap*)test)->abbrev);
}

static int uu_syntax_to_integer(UnitySyntax syntax)
{
    int syntaxIdx;
    for (syntaxIdx = 0; syntaxIdx < n_syntaxes; syntaxIdx++) {
        if (stxIndexes[syntaxIdx] == syntax)
            break;
    }
    // if we haven't found a syntaxIdx, that's a programming error -- things are out of sync
    assert(syntaxIdx < n_syntaxes);
    return syntaxIdx;
}

/**
 * Retrieves a function definition object.
 * Returns NULL if the abbreviation is not recognised in
 * the indicated syntax (or if the syntax is invalid).
 * @param abbrev a function abbreviation, for example "log" for Common Logarithm
 * @param syntax one of the UNITY_SYNTAX_* constants
 * @return a pointer to a function definitions string, or NULL if none such exists in this syntax
 */
const FunctionDef* unity_get_functiondef_from_string(const char* abbrev, const UnitySyntax syntax)
{
    const StxMap* stxmap_found;
    int syntaxIdx = uu_syntax_to_integer(syntax);
    
    stxmap_found = (StxMap*)bsearch(abbrev,
                                    stxmaps[syntaxIdx].m,
                                    stxmaps[syntaxIdx].len,
                                    sizeof(StxMap),
                                    stxmap_compare);
    if (stxmap_found == NULL) {
        return NULL;
    } else {
        assert(stxmap_found->idx >= 0
               && stxmap_found->idx < n_function_definitions);
        return &function_definitions[stxmap_found->idx];
    }
}

/* Inverse function: given a function definition, return its abbreviation,
   or NULL */
const char* unity_get_function_abbreviation(const FunctionDef* def, UnitySyntax syntax)
{
    const StxMap* map;
    int i;
    int syntaxIdx = uu_syntax_to_integer(syntax);

    map = stxmaps[syntaxIdx].m;
    for (i=0; i<stxmaps[syntaxIdx].len; i++) {
        // compare pointers
        if (def == &function_definitions[map[i].idx]) {
            return map[i].abbrev; /* JUMP OUT */
        }
    }
    return NULL;
}

