/*******************************************************************************
;*******************************************************************************
;**                                                                           **
;**                  COPYRIGHT 2001-2012 NUANCE COMMUNICATIONS                **
;**                                                                           **
;**               NUANCE COMMUNICATIONS PROPRIETARY INFORMATION               **
;**                                                                           **
;**     This software is supplied under the terms of a license agreement      **
;**     or non-disclosure agreement with Nuance Communications and may not    **
;**     be copied or disclosed except in accordance with the terms of that    **
;**     agreement.                                                            **
;**                                                                           **
;*******************************************************************************
;**                                                                           **
;**     FileName: et9asearchdb.h                                              **
;**                                                                           **
;**  Description: Compare a text string with a path.                          **
;**                                                                           **
;*******************************************************************************
;******************************************************************************/


#ifndef _SEARCHDB_H_
#define _SEARCHDB_H_            1

#if _MSC_VER > 1000
#pragma once
#endif /* _MSC_VER > 1000 */

#include "et9abuildconfig.h"

#include "et9aswapitypes.h"
#include "et9ageometry.h"
#include "et9aword.h"
#include "et9afixeddata.h"
#include "et9autilities.h"
#include "et9adbm.h"
#include "et9aipanalyzer.h"
#include "et9alogutils.h"
#include "et9aforword.h"

#if REFERENCE_DEBUG_BUILD
#define COMPARE_ALGORITHMS                  0                   /* Compare results from different algorithms */
/*#define COMPARE_ALGORITHMS                  1                   // Compare results from different algorithms */
#define ALTERNATE_ALGORITHMS                0                   /* Alternate order in which different algorithms are applied to each path */
/*#define ALTERNATE_ALGORITHMS                1                 // Alternate order in which different algorithms are applied to each path */
#define DEBUG_SHOW_WCW_TRACE_DETECT_DUPS    0
#define INCLUDE_ALG_ORIG_CODE               0
#define CONTROL_MGD_PARAMS                  1
#else
#define COMPARE_ALGORITHMS                  0                   /* Compare results from different algorithms */
#define ALTERNATE_ALGORITHMS                0                   /* Alternate order in which different algorithms are applied to each path */
#define DEBUG_SHOW_WCW_TRACE_DETECT_DUPS    0
#define INCLUDE_ALG_ORIG_CODE               0
#define CONTROL_MGD_PARAMS                  0
#endif

#if DEBUG_SHOW_MATCH_TRACE || DEBUG_SHOW_WCW_TRACE
    #define TRACK_PREDICTION_PROCESSING         1
#else
    #define TRACK_PREDICTION_PROCESSING         0
#endif

#define CAN_REQUIRE_DOUBLE_GESTURE              1           /* If define'd, there are at least some circumstances where a double gesture is required */

#define KEY1_VERTICAL_MATCH_MIN_SEQ_LENGTH  1       /* Expand search around Key 1 once two keystrokes received */
#define KEY2_VERTICAL_MATCH_MIN_SEQ_LENGTH  0       /* Expand search around Key 2 once one keystroke received (for now, on every keystroke) */

#define KEYS_MATCH_PATH                     0
#define KEYS_NOT_IN_SEQUENCE                1
#define KEYS_DO_NOT_MATCH_PATH              2

#define DEBUG_SHOW_MOUSE_COUNTS                 0   /* Outputs the counts of mouse data received for each path - Actual output controlled by DEBUG_SHOW_INFO_WITH_WOR */

/*                                            Algorithm:               ALG_ORIG           ALG_V2    ALG_LATEST */
/*#define ALG_USES_FILTERING                  ALG_LATEST                  //                            X */
/*#define ALG_USE_FINAL_KEY_PAIRS             N_ALGORITHMS                //                X           X */
/*#define ALG_NO_RECALC_THRESHOLDS            ALG_V2                      //                X           X */
/*#define ALG_NO_REPROC_IPTABLE               ALG_V2                      //                X           X */
/*#define ALG_NO_RESCORE_BOUNCES              ALG_V2                      //                X           X */
/*#define ALG_EXPAND_CANDIDATES               ALG_V2                      //                X           X */
/*#define ALG_REDUCED_RECENCY_WEIGHTING       N_ALGORITHMS                // */
/*#define ALG_REDUCED_FREQUENCY_WEIGHTING     N_ALGORITHMS                // */
/*#define ALG_INCREASED_RECENCY_WEIGHTING     N_ALGORITHMS                // */
/*#define ALG_INCREASED_FREQUENCY_WEIGHTING   N_ALGORITHMS                // */
/*#define ALG_SORT_TOP_THREE                  ALG_V2                      //                X           X */
/*#define ALG_NEW_NO_PENALTY_SCORE            N_ALGORITHMS                // */
/*#define ALG_NEW_COMBINED_SCORE              N_ALGORITHMS                // */
/*#define ALG_FILTER_ALL_CANDIDATES           ALG_LATEST                  //                            X */
/*#define ALG_EXPAND_FILTERED_CANDIDATES      ALG_LATEST                  //                            X */

#define CLOSE_IP_MATCH_THRESHOLD            (8*pThis->m_backend->sScreenGeometry.keyHeight/2)
#define CLOSE_SEGMENT_MATCH_THRESHOLD       (8*pThis->m_backend->sScreenGeometry.keyHeight/2)

/* Flag values for prediction key sequence key flags */
#define NO_FLAG                             0
#define SHIFT_CHAR                          1
#define MAX_KEY_FLAG                        1

#define PREFIX_LENGTH            2          /* Database words retrieved in groups according to (currently) first two keys of sequence */

#define MAX_CALLER_SIZE         20

#define MAX_INITIAL_SEGMENTS     3

#define MAX_SUFFIX_POOL_SIZE    200
#define MIN_SUFFIX_POOL_SIZE     50
#define MAX_WORD_POOL_SIZE       55
#define MIN_WORD_POOL_SIZE       30

#define Z1_SEARCH_LEVEL_MIN     1           /* Only one iteration if Z1OperationLevel set all the way to minimum value */
#define Z1_SEARCH_LEVEL_MAX     3           /* Never more than three iterations in searching */

#define Z1_OPERATION_MIN        0
#define Z1_OPERATION_MAX        1000

#define Z1_TASKTIME_LOW         6           /* Execution time for an SCH I909 (varies between 4 and 6) */
#define Z1_TASKTIME_HIGH        13          /* Lowest execution time for an LG VM670 */
#define Z1_OPERATION_INIT_LOW       100     /* These init values correspond to approximately a 4x increase in processing requirements ??? */
#define Z1_OPERATION_INIT_HIGH      500

/* These time factors represent the approximate variation in processing times between an LG VM670 and */
/*    an SCH I909 in an average processing task */
/* TODO: Validate this */
#define Z1_PROCESSOR_TIME_FACTOR_LOW    (float)1.0
#define Z1_PROCESSOR_TIME_FACTOR_HIGH   (float)2.0

/* These time factors represent a more conservative estimate of the approximate variation in processing times between an LG VM670 and */
/*    an SCH I909 in an intensive (worst case) processing task */
/* TODO: Validate this */
#define Z1_PROCESSOR_MAX_TIME_FACTOR_LOW    (float)1.0
#define Z1_PROCESSOR_MAX_TIME_FACTOR_HIGH   (float)2.0

#define THREAD_TIMEOUT_COUNT_MINIMUM    6
#define OUTPUT_STATS_TIMEOUT_COUNT_MINIMUM  10000

#define Z1_OP_PATHSEARCH_EXPAND_MIN1    Z1_OPERATION_INIT_LOW          /* Don't further expand searched path groups if Z1OperationLevel is less than this value */
                                                                       /*   This value should be greater than or equal to Z1_OPERATION_INIT_LOW */
/*#define Z1_OP_PATHSEARCH_EXPAND_MIN1    Z1_OPERATION_VOWEL_TRANSPOSE_LEVEL          // Don't further expand searched path groups unless Z1OperationLevel exceeds this value */
/*                                                                                    //   This value should be higher than Z1_OPERATION_INIT_LOW */
/*#define Z1_OP_PATHSEARCH_EXPAND_MIN2    650         // Don't further expand searched path groups unless Z1OperationLevel exceeds this value */
#define Z1_OP_PATHSEARCH_EXPAND_MIN2    850         /* Don't further expand searched path groups unless Z1OperationLevel exceeds this value */
#define Z1_OP_PATHSEARCH_REDUCE_SUFFIX_MAX    100   /* Reduce searched path groups for suffixes if Z1OperationLevel falls below this value */
#define Z1_OP_CHECK_XY_RATIO_LEVEL      750
#define Z1_OP_REMAP_MINSEARCH_KEYPAIRS  200
#define Z1_OP_REMAP_HALTCHECK1_KEYPAIRS 500
#define Z1_OP_REMAP_HALTCHECK2_KEYPAIRS 650
/*#define Z1_OP_REMAP_ALL_KEYPAIRS        800 */
#define Z1_OP_REMAP_ALL_KEYPAIRS        850
/*#define Z1_OP_CHECK_REMAPPED_SUFFIXES   500 */
#define Z1_OP_CHECK_REMAPPED_SUFFIXES   600

#define Z1_OPERATION_UNDEF      65535

#define Z1_OPERATION_IP_FACTOR      (float)0.75
#define Z1_OPERATION_SEGMENT_FACTOR (float)0.85

/* SavedCodeSegments/SearchDB.cpp/27 */
/* (Previous search fraction definitions) */

/* In order to attain the same relative search load imposed by scoring ALL words */
/* found within (0.70 key pairs * 0.50 suffixes) = 0.35 words of the potentially */
/* matching database words, we can search different proportions of the total number */
/* of potential word matches, scoring only a certain percentage of the candidates */
/* found (according the the frequency group of the candidates). */

/* The strategy below reflects scoring ALL words of frequency groups 4 through 7, */
/* and varying proportions of frequency groups 3, 2, 1 and 0, respectively. */

/* The relative proportions of words are approximated by searching on only the */
/* following proportions of key pairs and suffixes: */

/* Level 0: Total Search Load: ~ 0.209 */

/* Freq Proportion  Fraction    Relative        Cumulative */
/* Class    searched    searched    search load     search load */
/* 7        0.00390625  1.0         0.00390625 */
/* 6        0.0078125   1.0         0.0078125 */
/* 5        0.015625    1.0         0.015625 */
/* 4        0.03125     1.0         0.03125         0.05859375 */
/* 3        0.0625      0.60        0.0375          0.09609375 */
/* 2        0.125       0.30        0.0375          0.13359375 */
/* 1        0.25        0.15        0.0375          0.17109375 */
/* 0        0.50390625  0.075       0.03779296875   0.20888671875 */

/* The relative proportions of words are approximated by searching on only the */
/* following proportions of key pairs and suffixes: */
/* 1.00 searched =  1.00 key pairs * 1.00 suffixes */
/* 0.60 searched =  0.775 key pairs * 0.775 suffixes */
/* 0.30 searched =  0.55 key pairs * 0.55 suffixes */
/* 0.15 searched =  0.39 key pairs * 0.39 suffixes */
/* 0.075 searched = 0.27 key pairs * 0.27 suffixes */

#define MIN_SEARCH_FRACTION_0       (float)0.075
#define MIN_SEARCH_FRACTION_1       (float)0.15
#define MIN_SEARCH_FRACTION_2       (float)0.30
#define MIN_SEARCH_FRACTION_3       (float)0.60

/* The minimum values shown above are interpolated with 1.0 (i.e. searching ALL key pairs and */
/* suffixes) for each frequency class 3, 2, 1 and 0 at the point where the Z1OperationLevel */
/* attains the following values.  In other words, for example, for (Z1OperationLevel >= 500), */
/* all key pairs and suffixes are searched for words of frequency class 3. */
#define MAX_SEARCH_Z1_OPERATION_3   500
#define MAX_SEARCH_Z1_OPERATION_2   600
#define MAX_SEARCH_Z1_OPERATION_1   700
#define MAX_SEARCH_Z1_OPERATION_0   800

#define MAX_SEARCH_ITERATION        3                   /* Maximum number of times search will be performed (with increased Z1OperationLevel) */

#define SEARCH_ALL_KP_SUFFIX_RATIO  (float)0.10         /* Search the top 10% of each suffix fraction over ALL key pairs */

#define SUFFIX_COUNT_RANGE_LOW                90
#define SUFFIX_COUNT_RANGE_HIGH              225
#define SUFFIX_CANDIDATE_COUNT_LIMIT        SUFFIX_COUNT_RANGE_HIGH

#define EXCESS_ERROR_SUFFIX_REDUCTION       0.33            /* Include 2/3 of excess error candidates in merge process */
#define INCLUDED_ERROR_SUFFIX_PROPORTION    0.33            /* Include 1/3 of error candidates in merge process */
#define ERROR_CANDIDATE_MERGE_START_FACTOR  0.15            /* Error candidates follow after top 15% of error-free candidates */
#define ERROR_CANDIDATE_MERGE_START_LOW ((SBYTE2)(SUFFIX_COUNT_RANGE_HIGH * ERROR_CANDIDATE_MERGE_START_FACTOR))

#define HALT_CHECK_LIMIT_LAST_SEARCH_FACTOR  1.5

#define REALLY_BAD_TAP_SCORE                           55555    /* A score which will never win against a real word. */
#define REALLY_BAD_SCORE                        (float)90000.0  /* A score which will never win against a real word. */
#define GOOD_ENOUGH_SCORE_MAX                   (float)20000.0  /* Halt search iterations if we find a combinedScore < 20000.0 */
#define GOOD_ENOUGH_SCORE_MIN                   (float)12500.0  /* Halt search iterations if we find a combinedScore < 12500.0 */
#define GOOD_ENOUGH_SCORE_INIT                  (float)16250.0  /* Halt search iterations if we find a combinedScore < 16250.0 */
#define GOOD_ENOUGH_PENALTY                     (float)1.0      /* Halt search iterations if we find a good enough Score with Penalties < 1.0 */
#define FEW_ENOUGH_SKIPPED_IPS                0                 /* Halt search iterations if we find a good enough Score with no more than 0 skippedIPs */
#define FEW_ENOUGH_KEY_ERRORS                 0                 /* Halt search iterations if we find a good enough Score with no more than 0 key matching errors */

#define GOOD_ENOUGH                   2         /* Flag values for goodWord / goodSuffix fields */
#define FEW_ENOUGH_ERRORS             1
#define UNACCEPTABLE_ERRORS           0

#define ACCEPTABLE_SFX_SCORE_INIT           (float)12000.0  /* Reject all suffixes with combinedScore > 12000 in basic search */

#define SUFFIX_MAX_0_ERRORS_Z1_LEVEL     50             /* Reject all suffixes with any detected errors in basic search when Z1Operation <= 50 */
#define SUFFIX_MAX_1_ERRORS_Z1_LEVEL    400             /* Reject all suffixes with > 1 detected errors in basic search when Z1Operation <= 400 */
#define SUFFIX_MAX_2_ERRORS_Z1_LEVEL    Z1_OPERATION_VOWEL_TRANSPOSE_LEVEL  /* Reject all suffixes with > 2 detected errors in basic search when Z1Operation <= VOWEL_TRANSPOSE_LEVEL */
#define ACCEPTABLE_SUFFIX_MAX_ERRORS            3       /* Reject all suffixes with > 3 detected errors in basic search */

