00001 #ifndef BIT_FLOATARRAY_HH
00002 #define BIT_FLOATARRAY_HH
00003
00004 #include "bit/util.hh"
00005 #include <float.h>
00006 #include "bit/Array.hh"
00007 #include "bit/endian.hh"
00008
00009 namespace bit {
00010
00013 class FloatArray : public Array {
00014 public:
00015
00017 FloatArray()
00018 : Array(0, 0), m_mode(mode_default)
00019 {
00020 }
00021
00026 FloatArray(u64 num_elems, unsigned int bits_per_elem = 0)
00027 : Array(num_elems, bits_per_elem), m_mode(mode_default)
00028 {
00029 }
00030
00034 void set_mode(const FloatArray &array)
00035 {
00036 if (m_mode != mode_default)
00037 throw bit::invalid_call(
00038 "bit::FloatArray::set_mode() not default mode");
00039 if (array.m_mode == mode_default)
00040 return;
00041 else if (array.m_mode == mode_linear) {
00042 linear_quantization(array.m_linear_step);
00043 return;
00044 }
00045 assert(false);
00046 }
00047
00054 void linear_quantization(double step)
00055 {
00056 if (m_mode != mode_default)
00057 throw bit::invalid_call(
00058 "bit::FloatArray::set_linear_quantization() already quantized");
00059 if (step < 0)
00060 throw bit::invalid_argument(
00061 "bit::FloatArray::set_linear_quantization() negative step");
00062
00063 if (num_elems() == 0 || bits_per_elem() == 0) {
00064 m_mode = mode_linear;
00065 m_linear_step = step;
00066 return;
00067 }
00068
00069 FloatArray new_array(num_elems(), 0);
00070 new_array.linear_quantization(step);
00071 for (u64 i = 0; i < num_elems(); i++)
00072 new_array.set_grow_widen(i, get(i));
00073 *this = new_array;
00074 }
00075
00085 void linear_quantization_bits(unsigned int bits)
00086 {
00087 if (bits < 2 || bits > 31)
00088 throw bit::invalid_call(
00089 "bit::FloatArray::linear_quantization_bits() invalid bits argument");
00090
00091 if (num_elems() == 0 || bits_per_elem() == 0)
00092 return;
00093
00094 float min = FLT_MAX;
00095 float max = -FLT_MAX;
00096 for (u64 i = 0; i < num_elems(); i++) {
00097 float value = get(i);
00098 if (value < min)
00099 min = value;
00100 if (value > max)
00101 max = value;
00102 }
00103
00104 float absmax = std::max(util::abs(min), util::abs(max));
00105 if (absmax == 0)
00106 return;
00107
00108 linear_quantization(absmax / bit::one_masks[bits - 1]);
00109 }
00110
00116 float get(u64 elem) const
00117 {
00118 return to_float(Array::get(elem));
00119 }
00120
00129 void set(u64 elem, float value)
00130 {
00131 Array::set(elem, to_uint(value));
00132 }
00133
00142 void set_grow(u64 elem, float value)
00143 {
00144 Array::set_grow(elem, to_uint(value));
00145 }
00146
00155 void set_grow_widen(u64 elem, float value)
00156 {
00157 Array::set_grow_widen(elem, to_uint(value));
00158 }
00159
00164 u32 to_uint(float value) const
00165 {
00166 switch (m_mode) {
00167 case mode_default:
00168 return float2uint(value);
00169 case mode_linear:
00170 return quantize_float(value, m_linear_step);
00171 case mode_kmeans:
00172 break;
00173 }
00174 assert(false);
00175 return 0;
00176 }
00177
00182 float to_float(u32 i) const
00183 {
00184 switch (m_mode) {
00185 case mode_default:
00186 return uint2float(i);
00187 case mode_linear:
00188 return unquantize_float(i, m_linear_step);
00189 case mode_kmeans:
00190 break;
00191 }
00192 assert(false);
00193 return 0;
00194 }
00195
00201 void write(FILE *file) const
00202 {
00203 fprintf(file, "FARRAY1:%d:", (int)m_mode);
00204 size_t ret = endian::write8(m_linear_step, file);
00205 try {
00206 if (ret != 1)
00207 throw io_error("writing m_linear_step failed");
00208 Array::write(file);
00209 }
00210 catch (std::exception &e) {
00211 throw io_error(
00212 std::string("bit::FloatArray::write() failed: ") + e.what());
00213 }
00214 }
00215
00221 void read(FILE *file)
00222 {
00223 int version;
00224 int mode;
00225 int ret = fscanf(file, "FARRAY%d:%d:", &version, &mode);
00226 if (ret != 2 || version != 1)
00227 throw bit::io_error(
00228 "bit::FloatArray::read() error while reading header");
00229 m_mode = (Mode)mode;
00230 try {
00231 size_t ret = endian::read8(&m_linear_step, file);
00232 if (ret != 1)
00233 throw io_error("reading m_linear_step failed");
00234 Array::read(file);
00235 }
00236 catch (std::exception &e) {
00237 throw io_error(
00238 std::string("bit::FloatArray::read() failed: ") + e.what());
00239 }
00240 }
00241
00242 private:
00243
00245 enum Mode { mode_default = 0, mode_linear, mode_kmeans } m_mode;
00246
00248 double m_linear_step;
00249
00250 };
00251
00252 };
00253
00254 #endif