<commit_before>#pragma once

#include "light/ibl.h"

// NOTE
// http://www.cs.virginia.edu/~gfx/courses/2007/ImageSynthesis/assignments/envsample.pdf
// http://www.igorsklyar.com/system/documents/papers/4/fiscourse.comp.pdf

namespace AT_NAME {
	void ImageBasedLight::preCompute()
	{
		auto envmap = getEnvMap();
		AT_ASSERT(envmap);

		auto width = envmap->getTexture()->width();
		auto height = envmap->getTexture()->height();

		m_avgIllum = 0;

		// NOTE
		// }bv́A~i= ܓxox}bvĵ.

		// NOTE
		//    0 1 2 3 4
		//   +-+-+-+-+-+
		// 0 |a|b|c|d|e|...
		//   +-+-+-+-+-+
		// 1 |h|i|j|k|l|...
		//   +-+-+-+-+-+
		//
		// VicjPDF͂P񕪂̍vlƂȂ.
		// @pdfV_0 = a + b + c + d + e + ....
		// @pdfV_1 = h + i + j + k + l + ....
		//
		// UijPDF͂PsNZ̒lƂȂ.
		// @pdfU_00 = a, pdfU_01 = b, ...
		// @pdfU_10 = h, pdfU_11 = i, ...

		real totalWeight = 0;

		m_cdfU.resize(height);

		for (uint32_t y = 0; y < height; y++) {
			// NOTE
			// ~́AܓxɂĂ͋ɂقǘcނ̂ŁA̕␳.
			// ܓx [0, pi].
			// 0.5 ̂́AsNZS_Tv̂ƁA[ɂȂȂ悤ɂ邽.
			// sin(0) = 0  scalel[ɂȂ̂邽.
			real scale = aten::sin(AT_MATH_PI * (real)(y + 0.5) / height);

			// vpdf.
			real pdfV = 0;

			// updf.
			std::vector<real>& pdfU = m_cdfU[y];

			for (uint32_t x = 0; x < width; x++) {
				real u = (real)(x + 0.5) / width;
				real v = (real)(y + 0.5) / height;

				auto clr = envmap->sample(u, v);
				const auto illum = AT_NAME::color::luminance(clr);

				m_avgIllum += illum * scale;
				totalWeight += scale;

				// P񕪂̍vlvZ.
				pdfV += illum * scale;

				// ܂pdf𒙂߂.
				pdfU.push_back(illum * scale);
			}

			// ܂pdf𒙂߂.
			m_cdfV.push_back(pdfV);
		}

		// For vertical.
		{
			real sum = 0;
			for (int i = 0; i < m_cdfV.size(); i++) {
				sum += m_cdfV[i];
				if (i > 0) {
					m_cdfV[i] += m_cdfV[i - 1];
				}
			}
			if (sum > 0) {
				real invSum = 1 / sum;
				for (int i = 0; i < m_cdfV.size(); i++) {
					m_cdfV[i] *= invSum;
					m_cdfV[i] = aten::clamp<real>(m_cdfV[i], 0, 1);
				}
			}
		}

		// For horizontal.
		{
			for (uint32_t y = 0; y < height; y++) {
				real sum = 0;
				std::vector<real>& cdfU = m_cdfU[y];

				for (uint32_t x = 0; x < width; x++) {
					sum += cdfU[x];
					if (x > 0) {
						cdfU[x] += cdfU[x - 1];
					}
				}

				if (sum > 0) {
					real invSum = 1 / sum;
					for (uint32_t x = 0; x < width; x++) {
						cdfU[x] *= invSum;
						cdfU[x] = aten::clamp<real>(cdfU[x], 0, 1);
					}
				}
			}
		}

		m_avgIllum /= totalWeight;
	}

	real ImageBasedLight::samplePdf(const aten::ray& r) const
	{
		auto envmap = getEnvMap();

		auto clr = envmap->sample(r);

		auto pdf = samplePdf(clr, m_avgIllum);

		return pdf;
	}

	static int samplePdfAndCdf(
		real r,
		const std::vector<real>& cdf,
		real& outPdf,
		real& outCdf)
	{
		outPdf = 0;
		outCdf = 0;

		// NOTE
		// cdf is normalized to [0, 1].

#if 1
		int idxTop = 0;
		int idxTail = (int)cdf.size() - 1;

		for (;;) {
			int idxMid = (idxTop + idxTail) >> 1;
			auto midCdf = cdf[idxMid];

			if (r < midCdf) {
				idxTail = idxMid;
			}
			else {
				idxTop = idxMid;
			}

			if ((idxTail - idxTop) == 1) {
				auto topCdf = cdf[idxTop];
				auto tailCdf = cdf[idxTail];

				int idx = 0;

				if (r <= topCdf) {
					outPdf = topCdf;
					idx = idxTop;
				}
				else {
					outPdf = tailCdf - topCdf;
					idx = idxTail;
				}

				return idx;
			}
		}
#else
		for (int i = 0; i < cdf.size(); i++) {
			if (r <= cdf[i]) {
				auto idx = i;

				outCdf = cdf[i];

				if (i > 0) {
					outPdf = cdf[i] - cdf[i - 1];
				}
				else {
					outPdf = cdf[0];
				}

				return idx;
			}
		}
#endif

		AT_ASSERT(false);
		return 0;
	}

	aten::LightSampleResult ImageBasedLight::sample(
		const aten::vec3& org,
		const aten::vec3& nml,
		aten::sampler* sampler) const
	{
		auto envmap = getEnvMap();

		aten::LightSampleResult result;

#if 1
		const auto r1 = sampler->nextSample();
		const auto r2 = sampler->nextSample();

		real pdfU, pdfV;
		real cdfU, cdfV;

		int y = samplePdfAndCdf(r1, m_cdfV, pdfV, cdfV);
		int x = samplePdfAndCdf(r2, m_cdfU[y], pdfU, cdfU);

		auto width = envmap->getTexture()->width();
		auto height = envmap->getTexture()->height();

		real u = (real)(x + 0.5) / width;
		real v = (real)(y + 0.5) / height;

		// NOTE
		// p(w) = p(u, v) * (w * h) / (2^2 * sin())
		auto pi2 = AT_MATH_PI * AT_MATH_PI;
		auto theta = AT_MATH_PI * v;
		result.pdf = (pdfU * pdfV) * ((width * height) / (pi2 * aten::sin(theta)));

		// u, v -> direction.
		result.dir = AT_NAME::envmap::convertUVToDirection(u, v);

		result.le = envmap->sample(u, v);
		result.intensity = real(1);
		result.finalColor = result.le * result.intensity;
#elif 0
		auto uv = AT_NAME::envmap::convertDirectionToUV(nml);

		static const real radius = real(3);

		auto r1 = sampler->nextSample();
		auto r2 = sampler->nextSample();

		// [0, 1] -> [-1, 1]
		r1 = r1 * 2 - 1;
		r2 = r2 * 2 - 1;

		auto width = envmap->getTexture()->width();
		auto height = envmap->getTexture()->height();

		r1 = r1 * radius / (real)width;
		r2 = r2 * radius / (real)height;

		real u = uv.x + r1;
		if (u < real(0)) {
			u += real(1);
		}
		else if (u > real(1)) {
			u = real(1) - (u - real(1));
		}

		real v = uv.y + r2;
		if (v < real(0)) {
			v += real(1);
		}
		else if (v > real(1)) {
			v = real(1) - (v - real(1));
		}

		// u, v -> direction.
		result.dir = AT_NAME::envmap::convertUVToDirection(u, v);

		result.pdf = dot(nml, result.dir) / AT_MATH_PI;

		result.le = envmap->sample(u, v);
		result.intensity = real(1);
		result.finalColor = result.le * result.intensity;
#else
		auto n = nml;
		auto t = aten::getOrthoVector(nml);
		auto b = normalize(cross(n, t));

		real r1 = sampler->nextSample();
		real r2 = sampler->nextSample();

		real sinpsi = aten::sin(2 * AT_MATH_PI * r1);
		real cospsi = aten::cos(2 * AT_MATH_PI * r1);
		real costheta = aten::pow(1 - r2, 0.5);
		real sintheta = aten::sqrt(1 - costheta * costheta);

		// returnTo the result
		result.dir = normalize(t * sintheta * cospsi + b * sintheta * sinpsi + n * costheta);

		result.pdf = dot(nml, result.dir) / AT_MATH_PI;

		auto uv = AT_NAME::envmap::convertDirectionToUV(result.dir);

		result.le = envmap->sample(uv.x, uv.y);
		result.intensity = real(1);
		result.finalColor = result.le * result.intensity;
#endif

		// TODO
		// Currently not used...
		result.pos = aten::vec3();
		result.nml = aten::vec3();

		return std::move(result);
	}
}<commit_msg>Remove unmeaning code.<commit_after>#include "light/ibl.h"

// NOTE
// http://www.cs.virginia.edu/~gfx/courses/2007/ImageSynthesis/assignments/envsample.pdf
// http://www.igorsklyar.com/system/documents/papers/4/fiscourse.comp.pdf

namespace AT_NAME {
	void ImageBasedLight::preCompute()
	{
		auto envmap = getEnvMap();
		AT_ASSERT(envmap);

		auto width = envmap->getTexture()->width();
		auto height = envmap->getTexture()->height();

		m_avgIllum = 0;

		// NOTE
		// }bv́A~i= ܓxox}bvĵ.

		// NOTE
		//    0 1 2 3 4
		//   +-+-+-+-+-+
		// 0 |a|b|c|d|e|...
		//   +-+-+-+-+-+
		// 1 |h|i|j|k|l|...
		//   +-+-+-+-+-+
		//
		// VicjPDF͂P񕪂̍vlƂȂ.
		// @pdfV_0 = a + b + c + d + e + ....
		// @pdfV_1 = h + i + j + k + l + ....
		//
		// UijPDF͂PsNZ̒lƂȂ.
		// @pdfU_00 = a, pdfU_01 = b, ...
		// @pdfU_10 = h, pdfU_11 = i, ...

		real totalWeight = 0;

		m_cdfU.resize(height);

		for (uint32_t y = 0; y < height; y++) {
			// NOTE
			// ~́AܓxɂĂ͋ɂقǘcނ̂ŁA̕␳.
			// ܓx [0, pi].
			// 0.5 ̂́AsNZS_Tv̂ƁA[ɂȂȂ悤ɂ邽.
			// sin(0) = 0  scalel[ɂȂ̂邽.
			real scale = aten::sin(AT_MATH_PI * (real)(y + 0.5) / height);

			// vpdf.
			real pdfV = 0;

			// updf.
			std::vector<real>& pdfU = m_cdfU[y];

			for (uint32_t x = 0; x < width; x++) {
				real u = (real)(x + 0.5) / width;
				real v = (real)(y + 0.5) / height;

				auto clr = envmap->sample(u, v);
				const auto illum = AT_NAME::color::luminance(clr);

				m_avgIllum += illum * scale;
				totalWeight += scale;

				// P񕪂̍vlvZ.
				pdfV += illum * scale;

				// ܂pdf𒙂߂.
				pdfU.push_back(illum * scale);
			}

			// ܂pdf𒙂߂.
			m_cdfV.push_back(pdfV);
		}

		// For vertical.
		{
			real sum = 0;
			for (int i = 0; i < m_cdfV.size(); i++) {
				sum += m_cdfV[i];
				if (i > 0) {
					m_cdfV[i] += m_cdfV[i - 1];
				}
			}
			if (sum > 0) {
				real invSum = 1 / sum;
				for (int i = 0; i < m_cdfV.size(); i++) {
					m_cdfV[i] *= invSum;
					m_cdfV[i] = aten::clamp<real>(m_cdfV[i], 0, 1);
				}
			}
		}

		// For horizontal.
		{
			for (uint32_t y = 0; y < height; y++) {
				real sum = 0;
				std::vector<real>& cdfU = m_cdfU[y];

				for (uint32_t x = 0; x < width; x++) {
					sum += cdfU[x];
					if (x > 0) {
						cdfU[x] += cdfU[x - 1];
					}
				}

				if (sum > 0) {
					real invSum = 1 / sum;
					for (uint32_t x = 0; x < width; x++) {
						cdfU[x] *= invSum;
						cdfU[x] = aten::clamp<real>(cdfU[x], 0, 1);
					}
				}
			}
		}

		m_avgIllum /= totalWeight;
	}