/* Constants to define process for setting limits on execution time allowed for suffix search (SEARCH0) and word search (SEARCH1) */
/*   in first search iteration (ITER1) and second search iteration (ITER2), and for where there is only a single iteration (ITER0), */
/*   and for where (in exceptional cases) there may be an additional final iteration (ITER3) */
#define Z1_SETTING_LEVEL_1                  600             /* First threshold is for current setting <= 600 */
#define Z1_SETTING_LEVEL_2                  800             /* Second threshold is for current setting > 600 && <= 800 */

#define SEARCH0_LIMIT_ADJUST_FACTOR         (float)1.17     /* Pad estimated time limits for first-phase search process */
#define SEARCH1_LIMIT_ADJUST_FACTOR         (float)1.17     /* Pad estimated time limits for second-phase search process */
#define THREAD_TIMEOUT_ADJUST_FACTOR        (float)2.3      /* Pad estimated thread-timeout limit for search process */

#define SEARCH0_Z1_OPERATION_MAX_BASE_LEVEL     100.0           /* Number of millseconds for fast processor (processorSpeedFactor == 1.0) */
#define SEARCH0_ITER0_INCREMENT_LEVEL             0.0
#define SEARCH1_Z1_OPERATION_MAX_BASE_LEVEL     875.0           /* Number of millseconds for fast processor (processorSpeedFactor == 1.0) */
#define SEARCH1_ITER0_INCREMENT_LEVEL             0.0

#define SEARCH0_ITER1_BASE_LEVEL             37.5           /* Number of millseconds for fast processor (processorSpeedFactor == 1.0) */
#define SEARCH0_ITER1_INCREMENT_LEVEL        25.0

#define SEARCH1_ITER1_Z1LEVEL_1             500             /* Threshold test for Z1OperationLevel */
#define SEARCH1_ITER1_BASE_LEVEL_1           25.0           /* Number of millseconds for fast processor (processorSpeedFactor == 1.0) */
#define SEARCH1_ITER1_INCREMENT_LEVEL_1      56.25

#define SEARCH1_ITER1_Z1LEVEL_2             750             /* Threshold test for Z1OperationLevel */
#define SEARCH1_ITER1_BASE_LEVEL_2           81.25          /* Number of millseconds for fast processor (processorSpeedFactor == 1.0) */
#define SEARCH1_ITER1_INCREMENT_LEVEL_2     118.75

#define SEARCH1_ITER1_Z1LEVEL_3             Z1_OPERATION_MAX            /* Threshold test for Z1OperationLevel */
#define SEARCH1_ITER1_BASE_LEVEL_3          200.0           /* Number of millseconds for fast processor (processorSpeedFactor == 1.0) */
#define SEARCH1_ITER1_INCREMENT_LEVEL_3      50.0
#define SEARCH1_ITER1_BASE_LEVEL_4          875.0           /* Number of millseconds for fast processor (processorSpeedFactor == 1.0) */

#define SEARCH_ITER2_Z1LEVEL_1              500             /* Threshold test for Z1OperationLevel */
#define SEARCH0_ITER2_BASE_LEVEL_1           50.0           /* Number of millseconds for fast processor (processorSpeedFactor == 1.0) */
#define SEARCH0_ITER2_INCREMENT_LEVEL_1       0.0
#define SEARCH1_ITER2_BASE_LEVEL_1          125.0           /* Number of millseconds for fast processor (processorSpeedFactor == 1.0) */
#define SEARCH1_ITER2_INCREMENT_LEVEL_1       0.0

#define SEARCH_ITER2_Z1LEVEL_2              Z1_OPERATION_MAX                /* Threshold test for Z1OperationLevel */
#define SEARCH0_ITER2_BASE_LEVEL_2           50.0           /* Number of millseconds for fast processor (processorSpeedFactor == 1.0) */
#define SEARCH0_ITER2_INCREMENT_LEVEL_2      37.5
#define SEARCH1_ITER2_BASE_LEVEL_2          125.0           /* Number of millseconds for fast processor (processorSpeedFactor == 1.0) */
#define SEARCH1_ITER2_INCREMENT_LEVEL_2     475.0

/* Define constants used to set thresholds that determine which path length groups will be */
/*   searched as a function of the current Z1 Operation setting */

#define MIN_POS_TEST_MAXVAL     101

#define MIN_POS_TEST1_LIMIT1    100
#define MIN_POS_TEST1_LIMIT2    850
#define MIN_POS_TEST1_MINVAL     20
#define MIN_POS_TEST1_MAXVAL    101
#define MIN_POS_TEST2_LIMIT1    650
#define MIN_POS_TEST2_LIMIT2   1000
#define MIN_POS_TEST2_MINVAL     -1
#define MIN_POS_TEST2_MAXVAL     60

#define ACTUAL_POS_BELOW_TEST_MAXVAL    101

#define ACTUAL_POS_BELOW_TEST1_LIMIT1  1001
#define ACTUAL_POS_BELOW_TEST1_LIMIT2   200
#define ACTUAL_POS_BELOW_TEST1_MINVAL   101
#define ACTUAL_POS_BELOW_TEST1_MAXVAL   101
#define ACTUAL_POS_BELOW_TEST2_LIMIT1    50
#define ACTUAL_POS_BELOW_TEST2_LIMIT2   900
#define ACTUAL_POS_BELOW_TEST2_MINVAL    10
#define ACTUAL_POS_BELOW_TEST2_MAXVAL   101
#define ACTUAL_POS_BELOW_TEST3_LIMIT1   500
#define ACTUAL_POS_BELOW_TEST3_LIMIT2  1000
#define ACTUAL_POS_BELOW_TEST3_MINVAL    -1
#define ACTUAL_POS_BELOW_TEST3_MAXVAL    67

#define ACTUAL_POS_ABOVE_TEST_MINVAL     -1

#define ACTUAL_POS_ABOVE_TEST1_LIMIT1  1001
#define ACTUAL_POS_ABOVE_TEST1_LIMIT2   200
#define ACTUAL_POS_ABOVE_TEST1_MAXVAL    -1
#define ACTUAL_POS_ABOVE_TEST1_MINVAL    -1
#define ACTUAL_POS_ABOVE_TEST2_LIMIT1    50
#define ACTUAL_POS_ABOVE_TEST2_LIMIT2   900
#define ACTUAL_POS_ABOVE_TEST2_MAXVAL    90
#define ACTUAL_POS_ABOVE_TEST2_MINVAL    -1
#define ACTUAL_POS_ABOVE_TEST3_LIMIT1   500
#define ACTUAL_POS_ABOVE_TEST3_LIMIT2  1000
#define ACTUAL_POS_ABOVE_TEST3_MAXVAL   101
#define ACTUAL_POS_ABOVE_TEST3_MINVAL    33

#define MAX_POS_TEST_MINVAL      -1

#define MAX_POS_TEST1_LIMIT1    150
#define MAX_POS_TEST1_LIMIT2    850
#define MAX_POS_TEST1_MAXVAL    101
#define MAX_POS_TEST1_MINVAL     -1
#define MAX_POS_TEST2_LIMIT1    650
#define MAX_POS_TEST2_LIMIT2   1000
#define MAX_POS_TEST2_MAXVAL    101
#define MAX_POS_TEST2_MINVAL     40

/*#define KP_SKIPPED_IP_DISTANCE_PENALTY     (AngleThreshold8_2/2) */
#define KP_SKIPPED_IP_DISTANCE_PENALTY        AngleThreshold8_2
/*#define KP_SKIPPED_IP_DISTANCE_PENALTY2    (AngleThreshold8_2/5) */
#define KP_SKIPPED_IP_DISTANCE_PENALTY2      (AngleThreshold8_2/3)
#define KP_SKIPPED_IP_DISTANCE_PENALTY2_MGD  (AngleThreshold8_2/2)
#define KP_SKIPPED_IP_SLOPE_FACTOR_PENALTY (float)1.75
#define KP_SKIPPED_IP_SLOPE_FACTOR_PENALTY2 (float)1.25
#define KP_SKIPPED_IP_SLOPE_FACTOR_PENALTY2_MGD (float)1.75

#define KP_NO_PENALTY                   (float)1.0          /* Match-type penalties for key pairs */
#define KP_SEG1_PENALTY                 (float)1.01
/*#define KP_IP3_PENALTY                  (float)2.5 */
/*#define KP_IP3_PENALTY                  (float)2.0 */
#define KP_IP3_PENALTY                  (float)1.5
#define KP_IP3_PENALTY_MGD              (float)2.5
/*#define KP_SEG2_PENALTY                 (float)3.25 */
#define KP_SEG2_PENALTY                 (float)1.75
#define KP_SEG2_PENALTY_MGD             (float)3.25
#define KP_IP1_PENALTY                  (float)2.5
#define KP_ONLY_TWO_MULTIPLE_PENALTY    (float)5.0

#define SP_SKIPPED_IP_DISTANCE_PENALTY     (AngleThreshold8_2/2)
#define SP_SKIPPED_IP_DISTANCE_PENALTY2    (AngleThreshold8_2/5)

#define SP_NO_PENALTY                   (float)1.0          /* Match-type penalties for key pairs */
#define SP_SEG1_PENALTY                 (float)1.01
/*#define SP_IP3_PENALTY                  (float)3.0 */
/*#define SP_IP3_PENALTY                  (float)1.75 */
#define SP_IP3_PENALTY                  (float)1.5
/*#define SP_SEG2_PENALTY                 (float)3.25 */
#define SP_SEG2_PENALTY                 (float)1.75
#define SP_IP1_PENALTY                  (float)2.5
#define SP_ONLY_TWO_MULTIPLE_PENALTY    (float)5.75

#define KP_UNLIKELY_KEY1_PENALTY        (float)2.02
#define KP_UNLIKELY_KEY2_PENALTY        (float)2.04

#define NO_PENALTY              0
#define TENTH_PENALTY           1
#define HALF_PENALTY            2
#define STANDARD_PENALTY        3
#define ONE_AND_A_HALF_PENALTY  4
#define DOUBLE_PENALTY          5
#define TRIPLE_PENALTY          6
#define FOUR_X_PENALTY          7
#define EIGHT_X_PENALTY         8

/* generally expect fewer than 200 matching suffixes placed in table */
#define SUFFIX_TABLE_EXPECTED_SIZE      200
#define LETTER_DOUBLING_CHAR            '^'

/*#define NO_PENALTY_SCORE_RESERVE_COUNT  3               // Reserve three slots for the top-scoring noPenaltyScore words */
#define NO_PENALTY_SCORE_RESERVE_COUNT    0               /* Reserve NO slots for the top-scoring noPenaltyScore words */
#define MAX_CANDIDATE_WORDLIST_COUNT        12
#define MAX_CANDIDATE_WORDLIST_COUNT2        8
#define MAX_CANDIDATE_WORDLIST_COUNT3       20
#define MAX_CANDIDATE_WORDLIST_COUNT4        8
#define MAX_CANDIDATE_WORDLIST_COUNT4NP     12
#define MAX_CANDIDATE_WORDLIST_COUNT5        8

#define MAX_CANDIDATE_WORDLIST_COUNT_NEW         18
#define MAX_CANDIDATE_WORDLIST_COUNT2_NEW        12
#define MAX_CANDIDATE_WORDLIST_COUNT3_EXPANDED   75
#define MAX_CANDIDATE_WORDLIST_COUNT4_NEW        12
#define MAX_CANDIDATE_WORDLIST_COUNT4NP_NEW      18
#define MAX_CANDIDATE_WORDLIST_COUNT5_NEW        12

#define MAX_CANDIDATE_PREDICTIONWORDLIST_COUNT  12
#define MAX_CANDIDATE_PREDICTIONWORDLIST_COUNT2 12
#define ALT_CHARACTER_WORDLIST_POSITION 1
#define HIGHSCORE_BOUNCE_THRESHOLD      (float)2.0
#define SWAP_WORD_SCORE_FACTOR          (float)250.0    /* Score must be no worse than a factor of 100 (???) in order for word-order */
                                                        /*   swap to occur based on GoodWord or gross error count */

/*#define LOW_NO_PENALTY_WCW_POSITION     3               // Position at index 3 (fourth word on first page of WCW) */
#define LOW_NO_PENALTY_WCW_POSITION       7               /* Position at index 7 (last two word on second page of WCW) */

    /* SavedCodeSegments/SearchDB.cpp/99 */

/* Bit flag values for pattern matching */
#define NO_PATTERN_MATCH_FLAG               0x00
#define IP_MATCH_FLAG                       0x01
#define THIS_SEGMENT_MATCH_FLAG             0x02
#define NEXT_SEGMENT_MATCH_FLAG             0x04
#define DUAL_MATCH_FLAG                     0x03
#define MERGED_IP_MATCH_FLAG                0x10
#define MULTIPLE_IPS_MATCH_FLAG             0x20
#define ALL_IP_MATCH_FLAGS                  0x3D        /* Includes all match types except segment */

    /* Flag values for pattern matching */
#define NO_PATTERN_MATCH                    0
#define IP_MATCH                            1
#define THIS_SEGMENT_MATCH                  2
#define NEXT_SEGMENT_MATCH                  3
#define DUAL_MATCH                          4
#define MULTIPLE_KEYS_TO_MERGED_IP_MATCH    5
#define DOUBLE_KEYS_TO_SINGLE_IP_MATCH      6
#define DOUBLE_KEYS_TO_SEGMENT_MATCH        7
#define DOUBLE_KEYS_TO_MULTIPLE_IPS_MATCH   8
#define SEGMENT_MATCH_ONLY                  9
#define NEXT_KEY_IP_MATCH                   10
#define NEXT_KEY_SEGMENT_MATCH              11
#define OMIT_CURRENT_KEY                    12
#define CURRENT_KEY_TRANSPOSED              13
#define OMIT_TRANSPOSED_KEY                 14
#define OMIT_CURRENT_KEY_NOW                15
#define OMIT_PREVIOUS_KEY_NOW               16
#define MATCH_TYPE_COUNT                    17

#if PERFORM_FUTURE_MATCH_CHECK
    #define OMIT_LATER_KEY_NOW              18
#endif

/* Flag values for key skipping and transposition penalties */
#define NO_CHANGE                           0
#define TRANSPOSED_PREV                     1
#define TRANSPOSED_PREV_ONLY                2
#define TRANSPOSED_NEXT                     3
#define OMITTED                             4
#define OMIT_KEY_LATER                      5

    /* Flag values for key transposition types allowed */
#define NO_TRANSPOSITIONS                   0
#define VOWELS_ONLY                         1
#define ALL_TRANSPOSITIONS                  2


#define Z1_OPERATION_VOWEL_TRANSPOSE_LEVEL      300     /* Require max Z1Operation level >= 300 to allow transposition of adjacent vowels */
#define Z1_OPERATION_ANY_TRANSPOSE_LEVEL        950     /* Require max Z1Operation level >= 950 to allow transposition of any adjacent letters */
#define Z1_OPERATION_VOWEL_TRANSPOSE_LEVEL_MGD  500     /* Require max Z1Operation level >= 500 to allow transposition of adjacent vowels in MGD language */
#define Z1_OPERATION_ANY_TRANSPOSE_LEVEL_MGD   2000     /* Require max Z1Operation level >= 2000 (i.e. disallow!) to allow transposition of any adjacent letters in MGD language */


    /* Flag values for future key match checking */
