util.cpp

Go to the documentation of this file.
00001 
00002 /*
00003  * pbrt source code Copyright(c) 1998-2007 Matt Pharr and Greg Humphreys
00004  *
00005  * All Rights Reserved.
00006  * For educational use only; commercial use expressly forbidden.
00007  * NO WARRANTY, express or implied, for this software.
00008  * (See file License.txt for complete license)
00009  */
00010 
00011 // util.cpp*
00012 #include "pbrt.h"
00013 #include "timer.h"
00014 #include <map>
00015 using std::map;
00016 // Error Reporting Includes
00017 #include <stdarg.h>
00018 // Error Reporting Definitions
00019 #define PBRT_ERROR_IGNORE 0
00020 #define PBRT_ERROR_CONTINUE 1
00021 #define PBRT_ERROR_ABORT 2
00022 // Error Reporting Functions
00023 static void processError(const char *format, va_list args,
00024                 const char *message, int disposition) {
00025 #ifndef WIN32
00026         char *errorBuf;
00027         vasprintf(&errorBuf, format, args);
00028 #else
00029         char errorBuf[2048];
00030         _vsnprintf(errorBuf, sizeof(errorBuf), format, args);
00031 #endif
00032         // Report error
00033         switch (disposition) {
00034         case PBRT_ERROR_IGNORE:
00035                 return;
00036         case PBRT_ERROR_CONTINUE:
00037                 fprintf(stderr, "%s: %s\n", message, errorBuf);
00038                 // Print scene file and line number, if appropriate
00039                 extern int line_num;
00040                 if (line_num != 0) {
00041                         extern string current_file;
00042                         fprintf(stderr, "\tLine %d, file %s\n", line_num,
00043                                 current_file.c_str());
00044                 }
00045                 break;
00046         case PBRT_ERROR_ABORT:
00047                 fprintf(stderr, "%s: %s\n", message, errorBuf);
00048                 // Print scene file and line number, if appropriate
00049                 extern int line_num;
00050                 if (line_num != 0) {
00051                         extern string current_file;
00052                         fprintf(stderr, "\tLine %d, file %s\n", line_num,
00053                                 current_file.c_str());
00054                 }
00055                 exit(1);
00056         }
00057 #ifndef WIN32
00058         free(errorBuf);
00059 #endif
00060 }
00061 COREDLL void Info(const char *format, ...) {
00062         va_list args;
00063         va_start(args, format);
00064         processError(format, args, "Notice", PBRT_ERROR_CONTINUE);
00065         va_end(args);
00066 }
00067 COREDLL void Warning(const char *format, ...) {
00068         va_list args;
00069         va_start(args, format);
00070         processError(format, args, "Warning", PBRT_ERROR_CONTINUE);
00071         va_end(args);
00072 }
00073 COREDLL void Error(const char *format, ...) {
00074         va_list args;
00075         va_start(args, format);
00076         processError(format, args, "Error", PBRT_ERROR_CONTINUE);
00077         va_end(args);
00078 }
00079 COREDLL void Severe(const char *format, ...) {
00080         va_list args;
00081         va_start(args, format);
00082         processError(format, args, "Fatal Error", PBRT_ERROR_ABORT);
00083         va_end(args);
00084 }
00085 // Matrix Method Definitions
00086 COREDLL bool SolveLinearSystem2x2(const float A[2][2],
00087                 const float B[2], float x[2]) {
00088         float det = A[0][0]*A[1][1] - A[0][1]*A[1][0];
00089         if (fabsf(det) < 1e-5)
00090                 return false;
00091         float invDet = 1.0f/det;
00092         x[0] = (A[1][1]*B[0] - A[0][1]*B[1]) * invDet;
00093         x[1] = (A[0][0]*B[1] - A[1][0]*B[0]) * invDet;
00094         return true;
00095 }
00096 Matrix4x4::Matrix4x4(float mat[4][4]) {
00097         memcpy(m, mat, 16*sizeof(float));
00098 }
00099 Matrix4x4::Matrix4x4(float t00, float t01, float t02, float t03,
00100                      float t10, float t11, float t12, float t13,
00101                      float t20, float t21, float t22, float t23,
00102                      float t30, float t31, float t32, float t33) {
00103         m[0][0] = t00; m[0][1] = t01; m[0][2] = t02; m[0][3] = t03;
00104         m[1][0] = t10; m[1][1] = t11; m[1][2] = t12; m[1][3] = t13;
00105         m[2][0] = t20; m[2][1] = t21; m[2][2] = t22; m[2][3] = t23;
00106         m[3][0] = t30; m[3][1] = t31; m[3][2] = t32; m[3][3] = t33;
00107 }
00108 Reference<Matrix4x4> Matrix4x4::Transpose() const {
00109    return new Matrix4x4(m[0][0], m[1][0], m[2][0], m[3][0],
00110                             m[0][1], m[1][1], m[2][1], m[3][1],
00111                             m[0][2], m[1][2], m[2][2], m[3][2],
00112                             m[0][3], m[1][3], m[2][3], m[3][3]);
00113 }
00114 Reference<Matrix4x4> Matrix4x4::Inverse() const {
00115         int indxc[4], indxr[4];
00116         int ipiv[4] = { 0, 0, 0, 0 };
00117         float minv[4][4];
00118         memcpy(minv, m, 4*4*sizeof(float));
00119         for (int i = 0; i < 4; i++) {
00120                 int irow = -1, icol = -1;
00121                 float big = 0.;
00122                 // Choose pivot
00123                 for (int j = 0; j < 4; j++) {
00124                         if (ipiv[j] != 1) {
00125                                 for (int k = 0; k < 4; k++) {
00126                                         if (ipiv[k] == 0) {
00127                                                 if (fabsf(minv[j][k]) >= big) {
00128                                                         big = float(fabsf(minv[j][k]));
00129                                                         irow = j;
00130                                                         icol = k;
00131                                                 }
00132                                         }
00133                                         else if (ipiv[k] > 1)
00134                                                 Error("Singular matrix in MatrixInvert");
00135                                 }
00136                         }
00137                 }
00138                 ++ipiv[icol];
00139                 // Swap rows _irow_ and _icol_ for pivot
00140                 if (irow != icol) {
00141                         for (int k = 0; k < 4; ++k)
00142                                 swap(minv[irow][k], minv[icol][k]);
00143                 }
00144                 indxr[i] = irow;
00145                 indxc[i] = icol;
00146                 if (minv[icol][icol] == 0.)
00147                         Error("Singular matrix in MatrixInvert");
00148                 // Set $m[icol][icol]$ to one by scaling row _icol_ appropriately
00149                 float pivinv = 1.f / minv[icol][icol];
00150                 minv[icol][icol] = 1.f;
00151                 for (int j = 0; j < 4; j++)
00152                         minv[icol][j] *= pivinv;
00153                 // Subtract this row from others to zero out their columns
00154                 for (int j = 0; j < 4; j++) {
00155                         if (j != icol) {
00156                                 float save = minv[j][icol];
00157                                 minv[j][icol] = 0;
00158                                 for (int k = 0; k < 4; k++)
00159                                         minv[j][k] -= minv[icol][k]*save;
00160                         }
00161                 }
00162         }
00163         // Swap columns to reflect permutation
00164         for (int j = 3; j >= 0; j--) {
00165                 if (indxr[j] != indxc[j]) {
00166                         for (int k = 0; k < 4; k++)
00167                                 swap(minv[k][indxr[j]], minv[k][indxc[j]]);
00168                 }
00169         }
00170         return new Matrix4x4(minv);
00171 }
00172 // Statistics Definitions
00173 struct COREDLL StatTracker {
00174         StatTracker(const string &cat, const string &n,
00175                     StatsCounterType *pa, StatsCounterType *pb = NULL,
00176                     bool percentage = true);
00177         string category, name;
00178         StatsCounterType *ptra, *ptrb;
00179         bool percentage;
00180 };
00181 typedef map<std::pair<string, string>, StatTracker *> TrackerMap;
00182 static TrackerMap trackers;
00183 static void addTracker(StatTracker *newTracker) {
00184         std::pair<string, string> s = std::make_pair(newTracker->category, newTracker->name);
00185         if (trackers.find(s) != trackers.end()) {
00186                 newTracker->ptra = trackers[s]->ptra;
00187                 newTracker->ptrb = trackers[s]->ptrb;
00188                 return;
00189         }
00190         trackers[s] = newTracker;
00191 }
00192 static void StatsPrintVal(FILE *f, StatsCounterType v);
00193 static void StatsPrintVal(FILE *f, StatsCounterType v1, StatsCounterType v2);
00194 // Statistics Functions
00195 StatTracker::StatTracker(const string &cat, const string &n,
00196                          StatsCounterType *pa, StatsCounterType *pb, bool p) {
00197         category = cat;
00198         name = n;
00199         ptra = pa;
00200         ptrb = pb;
00201         percentage = p;
00202 }
00203 StatsCounter::StatsCounter(const string &category, const string &name) {
00204         num = 0;
00205         addTracker(new StatTracker(category, name, &num));
00206 }
00207 StatsRatio::StatsRatio(const string &category, const string &name) {
00208         na = nb = 0;
00209         addTracker(new StatTracker(category, name, &na, &nb, false));
00210 }
00211 StatsPercentage::StatsPercentage(const string &category, const string &name) {
00212         na = nb = 0;
00213         addTracker(new StatTracker(category, name, &na, &nb, true));
00214 }
00215 void StatsPrint(FILE *dest) {
00216         fprintf(dest, "Statistics:\n");
00217         TrackerMap::iterator iter = trackers.begin();
00218         string lastCategory;
00219         while (iter != trackers.end()) {
00220                 // Print statistic
00221                 StatTracker *tr = iter->second;
00222                 if (tr->category != lastCategory) {
00223                         fprintf(dest, "%s\n", tr->category.c_str());
00224                         lastCategory = tr->category;
00225                 }
00226                 fprintf(dest, "    %s", tr->name.c_str());
00227                 // Pad out to results column
00228                 int resultsColumn = 56;
00229                 int paddingSpaces = resultsColumn - (int) tr->name.size();
00230                 while (paddingSpaces-- > 0)
00231                         putc(' ', dest);
00232                 if (tr->ptrb == NULL)
00233                         StatsPrintVal(dest, *tr->ptra);
00234                 else {
00235                         if (*tr->ptrb > 0) {
00236                                 float ratio = (float)*tr->ptra / (float)*tr->ptrb;
00237                                 StatsPrintVal(dest, *tr->ptra, *tr->ptrb);
00238                                 if (tr->percentage)
00239                                         fprintf(dest, " (%3.2f%%)", 100. * ratio);
00240                                 else
00241                                         fprintf(dest, " (%.2fx)", ratio);
00242                         }
00243                         else
00244                                 StatsPrintVal(dest, *tr->ptra, *tr->ptrb);
00245                 }
00246                 fprintf(dest, "\n");
00247                 ++iter;
00248         }
00249 }
00250 static void StatsPrintVal(FILE *f, StatsCounterType v) {
00251         if (v > 1e9) fprintf(f, "%.3fB", v / 1e9f);
00252         else if (v > 1e6) fprintf(f, "%.3fM", v / 1e6f);
00253         else if (v > 1e4) fprintf(f, "%.1fk", v / 1e3f);
00254         else fprintf(f, "%.0f", (float)v);
00255 }
00256 static void StatsPrintVal(FILE *f, StatsCounterType v1,
00257                 StatsCounterType v2) {
00258         StatsCounterType m = min(v1, v2);
00259         if (m > 1e9) fprintf(f, "%.3fB:%.3fB", v1 / 1e9f, v2 / 1e9f);
00260         else if (m > 1e6) fprintf(f, "%.3fM:%.3fM", v1 / 1e6f, v2 / 1e6f);
00261         else if (m > 1e4) fprintf(f, "%.1fk:%.1fk", v1 / 1e3f, v2 / 1e3f);
00262         else fprintf(f, "%.0f:%.0f", v1, v2);
00263 }
00264 void StatsCleanup() {
00265         TrackerMap::iterator iter = trackers.begin();
00266         string lastCategory;
00267         while (iter != trackers.end()) {
00268                 delete iter->second;
00269                 ++iter;
00270         }
00271         trackers.erase(trackers.begin(), trackers.end());
00272 }
00273 // Random Number State
00274 /*
00275    Copyright (C) 1997 - 2002, Makoto Matsumoto and Takuji Nishimura,
00276    All rights reserved.
00277 
00278    Redistribution and use in source and binary forms, with or without
00279    modification, are permitted provided that the following conditions
00280    are met:
00281 
00282      1. Redistributions of source code must retain the above copyright
00283         notice, this list of conditions and the following disclaimer.
00284 
00285      2. Redistributions in binary form must reproduce the above copyright
00286         notice, this list of conditions and the following disclaimer in the
00287         documentation and/or other materials provided with the distribution.
00288 
00289      3. The names of its contributors may not be used to endorse or promote
00290         products derived from this software without specific prior written
00291         permission.
00292 
00293    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00294    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00295    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
00296    A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
00297    CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
00298    EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
00299    PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
00300    PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
00301    LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
00302    NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00303    SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00304 */
00305 #define N 624
00306 #define M 397
00307 #define MATRIX_A 0x9908b0dfUL   /* constant vector a */
00308 #define UPPER_MASK 0x80000000UL /* most significant w-r bits */
00309 #define LOWER_MASK 0x7fffffffUL /* least significant r bits */
00310 
00311 static unsigned long mt[N]; /* the array for the state vector  */
00312 static int mti=N+1; /* mti==N+1 means mt[N] is not initialized */
00313 // Random Number Functions
00314 static void init_genrand(u_long seed) {
00315         mt[0]= seed & 0xffffffffUL;
00316         for (mti=1; mti<N; mti++) {
00317                 mt[mti] =
00318                 (1812433253UL * (mt[mti-1] ^ (mt[mti-1] >> 30)) + mti);
00319                 /* See Knuth TAOCP Vol2. 3rd Ed. P.106 for multiplier. */
00320                 /* In the previous versions, MSBs of the seed affect   */
00321                 /* only MSBs of the array mt[].                        */
00322                 /* 2002/01/09 modified by Makoto Matsumoto             */
00323                 mt[mti] &= 0xffffffffUL;
00324                 /* for >32 bit machines */
00325         }
00326 }
00327 COREDLL unsigned long genrand_int32(void)
00328 {
00329         unsigned long y;
00330         static unsigned long mag01[2]={0x0UL, MATRIX_A};
00331         /* mag01[x] = x * MATRIX_A  for x=0,1 */
00332 
00333         if (mti >= N) { /* generate N words at one time */
00334                 int kk;
00335 
00336                 if (mti == N+1)   /* if init_genrand() has not been called, */
00337                         init_genrand(5489UL); /* default initial seed */
00338 
00339                 for (kk=0;kk<N-M;kk++) {
00340                         y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
00341                         mt[kk] = mt[kk+M] ^ (y >> 1) ^ mag01[y & 0x1UL];
00342                 }
00343                 for (;kk<N-1;kk++) {
00344                         y = (mt[kk]&UPPER_MASK)|(mt[kk+1]&LOWER_MASK);
00345                         mt[kk] = mt[kk+(M-N)] ^ (y >> 1) ^ mag01[y & 0x1UL];
00346                 }
00347                 y = (mt[N-1]&UPPER_MASK)|(mt[0]&LOWER_MASK);
00348                 mt[N-1] = mt[M-1] ^ (y >> 1) ^ mag01[y & 0x1UL];
00349 
00350                 mti = 0;
00351         }
00352 
00353         y = mt[mti++];
00354 
00355         /* Tempering */
00356         y ^= (y >> 11);
00357         y ^= (y << 7) & 0x9d2c5680UL;
00358         y ^= (y << 15) & 0xefc60000UL;
00359         y ^= (y >> 18);
00360 
00361         return y;
00362 }
00363 /* generates a random number on [0,1]-real-interval */
00364 COREDLL float genrand_real1(void)
00365 {
00366         return genrand_int32()*((float)1.0/(float)4294967295.0);
00367         /* divided by 2^32-1 */
00368 }
00369 /* generates a random number on [0,1)-real-interval */
00370 COREDLL float genrand_real2(void)
00371 {
00372         return genrand_int32()*((float)1.0/(float)4294967296.0);
00373         /* divided by 2^32 */
00374 }
00375 // Memory Allocation Functions
00376 COREDLL void *AllocAligned(size_t size) {
00377 #ifndef L1_CACHE_LINE_SIZE
00378 #define L1_CACHE_LINE_SIZE 64
00379 #endif
00380         return memalign(L1_CACHE_LINE_SIZE, size);
00381 }
00382 COREDLL void FreeAligned(void *ptr) {
00383 #ifdef WIN32 // NOBOOK
00384         _aligned_free(ptr);
00385 #else // NOBOOK
00386         free(ptr);
00387 #endif // NOBOOK
00388 }
00389 // ProgressReporter Method Definitions
00390 ProgressReporter::ProgressReporter(int totalWork, const string &title, int bar_length)
00391         : totalPlusses(bar_length - title.size()) {
00392         plussesPrinted = 0;
00393         frequency = (float)totalWork / (float)totalPlusses;
00394         count = frequency;
00395         timer = new Timer();
00396         timer->Start();
00397         outFile = stdout;
00398         // Initialize progress string
00399         const int bufLen = title.size() + totalPlusses + 64;
00400         buf = new char[bufLen];
00401         snprintf(buf, bufLen, "\r%s: [", title.c_str());
00402         curSpace = buf + strlen(buf);
00403         char *s = curSpace;
00404         for (int i = 0; i < totalPlusses; ++i)
00405                 *s++ = ' ';
00406         *s++ = ']';
00407         *s++ = ' ';
00408         *s++ = '\0';
00409         fprintf(outFile, buf);
00410         fflush(outFile);
00411 }
00412 ProgressReporter::~ProgressReporter() { delete[] buf; delete timer; }
00413 void ProgressReporter::Update(int num) const {
00414         count -= num;
00415         bool updatedAny = false;
00416         while (count <= 0) {
00417                 count += frequency;
00418                 if (plussesPrinted++ < totalPlusses)
00419                         *curSpace++ = '+';
00420                 updatedAny = true;
00421         }
00422         if (updatedAny) {
00423                 fputs(buf, outFile);
00424                 // Update elapsed time and estimated time to completion
00425                 float percentDone = (float)plussesPrinted / (float)totalPlusses;
00426                 float seconds = (float) timer->Time();
00427                 float estRemaining = seconds / percentDone - seconds;
00428                 if (percentDone == 1.f)
00429                         fprintf(outFile, " (%.1fs)       ", seconds);
00430                 else
00431                         fprintf(outFile, " (%.1fs|%.1fs)  ", seconds, max(0.f, estRemaining));
00432                 fflush(outFile);
00433         }
00434 }
00435 void ProgressReporter::Done() const {
00436         while (plussesPrinted++ < totalPlusses)
00437                 *curSpace++ = '+';
00438         fputs(buf, outFile);
00439         float seconds = (float) timer->Time();
00440         fprintf(outFile, " (%.1fs)       \n", seconds);
00441         fflush(outFile);
00442 }

Generated on Wed Sep 26 14:01:22 2007 for pbrt by  doxygen 1.5.1