	real ImageBasedLight::samplePdf(const aten::ray& r) const
	{
		auto envmap = getEnvMap();

		auto clr = envmap->sample(r);

		auto pdf = samplePdf(clr, m_avgIllum);

		return pdf;
	}

	static int samplePdfAndCdf(
		real r,
		const std::vector<real>& cdf,
		real& outPdf,
		real& outCdf)
	{
		outPdf = 0;
		outCdf = 0;

		// NOTE
		// cdf is normalized to [0, 1].

#if 1
		int idxTop = 0;
		int idxTail = (int)cdf.size() - 1;

		for (;;) {
			int idxMid = (idxTop + idxTail) >> 1;
			auto midCdf = cdf[idxMid];

			if (r < midCdf) {
				idxTail = idxMid;
			}
			else {
				idxTop = idxMid;
			}

			if ((idxTail - idxTop) == 1) {
				auto topCdf = cdf[idxTop];
				auto tailCdf = cdf[idxTail];

				int idx = 0;

				if (r <= topCdf) {
					outPdf = topCdf;
					idx = idxTop;
				}
				else {
					outPdf = tailCdf - topCdf;
					idx = idxTail;
				}

				return idx;
			}
		}
#else
		for (int i = 0; i < cdf.size(); i++) {
			if (r <= cdf[i]) {
				auto idx = i;

				outCdf = cdf[i];

				if (i > 0) {
					outPdf = cdf[i] - cdf[i - 1];
				}
				else {
					outPdf = cdf[0];
				}

				return idx;
			}
		}
#endif

		AT_ASSERT(false);
		return 0;
	}

	aten::LightSampleResult ImageBasedLight::sample(
		const aten::vec3& org,
		const aten::vec3& nml,
		aten::sampler* sampler) const
	{
		auto envmap = getEnvMap();

		aten::LightSampleResult result;

#if 1
		const auto r1 = sampler->nextSample();
		const auto r2 = sampler->nextSample();

		real pdfU, pdfV;
		real cdfU, cdfV;

		int y = samplePdfAndCdf(r1, m_cdfV, pdfV, cdfV);
		int x = samplePdfAndCdf(r2, m_cdfU[y], pdfU, cdfU);

		auto width = envmap->getTexture()->width();
		auto height = envmap->getTexture()->height();

		real u = (real)(x + 0.5) / width;
		real v = (real)(y + 0.5) / height;

		// NOTE
		// p(w) = p(u, v) * (w * h) / (2^2 * sin())
		auto pi2 = AT_MATH_PI * AT_MATH_PI;
		auto theta = AT_MATH_PI * v;
		result.pdf = (pdfU * pdfV) * ((width * height) / (pi2 * aten::sin(theta)));

		// u, v -> direction.
		result.dir = AT_NAME::envmap::convertUVToDirection(u, v);

		result.le = envmap->sample(u, v);
		result.intensity = real(1);
		result.finalColor = result.le * result.intensity;
#elif 0
		auto uv = AT_NAME::envmap::convertDirectionToUV(nml);

		static const real radius = real(3);

		auto r1 = sampler->nextSample();
		auto r2 = sampler->nextSample();

		// [0, 1] -> [-1, 1]
		r1 = r1 * 2 - 1;
		r2 = r2 * 2 - 1;

		auto width = envmap->getTexture()->width();
		auto height = envmap->getTexture()->height();

		r1 = r1 * radius / (real)width;
		r2 = r2 * radius / (real)height;

		real u = uv.x + r1;
		if (u < real(0)) {
			u += real(1);
		}
		else if (u > real(1)) {
			u = real(1) - (u - real(1));
		}

		real v = uv.y + r2;
		if (v < real(0)) {
			v += real(1);
		}
		else if (v > real(1)) {
			v = real(1) - (v - real(1));
		}

		// u, v -> direction.
		result.dir = AT_NAME::envmap::convertUVToDirection(u, v);

		result.pdf = dot(nml, result.dir) / AT_MATH_PI;

		result.le = envmap->sample(u, v);
		result.intensity = real(1);
		result.finalColor = result.le * result.intensity;
#else
		auto n = nml;
		auto t = aten::getOrthoVector(nml);
		auto b = normalize(cross(n, t));

		real r1 = sampler->nextSample();
		real r2 = sampler->nextSample();

		real sinpsi = aten::sin(2 * AT_MATH_PI * r1);
		real cospsi = aten::cos(2 * AT_MATH_PI * r1);
		real costheta = aten::pow(1 - r2, 0.5);
		real sintheta = aten::sqrt(1 - costheta * costheta);

		// returnTo the result
		result.dir = normalize(t * sintheta * cospsi + b * sintheta * sinpsi + n * costheta);

		result.pdf = dot(nml, result.dir) / AT_MATH_PI;

		auto uv = AT_NAME::envmap::convertDirectionToUV(result.dir);

		result.le = envmap->sample(uv.x, uv.y);
		result.intensity = real(1);
		result.finalColor = result.le * result.intensity;
#endif

		// TODO
		// Currently not used...
		result.pos = aten::vec3();
		result.nml = aten::vec3();

		return std::move(result);
	}
}<|endoftext|>


<commit_before>#include <mettle/driver/filters.hpp>

namespace mettle {
  filter_result attr_filter::operator ()(const test_name &,
                                         const attributes &attrs) const {
    using detail::join;

    std::set<const attr_instance*> explicitly_shown;
    for(const auto &f : filters_) {
      auto i = attrs.find(f.attribute);
      const attr_instance *attr = i == attrs.end() ? nullptr: &*i;

      if(!f.func(attr))
        return {test_action::hide, attr ? join(attr->value, ", ") : ""};
      else if(attr)
        explicitly_shown.insert(attr);
    }
    for(const auto &attr : attrs) {
      if(attr.attribute.action() == test_action::skip &&
         !explicitly_shown.count(&attr))
        return {test_action::skip, join(attr.value, ", ")};
    }
    return test_action::run;
  }

  filter_result attr_filter_set::operator ()(const test_name &name,
                                             const attributes &attrs) const {
    if(filters_.empty())
      return test_action::indeterminate;

    bool set = false;
    filter_result result;
    for(const auto &f : filters_) {
      auto curr = f(name, attrs);
      switch(curr.action) {
      case test_action::run:
        return curr;
      case test_action::skip:
        if(!set || result.action == test_action::hide) {
          result = curr;
          set = true;
        }
        break;
      case test_action::hide:
        if(!set) {
          result = curr;
          set = true;
        }
        break;
      case test_action::indeterminate:
        assert(false && "unexpected test_action");
      }
    }
    return result;
  }

  filter_result name_filter_set::operator ()(const test_name &name,
                                             const attributes &) const {
    if(filters_.empty())
      return test_action::indeterminate;

    for(const auto &f : filters_) {
      if(std::regex_search(name.full_name(), f))
        return test_action::run;
    }
    return test_action::hide;
  }
}
<commit_msg>Work around the lack of heterogeneous lookup for associative containers in libstdc++<commit_after>#include <mettle/driver/filters.hpp>

namespace mettle {
  filter_result attr_filter::operator ()(const test_name &,
                                         const attributes &attrs) const {
    using detail::join;

    std::set<const attr_instance*> explicitly_shown;
    for(const auto &f : filters_) {
#ifndef __GLIBCXX__
      auto i = attrs.find(f.attribute);
#else
      bool_attr tmp_attr(f.attribute);
      auto i = attrs.find({tmp_attr, {}});
#endif
      const attr_instance *attr = i == attrs.end() ? nullptr: &*i;

      if(!f.func(attr))
        return {test_action::hide, attr ? join(attr->value, ", ") : ""};
      else if(attr)
        explicitly_shown.insert(attr);
    }
    for(const auto &attr : attrs) {
      if(attr.attribute.action() == test_action::skip &&
         !explicitly_shown.count(&attr))
        return {test_action::skip, join(attr.value, ", ")};
    }
    return test_action::run;
  }

  filter_result attr_filter_set::operator ()(const test_name &name,
                                             const attributes &attrs) const {
    if(filters_.empty())
      return test_action::indeterminate;

    bool set = false;
    filter_result result;
    for(const auto &f : filters_) {
      auto curr = f(name, attrs);
      switch(curr.action) {
      case test_action::run:
        return curr;
      case test_action::skip:
        if(!set || result.action == test_action::hide) {
          result = curr;
          set = true;
        }
        break;
      case test_action::hide:
        if(!set) {
          result = curr;
          set = true;
        }
        break;
      case test_action::indeterminate:
        assert(false && "unexpected test_action");
      }
    }
    return result;
  }

  filter_result name_filter_set::operator ()(const test_name &name,
                                             const attributes &) const {
    if(filters_.empty())
      return test_action::indeterminate;

    for(const auto &f : filters_) {
      if(std::regex_search(name.full_name(), f))
        return test_action::run;
    }
    return test_action::hide;
  }
}
<|endoftext|>


<commit_before>/****************************************************************************
**
** Copyright (c) 2011 libmv authors.
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to
** deal in the Software without restriction, including without limitation the
** rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
** sell copies of the Software, and to permit persons to whom the Software is
** furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
** FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
** IN THE SOFTWARE.
**
****************************************************************************/

#include "libmv/tracking/sad.h"
#include <stdlib.h>
#include <math.h>

