00001 #ifndef MATRIX_UTILS_H
00002 #define MATRIX_UTILS_H
00003
00004 #include <iostream>
00005 #include <iomanip>
00006 #include <sstream>
00007 #include <string>
00008 #include <vector>
00009 #include <cfloat>
00010 #include <algorithm>
00011 #include <numeric>
00012 #include <stdint.h>
00013 #include <boost/numeric/ublas/matrix.hpp>
00014
00015
00016
00017 bool isDivisibleBy2(size_t n, int level);
00018
00019
00020 template <class Matrix>
00021 bool in_bounds(const Matrix& mat, size_t row, size_t col) {
00022 return (row < mat.size1()) && (col < mat.size2());
00023 }
00024
00025
00026 bool read_matrix(const char *filename, boost::numeric::ublas::matrix<double>& mat);
00027
00028
00029 template <class Matrix>
00030 void output(const Matrix& mat, std::ostream& out = std::cout) {
00031 const size_t width = 12;
00032
00033 for (size_t i=0; i < mat.size1(); i++) {
00034 if (mat.size2()) {
00035 out << std::setw(width) << mat(i,0);
00036 }
00037
00038 for (size_t j=1; j < mat.size2(); j++) {
00039 out << " " << std::setw(width) << mat(i,j);
00040 }
00041 out << std::endl;
00042 }
00043 }
00044
00045
00046 struct ms_summary {
00047 double sum_squares;
00048 double orig_max, orig_min;
00049 double repro_max, repro_min;
00050 double both_max, both_min;
00051
00052 ms_summary(double ss, double ma, double mi)
00053 : sum_squares(ss),
00054 orig_max(ma), orig_min(mi),
00055 repro_max(ma), repro_min(mi),
00056 both_max(ma), both_min(mi)
00057 { }
00058 };
00059
00060
00061 template <class Matrix>
00062 ms_summary get_summary(const Matrix& orig, const Matrix& repro,
00063 size_t row_start = 0, size_t row_end = std::numeric_limits<size_t>::max(),
00064 size_t col_start = 0, size_t col_end = std::numeric_limits<size_t>::max()) {
00065 assert(orig.size1() == repro.size1());
00066 assert(orig.size2() == repro.size2());
00067
00068 if (row_end > orig.size1()) row_end = orig.size1();
00069 if (col_end > orig.size2()) col_end = orig.size2();
00070
00071 ms_summary summary(0, -DBL_MAX, DBL_MAX);
00072
00073 for (size_t i=row_start; i < row_end; i++) {
00074 for (size_t j=col_start; j < col_end; j++) {
00075 double diff = repro(i,j) - orig(i,j);
00076 summary.sum_squares += diff*diff;
00077
00078 summary.orig_max = std::max(summary.orig_max, orig(i,j));
00079 summary.orig_min = std::min(summary.orig_min, orig(i,j));
00080 summary.repro_max = std::max(summary.repro_max, repro(i,j));
00081 summary.repro_min = std::min(summary.repro_min, repro(i,j));
00082 summary.both_max = std::max(summary.orig_max, summary.repro_max);
00083 summary.both_min = std::min(summary.orig_min, summary.repro_min);
00084 }
00085 }
00086
00087 return summary;
00088 }
00089
00090
00091 template <class Matrix>
00092 double rmse(const Matrix& orig, const Matrix& repro,
00093 size_t row_start = 0, size_t row_end = std::numeric_limits<size_t>::max(),
00094 size_t col_start = 0, size_t col_end = std::numeric_limits<size_t>::max()) {
00095 assert(orig.size1() == repro.size1());
00096 assert(orig.size2() == repro.size2());
00097
00098 if (row_end > orig.size1()) row_end = orig.size1();
00099 if (col_end > orig.size2()) col_end = orig.size2();
00100
00101 ms_summary summary = get_summary(orig, repro, row_start, row_end, col_start, col_end);
00102 size_t rows = (row_end - row_start);
00103 size_t cols = (col_end - col_start);
00104 return sqrt(summary.sum_squares / (rows * cols));
00105 }
00106
00107
00108
00109 template <class Matrix>
00110 double nrmse(const Matrix& orig, const Matrix& repro,
00111 size_t row_start = 0, size_t row_end = std::numeric_limits<size_t>::max(),
00112 size_t col_start = 0, size_t col_end = std::numeric_limits<size_t>::max()) {
00113 assert(orig.size1() == repro.size1());
00114 assert(orig.size2() == repro.size2());
00115
00116 if (row_end > orig.size1()) row_end = orig.size1();
00117 if (col_end > orig.size2()) col_end = orig.size2();
00118
00119 ms_summary summary = get_summary(orig, repro, row_start, row_end, col_start, col_end);
00120 double range = summary.orig_max - summary.orig_min;
00121 size_t rows = (row_end - row_start);
00122 size_t cols = (col_end - col_start);
00123 return sqrt(summary.sum_squares / (rows * cols)) / range;
00124 }
00125
00126
00127
00128 template <class Matrix>
00129 double psnr(const Matrix& orig, const Matrix& repro) {
00130 assert(orig.size1() == repro.size1());
00131 assert(orig.size2() == repro.size2());
00132
00133 ms_summary summary = get_summary(orig, repro);
00134 double range = summary.orig_max - summary.orig_min;
00135 return 20 * log10(range / sqrt(summary.sum_squares / (orig.size1() * orig.size2())));
00136 }
00137
00138
00139
00140 template <class Matrix>
00141 double similarity(const Matrix& orig, const Matrix& repro) {
00142 assert(orig.size1() == repro.size1());
00143 assert(orig.size2() == repro.size2());
00144
00145 ms_summary summary = get_summary(orig, repro);
00146 double range = summary.both_max - summary.both_min;
00147 return sqrt(summary.sum_squares / (orig.size1() * orig.size2())) / range;
00148 }
00149
00150
00151 template <class Matrix>
00152 void standardize(Matrix& mat) {
00153 size_t n = mat.size1() * mat.size2();
00154 double sum = 0;
00155 double sum2 = 0;
00156 for (size_t i=0; i < mat.size1(); i++) {
00157 for (size_t j=0; j < mat.size2(); j++) {
00158 sum += mat(i,j);
00159 sum2 += mat(i,j) * mat(i,j);
00160 }
00161 }
00162 double mean = sum / n;
00163 double stdDevInv = 1/sqrt(sum2/n - mean*mean);
00164
00165 for (size_t i=0; i < mat.size1(); i++) {
00166 for (size_t j=0; j < mat.size2(); j++) {
00167 mat(i,j) = (mat(i,j) - mean) * stdDevInv;
00168 }
00169 }
00170 }
00171
00172
00173
00174 template <typename T>
00175 struct Abs {
00176 T value;
00177 Abs(double num) : value(::fabs(num)) { }
00178 Abs(long num) : value(::labs(num)) { }
00179 Abs(unsigned long num) : value(::labs(num)) { }
00180 Abs(unsigned int num) : value(::labs(num)) { }
00181 Abs(long long num) : value(::llabs(num)) { }
00182 Abs(int num) : value(::abs(num)) { }
00183 };
00184
00185
00186
00187
00188 template<typename T> T abs_val(T num) {
00189 return Abs<T>(num).value;
00190 }
00191
00192
00193
00194 template <class Matrix>
00195 typename Matrix::value_type sum(const Matrix& mat,
00196 size_t row_start = 0, size_t row_end = std::numeric_limits<size_t>::max(),
00197 size_t col_start = 0, size_t col_end = std::numeric_limits<size_t>::max())
00198 {
00199 if (row_end > mat.size1()) row_end = mat.size1();
00200 if (col_end > mat.size2()) col_end = mat.size2();
00201
00202 typename Matrix::value_type total = 0;
00203 for (size_t i = row_start; i < row_end; i++) {
00204 for (size_t j = col_start; j < col_end; j++) {
00205 total += mat(i,j);
00206 }
00207 }
00208 return total;
00209 }
00210
00211
00212 template <class Matrix>
00213 double mean_val(const Matrix& mat,
00214 size_t row_start = 0, size_t row_end = std::numeric_limits<size_t>::max(),
00215 size_t col_start = 0, size_t col_end = std::numeric_limits<size_t>::max())
00216 {
00217 if (row_end > mat.size1()) row_end = mat.size1();
00218 if (col_end > mat.size2()) col_end = mat.size2();
00219
00220 size_t row_len = (row_end - row_start);
00221 size_t col_len = (col_end - col_start);
00222 return sum(mat, row_start, row_end, col_start, col_end)
00223 / ((double)row_len * col_len);
00224 }
00225
00226
00227 template <class Matrix>
00228 typename Matrix::value_type max_val(const Matrix& mat,
00229 size_t row_start = 0, size_t row_end = std::numeric_limits<size_t>::max(),
00230 size_t col_start = 0, size_t col_end = std::numeric_limits<size_t>::max())
00231 {
00232 if (row_end > mat.size1()) row_end = mat.size1();
00233 if (col_end > mat.size2()) col_end = mat.size2();
00234 if (row_end <= row_start || col_end <= col_start) return 0;
00235
00236 typename Matrix::value_type max = mat(row_start, col_start);
00237 for (size_t i = row_start; i < row_end; i++) {
00238 for (size_t j = col_start; j < col_end; j++) {
00239 max = mat(i,j) > max ? mat(i,j) : max;
00240 }
00241 }
00242 return max;
00243 }
00244
00245
00246 template <class Matrix>
00247 typename Matrix::value_type min_val(const Matrix& mat,
00248 size_t row_start = 0, size_t row_end = std::numeric_limits<size_t>::max(),
00249 size_t col_start = 0, size_t col_end = std::numeric_limits<size_t>::max())
00250 {
00251 if (row_end > mat.size1()) row_end = mat.size1();
00252 if (col_end > mat.size2()) col_end = mat.size2();
00253 if (row_end <= row_start || col_end <= col_start) return 0;
00254
00255 typename Matrix::value_type min = mat(row_start, col_start);
00256 for (size_t i = row_start; i < row_end; i++) {
00257 for (size_t j = col_start; j < col_end; j++) {
00258 min = mat(i,j) < min ? mat(i,j) : min;
00259 }
00260 }
00261 return min;
00262 }
00263
00264 template <class Matrix>
00265 typename Matrix::value_type abs_max_val(const Matrix& mat,
00266 size_t row_start = 0, size_t row_end = std::numeric_limits<size_t>::max(),
00267 size_t col_start = 0, size_t col_end = std::numeric_limits<size_t>::max())
00268 {
00269 if (row_end > mat.size1()) row_end = mat.size1();
00270 if (col_end > mat.size2()) col_end = mat.size2();
00271
00272 typename Matrix::value_type amax = 0;
00273 for (size_t i = row_start; i < row_end; i++) {
00274 for (size_t j = col_start; j < col_end; j++) {
00275 typename Matrix::value_type tmp = abs_val(mat(i,j));
00276 amax = (tmp > amax) ? tmp : amax;
00277 }
00278 }
00279 return amax;
00280 }
00281
00282 template <class Matrix, typename V>
00283 void set_all(const Matrix& mat, V value,
00284 size_t row_start = 0, size_t row_end = std::numeric_limits<size_t>::max(),
00285 size_t col_start = 0, size_t col_end = std::numeric_limits<size_t>::max())
00286 {
00287 if (row_end > mat.size1()) row_end = mat.size1();
00288 if (col_end > mat.size2()) col_end = mat.size2();
00289
00290 for (size_t i = row_start; i < row_end; i++) {
00291 for (size_t j = col_start; j < col_end; j++) {
00292 mat(i,j) = value;
00293 }
00294 }
00295 }
00296
00297
00298 template <typename Iterator1, typename Iterator2>
00299 double manhattan_distance(Iterator1 first1, Iterator1 last1, Iterator2 first2) {
00300 double sum = 0.0;
00301 Iterator1 i = first1;
00302 Iterator2 j = first2;
00303 while (i != last1) {
00304 sum += abs_val(*i - *j);
00305 i++;
00306 j++;
00307 }
00308 return sum;
00309 }
00310
00311
00312 template <typename Iterator1, typename Iterator2>
00313 double euclidean_distance(Iterator1 first1, Iterator1 last1, Iterator2 first2) {
00314 double sum = 0.0;
00315 Iterator1 i = first1;
00316 Iterator2 j = first2;
00317 while (i != last1) {
00318 double diff = (*i - *j);
00319 sum += diff * diff;
00320 i++;
00321 j++;
00322 }
00323 return sqrt(sum);
00324 }
00325
00326
00327
00328
00329
00330 template <class Matrix>
00331 double interp_bilinear(const Matrix& mat, double x, double y) {
00332 if (x < 0) {
00333 x = 0;
00334 } else if (x > (mat.size1() - 1)) {
00335 x = mat.size1() - 1;
00336 }
00337
00338 if (y < 0) {
00339 y = 0;
00340 } else if (y > (mat.size2() - 1)) {
00341 y = mat.size2() - 1;
00342 }
00343
00344
00345 size_t x1 = (size_t)floor(x);
00346 size_t x2 = (size_t)ceil(x);
00347
00348 size_t y1 = (size_t)floor(y);
00349 size_t y2 = (size_t)ceil(y);
00350
00351 size_t xd = (x2-x1);
00352 size_t yd = (y2-y1);
00353
00354 double value;
00355 if (xd == 0 && yd == 0) {
00356 value = mat(x1,y1);
00357
00358 } else if (yd == 0) {
00359 value = (x2 - x) * mat(x1,y1) + (x - x1) * mat(x2, y2);
00360
00361 } else if (xd == 0) {
00362 value = (y2 - y) * mat(x1,y1) + (y - y1) * mat(x2, y2);
00363
00364 } else {
00365 double d = xd * yd;
00366 value =
00367 mat(x1,y1)/d * ((x2-x) * (y2-y)) +
00368 mat(x2,y1)/d * ((x-x1) * (y2-y)) +
00369 mat(x1,y2)/d * ((x2-x) * (y-y1)) +
00370 mat(x2,y2)/d * ((x-x1) * (y-y1));
00371 }
00372
00373 return value;
00374 }
00375
00376 #endif // MATRIX_UTILS_H