#define NEVER_CHECK                         0
#define CHECK_WHEN_FINAL                    1
#define ALWAYS_CHECK                        2

#define Z1_OPERATION_CHECK_WHEN_FINAL_LEVEL     200     /* Require Z1Operation level >= 200 to enable future key match checking in Final scoring pass */
#define Z1_OPERATION_ALWAYS_CHECK_LEVEL         800     /* Require Z1Operation level >= 800 to enable future key match checking in first pass */

/*#define ADJACENT_KEY_SLOPE_THRESHOLD        (float)140.0    // Maximum slope variance between adjacent keys and matched locs is ~(140/2) = 75 degrees */
/*#define ADJACENT_KEY_SLOPE_THRESHOLD        (float)160.0    // Maximum slope variance between adjacent keys and matched locs is ~(160/2) = 88 degrees */
#define ADJACENT_KEY_SLOPE_THRESHOLD        (float)180.0    /* Maximum slope variance between adjacent keys and matched locs is ~(180/2) = ~90+ degrees */
#define DISTANT_KEY_SLOPE_THRESHOLD          (float)60.0    /* Maximum slope variance between "distant" keys and matched locs is (60/2) = 30 degrees */
#define MAX_ADJACENT_SLOPE_DIF_FACTOR       (float)1.145    /* When adjusted for initial key pair (* 1.75) results in ~1.25 */

/* Z1_FIXED_INTERVAL dependent value: */
#define DISCONTINUOUS_SLOPE_THRESHOLD        (float)80.0    /* Slope variance > 40.7 degrees between successive fixed points */


/*#define ADJACENT_SLOPE_FACTOR_INTERVAL       (float)23.0    // 0.2 of maximum slope variance threshold between "adjacent" keys */
#define ADJACENT_SLOPE_FACTOR_INTERVAL       (float)27.0    /* 0.17 of maximum slope variance threshold between "adjacent" keys */
/*#define ADJACENT_SLOPE_FACTOR_INTERVAL       (float)35.0    // 0.25 of maximum slope variance threshold between "adjacent" keys */
#define DISTANT_SLOPE_FACTOR_INTERVAL        (float)18.0    /* 0.3 of maximum slope variance threshold between "distant" keys */

/*#define SLOPE_FACTOR_BASE                     (float)5.0    // Increase matching score by 20% for each interval increment in slopeFactor */
#define SLOPE_FACTOR_BASE                     (float)4.0    /* Increase matching score by 25% for each interval increment in slopeFactor */
#define MAX_SLOPE_FACTOR                      (float)5.0    /* Limit slopeFactor to a maximum value of 5.0 (constrain results of non-linear heuristics) */
#define STRAIGHT_SEGMENT_RATIO                (float)1.03   /* Do not adjust slopeFactor unless path segment is relatively straight */
#define MAX_SLOPE_FACTOR_ADJUSTMENT           (float)7.0    /* Limit adjustment to slopeFactor to a maximum value of 7.0 (constrain results of non-linear heuristics) */

#define DEFAULT_SLOPE_FACTOR                  (float)1.0    /* Calculate slopeFactor with respect to a default value of 1.0 */
#define MINIMUM_SLOPE_FACTOR                  (float)1.0    /* Calculated slopeFactor always >= default value of 1.0 */
#define DEFAULT_SUFFIX_SLOPE_FACTOR           (float)1.25   /* Use as default local slopeFactor when actual value cannot be estimated in suffix */
#define DEFAULT_UNKNOWN_SLOPE_FACTOR          (float)1.75   /* Use as default local slopeFactor when actual value cannot be estimated */
#define DEFAULT_AVERAGE_SLOPE_FACTOR          (float)1.75   /* Use as average slopeFactor when no actual value can be calculated */
#define DEFAULT_PENALTY_SLOPE_FACTOR          (float)2.25   /* Use as average penalty slopeFactor when no actual value can be calculated */
#define SHORT_PATH_SEGMENT_LENGTH_FACTOR      (float)1.75   /* Use default value of 1.75 when path points are too close to calculate meaningful value */
#define SHIFT_GESTURE_LENGTH_FACTOR           (float)1.5    /* Use default value of 1.5 when shift gesture makes it impossible to calculate meaningful value */
#define SHIFT_GESTURE_KP_LENGTH_FACTOR        (float)1.25   /* Use default value of 1.25 when shift gesture makes it impossible to calculate meaningful value */
#define SHIFT_GESTURE_ENTRY_THRESHOLD   (2 * pThis->m_backend->sScreenGeometry.keyWidth)    /* Scale default value when x-coord of shift gesture exit/entry points is further than threshold distance */
#define DEFAULT_LENGTH_FACTOR                 (float)1.0    /* Use default value of 1.0 no length factor is actually calculated */
#define SKIPPED_IP_LENGTH_FACTOR              (float)4.0    /* Use default value of 4.0 when skipped IP makes it impossible to calculate meaningful value */
#define OMITTED_KEY_LENGTH_FACTOR             (float)1.5    /* Use default value of 1.5 when skipped IP makes it impossible to calculate meaningful value, but key was also omitted */
#define AV_DISTANCE_WEIGHT_FACTOR             (float)0.2    /* Weight applied to average raw distance when adding to weighted score for final result */
/*#define MIN_LEN_FACTOR_DISTANCE8            (float)216.0    // Minimum separation of 1 1/2 key-widths (pThis->m_backend->sScreenGeometry.keyWidth * 8 * 1.5)for valid length factor calculation */
#define MIN_LEN_FACTOR_DISTANCE8            (pThis->m_backend->sScreenGeometry.keyWidth * 12)    /* Minimum separation of 1 1/2 key-widths (pThis->m_backend->sScreenGeometry.keyWidth * 8 * 1.5)for valid length factor calculation */
#define LEN_RATIO_THRESHOLD_DISTANCE8       (pThis->m_backend->sScreenGeometry.keyWidth * 20)    /* Separation of 2 1/2 key-widths (pThis->m_backend->sScreenGeometry.keyWidth * 8 * 2.5) for higher-impact length ratio effect */
#define MAX_ADJACENT_HOPPING_LENGTH_FACTOR    (float)2.5      /* Reasonable limit for lengthFactor when "hopping" between adjacent keys */
#define DEFAULT_ADJACENT_HOPPING_LENGTH_FACTOR (float)1.2      /* Modest default lengthFactor when "hopping" between adjacent keys */
#define ADJACENT_HOPPING_LENGTH_FACTOR_ADJUSTMENT (float)1.0      /* Modest decrease to lengthFactor when calculated for adjacent keys */
#define MAX_INITIAL_LENGTH_FACTOR           (float)2.0      /* Limit base value for determination of lengthFactor */
#define MAX_CURVED_LENGTH_FACTOR            (float)3.75     /* Limit how large lengthFactor becomes in calcSlopeDif() */
#define LENGTH_RATIO_ADJUST_FOR_TWO_IPS         (float)1.2
#define MIN_SLOPE_FACTOR_TWO_IPS                (float)1.2
#define ADJ_MAX_CURVED_LENGTH_FACTOR_TWO_IPS    (float)1.25     /* Limit how large lengthFactor becomes in KeysMatchPoints() */
#define SWAPPED_KEY_SLOPE_THRESHOLD_FACTOR    (float)0.65   /* Insist on resonably good match for swapped key */
#define SWAPPED_KEY_SLOPE_FACTOR_FACTOR       (float)0.65   /* Insist on resonably good match for swapped key */

#define ADJACENT_KEY_DISTANCE_THRESHOLD   (pThis->m_backend->sScreenGeometry.keyHeight + 4)       /* Less than 2 key-widths, but allows vertical adjacency */
#define ADJACENT_KEY_DISTANCE_THRESHOLD8  (pThis->m_backend->sScreenGeometry.keyHeight8 + 32)     /* Less than 2 key-widths, but allows vertical adjacency */
#define DISTANT_KEY_DISTANCE_THRESHOLD    (6 * pThis->m_backend->sScreenGeometry.keyWidth)        /* Greater than 6 key-widths is a large separation */

/*#define MIN_LENGTH_EFFECT                 (float)0.166667   // Minimum length effect for adjacent keys */
#define MIN_LENGTH_EFFECT                 (float)0.125        /* Minimum length effect for adjacent keys */
#define MAX_LENGTH_EFFECT                 (float)1.0          /* Maximum length effect for distant keys */
#define MAX_NO_PENALTY_LENGTH_FACTOR      (float)2.0     /* Limit how much curvature is allowed in matching successive keys without imposing a penalty */
#define EXCESSIVE_LENGTH_FACTOR           (float)2.5     /* Limit how much curvature is allowed in matching successive keys without imposing a stiffer penalty */

#define MAX_NO_PENALTY_CURVATURE_RATIO    (float)2.25     /* Limit how much curvature is allowed in matching successive keys without imposing a penalty */
#define MAX_NO_PENALTY_CURVATURE_RATIO2   (float)2.0      /* Limit how much curvature is allowed in matching successive keys without imposing a penalty */
#define EXCESSIVE_CURVATURE_PENALTY       (float)0.30     /* Impose a penalty proportional to excessive curvature */
#define EXCESSIVE_CURVATURE_PENALTY2      (float)0.35     /* Impose a penalty proportional to excessive curvature */
#define MAX_CURVATURE_PENALTY             (float)2.25     /* Limit penalty imposed for excessive curvature */

#define MIN_TWO_LETTER_HIGH_FREQ     6      /* Improve score for last letter of two-letter words in frequencu classes 6 or 7 */

#define PATH_DIFFERENCE_FACTOR      (float)1.75 /* Allow IP match to be up to 1.75 * (current Angle match threshold) further from a segment match */
#define PATH_TO_SEGMENT_THRESHOLD1  (3 * pThis->m_backend->sScreenGeometry.keyWidth / 2)    /* When path distance to segment match location is < 1.5 pThis->m_backend->sScreenGeometry.keyWidths, */
#define PATH_DIFFERENCE_THRESHOLD1  (3 * pThis->m_backend->sScreenGeometry.keyWidth)        /*   allow IP path to be up to 2.5 KEY_WIDTHs longer */

#define DISTANT_MATCH_THRESHOLD     (float)0.8      /* Key match is "distant" if it is >= 80% of the maximum threshold */
#define BETTER_MATCH_THRESHOLD      (float)0.6      /* Key match is "distant" if it is < 60% of the the "distant" match's matching ratio */
#define USE_SEGMENT_MATCH_THRESHOLD (float)0.15     /* Sacrifice IP match and use segment if match is > 6 times better for segment */


#if     !FINGER_KEYBOARD

/* Double gesture thresholds for stylus use */

/* Changed to including current location when computing average location PRIOR to qualifying current location (and all previous locations) */
/*#define MULTIPLE_IP_VERTICAL_MARGIN    9      // Keep DoubleLetter Multiple IPs horizontally aligned (within approximately one key row) */
/*#define MULTIPLE_IP_VERTICAL_MARGIN       (DOUBLE_GESTURE_MAX_RADIUS/3)       // Keep DoubleLetter Multiple IPs horizontally aligned (within X * max radius of DoubleLetter gesture) */
#if SCRIBBLE_IS_HORIZONTAL
    #define MULTIPLE_IP_VERTICAL_MARGIN     (DOUBLE_GESTURE_MAX_RADIUS/2)       /* Keep DoubleLetter Multiple IPs horizontally aligned (within max radius of DoubleLetter gesture) */
#else
    #define MULTIPLE_IP_VERTICAL_MARGIN     DOUBLE_GESTURE_MAX_RADIUS       /* Keep DoubleLetter Multiple IPs horizontally aligned (within max diameter of DoubleLetter gesture) */
#endif
/*#define MULTIPLE_IP_HORIZONTAL_MARGIN (DOUBLE_GESTURE_MAX_RADIUS/2)       // Keep DoubleLetter Multiple IPs vertically aligned (within max radius of DoubleLetter gesture) */
#define MULTIPLE_IP_HORIZONTAL_MARGIN   DOUBLE_GESTURE_MAX_RADIUS           /* Keep DoubleLetter Multiple IPs horizontally aligned (within max diameter of DoubleLetter gesture) */
#define MULTIPLE_IP_MAX_DISTANCE        DOUBLE_GESTURE_MAX_DIAM             /* Keep DoubleLetter Multiple IPs horizontally aligned (within max diameter of DoubleLetter gesture) */
#define MULTIPLE_IP_THRESHOLD_DISTANCE      (3 * pThis->m_backend->sScreenGeometry.keyWidth / 2)                /* DoubleLetter Multiple IPs within less than 1.5 KEY_WIDTH of each other subject to relaxed path curvature requirement */
/*#define Y_TO_X_SUM_MAX_RATIO      0.4 */
#define Y_TO_X_SUM_MAX_RATIO        0.9

#define SINGLE_KEY_PATH_MAX_WIDTH           ((4*pThis->m_backend->sScreenGeometry.keyWidth)/3)
#define SINGLE_KEY_PATH_MAX_HEIGHT          ((4*pThis->m_backend->sScreenGeometry.keyHeight)/3)
#define SINGLE_KEY_PATH_ROW_CENTER_MARGIN   (pThis->m_backend->sScreenGeometry.keyHeight/4)

#else

/* Double gesture thresholds for fingertip use */

/* Changed to including current location when computing average location PRIOR to qualifying current location (and all previous locations) */
#if SCRIBBLE_IS_HORIZONTAL
    #define MULTIPLE_IP_VERTICAL_MARGIN     (DOUBLE_GESTURE_MAX_RADIUS/2)       /* Keep DoubleLetter Multiple IPs horizontally aligned (within max radius of DoubleLetter gesture) */
#else
    #define MULTIPLE_IP_VERTICAL_MARGIN     DOUBLE_GESTURE_MAX_RADIUS       /* Keep DoubleLetter Multiple IPs horizontally aligned (within max diameter of DoubleLetter gesture) */
#endif
#define MULTIPLE_IP_HORIZONTAL_MARGIN   DOUBLE_GESTURE_MAX_RADIUS           /* Keep DoubleLetter Multiple IPs horizontally aligned (within max diameter of DoubleLetter gesture) */
#define MULTIPLE_IP_MAX_DISTANCE        DOUBLE_GESTURE_MAX_DIAM             /* Keep DoubleLetter Multiple IPs horizontally aligned (within max diameter of DoubleLetter gesture) */
#define MULTIPLE_IP_THRESHOLD_DISTANCE      (pThis->m_backend->sScreenGeometry.keyWidth)                /* DoubleLetter Multiple IPs within less than 1 KEY_WIDTH of each other subject to relaxed path curvature requirement */
#define MULTIPLE_IP_PATH_DISTANCE_RATIO_CHECK_DISTANCE_THRESHOLD    (2 * pThis->m_backend->sScreenGeometry.keyWidth / 3)    /* Check path-to-distance ratio if successive points meet either minimum distance or minimum path length */
#define MULTIPLE_IP_PATH_DISTANCE_RATIO_CHECK_PATH_THRESHOLD        (3 * pThis->m_backend->sScreenGeometry.keyWidth / 2)    /*   separation.  Otherwise, assume points pass the test. */
#define Y_TO_X_SUM_MAX_RATIO        0.9