namespace libmv {

struct vec2 {
  float x,y;
  inline vec2(float x, float y):x(x),y(y){}
};
inline vec2 operator*(mat32 m, vec2 v) {
  return vec2(v.x*m(0,0)+v.y*m(0,1)+m(0,2),v.x*m(1,0)+v.y*m(1,1)+m(1,2));
}

//! fixed point bilinear sample with precision k
template <int k> inline int sample(const ubyte* image,int stride, int x, int y, int u, int v) {
  const ubyte* s = &image[y*stride+x];
  return ((s[     0] * (k-u) + s[       1] * u) * (k-v)
        + (s[stride] * (k-u) + s[stride+1] * u) * (  v) ) / (k*k);
}

#ifdef __SSE__
#include <xmmintrin.h>
int lround(float x) { return _mm_cvtss_si32(_mm_set_ss(x)); }
#elif defined(_MSC_VER)
int lround(float x) { return x+0.5; }
#endif

//TODO(MatthiasF): SSE optimization
void SamplePattern(ubyte* image, int stride, mat32 warp, ubyte* pattern, int size) {
  const int k = 256;
  for (int i = 0; i < size; i++) for (int j = 0; j < size; j++) {
    vec2 p = warp*vec2(j-size/2,i-size/2);
    int fx = lround(p.x*k), fy = lround(p.y*k);
    int ix = fx/k, iy = fy/k;
    int u = fx%k, v = fy%k;
    pattern[i*size+j] = sample<k>(image,stride,ix,iy,u,v);
  }
}

#ifdef __SSE2__
#include <emmintrin.h>
static uint SAD(const ubyte* pattern, const ubyte* image, int stride, int size) {
  __m128i a = _mm_setzero_si128();
  for(int i = 0; i < size; i++) {
    for(int j = 0; j < size/16; j++) {
      a = _mm_adds_epu16(a, _mm_sad_epu8( _mm_loadu_si128((__m128i*)(pattern+i*size+j*16)),
                                          _mm_loadu_si128((__m128i*)(image+i*stride+j*16))));
    }
  }
  return _mm_extract_epi16(a,0) + _mm_extract_epi16(a,4);
}
#else
static uint SAD(const ubyte* pattern, const ubyte* image, int stride, int size) {
  uint sad=0;
  for(int i = 0; i < size; i++) {
    for(int j = 0; j < size; j++) {
      sad += abs((int)pattern[i*size+j] - image[i*stride+j]);
    }
  }
  return sad;
}
#endif

float Track(ubyte* reference, int size, ubyte* image, int stride, int w, int h, mat32* warp) {
  mat32 m=*warp;
  uint min=-1;

  // exhaustive search integer pixel translation
  int ix = m(0,2), iy = m(1,2);
  for(int y = size/2; y < h-size/2; y++) {
    for(int x = size/2; x < w-size/2; x++) {
      m(0,2) = x, m(1,2) = y;
      ubyte match[size*size];
      SamplePattern(image,stride,m,match,size);
      uint sad = SAD(reference,match,size,size);
      if(sad < min) {
        min = sad;
        ix = x, iy = y;
      }
    }
  }
  m(0,2) = ix, m(1,2) = iy;

  // diamond search 6D affine transform
  float step = 0.5;
  for(int p = 0; p < 4; p++) { //foreach precision level
    step /= 2;
    for(int d = 0; d < 10; d++) { //foreach dimension (twice)
      for(float x = -step*2; x <= step*2; x+=step*2) { //test small steps
        mat32 t = m;
        t.data[d] += x;
        if( d<4 && (t.data[d] > 2 || t.data[d] < -2) ) continue; // avoid big distortion
        ubyte match[size*size];
        SamplePattern(image,stride,t,match,size);
        uint sad = SAD(reference,match,size,size);
        if(sad < min) {
          min = sad;
          m = t;
        }
      }
    }
  }
  *warp = m;

  // Compute Pearson product-moment correlation coefficient
  uint sX=0,sY=0,sXX=0,sYY=0,sXY=0;
  ubyte match[size*size];
  SamplePattern(image,stride,m,match,size);
  SAD(reference,match,size,size);
  for(int i = 0; i < size; i++) {
    for(int j = 0; j < size; j++) {
      int x = reference[i*size+j];
      int y = match[i*size+j];
      sX += x;
      sY += y;
      sXX += x*x;
      sYY += y*y;
      sXY += x*y;
    }
  }
  const int N = size*size;
  sX /= N, sY /= N, sXX /= N, sYY /= N, sXY /= N;
  return (sXY-sX*sY)/sqrt((sXX-sX*sX)*(sYY-sY*sY));
}

}  // namespace libmv
<commit_msg>Fix affine iteration.<commit_after>/****************************************************************************
**
** Copyright (c) 2011 libmv authors.
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to
** deal in the Software without restriction, including without limitation the
** rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
** sell copies of the Software, and to permit persons to whom the Software is
** furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
** FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
** IN THE SOFTWARE.
**
****************************************************************************/

#include "libmv/tracking/sad.h"
#include <stdlib.h>
#include <math.h>

namespace libmv {

struct vec2 {
  float x,y;
  inline vec2(float x, float y):x(x),y(y){}
};
inline vec2 operator*(mat32 m, vec2 v) {
  return vec2(v.x*m(0,0)+v.y*m(0,1)+m(0,2),v.x*m(1,0)+v.y*m(1,1)+m(1,2));
}

//! fixed point bilinear sample with precision k
template <int k> inline int sample(const ubyte* image,int stride, int x, int y, int u, int v) {
  const ubyte* s = &image[y*stride+x];
  return ((s[     0] * (k-u) + s[       1] * u) * (k-v)
        + (s[stride] * (k-u) + s[stride+1] * u) * (  v) ) / (k*k);
}

#ifdef __SSE__
#include <xmmintrin.h>
int lround(float x) { return _mm_cvtss_si32(_mm_set_ss(x)); }
#elif defined(_MSC_VER)
int lround(float x) { return x+0.5; }
#endif

//TODO(MatthiasF): SSE optimization
void SamplePattern(ubyte* image, int stride, mat32 warp, ubyte* pattern, int size) {
  const int k = 256;
  for (int i = 0; i < size; i++) for (int j = 0; j < size; j++) {
    vec2 p = warp*vec2(j-size/2,i-size/2);
    int fx = lround(p.x*k), fy = lround(p.y*k);
    int ix = fx/k, iy = fy/k;
    int u = fx%k, v = fy%k;
    pattern[i*size+j] = sample<k>(image,stride,ix,iy,u,v);
  }
}

#ifdef __SSE2__
#include <emmintrin.h>
static uint SAD(const ubyte* pattern, const ubyte* image, int stride, int size) {
  __m128i a = _mm_setzero_si128();
  for(int i = 0; i < size; i++) {
    for(int j = 0; j < size/16; j++) {
      a = _mm_adds_epu16(a, _mm_sad_epu8( _mm_loadu_si128((__m128i*)(pattern+i*size+j*16)),
                                          _mm_loadu_si128((__m128i*)(image+i*stride+j*16))));
    }
  }
  return _mm_extract_epi16(a,0) + _mm_extract_epi16(a,4);
}
#else
static uint SAD(const ubyte* pattern, const ubyte* image, int stride, int size) {
  uint sad=0;
  for(int i = 0; i < size; i++) {
    for(int j = 0; j < size; j++) {
      sad += abs((int)pattern[i*size+j] - image[i*stride+j]);
    }
  }
  return sad;
}
#endif

float Track(ubyte* reference, int size, ubyte* image, int stride, int w, int h, mat32* warp) {
  mat32 m=*warp;
  uint min=-1;

  // exhaustive search integer pixel translation
  int ix = m(0,2), iy = m(1,2);
  for(int y = size/2; y < h-size/2; y++) {
    for(int x = size/2; x < w-size/2; x++) {
      m(0,2) = x, m(1,2) = y;
      ubyte match[size*size];
      SamplePattern(image,stride,m,match,size);
      uint sad = SAD(reference,match,size,size);
      if(sad < min) {
        min = sad;
        ix = x, iy = y;
      }
    }
  }
  m(0,2) = ix, m(1,2) = iy;

  // 6D coordinate descent to find affine transform
  float step = 0.5;
  for(int p = 0; p < 4; p++) { //foreach precision level
    step /= 2;
    for(int i = 0; i < 2; i++) { // iterate twice per precision level
      for(int d = 0; d < 6; d++) { // foreach dimension
        for(float x = -step*2; x <= step*2; x+=step*2) { //test small steps
          mat32 t = m;
          t.data[d] += x;
          if( d<4 && (t.data[d] > 2 || t.data[d] < -2) ) continue; // avoid big distortion
          ubyte match[size*size];
          SamplePattern(image,stride,t,match,size);
          uint sad = SAD(reference,match,size,size);
          if(sad < min) {
            min = sad;
            m = t;
          }
        }
      }
    }
  }
  *warp = m;

  // Compute Pearson product-moment correlation coefficient
  uint sX=0,sY=0,sXX=0,sYY=0,sXY=0;
  ubyte match[size*size];
  SamplePattern(image,stride,m,match,size);
  SAD(reference,match,size,size);
  for(int i = 0; i < size; i++) {
    for(int j = 0; j < size; j++) {
      int x = reference[i*size+j];
      int y = match[i*size+j];
      sX += x;
      sY += y;
      sXX += x*x;
      sYY += y*y;
      sXY += x*y;
    }
  }
  const int N = size*size;
  sX /= N, sY /= N, sXX /= N, sYY /= N, sXY /= N;
  return (sXY-sX*sY)/sqrt((sXX-sX*sX)*(sYY-sY*sY));
}

}  // namespace libmv
<|endoftext|>


<commit_before>/*
 * Copyright 2009-2019 The VOTCA Development Team (http://www.votca.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include "apdft.h"
#include <votca/xtp/density_integration.h>
#include <votca/xtp/orbitals.h>
#include <votca/xtp/vxc_grid.h>

namespace votca {
namespace xtp {

void APDFT::Initialize(tools::Property &opt) {

  std::string key = "opt." + Identify();

  _grid_accuracy =
      opt.ifExistsReturnElseThrowRuntimeError<std::string>(key + ".grid");
  _orbfile =
      opt.ifExistsReturnElseThrowRuntimeError<std::string>(key + ".orbfile");
  _outputfile =
      opt.ifExistsReturnElseThrowRuntimeError<std::string>(key + ".output");
  std::string statestring =
      opt.ifExistsReturnElseThrowRuntimeError<std::string>(key + ".state");
  _state.FromString(statestring);
}

bool APDFT::Evaluate() {

  Orbitals orb;
  orb.ReadFromCpt(_orbfile);
  AOBasis basis = orb.SetupDftBasis();
  Vxc_Grid grid;
  grid.GridSetup(_grid_accuracy, orb.QMAtoms(), basis);

  DensityIntegration<Vxc_Grid> integration(grid);

  integration.IntegrateDensity(orb.DensityMatrixFull(_state));
  std::vector<double> potential_values;
  potential_values.reserve(orb.QMAtoms().size());
  for (const auto &atom : orb.QMAtoms()) {
    potential_values.push_back(integration.IntegratePotential(atom.getPos()));
  }

  std::fstream outfile;
  outfile.open(_outputfile, std::fstream::out);
  outfile << "AtomId, Element, Potential[Hartree]" << std::endl;
  for (Index i = 0; i < orb.QMAtoms().size(); i++) {
    outfile << orb.QMAtoms()[i].getId() << " " << orb.QMAtoms()[i].getElement()
            << " " << potential_values[i] << std::endl;
  }
  outfile.close();
  return true;
}

}  // namespace xtp
}  // namespace votca
<commit_msg>changed orbfile tag to input in options; fixed options tag; increased output precision<commit_after>/*
 * Copyright 2009-2019 The VOTCA Development Team (http://www.votca.org)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

#include "apdft.h"
#include <votca/xtp/density_integration.h>
#include <votca/xtp/orbitals.h>
#include <votca/xtp/vxc_grid.h>

namespace votca {
namespace xtp {

void APDFT::Initialize(tools::Property &opt) {

  std::string key = "options." + Identify();

  _grid_accuracy =
      opt.ifExistsReturnElseThrowRuntimeError<std::string>(key + ".grid");
  _orbfile =
      opt.ifExistsReturnElseThrowRuntimeError<std::string>(key + ".input");
  _outputfile =
      opt.ifExistsReturnElseThrowRuntimeError<std::string>(key + ".output");
  std::string statestring =
      opt.ifExistsReturnElseThrowRuntimeError<std::string>(key + ".state");
  _state.FromString(statestring);
}

bool APDFT::Evaluate() {

  Orbitals orb;
  orb.ReadFromCpt(_orbfile);
  AOBasis basis = orb.SetupDftBasis();
  Vxc_Grid grid;
  grid.GridSetup(_grid_accuracy, orb.QMAtoms(), basis);

  DensityIntegration<Vxc_Grid> integration(grid);

  integration.IntegrateDensity(orb.DensityMatrixFull(_state));
  std::vector<double> potential_values;
  potential_values.reserve(orb.QMAtoms().size());
  for (const auto &atom : orb.QMAtoms()) {
    potential_values.push_back(integration.IntegratePotential(atom.getPos()));
  }

  std::fstream outfile;
  outfile.open(_outputfile, std::fstream::out);
  outfile << "AtomId, Element, Potential[Hartree]" << std::endl;
  for (Index i = 0; i < orb.QMAtoms().size(); i++) {
    outfile << orb.QMAtoms()[i].getId() << " " << orb.QMAtoms()[i].getElement()
            << " " << std::setprecision(14) << potential_values[i] << std::endl;
  }
  outfile.close();
  return true;
}

}  // namespace xtp
}  // namespace votca
<|endoftext|>


<commit_before>#ifndef _PNMC_MC_UNITS_POST_LIVE_HH_
#define _PNMC_MC_UNITS_POST_LIVE_HH_

#include <functional> // hash
#include <iosfwd>

#include <boost/dynamic_bitset.hpp>

#include "sdd/values/flat_set.hh"
#include "sdd/values_manager.hh"

namespace pnmc { namespace mc { namespace units {

/*------------------------------------------------------------------------------------------------*/

