/* See {pz_symbol.h}. */ /* Last edited on 2008-02-12 19:22:39 by stolfi */ #include #include #include #include #define pz_symbol_valid_chars SET OF CHAR { 'a' .. 'z', '0', 'A'..'Z' } ; #define SqrtTwo (1.4142135623730950488) bool_t pz_symbol_is_valid(int c) { return ( ((c >= 'a') && (c <= 'z')) || ((c >= 'A') && (c <= 'Z')) || (c == '0') ); } int pz_symbol_to_int(pz_symbol_t ch) { if ((ch >= 'a') && (ch <= 'z')) { return -(int)(ch - 'a' + 1); } else if ((ch >= 'A') && (ch <= 'Z')) { return +(int)(ch - 'A' + 1); } else { return 0; } } pz_symbol_t pz_symbol_from_int(int i) { if (i > 0) { return (pz_symbol_t)((int)'A' + i - 1); } else if (i < 0) { return (pz_symbol_t)((int)'a' - i + 1); } else { return (pz_symbol_t)'0'; } } pz_symbol_t pz_symbol_encode(double x, double sigma) { double h = pz_squeeze(x, sigma); double hs = fmin(+1.0, fmax(-1.0, h)); int cs = pz_round(26.4999999 * hs); if (cs < 0) { return (pz_symbol_t)('a' - cs - 1); } else if (cs > 0) { return (pz_symbol_t)('A' + cs - 1); } else { return (pz_symbol_t)'0'; } } double pz_symbol_decode(pz_symbol_t c, double sigma) { double t; switch(c) { case 'z': t = -1.660378790 ; break; /* -26 */ case 'y': t = -1.347998672 ; break; /* -25 */ case 'x': t = -1.182945371 ; break; /* -24 */ case 'w': t = -1.064879956 ; break; /* -23 */ case 'v': t = -0.9707234887 ; break; /* -22 */ case 'u': t = -0.8911941104 ; break; /* -21 */ case 't': t = -0.8215753040 ; break; /* -20 */ case 's': t = -0.7591232363 ; break; /* -19 */ case 'r': t = -0.7020920871 ; break; /* -18 */ case 'q': t = -0.6492973318 ; break; /* -17 */ case 'p': t = -0.5998952031 ; break; /* -16 */ case 'o': t = -0.5532611312 ; break; /* -15 */ case 'n': t = -0.5089180847 ; break; /* -14 */ case 'm': t = -0.4664920092 ; break; /* -13 */ case 'l': t = -0.4256828778 ; break; /* -12 */ case 'k': t = -0.3862451866 ; break; /* -11 */ case 'j': t = -0.3479743920 ; break; /* -10 */ case 'i': t = -0.3106972226 ; break; /* -09 */ case 'h': t = -0.2742645829 ; break; /* -08 */ case 'g': t = -0.2385462394 ; break; /* -07 */ case 'f': t = -0.2034267554 ; break; /* -06 */ case 'e': t = -0.1688023113 ; break; /* -05 */ case 'd': t = -0.1345781676 ; break; /* -04 */ case 'c': t = -0.1006665890 ; break; /* -03 */ case 'b': t = -0.06698510374; break; /* -02 */ case 'a': t = -0.03345500266; break; /* -01 */ case '0': t = 00.00000000000; break; /* 000 */ case 'A': t = +0.03345500266; break; /* +01 */ case 'B': t = +0.06698510374; break; /* +02 */ case 'C': t = +0.1006665890 ; break; /* +03 */ case 'D': t = +0.1345781676 ; break; /* +04 */ case 'E': t = +0.1688023113 ; break; /* +05 */ case 'F': t = +0.2034267553 ; break; /* +06 */ case 'G': t = +0.2385462394 ; break; /* +07 */ case 'H': t = +0.2742645829 ; break; /* +08 */ case 'I': t = +0.3106972226 ; break; /* +09 */ case 'J': t = +0.3479743920 ; break; /* +10 */ case 'K': t = +0.3862451866 ; break; /* +11 */ case 'L': t = +0.4256828778 ; break; /* +12 */ case 'M': t = +0.4664920092 ; break; /* +13 */ case 'N': t = +0.5089180847 ; break; /* +14 */ case 'O': t = +0.5532611312 ; break; /* +15 */ case 'P': t = +0.5998952031 ; break; /* +16 */ case 'Q': t = +0.6492973318 ; break; /* +17 */ case 'R': t = +0.7020920871 ; break; /* +18 */ case 'S': t = +0.7591232363 ; break; /* +19 */ case 'T': t = +0.8215753040 ; break; /* +20 */ case 'U': t = +0.8911941104 ; break; /* +21 */ case 'V': t = +0.9707234887 ; break; /* +22 */ case 'W': t = +1.0648799560 ; break; /* +23 */ case 'X': t = +1.1829453710 ; break; /* +24 */ case 'Y': t = +1.3479986720 ; break; /* +25 */ case 'Z': t = +1.6603787900 ; break; /* +26 */ default: affirm(FALSE, "bug"); t = 0.0; } return t * sigma*SqrtTwo; } double pz_symbol_error_var(pz_symbol_t c, double sigma) { double t; switch(c) { case 'z': t = 0.070894076833 ; break; /* -26 */ case 'y': t = 0.033492902752 ; break; /* -25 */ case 'x': t = 0.026966880823 ; break; /* -24 */ case 'w': t = 0.023567564366 ; break; /* -23 */ case 'v': t = 0.021396374124 ; break; /* -22 */ case 'u': t = 0.019861386664 ; break; /* -21 */ case 't': t = 0.018707560200 ; break; /* -20 */ case 's': t = 0.017804070706 ; break; /* -19 */ case 'r': t = 0.017075871056 ; break; /* -18 */ case 'q': t = 0.016476395566 ; break; /* -17 */ case 'p': t = 0.015975017831 ; break; /* -16 */ case 'o': t = 0.015550669845 ; break; /* -15 */ case 'n': t = 0.015188334568 ; break; /* -14 */ case 'm': t = 0.014876997925 ; break; /* -13 */ case 'l': t = 0.014608391552 ; break; /* -12 */ case 'k': t = 0.014376190323 ; break; /* -11 */ case 'j': t = 0.014175481623 ; break; /* -10 */ case 'i': t = 0.014002404589 ; break; /* -09 */ case 'h': t = 0.013853898998 ; break; /* -08 */ case 'g': t = 0.0137275268070; break; /* -07 */ case 'f': t = 0.0136213431795; break; /* -06 */ case 'e': t = 0.0135338025270; break; /* -05 */ case 'd': t = 0.0134636891449; break; /* -04 */ case 'c': t = 0.0134100665806; break; /* -03 */ case 'b': t = 0.0133722402760; break; /* -02 */ case 'a': t = 0.0133497313538; break; /* -01 */ case '0': t = 0.0133422591945; break; /* 000 */ case 'A': t = 0.0133497313538; break; /* +01 */ case 'B': t = 0.0133722402760; break; /* +02 */ case 'C': t = 0.0134100665806; break; /* +03 */ case 'D': t = 0.0134636891449; break; /* +04 */ case 'E': t = 0.0135338025270; break; /* +05 */ case 'F': t = 0.0136213431795; break; /* +06 */ case 'G': t = 0.0137275268070; break; /* +07 */ case 'H': t = 0.013853898998 ; break; /* +08 */ case 'I': t = 0.014002404589 ; break; /* +09 */ case 'J': t = 0.014175481623 ; break; /* +10 */ case 'K': t = 0.014376190323 ; break; /* +11 */ case 'L': t = 0.014608391552 ; break; /* +12 */ case 'M': t = 0.014876997925 ; break; /* +13 */ case 'N': t = 0.015188334568 ; break; /* +14 */ case 'O': t = 0.015550669845 ; break; /* +15 */ case 'P': t = 0.015975017831 ; break; /* +16 */ case 'Q': t = 0.016476395566 ; break; /* +17 */ case 'R': t = 0.017075871056 ; break; /* +18 */ case 'S': t = 0.017804070706 ; break; /* +19 */ case 'T': t = 0.018707560200 ; break; /* +20 */ case 'U': t = 0.019861386664 ; break; /* +21 */ case 'V': t = 0.021396374124 ; break; /* +22 */ case 'W': t = 0.023567564366 ; break; /* +23 */ case 'X': t = 0.026966880823 ; break; /* +24 */ case 'Y': t = 0.033492902752 ; break; /* +25 */ case 'Z': t = 0.070894076833 ; break; /* +26 */ default: affirm(FALSE, "bug"); t = 0.0; } return t * sigma*sigma; } double_vec_t pz_symbol_make_decode_table(double sigma) { double_vec_t t = double_vec_new(256); int ic; for (ic = 0; ic < 256; ic++) { if (pz_symbol_is_valid(ic)) { t.el[ic] = pz_symbol_decode((char)ic, sigma); } else { t.el[ic] = 0.0; } } return t; } double_vec_t pz_symbol_make_error_var_table(double sigma) { double_vec_t t = double_vec_new(256); int ic; for (ic = 0; ic < 256; ic++) { if (pz_symbol_is_valid(ic)) { t.el[ic] = pz_symbol_error_var((char)ic, sigma); } else { t.el[ic] = 0.0; } } return t; } pz_symbol_t pz_symbol_complement(pz_symbol_t ch) { int i = pz_symbol_to_int(ch); return pz_symbol_from_int(-i); } double pz_symbol_dist_sqr ( pz_symbol_t a, pz_symbol_t b, bool_t complement, double_vec_t *decode, double_vec_t *errorVar ) { double d; int ia = ((int)a & 255); double sa = decode->el[ia], ea = errorVar->el[ia]; int ib = ((int)b & 255); double sb = decode->el[ib], eb = errorVar->el[ib]; if (complement) { d = sa + sb; } else { d = sa - sb; } return d*d + ea + eb; } double pz_symbol_intg_dist_sqr ( pz_symbol_t a1, pz_symbol_t a2, pz_symbol_t b1, pz_symbol_t b2, bool_t complement, double_vec_t *decode, double_vec_t *errorVar ) { double d1, d2; int ia1 = ((int)a1 & 255); double sa1 = decode->el[ia1], ea1 = errorVar->el[ia1]; int ib1 = ((int)b1 & 255); double sb1 = decode->el[ib1], eb1 = errorVar->el[ib1]; int ia2 = ((int)a2 & 255); double sa2 = decode->el[ia2], ea2 = errorVar->el[ia2]; int ib2 = ((int)b2 & 255); double sb2 = decode->el[ib2], eb2 = errorVar->el[ib2]; if (complement) { d1 = sa1 + sb1; d2 = sa2 + sb2; } else { d1 = sa1 - sb1; d2 = sa2 - sb2; } return (d1*d1 + d1*d2 + d2*d2 + ea1 + ea2 + eb1 + eb2)/3.0; }