00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include "lux.h"
00025 #include "stats.h"
00026
00027 #include "timer.h"
00028 #include <map>
00029 using std::map;
00030
00031 #include <cstdarg>
00032
00033
00034 using namespace lux;
00035
00036 #if 0
00037
00038 #define LUX_ERROR_IGNORE 0
00039 #define LUX_ERROR_CONTINUE 1
00040 #define LUX_ERROR_ABORT 2
00041
00042 static void processError(const char *format, va_list args,
00043 const char *message, int disposition) {
00044 #ifndef WIN32
00045 char *errorBuf;
00046 vasprintf(&errorBuf, format, args);
00047 #else
00048 char errorBuf[2048];
00049 _vsnprintf(errorBuf, sizeof(errorBuf), format, args);
00050 #endif
00051
00052 switch (disposition) {
00053 case LUX_ERROR_IGNORE:
00054 return;
00055 case LUX_ERROR_CONTINUE:
00056 fprintf(stderr, "%s: %s\n", message, errorBuf);
00057
00058 extern int line_num;
00059 if (line_num != 0) {
00060 extern string current_file;
00061 fprintf(stderr, "\tLine %d, file %s\n", line_num,
00062 current_file.c_str());
00063 }
00064 break;
00065 case LUX_ERROR_ABORT:
00066 fprintf(stderr, "%s: %s\n", message, errorBuf);
00067
00068 extern int line_num;
00069 if (line_num != 0) {
00070 extern string current_file;
00071 fprintf(stderr, "\tLine %d, file %s\n", line_num,
00072 current_file.c_str());
00073 }
00074 exit(1);
00075 }
00076 #ifndef WIN32
00077 free(errorBuf);
00078 #endif
00079 }
00080 #endif
00081
00082 namespace lux
00083 {
00084 #if 0
00085 void Info(const char *format, ...) {
00086 va_list args;
00087 va_start(args, format);
00088 processError(format, args, "Notice", LUX_ERROR_CONTINUE);
00089 va_end(args);
00090 }
00091 void Warning(const char *format, ...) {
00092 va_list args;
00093 va_start(args, format);
00094 processError(format, args, "Warning", LUX_ERROR_CONTINUE);
00095 va_end(args);
00096 }
00097 void Error(const char *format, ...) {
00098 va_list args;
00099 va_start(args, format);
00100 processError(format, args, "Error", LUX_ERROR_CONTINUE);
00101 va_end(args);
00102 }
00103 void Severe(const char *format, ...) {
00104 va_list args;
00105 va_start(args, format);
00106 processError(format, args, "Fatal Error", LUX_ERROR_ABORT);
00107 va_end(args);
00108 }
00109 #endif
00110
00111 bool SolveLinearSystem2x2(const float A[2][2],
00112 const float B[2], float x[2]) {
00113 float det = A[0][0]*A[1][1] - A[0][1]*A[1][0];
00114 if (fabsf(det) < 1e-5)
00115 return false;
00116 float invDet = 1.0f/det;
00117 x[0] = (A[1][1]*B[0] - A[0][1]*B[1]) * invDet;
00118 x[1] = (A[0][0]*B[1] - A[1][0]*B[0]) * invDet;
00119 return true;
00120 }
00121
00122 }
00123
00124
00125 struct StatTracker {
00126 StatTracker(const string &cat, const string &n,
00127 StatsCounterType *pa, StatsCounterType *pb = NULL,
00128 bool percentage = true);
00129 string category, name;
00130 StatsCounterType *ptra, *ptrb;
00131 bool percentage;
00132 };
00133 typedef map<std::pair<string, string>, StatTracker *> TrackerMap;
00134 static TrackerMap trackers;
00135 static void addTracker(StatTracker *newTracker) {
00136 std::pair<string, string> s = std::make_pair(newTracker->category, newTracker->name);
00137 if (trackers.find(s) != trackers.end()) {
00138 newTracker->ptra = trackers[s]->ptra;
00139 newTracker->ptrb = trackers[s]->ptrb;
00140 return;
00141 }
00142 trackers[s] = newTracker;
00143 }
00144 namespace lux {
00145 static void StatsPrintVal(FILE *f, StatsCounterType v);
00146 static void StatsPrintVal(FILE *f, StatsCounterType v1, StatsCounterType v2);
00147 }
00148
00149 StatTracker::StatTracker(const string &cat, const string &n,
00150 StatsCounterType *pa, StatsCounterType *pb, bool p) {
00151 category = cat;
00152 name = n;
00153 ptra = pa;
00154 ptrb = pb;
00155 percentage = p;
00156 }
00157 StatsCounter::StatsCounter(const string &category, const string &name) {
00158 num = 0;
00159 addTracker(new StatTracker(category, name, &num));
00160 }
00161 StatsRatio::StatsRatio(const string &category, const string &name) {
00162 na = nb = 0;
00163 addTracker(new StatTracker(category, name, &na, &nb, false));
00164 }
00165 StatsPercentage::StatsPercentage(const string &category, const string &name) {
00166 na = nb = 0;
00167 addTracker(new StatTracker(category, name, &na, &nb, true));
00168 }
00169
00170 namespace lux {
00171
00172 void StatsPrint(FILE *dest) {
00173 TrackerMap::iterator iter = trackers.begin();
00174 if(iter != trackers.end())
00175 fprintf(dest, "Statistics:\n");
00176
00177 string lastCategory;
00178 while (iter != trackers.end()) {
00179
00180 StatTracker *tr = iter->second;
00181 if (tr->category != lastCategory) {
00182 fprintf(dest, "%s\n", tr->category.c_str());
00183 lastCategory = tr->category;
00184 }
00185 fprintf(dest, " %s", tr->name.c_str());
00186
00187 int resultsColumn = 56;
00188 int paddingSpaces = resultsColumn - (int) tr->name.size();
00189 while (paddingSpaces-- > 0)
00190 putc(' ', dest);
00191 if (tr->ptrb == NULL)
00192 StatsPrintVal(dest, *tr->ptra);
00193 else {
00194 if (*tr->ptrb > 0) {
00195 float ratio = (float)*tr->ptra / (float)*tr->ptrb;
00196 StatsPrintVal(dest, *tr->ptra, *tr->ptrb);
00197 if (tr->percentage)
00198 fprintf(dest, " (%3.2f%%)", 100. * ratio);
00199 else
00200 fprintf(dest, " (%.2fx)", ratio);
00201 }
00202 else
00203 StatsPrintVal(dest, *tr->ptra, *tr->ptrb);
00204 }
00205 fprintf(dest, "\n");
00206 ++iter;
00207 }
00208 }
00209 static void StatsPrintVal(FILE *f, StatsCounterType v) {
00210 if (v > 1e9) fprintf(f, "%.3fB", v / 1e9f);
00211 else if (v > 1e6) fprintf(f, "%.3fM", v / 1e6f);
00212 else if (v > 1e4) fprintf(f, "%.1fk", v / 1e3f);
00213 else fprintf(f, "%.0f", (float)v);
00214 }
00215 static void StatsPrintVal(FILE *f, StatsCounterType v1,
00216 StatsCounterType v2) {
00217 StatsCounterType m = min(v1, v2);
00218 if (m > 1e9) fprintf(f, "%.3fB:%.3fB", v1 / 1e9f, v2 / 1e9f);
00219 else if (m > 1e6) fprintf(f, "%.3fM:%.3fM", v1 / 1e6f, v2 / 1e6f);
00220 else if (m > 1e4) fprintf(f, "%.1fk:%.1fk", v1 / 1e3f, v2 / 1e3f);
00221 else fprintf(f, "%.0f:%.0f", v1, v2);
00222 }
00223 void StatsCleanup() {
00224 TrackerMap::iterator iter = trackers.begin();
00225 string lastCategory;
00226 while (iter != trackers.end()) {
00227 delete iter->second;
00228 ++iter;
00229 }
00230 trackers.erase(trackers.begin(), trackers.end());
00231 }
00232
00233
00234 void *AllocAligned(size_t size) {
00235 #ifndef L1_CACHE_LINE_SIZE
00236 #define L1_CACHE_LINE_SIZE 64
00237 #endif
00238 return memalign(L1_CACHE_LINE_SIZE, size);
00239 }
00240 void FreeAligned(void *ptr) {
00241 #if defined(WIN32) && !defined(__CYGWIN__) // NOBOOK
00242 _aligned_free(ptr);
00243 #else // NOBOOK
00244 free(ptr);
00245 #endif // NOBOOK
00246 }
00247
00248 }
00249
00250
00251 ProgressReporter::ProgressReporter(int totalWork, const string &title, int bar_length)
00252 : totalPlusses(bar_length - title.size()) {
00253 plussesPrinted = 0;
00254 frequency = (float)totalWork / (float)totalPlusses;
00255 count = frequency;
00256 timer = new Timer();
00257 timer->Start();
00258 outFile = stdout;
00259
00260 const int bufLen = title.size() + totalPlusses + 64;
00261 buf = new char[bufLen];
00262 snprintf(buf, bufLen, "\r%s: [", title.c_str());
00263 curSpace = buf + strlen(buf);
00264 char *s = curSpace;
00265 for (int i = 0; i < totalPlusses; ++i)
00266 *s++ = ' ';
00267 *s++ = ']';
00268 *s++ = ' ';
00269 *s++ = '\0';
00270 fprintf(outFile, buf);
00271 fflush(outFile);
00272 }
00273 ProgressReporter::~ProgressReporter() { delete[] buf; delete timer; }
00274 void ProgressReporter::Update(int num) const {
00275 count -= num;
00276 bool updatedAny = false;
00277 while (count <= 0) {
00278 count += frequency;
00279 if (plussesPrinted++ < totalPlusses)
00280 *curSpace++ = '+';
00281 updatedAny = true;
00282 }
00283 if (updatedAny) {
00284 fputs(buf, outFile);
00285
00286 float percentDone = (float)plussesPrinted / (float)totalPlusses;
00287 float seconds = (float) timer->Time();
00288 float estRemaining = seconds / percentDone - seconds;
00289 if (percentDone == 1.f)
00290 fprintf(outFile, " (%.1fs) ", seconds);
00291 else
00292 fprintf(outFile, " (%.1fs|%.1fs) ", seconds, max(0.f, estRemaining));
00293 fflush(outFile);
00294 }
00295 }
00296 void ProgressReporter::Done() const {
00297 while (plussesPrinted++ < totalPlusses)
00298 *curSpace++ = '+';
00299 fputs(buf, outFile);
00300 float seconds = (float) timer->Time();
00301 fprintf(outFile, " (%.1fs) \n", seconds);
00302 fflush(outFile);
00303 }
00304
00305
00306 #include "randomgen.h"
00307 namespace lux
00308 {
00309 namespace random
00310 {
00311
00312 boost::thread_specific_ptr<RandomGenerator> myGen;
00313 }
00314 }
00315
00316
00317 namespace lux
00318 {
00319
00320
00321
00322 unsigned int DJBHash(const std::string& str)
00323 {
00324 unsigned int hash = 5381;
00325
00326 for(std::size_t i = 0; i < str.length(); i++)
00327 {
00328 hash = ((hash << 5) + hash) + str[i];
00329 }
00330
00331 return hash;
00332 }
00333 }