00001 #ifndef ORLM_QUANTIZER_H
00002 #define ORLM_QUANTIZER_H
00003
00004 #include <vector>
00005 #include <cmath>
00006 #include <algorithm>
00007 #include "types.h"
00008
00009 static const float kFloatErr = 0.00001f;
00010
00011 #ifdef WIN32
00012 #define log2(X) (log((double)X)/log((double)2))
00013 #endif
00014
00016 class LogQtizer
00017 {
00018 public:
00019 LogQtizer(float i): base_(pow(2, 1 / i)) {
00020 UTIL_THROW_IF2(base_ <= 1, "Can't calculate log base less than 1");
00021 max_code_ = 0;
00022 float value = 1;
00023 std::vector<float> code_to_value_vec;
00024 while (log2(value) < 30) {
00025 code_to_value_vec.push_back(value);
00026 value = pow(base_, ++max_code_);
00027 }
00028 code_to_value_vec.push_back(value);
00029
00030 max_value_ = code_to_value_vec[max_code_];
00031 min_value_ = 1;
00032
00033 code_to_value_ = new float[max_code_ + 1];
00034 code_to_log_value_ = new float[max_code_ + 1];
00035 for (int j = 0; j <= max_code_; ++j) {
00036
00037 code_to_value_[j] = floor(kFloatErr + code_to_value_vec[j]);
00038 code_to_log_value_[j] = log10(code_to_value_[j]);
00039 }
00040 std::cerr << "Initialized quantization (size = " << max_code_ + 1 << ")" << std::endl;
00041 }
00042 LogQtizer(Moses::FileHandler* fin) {
00043 UTIL_THROW_IF2(fin == NULL, "Null file handle");
00044 load(fin);
00045 }
00046 int code(float value) {
00047
00048 UTIL_THROW_IF2(value < min_value_ || value > max_value_,
00049 "Value " << value << " out of bound");
00050
00051
00052 int code = static_cast<int>(std::lower_bound(code_to_value_, code_to_value_+ max_code_,
00053 value) - code_to_value_);
00054
00055 code = code_to_value_[code] > value ? code - 1 : code;
00056 return code;
00057 }
00058 inline float value(int code) {
00059
00060 return code_to_value_[code];
00061 }
00062 inline int maxcode() {
00063 return max_code_;
00064 }
00065 inline float logValue(int code) {
00066
00067 return code_to_log_value_[code];
00068 }
00069 ~LogQtizer() {
00070 delete[] code_to_value_;
00071 delete[] code_to_log_value_;
00072 }
00073 void save(Moses::FileHandler* fout) {
00074 fout->write((char*)&base_, sizeof(base_));
00075 fout->write((char*)&max_code_, sizeof(max_code_));
00076 fout->write((char*)&max_value_, sizeof(max_value_));
00077 fout->write((char*)&min_value_, sizeof(min_value_));
00078 for (int j = 0; j <= max_code_; ++j)
00079 fout->write((char*)&code_to_value_[j], sizeof(code_to_value_[j]));
00080 for (int j = 0; j <= max_code_; ++j)
00081 fout->write((char*)&code_to_log_value_[j], sizeof(code_to_log_value_[j]));
00082 std::cerr << "Saved log codebook with " << max_code_ + 1 << " codes." <<std::endl;
00083 }
00084 private:
00085 float base_;
00086 float* code_to_value_;
00087 float* code_to_log_value_;
00088 int max_code_;
00089 float max_value_;
00090 float min_value_;
00091 void load(Moses::FileHandler* fin) {
00092 fin->read((char*)&base_, sizeof(base_));
00093 fin->read((char*)&max_code_, sizeof(max_code_));
00094 fin->read((char*)&max_value_, sizeof(max_value_));
00095 fin->read((char*)&min_value_, sizeof(min_value_));
00096 code_to_value_ = new float[max_code_ + 1];
00097 for(int j = 0; j <= max_code_; ++j)
00098 fin->read((char*)&code_to_value_[j], sizeof(code_to_value_[j]));
00099 code_to_log_value_ = new float[max_code_ + 1];
00100 for(int j = 0; j <= max_code_; ++j)
00101 fin->read((char*)&code_to_log_value_[j], sizeof(code_to_log_value_[j]));
00102 std::cerr << "Loaded log codebook with " << max_code_ + 1 << " codes." << std::endl;
00103 }
00104 };
00105
00106 #endif