├── .gitignore ├── .gitmodules ├── canonical ├── CMakeLists.txt ├── array3D.h ├── base_includes.h ├── canonical_test.cpp ├── canonical_test.h ├── common.h ├── estimators │ ├── bidirectional.cpp │ ├── bidirectional.h │ ├── estimator.cpp │ ├── estimator.h │ ├── expected.cpp │ ├── expected.h │ ├── next_flight_ratio.cpp │ ├── next_flight_ratio.h │ ├── pseries_cdf.cpp │ ├── pseries_cdf.h │ ├── pseries_cumulative.cpp │ ├── pseries_cumulative.h │ ├── pseries_next_flight_ratio.cpp │ ├── pseries_next_flight_ratio.h │ ├── pseries_ratio.cpp │ ├── pseries_ratio.h │ ├── ratio_tracking.cpp │ ├── ratio_tracking.h │ ├── track_length.cpp │ ├── track_length.h │ ├── unidirectional.cpp │ └── unidirectional.h ├── exceptions.h ├── ext │ ├── mpfr_pp │ │ ├── .gitignore │ │ ├── CMakeLists.txt │ │ ├── README.md │ │ ├── real.h │ │ └── test.cpp │ ├── pcg32 │ │ ├── Makefile │ │ ├── README.md │ │ ├── pcg32-demo.cpp │ │ ├── pcg32-demo.out │ │ ├── pcg32.h │ │ └── pcg32_8.h │ └── stb │ │ ├── stb_image.h │ │ └── stb_image_write.h ├── extinctions │ ├── constFunc.cpp │ ├── constFunc.h │ ├── cosFunc.cpp │ ├── cosFunc.h │ ├── extinctionFunc.cpp │ ├── extinctionFunc.h │ ├── func.h │ ├── gaussFunc.cpp │ ├── gaussFunc.h │ ├── holeFunc.cpp │ ├── holeFunc.h │ ├── lin_dec.cpp │ ├── lin_dec.h │ ├── lin_inc.cpp │ ├── lin_inc.h │ ├── nullRatioFunc.cpp │ ├── nullRatioFunc.h │ ├── scosFunc.cpp │ ├── scosFunc.h │ ├── tightConstFunc.cpp │ └── tightConstFunc.h ├── floatimage.cpp ├── floatimage.h ├── main.cpp ├── samplers │ ├── halton.cpp │ ├── halton.h │ ├── halton_sampler.h │ ├── hammersley.cpp │ ├── hammersley.h │ ├── independent.cpp │ ├── independent.h │ ├── latinip.cpp │ ├── latinip.h │ ├── permute.cpp │ ├── permute.h │ ├── sampler.cpp │ └── sampler.h ├── util.cpp └── util.h └── readme.md /.gitignore: -------------------------------------------------------------------------------- 1 | canonical/build/ 2 | .DS_Store 3 | *.DS_Store 4 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "pbrt-v3"] 2 | path = pbrt-v3 3 | url = https://github.com/ZackMisso/pbrt-v3.git 4 | -------------------------------------------------------------------------------- /canonical/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8.3) 2 | project(transm_est) 3 | 4 | if(APPLE) 5 | set(CMAKE_MACOSX_RPATH ON) 6 | endif() 7 | 8 | include(CheckCXXCompilerFlag) 9 | include(CheckCXXSourceRuns) 10 | 11 | if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") 12 | # Quench annoying deprecation warnings when compiling GLFW on OSX 13 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations") 14 | endif() 15 | 16 | if (CMAKE_CXX_COMPILER_ID MATCHES "^(GNU|Clang|Intel)$") 17 | CHECK_CXX_COMPILER_FLAG("-std=c++14" HAS_CPP14_FLAG) 18 | CHECK_CXX_COMPILER_FLAG("-std=c++11" HAS_CPP11_FLAG) 19 | 20 | if (HAS_CPP14_FLAG) 21 | #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") 22 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++14") 23 | elseif (HAS_CPP11_FLAG) 24 | #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 25 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11") 26 | else() 27 | message(FATAL_ERROR "Unsupported compiler -- pybind11 requires C++11 support!") 28 | endif() 29 | endif() 30 | 31 | IF(APPLE) 32 | # Fix linking on 10.14+. See https://stackoverflow.com/questions/54068035 33 | LINK_DIRECTORIES(/usr/local/lib) 34 | ENDIF() 35 | 36 | if (APPLE) 37 | find_library(cocoa_library Cocoa) 38 | find_library(opengl_library OpenGL) 39 | find_library(corevideo_library CoreVideo) 40 | find_library(iokit_library IOKit) 41 | list(APPEND NANOGUI_EXTRA_LIBS ${cocoa_library} ${opengl_library} ${corevideo_library} ${iokit_library}) 42 | list(APPEND LIBNANOGUI_EXTRA_SOURCE src/darwin.mm) 43 | endif() 44 | 45 | set(PCG32_INCLUDE_DIR 46 | ${CMAKE_CURRENT_SOURCE_DIR}/ext/pcg32) 47 | 48 | set(MPFR_INCLUDE_DIR 49 | ${CMAKE_CURRENT_SOURCE_DIR}/ext/mpfr_pp/) 50 | 51 | # On top of adding the path to nanogui/include, you may need extras 52 | include_directories( 53 | # Include directory 54 | ${CMAKE_CURRENT_SOURCE_DIR}/../include/ 55 | # Random number generator 56 | ${PCG32_INCLUDE_DIR}/ 57 | # MPFR library 58 | ${MPFR_INCLUDE_DIR} 59 | ${MPFR_INCLUDES} 60 | ../ext 61 | ) 62 | 63 | add_executable(transm_est 64 | estimators/bidirectional.h 65 | estimators/bidirectional.cpp 66 | estimators/estimator.h 67 | estimators/estimator.cpp 68 | estimators/expected.h 69 | estimators/expected.cpp 70 | estimators/next_flight_ratio.h 71 | estimators/next_flight_ratio.cpp 72 | estimators/pseries_cdf.h 73 | estimators/pseries_cdf.cpp 74 | estimators/pseries_cumulative.h 75 | estimators/pseries_cumulative.cpp 76 | estimators/pseries_next_flight_ratio.h 77 | estimators/pseries_next_flight_ratio.cpp 78 | estimators/pseries_ratio.h 79 | estimators/pseries_ratio.cpp 80 | estimators/ratio_tracking.h 81 | estimators/ratio_tracking.cpp 82 | estimators/track_length.h 83 | estimators/track_length.cpp 84 | estimators/unidirectional.h 85 | estimators/unidirectional.cpp 86 | 87 | extinctions/constFunc.h 88 | extinctions/constFunc.cpp 89 | extinctions/cosFunc.h 90 | extinctions/cosFunc.cpp 91 | extinctions/extinctionFunc.h 92 | extinctions/extinctionFunc.cpp 93 | extinctions/func.h 94 | extinctions/gaussFunc.h 95 | extinctions/gaussFunc.cpp 96 | extinctions/holeFunc.h 97 | extinctions/holeFunc.cpp 98 | extinctions/lin_dec.h 99 | extinctions/lin_dec.cpp 100 | extinctions/lin_inc.h 101 | extinctions/lin_inc.cpp 102 | extinctions/nullRatioFunc.h 103 | extinctions/nullRatioFunc.cpp 104 | extinctions/scosFunc.h 105 | extinctions/scosFunc.cpp 106 | extinctions/tightConstFunc.h 107 | extinctions/tightConstFunc.cpp 108 | 109 | samplers/halton_sampler.h 110 | samplers/halton.h 111 | samplers/halton.cpp 112 | samplers/hammersley.h 113 | samplers/hammersley.cpp 114 | samplers/independent.h 115 | samplers/independent.cpp 116 | samplers/latinip.h 117 | samplers/latinip.cpp 118 | samplers/permute.h 119 | samplers/permute.cpp 120 | samplers/sampler.h 121 | samplers/sampler.cpp 122 | 123 | array3D.h 124 | base_includes.h 125 | canonical_test.h 126 | canonical_test.cpp 127 | common.h 128 | exceptions.h 129 | floatimage.h 130 | floatimage.cpp 131 | main.cpp 132 | util.h 133 | util.cpp 134 | ) 135 | 136 | set(CompilerFlags 137 | CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE 138 | CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO CMAKE_C_FLAGS 139 | CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_MINSIZEREL 140 | CMAKE_C_FLAGS_RELWITHDEBINFO COMPILE_DEFINITIONS U_CMAKE_BUILD_TYPE 141 | CMAKE_MACOSX_RPATH 142 | PCG32_INCLUDE_DIR 143 | ) 144 | 145 | target_link_libraries(transm_est) 146 | -------------------------------------------------------------------------------- /canonical/array3D.h: -------------------------------------------------------------------------------- 1 | /*! 2 | \file array3D.h 3 | \brief Contains the definition of a resizable 3D array. 4 | \author Wojciech Jarosz 5 | 6 | CS 89/189 Computational Aspects of Digital Photography C++ basecode. 7 | */ 8 | 9 | // TODO :: Remove this dependance 10 | 11 | #ifndef __ARRAY3D_H 12 | #define __ARRAY3D_H 13 | 14 | #include 15 | #include "exceptions.h" 16 | #include 17 | 18 | // TODO REWRITE THIS FOR OWN USE 19 | 20 | // using namespace std 21 | 22 | //! Generic, resizable, 3D array class. 23 | template 24 | class Array3D 25 | { 26 | public: 27 | //@{ \name Constructors and destructors 28 | Array3D(); 29 | Array3D(int sizeX, int sizeY, int sizeZ); 30 | //@} 31 | 32 | //@{ \name Element access 33 | T & operator()(int x, int y, int z = 0); 34 | const T & operator()(int x, int y, int z = 0) const; 35 | T & operator()(int i); 36 | const T & operator()(int i) const; 37 | T& get(int x, int y, int z); 38 | //@} 39 | 40 | //@{ \name Dimension sizes 41 | int width() const { return m_sizeX; } 42 | int height() const { return m_sizeY; } 43 | int depth() const { return m_sizeZ; } 44 | 45 | int size() const { return m_sizeX*m_sizeY*m_sizeZ; } 46 | int sizeX() const { return m_sizeX; } 47 | int sizeY() const { return m_sizeY; } 48 | int sizeZ() const { return m_sizeZ; } 49 | //@} 50 | 51 | void resize(int sizeX, int sizeY, int sizeZ, const T & value = T(0)); 52 | void reset(const T& value = T(0)); 53 | void operator=(const T&); 54 | 55 | protected: 56 | std::vector m_data; 57 | int m_sizeX, m_sizeY, m_sizeZ; 58 | int m_strideZ; 59 | 60 | private: 61 | Array3D(const Array3D &); // Copying and assignment 62 | Array3D & operator=(const Array3D &); // are not implemented 63 | }; 64 | 65 | 66 | template 67 | inline 68 | Array3D::Array3D(): 69 | m_data(), m_sizeX(0), m_sizeY(0), m_sizeZ(0), m_strideZ(0) 70 | { 71 | // empty 72 | } 73 | 74 | 75 | template 76 | inline 77 | Array3D::Array3D(int sizeX, int sizeY, int sizeZ) : 78 | m_data(sizeX * sizeY * sizeZ), 79 | m_sizeX(sizeX), m_sizeY(sizeY), m_sizeZ(sizeZ), 80 | m_strideZ(sizeX*sizeY) 81 | { 82 | // empty 83 | } 84 | 85 | 86 | // ********************************************************// 87 | // IMPLEMENT THESE FUNCTIONS // 88 | // ********************************************************// 89 | 90 | template 91 | inline T & 92 | Array3D::operator()(int i) 93 | { 94 | return m_data[i]; 95 | } 96 | 97 | 98 | template 99 | inline T & 100 | Array3D::operator()(int x, int y, int z) 101 | { 102 | int index = z * width() * height() + y * width() + x; 103 | 104 | return m_data[index]; 105 | } 106 | 107 | 108 | // The next two functions should have the same implementation as the previous two 109 | template 110 | inline const T & 111 | Array3D::operator()(int i) const 112 | { 113 | return m_data[i]; 114 | } 115 | 116 | 117 | template 118 | inline const T & 119 | Array3D::operator()(int x, int y, int z) const 120 | { 121 | int index = z * width() * height() + y * width() + x; 122 | 123 | return m_data[index]; 124 | } 125 | 126 | 127 | // ********************************************************// 128 | // DON'T EDIT BELOW THIS LINE // 129 | // ********************************************************// 130 | 131 | 132 | template 133 | inline void 134 | Array3D::resize(int sizeX, int sizeY, int sizeZ, const T & value) 135 | { 136 | if (sizeX == m_sizeX && sizeY == m_sizeY && sizeZ == m_sizeZ) 137 | return; 138 | 139 | m_data.resize(sizeX * sizeY * sizeZ, value); 140 | m_sizeX = sizeX; 141 | m_sizeY = sizeY; 142 | m_sizeZ = sizeZ; 143 | m_strideZ = m_sizeX*m_sizeY; 144 | } 145 | 146 | 147 | template 148 | inline void 149 | Array3D::reset(const T& value) 150 | { 151 | int sz = size(); 152 | for (int i = 0; i < sz; i++) 153 | m_data[i] = value; 154 | } 155 | 156 | 157 | template 158 | inline void 159 | Array3D::operator=(const T& value) 160 | { 161 | reset(value); 162 | } 163 | 164 | #endif // __ARRAY3D_H 165 | -------------------------------------------------------------------------------- /canonical/base_includes.h: -------------------------------------------------------------------------------- 1 | #include "estimators/bidirectional.h" 2 | #include "estimators/expected.h" 3 | #include "estimators/next_flight_ratio.h" 4 | #include "estimators/pseries_cdf.h" 5 | #include "estimators/pseries_cumulative.h" 6 | #include "estimators/pseries_next_flight_ratio.h" 7 | #include "estimators/pseries_ratio.h" 8 | #include "estimators/ratio_tracking.h" 9 | #include "estimators/track_length.h" 10 | #include "estimators/unidirectional.h" 11 | 12 | #include "extinctions/constFunc.h" 13 | #include "extinctions/cosFunc.h" 14 | #include "extinctions/gaussFunc.h" 15 | #include "extinctions/holeFunc.h" 16 | #include "extinctions/lin_dec.h" 17 | #include "extinctions/lin_inc.h" 18 | #include "extinctions/nullRatioFunc.h" 19 | #include "extinctions/scosFunc.h" 20 | #include "extinctions/tightConstFunc.h" 21 | 22 | #include "samplers/halton.h" 23 | #include "samplers/hammersley.h" 24 | #include "samplers/independent.h" 25 | #include "samplers/latinip.h" 26 | -------------------------------------------------------------------------------- /canonical/canonical_test.cpp: -------------------------------------------------------------------------------- 1 | #include "canonical_test.h" 2 | #include "floatimage.h" 3 | #include "util.h" 4 | 5 | unsigned int simple_hash(unsigned int x) 6 | { 7 | x = ((x >> 16) ^ x) * 0x45d9f3b; 8 | x = ((x >> 16) ^ x) * 0x45d9f3b; 9 | x = (x >> 16) ^ x; 10 | return x; 11 | } 12 | 13 | CanonicalTest::CanonicalTest(std::string prefix, 14 | Estimator* estimator, 15 | Extinction* extinction, 16 | Sampler* sampler, 17 | long base_seed, 18 | bool equal_cost, 19 | uint32_t max_cost, 20 | uint32_t samples, 21 | uint32_t trials, 22 | uint32_t resolution) 23 | { 24 | FullResults results = FullResults(); 25 | 26 | Float maxTrans = 1.0; 27 | Float ninTrans = 0.0; 28 | Float baseTrans = 0.0; 29 | 30 | ninTrans = 0.98 * maxTrans; 31 | baseTrans = 0.01 * maxTrans; 32 | 33 | results.resize(resolution * resolution); 34 | 35 | for (int i = 0; i < resolution; ++i) 36 | { 37 | // debug status 38 | // if (i % 100 == 0) 39 | // { 40 | cout << extinction->getName() << " " << estimator->getName() << " i: " << i << endl; 41 | // } 42 | 43 | for (int j = 0; j < resolution; ++j) 44 | { 45 | Extinction* ext = extinction; 46 | 47 | Float minMajorantEfficiency = ext->calculateMinMajorantEfficiency(); 48 | Float maxMajorantEfficiency = ext->calculateMaxMajorantEfficiency(); 49 | 50 | ext->setA(0.0); 51 | ext->setB(1.0); 52 | 53 | Func* majFunc = ext->getMajorantFunction(); 54 | Func* extFunc = ext->getExtinctionFunction(); 55 | 56 | Float desiredTransmittance = maxTrans - (baseTrans + ninTrans * Float(j) / Float(resolution - 1)); 57 | Float sigmaT = -Util::LOG(desiredTransmittance); 58 | 59 | Float efficiency = (minMajorantEfficiency + (maxMajorantEfficiency - minMajorantEfficiency) * Float(resolution - i - 1) / Float(resolution - 1)); 60 | 61 | extFunc->solveForIntegral(0.0, 1.0, sigmaT); 62 | 63 | // majorant function should always be set to null-ratio 64 | ((NullRatioFunc*)majFunc)->setRatio(efficiency); 65 | 66 | ext->preProcess(); 67 | 68 | runEstimator(extinction, 69 | estimator, 70 | sampler, 71 | samples, 72 | trials, 73 | results[i * resolution + j], 74 | i * resolution + j, 75 | resolution, 76 | base_seed + i * resolution + j, 77 | equal_cost, 78 | max_cost); 79 | } 80 | } 81 | 82 | FloatImage trans = FloatImage(resolution, resolution, 3); 83 | FloatImage var = FloatImage(resolution, resolution, 3); 84 | FloatImage cost = FloatImage(resolution, resolution, 3); 85 | FloatImage eff = FloatImage(resolution, resolution, 3); 86 | 87 | // write out the results to images 88 | for (int k = 0; k < 3; ++k) 89 | { 90 | for (int i = 0; i < resolution; ++i) 91 | { 92 | for (int j = 0; j < resolution; ++j) 93 | { 94 | trans(j, i, k) = (results[j + resolution * i].transmittance); 95 | cost(j, i, k) = (results[j + resolution * i].cost); 96 | var(j, i, k) = (results[j + resolution * i].variance); 97 | eff(j, i, k) = (results[j + resolution * i].variance * results[j + resolution * i].cost); 98 | } 99 | } 100 | } 101 | 102 | string path = prefix + "/" + estimator->getName(); 103 | 104 | string extension = ".png"; 105 | string extension2 = ".hdr"; 106 | 107 | trans.write(path + "_mean" + extension); 108 | var.write(path + "_var" + extension); 109 | cost.write(path + "_cost" + extension); 110 | eff.write(path + "_eff" + extension); 111 | 112 | trans.write(path + "_mean" + extension2); 113 | var.write(path + "_var" + extension2); 114 | cost.write(path + "_cost" + extension2); 115 | eff.write(path + "_eff" + extension2); 116 | } 117 | 118 | void CanonicalTest::runEstimator(Extinction* ext, 119 | Estimator* est, 120 | Sampler* sampler, 121 | uint32_t samples, 122 | uint32_t trials, 123 | EstimatorTestResult& testResult, 124 | uint32_t location, 125 | uint32_t resolution, 126 | long base_seed, 127 | bool equal_cost, 128 | uint32_t max_cost) 129 | { 130 | Float expected = ext->calculateExtinctionIntegral(0.0, 1.0); 131 | 132 | Float mean = 0.0; 133 | Float var = 0.0; 134 | Float cost = 0.0; 135 | 136 | if (!equal_cost) 137 | { 138 | for (int i = 0; i < trials; ++i) 139 | { 140 | Float trans = 0.0; 141 | Float cost_tmp = 0.0; 142 | 143 | Sampler* base_sampler = sampler->copy(); 144 | base_sampler->reseed(simple_hash(base_seed + (i * resolution * resolution * resolution))); 145 | base_sampler->setNumSamples(samples); 146 | 147 | for (int j = 0; j < samples; ++j) 148 | { 149 | TransmittanceQuaryRecord rec(ext, 0.0, 1.0, -1, samples); 150 | trans += est->T(rec, base_sampler); 151 | cost_tmp += Float(rec.extCalls); 152 | 153 | base_sampler->nextSample(); 154 | } 155 | 156 | trans /= Float(samples); 157 | cost_tmp /= Float(samples); 158 | 159 | if (est->getName() == "expected") i = trials; 160 | 161 | Float mean_new = mean + (1.0 / Float(i+1)) * (trans - mean); 162 | var = var + (trans - mean) * (trans - mean_new); 163 | mean = mean_new; 164 | 165 | cost += cost_tmp; 166 | delete base_sampler; 167 | } 168 | } 169 | else 170 | { 171 | // this experiment runs a 1-sample estimator for an arbitrary number 172 | // of trials until a maximum cost is reached for all simulations 173 | 174 | // base_sampler is assumed to always be independent for this case 175 | Sampler* base_sampler = new Independent(); 176 | base_sampler->reseed(simple_hash(base_seed + (1 * resolution * resolution * resolution))); 177 | base_sampler->setNumSamples(1); 178 | trials = 0; 179 | 180 | while (cost < max_cost) 181 | { 182 | // run the estimator 183 | TransmittanceQuaryRecord rec(ext, 0.0, 1.0, -1, samples); 184 | Float trans = est->T(rec, base_sampler); 185 | int cost_tmp = rec.extCalls; 186 | sampler->nextSample(); 187 | 188 | if (est->getName() == "expected") cost_tmp = max_cost; 189 | 190 | cost += cost_tmp; 191 | 192 | trials++; 193 | 194 | Float mean_new = mean + (1.0 / Float(trials)) * (trans - mean); 195 | 196 | var = var + (trans - mean) * (trans - mean_new); 197 | 198 | mean = mean_new; 199 | } 200 | 201 | delete base_sampler; 202 | } 203 | 204 | testResult.trials = trials; 205 | testResult.gtTransmittance = expected; 206 | testResult.transmittance = mean; 207 | testResult.variance = var / Float(trials); 208 | testResult.cost = cost / Float(trials); 209 | } 210 | -------------------------------------------------------------------------------- /canonical/canonical_test.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "base_includes.h" 4 | 5 | class CanonicalTest { 6 | public: 7 | CanonicalTest(std::string prefix, 8 | Estimator* estimator, 9 | Extinction* extinction, 10 | Sampler* sampler, 11 | long base_seed, 12 | bool equal_cost, 13 | uint32_t max_cost, 14 | uint32_t samples, 15 | uint32_t trials, 16 | uint32_t resolution); 17 | 18 | void runEstimator(Extinction* ext, 19 | Estimator* est, 20 | Sampler* sampler, 21 | uint32_t samples, 22 | uint32_t trials, 23 | EstimatorTestResult& testResult, 24 | uint32_t location, 25 | uint32_t resolution, 26 | long base_seed, 27 | bool equal_cost, 28 | uint32_t max_cost); 29 | }; 30 | -------------------------------------------------------------------------------- /canonical/common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | using std::endl; 8 | using std::cout; 9 | using std::vector; 10 | using std::pair; 11 | 12 | #define M_PI 3.14159265358979323846f 13 | #define EPSILON 1e-8 14 | 15 | // number of raymarching steps taken to estimate integrals 16 | #define RESOLUTION 100000.0 17 | 18 | // #define USE_SINGLE_PRECISION 19 | #define USE_DOUBLE_PRECISION 20 | // TODO: maybe carry over support for this 21 | // #define USE_ARBITRARY_PRECISION 22 | 23 | #ifdef USE_SINGLE_PRECISION 24 | typedef float Float; 25 | #endif 26 | 27 | #ifdef USE_DOUBLE_PRECISION 28 | typedef double Float; 29 | #endif 30 | 31 | using namespace std; 32 | 33 | // pair datastructures 34 | typedef vector > HistData; 35 | typedef pair Pdd; 36 | typedef pair Puu; 37 | 38 | struct EstimatorTestResult 39 | { 40 | uint32_t samples; 41 | uint32_t trials; 42 | Float gtTransmittance; 43 | Float transmittance; 44 | Float variance; 45 | Float cost; 46 | }; 47 | 48 | struct EstimatorStratTestResult 49 | { 50 | uint32_t samples; 51 | uint32_t trials; 52 | Float gtTransmittance; 53 | 54 | Float base_transmittance; 55 | Float base_variance; 56 | Float base_cost; 57 | 58 | Float strat_transmittance; 59 | Float strat_variance; 60 | Float strat_cost; 61 | }; 62 | 63 | typedef vector FullResults; 64 | typedef vector FullStratResults; 65 | -------------------------------------------------------------------------------- /canonical/estimators/bidirectional.cpp: -------------------------------------------------------------------------------- 1 | #include "bidirectional.h" 2 | #include 3 | 4 | Bidirectional::Bidirectional() : Estimator() { } 5 | 6 | Float Bidirectional::T(TransmittanceQuaryRecord& rec, Sampler* sampler) const { 7 | Float Tr = 0.0; 8 | 9 | Float yab = rec.a; 10 | Float yba = rec.b; 11 | 12 | vector a2b = vector(); 13 | vector b2a = vector(); 14 | 15 | do { 16 | Float maja2b = rec.extFunc->calculateMajorant(yab); 17 | Float majb2a = rec.extFunc->calculateMajorant(yba); 18 | 19 | if (yab >= rec.b && yba <= rec.a) { 20 | break; 21 | } 22 | 23 | if (yab < rec.b) { 24 | a2b.push_back(yab); 25 | yab += sampleExpFF(rec, sampler, maja2b); 26 | } else { 27 | // path from a to b must use odd samples only 28 | sampler->next1D(); 29 | } 30 | 31 | if (yba > rec.a) { 32 | b2a.push_back(yba); 33 | yba -= sampleExpFF(rec, sampler, majb2a); 34 | } else { 35 | // path from b to a must use even samples only 36 | sampler->next1D(); 37 | } 38 | } while (true); 39 | 40 | a2b.push_back(rec.b); 41 | b2a.push_back(rec.a); 42 | 43 | Float k = rec.extFunc->calculateMajorant((rec.b - rec.a) / 2.0); 44 | 45 | Float val = exp(-k * (rec.b - rec.a)); 46 | 47 | vector extValsA2B = vector(); 48 | vector extValsB2A = vector(); 49 | 50 | vector expB2A = vector(); 51 | vector expA2B = vector(); 52 | 53 | extValsA2B.push_back(-1.0); 54 | for (int i = 1; i < a2b.size() - 1; ++i) { 55 | Float maj = rec.extFunc->calculateMajorant(a2b[i]); 56 | Float ex = (maj - rec.extFunc->calculateExtinction(a2b[i], rec.extCalls)) / maj; 57 | extValsA2B.push_back(ex); 58 | expA2B.push_back(val / exp(-k * (a2b[i] - a2b[i - 1]))); 59 | } 60 | expA2B.push_back(val / exp(-k * (a2b[a2b.size() - 1] - a2b[a2b.size() - 2]))); 61 | extValsA2B.push_back(-1.0); 62 | 63 | extValsB2A.push_back(-1.0); // b 64 | for (int i = 1; i < b2a.size() - 1; ++i) { 65 | Float maj = rec.extFunc->calculateMajorant(b2a[i]); 66 | Float ex = (maj - rec.extFunc->calculateExtinction(b2a[i], rec.extCalls)) / maj; 67 | extValsB2A.push_back(ex); 68 | expB2A.push_back(val / exp(-k * (b2a[i - 1] - b2a[i]))); 69 | } 70 | expB2A.push_back(val / exp(-k * (b2a[b2a.size() - 2] - b2a[b2a.size() - 1]))); 71 | extValsB2A.push_back(-1.0); // a 72 | 73 | int n = a2b.size() + b2a.size() - 4; 74 | 75 | for (int l = 0; l <= n; ++l) { 76 | for (int i = 0; i <= l; ++i) { 77 | int j = l - i; 78 | 79 | if (a2b.size() - 2 < i) { 80 | i = l+1; 81 | continue; 82 | } 83 | if (b2a.size() - 2 < j) continue; 84 | if (b2a[j] - a2b[i] < 0.0) continue; 85 | 86 | Float nee = exp(-k * (b2a[j] - a2b[i])); 87 | Float pdf = val / nee; 88 | 89 | Float prod = 1.0; 90 | Float pdfPath = 0.0; 91 | Float pdfLight = 0.0; 92 | 93 | for (int q = 1; q <= i; ++q) { 94 | prod *= extValsA2B[q]; 95 | pdfPath += expA2B[q - 1]; 96 | } 97 | 98 | for (int q = 1; q <= j; ++q) { 99 | prod *= extValsB2A[q]; 100 | pdfLight += expB2A[q - 1]; 101 | } 102 | 103 | Float weight = pdf / (pdf + pdfLight + pdfPath + 2.0 * val); 104 | 105 | Float ist = prod * nee; 106 | 107 | Tr += ist * weight; 108 | } 109 | } 110 | 111 | Float pathProd = 1.0; 112 | for (int i = 0; i < extValsA2B.size(); ++i) { 113 | pathProd *= extValsA2B[i]; 114 | } 115 | 116 | Float pdftotPath = 0.0; 117 | for (int i = 0; i < expA2B.size(); ++i) { 118 | pdftotPath += expA2B[i]; 119 | } 120 | 121 | Tr += pathProd * val / (2.0 * val + pdftotPath); 122 | 123 | Float lightProd = 1.0; 124 | for (int i = 0; i < extValsB2A.size(); ++i) { 125 | lightProd *= extValsB2A[i]; 126 | } 127 | 128 | Float pdftotLight = 0.0; 129 | for (int i = 0; i < expB2A.size(); ++i) { 130 | pdftotLight += expB2A[i]; 131 | } 132 | 133 | Tr += lightProd * val / (2.0 * val + pdftotLight); 134 | 135 | rec.transmittance = Tr; 136 | 137 | return Tr; 138 | } 139 | 140 | string Bidirectional::getName() const { 141 | return "bidirectional"; 142 | } 143 | -------------------------------------------------------------------------------- /canonical/estimators/bidirectional.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "estimator.h" 4 | 5 | class Bidirectional : public Estimator { 6 | public: 7 | Bidirectional(); 8 | 9 | // numerical estimaton 10 | virtual Float T(TransmittanceQuaryRecord& rec, Sampler* sampler) const; 11 | 12 | virtual string getName() const; 13 | protected: 14 | }; 15 | -------------------------------------------------------------------------------- /canonical/estimators/estimator.cpp: -------------------------------------------------------------------------------- 1 | #include "estimator.h" 2 | #include 3 | 4 | Estimator::Estimator() { 5 | // does nothing 6 | } 7 | 8 | Estimator::~Estimator() { 9 | // does nothing 10 | } 11 | 12 | void Estimator::preProcess(Extinction* extFunc, Float a, Float b) { 13 | // does nothing 14 | } 15 | 16 | Float Estimator::sampleExpFF(const TransmittanceQuaryRecord& rec, Sampler* sampler, Float maj) const { 17 | return -log(1.0 - sampler->next1D()) / maj; 18 | } 19 | 20 | Float Estimator::sampleUniFF(const TransmittanceQuaryRecord& rec, Sampler* sampler) const { 21 | return sampler->next1D() * (rec.b - rec.a) + rec.a; 22 | } 23 | 24 | Float Estimator::pdfExpFF(Float ffd, const TransmittanceQuaryRecord& rec, Float maj) const { 25 | return maj * exp(-maj * ffd); 26 | } 27 | 28 | Float Estimator::pdfUniFF(Float x, const TransmittanceQuaryRecord& rec) const { 29 | return 1.0 / (rec.b - rec.a); 30 | } 31 | -------------------------------------------------------------------------------- /canonical/estimators/estimator.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../extinctions/extinctionFunc.h" 4 | #include "../samplers/sampler.h" 5 | 6 | struct TransmittanceQuaryRecord 7 | { 8 | // input 9 | const Extinction* extFunc; // reference to the extinction function 10 | const Float a; // start of the medium 11 | const Float b; // end of the medium 12 | const int n; // path length to evaluate 13 | const int samples; // number of samples 14 | 15 | // output 16 | int extCalls; // cost of evaluating transmittance 17 | Float transmittance; 18 | 19 | 20 | TransmittanceQuaryRecord(const Extinction* ext, Float a, Float b, int n, int samples) : extFunc(ext), a(a), b(b), n(n), samples(samples) { 21 | extCalls = 0; 22 | transmittance = 0; 23 | } 24 | }; 25 | 26 | class Estimator { 27 | public: 28 | Estimator(); 29 | virtual ~Estimator(); 30 | 31 | // numerical estimation 32 | virtual Float T(TransmittanceQuaryRecord& rec, Sampler* sampler) const = 0; 33 | 34 | virtual void preProcess(Extinction* extFunc, Float a, Float b); 35 | virtual string getName() const = 0; 36 | 37 | Float sampleExpFF(const TransmittanceQuaryRecord& rec, Sampler* sampler, Float maj) const; 38 | Float sampleUniFF(const TransmittanceQuaryRecord& rec, Sampler* sampler) const; 39 | 40 | Float pdfUniFF(Float x, const TransmittanceQuaryRecord& rec) const; 41 | Float pdfExpFF(Float x, const TransmittanceQuaryRecord& rec, Float maj) const; 42 | protected: 43 | }; 44 | -------------------------------------------------------------------------------- /canonical/estimators/expected.cpp: -------------------------------------------------------------------------------- 1 | #include "expected.h" 2 | 3 | Expected::Expected() : Estimator() { } 4 | 5 | Float Expected::T(TransmittanceQuaryRecord& rec, Sampler* sampler) const { 6 | Float od = rec.extFunc->calculateExtinctionIntegral(rec.a, rec.b); 7 | rec.transmittance = exp(-od); 8 | return exp(-od); 9 | } 10 | 11 | string Expected::getName() const { 12 | return "expected"; 13 | } 14 | -------------------------------------------------------------------------------- /canonical/estimators/expected.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "estimator.h" 4 | 5 | class Expected : public Estimator { 6 | public: 7 | Expected(); 8 | 9 | // numerical esitimation 10 | virtual Float T(TransmittanceQuaryRecord& rec, Sampler* sampler) const; 11 | 12 | virtual string getName() const; 13 | }; 14 | -------------------------------------------------------------------------------- /canonical/estimators/next_flight_ratio.cpp: -------------------------------------------------------------------------------- 1 | #include "next_flight_ratio.h" 2 | 3 | NextFlight_RatioTracking::NextFlight_RatioTracking() : Estimator() { } 4 | 5 | Float NextFlight_RatioTracking::T(TransmittanceQuaryRecord& rec, Sampler* sampler) const { 6 | Float x = rec.a; 7 | 8 | vector samps = vector(); 9 | 10 | Float k = rec.extFunc->calculateMajorant((rec.b + rec.a) / 2.0); 11 | 12 | Float Tr = exp(-k * (rec.b - rec.a)); 13 | 14 | do { 15 | x += sampleExpFF(rec, sampler, k); 16 | 17 | if (x >= rec.b) break; 18 | 19 | Float ext = rec.extFunc->calculateExtinction(x, rec.extCalls); 20 | samps.push_back((k - ext) / k); 21 | 22 | Float extProd = 1.0; 23 | for (int i = 0; i < samps.size(); i++) extProd *= samps[i]; 24 | 25 | Tr += extProd * exp(-k * (rec.b - x)); 26 | } while(true); 27 | 28 | rec.transmittance = Tr; 29 | 30 | return Tr; 31 | } 32 | 33 | 34 | string NextFlight_RatioTracking::getName() const { 35 | return "next_flight_ratio"; 36 | } 37 | -------------------------------------------------------------------------------- /canonical/estimators/next_flight_ratio.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "estimator.h" 4 | 5 | class NextFlight_RatioTracking : public Estimator { 6 | public: 7 | NextFlight_RatioTracking(); 8 | 9 | // numerical estimaton 10 | virtual Float T(TransmittanceQuaryRecord& rec, Sampler* sampler) const; 11 | 12 | virtual string getName() const; 13 | }; 14 | -------------------------------------------------------------------------------- /canonical/estimators/pseries_cdf.cpp: -------------------------------------------------------------------------------- 1 | #include "pseries_cdf.h" 2 | #include 3 | 4 | Pseries_CDF::Pseries_CDF() : Estimator() { } 5 | 6 | Float Pseries_CDF::T(TransmittanceQuaryRecord& rec, Sampler* sampler) const { 7 | Float t = 0.0; 8 | Float W = 1.0; 9 | Float i = 1.0; 10 | Float runningCDF = 0.0; 11 | Float tau = rec.extFunc->getMajorantFunction()->evalIntegral(rec.a, rec.b); 12 | Float val = exp(-tau); 13 | Float lastPDF = val; 14 | 15 | Float goal = 0.99; 16 | 17 | Float rr; 18 | do 19 | { 20 | rr = sampler->next1D(); 21 | } while (rr == 0.0); 22 | 23 | while (runningCDF < goal) 24 | { 25 | Float x = sampleUniFF(rec, sampler); 26 | Float majorant = rec.extFunc->calculateMajorant(x); 27 | Float extdiff = majorant - rec.extFunc->calculateExtinction(x, rec.extCalls); 28 | Float wi = (1.0 / i) * (extdiff) / (pdfUniFF(x, rec)); 29 | runningCDF += lastPDF; 30 | lastPDF *= tau / (i); 31 | t += W; 32 | W *= (wi); 33 | i += 1.0; 34 | } 35 | 36 | while (true) { 37 | Float left = W; 38 | 39 | Float accept = tau / i; 40 | runningCDF += lastPDF; 41 | 42 | if (accept <= rr) { 43 | t += left; 44 | break; 45 | } 46 | 47 | rr /= accept; 48 | 49 | Float x = sampleUniFF(rec, sampler); 50 | Float majorant = rec.extFunc->calculateMajorant(x); 51 | Float extdiff = majorant - rec.extFunc->calculateExtinction(x, rec.extCalls); 52 | Float wi = (1.0 / i) * (extdiff) / (pdfUniFF(x, rec)); 53 | 54 | lastPDF *= tau / i; 55 | t += left; 56 | W *= (wi / accept); 57 | i += 1.0; 58 | } 59 | 60 | rec.transmittance = t * val; 61 | 62 | return t * val; 63 | } 64 | 65 | string Pseries_CDF::getName() const { 66 | return "pseries_cdf"; 67 | } 68 | -------------------------------------------------------------------------------- /canonical/estimators/pseries_cdf.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "estimator.h" 4 | 5 | class Pseries_CDF : public Estimator { 6 | public: 7 | Pseries_CDF(); 8 | 9 | // numerical estimation 10 | virtual Float T(TransmittanceQuaryRecord& rec, Sampler* sampler) const; 11 | 12 | virtual string getName() const; 13 | }; 14 | -------------------------------------------------------------------------------- /canonical/estimators/pseries_cumulative.cpp: -------------------------------------------------------------------------------- 1 | #include "pseries_cumulative.h" 2 | #include "../util.h" 3 | 4 | Pseries_Cumulative::Pseries_Cumulative() : Estimator() { } 5 | 6 | Float Pseries_Cumulative::T(TransmittanceQuaryRecord& rec, Sampler* sampler) const { 7 | Float t = 0.0; 8 | Float W = 1.0; 9 | Float i = 1.0; 10 | 11 | Float majorant = rec.extFunc->calculateMajorant(0.5); 12 | 13 | Float rr; 14 | do 15 | { 16 | rr = sampler->next1D(); 17 | } while (rr == 0.0); 18 | 19 | while (true) { 20 | Float left = W; 21 | Float x = sampleUniFF(rec, sampler); 22 | 23 | Float wi = (1.0 / i) * (majorant - rec.extFunc->calculateExtinction(x, rec.extCalls)) / (pdfUniFF(x, rec)); 24 | 25 | Float accept = Util::ABS(W * wi); 26 | 27 | if (accept > 1.0) accept = 1.0; 28 | 29 | if (accept <= rr) { 30 | t += left; 31 | break; 32 | } 33 | 34 | rr /= accept; 35 | 36 | t += left; 37 | W *= (wi / accept); 38 | i += 1.0; 39 | } 40 | 41 | rec.transmittance = t * exp(-majorant * (rec.b - rec.a)); 42 | 43 | return t * exp(-majorant * (rec.b - rec.a)); 44 | } 45 | 46 | string Pseries_Cumulative::getName() const { 47 | return "pseries_cumulative"; 48 | } 49 | -------------------------------------------------------------------------------- /canonical/estimators/pseries_cumulative.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "estimator.h" 4 | 5 | class Pseries_Cumulative : public Estimator { 6 | public: 7 | Pseries_Cumulative(); 8 | 9 | // numerical estimation 10 | virtual Float T(TransmittanceQuaryRecord& rec, Sampler* sampler) const; 11 | 12 | virtual string getName() const; 13 | }; 14 | -------------------------------------------------------------------------------- /canonical/estimators/pseries_next_flight_ratio.cpp: -------------------------------------------------------------------------------- 1 | #include "pseries_next_flight_ratio.h" 2 | #include "../util.h" 3 | #include 4 | 5 | Pseries_NextFlightRatio::Pseries_NextFlightRatio() : Estimator() { } 6 | 7 | Float Pseries_NextFlightRatio::T(TransmittanceQuaryRecord& rec, Sampler* sampler) const { 8 | Float sample = sampler->next1D(); 9 | 10 | Float maj = rec.extFunc->calculateMajorant((rec.b - rec.a) / 2.0 + rec.a); 11 | Float tau = maj * (rec.b - rec.a); 12 | Float prob = exp(-tau); 13 | Float cdf = 0.0; 14 | Float Tr = 0.0; 15 | Float prod = exp(-tau); 16 | 17 | for (int i = 0; cdf < sample; cdf += prob, ++i) 18 | { 19 | Float x = sampleUniFF(rec, sampler); 20 | 21 | if (i != 0) 22 | { 23 | prod *= (maj - rec.extFunc->calculateExtinction(x, rec.extCalls)) * (rec.b - rec.a); 24 | prod *= (1.0 / i); 25 | } 26 | 27 | Tr += prod / (1.0 - cdf); 28 | 29 | if (i != 0) 30 | { 31 | prob *= tau / Float(i); 32 | } 33 | } 34 | 35 | rec.transmittance = Tr; 36 | 37 | return Tr; 38 | } 39 | 40 | string Pseries_NextFlightRatio::getName() const { 41 | return "pseries_next_flight_ratio"; 42 | } 43 | -------------------------------------------------------------------------------- /canonical/estimators/pseries_next_flight_ratio.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "estimator.h" 4 | 5 | class Pseries_NextFlightRatio : public Estimator { 6 | public: 7 | Pseries_NextFlightRatio(); 8 | 9 | // numerical estimation 10 | virtual Float T(TransmittanceQuaryRecord& rec, Sampler* sampler) const; 11 | 12 | virtual string getName() const; 13 | }; 14 | -------------------------------------------------------------------------------- /canonical/estimators/pseries_ratio.cpp: -------------------------------------------------------------------------------- 1 | #include "pseries_ratio.h" 2 | #include 3 | 4 | Pseries_Ratio::Pseries_Ratio() : Estimator() { } 5 | 6 | Float Pseries_Ratio::T(TransmittanceQuaryRecord& rec, Sampler* sampler) const { 7 | Float sample = sampler->next1D(); 8 | 9 | Float maj = rec.extFunc->calculateMajorant((rec.b - rec.a) / 2.0 + rec.a); 10 | Float tau = maj * (rec.b - rec.a); 11 | Float prob = exp(-tau); 12 | Float cdf = prob; 13 | Float Tr = 1.0; 14 | 15 | int i = 1; 16 | 17 | for (; cdf < sample; cdf += prob, ++i) 18 | { 19 | Float x = sampleUniFF(rec, sampler); 20 | Tr *= 1.0 - rec.extFunc->calculateExtinction(x, rec.extCalls) / maj; 21 | prob *= tau / Float(i); 22 | } 23 | 24 | rec.transmittance = Tr; 25 | 26 | return Tr; 27 | } 28 | 29 | string Pseries_Ratio::getName() const { 30 | return "pseries_ratio"; 31 | } 32 | -------------------------------------------------------------------------------- /canonical/estimators/pseries_ratio.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "estimator.h" 4 | 5 | class Pseries_Ratio : public Estimator { 6 | public: 7 | Pseries_Ratio(); 8 | 9 | // numerical estimation 10 | virtual Float T(TransmittanceQuaryRecord& rec, Sampler* sampler) const; 11 | 12 | virtual string getName() const; 13 | }; 14 | -------------------------------------------------------------------------------- /canonical/estimators/ratio_tracking.cpp: -------------------------------------------------------------------------------- 1 | #include "ratio_tracking.h" 2 | #include 3 | 4 | RatioTracking::RatioTracking() : Estimator() { } 5 | 6 | Float RatioTracking::T(TransmittanceQuaryRecord& rec, Sampler* sampler) const { 7 | Float x = rec.a; 8 | Float T = 1; 9 | 10 | do { 11 | // Sample a random value y with pdf(y) = k * exp(-ky) set x = a + y 12 | Float k = rec.extFunc->calculateMajorant(x); 13 | x += sampleExpFF(rec, sampler, k); 14 | 15 | if (x >= rec.b) break; 16 | 17 | T *= (1.0 - rec.extFunc->calculateExtinction(x, rec.extCalls) / k); 18 | } while(true); 19 | 20 | rec.transmittance = T; 21 | 22 | return T; 23 | } 24 | 25 | string RatioTracking::getName() const { 26 | return "ratio"; 27 | } 28 | -------------------------------------------------------------------------------- /canonical/estimators/ratio_tracking.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "estimator.h" 4 | 5 | class RatioTracking : public Estimator { 6 | public: 7 | RatioTracking(); 8 | 9 | // numerical estimation 10 | virtual Float T(TransmittanceQuaryRecord& rec, Sampler* sampler) const; 11 | 12 | virtual string getName() const; 13 | }; 14 | -------------------------------------------------------------------------------- /canonical/estimators/track_length.cpp: -------------------------------------------------------------------------------- 1 | #include "track_length.h" 2 | #include 3 | 4 | TrackLength::TrackLength() : Estimator() { } 5 | 6 | Float TrackLength::T(TransmittanceQuaryRecord& rec, Sampler* sampler) const { 7 | // Choose a constant k such that k >= ext(x) for all x[a,b] 8 | Float k = rec.extFunc->calculateMajorant((rec.b + rec.a) / 2.0); 9 | Float x = rec.a; 10 | x = 0.0; 11 | 12 | do { 13 | // Sample a random value y with pdf(y) = k * exp(-ky) set x = a + y 14 | x += sampleExpFF(rec, sampler, k); 15 | 16 | // If x > b stop and return 1 17 | if (x >= rec.b) { 18 | rec.transmittance = 1.0; 19 | return 1.0; 20 | } 21 | // Sample a uniform random number g[0,1] 22 | Float g = sampler->next1D(); 23 | 24 | // If g <= ext(x) / k; stop and return 0 25 | if (g <= rec.extFunc->calculateExtinction(x, rec.extCalls) / k) { 26 | rec.transmittance = 0.0; 27 | return 0.0; 28 | } 29 | } while(true); 30 | // this should never be reached 31 | return 0.0; 32 | } 33 | 34 | string TrackLength::getName() const { 35 | return "track_length"; 36 | } 37 | -------------------------------------------------------------------------------- /canonical/estimators/track_length.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "estimator.h" 4 | 5 | class TrackLength : public Estimator { 6 | public: 7 | TrackLength(); 8 | 9 | // numerical estimation 10 | virtual Float T(TransmittanceQuaryRecord& rec, Sampler* sampler) const; 11 | 12 | virtual string getName() const; 13 | }; 14 | -------------------------------------------------------------------------------- /canonical/estimators/unidirectional.cpp: -------------------------------------------------------------------------------- 1 | #include "unidirectional.h" 2 | #include 3 | 4 | Unidirectional::Unidirectional() : Estimator() { } 5 | 6 | Float Unidirectional::T(TransmittanceQuaryRecord& rec, Sampler* sampler) const { 7 | Float x = rec.a; 8 | Float T = 0.0; 9 | Float weight = 1.0; 10 | 11 | while (true) { 12 | Float k = rec.extFunc->calculateMajorant(x); 13 | Float newx = x + sampleExpFF(rec, sampler, k); 14 | 15 | Float val = exp(-k * (rec.b - x)); 16 | 17 | Float nfrProb = 1.0; 18 | Float ratProb = val; 19 | Float nfrContr = val; 20 | Float ratContr = 1.0; 21 | 22 | Float ratMISWeight = ratProb / (ratProb + nfrProb); 23 | Float nfrMISWeight = nfrProb / (ratProb + nfrProb); 24 | 25 | if (newx >= rec.b) 26 | { 27 | T += weight * (ratContr * ratMISWeight + nfrContr * nfrMISWeight); 28 | break; 29 | } 30 | 31 | T += weight * (nfrContr * nfrMISWeight); 32 | x = newx; 33 | 34 | Float ext = rec.extFunc->calculateExtinction(x, rec.extCalls); 35 | weight *= ((k - ext) / k); 36 | } 37 | 38 | rec.transmittance = T; 39 | 40 | return T; 41 | } 42 | 43 | string Unidirectional::getName() const { 44 | return "unidirectional"; 45 | } 46 | -------------------------------------------------------------------------------- /canonical/estimators/unidirectional.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "estimator.h" 4 | 5 | class Unidirectional : public Estimator { 6 | public: 7 | Unidirectional(); 8 | 9 | // numerical estimaton 10 | virtual Float T(TransmittanceQuaryRecord& rec, Sampler* sampler) const; 11 | 12 | virtual string getName() const; 13 | protected: 14 | }; 15 | -------------------------------------------------------------------------------- /canonical/exceptions.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | class ChannelException : public std::runtime_error 7 | { 8 | public: 9 | ChannelException() : std::runtime_error("Number of channels must be 1, 3 or 4 when writing to image.") {} 10 | }; 11 | -------------------------------------------------------------------------------- /canonical/ext/mpfr_pp/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | build/ 3 | -------------------------------------------------------------------------------- /canonical/ext/mpfr_pp/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 2.8.3) 2 | project(real_test) 3 | 4 | if(APPLE) 5 | set(CMAKE_MACOSX_RPATH ON) 6 | endif() 7 | 8 | include(CheckCXXCompilerFlag) 9 | include(CheckCXXSourceRuns) 10 | 11 | message("source dir: " ${CMAKE_SOURCE_DIR}) 12 | 13 | SET (CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH}) 14 | 15 | if (CMAKE_CXX_COMPILER_ID MATCHES "Clang") 16 | # Quench annoying deprecation warnings when compiling GLFW on OSX 17 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wno-deprecated-declarations") 18 | endif() 19 | 20 | if (CMAKE_CXX_COMPILER_ID MATCHES "^(GNU|Clang|Intel)$") 21 | CHECK_CXX_COMPILER_FLAG("-std=c++14" HAS_CPP14_FLAG) 22 | CHECK_CXX_COMPILER_FLAG("-std=c++11" HAS_CPP11_FLAG) 23 | 24 | if (HAS_CPP14_FLAG) 25 | #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++14") 26 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++14") 27 | elseif (HAS_CPP11_FLAG) 28 | #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") 29 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11") 30 | else() 31 | message(FATAL_ERROR "Unsupported compiler -- pybind11 requires C++11 support!") 32 | endif() 33 | endif() 34 | 35 | IF(APPLE) 36 | # Fix linking on 10.14+. See https://stackoverflow.com/questions/54068035 37 | LINK_DIRECTORIES(/usr/local/lib) 38 | ENDIF() 39 | 40 | if (APPLE) 41 | find_library(cocoa_library Cocoa) 42 | find_library(opengl_library OpenGL) 43 | find_library(corevideo_library CoreVideo) 44 | find_library(iokit_library IOKit) 45 | list(APPEND NANOGUI_EXTRA_LIBS ${cocoa_library} ${opengl_library} ${corevideo_library} ${iokit_library}) 46 | list(APPEND LIBNANOGUI_EXTRA_SOURCE src/darwin.mm) 47 | endif() 48 | 49 | 50 | 51 | include_directories(${MPFR_INCLUDES}) 52 | 53 | message(yup) 54 | message(mpfr: (${MPFR_LIBRARIES})) 55 | 56 | if(APPLE) 57 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto -Wno-unused-result -fno-strict-aliasing") 58 | else() 59 | set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto -Wno-unused-result -fno-strict-aliasing -Wlto-type-mismatch") 60 | endif() 61 | 62 | 63 | add_executable(real_test 64 | real.h 65 | 66 | test.cpp 67 | ) 68 | 69 | #OPENEXR_INCLUDE_DIRS 70 | set(CompilerFlags 71 | CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE 72 | CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO CMAKE_C_FLAGS 73 | CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE CMAKE_C_FLAGS_MINSIZEREL 74 | CMAKE_C_FLAGS_RELWITHDEBINFO COMPILE_DEFINITIONS U_CMAKE_BUILD_TYPE 75 | CMAKE_MACOSX_RPATH 76 | MPFR_INCLUDES 77 | ) 78 | 79 | # Lastly, additional libraries may have been built for you. In addition to linking 80 | # against NanoGUI, we need to link against those as well. 81 | target_link_libraries(real_test mpfr ${MPFR_LIBRARIES}) 82 | -------------------------------------------------------------------------------- /canonical/ext/mpfr_pp/README.md: -------------------------------------------------------------------------------- 1 | This repository contains a simple C++ wrapper of the mpfr_t 2 | datastructure for simple integration in C++ projects. 3 | -------------------------------------------------------------------------------- /canonical/ext/mpfr_pp/real.h: -------------------------------------------------------------------------------- 1 | // The below code is authored by Zackary Misso 2 | // It is free to use as long as credit is given for its use 3 | 4 | #pragma once 5 | 6 | #include 7 | // #include "/usr/local/include/mpfr.h" 8 | #include 9 | #include 10 | 11 | #define REAL_PRECISION 512 12 | 13 | namespace mpfr_pp 14 | { 15 | 16 | static void mpfr_from_str(const std::string str, mpfr_t& result) 17 | { 18 | mpfr_init2(result, REAL_PRECISION); 19 | mpfr_set_str(result, str.c_str(), /*base*/10, MPFR_RNDN); 20 | } 21 | 22 | static void mpfr_from_str(const char* str, mpfr_t& result) 23 | { 24 | mpfr_init2(result, REAL_PRECISION); 25 | mpfr_set_str(result, str, /*base*/10, MPFR_RNDN); 26 | } 27 | 28 | struct real 29 | { 30 | protected: 31 | mpfr_t m_val; 32 | 33 | void text(std::string message, const mpfr_t& val) const 34 | { 35 | std::cout << message << std::endl; 36 | mpfr_out_str (stdout, 10, 0, val, MPFR_RNDD); 37 | std::cout << std::endl; 38 | } 39 | 40 | public: 41 | void text(std::string message) const 42 | { 43 | text(message, m_val); 44 | } 45 | 46 | real() 47 | { 48 | mpfr_init2(m_val, REAL_PRECISION); 49 | } 50 | 51 | real(const real& val) 52 | { 53 | mpfr_init2(m_val, REAL_PRECISION); 54 | mpfr_set(m_val, val.m_val, MPFR_RNDN); 55 | } 56 | 57 | real(const long double& val) 58 | { 59 | mpfr_init2(m_val, REAL_PRECISION); 60 | mpfr_set_ld(m_val, val, MPFR_RNDN); 61 | } 62 | 63 | real(const double& val) 64 | { 65 | mpfr_init2(m_val, REAL_PRECISION); 66 | mpfr_set_d(m_val, val, MPFR_RNDN); 67 | } 68 | 69 | real(const float& val) 70 | { 71 | mpfr_init2(m_val, REAL_PRECISION); 72 | mpfr_set_flt(m_val, val, MPFR_RNDN); 73 | } 74 | 75 | real(const unsigned long& val) 76 | { 77 | mpfr_init2(m_val, REAL_PRECISION); 78 | mpfr_set_ui(m_val, val, MPFR_RNDN); 79 | } 80 | 81 | real(const long& val) 82 | { 83 | mpfr_init2(m_val, REAL_PRECISION); 84 | mpfr_set_si(m_val, val, MPFR_RNDN); 85 | } 86 | 87 | real(const unsigned int& val) 88 | { 89 | mpfr_init2(m_val, REAL_PRECISION); 90 | mpfr_set_ui(m_val, val, MPFR_RNDN); 91 | } 92 | 93 | real(const int& val) 94 | { 95 | mpfr_init2(m_val, REAL_PRECISION); 96 | mpfr_set_si(m_val, val, MPFR_RNDN); 97 | } 98 | 99 | real(std::string val) 100 | { 101 | mpfr_init2(m_val, REAL_PRECISION); 102 | mpfr_set_str(m_val, val.c_str(), /*base*/10, MPFR_RNDN); 103 | } 104 | 105 | real(const char* val) 106 | { 107 | mpfr_init2(m_val, REAL_PRECISION); 108 | mpfr_set_str(m_val, val, /*base*/10, MPFR_RNDN); 109 | } 110 | 111 | ~real() 112 | { 113 | mpfr_clear(m_val); 114 | } 115 | 116 | // operators 117 | void operator++() 118 | { 119 | mpfr_t one; 120 | mpfr_from_str("1.0", one); 121 | mpfr_add(m_val, m_val, one, MPFR_RNDN); 122 | mpfr_clear(one); 123 | } 124 | 125 | void operator--() 126 | { 127 | mpfr_t one; 128 | mpfr_from_str("1.0", one); 129 | mpfr_sub(m_val, m_val, one, MPFR_RNDN); 130 | mpfr_clear(one); 131 | } 132 | 133 | real operator-() const 134 | { 135 | mpfr_t tmp; 136 | mpfr_init2(tmp, REAL_PRECISION); 137 | mpfr_set_d(tmp, -1.0, MPFR_RNDN); 138 | mpfr_mul(tmp, m_val, tmp, MPFR_RNDN); 139 | 140 | real val; 141 | mpfr_set(val.m_val, tmp, MPFR_RNDN); 142 | 143 | mpfr_clear(tmp); 144 | 145 | return val; 146 | } 147 | 148 | real operator+(const real& other) const 149 | { 150 | mpfr_t tmp; 151 | mpfr_init2(tmp, REAL_PRECISION); 152 | mpfr_add(tmp, other.m_val, m_val, MPFR_RNDN); 153 | 154 | real val; 155 | mpfr_set(val.m_val, tmp, MPFR_RNDN); 156 | 157 | mpfr_clear(tmp); 158 | 159 | return val; 160 | } 161 | 162 | real operator-(const real& other) const 163 | { 164 | mpfr_t tmp; 165 | mpfr_init2(tmp, REAL_PRECISION); 166 | mpfr_sub(tmp, m_val, other.m_val, MPFR_RNDN); 167 | 168 | real val; 169 | mpfr_set(val.m_val, tmp, MPFR_RNDN); 170 | 171 | mpfr_clear(tmp); 172 | 173 | return val; 174 | } 175 | 176 | real operator*(const real& other) const 177 | { 178 | mpfr_t tmp; 179 | mpfr_init2(tmp, REAL_PRECISION); 180 | mpfr_mul(tmp, m_val, other.m_val, MPFR_RNDN); 181 | 182 | real val; 183 | mpfr_set(val.m_val, tmp, MPFR_RNDN); 184 | 185 | mpfr_clear(tmp); 186 | 187 | return val; 188 | } 189 | 190 | real operator/(const real& other) const 191 | { 192 | mpfr_t tmp; 193 | mpfr_init2(tmp, REAL_PRECISION); 194 | mpfr_div(tmp, m_val, other.m_val, MPFR_RNDN); 195 | 196 | real val; 197 | mpfr_set(val.m_val, tmp, MPFR_RNDN); 198 | 199 | mpfr_clear(tmp); 200 | 201 | return val; 202 | } 203 | 204 | real& operator=(const real& other) 205 | { 206 | mpfr_set(m_val, other.m_val, MPFR_RNDN); 207 | return *this; 208 | } 209 | 210 | void operator+=(const real& other) 211 | { 212 | mpfr_add(m_val, m_val, other.m_val, MPFR_RNDN); 213 | } 214 | 215 | void operator-=(const real& other) 216 | { 217 | mpfr_sub(m_val, m_val, other.m_val, MPFR_RNDN); 218 | } 219 | 220 | void operator*=(const real& other) 221 | { 222 | mpfr_mul(m_val, m_val, other.m_val, MPFR_RNDN); 223 | } 224 | 225 | void operator/=(const real& other) 226 | { 227 | mpfr_div(m_val, m_val, other.m_val, MPFR_RNDN); 228 | } 229 | 230 | bool operator==(const real& other) const 231 | { 232 | int compare = mpfr_cmp(m_val, other.m_val); 233 | return compare == 0; 234 | } 235 | 236 | bool operator!=(const real& other) const 237 | { 238 | int compare = mpfr_cmp(m_val, other.m_val); 239 | return compare != 0; 240 | } 241 | 242 | bool operator<(const real& other) const 243 | { 244 | int compare = mpfr_cmp(m_val, other.m_val); 245 | return compare < 0; 246 | } 247 | 248 | bool operator<=(const real& other) const 249 | { 250 | int compare = mpfr_cmp(m_val, other.m_val); 251 | return compare <= 0; 252 | } 253 | 254 | bool operator>(const real& other) const 255 | { 256 | int compare = mpfr_cmp(m_val, other.m_val); 257 | return compare > 0; 258 | } 259 | 260 | bool operator>=(const real& other) const 261 | { 262 | int compare = mpfr_cmp(m_val, other.m_val); 263 | return compare >= 0; 264 | } 265 | 266 | explicit operator long double() const 267 | { 268 | return mpfr_get_ld(m_val, MPFR_RNDN); 269 | } 270 | explicit operator double() const 271 | { 272 | return mpfr_get_d(m_val, MPFR_RNDN); 273 | } 274 | explicit operator float() const 275 | { 276 | return mpfr_get_flt(m_val, MPFR_RNDN); 277 | } 278 | explicit operator unsigned long() const 279 | { 280 | return mpfr_get_ui(m_val, MPFR_RNDN); 281 | } 282 | explicit operator long() const 283 | { 284 | return mpfr_get_si(m_val, MPFR_RNDN); 285 | } 286 | explicit operator unsigned int() const 287 | { 288 | return (unsigned int)mpfr_get_ui(m_val, MPFR_RNDN); 289 | } 290 | explicit operator int() const 291 | { 292 | return (int)mpfr_get_si(m_val, MPFR_RNDN); 293 | } 294 | 295 | // friend methods 296 | friend real operator+(const double& two, const real& one); 297 | friend real operator-(const double& two, const real& one); 298 | friend real operator*(const double& two, const real& one); 299 | friend real operator/(const double& two, const real& one); 300 | 301 | friend inline bool operator>(const double& two, const real& one); 302 | friend inline bool operator<(const double& two, const real& one); 303 | friend inline bool operator==(const double& two, const real& one); 304 | friend inline bool operator!=(const double& two, const real& one); 305 | friend inline bool operator>=(const double& two, const real& one); 306 | friend inline bool operator<=(const double& two, const real& one); 307 | 308 | friend inline std::ostream& operator<<(std::ostream& out, const real& value); 309 | 310 | friend inline real abs(const real& value); 311 | friend inline real cos(const real& value); 312 | friend inline real sin(const real& value); 313 | friend inline real exp(const real& value); 314 | friend inline real log(const real& value); 315 | friend inline real pow(const real& base, const real& pow); 316 | }; 317 | 318 | inline std::ostream& operator<<(std::ostream& out, const real& value) 319 | { 320 | out << double(value); 321 | return out; 322 | } 323 | 324 | inline bool operator>(const double& two, const real& one) 325 | { 326 | mpfr_t tmp; 327 | mpfr_init2(tmp, REAL_PRECISION); 328 | mpfr_set_d(tmp, two, MPFR_RNDN); 329 | int compare = mpfr_cmp(tmp, one.m_val); 330 | mpfr_clear(tmp); 331 | return compare > 0; 332 | } 333 | 334 | inline bool operator<(const double& two, const real& one) 335 | { 336 | mpfr_t tmp; 337 | mpfr_init2(tmp, REAL_PRECISION); 338 | mpfr_set_d(tmp, two, MPFR_RNDN); 339 | int compare = mpfr_cmp(tmp, one.m_val); 340 | mpfr_clear(tmp); 341 | return compare < 0; 342 | } 343 | 344 | inline bool operator==(const double& two, const real& one) 345 | { 346 | mpfr_t tmp; 347 | mpfr_init2(tmp, REAL_PRECISION); 348 | mpfr_set_d(tmp, two, MPFR_RNDN); 349 | int compare = mpfr_cmp(tmp, one.m_val); 350 | mpfr_clear(tmp); 351 | return compare == 0; 352 | } 353 | 354 | inline bool operator!=(const double& two, const real& one) 355 | { 356 | mpfr_t tmp; 357 | mpfr_init2(tmp, REAL_PRECISION); 358 | mpfr_set_d(tmp, two, MPFR_RNDN); 359 | int compare = mpfr_cmp(tmp, one.m_val); 360 | mpfr_clear(tmp); 361 | return compare != 0; 362 | } 363 | 364 | inline bool operator>=(const double& two, const real& one) 365 | { 366 | mpfr_t tmp; 367 | mpfr_init2(tmp, REAL_PRECISION); 368 | mpfr_set_d(tmp, two, MPFR_RNDN); 369 | int compare = mpfr_cmp(tmp, one.m_val); 370 | mpfr_clear(tmp); 371 | return compare >= 0; 372 | } 373 | 374 | inline bool operator<=(const double& two, const real& one) 375 | { 376 | mpfr_t tmp; 377 | mpfr_init2(tmp, REAL_PRECISION); 378 | mpfr_set_d(tmp, two, MPFR_RNDN); 379 | int compare = mpfr_cmp(tmp, one.m_val); 380 | mpfr_clear(tmp); 381 | return compare <= 0; 382 | } 383 | 384 | inline real abs(const real& value) 385 | { 386 | mpfr_t tmp; 387 | mpfr_init2(tmp, REAL_PRECISION); 388 | mpfr_abs(tmp, value.m_val, MPFR_RNDN); 389 | 390 | real val; 391 | mpfr_set(val.m_val, tmp, MPFR_RNDN); 392 | 393 | mpfr_clear(tmp); 394 | 395 | return val; 396 | } 397 | 398 | inline real sin(const real& value) 399 | { 400 | mpfr_t tmp; 401 | mpfr_init2(tmp, REAL_PRECISION); 402 | mpfr_sin(tmp, value.m_val, MPFR_RNDN); 403 | 404 | real val; 405 | mpfr_set(val.m_val, tmp, MPFR_RNDN); 406 | 407 | mpfr_clear(tmp); 408 | 409 | return val; 410 | } 411 | 412 | inline real cos(const real& value) 413 | { 414 | mpfr_t tmp; 415 | mpfr_init2(tmp, REAL_PRECISION); 416 | mpfr_cos(tmp, value.m_val, MPFR_RNDN); 417 | 418 | real val; 419 | mpfr_set(val.m_val, tmp, MPFR_RNDN); 420 | 421 | mpfr_clear(tmp); 422 | 423 | return val; 424 | } 425 | 426 | inline real exp(const real& value) 427 | { 428 | mpfr_t e; 429 | mpfr_init2(e, REAL_PRECISION); 430 | mpfr_exp(e, value.m_val, MPFR_RNDN); 431 | 432 | real ret; 433 | mpfr_set(ret.m_val, e, MPFR_RNDN); 434 | 435 | mpfr_clear(e); 436 | 437 | return ret; 438 | } 439 | 440 | inline real log(const real& value) 441 | { 442 | mpfr_t e; 443 | mpfr_init2(e, REAL_PRECISION); 444 | mpfr_log(e, value.m_val, MPFR_RNDN); 445 | 446 | real ret; 447 | mpfr_set(ret.m_val, e, MPFR_RNDN); 448 | 449 | mpfr_clear(e); 450 | 451 | return ret; 452 | } 453 | 454 | inline real pow(const real& base, const real& power) 455 | { 456 | mpfr_t value; 457 | mpfr_init2(value, REAL_PRECISION); 458 | mpfr_pow(value, base.m_val, power.m_val, MPFR_RNDN); 459 | 460 | real ret; 461 | mpfr_set(ret.m_val, value, MPFR_RNDN); 462 | 463 | mpfr_clear(value); 464 | 465 | return ret; 466 | } 467 | 468 | inline real operator+(const double& two, const real& one) 469 | { 470 | mpfr_t tmp; 471 | mpfr_init2(tmp, REAL_PRECISION); 472 | mpfr_set_d(tmp, two, MPFR_RNDN); 473 | mpfr_add(tmp, one.m_val, tmp, MPFR_RNDN); 474 | 475 | real val; 476 | mpfr_set(val.m_val, tmp, MPFR_RNDN); 477 | 478 | mpfr_clear(tmp); 479 | 480 | return val; 481 | } 482 | 483 | inline real operator-(const double& two, const real& one) 484 | { 485 | mpfr_t tmp; 486 | mpfr_init2(tmp, REAL_PRECISION); 487 | mpfr_set_d(tmp, two, MPFR_RNDN); 488 | mpfr_sub(tmp, tmp, one.m_val, MPFR_RNDN); 489 | 490 | real val; 491 | mpfr_set(val.m_val, tmp, MPFR_RNDN); 492 | 493 | mpfr_clear(tmp); 494 | 495 | return val; 496 | } 497 | 498 | inline real operator*(const double& two, const real& one) 499 | { 500 | mpfr_t tmp; 501 | mpfr_init2(tmp, REAL_PRECISION); 502 | mpfr_set_d(tmp, two, MPFR_RNDN); 503 | mpfr_mul(tmp, tmp, one.m_val, MPFR_RNDN); 504 | 505 | real val; 506 | mpfr_set(val.m_val, tmp, MPFR_RNDN); 507 | 508 | mpfr_clear(tmp); 509 | 510 | return val; 511 | } 512 | 513 | inline real operator/(const double& two, const real& one) 514 | { 515 | mpfr_t tmp; 516 | mpfr_init2(tmp, REAL_PRECISION); 517 | mpfr_set_d(tmp, two, MPFR_RNDN); 518 | mpfr_div(tmp, tmp, one.m_val, MPFR_RNDN); 519 | 520 | real val; 521 | mpfr_set(val.m_val, tmp, MPFR_RNDN); 522 | 523 | mpfr_clear(tmp); 524 | 525 | return val; 526 | } 527 | 528 | } 529 | -------------------------------------------------------------------------------- /canonical/ext/mpfr_pp/test.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "real.h" 4 | 5 | using namespace mpfr_pp; 6 | 7 | bool initTest() 8 | { 9 | real one = 1; 10 | real two = 2.f; 11 | real three = 3.0; 12 | real four = "4.0"; 13 | 14 | std::string five_s = "5.0"; 15 | real five = five_s; 16 | 17 | int one_i = 1; 18 | int two_i = 2; 19 | int three_i = 3; 20 | int four_i = 4; 21 | int five_i = 5; 22 | 23 | if (one == one_i && 24 | two == two_i && 25 | three == three_i && 26 | four == four_i && 27 | five == five_i) 28 | { 29 | return true; 30 | } 31 | 32 | return false; 33 | } 34 | 35 | bool addTest() 36 | { 37 | int one = 1; 38 | float two = 2.f; 39 | double three = 3.0; 40 | std::string four = "4.0"; 41 | long five = 5u; 42 | 43 | real val = "0"; 44 | 45 | val += one; 46 | val = val + one; 47 | val += two; 48 | val = val + two; 49 | val += three; 50 | val = val + three; 51 | val += four; 52 | val = val + four; 53 | val += five; 54 | val = val + five; 55 | 56 | int answer = 2*(1+2+3+4+5); 57 | 58 | if (val == answer) return true; 59 | 60 | return false; 61 | } 62 | 63 | bool subTest() 64 | { 65 | real val = 2*(1+2+3+4+5); 66 | 67 | float one = 1.f; 68 | int two = 2; 69 | long three = 3u; 70 | double four = 4.0; 71 | std::string five = "05.00"; 72 | 73 | val -= one; 74 | val = val - one; 75 | val -= two; 76 | val = val - two; 77 | val -= three; 78 | val = val - three; 79 | val -= four; 80 | val = val - four; 81 | val -= five; 82 | val = val - five; 83 | 84 | if (val == "0.0") return true; 85 | 86 | return false; 87 | } 88 | 89 | bool mulTest() 90 | { 91 | long answer = 1*1*2*2*3*3*4*4*5*5; 92 | 93 | std::string one = "01.00"; 94 | double two = 2.0; 95 | int three = 3; 96 | long four = 4u; 97 | float five = 5.f; 98 | 99 | real val = 1.f; 100 | 101 | val *= one; 102 | val = val * one; 103 | val *= two; 104 | val = val * two; 105 | val *= three; 106 | val = val * three; 107 | val *= four; 108 | val = val * four; 109 | val *= five; 110 | val = val * five; 111 | 112 | if (val == answer) return true; 113 | 114 | return false; 115 | } 116 | 117 | bool divTest() 118 | { 119 | real val = 1.0*1.0*2.0*2.0*3.0*3.0*4.0*4.0*5.0*5.0; 120 | 121 | double one = 1.0; 122 | std::string two = "002.000"; 123 | long three = 3u; 124 | float four = 4.f; 125 | int five = 5; 126 | 127 | val /= one; 128 | val = val / one; 129 | val /= two; 130 | val = val / two; 131 | val /= three; 132 | val = val / three; 133 | val /= four; 134 | val = val / four; 135 | val /= five; 136 | val = val / five; 137 | 138 | if (val == 1) return true; 139 | 140 | return false; 141 | } 142 | 143 | bool lessThanTests() 144 | { 145 | // TODO 146 | 147 | return true; 148 | } 149 | 150 | bool greaterThanTests() 151 | { 152 | // TODO 153 | 154 | return true; 155 | } 156 | 157 | bool lessThanOrEqTests() 158 | { 159 | // TODO 160 | 161 | return true; 162 | } 163 | 164 | bool greaterThanOrEqTests() 165 | { 166 | // TODO 167 | 168 | return true; 169 | } 170 | 171 | bool eqOrNotEqTests() 172 | { 173 | // TODO 174 | 175 | return true; 176 | } 177 | 178 | bool test() 179 | { 180 | if (!initTest()) { 181 | std::cout << "Failed Init Test" << std::endl; 182 | return false; 183 | } 184 | if (!addTest()) { 185 | std::cout << "Failed Add Test" << std::endl; 186 | return false; 187 | } 188 | if (!subTest()) { 189 | std::cout << "Failed Sub Test" << std::endl; 190 | return false; 191 | } 192 | if (!mulTest()) { 193 | std::cout << "Failed Mul Test" << std::endl; 194 | return false; 195 | } 196 | if (!divTest()) { 197 | std::cout << "Failed Div Test" << std::endl; 198 | return false; 199 | } 200 | if (!lessThanTests()) { 201 | std::cout << "Failed Less Than Test" << std::endl; 202 | return false; 203 | } 204 | if (!greaterThanTests()) { 205 | std::cout << "Failed Greater Than Test" << std::endl; 206 | return false; 207 | } 208 | if (!lessThanOrEqTests()) { 209 | std::cout << "Failed Less Than Or Equal To Test" << std::endl; 210 | return false; 211 | } 212 | if (!greaterThanOrEqTests()) { 213 | std::cout << "Failed Greater Than Or Equal To Test" << std::endl; 214 | return false; 215 | } 216 | if (!eqOrNotEqTests()) { 217 | std::cout << "Failed Equal Or Not Equal To Test" << std::endl; 218 | return false; 219 | } 220 | 221 | return true; 222 | } 223 | 224 | int main(int argc, char* argv[]) 225 | { 226 | bool pass = test(); 227 | if (pass) std::cout << "All Tests Passed" << std::endl; 228 | 229 | return 0; 230 | } 231 | -------------------------------------------------------------------------------- /canonical/ext/pcg32/Makefile: -------------------------------------------------------------------------------- 1 | pcg32-demo: pcg32-demo.cpp 2 | 3 | clean: 4 | rm -f pcg32-demo 5 | -------------------------------------------------------------------------------- /canonical/ext/pcg32/README.md: -------------------------------------------------------------------------------- 1 | # pcg32 2 | This is a tiny self-contained C++ implementation of the PCG32 random number 3 | based on code by Melissa O'Neill available at http://www.pcg-random.org. 4 | 5 | I decided to put together my own version because the official small 6 | implementation lacks a C++ interface and various important features (e.g. 7 | rewind/difference support, shuffling, floating point sample generation), while 8 | while the official C++ version is extremely complex and seems to be intended 9 | for research on PRNGs involving the entire PCG family. 10 | 11 | The file ``pcg32_8.h`` contains a vectorized implementation designed by myself 12 | which runs eight PCG32 PRNGs in parallel. Expect to get a ~3-4x speedup when 13 | generating single or double precision floats. 14 | 15 | Wenzel Jakob 16 | June 2016 17 | -------------------------------------------------------------------------------- /canonical/ext/pcg32/pcg32-demo.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * PCG Random Number Generation for C. 3 | * 4 | * Copyright 2014 Melissa O'Neill 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * For additional information about the PCG random number generation scheme, 19 | * including its license and other licensing options, visit 20 | * 21 | * http://www.pcg-random.org 22 | */ 23 | 24 | /* 25 | * This is the original demo application from the PCG library ported to the new API 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include "pcg32.h" 37 | 38 | int main(int argc, char** argv) { 39 | // Read command-line options 40 | int rounds = 5; 41 | 42 | if (argc > 1) 43 | rounds = atoi(argv[1]); 44 | 45 | pcg32 rng; 46 | 47 | // You should *always* seed the RNG. The usual time to do it is the 48 | // point in time when you create RNG (typically at the beginning of the 49 | // program). 50 | // 51 | // pcg32::seed takes two 64-bit constants (the initial state, and the 52 | // rng sequence selector; rngs with different sequence selectors will 53 | // *never* have random sequences that coincide, at all) 54 | rng.seed(42u, 54u); 55 | 56 | printf("pcg32_random_r:\n" 57 | " - result: 32-bit unsigned int (uint32_t)\n" 58 | " - period: 2^64 (* 2^63 streams)\n" 59 | " - state type: pcg32_random_t (%zu bytes)\n" 60 | " - output func: XSH-RR\n" 61 | "\n", 62 | sizeof(pcg32)); 63 | 64 | for (int round = 1; round <= rounds; ++round) { 65 | printf("Round %d:\n", round); 66 | /* Make some 32-bit numbers */ 67 | printf(" 32bit:"); 68 | for (int i = 0; i < 6; ++i) 69 | printf(" 0x%08x", rng.nextUInt()); 70 | printf("\n"); 71 | 72 | /* Toss some coins */ 73 | printf(" Coins: "); 74 | for (int i = 0; i < 65; ++i) 75 | printf("%c", rng.nextUInt(2) ? 'H' : 'T'); 76 | printf("\n"); 77 | 78 | /* Roll some dice */ 79 | printf(" Rolls:"); 80 | for (int i = 0; i < 33; ++i) { 81 | printf(" %d", (int)rng.nextUInt(6) + 1); 82 | } 83 | printf("\n"); 84 | 85 | /* Deal some cards */ 86 | enum { SUITS = 4, NUMBERS = 13, CARDS = 52 }; 87 | char cards[CARDS]; 88 | 89 | for (int i = 0; i < CARDS; ++i) 90 | cards[i] = i; 91 | 92 | rng.shuffle(cards, cards + CARDS); 93 | 94 | printf(" Cards:"); 95 | static const char number[] = {'A', '2', '3', '4', '5', '6', '7', 96 | '8', '9', 'T', 'J', 'Q', 'K'}; 97 | static const char suit[] = {'h', 'c', 'd', 's'}; 98 | for (int i = 0; i < CARDS; ++i) { 99 | printf(" %c%c", number[cards[i] / SUITS], suit[cards[i] % SUITS]); 100 | if ((i + 1) % 22 == 0) 101 | printf("\n\t"); 102 | } 103 | printf("\n"); 104 | 105 | printf("\n"); 106 | } 107 | 108 | return 0; 109 | } 110 | -------------------------------------------------------------------------------- /canonical/ext/pcg32/pcg32-demo.out: -------------------------------------------------------------------------------- 1 | pcg32_random_r: 2 | - result: 32-bit unsigned int (uint32_t) 3 | - period: 2^64 (* 2^63 streams) 4 | - state type: pcg32_random_t (16 bytes) 5 | - output func: XSH-RR 6 | 7 | Round 1: 8 | 32bit: 0xa15c02b7 0x7b47f409 0xba1d3330 0x83d2f293 0xbfa4784b 0xcbed606e 9 | Coins: HHTTTHTHHHTHTTTHHHHHTTTHHHTHTHTHTTHTTTHHHHHHTTTTHHTTTTTHTTTTTTTHT 10 | Rolls: 3 4 1 1 2 2 3 2 4 3 2 4 3 3 5 2 3 1 3 1 5 1 4 1 5 6 4 6 6 2 6 3 3 11 | Cards: Qd Ks 6d 3s 3d 4c 3h Td Kc 5c Jh Kd Jd As 4s 4h Ad Th Ac Jc 7s Qs 12 | 2s 7h Kh 2d 6c Ah 4d Qh 9h 6s 5s 2c 9c Ts 8d 9s 3c 8c Js 5d 2h 6h 13 | 7d 8s 9d 5h 8h Qc 7c Tc 14 | 15 | Round 2: 16 | 32bit: 0x74ab93ad 0x1c1da000 0x494ff896 0x34462f2f 0xd308a3e5 0x0fa83bab 17 | Coins: HHHHHHHHHHTHHHTHTHTHTHTTTTHHTTTHHTHHTHTTHHTTTHHHHHHTHTTHTHTTTTTTT 18 | Rolls: 5 1 1 3 3 2 4 5 3 2 2 6 4 3 2 4 2 4 3 2 3 6 3 2 3 4 2 4 1 1 5 4 4 19 | Cards: 7d 2s 7h Td 8s 3c 3d Js 2d Tc 4h Qs 5c 9c Th 2c Jc Qd 9d Qc 7s 3s 20 | 5s 6h 4d Jh 4c Ac 4s 5h 5d Kc 8h 8d Jd 9s Ad 6s 6c Kd 2h 3h Kh Ts 21 | Qh 9h 6d As 7c Ks Ah 8c 22 | 23 | Round 3: 24 | 32bit: 0x39af5f9f 0x04196b18 0xc3c3eb28 0xc076c60c 0xc693e135 0xf8f63932 25 | Coins: HTTHHTTTTTHTTHHHTHTTHHTTHTHHTHTHTTTTHHTTTHHTHHTTHTTHHHTHHHTHTTTHT 26 | Rolls: 5 1 5 3 2 2 4 5 3 3 1 3 4 6 3 2 3 4 2 2 3 1 5 2 4 6 6 4 2 4 3 3 6 27 | Cards: Kd Jh Kc Qh 4d Qc 4h 9d 3c Kh Qs 8h 5c Jd 7d 8d 3h 7c 8s 3s 2h Ks 28 | 9c 9h 2c 8c Ad 7s 4s 2s 5h 6s 4c Ah 7h 5s Ac 3d 5d Qd As Tc 6h 9s 29 | 2d 6c 6d Td Jc Ts Th Js 30 | 31 | Round 4: 32 | 32bit: 0x55ce6851 0x97a7726d 0x17e10815 0x58007d43 0x962fb148 0xb9bb55bd 33 | Coins: HHTHHTTTTHTHHHHHTTHHHTTTHHTHTHTHTHHTTHTHHHHHHTHHTHHTHHTTTTHHTHHTT 34 | Rolls: 6 6 3 2 3 4 2 6 4 2 6 3 2 3 5 5 3 4 4 6 6 2 6 5 4 4 6 1 6 1 3 6 5 35 | Cards: Qd 8h 5d 8s 8d Ts 7h Th Qs Js 7s Kc 6h 5s 4d Ac Jd 7d 7c Td 2c 6s 36 | 5h 6d 3s Kd 9s Jh Kh As Ah 9h 3c Qh 9c 2d Tc 9d 2s 3d Ks 4h Qc Ad 37 | Jc 8c 2h 3h 4s 4c 5c 6c 38 | 39 | Round 5: 40 | 32bit: 0xfcef7cd6 0x1b488b5a 0xd0daf7ea 0x1d9a70f7 0x241a37cf 0x9a3857b7 41 | Coins: HHHHTHHTTHTTHHHTTTHHTHTHTTTTHTTHTHTTTHHHTHTHTTHTTHTHHTHTHHHTHTHTT 42 | Rolls: 5 4 1 2 6 1 3 1 5 6 3 6 2 1 4 4 5 2 1 5 6 5 6 4 4 4 5 2 6 4 3 5 6 43 | Cards: 4d 9s Qc 9h As Qs 7s 4c Kd 6h 6s 2c 8c 5d 7h 5h Jc 3s 7c Jh Js Ks 44 | Tc Jd Kc Th 3h Ts Qh Ad Td 3c Ah 2d 3d 5c Ac 8s 5s 9c 2h 6c 6d Kh 45 | Qd 8d 7d 2s 8h 4h 9d 4s 46 | 47 | -------------------------------------------------------------------------------- /canonical/ext/pcg32/pcg32.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Tiny self-contained version of the PCG Random Number Generation for C++ 3 | * put together from pieces of the much larger C/C++ codebase. 4 | * Wenzel Jakob, February 2015 5 | * 6 | * The PCG random number generator was developed by Melissa O'Neill 7 | * 8 | * 9 | * Licensed under the Apache License, Version 2.0 (the "License"); 10 | * you may not use this file except in compliance with the License. 11 | * You may obtain a copy of the License at 12 | * 13 | * http://www.apache.org/licenses/LICENSE-2.0 14 | * 15 | * Unless required by applicable law or agreed to in writing, software 16 | * distributed under the License is distributed on an "AS IS" BASIS, 17 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 | * See the License for the specific language governing permissions and 19 | * limitations under the License. 20 | * 21 | * For additional information about the PCG random number generation scheme, 22 | * including its license and other licensing options, visit 23 | * 24 | * http://www.pcg-random.org 25 | */ 26 | 27 | #ifndef __PCG32_H 28 | #define __PCG32_H 1 29 | 30 | #define PCG32_DEFAULT_STATE 0x853c49e6748fea9bULL 31 | #define PCG32_DEFAULT_STREAM 0xda3e39cb94b95bdbULL 32 | #define PCG32_MULT 0x5851f42d4c957f2dULL 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | /// PCG32 Pseudorandom number generator 40 | struct pcg32 { 41 | /// Initialize the pseudorandom number generator with default seed 42 | pcg32() : state(PCG32_DEFAULT_STATE), inc(PCG32_DEFAULT_STREAM) {} 43 | 44 | /// Initialize the pseudorandom number generator with the \ref seed() function 45 | pcg32(uint64_t initstate, uint64_t initseq = 1u) { seed(initstate, initseq); } 46 | 47 | /** 48 | * \brief Seed the pseudorandom number generator 49 | * 50 | * Specified in two parts: a state initializer and a sequence selection 51 | * constant (a.k.a. stream id) 52 | */ 53 | void seed(uint64_t initstate, uint64_t initseq = 1) { 54 | state = 0U; 55 | inc = (initseq << 1u) | 1u; 56 | nextUInt(); 57 | state += initstate; 58 | nextUInt(); 59 | } 60 | 61 | /// Generate a uniformly distributed unsigned 32-bit random number 62 | uint32_t nextUInt() { 63 | uint64_t oldstate = state; 64 | state = oldstate * PCG32_MULT + inc; 65 | uint32_t xorshifted = (uint32_t) (((oldstate >> 18u) ^ oldstate) >> 27u); 66 | uint32_t rot = (uint32_t) (oldstate >> 59u); 67 | return (xorshifted >> rot) | (xorshifted << ((~rot + 1u) & 31)); 68 | } 69 | 70 | /// Generate a uniformly distributed number, r, where 0 <= r < bound 71 | uint32_t nextUInt(uint32_t bound) { 72 | // To avoid bias, we need to make the range of the RNG a multiple of 73 | // bound, which we do by dropping output less than a threshold. 74 | // A naive scheme to calculate the threshold would be to do 75 | // 76 | // uint32_t threshold = 0x100000000ull % bound; 77 | // 78 | // but 64-bit div/mod is slower than 32-bit div/mod (especially on 79 | // 32-bit platforms). In essence, we do 80 | // 81 | // uint32_t threshold = (0x100000000ull-bound) % bound; 82 | // 83 | // because this version will calculate the same modulus, but the LHS 84 | // value is less than 2^32. 85 | 86 | uint32_t threshold = (~bound+1u) % bound; 87 | 88 | // Uniformity guarantees that this loop will terminate. In practice, it 89 | // should usually terminate quickly; on average (assuming all bounds are 90 | // equally likely), 82.25% of the time, we can expect it to require just 91 | // one iteration. In the worst case, someone passes a bound of 2^31 + 1 92 | // (i.e., 2147483649), which invalidates almost 50% of the range. In 93 | // practice, bounds are typically small and only a tiny amount of the range 94 | // is eliminated. 95 | for (;;) { 96 | uint32_t r = nextUInt(); 97 | if (r >= threshold) 98 | return r % bound; 99 | } 100 | } 101 | 102 | /// Generate a single precision floating point value on the interval [0, 1) 103 | float nextFloat() { 104 | /* Trick from MTGP: generate an uniformly distributed 105 | single precision number in [1,2) and subtract 1. */ 106 | union { 107 | uint32_t u; 108 | float f; 109 | } x; 110 | x.u = (nextUInt() >> 9) | 0x3f800000u; 111 | return x.f - 1.0f; 112 | } 113 | 114 | /** 115 | * \brief Generate a double precision floating point value on the interval [0, 1) 116 | * 117 | * \remark Since the underlying random number generator produces 32 bit output, 118 | * only the first 32 mantissa bits will be filled (however, the resolution is still 119 | * finer than in \ref nextFloat(), which only uses 23 mantissa bits) 120 | */ 121 | double nextDouble() { 122 | /* Trick from MTGP: generate an uniformly distributed 123 | double precision number in [1,2) and subtract 1. */ 124 | union { 125 | uint64_t u; 126 | double d; 127 | } x; 128 | x.u = ((uint64_t) nextUInt() << 20) | 0x3ff0000000000000ULL; 129 | return x.d - 1.0; 130 | } 131 | 132 | /** 133 | * \brief Multi-step advance function (jump-ahead, jump-back) 134 | * 135 | * The method used here is based on Brown, "Random Number Generation 136 | * with Arbitrary Stride", Transactions of the American Nuclear 137 | * Society (Nov. 1994). The algorithm is very similar to fast 138 | * exponentiation. 139 | */ 140 | void advance(int64_t delta_) { 141 | uint64_t 142 | cur_mult = PCG32_MULT, 143 | cur_plus = inc, 144 | acc_mult = 1u, 145 | acc_plus = 0u; 146 | 147 | /* Even though delta is an unsigned integer, we can pass a signed 148 | integer to go backwards, it just goes "the long way round". */ 149 | uint64_t delta = (uint64_t) delta_; 150 | 151 | while (delta > 0) { 152 | if (delta & 1) { 153 | acc_mult *= cur_mult; 154 | acc_plus = acc_plus * cur_mult + cur_plus; 155 | } 156 | cur_plus = (cur_mult + 1) * cur_plus; 157 | cur_mult *= cur_mult; 158 | delta /= 2; 159 | } 160 | state = acc_mult * state + acc_plus; 161 | } 162 | 163 | /** 164 | * \brief Draw uniformly distributed permutation and permute the 165 | * given STL container 166 | * 167 | * From: Knuth, TAoCP Vol. 2 (3rd 3d), Section 3.4.2 168 | */ 169 | template void shuffle(Iterator begin, Iterator end) { 170 | for (Iterator it = end - 1; it > begin; --it) 171 | std::iter_swap(it, begin + nextUInt((uint32_t) (it - begin + 1))); 172 | } 173 | 174 | /// Compute the distance between two PCG32 pseudorandom number generators 175 | int64_t operator-(const pcg32 &other) const { 176 | assert(inc == other.inc); 177 | 178 | uint64_t 179 | cur_mult = PCG32_MULT, 180 | cur_plus = inc, 181 | cur_state = other.state, 182 | the_bit = 1u, 183 | distance = 0u; 184 | 185 | while (state != cur_state) { 186 | if ((state & the_bit) != (cur_state & the_bit)) { 187 | cur_state = cur_state * cur_mult + cur_plus; 188 | distance |= the_bit; 189 | } 190 | assert((state & the_bit) == (cur_state & the_bit)); 191 | the_bit <<= 1; 192 | cur_plus = (cur_mult + 1ULL) * cur_plus; 193 | cur_mult *= cur_mult; 194 | } 195 | 196 | return (int64_t) distance; 197 | } 198 | 199 | /// Equality operator 200 | bool operator==(const pcg32 &other) const { return state == other.state && inc == other.inc; } 201 | 202 | /// Inequality operator 203 | bool operator!=(const pcg32 &other) const { return state != other.state || inc != other.inc; } 204 | 205 | uint64_t state; // RNG state. All values are possible. 206 | uint64_t inc; // Controls which RNG sequence (stream) is selected. Must *always* be odd. 207 | }; 208 | 209 | #endif // __PCG32_H 210 | -------------------------------------------------------------------------------- /canonical/ext/pcg32/pcg32_8.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Vectorized AVX2 version of the PCG32 random number generator developed by 3 | * Wenzel Jakob (June 2016) 4 | * 5 | * The PCG random number generator was developed by Melissa O'Neill 6 | * 7 | * 8 | * Licensed under the Apache License, Version 2.0 (the "License"); 9 | * you may not use this file except in compliance with the License. 10 | * You may obtain a copy of the License at 11 | * 12 | * http://www.apache.org/licenses/LICENSE-2.0 13 | * 14 | * Unless required by applicable law or agreed to in writing, software 15 | * distributed under the License is distributed on an "AS IS" BASIS, 16 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 | * See the License for the specific language governing permissions and 18 | * limitations under the License. 19 | * 20 | * For additional information about the PCG random number generation scheme, 21 | * including its license and other licensing options, visit 22 | * 23 | * http://www.pcg-random.org 24 | */ 25 | 26 | #include "pcg32.h" 27 | #include 28 | #include 29 | 30 | #if defined(_MSC_VER) 31 | # define PCG32_ALIGN(amt) __declspec(align(amt)) 32 | # define PCG32_VECTORCALL __vectorcall 33 | # define PCG32_INLINE __forceinline 34 | #else 35 | # define PCG32_ALIGN(amt) __attribute__ ((aligned(amt))) 36 | # define PCG32_INLINE __attribute__ ((always_inline)) 37 | # if defined(__clang__) 38 | # define PCG32_VECTORCALL __attribute__ ((vectorcall)) 39 | # else 40 | # define PCG32_VECTORCALL 41 | # endif 42 | #endif 43 | 44 | /// 8 parallel PCG32 pseudorandom number generators 45 | struct PCG32_ALIGN(32) pcg32_8 { 46 | 47 | #if defined(__AVX2__) 48 | __m256i state[2]; // RNG state. All values are possible. 49 | __m256i inc[2]; // Controls which RNG sequence (stream) is selected. Must *always* be odd. 50 | #else 51 | /* Scalar fallback */ 52 | pcg32 rng[8]; 53 | #endif 54 | 55 | /// Initialize the pseudorandom number generator with default seed 56 | pcg32_8() { 57 | PCG32_ALIGN(32) uint64_t initstate[8] = { 58 | PCG32_DEFAULT_STATE, PCG32_DEFAULT_STATE, 59 | PCG32_DEFAULT_STATE, PCG32_DEFAULT_STATE, 60 | PCG32_DEFAULT_STATE, PCG32_DEFAULT_STATE, 61 | PCG32_DEFAULT_STATE, PCG32_DEFAULT_STATE 62 | }; 63 | 64 | PCG32_ALIGN(32) uint64_t initseq[8] = 65 | { 1, 2, 3, 4, 5, 6, 7, 8 }; 66 | 67 | seed(initstate, initseq); 68 | } 69 | 70 | /// Initialize the pseudorandom number generator with the \ref seed() function 71 | pcg32_8(const uint64_t initstate[8], const uint64_t initseq[8]) { 72 | seed(initstate, initseq); 73 | } 74 | 75 | 76 | #if defined(__AVX2__) 77 | /** 78 | * \brief Seed the pseudorandom number generator 79 | * 80 | * Specified in two parts: a state initializer and a sequence selection 81 | * constant (a.k.a. stream id) 82 | */ 83 | void seed(const uint64_t initstate[8], const uint64_t initseq[8]) { 84 | const __m256i one = _mm256_set1_epi64x((long long) 1); 85 | 86 | state[0] = state[1] = _mm256_setzero_si256(); 87 | inc[0] = _mm256_or_si256( 88 | _mm256_slli_epi64(_mm256_load_si256((__m256i *) &initseq[0]), 1), 89 | one); 90 | inc[1] = _mm256_or_si256( 91 | _mm256_slli_epi64(_mm256_load_si256((__m256i *) &initseq[4]), 1), 92 | one); 93 | step(); 94 | 95 | state[0] = _mm256_add_epi64(state[0], _mm256_load_si256((__m256i *) &initstate[0])); 96 | state[1] = _mm256_add_epi64(state[1], _mm256_load_si256((__m256i *) &initstate[4])); 97 | 98 | step(); 99 | } 100 | 101 | /// Generate 8 uniformly distributed unsigned 32-bit random numbers 102 | void nextUInt(uint32_t result[8]) { 103 | _mm256_store_si256((__m256i *) result, step()); 104 | } 105 | 106 | /// Generate 8 uniformly distributed unsigned 32-bit random numbers 107 | __m256i PCG32_VECTORCALL nextUInt() { 108 | return step(); 109 | } 110 | 111 | /// Generate eight single precision floating point value on the interval [0, 1) 112 | __m256 PCG32_VECTORCALL nextFloat() { 113 | /* Trick from MTGP: generate an uniformly distributed 114 | single precision number in [1,2) and subtract 1. */ 115 | 116 | const __m256i const1 = _mm256_set1_epi32((int) 0x3f800000u); 117 | 118 | __m256i value = step(); 119 | __m256i fltval = _mm256_or_si256(_mm256_srli_epi32(value, 9), const1); 120 | 121 | return _mm256_sub_ps(_mm256_castsi256_ps(fltval), 122 | _mm256_castsi256_ps(const1)); 123 | } 124 | 125 | /// Generate eight single precision floating point value on the interval [0, 1) 126 | void nextFloat(float result[8]) { 127 | _mm256_store_ps(result, nextFloat()); 128 | } 129 | 130 | /** 131 | * \brief Generate eight double precision floating point value on the interval [0, 1) 132 | * 133 | * \remark Since the underlying random number generator produces 32 bit output, 134 | * only the first 32 mantissa bits will be filled (however, the resolution is still 135 | * finer than in \ref nextFloat(), which only uses 23 mantissa bits) 136 | */ 137 | std::pair<__m256d, __m256d> nextDouble() { 138 | /* Trick from MTGP: generate an uniformly distributed 139 | double precision number in [1,2) and subtract 1. */ 140 | 141 | const __m256i const1 = 142 | _mm256_set1_epi64x((long long) 0x3ff0000000000000ull); 143 | 144 | __m256i value = step(); 145 | 146 | __m256i lo = _mm256_cvtepu32_epi64(_mm256_castsi256_si128(value)); 147 | __m256i hi = _mm256_cvtepu32_epi64(_mm256_extractf128_si256(value, 1)); 148 | 149 | __m256i tlo = _mm256_or_si256(_mm256_slli_epi64(lo, 20), const1); 150 | __m256i thi = _mm256_or_si256(_mm256_slli_epi64(hi, 20), const1); 151 | 152 | __m256d flo = _mm256_sub_pd(_mm256_castsi256_pd(tlo), 153 | _mm256_castsi256_pd(const1)); 154 | 155 | __m256d fhi = _mm256_sub_pd(_mm256_castsi256_pd(thi), 156 | _mm256_castsi256_pd(const1)); 157 | 158 | return std::make_pair(flo, fhi); 159 | } 160 | 161 | /** 162 | * \brief Generate eight double precision floating point value on the interval [0, 1) 163 | * 164 | * \remark Since the underlying random number generator produces 32 bit output, 165 | * only the first 32 mantissa bits will be filled (however, the resolution is still 166 | * finer than in \ref nextFloat(), which only uses 23 mantissa bits) 167 | */ 168 | void nextDouble(double result[8]) { 169 | std::pair<__m256d, __m256d> value = nextDouble(); 170 | 171 | _mm256_store_pd(&result[0], value.first); 172 | _mm256_store_pd(&result[4], value.second); 173 | } 174 | 175 | private: 176 | PCG32_INLINE __m256i PCG32_VECTORCALL step() { 177 | const __m256i pcg32_mult_l = _mm256_set1_epi64x((long long) (PCG32_MULT & 0xffffffffu)); 178 | const __m256i pcg32_mult_h = _mm256_set1_epi64x((long long) (PCG32_MULT >> 32)); 179 | const __m256i mask_l = _mm256_set1_epi64x((long long) 0x00000000ffffffffull); 180 | const __m256i shift0 = _mm256_set_epi32(7, 7, 7, 7, 6, 4, 2, 0); 181 | const __m256i shift1 = _mm256_set_epi32(6, 4, 2, 0, 7, 7, 7, 7); 182 | const __m256i const32 = _mm256_set1_epi32(32); 183 | 184 | __m256i s0 = state[0], s1 = state[1]; 185 | 186 | /* Extract low and high words for partial products below */ 187 | __m256i s0_l = _mm256_and_si256(s0, mask_l); 188 | __m256i s0_h = _mm256_srli_epi64(s0, 32); 189 | __m256i s1_l = _mm256_and_si256(s1, mask_l); 190 | __m256i s1_h = _mm256_srli_epi64(s1, 32); 191 | 192 | /* Improve high bits using xorshift step */ 193 | __m256i s0s = _mm256_srli_epi64(s0, 18); 194 | __m256i s1s = _mm256_srli_epi64(s1, 18); 195 | 196 | __m256i s0x = _mm256_xor_si256(s0s, s0); 197 | __m256i s1x = _mm256_xor_si256(s1s, s1); 198 | 199 | __m256i s0xs = _mm256_srli_epi64(s0x, 27); 200 | __m256i s1xs = _mm256_srli_epi64(s1x, 27); 201 | 202 | __m256i xors0 = _mm256_and_si256(mask_l, s0xs); 203 | __m256i xors1 = _mm256_and_si256(mask_l, s1xs); 204 | 205 | /* Use high bits to choose a bit-level rotation */ 206 | __m256i rot0 = _mm256_srli_epi64(s0, 59); 207 | __m256i rot1 = _mm256_srli_epi64(s1, 59); 208 | 209 | /* 64 bit multiplication using 32 bit partial products :( */ 210 | __m256i m0_hl = _mm256_mul_epu32(s0_h, pcg32_mult_l); 211 | __m256i m1_hl = _mm256_mul_epu32(s1_h, pcg32_mult_l); 212 | __m256i m0_lh = _mm256_mul_epu32(s0_l, pcg32_mult_h); 213 | __m256i m1_lh = _mm256_mul_epu32(s1_l, pcg32_mult_h); 214 | 215 | /* Assemble lower 32 bits, will be merged into one 256 bit vector below */ 216 | xors0 = _mm256_permutevar8x32_epi32(xors0, shift0); 217 | rot0 = _mm256_permutevar8x32_epi32(rot0, shift0); 218 | xors1 = _mm256_permutevar8x32_epi32(xors1, shift1); 219 | rot1 = _mm256_permutevar8x32_epi32(rot1, shift1); 220 | 221 | /* Continue with partial products */ 222 | __m256i m0_ll = _mm256_mul_epu32(s0_l, pcg32_mult_l); 223 | __m256i m1_ll = _mm256_mul_epu32(s1_l, pcg32_mult_l); 224 | 225 | __m256i m0h = _mm256_add_epi64(m0_hl, m0_lh); 226 | __m256i m1h = _mm256_add_epi64(m1_hl, m1_lh); 227 | 228 | __m256i m0hs = _mm256_slli_epi64(m0h, 32); 229 | __m256i m1hs = _mm256_slli_epi64(m1h, 32); 230 | 231 | __m256i s0n = _mm256_add_epi64(m0hs, m0_ll); 232 | __m256i s1n = _mm256_add_epi64(m1hs, m1_ll); 233 | 234 | __m256i xors = _mm256_or_si256(xors0, xors1); 235 | __m256i rot = _mm256_or_si256(rot0, rot1); 236 | 237 | state[0] = _mm256_add_epi64(s0n, inc[0]); 238 | state[1] = _mm256_add_epi64(s1n, inc[1]); 239 | 240 | /* Finally, rotate and return the result */ 241 | __m256i result = _mm256_or_si256( 242 | _mm256_srlv_epi32(xors, rot), 243 | _mm256_sllv_epi32(xors, _mm256_sub_epi32(const32, rot)) 244 | ); 245 | 246 | return result; 247 | } 248 | #else 249 | /** 250 | * \brief Seed the pseudorandom number generator 251 | * 252 | * Specified in two parts: a state initializer and a sequence selection 253 | * constant (a.k.a. stream id) 254 | */ 255 | void seed(const uint64_t initstate[8], const uint64_t initseq[8]) { 256 | for (int i = 0; i < 8; ++i) 257 | rng[i].seed(initstate[i], initseq[i]); 258 | } 259 | 260 | /// Generate 8 uniformly distributed unsigned 32-bit random numbers 261 | void nextUInt(uint32_t result[8]) { 262 | for (int i = 0; i < 8; ++i) 263 | result[i] = rng[i].nextUInt(); 264 | } 265 | 266 | /// Generate eight single precision floating point value on the interval [0, 1) 267 | void nextFloat(float result[8]) { 268 | for (int i = 0; i < 8; ++i) 269 | result[i] = rng[i].nextFloat(); 270 | } 271 | 272 | /** 273 | * \brief Generate eight double precision floating point value on the interval [0, 1) 274 | * 275 | * \remark Since the underlying random number generator produces 32 bit output, 276 | * only the first 32 mantissa bits will be filled (however, the resolution is still 277 | * finer than in \ref nextFloat(), which only uses 23 mantissa bits) 278 | */ 279 | void nextDouble(double result[8]) { 280 | for (int i = 0; i < 8; ++i) 281 | result[i] = rng[i].nextDouble(); 282 | } 283 | #endif 284 | }; 285 | -------------------------------------------------------------------------------- /canonical/extinctions/constFunc.cpp: -------------------------------------------------------------------------------- 1 | #include "constFunc.h" 2 | 3 | ConstFunc::ConstFunc() { 4 | c = 1.0; 5 | } 6 | 7 | ConstFunc::ConstFunc(Float c) : c(c) { } 8 | 9 | Float ConstFunc::evalFunction(Float x, Float a, Float b) const { 10 | return c; 11 | } 12 | 13 | Float ConstFunc::calculateIntegral(Float a, Float b) const { 14 | return c * (b - a); 15 | } 16 | 17 | Float ConstFunc::calculateVariance(Float a, Float b) const { 18 | return 0.0; 19 | } 20 | 21 | Float ConstFunc::calculateMaxValue(Float a, Float b) const { 22 | return c; 23 | } 24 | 25 | Float ConstFunc::calculateMinValue(Float a, Float b) const { 26 | return c; 27 | } 28 | 29 | Float ConstFunc::calculateMinEfficiency() const { 30 | return 0.01; 31 | } 32 | 33 | Float ConstFunc::calculateMaxEfficiency() const { 34 | return 0.95; 35 | } 36 | 37 | void ConstFunc::solveForIntegral(Float a, Float b, Float area) { 38 | c = area / (b - a); 39 | preProcess(a, b); 40 | } 41 | 42 | Func* ConstFunc::copy() const { 43 | ConstFunc* newFunc = new ConstFunc(); 44 | 45 | newFunc->c = c; 46 | newFunc->integral = integral; 47 | newFunc->variance = variance; 48 | newFunc->min = min; 49 | newFunc->max = max; 50 | 51 | return newFunc; 52 | } 53 | 54 | string ConstFunc::getName(FuncType type) const { 55 | if (type == FUNC_MAJORANT) { 56 | return "maj_const"; 57 | } else if (type == FUNC_MINORANT) { 58 | return "min_const"; 59 | } else if (type == FUNC_EXTINCTION) { 60 | return "const"; 61 | } else { 62 | return "const"; 63 | } 64 | } 65 | 66 | bool ConstFunc::needsDependent() const { 67 | return false; 68 | } 69 | 70 | Float ConstFunc::getC() const { return c; } 71 | 72 | // setter methods 73 | void ConstFunc::setC(Float param) { c = param; } 74 | -------------------------------------------------------------------------------- /canonical/extinctions/constFunc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "func.h" 4 | 5 | class ConstFunc : public Func { 6 | public: 7 | ConstFunc(); 8 | 9 | // debugging constructor 10 | ConstFunc(Float c); 11 | 12 | virtual Float evalFunction(Float x, Float a = 0.0, Float b = 1.0) const; 13 | 14 | virtual Float calculateMinEfficiency() const; 15 | virtual Float calculateMaxEfficiency() const; 16 | 17 | virtual void solveForIntegral(Float a, Float b, Float area); 18 | 19 | virtual Func* copy() const; 20 | 21 | virtual string getName(FuncType type) const; 22 | 23 | virtual bool needsDependent() const; 24 | 25 | // getter methods 26 | Float getC() const; 27 | 28 | // setter methods 29 | void setC(Float param); 30 | protected: 31 | virtual Float calculateMaxValue(Float a, Float b) const; 32 | virtual Float calculateMinValue(Float a, Float b) const; 33 | virtual Float calculateIntegral(Float a, Float b) const; 34 | virtual Float calculateVariance(Float a, Float b) const; 35 | 36 | Float c; 37 | }; 38 | -------------------------------------------------------------------------------- /canonical/extinctions/cosFunc.cpp: -------------------------------------------------------------------------------- 1 | #include "cosFunc.h" 2 | #include "../util.h" 3 | 4 | CosFunc::CosFunc() { 5 | h = 0.8; 6 | s = 20.0; 7 | k = 0.0; 8 | y = 0.8; 9 | } 10 | 11 | Float CosFunc::evalFunction(Float x, Float a, Float b) const { 12 | return h * Util::COS(s * x + k) + y; 13 | } 14 | 15 | Float CosFunc::calculateIntegral(Float a, Float b) const { 16 | Float bcomp = (h / s) * Util::SIN(s * b + k) + y * b; 17 | Float acomp = (h / s) * Util::SIN(s * a + k) + y * a; 18 | return bcomp - acomp; 19 | } 20 | 21 | Float CosFunc::calculateVariance(Float a, Float b) const { 22 | // TODO 23 | return 0.0; 24 | } 25 | 26 | Float CosFunc::calculateMaxValue(Float a, Float b) const { 27 | return h + y; 28 | } 29 | 30 | Float CosFunc::calculateMinValue(Float a, Float b) const { 31 | return y - h; 32 | } 33 | 34 | Float CosFunc::calculateMinEfficiency() const { 35 | return 0.01; 36 | } 37 | 38 | Float CosFunc::calculateMaxEfficiency() const { 39 | return 0.45; 40 | } 41 | 42 | void CosFunc::solveForIntegral(Float a, Float b, Float area) { 43 | h = 10000000000000000.0; 44 | 45 | y = area / (b - a); 46 | if (h > y) h = y; 47 | 48 | Func::solveForIntegral(a, b, area); 49 | } 50 | 51 | Func* CosFunc::copy() const { 52 | CosFunc* newFunc = new CosFunc(); 53 | 54 | newFunc->h = h; 55 | newFunc->s = s; 56 | newFunc->k = k; 57 | newFunc->y = y; 58 | newFunc->integral = integral; 59 | newFunc->variance = variance; 60 | newFunc->min = min; 61 | newFunc->max = max; 62 | 63 | return newFunc; 64 | } 65 | 66 | string CosFunc::getName(FuncType type) const { 67 | if (type == FUNC_MAJORANT) { 68 | return "maj_cos"; 69 | } 70 | else if (type == FUNC_MINORANT) { 71 | return "min_cos"; 72 | } 73 | else if (type == FUNC_EXTINCTION) { 74 | return "cos"; 75 | } 76 | 77 | return "cos"; 78 | } 79 | 80 | bool CosFunc::needsDependent() const { 81 | return false; 82 | } 83 | 84 | void CosFunc::setH(Float param) { h = param; } 85 | void CosFunc::setS(Float param) { s = param; } 86 | void CosFunc::setK(Float param) { k = param; } 87 | void CosFunc::setY(Float param) { y = param; } 88 | -------------------------------------------------------------------------------- /canonical/extinctions/cosFunc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "func.h" 4 | 5 | class CosFunc : public Func { 6 | public: 7 | CosFunc(); 8 | 9 | virtual Float evalFunction(Float x, Float a = 0.0, Float b = 1.0) const; 10 | 11 | virtual Float calculateMinEfficiency() const; 12 | virtual Float calculateMaxEfficiency() const; 13 | 14 | virtual void solveForIntegral(Float a, Float b, Float area); 15 | 16 | virtual Func* copy() const; 17 | 18 | virtual string getName(FuncType type) const; 19 | 20 | virtual bool needsDependent() const; 21 | 22 | // setter methods 23 | void setH(Float param); 24 | void setS(Float param); 25 | void setK(Float param); 26 | void setY(Float param); 27 | protected: 28 | virtual Float calculateMaxValue(Float a, Float b) const; 29 | virtual Float calculateMinValue(Float a, Float b) const; 30 | virtual Float calculateIntegral(Float a, Float b) const; 31 | virtual Float calculateVariance(Float a, Float b) const; 32 | 33 | Float h; 34 | Float s; 35 | Float k; 36 | Float y; 37 | }; 38 | -------------------------------------------------------------------------------- /canonical/extinctions/extinctionFunc.cpp: -------------------------------------------------------------------------------- 1 | #include "extinctionFunc.h" 2 | #include "constFunc.h" 3 | #include "tightConstFunc.h" 4 | 5 | Extinction::Extinction() { 6 | a = 0.0; 7 | b = 1.0; 8 | extinctionFunction = nullptr; 9 | majorantFunction = nullptr; 10 | minorantFunction = nullptr; 11 | } 12 | 13 | Extinction::~Extinction() { 14 | delete extinctionFunction; 15 | delete minorantFunction; 16 | delete majorantFunction; 17 | } 18 | 19 | Float Extinction::calculateExtinction(Float x, int& extCalls) const { 20 | extCalls++; 21 | return extinctionFunction->evalFunction(x, a, b); 22 | } 23 | 24 | Float Extinction::calculateExtinction(Float x, bool log) const { 25 | return extinctionFunction->evalFunction(x, a, b); 26 | } 27 | 28 | Float Extinction::calculateExtinctionIntegral(Float a, Float b) const { 29 | return extinctionFunction->getIntegral(); 30 | } 31 | 32 | Float Extinction::calculateExtinctionVariance(Float a, Float b) const { 33 | return extinctionFunction->getVariance(); 34 | } 35 | 36 | Float Extinction::calculateAverageExtinction(Float a, Float b) const { 37 | return extinctionFunction->getIntegral() / (b - a); 38 | } 39 | 40 | Float Extinction::calculateMajorant(Float x) const { 41 | return majorantFunction->evalFunction(x, a, b); 42 | } 43 | 44 | Float Extinction::calculateMajorantIntegral(Float a, Float b) const { 45 | // if (b == this->b) // this seems very fishy 46 | // return majorantFunction->getIntegral(); 47 | return majorantFunction->evalIntegral(a, b); 48 | } 49 | 50 | Float Extinction::calculateMajorantVariance(Float a, Float b) const { 51 | return majorantFunction->getVariance(); 52 | } 53 | 54 | Float Extinction::calculateMajorantAverage(Float a, Float b) const { 55 | return majorantFunction->getIntegral() / (b - a); 56 | } 57 | 58 | Float Extinction::calculateMinorant(Float x) const { 59 | return minorantFunction->evalFunction(x, a, b); 60 | } 61 | 62 | Float Extinction::calculateMinorantIntegral(Float a, Float b) const { 63 | // if (b == this->b) 64 | // return majorantFunction->getIntegral(); 65 | return majorantFunction->evalIntegral(a, b); 66 | } 67 | 68 | Float Extinction::calculateMinorantVariance(Float a, Float b) const { 69 | return minorantFunction->getVariance(); 70 | } 71 | 72 | Float Extinction::calculateMinorantAverage(Float a, Float b) const { 73 | return minorantFunction->getIntegral() / (b - a); 74 | } 75 | 76 | Float Extinction::calculateMinMajorantEfficiency() const { 77 | return extinctionFunction->calculateMinEfficiency(); 78 | } 79 | 80 | Float Extinction::calculateMaxMajorantEfficiency() const { 81 | return extinctionFunction->calculateMaxEfficiency(); 82 | } 83 | 84 | void Extinction::setOpticalDepth(Float c) { 85 | extinctionFunction->solveForIntegral(a, b, c); 86 | // TODO: majorant / minorants ??? 87 | } 88 | 89 | Float Extinction::calculateMaxExtinction(Float a, Float b) const { 90 | return extinctionFunction->getMax(); 91 | } 92 | 93 | Float Extinction::calculateMinExtinction(Float a, Float b) const { 94 | return extinctionFunction->getMin(); 95 | } 96 | 97 | void Extinction::preProcess() { 98 | // cout << "what" << endl; 99 | extinctionFunction->preProcess(a, b); 100 | // cout << "who" << endl; 101 | majorantFunction->preProcess(a, b); 102 | // cout << "where" << endl; 103 | minorantFunction->preProcess(a, b); 104 | // cout << "which" << endl; 105 | } 106 | 107 | Extinction* Extinction::copy() const { 108 | Extinction* newFunc = new Extinction(); 109 | 110 | newFunc->setA(a); 111 | newFunc->setB(b); 112 | newFunc->setExtinctionFunction(extinctionFunction->copy()); 113 | newFunc->setMajorantFunction(majorantFunction->copy()); 114 | newFunc->setMinorantFunction(minorantFunction->copy()); 115 | 116 | // cout << "post copy" << endl; 117 | 118 | if (newFunc->getMajorantFunction()->needsDependent()) 119 | { 120 | newFunc->getMajorantFunction()->setDependent(newFunc->getExtinctionFunction()); 121 | } 122 | 123 | if (newFunc->getMinorantFunction()->needsDependent()) 124 | { 125 | newFunc->getMinorantFunction()->setDependent(newFunc->getExtinctionFunction()); 126 | } 127 | 128 | return newFunc; 129 | } 130 | 131 | string Extinction::getName() const { 132 | return extinctionFunction->getName(FUNC_EXTINCTION); 133 | } 134 | 135 | // getter methods 136 | Func* Extinction::getExtinctionFunction() const { return extinctionFunction; } 137 | Func* Extinction::getMajorantFunction() const { return majorantFunction; } 138 | Func* Extinction::getMinorantFunction() const { return minorantFunction; } 139 | 140 | // setter methods 141 | void Extinction::setExtinctionFunction(Func* param) { 142 | // if (extinctionFunction) delete extinctionFunction; 143 | extinctionFunction = param; 144 | } 145 | 146 | void Extinction::setMajorantFunction(Func* param) { 147 | // if (majorantFunction) delete majorantFunction; 148 | majorantFunction = param; 149 | } 150 | 151 | void Extinction::setMinorantFunction(Func* param) { 152 | // if (minorantFunction) delete minorantFunction; 153 | minorantFunction = param; 154 | } 155 | 156 | Float Extinction::getA() const { return a; } 157 | Float Extinction::getB() const { return b; } 158 | 159 | void Extinction::setA(Float param) { a = param; } 160 | void Extinction::setB(Float param) { b = param; } 161 | -------------------------------------------------------------------------------- /canonical/extinctions/extinctionFunc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../common.h" 4 | #include "func.h" 5 | 6 | class Extinction { 7 | public: 8 | Extinction(); 9 | ~Extinction(); 10 | 11 | Float calculateExtinction(Float x, int& extCalls) const; 12 | Float calculateExtinction(Float x, bool log) const; 13 | Float calculateExtinctionIntegral(Float a, Float b) const; 14 | Float calculateExtinctionVariance(Float a, Float b) const; 15 | Float calculateAverageExtinction(Float a, Float b) const; 16 | 17 | Float calculateMajorant(Float x) const; 18 | Float calculateMajorantIntegral(Float a, Float b) const; 19 | Float calculateMajorantVariance(Float a, Float b) const; 20 | Float calculateMajorantAverage(Float a, Float b) const; 21 | 22 | Float calculateMinorant(Float x) const; 23 | Float calculateMinorantIntegral(Float a, Float b) const; 24 | Float calculateMinorantVariance(Float a, Float b) const; 25 | Float calculateMinorantAverage(Float a, Float b) const; 26 | 27 | void setOpticalDepth(Float c); 28 | 29 | void preProcess(); 30 | 31 | Float calculateMaxExtinction(Float a, Float b) const; 32 | Float calculateMinExtinction(Float a, Float b) const; 33 | 34 | Float calculateMinMajorantEfficiency() const; 35 | Float calculateMaxMajorantEfficiency() const; 36 | 37 | Extinction* copy() const; 38 | string getName() const; 39 | 40 | // getter methods 41 | Func* getExtinctionFunction() const; 42 | Func* getMajorantFunction() const; 43 | Func* getMinorantFunction() const; 44 | Float getA() const; 45 | Float getB() const; 46 | 47 | // setter methods 48 | void setExtinctionFunction(Func* param); 49 | void setMajorantFunction(Func* param); 50 | void setMinorantFunction(Func* param); 51 | void setA(Float param); 52 | void setB(Float param); 53 | protected: 54 | Func* extinctionFunction; 55 | Func* majorantFunction; 56 | Func* minorantFunction; 57 | 58 | Float a; 59 | Float b; 60 | }; 61 | -------------------------------------------------------------------------------- /canonical/extinctions/func.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../common.h" 4 | 5 | enum FuncType { 6 | FUNC_MAJORANT, 7 | FUNC_MINORANT, 8 | FUNC_EXTINCTION 9 | }; 10 | 11 | class Func { 12 | public: 13 | virtual ~Func() { } 14 | 15 | virtual Float evalFunction(Float x, Float a, Float b) const = 0; 16 | 17 | virtual Float evalIntegral(Float a, Float b) const 18 | { 19 | return calculateIntegral(a, b); 20 | } 21 | 22 | virtual Float calculateMinEfficiency() const = 0; 23 | virtual Float calculateMaxEfficiency() const = 0; 24 | 25 | virtual void solveForIntegral(Float a, Float b, Float area) 26 | { 27 | preProcess(a, b); 28 | } 29 | 30 | // speed improvements 31 | void preProcess(Float a, Float b) 32 | { 33 | integral = calculateIntegral(a, b); 34 | variance = calculateVariance(a, b); 35 | min = calculateMinValue(a, b); 36 | max = calculateMaxValue(a, b); 37 | } 38 | 39 | virtual Func* copy() const = 0; 40 | virtual bool needsDependent() const = 0; 41 | 42 | virtual void setDependent(Func* param) { } 43 | virtual void declareMajorant() { } 44 | virtual void declareMinorant() { } 45 | 46 | virtual string getName(FuncType type) const = 0; 47 | 48 | Float getIntegral() const { return integral; } 49 | Float getVariance() const { return variance; } 50 | Float getMin() const { return min; } 51 | Float getMax() const { return max; } 52 | 53 | protected: 54 | virtual Float calculateMaxValue(Float a, Float b) const = 0; 55 | virtual Float calculateMinValue(Float a, Float b) const = 0; 56 | virtual Float calculateIntegral(Float a, Float b) const = 0; 57 | virtual Float calculateVariance(Float a, Float b) const = 0; 58 | 59 | // cached data 60 | Float integral; 61 | Float variance; 62 | Float min; 63 | Float max; 64 | }; 65 | -------------------------------------------------------------------------------- /canonical/extinctions/gaussFunc.cpp: -------------------------------------------------------------------------------- 1 | #include "gaussFunc.h" 2 | #include "../util.h" 3 | 4 | GaussFunc::GaussFunc() { 5 | h = 1.0; 6 | sig = 1.0; 7 | m = 0.5; 8 | } 9 | 10 | Float GaussFunc::evalFunction(Float x, Float a, Float b) const { 11 | Float exponent = (x - m) * (x - m) / (2.0 * sig * sig); 12 | return h * Util::EXP(-exponent); 13 | } 14 | 15 | Float GaussFunc::calculateIntegral(Float a, Float b) const { 16 | Float sum = 0.0; 17 | Float stepSize = (b - a) / RESOLUTION; 18 | 19 | for (Float i = 0.0; i < b; i += stepSize) { 20 | sum += stepSize * evalFunction(i, a, b); 21 | } 22 | 23 | return sum; 24 | } 25 | 26 | Float GaussFunc::calculateVariance(Float a, Float b) const { 27 | return sig; 28 | } 29 | 30 | Float GaussFunc::calculateMaxValue(Float a, Float b) const { 31 | return h; 32 | } 33 | 34 | Float GaussFunc::calculateMinValue(Float a, Float b) const { 35 | return std::min(evalFunction(a, a, b), evalFunction(b, a, b)); 36 | } 37 | 38 | Float GaussFunc::calculateMinEfficiency() const { 39 | return 0.01; 40 | } 41 | 42 | Float GaussFunc::calculateMaxEfficiency() const { 43 | return 0.12; 44 | } 45 | 46 | void GaussFunc::solveForIntegral(Float a, Float b, Float area) { 47 | Float currentArea = calculateIntegral(a, b); 48 | Float newh = area * h / currentArea; 49 | h = newh; 50 | Func::solveForIntegral(a, b, area); 51 | } 52 | 53 | Func* GaussFunc::copy() const { 54 | GaussFunc* newFunc = new GaussFunc(); 55 | 56 | newFunc->h = h; 57 | newFunc->m = m; 58 | newFunc->sig = sig; 59 | newFunc->integral = integral; 60 | newFunc->variance = variance; 61 | newFunc->min = min; 62 | newFunc->max = max; 63 | 64 | return newFunc; 65 | } 66 | 67 | string GaussFunc::getName(FuncType type) const { 68 | if (type == FUNC_MAJORANT) { 69 | return "maj_gauss"; 70 | } 71 | else if (type == FUNC_MINORANT) { 72 | return "min_gauss"; 73 | } 74 | else if (type == FUNC_EXTINCTION) { 75 | return "gauss"; 76 | } 77 | 78 | return "gauss"; 79 | } 80 | 81 | bool GaussFunc::needsDependent() const { 82 | return false; 83 | } 84 | 85 | void GaussFunc::setH(Float param) { h = param; } 86 | void GaussFunc::setM(Float param) { m = param; } 87 | void GaussFunc::setSig(Float param) { sig = param; } 88 | -------------------------------------------------------------------------------- /canonical/extinctions/gaussFunc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "func.h" 4 | 5 | class GaussFunc : public Func { 6 | public: 7 | GaussFunc(); 8 | 9 | virtual Float evalFunction(Float x, Float a = 0.0, Float b = 1.0) const; 10 | 11 | virtual Float calculateMinEfficiency() const; 12 | virtual Float calculateMaxEfficiency() const; 13 | 14 | virtual void solveForIntegral(Float a, Float b, Float area); 15 | 16 | virtual Func* copy() const; 17 | 18 | virtual string getName(FuncType type) const; 19 | 20 | virtual bool needsDependent() const; 21 | 22 | // setter methods 23 | void setM(Float param); 24 | void setH(Float param); 25 | void setSig(Float param); 26 | protected: 27 | virtual Float calculateMaxValue(Float a, Float b) const; 28 | virtual Float calculateMinValue(Float a, Float b) const; 29 | virtual Float calculateIntegral(Float a, Float b) const; 30 | virtual Float calculateVariance(Float a, Float b) const; 31 | 32 | Float m; 33 | Float h; 34 | Float sig; 35 | }; 36 | -------------------------------------------------------------------------------- /canonical/extinctions/holeFunc.cpp: -------------------------------------------------------------------------------- 1 | #include "holeFunc.h" 2 | #include "../util.h" 3 | 4 | HoleFunc::HoleFunc() { 5 | h = 1.0; 6 | sig = 1.0; 7 | m = 0.5; 8 | c = 1.0; 9 | } 10 | 11 | Float HoleFunc::evalFunction(Float x, Float a, Float b) const { 12 | Float exponent = (x - m) * (x - m) / (2.0 * sig * sig); 13 | return c - h * Util::EXP(-exponent); 14 | } 15 | 16 | Float HoleFunc::gaussFunction(Float x, Float a, Float b) const { 17 | Float exponent = (x - m) * (x - m) / (2.0 * sig * sig); 18 | return h * Util::EXP(-exponent); 19 | } 20 | 21 | Float HoleFunc::calculateIntegral(Float a, Float b) const { 22 | Float sum = 0.0; 23 | Float stepSize = (b - a) / RESOLUTION; 24 | 25 | for (Float i = 0.0; i < b; i += stepSize) { 26 | sum += stepSize * evalFunction(i, a, b); 27 | } 28 | 29 | return sum; 30 | } 31 | 32 | Float HoleFunc::gaussArea(Float a, Float b) const { 33 | Float sum = 0.0; 34 | Float stepSize = (b - a) / RESOLUTION; 35 | 36 | for (Float i = 0.0; i < b; i += stepSize) { 37 | sum += stepSize * gaussFunction(i, a, b); 38 | } 39 | 40 | return sum; 41 | } 42 | 43 | Float HoleFunc::calculateVariance(Float a, Float b) const { 44 | // TODO 45 | 46 | return 0.0; 47 | } 48 | 49 | Float HoleFunc::calculateMaxValue(Float a, Float b) const { 50 | return c; 51 | } 52 | 53 | Float HoleFunc::calculateMinValue(Float a, Float b) const { 54 | return c - h; 55 | } 56 | 57 | Float HoleFunc::calculateMinEfficiency() const { 58 | return 0.01; 59 | } 60 | 61 | Float HoleFunc::calculateMaxEfficiency() const { 62 | return 0.85; 63 | } 64 | 65 | void HoleFunc::solveForIntegral(Float a, Float b, Float area) { 66 | Float gArea = gaussArea(a, b); 67 | 68 | Float newC = (area + gArea) / (b - a); 69 | 70 | h = 100.0; 71 | 72 | if (newC > h) c = newC; 73 | else 74 | { 75 | for (int i = 0; i < 5; ++i) 76 | { 77 | Float currentArea = calculateIntegral(a, b); 78 | Float newH = area * c / (currentArea); 79 | c = newH; 80 | h = newH; 81 | } 82 | } 83 | } 84 | 85 | Func* HoleFunc::copy() const { 86 | HoleFunc* newFunc = new HoleFunc(); 87 | 88 | newFunc->h = h; 89 | newFunc->m = m; 90 | newFunc->sig = sig; 91 | newFunc->c = c; 92 | newFunc->integral = integral; 93 | newFunc->variance = variance; 94 | newFunc->min = min; 95 | newFunc->max = max; 96 | 97 | return newFunc; 98 | } 99 | 100 | string HoleFunc::getName(FuncType type) const { 101 | if (type == FUNC_MAJORANT) { 102 | return "maj_hole"; 103 | } 104 | else if (type == FUNC_MINORANT) { 105 | return "min_hole"; 106 | } 107 | else if (type == FUNC_EXTINCTION) { 108 | return "hole"; 109 | } 110 | 111 | return "hole"; 112 | } 113 | 114 | bool HoleFunc::needsDependent() const { 115 | return false; 116 | } 117 | 118 | void HoleFunc::setH(Float param) { h = param; } 119 | void HoleFunc::setM(Float param) { m = param; } 120 | void HoleFunc::setSig(Float param) { sig = param; } 121 | void HoleFunc::setC(Float param) { c = param; } 122 | -------------------------------------------------------------------------------- /canonical/extinctions/holeFunc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "func.h" 4 | #include "constFunc.h" 5 | #include "gaussFunc.h" 6 | 7 | class HoleFunc : public Func 8 | { 9 | public: 10 | HoleFunc(); 11 | 12 | virtual Float evalFunction(Float x, Float a = 0.0, Float b = 1.0) const; 13 | Float gaussFunction(Float x, Float a = 0.0, Float b = 1.0) const; 14 | Float gaussArea(Float a, Float b) const; 15 | 16 | virtual Float calculateMinEfficiency() const; 17 | virtual Float calculateMaxEfficiency() const; 18 | 19 | virtual void solveForIntegral(Float a, Float b, Float area); 20 | 21 | virtual Func* copy() const; 22 | 23 | virtual string getName(FuncType type) const; 24 | 25 | virtual bool needsDependent() const; 26 | 27 | void setC(Float param); 28 | void setM(Float param); 29 | void setSig(Float param); 30 | void setH(Float param); 31 | 32 | protected: 33 | virtual Float calculateMaxValue(Float a, Float b) const; 34 | virtual Float calculateMinValue(Float a, Float b) const; 35 | virtual Float calculateIntegral(Float a, Float b) const; 36 | virtual Float calculateVariance(Float a, Float b) const; 37 | 38 | Float c; 39 | Float m; 40 | Float h; 41 | Float sig; 42 | }; 43 | -------------------------------------------------------------------------------- /canonical/extinctions/lin_dec.cpp: -------------------------------------------------------------------------------- 1 | #include "lin_dec.h" 2 | 3 | LinDecFunc::LinDecFunc() { 4 | m = 1.0; 5 | y = 0.0; 6 | } 7 | 8 | Float LinDecFunc::evalFunction(Float x, Float a, Float b) const { 9 | Float val = m * x + y; 10 | return (val < 0.0) ? 0.0 : val; 11 | } 12 | 13 | Float LinDecFunc::calculateIntegral(Float a, Float b) const { 14 | Float bcomp = 0.5 * m * b * b + b * y; 15 | Float acomp = 0.5 * m * a * a + a * y; 16 | return bcomp - acomp; 17 | } 18 | 19 | Float LinDecFunc::calculateVariance(Float a, Float b) const { 20 | // TODO 21 | return 0.0; 22 | } 23 | 24 | Float LinDecFunc::calculateMaxValue(Float a, Float b) const { 25 | if (m > 0.0) return evalFunction(b); 26 | return evalFunction(a); 27 | } 28 | 29 | Float LinDecFunc::calculateMinValue(Float a, Float b) const { 30 | if (m > 0.0) return evalFunction(a); 31 | return evalFunction(b); 32 | } 33 | 34 | Float LinDecFunc::calculateMinEfficiency() const { 35 | return 0.01; 36 | } 37 | 38 | Float LinDecFunc::calculateMaxEfficiency() const { 39 | return 0.45; 40 | } 41 | 42 | void LinDecFunc::solveForIntegral(Float a, Float b, Float area) { 43 | y = 2.0 * area; 44 | m = -2.0 * area; 45 | 46 | Func::solveForIntegral(a, b, area); 47 | } 48 | 49 | Func* LinDecFunc::copy() const { 50 | LinDecFunc* newFunc = new LinDecFunc(); 51 | 52 | newFunc->setM(m); 53 | newFunc->setY(y); 54 | 55 | newFunc->m = m; 56 | newFunc->y = y; 57 | newFunc->integral = integral; 58 | newFunc->variance = variance; 59 | newFunc->min = min; 60 | newFunc->max = max; 61 | 62 | return newFunc; 63 | } 64 | 65 | string LinDecFunc::getName(FuncType type) const { 66 | if (type == FUNC_MAJORANT) { 67 | return "maj_lin_dec"; 68 | } 69 | else if (type == FUNC_MINORANT) { 70 | return "min_lin_dec"; 71 | } 72 | else if (type == FUNC_EXTINCTION) { 73 | return "lin_dec"; 74 | } 75 | 76 | return "lin_dec"; 77 | } 78 | 79 | bool LinDecFunc::needsDependent() const { 80 | return false; 81 | } 82 | 83 | void LinDecFunc::setM(Float param) { m = param; } 84 | void LinDecFunc::setY(Float param) { y = param; } 85 | -------------------------------------------------------------------------------- /canonical/extinctions/lin_dec.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "func.h" 4 | 5 | class LinDecFunc : public Func { 6 | public: 7 | LinDecFunc(); 8 | 9 | virtual Float evalFunction(Float x, Float a = 0.0, Float b = 1.0) const; 10 | 11 | virtual Float calculateMinEfficiency() const; 12 | virtual Float calculateMaxEfficiency() const; 13 | 14 | virtual void solveForIntegral(Float a, Float b, Float area); 15 | 16 | virtual Func* copy() const; 17 | 18 | virtual string getName(FuncType type) const; 19 | 20 | virtual bool needsDependent() const; 21 | 22 | // setter methods 23 | void setM(Float param); 24 | void setY(Float param); 25 | 26 | protected: 27 | virtual Float calculateMaxValue(Float a, Float b) const; 28 | virtual Float calculateMinValue(Float a, Float b) const; 29 | virtual Float calculateIntegral(Float a, Float b) const; 30 | virtual Float calculateVariance(Float a, Float b) const; 31 | 32 | Float m; 33 | Float y; 34 | }; 35 | -------------------------------------------------------------------------------- /canonical/extinctions/lin_inc.cpp: -------------------------------------------------------------------------------- 1 | #include "lin_inc.h" 2 | 3 | LinIncFunc::LinIncFunc() { 4 | m = 1.0; 5 | y = 0.0; 6 | } 7 | 8 | Float LinIncFunc::evalFunction(Float x, Float a, Float b) const { 9 | Float val = m * x + y; 10 | return (val < 0.0) ? 0.0 : val; 11 | } 12 | 13 | Float LinIncFunc::calculateIntegral(Float a, Float b) const { 14 | Float bcomp = 0.5 * m * b * b + b * y; 15 | Float acomp = 0.5 * m * a * a + a * y; 16 | return bcomp - acomp; 17 | } 18 | 19 | Float LinIncFunc::calculateVariance(Float a, Float b) const { 20 | // TODO 21 | return 0.0; 22 | } 23 | 24 | Float LinIncFunc::calculateMaxValue(Float a, Float b) const { 25 | if (m > 0.0) return evalFunction(b); 26 | return evalFunction(a); 27 | } 28 | 29 | Float LinIncFunc::calculateMinValue(Float a, Float b) const { 30 | if (m > 0.0) return evalFunction(a); 31 | return evalFunction(b); 32 | } 33 | 34 | Float LinIncFunc::calculateMinEfficiency() const { 35 | return 0.01; 36 | } 37 | 38 | Float LinIncFunc::calculateMaxEfficiency() const { 39 | return 0.45; 40 | } 41 | 42 | void LinIncFunc::solveForIntegral(Float a, Float b, Float area) { 43 | y = 0; 44 | m = 2.0 * area; 45 | Func::solveForIntegral(a, b, area); 46 | } 47 | 48 | Func* LinIncFunc::copy() const { 49 | LinIncFunc* newFunc = new LinIncFunc(); 50 | 51 | newFunc->setM(m); 52 | newFunc->setY(y); 53 | 54 | newFunc->m = m; 55 | newFunc->y = y; 56 | newFunc->integral = integral; 57 | newFunc->variance = variance; 58 | newFunc->min = min; 59 | newFunc->max = max; 60 | 61 | return newFunc; 62 | } 63 | 64 | string LinIncFunc::getName(FuncType type) const { 65 | if (type == FUNC_MAJORANT) { 66 | return "maj_lin_inc"; 67 | } 68 | else if (type == FUNC_MINORANT) { 69 | return "min_lin_inc"; 70 | } 71 | else if (type == FUNC_EXTINCTION) { 72 | return "lin_inc"; 73 | } 74 | 75 | return "lin_inc"; 76 | } 77 | 78 | bool LinIncFunc::needsDependent() const { 79 | return false; 80 | } 81 | 82 | void LinIncFunc::setM(Float param) { m = param; } 83 | void LinIncFunc::setY(Float param) { y = param; } 84 | -------------------------------------------------------------------------------- /canonical/extinctions/lin_inc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "func.h" 4 | 5 | class LinIncFunc : public Func { 6 | public: 7 | LinIncFunc(); 8 | 9 | virtual Float evalFunction(Float x, Float a = 0.0, Float b = 1.0) const; 10 | 11 | virtual Float calculateMinEfficiency() const; 12 | virtual Float calculateMaxEfficiency() const; 13 | 14 | virtual void solveForIntegral(Float a, Float b, Float area); 15 | 16 | virtual Func* copy() const; 17 | 18 | virtual string getName(FuncType type) const; 19 | 20 | virtual bool needsDependent() const; 21 | 22 | // setter methods 23 | void setM(Float param); 24 | void setY(Float param); 25 | 26 | protected: 27 | virtual Float calculateMaxValue(Float a, Float b) const; 28 | virtual Float calculateMinValue(Float a, Float b) const; 29 | virtual Float calculateIntegral(Float a, Float b) const; 30 | virtual Float calculateVariance(Float a, Float b) const; 31 | 32 | Float m; 33 | Float y; 34 | }; 35 | -------------------------------------------------------------------------------- /canonical/extinctions/nullRatioFunc.cpp: -------------------------------------------------------------------------------- 1 | #include "nullRatioFunc.h" 2 | #include "../util.h" 3 | 4 | NullRatioFunc::NullRatioFunc() { 5 | isMajorant = true; 6 | func = nullptr; 7 | ratio = 1.0; 8 | preProcessed = false; 9 | preProcessedG = 0.0; 10 | preProcessedMax = 0.0; 11 | } 12 | 13 | Float NullRatioFunc::evalFunction(Float x, Float a, Float b) const { 14 | Float majVal = func->getMax(); 15 | Float minVal = func->getMin(); 16 | Float area = func->getIntegral(); 17 | 18 | Float realArea = area; 19 | Float tightArea = majVal * (b - a); 20 | 21 | Float g = ((realArea / ratio) - tightArea) / (b - a); 22 | 23 | return g + majVal; 24 | } 25 | 26 | Float NullRatioFunc::calculateIntegral(Float a, Float b) const { 27 | return evalFunction((b - a) / 2.0, a, b) * (b - a); 28 | } 29 | 30 | Float NullRatioFunc::calculateVariance(Float a, Float b) const { 31 | return 0.0; 32 | } 33 | 34 | Float NullRatioFunc::calculateMaxValue(Float a, Float b) const { 35 | return evalFunction((b - a) / 2.0, a, b); 36 | } 37 | 38 | Float NullRatioFunc::calculateMinValue(Float a, Float b) const { 39 | return evalFunction((b - a) / 2.0, a, b); 40 | } 41 | 42 | Float NullRatioFunc::calculateMinEfficiency() const { 43 | // TODO 44 | return 0.0; 45 | } 46 | 47 | Float NullRatioFunc::calculateMaxEfficiency() const { 48 | // TODO 49 | return 0.0; 50 | } 51 | 52 | void NullRatioFunc::solveForIntegral(Float a, Float b, Float area) { 53 | // this can not be supported 54 | Func::solveForIntegral(a, b, area); 55 | } 56 | 57 | Func* NullRatioFunc::copy() const { 58 | NullRatioFunc* newFunc = new NullRatioFunc(); 59 | 60 | newFunc->isMajorant = isMajorant; 61 | newFunc->func = nullptr; 62 | newFunc->ratio = ratio; 63 | newFunc->preProcessed = false; 64 | newFunc->integral = integral; 65 | newFunc->variance = variance; 66 | newFunc->min = min; 67 | newFunc->max = max; 68 | 69 | return newFunc; 70 | } 71 | 72 | string NullRatioFunc::getName(FuncType type) const { 73 | if (type == FUNC_MAJORANT) { 74 | return "maj_null_ratio"; 75 | } 76 | else if (type == FUNC_MINORANT) { 77 | return "min_null_ratio"; 78 | } 79 | return "maj_null_ratio"; 80 | } 81 | 82 | bool NullRatioFunc::needsDependent() const { 83 | return true; 84 | } 85 | 86 | void NullRatioFunc::setDependent(Func* param) { 87 | func = param; 88 | } 89 | 90 | void NullRatioFunc::declareMajorant() { 91 | isMajorant = true; 92 | } 93 | 94 | void NullRatioFunc::declareMinorant() { 95 | isMajorant = false; 96 | } 97 | 98 | void NullRatioFunc::setIsMajorant(bool param) { isMajorant = param; } 99 | void NullRatioFunc::setRatio(Float param) { ratio = param; } 100 | -------------------------------------------------------------------------------- /canonical/extinctions/nullRatioFunc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "func.h" 4 | 5 | class NullRatioFunc : public Func { 6 | public: 7 | NullRatioFunc(); 8 | 9 | virtual Float evalFunction(Float x, Float a = 0.0, Float b = 1.0) const; 10 | 11 | virtual Float calculateMinEfficiency() const; 12 | virtual Float calculateMaxEfficiency() const; 13 | 14 | virtual void solveForIntegral(Float a, Float b, Float area); 15 | 16 | virtual Func* copy() const; 17 | 18 | virtual string getName(FuncType type) const; 19 | 20 | virtual bool needsDependent() const; 21 | virtual void setDependent(Func* param); 22 | virtual void declareMajorant(); 23 | virtual void declareMinorant(); 24 | 25 | // setter methods 26 | void setIsMajorant(bool param); 27 | void setRatio(Float param); 28 | protected: 29 | virtual Float calculateMaxValue(Float a, Float b) const; 30 | virtual Float calculateMinValue(Float a, Float b) const; 31 | virtual Float calculateIntegral(Float a, Float b) const; 32 | virtual Float calculateVariance(Float a, Float b) const; 33 | 34 | Float ratio; 35 | bool isMajorant; 36 | Func* func; 37 | 38 | Float preProcessedMax; 39 | Float preProcessedG; 40 | bool preProcessed; 41 | }; 42 | -------------------------------------------------------------------------------- /canonical/extinctions/scosFunc.cpp: -------------------------------------------------------------------------------- 1 | #include "scosFunc.h" 2 | #include "../util.h" 3 | 4 | ScosFunc::ScosFunc() { 5 | h = 0.8; 6 | s = 5.0; 7 | } 8 | 9 | Float ScosFunc::evalFunction(Float x, Float a, Float b) const { 10 | return h * Util::COS(s * x) + h; 11 | } 12 | 13 | Float ScosFunc::calculateIntegral(Float a, Float b) const { 14 | Float bcomp = (h / s) * Util::SIN(s * b) + h * b; 15 | Float acomp = (h / s) * Util::SIN(s * a) + h * a; 16 | return bcomp - acomp; 17 | } 18 | 19 | Float ScosFunc::calculateVariance(Float a, Float b) const { 20 | // TODO 21 | return 0.0; 22 | } 23 | 24 | Float ScosFunc::calculateMaxValue(Float a, Float b) const { 25 | return 2.0 * h; 26 | } 27 | 28 | Float ScosFunc::calculateMinValue(Float a, Float b) const { 29 | return 0.0; 30 | } 31 | 32 | Float ScosFunc::calculateMinEfficiency() const { 33 | return 0.01; 34 | } 35 | 36 | Float ScosFunc::calculateMaxEfficiency() const { 37 | return 0.45; 38 | } 39 | 40 | void ScosFunc::solveForIntegral(Float a, Float b, Float area) { 41 | Float bcomp = (1.0 / s) * sin(s * b) + b; 42 | Float acomp = (1.0 / s) * sin(s * a) + a; 43 | h = area / (bcomp - acomp); 44 | Func::solveForIntegral(a, b, area); 45 | } 46 | 47 | Func* ScosFunc::copy() const { 48 | ScosFunc* newFunc = new ScosFunc(); 49 | 50 | newFunc->setH(h); 51 | newFunc->setS(s); 52 | 53 | newFunc->h = h; 54 | newFunc->s = s; 55 | newFunc->integral = integral; 56 | newFunc->variance = variance; 57 | newFunc->min = min; 58 | newFunc->max = max; 59 | 60 | return newFunc; 61 | } 62 | 63 | string ScosFunc::getName(FuncType type) const { 64 | if (type == FUNC_MAJORANT) { 65 | return "maj_scos"; 66 | } 67 | else if (type == FUNC_MINORANT) { 68 | return "min_scos"; 69 | } 70 | else if (type == FUNC_EXTINCTION) { 71 | return "scos"; 72 | } 73 | 74 | return "scos"; 75 | } 76 | 77 | bool ScosFunc::needsDependent() const { 78 | return false; 79 | } 80 | 81 | void ScosFunc::setH(Float param) { h = param; } 82 | void ScosFunc::setS(Float param) { s = param; } 83 | -------------------------------------------------------------------------------- /canonical/extinctions/scosFunc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "func.h" 4 | 5 | class ScosFunc : public Func { 6 | public: 7 | ScosFunc(); 8 | 9 | virtual Float evalFunction(Float x, Float a = 0.0, Float b = 1.0) const; 10 | 11 | virtual Float calculateMinEfficiency() const; 12 | virtual Float calculateMaxEfficiency() const; 13 | 14 | virtual void solveForIntegral(Float a, Float b, Float area); 15 | 16 | virtual Func* copy() const; 17 | 18 | virtual string getName(FuncType type) const; 19 | 20 | virtual bool needsDependent() const; 21 | 22 | // setter methods 23 | void setH(Float param); 24 | void setS(Float param); 25 | protected: 26 | virtual Float calculateMaxValue(Float a, Float b) const; 27 | virtual Float calculateMinValue(Float a, Float b) const; 28 | virtual Float calculateIntegral(Float a, Float b) const; 29 | virtual Float calculateVariance(Float a, Float b) const; 30 | 31 | Float h; 32 | Float s; 33 | }; 34 | -------------------------------------------------------------------------------- /canonical/extinctions/tightConstFunc.cpp: -------------------------------------------------------------------------------- 1 | #include "tightConstFunc.h" 2 | 3 | TightConstFunc::TightConstFunc() { 4 | isMajorant = true; 5 | func = nullptr; 6 | } 7 | 8 | TightConstFunc::TightConstFunc(Func* func, bool isMajorant) 9 | : func(func), isMajorant(isMajorant) { } 10 | 11 | Float TightConstFunc::evalFunction(Float x, Float a, Float b) const { 12 | if (isMajorant) 13 | { 14 | return func->getMax(); 15 | } 16 | else 17 | { 18 | return func->getMin(); 19 | } 20 | } 21 | 22 | Float TightConstFunc::calculateIntegral(Float a, Float b) const { 23 | return evalFunction((b - a) / 2.0, a, b) * (b - a); 24 | } 25 | 26 | Float TightConstFunc::calculateVariance(Float a, Float b) const { 27 | return 0.0; 28 | } 29 | 30 | Float TightConstFunc::calculateMaxValue(Float a, Float b) const { 31 | return evalFunction((b + a) / 2.0, a, b); 32 | } 33 | 34 | Float TightConstFunc::calculateMinValue(Float a, Float b) const { 35 | return evalFunction((b + a) / 2.0, a, b); 36 | } 37 | 38 | Float TightConstFunc::calculateMinEfficiency() const { 39 | // TODO 40 | return 0.0; 41 | } 42 | 43 | Float TightConstFunc::calculateMaxEfficiency() const { 44 | // TODO 45 | return 0.0; 46 | } 47 | 48 | void TightConstFunc::solveForIntegral(Float a, Float b, Float area) { 49 | // this can not be supported 50 | Func::solveForIntegral(a, b, area); 51 | } 52 | 53 | Func* TightConstFunc::copy() const { 54 | TightConstFunc* newFunc = new TightConstFunc(); 55 | 56 | newFunc->setIsMajorant(isMajorant); 57 | newFunc->func = nullptr; 58 | newFunc->integral = integral; 59 | newFunc->variance = variance; 60 | newFunc->min = min; 61 | newFunc->max = max; 62 | 63 | return newFunc; 64 | } 65 | 66 | string TightConstFunc::getName(FuncType type) const { 67 | if (type == FUNC_MAJORANT) { 68 | return "maj_tight"; 69 | } 70 | else if (type == FUNC_MINORANT) { 71 | return "min_tight"; 72 | } 73 | return "maj_tight"; 74 | } 75 | 76 | bool TightConstFunc::needsDependent() const { 77 | return true; 78 | } 79 | 80 | void TightConstFunc::setDependent(Func* param) { 81 | // cout << "whim" << endl; 82 | func = param; 83 | } 84 | 85 | void TightConstFunc::declareMajorant() { 86 | isMajorant = true; 87 | } 88 | 89 | void TightConstFunc::declareMinorant() { 90 | isMajorant = false; 91 | } 92 | 93 | void TightConstFunc::setIsMajorant(bool param) { isMajorant = param; } 94 | -------------------------------------------------------------------------------- /canonical/extinctions/tightConstFunc.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "func.h" 4 | 5 | class TightConstFunc : public Func { 6 | public: 7 | TightConstFunc(); 8 | TightConstFunc(Func* func, bool isMajorant); 9 | 10 | virtual Float evalFunction(Float x, Float a = 0.0, Float b = 1.0) const; 11 | 12 | virtual Float calculateMinEfficiency() const; 13 | virtual Float calculateMaxEfficiency() const; 14 | 15 | virtual void solveForIntegral(Float a, Float b, Float area); 16 | 17 | virtual Func* copy() const; 18 | 19 | virtual string getName(FuncType type) const; 20 | 21 | virtual bool needsDependent() const; 22 | virtual void setDependent(Func* param); 23 | virtual void declareMajorant(); 24 | virtual void declareMinorant(); 25 | 26 | void setIsMajorant(bool param); 27 | protected: 28 | virtual Float calculateMaxValue(Float a, Float b) const; 29 | virtual Float calculateMinValue(Float a, Float b) const; 30 | virtual Float calculateIntegral(Float a, Float b) const; 31 | virtual Float calculateVariance(Float a, Float b) const; 32 | 33 | bool isMajorant; 34 | Func* func; 35 | }; 36 | -------------------------------------------------------------------------------- /canonical/floatimage.cpp: -------------------------------------------------------------------------------- 1 | /*! 2 | modified version of code from Wojciech Jarosz 3 | */ 4 | 5 | #include "floatimage.h" 6 | #include "util.h" 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | 13 | #define STB_IMAGE_IMPLEMENTATION 14 | #include "ext/stb/stb_image.h" 15 | 16 | #define STB_IMAGE_WRITE_IMPLEMENTATION 17 | #include "ext/stb/stb_image_write.h" 18 | 19 | using namespace std; 20 | 21 | namespace 22 | { 23 | 24 | string getExtension(const string &filename) 25 | { 26 | if (filename.find_last_of(".") != string::npos) 27 | return filename.substr(filename.find_last_of(".") + 1); 28 | return ""; 29 | } 30 | 31 | float byteToFloat(const unsigned char in) 32 | { 33 | return in / 255.0f; 34 | } 35 | 36 | unsigned char floatToByte(float in) 37 | { 38 | return int(255.0f * Util::clamp(in, 0.0f, 1.0f)); 39 | } 40 | 41 | } 42 | 43 | FloatImage::FloatImage() : Array3D() 44 | { 45 | // empty 46 | } 47 | 48 | FloatImage::FloatImage(int width, int height, int channels) : 49 | Array3D(width, height, channels) 50 | { 51 | // empty 52 | } 53 | 54 | FloatImage::FloatImage(const string &filename) : Array3D() 55 | { 56 | read(filename); 57 | } 58 | 59 | FloatImage::FloatImage(const FloatImage &in) : Array3D() 60 | { 61 | resize(in.width(), in.height(), in.depth()); 62 | m_data = in.m_data; 63 | } 64 | 65 | FloatImage &FloatImage::operator=(const FloatImage &in) 66 | { 67 | m_data = in.m_data; 68 | m_sizeX = in.m_sizeX; 69 | m_sizeY = in.m_sizeY; 70 | m_sizeZ = in.m_sizeZ; 71 | m_strideZ = in.m_strideZ; 72 | return *this; 73 | } 74 | 75 | void FloatImage::clear(const vector &channelValues) 76 | { 77 | for (int z = 0; z < sizeZ(); ++z) 78 | for (int y = 0; y < sizeY(); ++y) 79 | for (int x = 0; x < sizeX(); ++x) 80 | operator()(x, y, z) = channelValues[z]; 81 | } 82 | 83 | bool FloatImage::read(const string &filename) 84 | { 85 | int n, w, h; 86 | 87 | try 88 | { 89 | if (stbi_is_hdr(filename.c_str())) 90 | { 91 | float *floatPixels = stbi_loadf(filename.c_str(), &w, &h, &n, 3); 92 | if (floatPixels) 93 | { 94 | resize(w, h, 3); 95 | 96 | for (int x = 0; x < w; x++) 97 | for (int y = 0; y < h; y++) 98 | for (int c = 0; c < 3; c++) 99 | operator()(x, y, c) = floatPixels[3 * (x + y * w) + c]; 100 | 101 | stbi_image_free(floatPixels); 102 | return true; 103 | } 104 | else 105 | throw runtime_error("Could not load HDR image."); 106 | } 107 | else 108 | { 109 | unsigned char *bytePixels = stbi_load(filename.c_str(), &w, &h, &n, 3); 110 | if (bytePixels) 111 | { 112 | resize(w, h, 3); 113 | 114 | for (int x = 0; x < w; x++) 115 | for (int y = 0; y < h; y++) 116 | for (int c = 0; c < 3; c++) 117 | operator()(x, y, c) = byteToFloat(bytePixels[3 * (x + y * w) + c]); 118 | 119 | stbi_image_free(bytePixels); 120 | return true; 121 | } 122 | else 123 | throw runtime_error("Could not load LDR image."); 124 | } 125 | } 126 | catch (const exception &e) 127 | { 128 | cerr << "Image decoder error in FloatImage::read(...) for file: \"" << filename << "\":\n\t" 129 | << stbi_failure_reason() << endl; 130 | return false; 131 | } 132 | } 133 | 134 | bool FloatImage::write(const string &filename) const 135 | { 136 | if (channels() != 1 && channels() != 3 && channels() != 4) 137 | throw ChannelException(); 138 | 139 | string extension = getExtension(filename); 140 | transform(extension.begin(), 141 | extension.end(), 142 | extension.begin(), 143 | ::tolower); 144 | try 145 | { 146 | if (extension == "hdr") 147 | { 148 | // stbi_write_hdr expects color channels for a single pixel to be adjacent in memory 149 | vector floatPixels(height() * width() * 3, 1.0f); 150 | for (int x = 0; x < width(); x++) 151 | for (int y = 0; y < height(); y++) 152 | for (int c = 0; c < channels(); c++) 153 | floatPixels[c + x * 3 + y * 3 * width()] = operator()(x, y, c); 154 | 155 | if (!stbi_write_hdr(filename.c_str(), width(), height(), channels(), &floatPixels[0])) 156 | throw runtime_error("Could not write HDR image."); 157 | } 158 | else if (extension == "png" || 159 | extension == "bmp" || 160 | extension == "tga" || 161 | extension == "jpg" || extension == "jpeg") 162 | { 163 | int outputChannels = 4; 164 | vector bytePixels(height() * width() * outputChannels, 255); 165 | int c; 166 | for (int x = 0; x < width(); x++) 167 | for (int y = 0; y < height(); y++) 168 | { 169 | for (c = 0; c < channels(); c++) 170 | bytePixels[c + x * outputChannels + y * outputChannels * width()] = 171 | floatToByte(operator()(x, y, c)); 172 | 173 | for (; c < 3; c++) 174 | // Only executes when there is one channel 175 | bytePixels[c + x * outputChannels + y * outputChannels * width()] = 176 | floatToByte(operator()(x, y, 0)); 177 | } 178 | 179 | if (extension == "png") 180 | { 181 | if (!stbi_write_png(filename.c_str(), width(), height(), 182 | outputChannels, &bytePixels[0], 183 | sizeof(unsigned char) * width() * outputChannels)) 184 | throw runtime_error("Could not write PNG image."); 185 | } 186 | else if (extension == "bmp") 187 | { 188 | if (!stbi_write_bmp(filename.c_str(), width(), height(), outputChannels, &bytePixels[0])) 189 | throw runtime_error("Could not write BMP image."); 190 | } 191 | else if (extension == "tga") 192 | { 193 | if (!stbi_write_tga(filename.c_str(), width(), height(), outputChannels, &bytePixels[0])) 194 | throw runtime_error("Could not write TGA image."); 195 | } 196 | else if (extension == "jpg" || extension == "jpeg") 197 | { 198 | if (!stbi_write_jpg(filename.c_str(), width(), height(), outputChannels, &bytePixels[0], 100)) 199 | throw runtime_error("Could not write JPG image."); 200 | } 201 | } 202 | else if (extension == "txt") 203 | { 204 | // since hdr write is bugged I am added this to convert to exrs in pbrt 205 | std::ofstream file(filename); 206 | file << width() << "\n"; 207 | file << height() << "\n"; 208 | file << depth() << "\n"; 209 | 210 | for (int i = 0; i < size(); ++i) 211 | { 212 | file << operator()(i) << "\n"; 213 | } 214 | } 215 | else 216 | throw invalid_argument("Could not determine desired file type from extension."); 217 | } 218 | catch (const exception &e) 219 | { 220 | // if there's an error, display it 221 | cerr << "Error in FloatImage::write(...) for file: \"" << filename << "\":\n\t" << e.what() << endl; 222 | } 223 | 224 | return true; 225 | } 226 | 227 | void FloatImage::ratio(const FloatImage& one, const FloatImage& two, FloatImage& out, double exposure) { 228 | if (one.width() != two.width() || one.height() != two.height() || one.depth() != two.depth()) { 229 | cout << "ERROR: Input images are of different sizes" << endl; 230 | return; 231 | } 232 | 233 | for (int i = 0; i < one.height(); ++i) { 234 | for (int j = 0; j < one.width(); ++j) { 235 | for (int k = 0; k < one.depth(); ++k) { 236 | if (one(j, i, k) == 0.0) { 237 | out(j, i, k) = 0.0; 238 | } else { 239 | out(j, i, k) = two(j, i, k) / one(j, i, k) * exposure; 240 | } 241 | } 242 | } 243 | } 244 | } 245 | 246 | double FloatImage::mean(const FloatImage& image) { 247 | double mean = 0.0; 248 | 249 | for (int i = 0; i < image.size(); ++i) { 250 | mean += image(i); 251 | } 252 | 253 | mean /= double(image.size()); 254 | 255 | return mean; 256 | } 257 | 258 | double FloatImage::variance(const FloatImage& image) { 259 | double mean = FloatImage::mean(image); 260 | double variance = 0.0; 261 | 262 | for (int i = 0; i < image.size(); ++i) { 263 | variance += (image(i) - mean) * (image(i) - mean); 264 | } 265 | 266 | variance /= double(image.size() - 1); 267 | 268 | return variance; 269 | } 270 | 271 | void FloatImage::flipXAxis(const FloatImage& in, FloatImage& out) { 272 | for (int i = 0; i < in.height(); ++i) { 273 | for (int j = 0; j < in.width(); ++j) { 274 | out(in.width() - j - 1, i, 0) = in(j, i, 0); 275 | out(in.width() - j - 1, i, 1) = in(j, i, 1); 276 | out(in.width() - j - 1, i, 2) = in(j, i, 2); 277 | } 278 | } 279 | } 280 | 281 | void FloatImage::flipYAxis(const FloatImage& in, FloatImage& out) { 282 | for (int i = 0; i < in.height(); ++i) { 283 | for (int j = 0; j < in.width(); ++j) { 284 | out(j, in.height() - i - 1, 0) = in(j, i, 0); 285 | out(j, in.height() - i - 1, 1) = in(j, i, 1); 286 | out(j, in.height() - i - 1, 2) = in(j, i, 2); 287 | } 288 | } 289 | } 290 | -------------------------------------------------------------------------------- /canonical/floatimage.h: -------------------------------------------------------------------------------- 1 | /*! 2 | \file floatimage.h 3 | \brief Contains the definition of a floating-point image class with an arbitrary number of channels 4 | \author Wojciech Jarosz 5 | \author Zack Misso 6 | */ 7 | #pragma once 8 | 9 | #include "common.h" 10 | #include "array3D.h" 11 | #include 12 | 13 | //! Floating point image 14 | class FloatImage : public Array3D 15 | { 16 | public: 17 | //----------------------------------------------------------------------- 18 | //@{ \name Constructors, destructors, etc. 19 | //----------------------------------------------------------------------- 20 | FloatImage(); 21 | FloatImage(int width, int height, int channels); 22 | FloatImage(const std::string & filename); 23 | FloatImage(const FloatImage &other); 24 | FloatImage & operator=(const FloatImage &other); 25 | void clear(Float v = 0.0f) {reset(v);} 26 | void clear(const std::vector & channelValues); 27 | //@} 28 | 29 | int channels() const {return m_sizeZ;} 30 | 31 | static void ratio(const FloatImage& one, const FloatImage& two, FloatImage& out, double exposure = 1.0); 32 | static double mean(const FloatImage& image); 33 | static double variance(const FloatImage& image); 34 | 35 | static void flipXAxis(const FloatImage& in, FloatImage& out); 36 | static void flipYAxis(const FloatImage& in, FloatImage& out); 37 | 38 | //----------------------------------------------------------------------- 39 | //@{ \name Image I/O. 40 | //----------------------------------------------------------------------- 41 | bool read(const std::string &name); 42 | bool write(const std::string &name) const; 43 | //@} 44 | }; 45 | -------------------------------------------------------------------------------- /canonical/main.cpp: -------------------------------------------------------------------------------- 1 | #include "canonical_test.h" 2 | #include "floatimage.h" 3 | #include "base_includes.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | Extinction* create_cos_extinction() 12 | { 13 | CosFunc* cosFunc = new CosFunc(); 14 | cosFunc->setY(1.1); 15 | cosFunc->setS(20.0); 16 | cosFunc->setK(0.8); 17 | cosFunc->setH(0.4); 18 | NullRatioFunc* majFuncCos = new NullRatioFunc(); 19 | Extinction* cosExt = new Extinction(); 20 | cosExt->setExtinctionFunction(cosFunc); 21 | cosExt->setMajorantFunction(majFuncCos); 22 | cosExt->setMinorantFunction(new TightConstFunc(cosFunc, false)); 23 | majFuncCos->setDependent(cosFunc); 24 | 25 | return cosExt; 26 | } 27 | 28 | Extinction* create_const_extinction() 29 | { 30 | ConstFunc* constFunc = new ConstFunc(); 31 | NullRatioFunc* majFuncConst = new NullRatioFunc(); 32 | Extinction* constExt = new Extinction(); 33 | constExt->setExtinctionFunction(constFunc); 34 | constExt->setMajorantFunction(majFuncConst); 35 | constExt->setMinorantFunction(new TightConstFunc(constFunc, false)); 36 | return constExt; 37 | } 38 | 39 | Extinction* create_gauss_extinction() 40 | { 41 | GaussFunc* gaussFunc = new GaussFunc(); 42 | NullRatioFunc* majFuncGauss = new NullRatioFunc(); 43 | Extinction* gaussExt = new Extinction(); 44 | gaussFunc->setM(0.32); 45 | gaussFunc->setSig(0.05); 46 | gaussFunc->setH(0.8); 47 | gaussExt->setExtinctionFunction(gaussFunc); 48 | gaussExt->setMajorantFunction(majFuncGauss); 49 | gaussExt->setMinorantFunction(new TightConstFunc(gaussFunc, false)); 50 | return gaussExt; 51 | } 52 | 53 | Extinction* create_hole_extinction() 54 | { 55 | HoleFunc* holeFunc = new HoleFunc(); 56 | NullRatioFunc* majFuncHole = new NullRatioFunc(); 57 | Extinction* holeExt = new Extinction(); 58 | holeFunc->setM(0.32); 59 | holeFunc->setSig(0.05); 60 | holeFunc->setH(0.8); 61 | holeFunc->setC(1.0); 62 | holeExt->setExtinctionFunction(holeFunc); 63 | holeExt->setMajorantFunction(majFuncHole); 64 | holeExt->setMinorantFunction(new TightConstFunc(holeFunc, false)); 65 | return holeExt; 66 | } 67 | 68 | Extinction* create_lin_dec_extinction() 69 | { 70 | LinDecFunc* linDecFunc = new LinDecFunc(); 71 | NullRatioFunc* majFuncLinDec = new NullRatioFunc(); 72 | Extinction* linDecExt = new Extinction(); 73 | linDecExt->setExtinctionFunction(linDecFunc); 74 | linDecExt->setMajorantFunction(majFuncLinDec); 75 | linDecExt->setMinorantFunction(new TightConstFunc(linDecFunc, false)); 76 | return linDecExt; 77 | } 78 | 79 | Extinction* create_lin_inc_extinction() 80 | { 81 | LinIncFunc* linIncFunc = new LinIncFunc(); 82 | NullRatioFunc* majFuncLinInc = new NullRatioFunc(); 83 | Extinction* linIncExt = new Extinction(); 84 | linIncExt->setExtinctionFunction(linIncFunc); 85 | linIncExt->setMajorantFunction(majFuncLinInc); 86 | linIncExt->setMinorantFunction(new TightConstFunc(linIncFunc, false)); 87 | return linIncExt; 88 | } 89 | 90 | int main(int argc, char* argv[]) 91 | { 92 | std::cout << "hello world" << std::endl; 93 | 94 | std::vector extinctions = std::vector(); 95 | std::vector estimators = std::vector(); 96 | Sampler* sampler = new Independent(); 97 | 98 | std::string prefix = "."; 99 | long base_seed = 0x34da32d; 100 | bool equal_cost = false; 101 | uint32_t max_cost = 16384; 102 | uint32_t samples = 16; 103 | uint32_t trials = 16; 104 | uint32_t resolution = 512; 105 | 106 | for (int i = 1; i < argc; ++i) 107 | { 108 | // sampler setting 109 | if (strcmp(argv[i], "independent") == 0) 110 | { 111 | delete sampler; 112 | sampler = new Independent(); 113 | } 114 | else if (strcmp(argv[i], "halton") == 0) 115 | { 116 | delete sampler; 117 | sampler = new Halton(); 118 | } 119 | else if (strcmp(argv[i], "hammersley") == 0) 120 | { 121 | delete sampler; 122 | sampler = new Hammersley(); 123 | } 124 | else if (strcmp(argv[i], "latinip") == 0) 125 | { 126 | delete sampler; 127 | sampler = new LatinHyperCubesInPlace(); 128 | } 129 | 130 | // extinction setting 131 | else if (strcmp(argv[i], "const") == 0) 132 | { 133 | extinctions.push_back(create_const_extinction()); 134 | } 135 | else if (strcmp(argv[i], "cos") == 0) 136 | { 137 | extinctions.push_back(create_cos_extinction()); 138 | } 139 | else if (strcmp(argv[i], "gauss") == 0) 140 | { 141 | extinctions.push_back(create_gauss_extinction()); 142 | } 143 | else if (strcmp(argv[i], "hole") == 0) 144 | { 145 | extinctions.push_back(create_hole_extinction()); 146 | } 147 | else if (strcmp(argv[i], "lin_inc") == 0) 148 | { 149 | extinctions.push_back(create_lin_inc_extinction()); 150 | } 151 | else if (strcmp(argv[i], "lin_dec") == 0) 152 | { 153 | extinctions.push_back(create_lin_dec_extinction()); 154 | } 155 | 156 | // estimator setting 157 | else if (strcmp(argv[i], "bidirectional") == 0) 158 | { 159 | estimators.push_back(new Bidirectional()); 160 | } 161 | else if (strcmp(argv[i], "expected") == 0) 162 | { 163 | estimators.push_back(new Expected()); 164 | } 165 | else if (strcmp(argv[i], "next_flight_ratio") == 0) 166 | { 167 | estimators.push_back(new NextFlight_RatioTracking()); 168 | } 169 | else if (strcmp(argv[i], "pseries_cmf") == 0) 170 | { 171 | estimators.push_back(new Pseries_CDF()); 172 | } 173 | else if (strcmp(argv[i], "pseries_cumulative") == 0) 174 | { 175 | estimators.push_back(new Pseries_Cumulative()); 176 | } 177 | else if (strcmp(argv[i], "pseries_next_flight_ratio") == 0) 178 | { 179 | estimators.push_back(new Pseries_NextFlightRatio()); 180 | } 181 | else if (strcmp(argv[i], "pseries_ratio") == 0) 182 | { 183 | estimators.push_back(new Pseries_Ratio()); 184 | } 185 | else if (strcmp(argv[i], "ratio") == 0) 186 | { 187 | estimators.push_back(new RatioTracking()); 188 | } 189 | else if (strcmp(argv[i], "track_length") == 0) 190 | { 191 | estimators.push_back(new TrackLength()); 192 | } 193 | else if (strcmp(argv[i], "unidirectional") == 0) 194 | { 195 | estimators.push_back(new Unidirectional()); 196 | } 197 | 198 | // other option setting 199 | else if (strcmp(argv[i], "prefix") == 0) 200 | { 201 | prefix = std::string(argv[++i]); 202 | } 203 | else if (strcmp(argv[i], "base_seed") == 0) 204 | { 205 | base_seed = (long)stoi(argv[++i]); 206 | } 207 | else if (strcmp(argv[i], "equal_cost") == 0) 208 | { 209 | equal_cost = true; 210 | } 211 | else if (strcmp(argv[i], "samples") == 0) 212 | { 213 | samples = stoi(argv[++i]); 214 | } 215 | else if (strcmp(argv[i], "trials") == 0) 216 | { 217 | trials = stoi(argv[++i]); 218 | } 219 | else if (strcmp(argv[i], "resolution") == 0) 220 | { 221 | resolution = stoi(argv[++i]); 222 | } 223 | 224 | // specifying all 225 | else if (strcmp(argv[i], "all") == 0) 226 | { 227 | extinctions.push_back(create_const_extinction()); 228 | extinctions.push_back(create_cos_extinction()); 229 | extinctions.push_back(create_gauss_extinction()); 230 | extinctions.push_back(create_hole_extinction()); 231 | extinctions.push_back(create_lin_inc_extinction()); 232 | extinctions.push_back(create_lin_dec_extinction()); 233 | 234 | estimators.push_back(new Bidirectional()); 235 | estimators.push_back(new Expected()); 236 | estimators.push_back(new NextFlight_RatioTracking()); 237 | estimators.push_back(new Pseries_CDF()); 238 | estimators.push_back(new Pseries_Cumulative()); 239 | estimators.push_back(new Pseries_NextFlightRatio()); 240 | estimators.push_back(new Pseries_Ratio()); 241 | estimators.push_back(new RatioTracking()); 242 | estimators.push_back(new TrackLength()); 243 | estimators.push_back(new Unidirectional()); 244 | } 245 | } 246 | 247 | if (estimators.size() == 0) std::cout << "Warning: no esitmator specified" << std::endl; 248 | if (extinctions.size() == 0) std::cout << "Warning: no extinction specified" << std::endl; 249 | 250 | // run canonical tests for each combination of specified extinctions 251 | // and estimators 252 | for (int i = 0; i < estimators.size(); ++i) 253 | { 254 | for (int j = 0; j < extinctions.size(); ++j) 255 | { 256 | Estimator* est = estimators[i]; 257 | Extinction* ext = extinctions[j]; 258 | 259 | CanonicalTest(prefix, 260 | est, 261 | ext, 262 | sampler, 263 | base_seed, 264 | equal_cost, 265 | max_cost, 266 | samples, 267 | trials, 268 | resolution); 269 | } 270 | } 271 | 272 | for (int i = 0; i < estimators.size(); ++i) delete estimators[i]; 273 | for (int i = 0; i < extinctions.size(); ++i) delete extinctions[i]; 274 | delete sampler; 275 | 276 | return 0; 277 | } 278 | -------------------------------------------------------------------------------- /canonical/samplers/halton.cpp: -------------------------------------------------------------------------------- 1 | #include "halton.h" 2 | 3 | Halton::Halton() : Sampler() { 4 | currentDim = 0; 5 | currentSample = 0; 6 | } 7 | 8 | Halton::Halton(unsigned int seed) : Sampler(seed) { 9 | currentDim = 0; 10 | currentSample = 0; 11 | } 12 | 13 | Halton::Halton(unsigned int seedOne, unsigned int seedTwo) : Sampler(seedOne, seedTwo) { 14 | currentDim = 0; 15 | currentSample = 0; 16 | } 17 | 18 | // halton does not require jitter 19 | 20 | void Halton::reseed() { 21 | reseedSampler(sampSeed); 22 | halton.init_random(sampleRNG); 23 | currentDim = 0; 24 | } 25 | 26 | void Halton::reseed(unsigned int seed) { 27 | sampSeed = seed; 28 | reseedSampler(sampSeed); 29 | halton.init_random(sampleRNG); 30 | currentDim = 0; 31 | } 32 | 33 | void Halton::reseed(unsigned int seedOne, unsigned int seedTwo) { 34 | sampSeed = seedOne; 35 | reseedSampler(sampSeed); 36 | halton.init_random(sampleRNG); 37 | currentDim = 0; 38 | } 39 | 40 | Halton::~Halton() { 41 | // does nothing 42 | } 43 | 44 | Float Halton::next1D() { 45 | if (currentDim > 255) { 46 | currentDim++; 47 | Float samp = sampleRNG.nextFloat(); 48 | return samp; 49 | } 50 | 51 | Float sample = halton.sample(currentDim, currentSample); 52 | currentDim++; 53 | return sample; 54 | } 55 | 56 | Pdd Halton::next2D() { 57 | return Pdd(next1D(), next1D()); 58 | } 59 | 60 | void Halton::nextSample() { 61 | currentSample++; 62 | currentDim = 0; 63 | } 64 | 65 | void Halton::reset() { 66 | reseed(sampSeed, jitSeed); 67 | currentSample = 0; 68 | currentDim = 0; 69 | } 70 | 71 | Sampler* Halton::copy() { 72 | return new Halton(sampSeed, jitSeed); 73 | } 74 | 75 | string Halton::getName() const { 76 | return "halton"; 77 | } 78 | -------------------------------------------------------------------------------- /canonical/samplers/halton.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sampler.h" 4 | #include "halton_sampler.h" 5 | 6 | class Halton : public Sampler { 7 | public: 8 | Halton(); 9 | Halton(unsigned int seed); 10 | Halton(unsigned int seedOne, unsigned int seedTwo); 11 | 12 | virtual ~Halton(); 13 | 14 | virtual void reseed(); 15 | virtual void reseed(unsigned int seed); 16 | virtual void reseed(unsigned int seedOne, unsigned int seedTwo); 17 | 18 | virtual Float next1D(); 19 | virtual Pdd next2D(); 20 | 21 | virtual void nextSample(); 22 | 23 | virtual void reset(); 24 | 25 | virtual Sampler* copy(); 26 | 27 | virtual string getName() const; 28 | 29 | protected: 30 | Halton_sampler halton; 31 | uint32_t currentDim; 32 | uint32_t currentSample; 33 | }; 34 | -------------------------------------------------------------------------------- /canonical/samplers/hammersley.cpp: -------------------------------------------------------------------------------- 1 | #include "hammersley.h" 2 | #include "../util.h" 3 | 4 | Hammersley::Hammersley() : Sampler() { 5 | currentDim = 0; 6 | currentSample = 0; 7 | } 8 | 9 | Hammersley::Hammersley(unsigned int seed) : Sampler(seed) { 10 | currentDim = 0; 11 | currentSample = 0; 12 | } 13 | 14 | Hammersley::Hammersley(unsigned int seedOne, unsigned int seedTwo) : Sampler(seedOne, seedTwo) { 15 | currentDim = 0; 16 | currentSample = 0; 17 | } 18 | 19 | void Hammersley::reseed() { 20 | reseedSampler(sampSeed); 21 | halton.init_random(sampleRNG); 22 | scramble = sampleRNG.nextUInt(); 23 | } 24 | 25 | void Hammersley::reseed(unsigned int seed) { 26 | sampSeed = seed; 27 | reseedSampler(sampSeed); 28 | halton.init_random(sampleRNG); 29 | scramble = sampleRNG.nextUInt(); 30 | } 31 | 32 | void Hammersley::reseed(unsigned int seedOne, unsigned int seedTwo) { 33 | sampSeed = seedOne; 34 | reseedSampler(sampSeed); 35 | halton.init_random(sampleRNG); 36 | scramble = sampleRNG.nextUInt(); 37 | } 38 | 39 | Hammersley::~Hammersley() { 40 | // does nothing 41 | } 42 | 43 | Float Hammersley::next1D() { 44 | Float sample = 0.0; 45 | 46 | if (currentDim == 0) { 47 | sample = Util::randomDigitScramble(float(currentSample * inv), scramble); 48 | } else { 49 | if (currentDim > 255) { 50 | return sampleRNG.nextFloat(); 51 | } 52 | 53 | sample = halton.sample(currentDim, currentSample); 54 | } 55 | 56 | currentDim++; 57 | return sample; 58 | } 59 | 60 | Pdd Hammersley::next2D() { 61 | return Pdd(next1D(), next1D()); 62 | } 63 | 64 | void Hammersley::nextSample() { 65 | currentSample++; 66 | currentDim = 0; 67 | } 68 | 69 | void Hammersley::reset() { 70 | reseed(sampSeed, jitSeed); 71 | currentSample = 0; 72 | currentDim = 0; 73 | } 74 | 75 | Sampler* Hammersley::copy() { 76 | return new Hammersley(sampSeed, jitSeed); 77 | } 78 | 79 | string Hammersley::getName() const { 80 | return "hammersley"; 81 | } 82 | 83 | void Hammersley::setNumSamples(uint32_t param) { 84 | numSamples = param; 85 | inv = 1.0 / Float(param); 86 | } 87 | -------------------------------------------------------------------------------- /canonical/samplers/hammersley.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sampler.h" 4 | #include "halton_sampler.h" 5 | 6 | class Hammersley : public Sampler { 7 | public: 8 | Hammersley(); 9 | Hammersley(unsigned int seed); 10 | Hammersley(unsigned int seedOne, unsigned int seedTwo); 11 | 12 | virtual ~Hammersley(); 13 | 14 | virtual void reseed(); 15 | virtual void reseed(unsigned int seed); 16 | virtual void reseed(unsigned int seedOne, unsigned int seedTwo); 17 | 18 | virtual Float next1D(); 19 | virtual Pdd next2D(); 20 | 21 | virtual void nextSample(); 22 | 23 | virtual void reset(); 24 | 25 | virtual Sampler* copy(); 26 | 27 | virtual string getName() const; 28 | 29 | virtual void setNumSamples(uint32_t param); 30 | 31 | protected: 32 | Halton_sampler halton; 33 | Float inv; 34 | uint32_t scramble; 35 | uint32_t currentDim; 36 | uint32_t currentSample; 37 | }; 38 | -------------------------------------------------------------------------------- /canonical/samplers/independent.cpp: -------------------------------------------------------------------------------- 1 | #include "independent.h" 2 | 3 | Independent::Independent() : Sampler() { } 4 | 5 | Independent::Independent(unsigned int seed) : Sampler(seed) { } 6 | 7 | Independent::Independent(unsigned int seedOne, unsigned int seedTwo) : Sampler(seedOne, seedTwo) { } 8 | 9 | Independent::~Independent() { 10 | // nothing to clean up 11 | } 12 | 13 | Float Independent::next1D() { 14 | return sampleRNG.nextFloat(); 15 | } 16 | 17 | Pdd Independent::next2D() { 18 | return Pdd(sampleRNG.nextFloat(), sampleRNG.nextFloat()); 19 | } 20 | 21 | uint32_t Independent::next1D_U() { 22 | return sampleRNG.nextUInt(); 23 | } 24 | 25 | void Independent::nextSample() { 26 | // does nothing 27 | } 28 | 29 | void Independent::reset() { 30 | reseed(sampSeed, jitSeed); 31 | } 32 | 33 | Sampler* Independent::copy() { 34 | Independent* newSampler = new Independent(sampSeed, jitSeed); 35 | return newSampler; 36 | } 37 | 38 | string Independent::getName() const { 39 | return "independent"; 40 | } 41 | -------------------------------------------------------------------------------- /canonical/samplers/independent.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sampler.h" 4 | 5 | class Independent : public Sampler { 6 | public: 7 | Independent(); 8 | Independent(unsigned int seed); 9 | Independent(unsigned int seedOne, unsigned int seedTwo); 10 | 11 | virtual ~Independent(); 12 | 13 | virtual Float next1D(); 14 | virtual Pdd next2D(); 15 | 16 | uint32_t next1D_U(); 17 | 18 | virtual void nextSample(); 19 | 20 | virtual void reset(); 21 | 22 | virtual Sampler* copy(); 23 | 24 | virtual string getName() const; 25 | 26 | protected: 27 | }; 28 | -------------------------------------------------------------------------------- /canonical/samplers/latinip.cpp: -------------------------------------------------------------------------------- 1 | #include "latinip.h" 2 | #include "permute.h" 3 | 4 | LatinHyperCubesInPlace::LatinHyperCubesInPlace() : Sampler() { 5 | currentDim = 0; 6 | currentSample = 0; 7 | jit = 0.0; 8 | } 9 | 10 | LatinHyperCubesInPlace::LatinHyperCubesInPlace(unsigned int seed) : Sampler(seed) { 11 | currentDim = 0; 12 | currentSample = 0; 13 | jit = 0.0; 14 | } 15 | 16 | LatinHyperCubesInPlace::LatinHyperCubesInPlace(unsigned int seedOne, unsigned int seedTwo) : Sampler(seedOne, seedTwo) { 17 | currentDim = 0; 18 | currentSample = 0; 19 | jit = 0.0; 20 | } 21 | 22 | void LatinHyperCubesInPlace::reseed() { 23 | Sampler::reseed(); 24 | 25 | jit = 1.0; 26 | } 27 | 28 | void LatinHyperCubesInPlace::reseed(unsigned int seed) { 29 | Sampler::reseed(seed); 30 | 31 | jit = 1.0; 32 | } 33 | 34 | void LatinHyperCubesInPlace::reseed(unsigned int seedOne, unsigned int seedTwo) { 35 | Sampler::reseed(seedOne, seedTwo); 36 | 37 | jit = 1.0; 38 | } 39 | 40 | Float LatinHyperCubesInPlace::next1D() { 41 | int32_t samp = sampleRNG.nextUInt(); 42 | int32_t value = Permutation::permute(currentSample, numSamples, samp); 43 | 44 | Float sample = Float(value) + 0.5; 45 | Float jitter = jit * (jitterRNG.nextFloat() - 0.5); 46 | sample += jitter; 47 | sample /= Float(numSamples); 48 | currentDim++; 49 | 50 | return sample; 51 | } 52 | 53 | Pdd LatinHyperCubesInPlace::next2D() { 54 | return Pdd(next1D(), next1D()); 55 | } 56 | 57 | void LatinHyperCubesInPlace::nextSample() { 58 | reseedSampler(sampSeed); 59 | currentDim = 0; 60 | currentSample++; 61 | } 62 | 63 | void LatinHyperCubesInPlace::reset() { 64 | reseedSampler(sampSeed); 65 | reseedJitter(jitSeed); 66 | currentSample = 0; 67 | currentDim = 0; 68 | } 69 | 70 | Sampler* LatinHyperCubesInPlace::copy() { 71 | return new LatinHyperCubesInPlace(sampSeed, jitSeed); 72 | } 73 | 74 | string LatinHyperCubesInPlace::getName() const { 75 | return "latin_in_place"; 76 | } 77 | -------------------------------------------------------------------------------- /canonical/samplers/latinip.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "sampler.h" 4 | 5 | class LatinHyperCubesInPlace : public Sampler { 6 | public: 7 | LatinHyperCubesInPlace(); 8 | LatinHyperCubesInPlace(unsigned int seed); 9 | LatinHyperCubesInPlace(unsigned int seedOne, unsigned int seedTwo); 10 | 11 | virtual void reseed(); 12 | virtual void reseed(unsigned int seed); 13 | virtual void reseed(unsigned int seedOne, unsigned int seedTwo); 14 | 15 | virtual Float next1D(); 16 | virtual Pdd next2D(); 17 | 18 | virtual void reset(); 19 | 20 | virtual void nextSample(); 21 | 22 | virtual Sampler* copy(); 23 | 24 | virtual string getName() const; 25 | 26 | protected: 27 | Float jit; 28 | uint32_t currentDim; 29 | uint32_t currentSample; 30 | }; 31 | -------------------------------------------------------------------------------- /canonical/samplers/permute.cpp: -------------------------------------------------------------------------------- 1 | #include "permute.h" 2 | 3 | Permutation::Permutation() { 4 | indices = vector(); 5 | } 6 | 7 | Permutation::Permutation(uint32_t size) { 8 | indices = vector(size); 9 | } 10 | 11 | void Permutation::initialize() { 12 | for (int i = 0; i < indices.size(); ++i) { 13 | indices[i] = i; 14 | } 15 | } 16 | 17 | void Permutation::resize(uint32_t newSize) { 18 | indices.resize(newSize); 19 | } 20 | 21 | int32_t Permutation::operator[](const uint32_t i) const { 22 | return indices[i]; 23 | } 24 | 25 | void Permutation::shuffle(pcg32& rand) { 26 | rand.shuffle(indices.begin(), indices.end()); 27 | } 28 | 29 | uint32_t Permutation::getSize() const { 30 | return indices.size(); 31 | } 32 | 33 | //! In-place enumeration of random permutations 34 | /*! 35 | Returns the i-th element of the p-th pseudo-random permutation of the 36 | numbers 0..(l-1). 37 | 38 | Based on method described in the tech report: 39 | 40 | Andrew Kensler. "Correlated Multi-Jittered Sampling", 41 | Pixar Technical Memo 13-01. 42 | */ 43 | unsigned int Permutation::permute(unsigned int i, unsigned int l, unsigned int p) { 44 | unsigned w = l - 1; 45 | w |= w >> 1; 46 | w |= w >> 2; 47 | w |= w >> 4; 48 | w |= w >> 8; 49 | w |= w >> 16; 50 | do 51 | { 52 | i ^= p; i *= 0xe170893d; 53 | i ^= p >> 16; 54 | i ^= (i & w) >> 4; 55 | i ^= p >> 8; i *= 0x0929eb3f; 56 | i ^= p >> 23; 57 | i ^= (i & w) >> 1; i *= 1 | p >> 27; 58 | i *= 0x6935fa69; 59 | i ^= (i & w) >> 11; i *= 0x74dcb303; 60 | i ^= (i & w) >> 2; i *= 0x9e501cc3; 61 | i ^= (i & w) >> 2; i *= 0xc860a3df; 62 | i &= w; 63 | i ^= i >> 5; 64 | } while (i >= l); 65 | 66 | return (i + p) % l; 67 | } 68 | -------------------------------------------------------------------------------- /canonical/samplers/permute.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | // This class is based off of code from Wojciech Jarosz 4 | 5 | #include "../common.h" 6 | #include 7 | 8 | class Permutation { 9 | public: 10 | Permutation(); 11 | Permutation(uint32_t size); 12 | 13 | void initialize(); 14 | void resize(uint32_t newSize); 15 | 16 | int32_t operator[](const uint32_t i) const; 17 | void shuffle(pcg32& rand); 18 | 19 | static unsigned int permute(unsigned int i, unsigned int l, unsigned int p); 20 | 21 | uint32_t getSize() const; 22 | 23 | protected: 24 | std::vector indices; 25 | }; 26 | -------------------------------------------------------------------------------- /canonical/samplers/sampler.cpp: -------------------------------------------------------------------------------- 1 | #include "sampler.h" 2 | 3 | Sampler::Sampler() { 4 | sampSeed = 0x45454; 5 | jitSeed = 0x54545; 6 | numDimensions = 0; 7 | numSamples = 0; 8 | 9 | reseed(sampSeed, jitSeed); 10 | } 11 | 12 | Sampler::Sampler(uint32_t seed) { 13 | sampSeed = seed; 14 | jitSeed = 0x54545; 15 | numDimensions = 0; 16 | numSamples = 0; 17 | 18 | reseed(sampSeed, jitSeed); 19 | } 20 | 21 | Sampler::Sampler(uint32_t seedOne, uint32_t seedTwo) { 22 | sampSeed = seedOne; 23 | jitSeed = seedTwo; 24 | numDimensions = 0; 25 | numSamples = 0; 26 | 27 | reseed(sampSeed, jitSeed); 28 | } 29 | 30 | Sampler::~Sampler() { 31 | // does nothing 32 | } 33 | 34 | void Sampler::reseed() { 35 | reseedSampler(sampSeed); 36 | reseedJitter(jitSeed); 37 | } 38 | 39 | void Sampler::reseed(unsigned int seed) { 40 | reseedSampler(seed); 41 | reseedJitter(jitSeed); 42 | } 43 | 44 | void Sampler::reseed(unsigned int seedOne, unsigned int seedTwo) { 45 | reseedSampler(seedOne); 46 | reseedJitter(seedTwo); 47 | } 48 | 49 | void Sampler::reseedSampler(unsigned int seed) { 50 | sampSeed = seed; 51 | // srand(sampSeed); 52 | uint64_t r1 = 142; 53 | // cout << "R1: " << r1 << endl; 54 | uint64_t r2 = seed; 55 | // cout << "R2: " << r2 << endl; 56 | sampleRNG = pcg32(r1, r2); 57 | } 58 | 59 | void Sampler::reseedJitter(unsigned int seed) { 60 | jitSeed = seed; 61 | // srand(jitSeed); 62 | // uint64_t r1 = rand(); 63 | // uint64_t r2 = rand(); 64 | jitterRNG = pcg32(2185, seed); 65 | } 66 | 67 | pcg32 Sampler::getSampleRNG() const { 68 | return sampleRNG; 69 | } 70 | 71 | pcg32 Sampler::getJitterRNG() const { 72 | return jitterRNG; 73 | } 74 | 75 | uint32_t Sampler::getSampSeed() const { 76 | return sampSeed; 77 | } 78 | 79 | uint32_t Sampler::getJitSeed() const { 80 | return jitSeed; 81 | } 82 | 83 | uint32_t Sampler::getNumDimensions() const { 84 | return numDimensions; 85 | } 86 | 87 | uint32_t Sampler::getNumSamples() const { 88 | return numSamples; 89 | } 90 | 91 | void Sampler::setSampSeed(uint32_t param) { 92 | sampSeed = param; 93 | } 94 | 95 | void Sampler::setJitSeed(uint32_t param) { 96 | jitSeed = param; 97 | } 98 | 99 | void Sampler::setNumDimensions(uint32_t param) { 100 | numDimensions = param; 101 | } 102 | 103 | void Sampler::setNumSamples(uint32_t param) { 104 | numSamples = param; 105 | } 106 | -------------------------------------------------------------------------------- /canonical/samplers/sampler.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../common.h" 4 | #include 5 | 6 | class Sampler { 7 | public: 8 | Sampler(); 9 | Sampler(uint32_t seed); 10 | Sampler(uint32_t seedOne, uint32_t seedTwo); 11 | virtual ~Sampler(); 12 | 13 | virtual void reseed(); 14 | virtual void reseed(unsigned int seed); 15 | virtual void reseed(unsigned int seedOne, unsigned int seedTwo); 16 | 17 | virtual void reseedSampler(unsigned int seed); 18 | virtual void reseedJitter(unsigned int seed); 19 | 20 | virtual void reset() = 0; 21 | 22 | virtual Float next1D() = 0; 23 | virtual Pdd next2D() = 0; 24 | 25 | virtual void nextSample() = 0; 26 | 27 | virtual Sampler* copy() = 0; 28 | 29 | virtual string getName() const = 0; 30 | 31 | pcg32 getSampleRNG() const; 32 | pcg32 getJitterRNG() const; 33 | uint32_t getSampSeed() const; 34 | uint32_t getJitSeed() const; 35 | uint32_t getNumDimensions() const; 36 | uint32_t getNumSamples() const; 37 | 38 | virtual void setSampSeed(uint32_t param); 39 | virtual void setJitSeed(uint32_t param); 40 | virtual void setNumDimensions(uint32_t param); 41 | virtual void setNumSamples(uint32_t param); 42 | 43 | protected: 44 | pcg32 sampleRNG; 45 | pcg32 jitterRNG; 46 | uint32_t sampSeed; 47 | uint32_t jitSeed; 48 | uint32_t numDimensions; 49 | uint32_t numSamples; 50 | }; 51 | -------------------------------------------------------------------------------- /canonical/util.cpp: -------------------------------------------------------------------------------- 1 | #include "util.h" 2 | 3 | Float Util::clamp(Float val, Float min, Float max) { 4 | if (val > max) return max; 5 | if (val < min) return min; 6 | return val; 7 | } 8 | 9 | Float Util::abs(Float value) { 10 | if (value >= 0.0) return value; 11 | return -value; 12 | } 13 | 14 | Float Util::EXP(Float val) 15 | { 16 | #ifdef USE_ARBITRARY_PRECISION 17 | return mpfr_pp::exp(val); 18 | #else 19 | return exp(val); 20 | #endif 21 | } 22 | 23 | Float Util::LOG(Float val) 24 | { 25 | #ifdef USE_ARBITRARY_PRECISION 26 | return mpfr_pp::log(val); 27 | #else 28 | return log(val); 29 | #endif 30 | } 31 | 32 | Float Util::POW(Float base, Float power) 33 | { 34 | #ifdef USE_ARBITRARY_PRECISION 35 | return mpfr_pp::pow(base, power); 36 | #else 37 | return pow(base, power); 38 | #endif 39 | } 40 | 41 | Float Util::ABS(Float val) 42 | { 43 | #ifdef USE_ARBITRARY_PRECISION 44 | return mpfr_pp::abs(val); 45 | #else 46 | return abs(val); 47 | #endif 48 | } 49 | 50 | Float Util::COS(Float val) 51 | { 52 | #ifdef USE_ARBITRARY_PRECISION 53 | return mpfr_pp::cos(val); 54 | #else 55 | return cos(val); 56 | #endif 57 | } 58 | 59 | Float Util::SIN(Float val) 60 | { 61 | #ifdef USE_ARBITRARY_PRECISION 62 | return mpfr_pp::sin(val); 63 | #else 64 | return sin(val); 65 | #endif 66 | } 67 | 68 | float Util::randomDigitScramble(float f, unsigned scramble) 69 | { 70 | return (unsigned(f*0x100000000LL) ^ scramble) * 2.3283064365386962890625e-10f; 71 | } 72 | -------------------------------------------------------------------------------- /canonical/util.h: -------------------------------------------------------------------------------- 1 | #include "common.h" 2 | #include 3 | 4 | // just a collection of math helper functions 5 | 6 | class Util { 7 | public: 8 | // clamp methods 9 | static Float clamp(Float val, Float min, Float max); 10 | 11 | static Float abs(Float value); 12 | static Float EXP(Float val); 13 | static Float LOG(Float val); 14 | static Float POW(Float base, Float power); 15 | static Float ABS(Float val); 16 | static Float COS(Float val); 17 | static Float SIN(Float val); 18 | 19 | // sampling methods 20 | static float randomDigitScramble(float f, unsigned scramble); 21 | }; 22 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | Hello! Will have this readme and the tests cleaned up soon. Will also finish incorporating 2 | my pbrt implementation and create a quick script for generating them. 3 | 4 | Canonical Tests 5 | 6 | In this repository we provide the implementation of generating our canonical 7 | plots as seen in the paper Integral formulations of volumetric 8 | transmittance. While our paper utilizes a false color transformation and 9 | provides isocontours, we leave out our that messy implementation and just 10 | provide the logic and means of generating the base heatmaps. We also provide 11 | an intuitive abstraction of transmittance estimators for any individuals who 12 | wants to test their own against ours and previous work. 13 | 14 | To compile the program simply do the following: 15 | 16 | cmake ./ && make 17 | 18 | And to run the program you have the following options: 19 | 20 | ./transm_est samp_name all 21 | ./transm_est samp_name ext_name_1 ... ext_name_n est_name_1 ... est_name_n 22 | 23 | The first option runs all combinations of estimators and extinctions utilizing the specified sampler, while the second option runs all combinations of the estimators and extinctions specified. 24 | 25 | The sampler is optional, and if no sampler is specified the sampler defaults to independent samples. 26 | At least one extinction and one estimator must be specified, otherwise the program will terminate without running any experiments. 27 | 28 | List of : 29 | prefix - adds a prefix to the paths for all saved images 30 | base_seed - sets the base seed for the rng 31 | equal_cost - specifies that the test is equal cost 32 | if a test is equal cost then the sampler is only allowed to be an independent sampler, and samples/trials will be hardcoded to 1. 33 | samples - sets the sample count (disabled if equal cost) 34 | trials - sets the number of trials (disabled if equal cost) 35 | resolution - sets the resolution of the plots 36 | 37 | List of available samplers: 38 | 39 | halton - Halton sampler 40 | hammersley - Hammersley sampler 41 | independent - Independent sampler 42 | latinip - In-Place Latin Hypercubes sampler 43 | 44 | List of available extinction functions: 45 | 46 | const - Constant extinction: f(x) = c 47 | cos - Cosine extinction: f(x) = y + h * cos(s * x + k) 48 | gauss - Gaussian extinction: f(x) = h * e^((-(x-m)^2) / (2 * s)) 49 | hole - Hole extinction: f(x) = c - h * e^((-(x-m)^2) / (2 * s)) 50 | lin_inc - Linear increasing extinction: f(x) = m * x + y 51 | lin_dec - Linear decreasing extinction: f(x) = -m * x + y 52 | 53 | List of available transmittance estimators: 54 | 55 | bidirectional - Bidirectional MIS 56 | expected - Ground Truth 57 | next_flight_ratio - Next-flight 58 | pseries_cmf - p-series CMF 59 | pseries_cumulative - p-series cumulative 60 | pseries_next_flight_ratio - Next-flight reformulated in p-series framework 61 | pseries_ratio - Ratio-tracking reformulated in p-series framework 62 | ratio - Ratio_tracking 63 | track_length - Delta-tracking / track-length 64 | unidirectional - Unidirectional MIS 65 | 66 | All results are written as png and hdr images. 67 | --------------------------------------------------------------------------------