struct post_live
{
  /// @brief Target place.
  const unsigned int place;

  /// @brief Transition index.
  const unsigned int transition;

  /// @brief The bitset to update.
  boost::dynamic_bitset<>& bitset;

  /// @brief Constructor.
  post_live(unsigned int place, unsigned int transition, boost::dynamic_bitset<>& bitset);

  /// @brief Apply this operation.
  sdd::values::flat_set<unsigned int>
  operator()(const sdd::values::flat_set<unsigned int>&) const noexcept;
};

/// @brief Equality of two post_live.
bool
operator==(const post_live& lhs, const post_live& rhs) noexcept;

/// @brief Textual output of a post.
std::ostream&
operator<<(std::ostream&, const post_live&);

/*------------------------------------------------------------------------------------------------*/

}}} // namespace pnmc::mc::units

namespace std {

/*------------------------------------------------------------------------------------------------*/

template <>
struct hash<pnmc::mc::units::post_live>
{
  std::size_t operator()(const pnmc::mc::units::post_live&) const noexcept;
};

/*------------------------------------------------------------------------------------------------*/

} // namespace std

#endif // _PNMC_MC_UNITS_POST_LIVE_HH_
<commit_msg>Comment.<commit_after>#ifndef _PNMC_MC_UNITS_POST_LIVE_HH_
#define _PNMC_MC_UNITS_POST_LIVE_HH_

#include <functional> // hash
#include <iosfwd>

#include <boost/dynamic_bitset.hpp>

#include "sdd/values/flat_set.hh"
#include "sdd/values_manager.hh"

namespace pnmc { namespace mc { namespace units {

/*------------------------------------------------------------------------------------------------*/

struct post_live
{
  /// @brief Target place.
  const unsigned int place;

  /// @brief Transition index.
  const unsigned int transition;

  /// @brief The bitset to update.
  boost::dynamic_bitset<>& bitset;

  /// @brief Constructor.
  post_live(unsigned int place, unsigned int transition, boost::dynamic_bitset<>& bitset);

  /// @brief Apply this operation.
  sdd::values::flat_set<unsigned int>
  operator()(const sdd::values::flat_set<unsigned int>&) const noexcept;
};

/// @brief Equality of two post_live.
bool
operator==(const post_live& lhs, const post_live& rhs) noexcept;

/// @brief Textual output of a post_live.
std::ostream&
operator<<(std::ostream&, const post_live&);

/*------------------------------------------------------------------------------------------------*/

}}} // namespace pnmc::mc::units

namespace std {

/*------------------------------------------------------------------------------------------------*/

template <>
struct hash<pnmc::mc::units::post_live>
{
  std::size_t operator()(const pnmc::mc::units::post_live&) const noexcept;
};

/*------------------------------------------------------------------------------------------------*/

} // namespace std

#endif // _PNMC_MC_UNITS_POST_LIVE_HH_
<|endoftext|>


<commit_before>#include "process.hpp"

//////////////
// Includes //
#include <tuple>

#include "image.hpp"

//////////
// Code //

using std::make_tuple;
using std::tuple;
using std::get;

// Verifying the validity of a set of images.
bool validateImages(int count, Image** imgs) {
    for (int i = 1; i < count; i++) {
        if (imgs[i - 1]->width    != imgs[i]->width  ||
            imgs[i - 1]->height   != imgs[i]->height ||
            imgs[i - 1]->maxValue != imgs[i]->maxValue)
            return false;
    }
    return true;
}

// Getting a single pixel at a given index of every image.
Pixel* getPixelsAt(int count, Image** imgs, int index) {
    Pixel* pixels = new Pixel[count];
    for (int i = 0; i < count; i++)
        pixels[i] = imgs[i]->pixels[index];
    return pixels;
}

// Choosing a pixel from a vector of pixels.
Pixel choosePixel(int count, Pixel* pixels) {
    int n = 0;

    Pixel ips[] = {
        Pixel(0, 0, 0),
        Pixel(0, 0, 0)
    };

    for (int i = 0; i < count; i++) {
        if (n == 0)
            ips[1] = pixels[i];

        if (pixels[i] == ips[1])
            n++;
        else
            n--;
    }

    n = 0;
    for (int i = 0; i < count; i++)
        if (pixels[i] == ips[1])
            n++;

    if (n > count / 2)
        return ips[1];
    return ips[0];
}

// Processing a set of images.
Image* processImages(int count, Image** imgs) {
    if (!validateImages(count, imgs))
        return nullptr;

    int length = imgs[0]->width * imgs[0]->height;
    Pixel* finalPixels = new Pixel[length];
    Pixel* pixels;

    for (int i = 0; i < length; i++) {
        pixels = getPixelsAt(count, imgs, i);
        finalPixels[i] = choosePixel(count, pixels);
        delete[] pixels;
    }

    return new Image(finalPixels,
                     imgs[0]->width,
                     imgs[0]->height,
                     imgs[0]->maxValue);
}

// Greyscaling an image.
Image* grayscaleImage(Image* img) {
    int l = img->width * img->height;
    Pixel* grayPixels = new Pixel[l];

    int avg;
    for (int i = 0; i < l; i++) {
        avg = img->pixels[i].sum() / 3;
        grayPixels[i] = Pixel(avg, avg, avg);
    }

    return new Image(grayPixels, img->width, img->height, img->maxValue);
}

// Converting 2D coordinates to a 1D ordinate.
int convertCoords(Image* img, int row, int col) {
    return (row * img->width) + col;
}

// Determining the new column of a column.
int newColumn(Image* img, int col) {
    return img->width - col;
}

// Determining the new row of a row.
int newRow(Image* img, int row) {
    return img->height - row;
}

// Creating a new image based on some vertex transformation.
template <class Function>
Image* vertexTransform(Image* img, Function transform) {
    Pixel* pixels = new Pixel[img->width * img->height];

    for (int row = 0; row < img->height; row++) {
        for (int col = 0; col < img->width; col++) {
            tuple<int, int> tpos = transform(make_tuple(row, col));

            pixels[convertCoords(img, row, col)] =
                img->pixels[convertCoords(img,
                                          get<0>(tpos),
                                          get<1>(tpos))];
        }
    }

    return new Image(pixels, img->width, img->height, img->maxValue);
}

// Flipping an image in the X coordinate.
Image* flipxImage(Image* img) {
    return vertexTransform(img, [=](tuple<int, int> pair) -> tuple<int, int> {
        return make_tuple(get<0>(pair), img->width - get<1>(pair));
    });
}

// Flipping an image in the Y coordinate.
Image* flipyImage(Image* img) {
    return vertexTransform(img, [=](tuple<int, int> pair) -> tuple<int, int> {
        return make_tuple(img->height - get<0>(pair), get<1>(pair));
    });
}
<commit_msg>Fixed an invalid read.<commit_after>#include "process.hpp"

//////////////
// Includes //
#include <tuple>

#include "image.hpp"

//////////
// Code //

using std::make_tuple;
using std::tuple;
using std::get;

// Verifying the validity of a set of images.
bool validateImages(int count, Image** imgs) {
    for (int i = 1; i < count; i++) {
        if (imgs[i - 1]->width    != imgs[i]->width  ||
            imgs[i - 1]->height   != imgs[i]->height ||
            imgs[i - 1]->maxValue != imgs[i]->maxValue)
            return false;
    }
    return true;
}

// Getting a single pixel at a given index of every image.
Pixel* getPixelsAt(int count, Image** imgs, int index) {
    Pixel* pixels = new Pixel[count];
    for (int i = 0; i < count; i++)
        pixels[i] = imgs[i]->pixels[index];
    return pixels;
}

// Choosing a pixel from a vector of pixels.
Pixel choosePixel(int count, Pixel* pixels) {
    int n = 0;

    Pixel ips[] = {
        Pixel(0, 0, 0),
        Pixel(0, 0, 0)
    };

    for (int i = 0; i < count; i++) {
        if (n == 0)
            ips[1] = pixels[i];

        if (pixels[i] == ips[1])
            n++;
        else
            n--;
    }

    n = 0;
    for (int i = 0; i < count; i++)
        if (pixels[i] == ips[1])
            n++;

    if (n > count / 2)
        return ips[1];
    return ips[0];
}

// Processing a set of images.
Image* processImages(int count, Image** imgs) {
    if (!validateImages(count, imgs))
        return nullptr;

    int length = imgs[0]->width * imgs[0]->height;
    Pixel* finalPixels = new Pixel[length];
    Pixel* pixels;

    for (int i = 0; i < length; i++) {
        pixels = getPixelsAt(count, imgs, i);
        finalPixels[i] = choosePixel(count, pixels);
        delete[] pixels;
    }

    return new Image(finalPixels,
                     imgs[0]->width,
                     imgs[0]->height,
                     imgs[0]->maxValue);
}

// Greyscaling an image.
Image* grayscaleImage(Image* img) {
    int l = img->width * img->height;
    Pixel* grayPixels = new Pixel[l];

    int avg;
    for (int i = 0; i < l; i++) {
        avg = img->pixels[i].sum() / 3;
        grayPixels[i] = Pixel(avg, avg, avg);
    }

    return new Image(grayPixels, img->width, img->height, img->maxValue);
}

// Converting 2D coordinates to a 1D ordinate.
int convertCoords(Image* img, int row, int col) {
    return (row * (img->width - 1)) + col;
}

// Creating a new image based on some vertex transformation.
template <class Function>
Image* vertexTransform(Image* img, Function transform) {
    Pixel* pixels = new Pixel[img->width * img->height];

    for (int row = 0; row < img->height; row++) {
        for (int col = 0; col < img->width; col++) {
            tuple<int, int> tpos = transform(make_tuple(row, col));

            pixels[convertCoords(img, row, col)] =
                img->pixels[convertCoords(img,
                                          get<0>(tpos),
                                          get<1>(tpos))];
        }
    }

    return new Image(pixels, img->width, img->height, img->maxValue);
}

// Flipping an image in the X coordinate.
Image* flipxImage(Image* img) {
    return vertexTransform(img, [=](tuple<int, int> pair) -> tuple<int, int> {
        return make_tuple(get<0>(pair), img->width - get<1>(pair));
    });
}

// Flipping an image in the Y coordinate.
Image* flipyImage(Image* img) {
    return vertexTransform(img, [=](tuple<int, int> pair) -> tuple<int, int> {
        return make_tuple(img->height - get<0>(pair), get<1>(pair));
    });
}
<|endoftext|>


<commit_before>#include <babylon/materialslibrary/sky/sky_material.h>

#include <nlohmann/json.hpp>

#include <babylon/cameras/camera.h>
#include <babylon/engines/engine.h>
#include <babylon/engines/scene.h>
#include <babylon/materials/effect.h>
#include <babylon/materials/effect_fallbacks.h>
#include <babylon/materials/ieffect_creation_options.h>
#include <babylon/materials/image_processing_configuration.h>
#include <babylon/materials/material_helper.h>
#include <babylon/materialslibrary/sky/sky_fragment_fx.h>
#include <babylon/materialslibrary/sky/sky_vertex_fx.h>
#include <babylon/meshes/abstract_mesh.h>
#include <babylon/meshes/mesh.h>
#include <babylon/meshes/sub_mesh.h>
#include <babylon/meshes/vertex_buffer.h>