#define SINGLE_KEY_PATH_MAX_WIDTH           (2*pThis->m_backend->sScreenGeometry.keyWidth)
#define SINGLE_KEY_PATH_MAX_HEIGHT          ((5*pThis->m_backend->sScreenGeometry.keyHeight)/3)
#define SINGLE_KEY_PATH_ROW_CENTER_MARGIN   (pThis->m_backend->sScreenGeometry.keyHeight/3)

#endif

#define OVERSHOOT_PATH_ESTIMATE     pThis->m_backend->sScreenGeometry.keyWidth      /* Allow for one key-width of overshoot for each Angle IP (1/2 key-width each half of "round trip") and PenDown, PenUp */
#define UNDERSHOOT_PATH_ESTIMATE    pThis->m_backend->sScreenGeometry.keyWidth      /* Allow for one key-width of undershoot for each Angle IP (1/2 key-width each half of "round trip") and PenDown, PenUp */

#define MAX_AMBIGUITY_LEVEL (float)10.0             /* Max Ambiguous point level is 9.0 */
#define RED_LEVEL           (float)8.0              /* Ambiguous point level >= 8 shows ambiguous words in RED */
#define YELLOW_LEVEL        (float)6.0              /* Ambiguous point level >= 6 shows ambiguous words in YELLOW */
#define GREEN_LEVEL         (float)4.5              /* Ambiguous point level >= 4.5 shows default word in GREEN */
#define NONE_LEVEL          (float)1.0              /* Ambiguous point level <= 1 suppresses WCW */

#define RED_SCORE_LEVEL         800             /* Ambiguous score level >= 800 shows ambiguous words in RED */
#define YELLOW_SCORE_LEVEL      600             /* Ambiguous score level >= 600 shows ambiguous words in YELLOW */
#define GREEN_SCORE_LEVEL       450             /* Ambiguous score level >= 450 shows default word in GREEN */
#define NONE_SCORE_LEVEL        100             /* Ambiguous score level <= WCW Slider level suppresses WCW */

#define BETTER_SCORE_THRESHOLD_FACTOR   3       /* Set "betterScore" flag to true if noPenaltyScore is < (3 * noPenaltyScore) of default word */

                                            /* Following thresholds are %age differences between 1st and 2nd-place combinedScore values */
                                            /* SavedCodeSegments/SearchDB.cpp/100 (Historical values used previously) */
#define VERY_AMBIGUOUS_SCORE         (float)50.0        /* If 2nd best score no more than 50% greater than top score, result is very ambiguous */
#define AMBIGUOUS_SCORE             (float)100.0        /* If 2nd best score no more than 100% greater than top score, result is ambiguous */
#define SOMEWHAT_AMBIGUOUS_SCORE    (float)250.0        /* If 2nd best score no more than 250% greater than top score, result is somewhat ambiguous */
#define NOT_VERY_AMBIGUOUS_SCORE    (float)500.0        /* If 2nd best score IS more than 500% greater than top score, result is not very ambiguous */
#define UNAMBIGUOUS_SCORE          (float)1000.0        /* If 2nd best score IS more than 1000% greater than top score, result is "not ambiguous" */

                                            /* Following values are "ambiguous points" assessed based on combinedScore difference values */
#define VERY_AMBIGUOUS_POINTS       (float)8.0      /* If score difference indicates result is very ambiguous */
#define AMBIGUOUS_POINTS            (float)5.5      /* If score difference indicates result is ambiguous */
#define SOMEWHAT_AMBIGUOUS_POINTS   (float)3.0      /* If score difference indicates result is somewhat ambiguous */
#define NOT_VERY_AMBIGUOUS_POINTS   (float)1.5      /* If score difference indicates result is not very ambiguous */
#define UNAMBIGUOUS_POINTS          (float)0.0      /* If score difference indicates result is "not ambiguous" */
#define OPPOSITE_SIGN_POINTS        (float)2.0      /*  ...but the two difference ratio values have opposite signs. */

                                                    /* Following thresholds are %age differences between 1st and 2nd-place noPenaltyScore values */
#define VERY_AMBIGUOUS_SCORE1       (float)10.0     /* If 2nd best score differs by no more than 15% from top score, result is very ambiguous */
#define AMBIGUOUS_SCORE1            (float)20.0     /* If 2nd best score is less than or equal to top score, result is still ambiguous */
#define SOMEWHAT_AMBIGUOUS_SCORE1   (float)40.0     /* If 2nd best score is less than 20% greater than top score, result is somewhat ambiguous */
#define NOT_VERY_AMBIGUOUS_SCORE1   (float)80.0     /* If 2nd best score is more than 50% greater than top score, result is not very ambiguous */
#define UNAMBIGUOUS_SCORE1         (float)120.0     /* If 2nd best score is more than 120% greater than top score, result is "not ambiguous" */

                                            /* Following values are "ambiguous points" assessed based on noPenaltyScore difference values */
#define VERY_AMBIGUOUS_POINTS1      (float)5.0      /* If score difference indicates result is very ambiguous */
#define AMBIGUOUS_POINTS1           (float)3.5      /* If score difference indicates result is ambiguous */
#define SOMEWHAT_AMBIGUOUS_POINTS1  (float)2.0      /* If score difference indicates result is somewhat ambiguous */
#define NOT_VERY_AMBIGUOUS_POINTS1  (float)1.0      /* If score difference indicates result is not very ambiguous */
#define UNAMBIGUOUS_POINTS1         ((float)-1.0)   /* If score difference indicates result is "not ambiguous" */
                                            /* Assign higher ambiguity when results have opposite signs */
#define VERY_AMBIGUOUS_POINTS12     (float)6.5      /* If score difference indicates result is very ambiguous */
#define AMBIGUOUS_POINTS12          (float)5.0      /* If score difference indicates result is ambiguous */
#define SOMEWHAT_AMBIGUOUS_POINTS12 (float)3.5      /* If score difference indicates result is somewhat ambiguous */
#define NOT_VERY_AMBIGUOUS_POINTS12 (float)2.0      /* If score difference indicates result is not very ambiguous */
#define UNAMBIGUOUS_POINTS12        (float)1.0      /* If score difference indicates result is "not ambiguous" */

                                            /* Following values are based on average of (combinedScore difference + noPenaltyScore difference) values */
                                            /*   when the two difference ratio values have opposite signs. */
#define VERY_AMBIGUOUS_SCORE_SUM        (float)10.0     /* If two ratios differ by no more than 10%, result is very ambiguous */
#define AMBIGUOUS_SCORE_SUM             (float)20.0     /* If two ratios differ by no more than 20%, result is ambiguous */
#define SOMEWHAT_AMBIGUOUS_SCORE_SUM    (float)35.0     /* If two ratios differ by no more than 35%, result is somewhat ambiguous */
#define NOT_VERY_AMBIGUOUS_SCORE_SUM    (float)55.0     /* If two ratios differ by no more than 55%, result is not very ambiguous */
#define UNAMBIGUOUS_SCORE_SUM          (float)100.0     /* If two ratios differ by more than 100%, result is "not ambiguous" */

#define VERY_AMBIGUOUS_POINTS_SUM       (float)3.0      /* If sum of opposite-signed score difference ratios indicates result is very ambiguous */
#define AMBIGUOUS_POINTS_SUM            (float)2.5      /* If sum of score difference ratios indicates result is ambiguous */
#define SOMEWHAT_AMBIGUOUS_POINTS_SUM   (float)2.0      /* If sum of score difference ratios indicates result is somewhat ambiguous */
#define NOT_VERY_AMBIGUOUS_POINTS_SUM   (float)1.0      /* If sum of score difference ratios indicates result is not very ambiguous */
#define UNAMBIGUOUS_POINTS_SUM          (float)0.0      /* If sum of score difference ratios indicates result is "not ambiguous" */


#define MAX_SUFFIX_LEN              12      /* ??? Determine appropriate value! */
#define MAX_DOUBLE_KEYS             16      /* Maximum possible number given max word length of 32 */

/* SavedCodeSegments/SearchDB.cpp/21 */

/* SavedCodeSegments/SearchDB.cpp/82  - History of Penalty Definitions */

/* Penalty Definitions */
/* Define all penalties with respect to a base of 1.0 (i.e. 0.5 increases score by 50%, etc.) */
#define SHIFT_PENALTY_0              (float)2.0             /* Odd path for shifted first letter, or odd letter for normal first-letter-shift path */
#define SHIFT_PENALTY_1              (float)8.0             /* McDoNALd... */
#define SHIFT_PENALTY_2A             (float)7.0             /* wRong... */
#define SHIFT_PENALTY_2B             (float)3.5             /* iPAQ; other single non-initial shifted letter */
#define SHIFT_PENALTY_2C             (float)0.25            /* iTunes, iPod, etc. */
#define SHIFT_PENALTY_3A             (float)1.25            /* ICBMs, PCs */
#define SHIFT_PENALTY_3B             (float)5.5             /* McDONALD */
#define SHIFT_PENALTY_3C             (float)2.5             /* McDonald */
#define SHIFT_PENALTY_3D             (float)8.0             /* McDoNALd..., MCDoNALD, McdoNald */
#define SHIFT_PENALTY_4              (float)4.5             /* iWHat... */
#define SHIFT_PENALTY_5              (float)2.5             /* ilasT */

#define DIACRITIC_PENALTY_1          (float)0.5

#define SKIPPED_PEN_UP               (float)1.6
#define SKIPPED_PEN_DOWN             (float)3.0
#define SKIPPED_PEN_UP_DOWN          (float)1.6
#define PATH_DIVISION_WITHOUT_SEGMENT_MATCH      (float)1.0             /* IP generated within a DoubleLetter gesture that is matched to a single key */

#define SKIPPED_DOUBLE_IP            (float)1.4             /* DoubleLetter IP that is skipped entirely */
#define SKIPPED_ANGLE_IP             (float)1.0
#define SKIPPED_ANGLE_IP_MIN         (float)0.35
#define SKIPPED_ANGLE_IP_MAX         (float)1.0
#define SKIPPED_PAUSE_IP             (float)0.25
#define SKIPPED_PAUSEANGLE_IP        (float)0.2
#define SKIPPED_PAUSEANGLE_IP_MIN    (float)(SKIPPED_ANGLE_IP_MIN * PAUSE_ANGLE_WEIGHT_FACTOR)
#define SKIPPED_PAUSEANGLE_IP_MAX    (float)(SKIPPED_ANGLE_IP_MAX * PAUSE_ANGLE_WEIGHT_FACTOR)

#define SKIPPED_MULTIPLE_IP          (float)0.0

#define SKIPPED_SOFT_UP              (float)0.0             /* No penalty for skipping SoftUp IP */
#define SKIPPED_DOUBLE_IP_SOFT_UP    (float)0.5         /* Add a penalty if this was included as part of Double gesture */

#define SKIPPED_SOFT_DOWN            (float)0.0             /* No penalty for skipping SoftDown */
#define SKIPPED_SOFT_IP              (float)0.0             /* No penalty for skipping Soft IP */
#define SKIPPED_EXIT_IP              (float)0.0             /* No penalty for skipping Exit IP */
#define SKIPPED_ENTRY_IP             (float)0.0             /* No penalty for skipping Entry IP */

#define SINGLE_KEY_TO_DOUBLE_IP      (float)0.5             /* IP generated within a DoubleLetter gesture that is matched to a single key */
#define SINGLE_KEY_TO_MERGED_IP      (float)0.0             /* Multiple (merged) IP that is matched to a single key */
#define MULTIPLE_KEYS_TO_MERGED_IP   (float)0.8             /* Multiple (merged) IP that is matched to two distinct keys */

/* Double letter gesture penalties used when the language (e.g. Finnish) requires the original, relatively harsh penalty */
#define KP_DOUBLE_TO_SINGLE_PENALTY     (float)7.5
#define SP_DOUBLE_TO_SINGLE_PENALTY     (float)7.5
#define DOUBLE_KEYS_TO_SEGMENT       (float)1.0                 /* Double-letter in word that is matched to a segment */
#define DOUBLE_KEYS_TO_SINGLE_IP     (float)0.7                 /* Double-letter in word that is matched to a single-key (Angle) IP */
#define DOUBLE_KEYS_TO_SINGLE_IP_ONLY2_IPS   (float)0.25        /* Double-letter in word that is matched to a single-key (Angle) IP when path has only 2 IPs */
#define DOUBLE_KEYS_TO_SINGLE_IP_ONLY3_IPS   (float)0.15        /* Double-letter in word that is matched to a single-key (Angle) IP when path has only 3 IPs */
#define DOUBLE_KEYS_TO_MERGED_IP        (float)0.25             /* Double-letter in word that is matched to a merged IP (two or more neigboring Angle IPs) */

#define EXCESS_DOUBLE_KEYS_PENALTY_ALLOWANCE (float)1.0

/* Double letter gesture penalties used for short (2 IPs only), relatively straight paths */
#define KP_DOUBLE_TO_SINGLE_PENALTY_1   (float)1.1
#define SP_DOUBLE_TO_SINGLE_PENALTY_1   (float)1.1
/*#define DOUBLE_KEYS_TO_SEGMENT_1     (float)0.25                 // Double-letter in word that is matched to a segment */
/*#define DOUBLE_KEYS_TO_SINGLE_IP_1   (float)0.15                 // Double-letter in word that is matched to a single-key (Angle) IP */
/*#define DOUBLE_KEYS_TO_SINGLE_IP_ONLY2_IPS_1  (float)0.15        // Double-letter in word that is matched to a single-key (Angle) IP when path has only 2 IPs */
/*#define DOUBLE_KEYS_TO_SINGLE_IP_ONLY3_IPS_1  (float)0.10        // Double-letter in word that is matched to a single-key (Angle) IP when path has only 3 IPs */
/*#define DOUBLE_KEYS_TO_MERGED_IP_1      (float)0.05              // Double-letter in word that is matched to a merged IP (two or more neigboring Angle IPs) */
#define DOUBLE_KEYS_TO_SEGMENT_1     (float)0.00                 /* Double-letter in word that is matched to a segment */
#define DOUBLE_KEYS_TO_SINGLE_IP_1   (float)0.00                 /* Double-letter in word that is matched to a single-key (Angle) IP */
#define DOUBLE_KEYS_TO_SINGLE_IP_ONLY2_IPS_1  (float)0.00        /* Double-letter in word that is matched to a single-key (Angle) IP when path has only 2 IPs */
#define DOUBLE_KEYS_TO_SINGLE_IP_ONLY3_IPS_1  (float)0.00        /* Double-letter in word that is matched to a single-key (Angle) IP when path has only 3 IPs */
#define DOUBLE_KEYS_TO_MERGED_IP_1      (float)0.00              /* Double-letter in word that is matched to a merged IP (two or more neigboring Angle IPs) */

#define EXCESS_DOUBLE_KEYS_PENALTY_ALLOWANCE_1 (float)0.15

