/* * libpinyin * Library to deal with pinyin. * * Copyright (C) 2016 Peng Wu * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #ifndef PINYIN_PHRASE3_H #define PINYIN_PHRASE3_H #include #include "novel_types.h" #include "chewing_key.h" /* All compare function should be symmetric for the lhs and rhs operands. URL: http://en.cppreference.com/w/cpp/algorithm/equal_range . */ namespace pinyin{ inline int pinyin_exact_compare2(const ChewingKey * key_lhs, const ChewingKey * key_rhs, int phrase_length){ int i; int result; /* compare initial */ for (i = 0; i < phrase_length; ++i) { result = key_lhs[i].m_initial - key_rhs[i].m_initial; if (0 != result) return result; } /* compare middle and final */ for (i = 0; i < phrase_length; ++i) { result = key_lhs[i].m_middle - key_rhs[i].m_middle; if (0 != result) return result; result = key_lhs[i].m_final - key_rhs[i].m_final; if (0 != result) return result; } /* compare tone */ for (i = 0; i < phrase_length; ++i) { result = key_lhs[i].m_tone - key_rhs[i].m_tone; if (0 != result) return result; } return 0; } /* compare pinyins with chewing internal representations, fuzzy pinyin is not handled here. */ inline int pinyin_compare_initial3(ChewingInitial lhs, ChewingInitial rhs) { return (lhs - rhs); } inline int pinyin_compare_middle_and_final3(ChewingMiddle middle_lhs, ChewingMiddle middle_rhs, ChewingFinal final_lhs, ChewingFinal final_rhs) { if (middle_lhs == middle_rhs && final_lhs == final_rhs) return 0; /* handle in-complete pinyin here. */ if (middle_lhs == CHEWING_ZERO_MIDDLE && final_lhs == CHEWING_ZERO_FINAL) return 0; if (middle_rhs == CHEWING_ZERO_MIDDLE && final_rhs == CHEWING_ZERO_FINAL) return 0; /* compare chewing middle first. */ int middle_diff = middle_lhs - middle_rhs; if (middle_diff) return middle_diff; return (final_lhs - final_rhs); } inline int pinyin_compare_tone3(ChewingTone lhs, ChewingTone rhs) { if (lhs == rhs) return 0; if (lhs == CHEWING_ZERO_TONE) return 0; if (rhs == CHEWING_ZERO_TONE) return 0; return (lhs - rhs); } /* compare with incomplete pinyin and zero tone. */ inline int pinyin_compare_with_tones(const ChewingKey * key_lhs, const ChewingKey * key_rhs, int phrase_length){ int i; int result; /* compare initial */ for (i = 0; i < phrase_length; ++i) { result = pinyin_compare_initial3 ((ChewingInitial)key_lhs[i].m_initial, (ChewingInitial)key_rhs[i].m_initial); if (0 != result) return result; } /* compare middle and final */ for (i = 0; i < phrase_length; ++i) { result = pinyin_compare_middle_and_final3 ((ChewingMiddle)key_lhs[i].m_middle, (ChewingMiddle)key_rhs[i].m_middle, (ChewingFinal) key_lhs[i].m_final, (ChewingFinal) key_rhs[i].m_final); if (0 != result) return result; } /* compare tone */ for (i = 0; i < phrase_length; ++i) { result = pinyin_compare_tone3 ((ChewingTone)key_lhs[i].m_tone, (ChewingTone)key_rhs[i].m_tone); if (0 != result) return result; } return 0; } inline bool contains_incomplete_pinyin(const ChewingKey * keys, int phrase_length) { for (int i = 0; i < phrase_length; ++i) { const ChewingKey key = keys[i]; if (CHEWING_ZERO_MIDDLE == key.m_middle && CHEWING_ZERO_FINAL == key.m_final) { assert(CHEWING_ZERO_TONE == key.m_tone); return true; } } return false; } inline void compute_chewing_index(const ChewingKey * in_keys, ChewingKey * out_keys, int phrase_length) { for (int i = 0; i < phrase_length; ++i) { ChewingKey key = in_keys[i]; key.m_tone = CHEWING_ZERO_TONE; out_keys[i] = key; } } inline void compute_incomplete_chewing_index(const ChewingKey * in_keys, ChewingKey * out_keys, int phrase_length) { for (int i = 0; i < phrase_length; ++i) { ChewingKey key; key.m_initial = in_keys[i].m_initial; out_keys[i] = key; } } template struct PinyinIndexItem2{ phrase_token_t m_token; ChewingKey m_keys[phrase_length]; public: PinyinIndexItem2 () { memset(m_keys, 0, sizeof(ChewingKey) * phrase_length); m_token = null_token; } PinyinIndexItem2 (const ChewingKey * keys, phrase_token_t token) { memmove(m_keys, keys, sizeof(ChewingKey) * phrase_length); m_token = token; } }; /* for find the element in the phrase array */ template inline int phrase_exact_compare2(const PinyinIndexItem2 &lhs, const PinyinIndexItem2 &rhs) { ChewingKey * keys_lhs = (ChewingKey *) lhs.m_keys; ChewingKey * keys_rhs = (ChewingKey *) rhs.m_keys; return pinyin_exact_compare2(keys_lhs, keys_rhs, phrase_length); } template inline bool phrase_exact_less_than2(const PinyinIndexItem2 &lhs, const PinyinIndexItem2 &rhs) { return 0 > phrase_exact_compare2(lhs, rhs); } template inline int phrase_compare_with_tones(const PinyinIndexItem2 &lhs, const PinyinIndexItem2 &rhs) { ChewingKey * keys_lhs = (ChewingKey *) lhs.m_keys; ChewingKey * keys_rhs = (ChewingKey *) rhs.m_keys; return pinyin_compare_with_tones(keys_lhs, keys_rhs, phrase_length); } template inline int phrase_less_than_with_tones(const PinyinIndexItem2 &lhs, const PinyinIndexItem2 &rhs) { return 0 > phrase_compare_with_tones(lhs, rhs); } }; #endif