namespace BABYLON {
namespace MaterialsLibrary {

SkyMaterial::SkyMaterial(const std::string& iName, Scene* scene)
    : PushMaterial{iName, scene}
    , luminance{1.f}
    , turbidity{10.f}
    , rayleigh{2.f}
    , mieCoefficient{0.005f}
    , mieDirectionalG{0.8f}
    , distance{500.f}
    , inclination{0.49f}
    , azimuth{0.25f}
    , sunPosition{Vector3(0.f, 100.f, 0.f)}
    , useSunPosition{false}
    , cameraOffset{Vector3::Zero()}
    , up{Vector3::Up()}
    , _cameraPosition{Vector3::Zero()}
{
  // Vertex shader
  Effect::ShadersStore()["skyVertexShader"] = skyVertexShader;

  // Fragment shader
  Effect::ShadersStore()["skyPixelShader"] = skyPixelShader;
}

SkyMaterial::~SkyMaterial() = default;

bool SkyMaterial::needAlphaBlending() const
{
  return (alpha < 1.f);
}

bool SkyMaterial::needAlphaTesting() const
{
  return false;
}

BaseTexturePtr SkyMaterial::getAlphaTestTexture()
{
  return nullptr;
}

bool SkyMaterial::isReadyForSubMesh(AbstractMesh* mesh, SubMesh* subMesh, bool /*useInstances*/)
{
  if (isFrozen()) {
    if (subMesh->effect() && subMesh->effect()->_wasPreviouslyReady) {
      return true;
    }
  }

  if (!subMesh->_materialDefines) {
    subMesh->_materialDefines = std::make_shared<SkyMaterialDefines>();
  }

  auto definesPtr = std::static_pointer_cast<SkyMaterialDefines>(subMesh->_materialDefines);
  auto& defines   = *definesPtr.get();
  auto scene      = getScene();

  if (_isReadyForSubMesh(subMesh)) {
    return true;
  }

  auto engine = scene->getEngine();

  MaterialHelper::PrepareDefinesForMisc(mesh, scene, false, pointsCloud(), fogEnabled(), false,
                                        defines);

  // Attribs
  MaterialHelper::PrepareDefinesForAttributes(mesh, defines, true, false);

  // Get correct effect
  if (defines.isDirty()) {
    defines.markAsProcessed();

    scene->resetCachedMaterial();

    // Fallbacks
    auto fallbacks = std::make_unique<EffectFallbacks>();
    if (defines["FOG"]) {
      fallbacks->addFallback(1, "FOG");
    }

    defines.boolDef["IMAGEPROCESSINGPOSTPROCESS"]
      = scene->imageProcessingConfiguration()->applyByPostProcess();

    // Attributes
    std::vector<std::string> attribs{VertexBuffer::PositionKind};

    if (defines["VERTEXCOLOR"]) {
      attribs.emplace_back(VertexBuffer::ColorKind);
    }

    const std::string shaderName{"sky"};
    auto join = defines.toString();
    const std::vector<std::string> uniforms{"world",          "viewProjection",  "view",
                                            "vFogInfos",      "vFogColor",       "pointSize",
                                            "vClipPlane",     "vClipPlane2",     "vClipPlane3",
                                            "vClipPlane4",    "vClipPlane5",     "vClipPlane6",
                                            "luminance",      "turbidity",       "rayleigh",
                                            "mieCoefficient", "mieDirectionalG", "sunPosition",
                                            "cameraPosition", "cameraOffset",    "up"};
    const std::vector<std::string> samplers{};
    const std::vector<std::string> uniformBuffers{};

    IEffectCreationOptions options;
    options.attributes          = std::move(attribs);
    options.uniformsNames       = std::move(uniforms);
    options.uniformBuffersNames = std::move(uniformBuffers);
    options.samplers            = std::move(samplers);
    options.materialDefines     = &defines;
    options.defines             = std::move(join);
    options.fallbacks           = std::move(fallbacks);
    options.onCompiled          = onCompiled;
    options.onError             = onError;

    subMesh->setEffect(scene->getEngine()->createEffect(shaderName, options, engine), definesPtr);
  }

  if (!subMesh->effect() || !subMesh->effect()->isReady()) {
    return false;
  }

  defines._renderId                      = scene->getRenderId();
  subMesh->effect()->_wasPreviouslyReady = true;

  return true;
}

void SkyMaterial::bindForSubMesh(Matrix& world, Mesh* mesh, SubMesh* subMesh)
{
  auto scene = getScene();

  auto defines = static_cast<SkyMaterialDefines*>(subMesh->_materialDefines.get());
  if (!defines) {
    return;
  }

  auto effect = subMesh->effect();
  if (!effect) {
    return;
  }
  _activeEffect = effect;

  // Matrices
  bindOnlyWorldMatrix(world);
  _activeEffect->setMatrix("viewProjection", scene->getTransformMatrix());

  if (_mustRebind(scene, effect)) {
    // Clip plane
    MaterialHelper::BindClipPlane(_activeEffect, scene);

    // Point size
    if (pointsCloud()) {
      _activeEffect->setFloat("pointSize", pointSize);
    }
  }

  // View
  if (scene->fogEnabled() && mesh->applyFog() && scene->fogMode() != Scene::FOGMODE_NONE) {
    _activeEffect->setMatrix("view", scene->getViewMatrix());
  }

  // Fog
  MaterialHelper::BindFogParameters(scene, mesh, _activeEffect);

  // Sky
  const auto& camera = scene->activeCamera();
  if (camera) {
    const auto& cameraWorldMatrixM = camera->getWorldMatrix().m();
    _cameraPosition.x              = cameraWorldMatrixM[12];
    _cameraPosition.y              = cameraWorldMatrixM[13];
    _cameraPosition.z              = cameraWorldMatrixM[14];
    _activeEffect->setVector3("cameraPosition", _cameraPosition);
  }

  _activeEffect->setVector3("cameraOffset", cameraOffset);

  _activeEffect->setVector3("up", up);

  if (luminance > 0.f) {
    _activeEffect->setFloat("luminance", luminance);
  }

  _activeEffect->setFloat("turbidity", turbidity);
  _activeEffect->setFloat("rayleigh", rayleigh);
  _activeEffect->setFloat("mieCoefficient", mieCoefficient);
  _activeEffect->setFloat("mieDirectionalG", mieDirectionalG);

  if (!useSunPosition) {
    auto theta = Math::PI * (inclination - 0.5f);
    auto phi   = 2.f * Math::PI * (azimuth - 0.5f);

    sunPosition.x = distance * std::cos(phi);
    sunPosition.y = distance * std::sin(phi) * std::sin(theta);
    sunPosition.z = distance * std::sin(phi) * std::cos(theta);

    Quaternion::FromUnitVectorsToRef(Vector3::UpReadOnly(), up, _skyOrientation);
    sunPosition.rotateByQuaternionToRef(_skyOrientation, sunPosition);
  }

  _activeEffect->setVector3("sunPosition", sunPosition);

  _afterBind(mesh, _activeEffect);
}

std::vector<IAnimatablePtr> SkyMaterial::getAnimatables()
{
  return std::vector<IAnimatablePtr>();
}

void SkyMaterial::dispose(bool forceDisposeEffect, bool forceDisposeTextures,
                          bool /*notBoundToMesh*/)
{
  Material::dispose(forceDisposeEffect, forceDisposeTextures);
}

MaterialPtr SkyMaterial::clone(const std::string& /*name*/, bool /*cloneChildren*/) const
{
  return nullptr;
}

json SkyMaterial::serialize() const
{
  return nullptr;
}

std::string SkyMaterial::getClassName() const
{
  return "SkyMaterial";
}

SkyMaterial* SkyMaterial::Parse(const json& /*source*/, Scene* /*scene*/,
                                const std::string& /*rootUrl*/)
{
  return nullptr;
}

} // end of namespace MaterialsLibrary
} // end of namespace BABYLON
<commit_msg>Updated SkyMaterial::isReadyForSubMesh function to pass material context<commit_after>#include <babylon/materialslibrary/sky/sky_material.h>

#include <nlohmann/json.hpp>

#include <babylon/cameras/camera.h>
#include <babylon/engines/engine.h>
#include <babylon/engines/scene.h>
#include <babylon/materials/effect.h>
#include <babylon/materials/effect_fallbacks.h>
#include <babylon/materials/ieffect_creation_options.h>
#include <babylon/materials/image_processing_configuration.h>
#include <babylon/materials/material_helper.h>
#include <babylon/materialslibrary/sky/sky_fragment_fx.h>
#include <babylon/materialslibrary/sky/sky_vertex_fx.h>
#include <babylon/meshes/abstract_mesh.h>
#include <babylon/meshes/mesh.h>
#include <babylon/meshes/sub_mesh.h>
#include <babylon/meshes/vertex_buffer.h>