/* Double letter gesture penalties used for all other paths */
#define KP_DOUBLE_TO_SINGLE_PENALTY_2   (float)1.1
#define SP_DOUBLE_TO_SINGLE_PENALTY_2   (float)1.1
/*#define DOUBLE_KEYS_TO_SEGMENT_2     (float)0.20                 // Double-letter in word that is matched to a segment */
/*#define DOUBLE_KEYS_TO_SINGLE_IP_2   (float)0.10                 // Double-letter in word that is matched to a single-key (Angle) IP */
/*#define DOUBLE_KEYS_TO_SINGLE_IP_ONLY2_IPS_2  (float)0.15        // Double-letter in word that is matched to a single-key (Angle) IP when path has only 2 IPs */
/*#define DOUBLE_KEYS_TO_SINGLE_IP_ONLY3_IPS_2  (float)0.10        // Double-letter in word that is matched to a single-key (Angle) IP when path has only 3 IPs */
/*#define DOUBLE_KEYS_TO_MERGED_IP_2      (float)0.00              // Double-letter in word that is matched to a merged IP (two or more neigboring Angle IPs) */
#define DOUBLE_KEYS_TO_SEGMENT_2     (float)0.00                 /* Double-letter in word that is matched to a segment */
#define DOUBLE_KEYS_TO_SINGLE_IP_2   (float)0.0                /* Double-letter in word that is matched to a single-key (Angle) IP */
#define DOUBLE_KEYS_TO_SINGLE_IP_ONLY2_IPS_2  (float)0.00        /* Double-letter in word that is matched to a single-key (Angle) IP when path has only 2 IPs */
#define DOUBLE_KEYS_TO_SINGLE_IP_ONLY3_IPS_2  (float)0.00        /* Double-letter in word that is matched to a single-key (Angle) IP when path has only 3 IPs */
#define DOUBLE_KEYS_TO_MERGED_IP_2      (float)0.00              /* Double-letter in word that is matched to a merged IP (two or more neigboring Angle IPs) */

#define EXCESS_DOUBLE_KEYS_PENALTY_ALLOWANCE_2 (float)0.15

/*#define DOUBLE_KEYS_TO_MULTIPLE_IPS     (float)0.05             // Double-letter in word that is matched to two (or more) successive single-key (Angle) IPs */
/*#define DOUBLE_KEYS_TO_MULTIPLE_IPS_SFX (float)0.1              // Double-letter in suffix that is matched to two (or more) successive single-key (Angle) IPs */
/*#define MULTIPLE_IPS_INCLUDE_PEN_UP     (float)0.15             // Additional penalty when multiple IPs include the PenUp IP */
/*#define PEN_UP_NOT_IN_GESTURE           (float)1.25             // Additional penalty when multiple IPs (including PenUp) are from a DoubleLetter gesture, */
/*#define MULTIPLE_IPS_INCLUDE_PEN_UP_SFX (float)0.15             // Additional penalty when multiple IPs include the PenUp IP */
/*//#define MULTIPLE_IPS_INCLUDE_PEN_DOWN   (float)0.5              // Additional penalty when multiple IPs include the PenDown IP */
/*#define MULTIPLE_IPS_INCLUDE_PEN_DOWN   (float)0.25              // Additional penalty when multiple IPs include the PenDown IP */
/*#define PEN_DOWN_NOT_IN_GESTURE         (float)1.25             // Additional penalty when multiple IPs (including PenDown) are from a DoubleLetter gesture, */
/*                                                                  //   but the gesture does not include the PenDown IP */
/*#define MULTIPLE_IPS_ONLY_2_IPS_IN_TABLE        (float)2.5      // Additional penalty when multiple IPs matched when total IP count == 2 */
/*#define MULTIPLE_IPS_ONLY_2_IPS_IN_TABLE_SFX    (float)2.75     // Additional penalty when multiple IPs matched when total IP count == 2 */
/*//#define MULTIPLE_IPS_ONLY_3_IPS_IN_TABLE        (float)2.0      // Additional penalty when multiple IPs matched when total IP count == 3 */
/*//#define MULTIPLE_IPS_ONLY_3_IPS_IN_TABLE_SFX    (float)1.5      // Additional penalty when multiple IPs matched when total IP count == 3 */
/*#define MULTIPLE_IPS_ONLY_3_IPS_IN_TABLE        (float)0.5      // Additional penalty when multiple IPs matched when total IP count == 3 */
/*#define MULTIPLE_IPS_ONLY_3_IPS_IN_TABLE_SFX    (float)0.5      // Additional penalty when multiple IPs matched when total IP count == 3 */
/*//#define MULTIPLE_IPS_ONLY_2_IPS                 (float)0.20     // Additional penalty when multiple IPs matched when only 2 IPs in Multiple group */
/*#define MULTIPLE_IPS_ONLY_2_IPS                 (float)0.10     // Additional penalty when multiple IPs matched when only 2 IPs in Multiple group */
/*//#define MULTIPLE_IPS_ONLY_2_IPS_SFX             (float)0.25     // Additional penalty when multiple IPs matched when only 2 IPs in Multiple group */
/*#define MULTIPLE_IPS_ONLY_2_IPS_SFX             (float)0.10     // Additional penalty when multiple IPs matched when only 2 IPs in Multiple group */
/*#define FOURTH_MULTIPLE_IPS_PENALTY  (float)0.075           // 0.075 penalty points for first extra IP when count exceeds 3 */
/*//#define EXCESS_MULTIPLE_IPS_PENALTY  (float)0.4             // 0.4 penalty points for each additional extra IP when count exceeds 4 */
/*//#define EXCESS_MULTIPLE_IPS_PENALTY2 (float)0.4             // 0.4 penalty points for each additional extra IP when count exceeds 6 */
/*//#define EXCESS_MULTIPLE_IPS_PENALTY  (float)0.25             // 0.25 penalty points for each additional extra IP when count exceeds 4 */
/*//#define EXCESS_MULTIPLE_IPS_PENALTY2 (float)0.3             // 0.3 penalty points for each additional extra IP when count exceeds 6 */
/*#define EXCESS_MULTIPLE_IPS_PENALTY  (float)0.15             // 0.15 penalty points when total multiple IP count exceeds 4 */

#define DOUBLE_KEYS_TO_MULTIPLE_IPS     (float)0.05             /* Double-letter in word that is matched to two (or more) successive single-key (Angle) IPs */
#define DOUBLE_KEYS_TO_MULTIPLE_IPS_SFX (float)0.05              /* Double-letter in suffix that is matched to two (or more) successive single-key (Angle) IPs */
#define MULTIPLE_IPS_INCLUDE_PEN_UP     (float)0.05             /* Additional penalty when multiple IPs include the PenUp IP */
#define PEN_UP_NOT_IN_GESTURE           (float)1.25             /* Additional penalty when multiple IPs (including PenUp) are from a DoubleLetter gesture, */
                                                                /*   but the gesture does not include the PenUp IP */
#define MULTIPLE_IPS_INCLUDE_PEN_UP_SFX (float)0.15             /* Additional penalty when multiple IPs include the PenUp IP */
/*#define MULTIPLE_IPS_INCLUDE_PEN_DOWN   (float)0.5              // Additional penalty when multiple IPs include the PenDown IP */
#define MULTIPLE_IPS_INCLUDE_PEN_DOWN   (float)0.25              /* Additional penalty when multiple IPs include the PenDown IP */
#define PEN_DOWN_NOT_IN_GESTURE         (float)1.25             /* Additional penalty when multiple IPs (including PenDown) are from a DoubleLetter gesture, */
                                                                /*   but the gesture does not include the PenDown IP */
#define MULTIPLE_IPS_ONLY_2_IPS_IN_TABLE        (float)0.25      /* Additional penalty when multiple IPs matched when total IP count == 2 */
#define MULTIPLE_IPS_ONLY_2_IPS_IN_TABLE_SFX    (float)1.25     /* Additional penalty when multiple IPs matched when total IP count == 2 */
/*#define MULTIPLE_IPS_ONLY_3_IPS_IN_TABLE        (float)2.0      // Additional penalty when multiple IPs matched when total IP count == 3 */
/*#define MULTIPLE_IPS_ONLY_3_IPS_IN_TABLE_SFX    (float)1.5      // Additional penalty when multiple IPs matched when total IP count == 3 */
#define MULTIPLE_IPS_ONLY_3_IPS_IN_TABLE        (float)0.05      /* Additional penalty when multiple IPs matched when total IP count == 3 */
#define MULTIPLE_IPS_ONLY_3_IPS_IN_TABLE_SFX    (float)0.05      /* Additional penalty when multiple IPs matched when total IP count == 3 */
/*#define MULTIPLE_IPS_ONLY_2_IPS                 (float)0.20     // Additional penalty when multiple IPs matched when only 2 IPs in Multiple group */
#define MULTIPLE_IPS_ONLY_2_IPS                 (float)0.10     /* Additional penalty when multiple IPs matched when only 2 IPs in Multiple group */
/*#define MULTIPLE_IPS_ONLY_2_IPS_SFX             (float)0.25     // Additional penalty when multiple IPs matched when only 2 IPs in Multiple group */
#define MULTIPLE_IPS_ONLY_2_IPS_SFX             (float)0.10     /* Additional penalty when multiple IPs matched when only 2 IPs in Multiple group */
#define FOURTH_MULTIPLE_IPS_PENALTY  (float)0.05            /* 0.05 penalty points for first extra IP when count exceeds 3 */
/*#define EXCESS_MULTIPLE_IPS_PENALTY  (float)0.4             // 0.4 penalty points for each additional extra IP when count exceeds 4 */
/*#define EXCESS_MULTIPLE_IPS_PENALTY2 (float)0.4             // 0.4 penalty points for each additional extra IP when count exceeds 6 */
/*#define EXCESS_MULTIPLE_IPS_PENALTY  (float)0.25             // 0.25 penalty points for each additional extra IP when count exceeds 4 */
/*#define EXCESS_MULTIPLE_IPS_PENALTY2 (float)0.3             // 0.3 penalty points for each additional extra IP when count exceeds 6 */
#define EXCESS_MULTIPLE_IPS_PENALTY  (float)0.05             /* 0.05 penalty points when total multiple IP count exceeds 4 */

#define MAX_SINGLE_KEY_SCORING_PENALTY  (float)1.5          /* Limit local scoring penalty to (1.5 * penalized_key_score) */
#define KEY_OMITTED_PENALTY          (float)1.5             /* Letter omission more "severe" than insertion (SKIPPED_ANGLE_IP) */
#define KEY_TRANSPOSED_PENALTY       (float)1.25            /* Letter transposition similar to omission unless both keys are vowels (SKIPPED_ANGLE_IP) */
#define VOWEL_TRANSPOSED_PENALTY     (float)0.5             /* Vowel transposition less severe than other transposition, omission or insertion (SKIPPED_ANGLE_IP) */
#define KEY_SUBSTITUTED_PENALTY      (float)1.25                /* Letter substitution less severe than transposition or omission */
#define EXCESS_IPS_PENALTY           (float)0.4             /* Penalty for each extra IP when counts exceeds (2 * word-length) */

/* The following three */
#define KP_KEY_SUBSTITUTED_PENALTYFACTOR   (float)2.0       /* Letter substitution is lowest penalty */
#define KP_KEY_INSERTED_PENALTYFACTOR      (float)2.25      /* Letter insertion more "severe" than substitution */
#define KP_KEY_OMITTED_PENALTYFACTOR       (float)3.25      /* Letter omission more "severe" than insertion */

#define MAX_GOOD_PATH_SIZE           (float)1.75
#define PATH_SIZE_PENALTY            (float)0.4

#define PENALTY_SURCHARGE_LENGTH1               3           /* Add extra penalty for skipped IPs if word is 3 letters or less */

#define SKIPPED_IP_SURCHARGE_FACTOR1            (float)0.5      /* Add in 0.5 times the sum of the actual skipped IP penalties */
#define SPELLING_ERROR_SURCHARGE_FACTOR1        (float)0.5      /* Add in 0.5 times the sum of the key omission, etc., penalties */
#define PENALTY_DISTANCE_SURCHARGE_FACTOR1      (float)0.75
#define PENALTY_SCORE_SURCHARGE_FACTOR1         (float)0.75
#define PENALTY_WEIGHT_SURCHARGE_FACTOR1        (float)0.75

#define PENALTY_SURCHARGE_LENGTH2               4           /* Add extra penalty for skipped IPs if word is 3 letters or less */

#define SKIPPED_IP_SURCHARGE_FACTOR2            (float)0.5      /* Add in 1.5 times the sum of the actual skipped IP penalties */
#define SPELLING_ERROR_SURCHARGE_FACTOR2        (float)0.5      /* Add in 1.5 times the sum of the key omission, etc., penalties */
#define PENALTY_DISTANCE_SURCHARGE_FACTOR2      (float)0.5
#define PENALTY_SCORE_SURCHARGE_FACTOR2         (float)0.5
#define PENALTY_WEIGHT_SURCHARGE_FACTOR2        (float)0.5

/*#define ZERO_PENALTY_SCORE_FACTOR           (float)0.55     // Reduce finalScore by 0.45 (adjusted by avSlopeFactor) if no penalties assessed whatsoever */
#define ZERO_PENALTY_SCORE_FACTOR           (float)0.65     /* Reduce finalScore by 0.35 (adjusted by avSlopeFactor and matched keys length) if no penalties assessed whatsoever */

#define MIN_ACCEPTABLE_CIRCLE_SCORE         (float)0.10

#define KEY_ERROR_COUNT_RANGE               4
#define MAX_KEY_ERROR_COUNT_MAX             3
#define MAX_KEY_ERROR_COUNT_MIN             0

#define MAX_SKIPPED_IPS_COUNT_MAX           3
#define MAX_SKIPPED_IPS_COUNT_MIN           1

#define MAX_GROSS_ERROR_COUNT_MAX           4
#define MAX_GROSS_ERROR_COUNT_MIN           1

#define MAX_CANDIDATE_PENALTY_MAX        (float)8.0
#define MAX_CANDIDATE_PENALTY_MIN        (float)3.0

#define MAX_CANDIDATE_IP_PENALTY_MAX     (float)6.5
#define MAX_CANDIDATE_IP_PENALTY_MIN     (float)1.5

#define MAX_CANDIDATE_SPELL_PENALTY_MAX  (float)4.0
#define MAX_CANDIDATE_SPELL_PENALTY_MIN  (float)2.25

#define MAX_SUFFIX_CANDIDATE_PENALTY_MAX (float)4.0
#define MAX_SUFFIX_CANDIDATE_PENALTY_MIN (float)2.0

#define MAX_SUFFIX_CHECK_SCORE_MIN       (float)300.0
#define MAX_SUFFIX_CHECK_SCORE_MAX       (float)5000.0

#define MAX_KEYPAIR_CHECK_SCORE_MIN      (float)300.0
#define MAX_KEYPAIR_CHECK_SCORE_MAX      (float)600.0

#define SKIPPED_IP_DISTANCE_PENALTY     ((AngleThreshold8 + AngleThreshold8_2)/2)
#define SKIPPED_IP_SCORE_PENALTY        (SKIPPED_IP_DISTANCE_PENALTY*AnglePenaltyWeight)
#define SKIPPED_IP_WEIGHT_CREDIT        AnglePenaltyWeightCredit

#define OMITTED_KEY_DISTANCE_PENALTY    AngleThreshold8_2
#define OMITTED_KEY_SCORE_PENALTY       (OMITTED_KEY_DISTANCE_PENALTY*AnglePenaltyWeight)
#define OMITTED_KEY_WEIGHT_CREDIT       AnglePenaltyWeightCredit

/* The "SUBSTITUTED_KEY_XXX" penalties include the penalties assessed for both a skipped IP and an omitted key. */
/* The total penalty assessed is reduced since both penalties are probably being assessed for a */
/* single path error. */
#define SUBSTITUTED_KEY_DISTANCE_PENALTY    AngleThreshold8_2
#define SUBSTITUTED_KEY_SCORE_PENALTY       (SUBSTITUTED_KEY_DISTANCE_PENALTY*AnglePenaltyWeight)
#define SUBSTITUTED_KEY_WEIGHT_CREDIT       AnglePenaltyWeightCredit

#define TRANSPOSED_KEY_DISTANCE_PENALTY     (2*AngleThreshold8/3)
#define TRANSPOSED_KEY_SCORE_PENALTY        (TRANSPOSED_KEY_DISTANCE_PENALTY*AnglePenaltyWeight)
#define TRANSPOSED_KEY_WEIGHT_CREDIT        AnglePenaltyWeightCredit

#define TRANSPOSED_VOWEL_DISTANCE_PENALTY   (AngleThreshold8/3)
#define TRANSPOSED_VOWEL_SCORE_PENALTY      (TRANSPOSED_KEY_DISTANCE_PENALTY*AnglePenaltyWeight)
#define TRANSPOSED_VOWEL_WEIGHT_CREDIT      AnglePenaltyWeightCredit

#define ADDITIVE_PENALTY_DISTANCE       AngleThreshold8_2
#define ADDITIVE_PENALTY_SCORE          (ADDITIVE_PENALTY_DISTANCE*AnglePenaltyWeight)
#define ADDITIVE_PENALTY_WEIGHT_CREDIT  AnglePenaltyWeightCredit

#define AV_DISTANCE_SCORE_WEIGHT_ADJUSTMENT     (float)40.0     /* Add to each avDistance in calculating finalScore to de-emphasize effect of average distance */
#define AV_NOPENALTYSCORESORT_WEIGHT_ADJUSTMENT (float)25.0     /* Add to instance of noPenaltyScoreSort in calculating combinedScore to de-emphasize effect of noPenaltyScoreSort */

#define RECENT_USE_ADJUSTMENT_FACTOR    (float)0.43

#define MIN_SUFFIX_SCORING_LENGTH       1           /* Suffix must be at least 1 letter to save & use separate score */

#define MINIMUM_AV_DISTANCE           7.5                   /* Keep scores above highly improbable, but possible, anomalous values */
#define MINIMUM_PENALTY_AV_DISTANCE   7.5                   /* Keep scores above highly improbable, but possible, anomalous values */
#define MINIMUM_AV_SCORE              7.5                   /* Keep scores above highly improbable, but possible, anomalous values */
#define MINIMUM_PENALTY_AV_SCORE      7.5                   /* Keep scores above highly improbable, but possible, anomalous values */

#define MAX_FINAL_SCORE             2.147483647e9       /* Scores greater than 2,147,483,647 exceed 31 bits.  Avoid possibility of overflow */
#define BEST_SCORE_RATIO            50                  /* Permit scores in word list up to 50 ??? times greater than best score found */

#define MAX_FREQ_CLASS                7                 /* frequency classes 0 - 7 in database */
#define MAX_FREQ_MARGIN               2                 /* Don't promote words closer than 2 classes from a class 7 word */
#define FREQ_CLASS_GOAL               5                 /* Preferentially move frequency classes toward level 5 in dynamic promotion / demotion */

#define MAX_FREQ_CLASS_MGD           14                 /* frequency classes 0 - 7 in database */
#define MAX_FREQ_CLASS_STEM           7                 /* frequency classes 0 - 7 for stems in database */
#define FREQ_CLASS_GOAL_MGD           5                 /* Preferentially move frequency classes toward level 5 in dynamic promotion / demotion */

#define STATS_INTERVAL_WORD_COUNT    10                 /* Output stats every 25 words */
#define STATS_LEVEL_SIZE              8                 /* Collect stats at 8 different durations, from 15 sec. up to 60 minutes */
#define STATS_LEVEL_MAX               7                 /* Collect stats at 8 different durations, from very short up to 30 minutes */

#define RESTART_TRACKING_IDLE_TIME   (10 * 60 * 1000)   /* 10 minutes in msec. */

#define FILES_UPDATED                   0               /* Main and back-up files exist, were identical, and were updated */
#define FILES_CREATED                   1               /* Main and back-up files successfully created */
#define FILE_MAIN_UPDATED               2               /* Main file successfully updated */
#define FILE_BACKUP_UPDATED             3               /* Back-up file successfully updated */
#define FILE_MAIN_RESTORED              4               /* Main file successfully restored from back-up file */
#define FILE_BACKUP_RESTORED            5               /* Back-up file successfully restored from main file */
#define FILE_MAIN_CREATED               6               /* Main file successfully created */
#define FILE_BACKUP_CREATED             7               /* Back-up file successfully created */
#define FILE_UPDATE_FAILURE             -1              /* Main and back-up files both failed */

/* Define constants for usage of array elements for mean, max, min and variance tracking */
#define N_VALUES                    0                   /* The number of values added so far */
#define XBAR                        1                   /* The mean of those values */
#define MIN_VALUE                   2                   /* The minimum value added so far */
#define MAX_VALUE                   3                   /* The maximum value added so far */
#define SSTOT                       4                   /* The sum of the squares of the standard deviations */
#define VALUE_ARRAY_SIZE            5
#define MIN_VALUE2                  5                   /* The next-to-minimum value added so far */
#define MAX_VALUE2                  6                   /* The next-to-maximum value added so far */
#define VALUE_ARRAY_SIZE2           7

#define SUM_SQUARES                 7                   /* The sum of the squares of those values (NOT CURRENTLY USED) */


#define Z1OPERATION_CYCLE_WORD_COUNT  250               /* Output stats every 250 words */


#define CONTINUE_CYCLING                2
#define LAST_CYCLING_WORD               1
#define NOT_CYCLING                     0

#define TOP_TEN_PERCENT             (Z1OPERATION_CYCLE_WORD_COUNT/10)   /* Track at least top 10% of scores */
#if TOP_TEN_PERCENT > 10
#define MAX_VALUES_TRACKED          TOP_TEN_PERCENT
#else
#if Z1OPERATION_CYCLE_WORD_COUNT > 10
#define MAX_VALUES_TRACKED            10                /* track at least 10 values */
#else
#define MAX_VALUES_TRACKED            Z1OPERATION_CYCLE_WORD_COUNT              /* track at most all values */
#endif
#endif
#define MAX_INTER_WORD_PAUSE        2000                /* Exclude pause in input if pause is greater than 2.0 seconds (approximately three times an "average proficient" pause) */
#define MIN_REQUIRED_PAUSE_COUNT      25                /* Replace MAX_INTER_WORD_PAUSE with 2 * avg. pause after 25 valid pause measurements */
#define MAX_WORD_SCANNING_TIME       500                /* Allow maximum of 0.5 sec. to read each word in an editing scan */
#define MAX_EDITING_SCANNING_TIME  15000                /* Allow 15 seconds when no record is available */

/* Define integer values so that FreqRangeRatio can be stored (as a 2-byte integer value) in the registry . */
/* Calculate FreqRangeRatio = FreqRangeRatioInt / FREQ_RANGE_RATIO_INT_DENOM */
/* Two-byte integer used, so values are constrained so that FREQ_RANGE_RATIO_INT_MAX = 65534 */

#define FREQ_RANGE_RATIO_ADJUST      (float)0.5         /* Adjust up or down by (total spread) factor of 0.5 when frequency effect demotes intended word */
#define FREQ_RANGE_RATIO_INIT        (float)11.0        /* Initial value for increase between frequency class 0 and class 7 */
#define FREQ_RANGE_RATIO_INT_INIT     11000             /* = (FREQ_RANGE_RATIO_INIT * FREQ_RANGE_RATIO_INT_DENOM) */
#define FREQ_RANGE_RATIO_MIN         (float)7.0         /* Minimum increase between frequency class 0 and class 7 */
#define FREQ_RANGE_RATIO_MAX         (float)15.0        /* Maximum increase between frequency class 0 and class 7 */
#define FREQ_RANGE_RATIO_INT_DENOM    1000
#define FREQ_RANGE_RATIO_INT_MULT     1000
#define FREQ_RANGE_RATIO_INT_UNDEF   65535

/* SavedCodeSegments/SearchDB.cpp/181 */


#define MAX_PG_WIDTH                  4                 /* Maximum path group width distinguished by IdentifyPathLengthGroups() */

    /* SavedCodeSegments/SearchDB.cpp/65 */

#define DISTANCE_BASE               10

#define WORD_CANCEL_FLAG_INDEX      0xFFFF

/* Define constants for defining nature of final key matching */
#define NO_PENUP_MATCH                    0                   /* No match found for final key */
#define SEGMENT_MATCH                     1                   /* Final key matches on final segment preceding a SoftUp */
#define SOFT_UP_MATCH                     2                   /* Final key matches the actual SoftUp */
#define PRE_EXIT_MATCH                    3                   /* Final key matches last IP preceding a SoftUp */
#define DOUBLE_MATCH                      4                   /* Final key matches actual Double IP preceding a SoftUp */
#define PENUP_MATCH                       5                   /* Final key matches actual PenUp */

/* forward declarations */
struct SWCIPAnalyzer_s;

typedef struct SWSuffixTrace_s
{
    IPType      p_IPType;
    SBYTE2      matchKey;
    SBYTE2      keyIndex;
    SBYTE2      ipIndex;
    _SWPoint    matchKeyPos;
    SBYTE2      matchKeyIndex;
}
SWSuffixTrace;

struct _SWCSearchDB_s
{
    ET9BOOL  algRecalcsThresholds[N_ALGORITHMS];
    ET9BOOL  algNoReprocIPTable[N_ALGORITHMS];
    ET9BOOL  algReduceRecencyWeight[N_ALGORITHMS];
    ET9BOOL  algReduceFrequencyWeight[N_ALGORITHMS];
    ET9BOOL  algIncreaseClass0FrequencyWeight[N_ALGORITHMS];
    ET9BOOL  algIncreaseRecencyWeight[N_ALGORITHMS];
    ET9BOOL  algIncreaseFrequencyWeight[N_ALGORITHMS];
    ET9BOOL  algNewNoPenaltyScore[N_ALGORITHMS];
    ET9BOOL  algNewCombinedScore[N_ALGORITHMS];
    ET9BOOL  algAddUndershootToMaxLen[N_ALGORITHMS];
    ET9BOOL  algConvertAngleCloseToAngle[N_ALGORITHMS];
    ET9BOOL  algDeleteAngleCloseToAngle[N_ALGORITHMS];
    ET9BOOL  algConvertAngleCloseToPenDown[N_ALGORITHMS];
    ET9BOOL  algReduceMGDScoreThresholds[N_ALGORITHMS];

    ET9BOOL  m_ForceShowWCW;             /* Force showing of WCW for 1-letter words when multiple DoubleLetter gestures performed */
    ET9BOOL  calledCheckMultipleIPsSequence;

    SBYTE2  vowelKeysLowerBound;        /* Set to y-coordinate of lower bound of u, i, and o keys */
    SBYTE2  vowelKeysLeftBound, vowelKeysRightBound;

    ET9BOOL  m_initialized;              /* Has SearchDB been initialized? */

#if DEBUG_SHOW_MATCH_TRACE || DEBUG_SHOW_WCW_TRACE
    ET9BOOL  bBreakHere;
#endif

    /* Local copy of IP Table pointer array */
    SWCIPTableRow   *m_aIPTable[_SWYPE_MAX_IPS];
    SWCIPTableRow   *m_aIPTable2[_SWYPE_MAX_DOUBLE_LETTER_IPS];  /* To save Double IPs in separate list */
    SWCIPTableRow   *m_aExitIPTable[_SWYPE_MAX_EXIT_IPS];
    SBYTE2 actualIPTableCount;          /* Number of IPs in orignal "raw" IP table */
    SBYTE2 m_wIPTableCount;             /* Number of IPs added to table used in Search process */
    SBYTE2 m_wIPTable2Count;            /* Number of IPs added to table 2 */
    SBYTE2 m_wExitIPTableCount;         /* Number of Exit IPs added to table */

    SBYTE2 m_wSearchLevel;              /* Current search iteration level */

    SBYTE2 pathWidth, pathHeight, pathCenter, pathCenterFromRow;        /* Maximum width, height, and y-coordinate difference of vertical center of current path */
                                                                        /*   from nearest vertical row center */
    /* CSearchDB's copy of Fixed data */
    SWFixedData     *m_pZ1FixedData;
    ET9U16          wFixedDataCount;

    SBYTE2  m_SearchShiftPos[DEFAULT_WORD_SIZE];        /* Up to DEFAULT_WORD_SIZE positions along the path */
                                                        /*   where the path exits from the top of the keyboard */
    SBYTE2  m_SearchExitXPos[DEFAULT_WORD_SIZE];        /* Up to DEFAULT_WORD_SIZE x-coordinates of where path exits keyboard */
    SBYTE2  m_SearchEntryXPos[DEFAULT_WORD_SIZE];       /* Up to DEFAULT_WORD_SIZE x-coordinates of where path re-enters keyboard */
    SBYTE2  m_SearchEntryPosIndex[DEFAULT_WORD_SIZE];   /* Up to DEFAULT_WORD_SIZE fixed indices of point where path re-enters keyboard */
    SBYTE2  m_SearchShiftLocCount;                      /* Number of m_ShiftPos[] locations recorded */
    ET9BOOL  m_SearchShiftAll;                           /* CAPLOCK gesture flag to Upper-case all letters */
    ET9BOOL  m_bShiftFirstLetter;                        /* Flag that SHIFT flag was set at start of Swype path */
    ET9BOOL  m_SearchFirstLetterShiftGesture;            /* If true, initial shift gesture is highly likely to be intended for first letter of word */
    /* Search parameters that may vary in value for subsequent passes during a search */
    SBYTE2  searchPassLimit;                /* Number of search passes possible given current Z1OperationSetting */
    int     Z1IterationLevels[Z1_SEARCH_LEVEL_MAX];
    ET9BOOL  IPThresholdLevelsSet;         /* Flag that SetIPThresholdLevels() has been called since Z1OperationSetting slider was changed */