namespace BABYLON {
namespace MaterialsLibrary {

SkyMaterial::SkyMaterial(const std::string& iName, Scene* scene)
    : PushMaterial{iName, scene}
    , luminance{1.f}
    , turbidity{10.f}
    , rayleigh{2.f}
    , mieCoefficient{0.005f}
    , mieDirectionalG{0.8f}
    , distance{500.f}
    , inclination{0.49f}
    , azimuth{0.25f}
    , sunPosition{Vector3(0.f, 100.f, 0.f)}
    , useSunPosition{false}
    , cameraOffset{Vector3::Zero()}
    , up{Vector3::Up()}
    , _cameraPosition{Vector3::Zero()}
{
  // Vertex shader
  Effect::ShadersStore()["skyVertexShader"] = skyVertexShader;

  // Fragment shader
  Effect::ShadersStore()["skyPixelShader"] = skyPixelShader;
}

SkyMaterial::~SkyMaterial() = default;

bool SkyMaterial::needAlphaBlending() const
{
  return (alpha < 1.f);
}

bool SkyMaterial::needAlphaTesting() const
{
  return false;
}

BaseTexturePtr SkyMaterial::getAlphaTestTexture()
{
  return nullptr;
}

bool SkyMaterial::isReadyForSubMesh(AbstractMesh* mesh, SubMesh* subMesh, bool /*useInstances*/)
{
  if (isFrozen()) {
    if (subMesh->effect() && subMesh->effect()->_wasPreviouslyReady) {
      return true;
    }
  }

  if (!subMesh->_materialDefines) {
    subMesh->materialDefines = std::make_shared<SkyMaterialDefines>();
  }

  auto definesPtr = std::static_pointer_cast<SkyMaterialDefines>(subMesh->_materialDefines);
  auto& defines   = *definesPtr.get();
  auto scene      = getScene();

  if (_isReadyForSubMesh(subMesh)) {
    return true;
  }

  auto engine = scene->getEngine();

  MaterialHelper::PrepareDefinesForMisc(mesh, scene, false, pointsCloud(), fogEnabled(), false,
                                        defines);

  // Attribs
  MaterialHelper::PrepareDefinesForAttributes(mesh, defines, true, false);

  // Get correct effect
  if (defines.isDirty()) {
    defines.markAsProcessed();

    scene->resetCachedMaterial();

    // Fallbacks
    auto fallbacks = std::make_unique<EffectFallbacks>();
    if (defines["FOG"]) {
      fallbacks->addFallback(1, "FOG");
    }

    defines.boolDef["IMAGEPROCESSINGPOSTPROCESS"]
      = scene->imageProcessingConfiguration()->applyByPostProcess();

    // Attributes
    std::vector<std::string> attribs{VertexBuffer::PositionKind};

    if (defines["VERTEXCOLOR"]) {
      attribs.emplace_back(VertexBuffer::ColorKind);
    }

    const std::string shaderName{"sky"};
    auto join = defines.toString();
    const std::vector<std::string> uniforms{"world",          "viewProjection",  "view",
                                            "vFogInfos",      "vFogColor",       "pointSize",
                                            "vClipPlane",     "vClipPlane2",     "vClipPlane3",
                                            "vClipPlane4",    "vClipPlane5",     "vClipPlane6",
                                            "luminance",      "turbidity",       "rayleigh",
                                            "mieCoefficient", "mieDirectionalG", "sunPosition",
                                            "cameraPosition", "cameraOffset",    "up"};
    const std::vector<std::string> samplers{};
    const std::vector<std::string> uniformBuffers{};

    IEffectCreationOptions options;
    options.attributes          = std::move(attribs);
    options.uniformsNames       = std::move(uniforms);
    options.uniformBuffersNames = std::move(uniformBuffers);
    options.samplers            = std::move(samplers);
    options.materialDefines     = &defines;
    options.defines             = std::move(join);
    options.fallbacks           = std::move(fallbacks);
    options.onCompiled          = onCompiled;
    options.onError             = onError;

    subMesh->setEffect(scene->getEngine()->createEffect(shaderName, options, engine), definesPtr,
                       _materialContext);
  }

  if (!subMesh->effect() || !subMesh->effect()->isReady()) {
    return false;
  }

  defines._renderId                      = scene->getRenderId();
  subMesh->effect()->_wasPreviouslyReady = true;

  return true;
}

void SkyMaterial::bindForSubMesh(Matrix& world, Mesh* mesh, SubMesh* subMesh)
{
  auto scene = getScene();

  auto defines = static_cast<SkyMaterialDefines*>(subMesh->_materialDefines.get());
  if (!defines) {
    return;
  }

  auto effect = subMesh->effect();
  if (!effect) {
    return;
  }
  _activeEffect = effect;

  // Matrices
  bindOnlyWorldMatrix(world);
  _activeEffect->setMatrix("viewProjection", scene->getTransformMatrix());

  if (_mustRebind(scene, effect)) {
    // Clip plane
    MaterialHelper::BindClipPlane(_activeEffect, scene);

    // Point size
    if (pointsCloud()) {
      _activeEffect->setFloat("pointSize", pointSize);
    }
  }

  // View
  if (scene->fogEnabled() && mesh->applyFog() && scene->fogMode() != Scene::FOGMODE_NONE) {
    _activeEffect->setMatrix("view", scene->getViewMatrix());
  }

  // Fog
  MaterialHelper::BindFogParameters(scene, mesh, _activeEffect);

  // Sky
  const auto& camera = scene->activeCamera();
  if (camera) {
    const auto& cameraWorldMatrixM = camera->getWorldMatrix().m();
    _cameraPosition.x              = cameraWorldMatrixM[12];
    _cameraPosition.y              = cameraWorldMatrixM[13];
    _cameraPosition.z              = cameraWorldMatrixM[14];
    _activeEffect->setVector3("cameraPosition", _cameraPosition);
  }

  _activeEffect->setVector3("cameraOffset", cameraOffset);

  _activeEffect->setVector3("up", up);

  if (luminance > 0.f) {
    _activeEffect->setFloat("luminance", luminance);
  }

  _activeEffect->setFloat("turbidity", turbidity);
  _activeEffect->setFloat("rayleigh", rayleigh);
  _activeEffect->setFloat("mieCoefficient", mieCoefficient);
  _activeEffect->setFloat("mieDirectionalG", mieDirectionalG);

  if (!useSunPosition) {
    auto theta = Math::PI * (inclination - 0.5f);
    auto phi   = 2.f * Math::PI * (azimuth - 0.5f);

    sunPosition.x = distance * std::cos(phi);
    sunPosition.y = distance * std::sin(phi) * std::sin(theta);
    sunPosition.z = distance * std::sin(phi) * std::cos(theta);

    Quaternion::FromUnitVectorsToRef(Vector3::UpReadOnly(), up, _skyOrientation);
    sunPosition.rotateByQuaternionToRef(_skyOrientation, sunPosition);
  }

  _activeEffect->setVector3("sunPosition", sunPosition);

  _afterBind(mesh, _activeEffect);
}

std::vector<IAnimatablePtr> SkyMaterial::getAnimatables()
{
  return std::vector<IAnimatablePtr>();
}

void SkyMaterial::dispose(bool forceDisposeEffect, bool forceDisposeTextures,
                          bool /*notBoundToMesh*/)
{
  Material::dispose(forceDisposeEffect, forceDisposeTextures);
}

MaterialPtr SkyMaterial::clone(const std::string& /*name*/, bool /*cloneChildren*/) const
{
  return nullptr;
}

json SkyMaterial::serialize() const
{
  return nullptr;
}

std::string SkyMaterial::getClassName() const
{
  return "SkyMaterial";
}

SkyMaterial* SkyMaterial::Parse(const json& /*source*/, Scene* /*scene*/,
                                const std::string& /*rootUrl*/)
{
  return nullptr;
}

} // end of namespace MaterialsLibrary
} // end of namespace BABYLON
<|endoftext|>


<commit_before>#include <silicium/process.hpp>
#include <silicium/build_result.hpp>
#include <silicium/to_unique.hpp>
#include <silicium/read_file.hpp>
#include <silicium/write_file.hpp>
#include <silicium/directory_builder.hpp>
#include <silicium/tcp_trigger.hpp>
#include <silicium/git/repository.hpp>
#include <boost/filesystem/operations.hpp>

namespace
{
	boost::filesystem::path make_last_built_file_name(boost::filesystem::path const &output_location)
	{
		return output_location / ("lastbuild.txt");
	}

	boost::optional<git_oid> get_last_built(boost::filesystem::path const &last_build_file_name)
	{
		if (!boost::filesystem::exists(last_build_file_name))
		{
			return boost::none;
		}
		auto str = Si::read_file(last_build_file_name);
		git_oid id;
		Si::git::throw_if_libgit2_error(git_oid_fromstrn(&id, str.data(), str.size()));
		return id;
	}

	void set_last_built(
			git_repository &repository,
			boost::filesystem::path const &last_build_file_name,
			git_reference const &built)
	{
		char const * const name = git_reference_name(&built);
		git_oid commit_id;
		Si::git::throw_if_libgit2_error(git_reference_name_to_id(&commit_id, &repository, name));
		auto const id_str = Si::git::format_oid(commit_id);
		Si::write_file(last_build_file_name, id_str.data(), id_str.size());
	}

	void clone(
			std::string const &branch,
			std::string const &source_location,
			boost::filesystem::path const &cloned_dir)
	{
		git_clone_options options = GIT_CLONE_OPTIONS_INIT;
		options.checkout_branch = branch.c_str(); //TODO: clone the reference directly without repeating the branch name
		Si::git::clone(source_location, cloned_dir, &options);
	}

	void push(
			boost::filesystem::path const &repository,
			Si::sink<char> *git_log,
			std::string message)
	{
		{
			Si::process_parameters parameters;
			parameters.executable = "/usr/bin/git";
			parameters.arguments = {"add", "-A", "."};
			parameters.current_path = repository;
			parameters.stdout = git_log;
			int const exit_code = Si::run_process(parameters);
			if (exit_code != 0)
			{
				throw std::runtime_error{"git add failed"};
			}
		}

		{
			Si::process_parameters parameters;
			parameters.executable = "/usr/bin/git";
			parameters.arguments = {"commit", "-m", std::move(message)};
			parameters.current_path = repository;
			parameters.stdout = git_log;
			int const exit_code = Si::run_process(parameters);
			if (exit_code != 0)
			{
				throw std::runtime_error{"git commit failed"};
			}
		}

		{
			Si::process_parameters parameters;
			parameters.executable = "/usr/bin/git";
			parameters.arguments = {"push"};
			parameters.current_path = repository;
			parameters.stdout = git_log;
			int const exit_code = Si::run_process(parameters);
			if (exit_code != 0)
			{
				throw std::runtime_error{"git push failed"};
			}
		}
	}

	Si::build_result make(
			boost::filesystem::path const &source,
			boost::filesystem::path const &build_dir,
			Si::directory_builder &artifacts)
	{
		if (Si::run_process("/usr/bin/cmake", {source.string()}, build_dir, *artifacts.begin_artifact("cmake.log")) != 0)
		{
			return Si::build_failure{"CMake failed"};
		}
		if (Si::run_process("/usr/bin/make", {"-j2"}, build_dir, *artifacts.begin_artifact("make.log")) != 0)
		{
			return Si::build_failure{"make failed"};
		}
		if (Si::run_process("test/test", {}, build_dir, *artifacts.begin_artifact("test.log")) != 0)
		{
			return Si::build_failure{"tests failed"};
		}
		return Si::build_success{};
	}

	Si::build_result build_commit(
			std::string const &branch,
			std::string const &source_location,
			boost::filesystem::path const &commit_dir,
			Si::directory_builder &reports)
	{
		auto const cloned_dir = commit_dir / "source";
		clone(branch, source_location, cloned_dir);

		auto const build_dir = commit_dir / "build";
		boost::filesystem::create_directories(build_dir);
		return make(cloned_dir, build_dir, reports);
	}

	void check_build(
			boost::filesystem::path const &source_location,
			std::string const &branch,
			boost::filesystem::path const &workspace)
	{
		auto const source = Si::git::open_repository(source_location);
		auto const full_branch_name = ("refs/heads/" + branch);
		auto const ref_to_build = Si::git::lookup(*source, full_branch_name.c_str());
		if (!ref_to_build)
		{
			throw std::runtime_error(branch + " branch does not exist");
		}
		git_oid oid_to_build;
		Si::git::throw_if_libgit2_error(git_reference_name_to_id(&oid_to_build, source.get(), full_branch_name.c_str()));
		auto const results_repository = workspace / "results.git";
		auto const last_built_file_name = make_last_built_file_name(results_repository);
		auto const ref_last_built = get_last_built(last_built_file_name);
		if (ref_last_built &&
			git_oid_equal(&*ref_last_built, &oid_to_build))
		{
			//nothing to do
			return;
		}

		auto const formatted_build_oid = Si::git::format_oid(oid_to_build);
		auto const temporary_location = workspace / formatted_build_oid;
		boost::filesystem::create_directories(temporary_location);

		Si::filesystem_directory_builder results(results_repository);
		auto const reports = results.create_subdirectory(formatted_build_oid);
		build_commit(branch, source_location.string(), temporary_location, *reports);
		set_last_built(*source, last_built_file_name, *ref_to_build);

		auto git_log = Si::make_file_sink(temporary_location / "git_commit.log");
		push(results_repository, git_log.get(), "built by silicium");
	}
}

int main(int argc, char **argv)
{
	if (argc < 3)
	{
		return 1;
	}
	boost::filesystem::path const source_location = argv[1];
	boost::filesystem::path const workspace = argv[2];

	auto const build = [&]
	{
		try
		{
			check_build(source_location, "master", workspace);
		}
		catch (std::exception const &ex)
		{
			//continue to run
			std::cerr << ex.what() << '\n';
		}
	};

	boost::asio::io_service io;
	Si::tcp_trigger external_build_trigger(io, boost::asio::ip::tcp::endpoint(boost::asio::ip::address_v4(), 12345));
	std::function<void ()> wait_for_trigger;
	wait_for_trigger = [&wait_for_trigger, &external_build_trigger, &build]
	{
		external_build_trigger.async_wait([&wait_for_trigger, &build]
		{
			build();
			wait_for_trigger();
		});
	};
	wait_for_trigger();

	build();
	io.run();
}
<commit_msg>make -j factor is no longer hard-coded<commit_after>#include <silicium/process.hpp>
#include <silicium/build_result.hpp>
#include <silicium/to_unique.hpp>
#include <silicium/read_file.hpp>
#include <silicium/write_file.hpp>
#include <silicium/directory_builder.hpp>
#include <silicium/tcp_trigger.hpp>
#include <silicium/git/repository.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/filesystem/operations.hpp>

namespace
{
	boost::filesystem::path make_last_built_file_name(boost::filesystem::path const &output_location)
	{
		return output_location / ("lastbuild.txt");
	}

	boost::optional<git_oid> get_last_built(boost::filesystem::path const &last_build_file_name)
	{
		if (!boost::filesystem::exists(last_build_file_name))
		{
			return boost::none;
		}
		auto str = Si::read_file(last_build_file_name);
		git_oid id;
		Si::git::throw_if_libgit2_error(git_oid_fromstrn(&id, str.data(), str.size()));
		return id;
	}

	void set_last_built(
			git_repository &repository,
			boost::filesystem::path const &last_build_file_name,
			git_reference const &built)
	{
		char const * const name = git_reference_name(&built);
		git_oid commit_id;
		Si::git::throw_if_libgit2_error(git_reference_name_to_id(&commit_id, &repository, name));
		auto const id_str = Si::git::format_oid(commit_id);
		Si::write_file(last_build_file_name, id_str.data(), id_str.size());
	}

	void clone(
			std::string const &branch,
			std::string const &source_location,
			boost::filesystem::path const &cloned_dir)
	{
		git_clone_options options = GIT_CLONE_OPTIONS_INIT;
		options.checkout_branch = branch.c_str(); //TODO: clone the reference directly without repeating the branch name
		Si::git::clone(source_location, cloned_dir, &options);
	}

	void push(
			boost::filesystem::path const &repository,
			Si::sink<char> *git_log,
			std::string message)
	{
		{
			Si::process_parameters parameters;
			parameters.executable = "/usr/bin/git";
			parameters.arguments = {"add", "-A", "."};
			parameters.current_path = repository;
			parameters.stdout = git_log;
			int const exit_code = Si::run_process(parameters);
			if (exit_code != 0)
			{
				throw std::runtime_error{"git add failed"};
			}
		}

		{
			Si::process_parameters parameters;
			parameters.executable = "/usr/bin/git";
			parameters.arguments = {"commit", "-m", std::move(message)};
			parameters.current_path = repository;
			parameters.stdout = git_log;
			int const exit_code = Si::run_process(parameters);
			if (exit_code != 0)
			{
				throw std::runtime_error{"git commit failed"};
			}
		}

		{
			Si::process_parameters parameters;
			parameters.executable = "/usr/bin/git";
			parameters.arguments = {"push"};
			parameters.current_path = repository;
			parameters.stdout = git_log;
			int const exit_code = Si::run_process(parameters);
			if (exit_code != 0)
			{
				throw std::runtime_error{"git push failed"};
			}
		}
	}

	Si::build_result run_tests(
			boost::filesystem::path const &source,
			boost::filesystem::path const &build_dir,
			Si::directory_builder &artifacts,
			unsigned parallelization)
	{
		if (Si::run_process("/usr/bin/cmake", {source.string()}, build_dir, *artifacts.begin_artifact("cmake.log")) != 0)
		{
			return Si::build_failure{"CMake failed"};
		}
		if (Si::run_process("/usr/bin/make", {"-j" + boost::lexical_cast<std::string>(parallelization)}, build_dir, *artifacts.begin_artifact("make.log")) != 0)
		{
			return Si::build_failure{"make failed"};
		}
		if (Si::run_process("test/test", {}, build_dir, *artifacts.begin_artifact("test.log")) != 0)
		{
			return Si::build_failure{"tests failed"};
		}
		return Si::build_success{};
	}

	Si::build_result build_commit(
			std::string const &branch,
			std::string const &source_location,
			boost::filesystem::path const &commit_dir,
			Si::directory_builder &reports,
			unsigned parallelization)
	{
		auto const cloned_dir = commit_dir / "source";
		clone(branch, source_location, cloned_dir);

		auto const build_dir = commit_dir / "build";
		boost::filesystem::create_directories(build_dir);
		return run_tests(cloned_dir, build_dir, reports, parallelization);
	}

	void check_build(
			boost::filesystem::path const &source_location,
			std::string const &branch,
			boost::filesystem::path const &workspace,
			unsigned parallelization)
	{
		auto const source = Si::git::open_repository(source_location);
		auto const full_branch_name = ("refs/heads/" + branch);
		auto const ref_to_build = Si::git::lookup(*source, full_branch_name.c_str());
		if (!ref_to_build)
		{
			throw std::runtime_error(branch + " branch does not exist");
		}
		git_oid oid_to_build;
		Si::git::throw_if_libgit2_error(git_reference_name_to_id(&oid_to_build, source.get(), full_branch_name.c_str()));
		auto const results_repository = workspace / "results.git";
		auto const last_built_file_name = make_last_built_file_name(results_repository);
		auto const ref_last_built = get_last_built(last_built_file_name);
		if (ref_last_built &&
			git_oid_equal(&*ref_last_built, &oid_to_build))
		{
			//nothing to do
			return;
		}

		auto const formatted_build_oid = Si::git::format_oid(oid_to_build);
		auto const temporary_location = workspace / formatted_build_oid;
		boost::filesystem::create_directories(temporary_location);

		Si::filesystem_directory_builder results(results_repository);
		auto const reports = results.create_subdirectory(formatted_build_oid);
		build_commit(branch, source_location.string(), temporary_location, *reports, parallelization);
		set_last_built(*source, last_built_file_name, *ref_to_build);

		auto git_log = Si::make_file_sink(temporary_location / "git_commit.log");
		push(results_repository, git_log.get(), "built by silicium");
	}
}

int main(int argc, char **argv)
{
	if (argc < 3)
	{
		return 1;
	}
	boost::filesystem::path const source_location = argv[1];
	boost::filesystem::path const workspace = argv[2];
	unsigned parallelization = 1;
	if (argc >= 4)
	{
		parallelization = boost::lexical_cast<unsigned>(argv[3]);
	}

	auto const build = [&]
	{
		try
		{
			check_build(source_location, "master", workspace, parallelization);
		}
		catch (std::exception const &ex)
		{
			//continue to run
			std::cerr << ex.what() << '\n';
		}
	};

	boost::asio::io_service io;
	Si::tcp_trigger external_build_trigger(io, boost::asio::ip::tcp::endpoint(boost::asio::ip::address_v4(), 12345));
	std::function<void ()> wait_for_trigger;
	wait_for_trigger = [&wait_for_trigger, &external_build_trigger, &build]
	{
		external_build_trigger.async_wait([&wait_for_trigger, &build]
		{
			build();
			wait_for_trigger();
		});
	};
	wait_for_trigger();

	build();
	io.run();
}
<|endoftext|>


<commit_before>//
// Physical page allocator.
// Slab allocator, for chunks larger than one page.
//

#include "types.h"
#include "mmu.h"
#include "kernel.hh"
#include "spinlock.h"
#include "kalloc.hh"
#include "mtrace.h"
#include "cpu.hh"
#include "multiboot.hh"
#include "wq.hh"

static struct Mbmem mem[128];
static u64 nmem;
static u64 membytes;
struct kmem kmems[NCPU];
struct kmem slabmem[slab_type_max][NCPU];

extern char end[]; // first address after kernel loaded from ELF file
char *newend;

static int kinited __mpalign__;

static struct Mbmem *
memsearch(paddr pa)
{
  struct Mbmem *e;
  struct Mbmem *q;

  q = mem+nmem;
  for (e = &mem[0]; e < q; e++)
    if ((e->base <= pa) && ((e->base+e->length) > pa))
      return e;
  return 0;
}

static u64
memsize(void *va)
{
  struct Mbmem *e;
  paddr pa = v2p(va);

  e = memsearch(pa);
  if (e == nullptr)
    return -1;
  return (e->base+e->length) - pa;
}

static void *
memnext(void *va, u64 inc)
{
  struct Mbmem *e, *q;
  paddr pa = v2p(va);

  e = memsearch(pa);
  if (e == nullptr)
    return (void *)-1;

  pa += inc;
  if (pa < (e->base+e->length))
    return p2v(pa);

  q = mem+nmem;
  for (e = e + 1; e < q; e++)
      return p2v(e->base);

  return (void *)-1;
}

static void
initmem(u64 mbaddr)
{
  struct Mbdata *mb;
  struct Mbmem *mbmem;
  u8 *p, *ep;

  mb = (Mbdata*) p2v(mbaddr);
  if(!(mb->flags & (1<<6)))
    panic("multiboot header has no memory map");

  p = (u8*) p2v(mb->mmap_addr);
  ep = p + mb->mmap_length;

  while (p < ep) {
    mbmem = (Mbmem *)(p+4);
    p += 4 + *(u32*)p;
    if (mbmem->type == 1 && mbmem->base >= 0x100000) {
      membytes += mbmem->length;
      mem[nmem] = *mbmem;
      nmem++;
    }
  }
}

// simple page allocator to get off the ground during boot
static char *
pgalloc(void)
{
  if (newend == 0)
    newend = end;

  void *p = (void*)PGROUNDUP((uptr)newend);
  memset(p, 0, PGSIZE);
  newend = newend + PGSIZE;
  return (char*) p;
}

//
// kmem
//
run*
kmem::alloc(const char* name)
{
  run* r;

  for (;;) {
    auto headval = freelist.load();
    r = headval.ptr();
    if (!r)
      return nullptr;

    run *nxt = r->next;
    if (freelist.compare_exchange(headval, nxt)) {
      if (r->next != nxt)
        panic("kmem:alloc: aba race %p %p %p\n",
              r, r->next, nxt);
      nfree--;
      if (name)
        mtlabel(mtrace_label_block, r, size, name, strlen(name));
      return r;
    }
  }
}

void
kmem::free(run* r)
{
  if (kinited)
    mtunlabel(mtrace_label_block, r);

  for (;;) {
    auto headval = freelist.load();
    r->next = headval.ptr();
    if (freelist.compare_exchange(headval, r))
      break;
  }
  nfree++;
}

// Free the page of physical memory pointed at by v,
// which normally should have been returned by a
// call to kalloc().  (The exception is when
// initializing the allocator; see kinit above.)
static void
kfree_pool(struct kmem *m, char *v)
{
  if ((uptr)v % PGSIZE)
    panic("kfree_pool: misaligned %p", v);
  if (memsize(v) == -1ull)
    panic("kfree_pool: unknown region %p", v);

  // Fill with junk to catch dangling refs.
  if (ALLOC_MEMSET && kinited && m->size <= 16384)
    memset(v, 1, m->size);

  m->free((run*)v);
}

static void
kmemprint_pool(struct kmem *km)
{
  cprintf("pool %s: [ ", &km[0].name[1]);
  for (u32 i = 0; i < NCPU; i++)
    if (i == mycpu()->id)
      cprintf("<%lu> ", km[i].nfree.load());
    else
      cprintf("%lu ", km[i].nfree.load());
  cprintf("]\n");
}

void
kmemprint()
{
  kmemprint_pool(kmems);
  for (int i = 0; i < slab_type_max; i++)
    kmemprint_pool(slabmem[i]);
}

static char*
kalloc_pool(struct kmem *km, const char *name)
{
  struct run *r = 0;
  struct kmem *m;

  u32 startcpu = mycpu()->id;
  for (u32 i = 0; r == 0 && i < NCPU; i++) {
    int cn = (i + startcpu) % NCPU;
    m = &km[cn];
    r = m->alloc(name);
  }

  if (r == 0) {
    cprintf("kalloc: out of memory in pool %s\n", km->name);
    // kmemprint();
    return 0;
  }

  if (ALLOC_MEMSET && m->size <= 16384)
    memset(r, 2, m->size);
  return (char*)r;
}

// Allocate one 4096-byte page of physical memory.
// Returns a pointer that the kernel can use.
// Returns 0 if the memory cannot be allocated.
char*
kalloc(const char *name)
{
  if (!kinited)
    return pgalloc();
  return kalloc_pool(kmems, name);
}