    SBYTE2  rowCenter[KEY_ROWS_MAX];    /* Vertical centers of keyboard rows */
    ET9BOOL  forward;                        /* True if scoring words (PenDown -> PenUp), false if scoring suffixes */
                                            /*   when the current word includes an optional character */
    ET9BOOL  nextKeyCheckAlternateMatches, thisKeyCheckAlternateMatches;
    float   goodEnoughScore;                /* Halt search if candidate found with combinedScore less than goodEnoughScore */
    float   goodEnoughScoreCurrent;         /* Calculated from goodEnoughScore based on current path characteristics */
    float   bestGoodWordScore;              /* Halt search if candidate found with combinedScore less than goodEnoughScore */
    float   penSpeedFactor;                 /* Calibrated factor based on current pen speed with respect to pen speed history; 0.5 <= penSpeedFactor <= 1.75 */
    float   ipCountFactor;                  /* Adjustment factor 1.0 < ipCountFactor < 1.33; hits max for ipCount == 2 */

    /* SavedCodeSegments/SearchDB.h/16 (SCORING_METHOD_2 code) */
#if INTERNAL_STATISTICS
    #define SD_STRUCTURE_FORMAT_CODE    0xABCDEF0C          /* Unlikely to match randomly... */
#else
    #define SD_STRUCTURE_FORMAT_CODE    0x1234567C          /* Unlikely to match randomly... */
#endif

#define SDO_STRUCTURE_FORMAT_CODE   0xFEDCBA01              /* Unlikely to match randomly... */

    int  RenderIPsFlag;                  /* Flag to display Inflection Points in path from registry */
    int  Z1OperationSetting;             /* Current base value of Z1OperationLevel from registry */
    ET9BOOL  TrackZ1Stats;
    float IPThresholdFactor;             /* Float value to scale IP thresholds */
    float SegmentThresholdFactor;        /* Float value to scale Segment thresholds */

    _SWWord   *thisWord;                  /* Current word being analyzed */

    ALGORITHM_TYPE  CurrentAlgorithm;               /* Index of current Search algorithm */

    ET9BOOL  bFirstKeyboardInit;

    int     Z1OperationLevel;           /* Value set to options page slider setting (0 - 1000) */
    int     Z1OperationLevelCurrent;    /* Value for current search pass (0 - 1000) */
    int     Z1OperationLevelMax;        /* Max value for current setting in final iteration (0 - 1000) */
    int     Z1OperationLevelPrevious;   /* Previous value of options page slider setting (0 - 1000) */

    /* Local copy of scoring weights for each IP type */
    float FreqWeight[FREQ_CLASS_COUNT];         /* Run-time adjusted frequency weighting factors for each frequency class */
    float RecencyWeight[FREQ_CLASS_COUNT];               /* Recency weighting factors for each frequency class */
    float RecencyWeightReduced[FREQ_CLASS_COUNT];        /* Recency weighting factors for each frequency class */
    float RecencyWeightIncreased[FREQ_CLASS_COUNT];      /* Recency weighting factors for each frequency class */
    float FreqWeightMGD[FREQ_CLASS_COUNT_MGD];                  /* Run-time adjusted frequency weighting factors for each MGD frequency class */
    float RecencyWeightMGD[FREQ_CLASS_COUNT_MGD];               /* Recency weighting factors for each MGD frequency class */
    float RecencyWeightReducedMGD[FREQ_CLASS_COUNT_MGD];        /* Recency weighting factors for each MGD frequency class */
    float RecencyWeightIncreasedMGD[FREQ_CLASS_COUNT_MGD];      /* Recency weighting factors for each MGD frequency class */
    float Class7MinRecencyWeight;                  /* Minimum recency weighting factor for highest frequency class */
    float Class7MinRecencyWeightReduced;           /* Minimum recency weighting factor for highest frequency class */
    float Class7MinRecencyWeightIncreased;         /* Minimum recency weighting factor for highest frequency class */
    float FreqRangeRatio;                   /* Maximum increase in weighting (between frequency classes 7 and 0) */
    BYTE2 FreqRangeRatioInt;            /* Registry value (BYTE2 int) to save ratio as value X such */
                                        /* that ratio is = (? + X) / ?? */

    /* Word and Suffix array position pointers */
    SBYTE2 m_wRequiredIPTableCount;         /* Number of required IPs added to table */

    BYTE2  actualPath, minPath, maxPath;

    SBYTE2 multipleIPPathLen, overshootPathLen, undershootPathLen;

    /* Variables shared by both Suffix- and Word-scoring routines to track scoring results */
    ET9BOOL  isMGDataBase;                   /* True if current database is morphologically generative */
    BYTE1   keys[DEFAULT_WORD_SIZE];              /* keys for characters in word ( [SearchDB] ) */
    BYTE1   m_keyRepeats[DEFAULT_WORD_SIZE];      /* Number of times each key in keys[] is repeated in actual sequence (i.e. set to 1 for a double letter) ( [SearchDB] ) */
    BYTE1   keyFlags[DEFAULT_WORD_SIZE+1];    /* Transposition, ommission, etc. flags for keys as matched ( [SearchDB] ) */
    BYTE1   omitKeys[OMIT_KEYS_MAX];        /* key indices of characters omitted from word ( [SearchDB] ) */
    BYTE1   omitCounts[OMIT_KEYS_MAX];      /* number of characters omitted from word in each omission event( [SearchDB] ) */
    BYTE1   omitKeysActual[OMIT_KEYS_MAX];  /* Original key indices of characters omitted from word ( [SearchDB] ) */
    BYTE4   rawDistKey[DEFAULT_WORD_SIZE], rawScoreKey[DEFAULT_WORD_SIZE];
    float   weightSumKey[DEFAULT_WORD_SIZE];
    float   skipPenaltyKey[DEFAULT_WORD_SIZE];
    SBYTE2  skippedIPsCount[DEFAULT_WORD_SIZE];     /* Number of required IPs skipped in matching each ley */
    ET9BOOL    hasSkippedIPs[DEFAULT_WORD_SIZE];       /* True if any (including not-required) IPs are skipped in matching each key */
    SBYTE2  ipIndexKey[DEFAULT_WORD_SIZE];
    float   slopeFactorKey[DEFAULT_WORD_SIZE];
    SBYTE2  matchKeyType[DEFAULT_WORD_SIZE];        /* Type of match determined for each key and its matched location ( [SearchDB] ) */
    _SWPoint matchKeyLocs[DEFAULT_WORD_SIZE];         /* Coordinates of match location determined for each key ( [SearchDB] ) */
    ET9BOOL    hasSegmentMatch[DEFAULT_WORD_SIZE];     /* Flag set true for each key matched to a path segment ( [SearchDB] ) */

    SBYTE2  ipLimitSuffix;              /* Index of earliest IP required for current suffix matching */
    SBYTE2  keyLimit, keyLimitSuffix, lastChangeIndex, swapPos, omitPos, fixedLimitSuffix;

    SWCIPTableRow *ipPenDown, *ipPenUp;
    SBYTE2  matchKey, dualMatch;
    ET9BOOL    dualMatchSet;               /* Set true once dualMatch found for current suffix */
    SBYTE2  transpositionLevel;         /* Type of transpositions allowed by system settings: None, vowels-ony, or any */
    SWCIPTableRow *ipData, *seg1Data, *ipData2, *seg2Data, *ipData3, *seg3Data;
    ET9BOOL  reScoreSuffix;              /* True if original suffix scoring is NOT being used when scoring word */
    BYTE4   rawDist, rawScore;
    float   rawSlopeScore;
    BYTE4   penaltyRawDist;             /* Sum of assessed weighted penalty distances from input path (IPs and segments) ( [SearchDB] ) */
    float   penaltyRawScore;            /* Sum of assessed weighted penalty scores for word */
    float   weightSum;
    float   penaltyWeightSum;           /* Sum of weights used in calculating penaltyRawScore ( [SearchDB] ) */
    float   slopeFactorTotal;
    float   penaltySlopeFactor;
    float   skipPenaltyWord, oddPathPenalty;
    SBYTE2  skippedIPsWord;
    SBYTE2  ipIndex, keyIndex, keyIndexM1, keyIndexMax, key2Index, key3Index, keySeqLength, keysRemaining, ipsRemaining, lastOmittedKey;
    SBYTE2  transposeCount, vowelTransposeCount, omissionCount, omitCount, substituteCount, multipleIPCount, multipleIPsTotal;
    SBYTE2  maxKeyErrorCount[Z1_SEARCH_LEVEL_MAX];           /* Maximum number of key errors allowed before a word is disqualified */
    SBYTE2  maxKeyErrorCountCurrent;           /* Maximum number of key errors allowed before a word is pre-filtered out (for current word) */
    SBYTE2  maxKeyErrorCountActual;            /* Maximum number of key errors allowed before a word is pre-filtered out (for current word) */
    SBYTE2  wordMinX, wordMaxX, wordMinY, wordMaxY, wordWidth, wordHeight;
    float   pathSize;
    float   maxCandidateIPPenalty, maxCandidateIPPenaltyBase, maxCandidateSpellPenalty, maxSuffixCandidatePenalty;

    SBYTE2  doubleKeyCount, repeatedKeyCount, nextDoubleKeyIndex;
#if CAN_REQUIRE_DOUBLE_GESTURE
    ET9BOOL  doubleGestureRequired;
#endif
    SBYTE2  doubleKeyIndices[MAX_DOUBLE_KEYS];
    BYTE1   key1, key2, key3, key4, lastKey;
    float   DoubleKeysToSegmentPenalty;
    float   DoubleKeysToSingleIPPenalty;
    float   DoubleKeysToSingleIPOnly2IPsPenalty;
    float   DoubleKeysToSingleIPOnly3IPsPenalty;
    float   DoubleKeysToMergedIPPenalty;
    float   ExcessDoubleKeysPenaltyAllowance;

    /* Coordinates and fixed indices related to actual position of closest point matched with a key, or actual IP location */
    _SWPoint matchKeyPos, altMatchKeyPos, lastMatchKeyPos, altLastMatchKeyPos, dualMatchPos;
    SBYTE2  matchKeyPosIndex, altMatchKeyPosIndex, lastMatchKeyPosIndex, altLastMatchKeyPosIndex, dualMatchPosIndex, lastSkipPosIndex;
    SBYTE2  altMatchKeyType, altLastMatchKeyType;
    BYTE4   altMatchKeyRawScore, altLastMatchKeyRawScore, altMatchKeyRawDist, altLastMatchKeyRawDist;
    float   altMatchKeyWeightSum, altLastMatchKeyWeightSum;
    ET9BOOL  altMatchKeyHasSegmentMatch, altLastMatchKeyHasSegmentMatch;
    SBYTE2  finalMatchPosIndex, finalRequiredIPPosIndex;
    SBYTE2  matchLocExitIndex[DEFAULT_WORD_SIZE];   /* Fixed index matching exit locations for chars in text ( [SearchDB] ) */
    /* Coordinates and fixed indices related to position of point matched with a key at closest point of greatest inflection, or other point */
    /*   intended to yield a reasonable slopeFactor calculation for a match */
    _SWPoint matchKeyLoc, altMatchKeyLoc, altMatchKeyLoc2, lastMatchKeyLoc, altLastMatchKeyLoc, dualMatchLoc;
    _SWPoint matchKeyLoc3, altMatchKeyLoc3;  /* _SWPoint(0, 0) constants */
    SBYTE2  matchKeyLocIndex, matchKeyLocExitIndex, altMatchKeyLocIndex, altMatchKeyLocExitIndex, lastMatchKeyLocIndex, altLastMatchKeyLocIndex, dualMatchLocIndex;
    SBYTE2  altMatchKeyLocIndex2, matchKeyLocIndex3 /* contant 0 */, altMatchKeyLocIndex3 /* contant 0 */;

    float   matchSlopeDifFactor, dualSlopeDifFactor;
    BYTE2   key1IP1, key1Seg1, key1IP2, key1Seg2, key1IP3, key1Seg3;
    BYTE2   key2IP1, key2Seg1, key2IP2, key2Seg2, key2IP3, key2Seg3;
    BYTE2   key3IP1, key3Seg1, key3IP2, key3Seg2, key3IP3, key3Seg3;
    BYTE2   key4IP1, key4Seg1, key4IP2, key4Seg2;
    BYTE2   keyMultipleIPs, keyMultipleIPsDistance, keyMultipleIPsWDistance;
    SBYTE2  key1Seg1PosIndex, key1Seg2PosIndex, key1Seg3PosIndex;
    SBYTE2  key2Seg1PosIndex, key2Seg2PosIndex, key2Seg3PosIndex;
    SBYTE2  key3Seg1PosIndex, key3Seg2PosIndex, key3Seg3PosIndex;
    SBYTE2  key4Seg1PosIndex, key4Seg2PosIndex;
    ET9BOOL  isCandidate, requiredIP, key1IsDoubleKey, key2IsDoubleKey, key3IsDoubleKey, key4IsDoubleKey, lastKeyMatchesPenUp, finalKeyScoreAdjusted;
    ET9BOOL  IP1isPenUp, IP2isPenUp, IP3isPenUp, IP1canBePenUp, IP1isPathDivision, IP2isPathDivision, IP3isPathDivision;
    ET9BOOL  IP1isArtificial, IP2isArtificial, IP3isArtificial;      /* IP is either a PathDivision IP, or an artificially created "Multiple" IP */
    ET9BOOL  IP1isMultiple, IP2isMultiple, IP3isMultiple;
    ET9BOOL  advanceIP, advanceKey, finalKey, exitLoop, finalScoringPass /* constant true */;
    ET9BOOL  calculatingKeyPairs /* contant false */;
    ET9BOOL  isSwappedKey, wasSwappedKey;
    BYTE2   mergedIP;

    float   penaltyAvDistance;          /* Average distance from input path / inflection points including assessed penalty distances */
    float   penaltyAvScore;             /* Average of assessed weighted penalty scores for word */
    float   avScore;                    /* Average weighted distance from input path (IPs and segments) ( [SearchDB] ) */
    float   avSlopeFactor;              /* Average matchSlopeDifFactor in scoring for word */

    BackEnd *m_backend;
};

#if SW_UNUSED
    ET9PRIVATE void  ET9FARCALL _SWCSearchDB_DumpWord(_SWCSearchDB *pThis, _SWWord *tblWord, ET9BOOL dumpSwypeInfo, ET9BOOL dumpTapData, ET9BOOL announceWordDump);