void *
ksalloc(int slab)
{
  return kalloc_pool(slabmem[slab], slabmem[slab]->name);
}

void
slabinit(struct kmem *k, char **p, u64 *off)
{
  for (int i = 0; i < k->ninit; i++) {
    if (*p == (void *)-1)
      panic("slabinit: memnext");
    // XXX(sbw) handle this condition
    if (memsize(p) < k->size)
      panic("slabinit: memsize");
    kfree_pool(k, *p);
    *p = (char*) memnext(*p, k->size);
    *off = *off+k->size;
  }
}

// Initialize free list of physical pages.
void
initkalloc(u64 mbaddr)
{
  char *p;
  u64 n;
  u64 k;

  initmem(mbaddr);

  for (int c = 0; c < NCPU; c++) {
    kmems[c].name[0] = (char) c + '0';
    safestrcpy(kmems[c].name+1, "kmem", MAXNAME-1);
    kmems[c].size = PGSIZE;
  }

  if (VERBOSE)
    cprintf("%lu mbytes\n", membytes / (1<<20));
  n = membytes / NCPU;
  if (n & (PGSIZE-1))
    n = PGROUNDDOWN(n);

  p = (char*)PGROUNDUP((uptr)newend);
  k = (((uptr)p) - KCODE);
  p = (char*) KBASE + k;
  for (int c = 0; c < NCPU; c++) {
    // Fill slab allocators
    strncpy(slabmem[slab_stack][c].name, " kstack", MAXNAME);
    slabmem[slab_stack][c].size = KSTACKSIZE;
    slabmem[slab_stack][c].ninit = CPUKSTACKS;

    strncpy(slabmem[slab_perf][c].name, " kperf", MAXNAME);
    slabmem[slab_perf][c].size = PERFSIZE;
    slabmem[slab_perf][c].ninit = 1;

    strncpy(slabmem[slab_kshared][c].name, " kshared", MAXNAME);
    slabmem[slab_kshared][c].size = KSHAREDSIZE;
    slabmem[slab_kshared][c].ninit = CPUKSTACKS;

    strncpy(slabmem[slab_wq][c].name, " wq", MAXNAME);
    slabmem[slab_wq][c].size = PGROUNDUP(wq_size());
    slabmem[slab_wq][c].ninit = 2;

    strncpy(slabmem[slab_userwq][c].name, " uwq", MAXNAME);
    slabmem[slab_userwq][c].size = USERWQSIZE;
    slabmem[slab_userwq][c].ninit = CPUKSTACKS;

    for (int i = 0; i < slab_type_max; i++) {
      slabmem[i][c].name[0] = (char) c + '0';
      slabinit(&slabmem[i][c], &p, &k);
    }

    // The rest goes to the page allocator
    for (; k != n; k += PGSIZE, p = (char*) memnext(p, PGSIZE)) {
      if (p == (void *)-1)
        panic("initkalloc: e820next");
      kfree_pool(&kmems[c], p);
    }

    k = 0;
  }

  kminit();
  kinited = 1;
}

void
kfree(void *v)
{
  kfree_pool(mykmem(), (char*) v);
}

void
ksfree(int slab, void *v)
{
  kfree_pool(slabmem[slab], (char*) v);
}
<commit_msg>Free to our CPU's slab, not to CPU 0's slab<commit_after>//
// Physical page allocator.
// Slab allocator, for chunks larger than one page.
//

#include "types.h"
#include "mmu.h"
#include "kernel.hh"
#include "spinlock.h"
#include "kalloc.hh"
#include "mtrace.h"
#include "cpu.hh"
#include "multiboot.hh"
#include "wq.hh"

static struct Mbmem mem[128];
static u64 nmem;
static u64 membytes;
struct kmem kmems[NCPU];
struct kmem slabmem[slab_type_max][NCPU];

extern char end[]; // first address after kernel loaded from ELF file
char *newend;

static int kinited __mpalign__;

static struct Mbmem *
memsearch(paddr pa)
{
  struct Mbmem *e;
  struct Mbmem *q;

  q = mem+nmem;
  for (e = &mem[0]; e < q; e++)
    if ((e->base <= pa) && ((e->base+e->length) > pa))
      return e;
  return 0;
}

static u64
memsize(void *va)
{
  struct Mbmem *e;
  paddr pa = v2p(va);

  e = memsearch(pa);
  if (e == nullptr)
    return -1;
  return (e->base+e->length) - pa;
}

static void *
memnext(void *va, u64 inc)
{
  struct Mbmem *e, *q;
  paddr pa = v2p(va);

  e = memsearch(pa);
  if (e == nullptr)
    return (void *)-1;

  pa += inc;
  if (pa < (e->base+e->length))
    return p2v(pa);

  q = mem+nmem;
  for (e = e + 1; e < q; e++)
      return p2v(e->base);

  return (void *)-1;
}

static void
initmem(u64 mbaddr)
{
  struct Mbdata *mb;
  struct Mbmem *mbmem;
  u8 *p, *ep;

  mb = (Mbdata*) p2v(mbaddr);
  if(!(mb->flags & (1<<6)))
    panic("multiboot header has no memory map");

  p = (u8*) p2v(mb->mmap_addr);
  ep = p + mb->mmap_length;

  while (p < ep) {
    mbmem = (Mbmem *)(p+4);
    p += 4 + *(u32*)p;
    if (mbmem->type == 1 && mbmem->base >= 0x100000) {
      membytes += mbmem->length;
      mem[nmem] = *mbmem;
      nmem++;
    }
  }
}

// simple page allocator to get off the ground during boot
static char *
pgalloc(void)
{
  if (newend == 0)
    newend = end;

  void *p = (void*)PGROUNDUP((uptr)newend);
  memset(p, 0, PGSIZE);
  newend = newend + PGSIZE;
  return (char*) p;
}

//
// kmem
//
run*
kmem::alloc(const char* name)
{
  run* r;

  for (;;) {
    auto headval = freelist.load();
    r = headval.ptr();
    if (!r)
      return nullptr;

    run *nxt = r->next;
    if (freelist.compare_exchange(headval, nxt)) {
      if (r->next != nxt)
        panic("kmem:alloc: aba race %p %p %p\n",
              r, r->next, nxt);
      nfree--;
      if (name)
        mtlabel(mtrace_label_block, r, size, name, strlen(name));
      return r;
    }
  }
}

void
kmem::free(run* r)
{
  if (kinited)
    mtunlabel(mtrace_label_block, r);

  for (;;) {
    auto headval = freelist.load();
    r->next = headval.ptr();
    if (freelist.compare_exchange(headval, r))
      break;
  }
  nfree++;
}

// Free the page of physical memory pointed at by v,
// which normally should have been returned by a
// call to kalloc().  (The exception is when
// initializing the allocator; see kinit above.)
static void
kfree_pool(struct kmem *m, char *v)
{
  if ((uptr)v % PGSIZE)
    panic("kfree_pool: misaligned %p", v);
  if (memsize(v) == -1ull)
    panic("kfree_pool: unknown region %p", v);

  // Fill with junk to catch dangling refs.
  if (ALLOC_MEMSET && kinited && m->size <= 16384)
    memset(v, 1, m->size);

  m->free((run*)v);
}

static void
kmemprint_pool(struct kmem *km)
{
  cprintf("pool %s: [ ", &km[0].name[1]);
  for (u32 i = 0; i < NCPU; i++)
    if (i == mycpu()->id)
      cprintf("<%lu> ", km[i].nfree.load());
    else
      cprintf("%lu ", km[i].nfree.load());
  cprintf("]\n");
}

void
kmemprint()
{
  kmemprint_pool(kmems);
  for (int i = 0; i < slab_type_max; i++)
    kmemprint_pool(slabmem[i]);
}

static char*
kalloc_pool(struct kmem *km, const char *name)
{
  struct run *r = 0;
  struct kmem *m;

  u32 startcpu = mycpu()->id;
  for (u32 i = 0; r == 0 && i < NCPU; i++) {
    int cn = (i + startcpu) % NCPU;
    m = &km[cn];
    r = m->alloc(name);
  }

  if (r == 0) {
    cprintf("kalloc: out of memory in pool %s\n", km->name);
    // kmemprint();
    return 0;
  }

  if (ALLOC_MEMSET && m->size <= 16384)
    memset(r, 2, m->size);
  return (char*)r;
}

// Allocate one 4096-byte page of physical memory.
// Returns a pointer that the kernel can use.
// Returns 0 if the memory cannot be allocated.
char*
kalloc(const char *name)
{
  if (!kinited)
    return pgalloc();
  return kalloc_pool(kmems, name);
}

void *
ksalloc(int slab)
{
  return kalloc_pool(slabmem[slab], slabmem[slab]->name);
}

void
slabinit(struct kmem *k, char **p, u64 *off)
{
  for (int i = 0; i < k->ninit; i++) {
    if (*p == (void *)-1)
      panic("slabinit: memnext");
    // XXX(sbw) handle this condition
    if (memsize(p) < k->size)
      panic("slabinit: memsize");
    kfree_pool(k, *p);
    *p = (char*) memnext(*p, k->size);
    *off = *off+k->size;
  }
}

// Initialize free list of physical pages.
void
initkalloc(u64 mbaddr)
{
  char *p;
  u64 n;
  u64 k;

  initmem(mbaddr);

  for (int c = 0; c < NCPU; c++) {
    kmems[c].name[0] = (char) c + '0';
    safestrcpy(kmems[c].name+1, "kmem", MAXNAME-1);
    kmems[c].size = PGSIZE;
  }

  if (VERBOSE)
    cprintf("%lu mbytes\n", membytes / (1<<20));
  n = membytes / NCPU;
  if (n & (PGSIZE-1))
    n = PGROUNDDOWN(n);

  p = (char*)PGROUNDUP((uptr)newend);
  k = (((uptr)p) - KCODE);
  p = (char*) KBASE + k;
  for (int c = 0; c < NCPU; c++) {
    // Fill slab allocators
    strncpy(slabmem[slab_stack][c].name, " kstack", MAXNAME);
    slabmem[slab_stack][c].size = KSTACKSIZE;
    slabmem[slab_stack][c].ninit = CPUKSTACKS;

    strncpy(slabmem[slab_perf][c].name, " kperf", MAXNAME);
    slabmem[slab_perf][c].size = PERFSIZE;
    slabmem[slab_perf][c].ninit = 1;

    strncpy(slabmem[slab_kshared][c].name, " kshared", MAXNAME);
    slabmem[slab_kshared][c].size = KSHAREDSIZE;
    slabmem[slab_kshared][c].ninit = CPUKSTACKS;

    strncpy(slabmem[slab_wq][c].name, " wq", MAXNAME);
    slabmem[slab_wq][c].size = PGROUNDUP(wq_size());
    slabmem[slab_wq][c].ninit = 2;

    strncpy(slabmem[slab_userwq][c].name, " uwq", MAXNAME);
    slabmem[slab_userwq][c].size = USERWQSIZE;
    slabmem[slab_userwq][c].ninit = CPUKSTACKS;

    for (int i = 0; i < slab_type_max; i++) {
      slabmem[i][c].name[0] = (char) c + '0';
      slabinit(&slabmem[i][c], &p, &k);
    }

    // The rest goes to the page allocator
    for (; k != n; k += PGSIZE, p = (char*) memnext(p, PGSIZE)) {
      if (p == (void *)-1)
        panic("initkalloc: e820next");
      kfree_pool(&kmems[c], p);
    }

    k = 0;
  }

  kminit();
  kinited = 1;
}

void
kfree(void *v)
{
  kfree_pool(mykmem(), (char*) v);
}

void
ksfree(int slab, void *v)
{
  kfree_pool(&slabmem[slab][mycpuid()], (char*) v);
}
<|endoftext|>