#endif

    ET9PRIVATE _SWPoint ET9FARCALL _SWCSearchDB_GetZ1FixedPoint(_SWCSearchDB *pThis, SBYTE2 fixedIndex);
    ET9PRIVATE SBYTE4  ET9FARCALL _SWCSearchDB_GetZ1FixedD2Sum(_SWCSearchDB *pThis, SBYTE2 fixedIndex);
    ET9PRIVATE BYTE2   ET9FARCALL _SWCSearchDB_GetZ1PathLength(_SWCSearchDB *pThis, SBYTE2 fixedIndex1, SBYTE2 fixedIndex2);
    ET9PRIVATE BYTE2   ET9FARCALL _SWCSearchDB_GetZ1PathLength8(_SWCSearchDB *pThis, SBYTE2 fixedIndex1, SBYTE2 fixedIndex2);
    ET9PRIVATE BYTE4   ET9FARCALL _SWCSearchDB_GetZ1PathLengthPrecise(_SWCSearchDB *pThis, SBYTE2 fixedIndex1, SBYTE2 fixedIndex2);
    ET9PRIVATE SBYTE2  ET9FARCALL _SWCSearchDB_GetZ1FixedDataSize(_SWCSearchDB *pThis);

    ET9PRIVATE void  ET9FARCALL _SWCSearchDB_Construct(_SWCSearchDB *pThis);
    ET9PRIVATE void  ET9FARCALL _SWCSearchDB_Destruct(_SWCSearchDB *pThis);
    ET9PRIVATE void  ET9FARCALL _SWCSearchDB_Initialize(_SWCSearchDB *pThis);
    ET9PRIVATE void  ET9FARCALL _SWCSearchDB_SetZ1Operation(_SWCSearchDB *pThis);
    ET9PRIVATE ET9BOOL ET9FARCALL _SWCSearchDB_KeyboardChanged(_SWCSearchDB *pThis);
    ET9PRIVATE void  ET9FARCALL _SWCSearchDB_ResetDoubleIndices(_SWCSearchDB *pThis, SBYTE2 restartPos);
    ET9PRIVATE void  ET9FARCALL _SWCSearchDB_SetDoubleIndicesFromKeyRepeats(_SWCSearchDB *pThis, BYTE1 *keyRepeats, CPOS length);
    ET9PRIVATE void  ET9FARCALL _SWCSearchDB_FailCandidate(_SWCSearchDB *pThis);
    ET9PRIVATE ET9BOOL ET9FARCALL _SWCSearchDB_SwapKeysOKFromKeyRepeats(_SWCSearchDB *pThis, SBYTE2 swapLoc, SBYTE2 keyLimit, ET9BOOL *swapPrevOK, ET9BOOL *swapNextOK, ET9BOOL *omitKeyOK);
    ET9PRIVATE ET9BOOL ET9FARCALL _SWCSearchDB_MatchLocOK(_SWCSearchDB *pThis, SBYTE2 *matchPos, float *mSlopeDif, float *dSlopeDif);
    ET9PRIVATE SBYTE2 ET9FARCALL _SWCSearchDB_PathExitsKeyboard(_SWCSearchDB *pThis, SBYTE2 fixedIndex1, SBYTE2 fixedIndex2, SBYTE2 *exitXpos, SBYTE2 *entryPosIndex);
    static ET9INLINE ET9BOOL _SWCSearchDB_InvalidPosIndex(_SWCSearchDB *pThis, SBYTE2 posIndex)
        { return (ET9BOOL)((posIndex < 0) || (posIndex >= _SWCSearchDB_GetZ1FixedDataSize(pThis))); }

    static ET9INLINE ET9BOOL _SWCSearchDB_PointsInSequence(_SWCSearchDB *pThis, SBYTE2 pos1, SBYTE2 pos2)
        { return (ET9BOOL)((pThis->forward) ? pos1 < pos2 : pos2 < pos1); }

    static ET9INLINE ET9BOOL _SWCSearchDB_PointsInSequenceOrIdentical(_SWCSearchDB *pThis, SBYTE2 pos1, SBYTE2 pos2)
        { return (ET9BOOL)((pThis->forward) ? pos1 <= pos2 : pos2 <= pos1); }

    static ET9INLINE ET9BOOL _SWCSearchDB_IsAngleIP(SWCIPTableRow *ipDat)
        { return (ET9BOOL)((ipDat != NULL) && ((ipDat->m_IPFlags & ANGLE_IP) != 0)); }

    /* An IP inside a Diacritic Gesture is not required to be matched */
    static ET9INLINE ET9BOOL _SWCSearchDB_IsRequiredIP(SWCIPTableRow *ipDat)
        { return (ET9BOOL)((ipDat != NULL) && (((ipDat->m_IPFlags & (REQUIRED_IP | DIACRITIC_IP)) == REQUIRED_IP))); }

    static ET9INLINE ET9BOOL _SWCSearchDB_CanBeMultipleIP(SWCIPTableRow *ipDat)
        { return (ET9BOOL)((ipDat != NULL) && ((ipDat->m_IPFlags & MULTIPLE_IP) != 0)); }

    static ET9INLINE ET9BOOL _SWCSearchDB_IsDiacriticIP(SWCIPTableRow *ipDat)
        { return (ET9BOOL)((ipDat != NULL) && ((ipDat->m_IPFlags & DIACRITIC_IP) != 0)); }

    static ET9INLINE ET9BOOL _SWCSearchDB_CanHaveOvershoot(SWCIPTableRow *ipDat)
        { return (ET9BOOL)((ipDat != NULL) && ((ipDat->m_IPFlags & OVERSHOOT_IP) != 0)); }

    static ET9INLINE BYTE2 _SWCSearchDB_minNonZero(BYTE2 arg1, BYTE2 arg2)
        { return !arg1 ? arg2 : (!arg2 ? arg1 : sw_min(arg1, arg2)); }

    ET9PRIVATE float ET9FARCALL _SWCSearchDB_calcVectorDif(_SWCSearchDB *pThis, BYTE1 key_2, BYTE1 key_3, SBYTE2 matchKeyPosIndex2, SBYTE2 matchKeyPosIndex3, _SWVector keyVector, _SWVector pathVector, BYTE2 *keyVectorLength);
    ET9PRIVATE ET9BOOL ET9FARCALL _SWCSearchDB_calcSlopeDif(_SWCSearchDB *pThis, BYTE1 key_1, BYTE1 key_2, BYTE1 key_3, ET9BOOL swappedKey, ET9BOOL suffixCheck, _SWPoint matchKeyPos1, _SWPoint matchKeyPos2, SBYTE2 matchKeyPosIndex1,
                       SBYTE2 matchKeyPosIndex2, float *slopeDifFactor, float *lengthFactor, SBYTE2 matchKeyPosIndex3, SBYTE2 altKeyPosIndex1, SBYTE2 altKeyPosIndex2,
                       SBYTE2 altKeyPosIndex22, ET9BOOL adjustForPathLength);
    ET9PRIVATE ET9BOOL ET9FARCALL _SWCSearchDB_KeysMatchPoints(_SWCSearchDB *pThis, BYTE1 key1, BYTE1 key2, BYTE1 key3, ET9BOOL isSegmentMatch, ET9BOOL swappedKey, ET9BOOL suffixCheck, _SWPoint matchKeyLoc1, _SWPoint matchKeyLoc2, SBYTE2 matchKeyLocIndex1, SBYTE2 matchKeyLocIndex2,
                          _SWPoint matchKeyPos1, _SWPoint matchKeyPos2, SBYTE2 matchKeyPosIndex1, SBYTE2 matchKeyPosIndex2, float *slopeDif, SBYTE2 matchKeyPosIndex3, SBYTE2 altKeyPosIndex1, SBYTE2 altKeyPosIndex2,
                          SBYTE2 altKeyPosIndex22, ET9BOOL adjustForPathLength);

    ET9PRIVATE ET9BOOL ET9FARCALL _SWCSearchDB_AdjustWordFrequency(_SWCSearchDB *pThis, ET9AWLingInfo * const pLingInfo,
                            const ET9U8 bWordIndex,
                            ET9BOOL corrected);
    ET9PRIVATE int   ET9FARCALL _SWCSearchDB_ScoreWordFromKeyRepeats(_SWCSearchDB *pThis, _SWWord *dbWord, ET9BOOL forceRescore, ALGORITHM_TYPE searchAlgorithm);
    ET9PRIVATE SWCIPTableRow * ET9FARCALL _SWCSearchDB_GetExitEntryIP(_SWCSearchDB *pThis, SBYTE2 exitIndex, IPType desiredIPType);
    ET9PRIVATE BYTE2 ET9FARCALL _SWCSearchDB_GetIPWDistance(_SWCSearchDB *pThis, SWCIPTableRow *ipData, BYTE1 key);
    ET9PRIVATE BYTE2 ET9FARCALL _SWCSearchDB_GetIPDistance8(_SWCSearchDB *pThis, SWCIPTableRow *ipData, BYTE1 key);
    ET9PRIVATE BYTE2 ET9FARCALL _SWCSearchDB_GetSegmentWDistance(_SWCSearchDB *pThis, SWCIPTableRow *segData, BYTE1 key, SBYTE2 fixedLimit);
    ET9PRIVATE BYTE2 ET9FARCALL _SWCSearchDB_GetSegmentDistance8(_SWCSearchDB *pThis, SWCIPTableRow *segData, BYTE1 key);
    ET9PRIVATE SBYTE2 ET9FARCALL _SWCSearchDB_GetSegmentMatchPos(_SWCSearchDB *pThis, SWCIPTableRow *segData, BYTE1 key, _SWPoint *matchPos, _SWPoint *matchLoc, SBYTE2 *matchLocIndex);
    ET9PRIVATE float ET9FARCALL _SWCSearchDB_GetSegmentMatchWeight(_SWCSearchDB *pThis, SWCIPTableRow *segData, BYTE1 key);
#if DEBUG_SHOW_MATCH_TRACE || DEBUG_SHOW_WCW_TRACE
    ET9PRIVATE float ET9FARCALL _SWCSearchDB_GetSkippingPenalty1(_SWCSearchDB *pThis, SWCIPTableRow *ipData, SBYTE2 matchKey, ET9BOOL advanceIP, SBYTE2 *skippedIPs, float *IPskipPenalty, ET9BOOL isSuffix, float oddPathPenaltyVal);
#endif
    ET9PRIVATE float ET9FARCALL _SWCSearchDB_GetSkippingPenalty(_SWCSearchDB *pThis, SWCIPTableRow *ipData, SBYTE2 matchKey, ET9BOOL advanceIP, SBYTE2 *skippedIPs, float *IPskipPenalty, ET9BOOL isSuffix, float oddPathPenaltyVal);
    ET9PRIVATE BYTE2 ET9FARCALL _SWCSearchDB_SetSegmentDistancePosition(_SWCSearchDB *pThis, SWCIPTableRow *segData, BYTE1 key, SBYTE2 fixedLimit, SBYTE2 *posIndex);
    ET9PRIVATE void  ET9FARCALL _SWCSearchDB_SetKeyDistancesFromKeyRepeats(_SWCSearchDB *pThis, SBYTE2 fixedLimit);
    ET9BOOL ET9FARCALL _SWCSearchDB_isVowelKey(_SWCSearchDB *pThis, BYTE1 key, ET9BOOL useActiveKeyboard);
    ET9PRIVATE ET9BOOL ET9FARCALL _SWCSearchDB_checkTranspositions(_SWCSearchDB *pThis, ET9BOOL *swappedNext, ET9BOOL *swappedPrev, SBYTE2 keyLimit);
    ET9PRIVATE CPOS  ET9FARCALL _SWCSearchDB_findTransposedCharOffset(_SWCSearchDB *pThis, CPOS keyPos, CPOS keyLimit);
    ET9PRIVATE void  ET9FARCALL _SWCSearchDB_setIPVars(_SWCSearchDB *pThis);
    ET9PRIVATE SBYTE2 ET9FARCALL _SWCSearchDB_RecordKeyOmissionFromKeyRepeats(_SWCSearchDB *pThis, SBYTE2 omitPosRelative, SBYTE2 omitPosActual);
    ET9PRIVATE void  ET9FARCALL _SWCSearchDB_RestoreEnvironmentFromKeyRepeats(_SWCSearchDB *pThis, SBYTE2 omitted, SBYTE2 *matchPosIndex, float *skipPenalty, SBYTE2 *skippedIPs);
    ET9PRIVATE SBYTE2 ET9FARCALL _SWCSearchDB_CheckTransposeOmitKey(_SWCSearchDB *pThis, SBYTE2 *matchPos, SBYTE2 fixedLimit, float *skipPenalty, SBYTE2 *skippedIPs);
    ET9PRIVATE ET9BOOL ET9FARCALL _SWCSearchDB_CheckMultipleIPsMatch(_SWCSearchDB *pThis, SBYTE2 fixedLimit) GCC_CHECK_MULTIPLE_IPS_MATCH_OPTIMIZATION_ATTRIBUTE;
    ET9PRIVATE SBYTE2 ET9FARCALL _SWCSearchDB_SetKeyMultipleIPs(_SWCSearchDB *pThis, BYTE1 multKey, SBYTE2 startIndex, SBYTE2 multipleCount, SBYTE2 minMatchCount);
    ET9PRIVATE ET9BOOL ET9FARCALL _SWCSearchDB_MatchKey1AfterExit(_SWCSearchDB *pThis);
    ET9PRIVATE ET9BOOL ET9FARCALL _SWCSearchDB_MatchKey2AfterExit(_SWCSearchDB *pThis);
    ET9PRIVATE ET9BOOL ET9FARCALL _SWCSearchDB_MatchKey1AfterPathDivision(_SWCSearchDB *pThis);
    ET9PRIVATE ET9BOOL ET9FARCALL _SWCSearchDB_MatchKey1ToSeg1(_SWCSearchDB *pThis, SBYTE2 *matchKeyVal);
    ET9PRIVATE ET9BOOL ET9FARCALL _SWCSearchDB_MatchKey2ToSeg1(_SWCSearchDB *pThis);
    ET9PRIVATE ET9BOOL ET9FARCALL _SWCSearchDB_SwapNextKeyOK(_SWCSearchDB *pThis, SBYTE2 *chkMatchKey);
    ET9PRIVATE void  ET9FARCALL _SWCSearchDB_CheckKeyMatches(_SWCSearchDB *pThis, SBYTE2 *matchPos, SBYTE2 fixedLimit, ET9BOOL findMatch);
    ET9PRIVATE float ET9FARCALL _SWCSearchDB_AdjustSegmentSlopeFactor(_SWCSearchDB *pThis, SBYTE2 *matchPosIndex, SBYTE2 thisKeyIndex, SBYTE2 nextKeyIndex, float initialValue);
#if DEBUG_LOG_MATCH_TRACE
    ET9PRIVATE void  ET9FARCALL _SWCSearchDB_DebugTraceWordMGD(_SWCSearchDB *pThis, _SWWord *dbWord, float skipPenalty, ET9BOOL passed, SBYTE2 lastKeyScored);
#endif
    ET9PRIVATE void  ET9FARCALL _SWCSearchDB_SetFreqWeights(_SWCSearchDB *pThis, float RunTimeFreqRange, ALGORITHM_TYPE searchAlgorithm, ET9BOOL setForMGD);
    ET9PRIVATE void  ET9FARCALL _SWCSearchDB_SetZ1OperationSetting(_SWCSearchDB *pThis, int Z1Level);
    ET9PRIVATE void  ET9FARCALL _SWCSearchDB_ClearSearchIPTable(_SWCSearchDB *pThis);
    ET9PRIVATE void  ET9FARCALL _SWCSearchDB_ReleaseObjects(_SWCSearchDB *pThis);
    ET9PRIVATE void  ET9FARCALL _SWCSearchDB_CreateSearchIPTable(_SWCSearchDB *pThis, SBYTE2 searchIndex, ALGORITHM_TYPE searchAlgorithm, ET9BOOL firstAlgorithm, ET9BOOL finalAlgorithm);
    ET9PRIVATE void  ET9FARCALL _SWCSearchDB_AnalyzePathLength(_SWCSearchDB *pThis, ALGORITHM_TYPE searchAlgorithm, ET9BOOL finalAlgorithm);

/*lint +e818 +e1762 */


#endif /* _SEARCHDB_H__INCLUDED_ */



/* eof */
