<commit_before>/*

Copyright (c) 2012-2014, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/config.hpp"
#include "libtorrent/utf8.hpp"
#include "libtorrent/ConvertUTF.h"

// on windows we need these functions for
// convert_to_native and convert_from_native
#if TORRENT_USE_WSTRING || defined TORRENT_WINDOWS

namespace libtorrent
{
	utf8_conv_result_t utf8_wchar(const std::string &utf8, std::wstring &wide)
	{
		// allocate space for worst-case
		wide.resize(utf8.size());
		wchar_t const* dst_start = wide.c_str();
		char const* src_start = utf8.c_str();
		ConversionResult ret;
		// TODO: 3 refactor this to use wchar_t as a template
		// it would cause less code to be generated without
		// relying on dead-code elimination and fix msvc constant
		// expression warning
		if (sizeof(wchar_t) == sizeof(UTF32))
		{
			ret = ConvertUTF8toUTF32((const UTF8**)&src_start, (const UTF8*)src_start
				+ utf8.size(), (UTF32**)&dst_start, (UTF32*)dst_start + wide.size()
				, lenientConversion);
			wide.resize(dst_start - wide.c_str());
			return (utf8_conv_result_t)ret;
		}
		else if (sizeof(wchar_t) == sizeof(UTF16))
		{
			ret = ConvertUTF8toUTF16((const UTF8**)&src_start, (const UTF8*)src_start
				+ utf8.size(), (UTF16**)&dst_start, (UTF16*)dst_start + wide.size()
				, lenientConversion);
			wide.resize(dst_start - wide.c_str());
			return (utf8_conv_result_t)ret;
		}
		else
		{
			return source_illegal;
		}
	}

	utf8_conv_result_t wchar_utf8(const std::wstring &wide, std::string &utf8)
	{
		// allocate space for worst-case
		utf8.resize(wide.size() * 6);
		if (wide.empty()) return conversion_ok;
		char* dst_start = &utf8[0];
		wchar_t const* src_start = wide.c_str();
		ConversionResult ret;
		if (sizeof(wchar_t) == sizeof(UTF32))
		{
			ret = ConvertUTF32toUTF8((const UTF32**)&src_start, (const UTF32*)src_start
				+ wide.size(), (UTF8**)&dst_start, (UTF8*)dst_start + utf8.size()
				, lenientConversion);
			utf8.resize(dst_start - &utf8[0]);
			return (utf8_conv_result_t)ret;
		}
		else if (sizeof(wchar_t) == sizeof(UTF16))
		{
			ret = ConvertUTF16toUTF8((const UTF16**)&src_start, (const UTF16*)src_start
				+ wide.size(), (UTF8**)&dst_start, (UTF8*)dst_start + utf8.size()
				, lenientConversion);
			utf8.resize(dst_start - &utf8[0]);
			return (utf8_conv_result_t)ret;
		}
		else
		{
			return source_illegal;
		}
	}
}

#endif

<commit_msg>clean up utf8 conversion wrapper a bit, to not rely on dead-code elimination in constant conditions<commit_after>/*

Copyright (c) 2012-2014, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#include "libtorrent/config.hpp"
#include "libtorrent/utf8.hpp"
#include "libtorrent/ConvertUTF.h"

// on windows we need these functions for
// convert_to_native and convert_from_native
#if TORRENT_USE_WSTRING || defined TORRENT_WINDOWS

namespace libtorrent
{
	namespace
	{
		// ==== utf-8 -> wide ===
		template<int width>
		struct convert_to_wide
		{
			static utf8_conv_result_t convert(UTF8 const** src_start
				, UTF8 const* src_end
				, std::wstring& wide)
			{
				return source_illegal;
			}
		};

		// ==== utf-8 -> utf-32 ===
		template<>
		struct convert_to_wide<4>
		{
			static utf8_conv_result_t convert(char const** src_start
				, char const* src_end
				, std::wstring& wide)
			{
				wchar_t const* dst_start = wide.c_str();
				int ret = ConvertUTF8toUTF32((UTF8 const**)src_start
					, (UTF8 const*)src_end
					, (UTF32**)&dst_start, (UTF32*)dst_start + wide.size()
					, lenientConversion);
				wide.resize(dst_start - wide.c_str());
				return (utf8_conv_result_t)ret;
			}
		};

		// ==== utf-8 -> utf-16 ===
		template<>
		struct convert_to_wide<2>
		{
			static utf8_conv_result_t convert(char const** src_start
				, char const* src_end
				, std::wstring& wide)
			{
				wchar_t const* dst_start = wide.c_str();
				int ret = ConvertUTF8toUTF16((UTF8 const**)src_start
					, (UTF8 const*)src_end
					, (UTF16**)&dst_start, (UTF16*)dst_start + wide.size()
					, lenientConversion);
				wide.resize(dst_start - wide.c_str());
				return (utf8_conv_result_t)ret;
			}
		};

		// ==== wide -> utf-8 ===
		template<int width>
		struct convert_from_wide
		{
			static utf8_conv_result_t convert(wchar_t const** src_start
				, wchar_t const* src_end
				, std::string& utf8)
			{
				return source_illegal;
			}
		};

		// ==== utf-32 -> utf-8 ===
		template<>
		struct convert_from_wide<4>
		{
			static utf8_conv_result_t convert(wchar_t const** src_start
				, wchar_t const* src_end
				, std::string& utf8)
			{
				char const* dst_start = utf8.c_str();
				int ret = ConvertUTF32toUTF8((UTF32 const**)src_start
					, (UTF32 const*)src_end, (UTF8**)&dst_start
					, (UTF8*)dst_start + utf8.size()
					, lenientConversion);
				utf8.resize(dst_start - &utf8[0]);
				return (utf8_conv_result_t)ret;
			}
		};

		// ==== utf-16 -> utf-8 ===
		template<>
		struct convert_from_wide<2>
		{
			static utf8_conv_result_t convert(wchar_t const** src_start
				, wchar_t const* src_end
				, std::string& utf8)
			{
				char const* dst_start = utf8.c_str();
				int ret = ConvertUTF16toUTF8((UTF16 const**)src_start
					, (UTF16 const*)src_end, (UTF8**)&dst_start
					, (UTF8*)dst_start + utf8.size()
					, lenientConversion);
				utf8.resize(dst_start - &utf8[0]);
				return (utf8_conv_result_t)ret;
			}
		};
	} // anonymous namespace

	utf8_conv_result_t utf8_wchar(std::string const& utf8, std::wstring &wide)
	{
		// allocate space for worst-case
		wide.resize(utf8.size());
		wchar_t const* dst_start = wide.c_str();
		char const* src_start = utf8.c_str();
		return convert_to_wide<sizeof(wchar_t)>::convert(
			&src_start, src_start + utf8.size(), wide);
	}

	utf8_conv_result_t wchar_utf8(std::wstring const& wide, std::string &utf8)
	{
		// allocate space for worst-case
		utf8.resize(wide.size() * 6);
		if (wide.empty()) return conversion_ok;
		char* dst_start = &utf8[0];
		wchar_t const* src_start = wide.c_str();
		return convert_from_wide<sizeof(wchar_t)>::convert(
			&src_start, src_start + wide.size(), utf8);
	}
}

#endif

<|endoftext|>


<commit_before>#include <cmath>
#include <cstdarg>
#include <assert.h>

#include "opencv2/opencv.hpp"
using namespace cv;

#include "structures.hpp"
#include "util.hpp"

void showImage(const char* title, const Mat& img)
{
	std::cout << "\nShowing image: \"" << title << "\"." << std::endl;
	namedWindow(title, CV_WINDOW_NORMAL);
	imshow(title, img);
}

void showImageAndWait(const char* title, const Mat& img)
{
	showImage(title, img);
	std::cout << "Press any key to continue..." << std::endl;
	waitKey(0);
}

Point3f backproject3D(const float& x,const float& y, const float& depth, const Mat& m_cameraMatrix)
{
	Mat new_point = depth * (Mat_<float>(1,3) << x,y,1) * m_cameraMatrix.inv().t();
	return Point3f(new_point);
}

/**
 * Custom logger, instantiate with namespace string to prefix messages with.
 * For example:
 *     Logger _log("Load Images");
 */
Logger::Logger(const char* _namespace)
	: name_space(_namespace), start(ch::system_clock::now())
{}

void Logger::operator() (const char* format, ...)
{
	va_list args;
	va_start(args, format);

	printf("%s>\t", name_space);
	vprintf(format, args);
	printf("\n");

	va_end(args);
}

void Logger::tok()
{
	const clock_t    end = ch::system_clock::now();
	ch::milliseconds dur = ch::duration_cast<ch::milliseconds>(end - start);
	(*this)("Done in %.2fs.", (float)dur.count() / 1e3);
}

/*
 * convert rotation matrix to quaternion
*/
Vec4f R2Quaternion(Mat& R)
{
	assert(R.rows == 3 && R.cols == 3);
	// typedef typename DataType<float>::work_type _wTp;
	if (R.type() != CV_32F) R.convertTo(R, CV_32F);;
	float q0,q1,q2,q3;
	float r00 = R.at<float>(0,0);
	float r01 = R.at<float>(0,1);
	float r02 = R.at<float>(0,2);
	float r10 = R.at<float>(1,0);
	float r11 = R.at<float>(1,1);
	float r12 = R.at<float>(1,2);
	float r20 = R.at<float>(2,0);
	float r21 = R.at<float>(2,1);
	float r22 = R.at<float>(2,2);

	float trace = r00 + r11 + r22;
	if( trace > 0 ){
		float s = 0.5 / sqrt(trace+ 1.0);
    	q0 = 0.25 / s;
    	q1 = ( r21 - r12 ) * s;
    	q2 = ( r02 - r20 ) * s;
    	q3 = ( r10 - r01 ) * s;
	} else {
    	if ( r00 > r11 && r00 > r22 )
    	{
      	float s = 2.0 * sqrt( 1.0 + r00 - r11 - r22);
      	q0 = (r21 - r12 ) / s;
      	q1 = 0.25 * s;
      	q2 = (r01 + r10 ) / s;
      	q3 = (r02 + r20 ) / s;
    	} else if (r11 > r22) {
	    float s = 2.0 * sqrt( 1.0 + r11 - r00 - r22);
	    q0 = (r02 - r20 ) / s;
	    q1 = (r01 + r10 ) / s;
	    q2 = 0.25 * s;
	    q3 = (r12 + r21 ) / s;
    	} else {
      	float s = 2.0 * sqrt( 1.0 + r22 - r00 - r11 );
      	q0 = (r10 - r01 ) / s;
	    q1 = (r02 + r20 ) / s;
	    q2 = (r12 + r21 ) / s;
	    q3 = 0.25 * s;
    	}
	}
	Vec4f q = normalize(Vec4f(q0, q1, q2, q3));
	return q;
}

Mat quat2R(Vec4f& q){

    float sqw = q[0]*q[0];
    float sqx = q[1]*q[1];
    float sqy = q[2]*q[2];
    float sqz = q[3]*q[3];

    // invs (inverse square length) is only required if quaternion is not already normalised
    float invs = 1 / (sqx + sqy + sqz + sqw);
    float m00 = ( sqx - sqy - sqz + sqw)*invs ; // since sqw + sqx + sqy + sqz =1/invs*invs
    float m11 = (-sqx + sqy - sqz + sqw)*invs ;
    float m22 = (-sqx - sqy + sqz + sqw)*invs ;

    float tmp1 = q[1]*q[2];
    float tmp2 = q[3]*q[0];
    float m10 = 2.0 * (tmp1 + tmp2)*invs ;
    float m01 = 2.0 * (tmp1 - tmp2)*invs ;

    tmp1 = q[1]*q[3];
    tmp2 = q[2]*q[0];
    float m20 = 2.0 * (tmp1 - tmp2)*invs ;
    float m02 = 2.0 * (tmp1 + tmp2)*invs ;
    tmp1 = q[2]*q[3];
    tmp2 = q[1]*q[0];
    float m21 = 2.0 * (tmp1 + tmp2)*invs ;
    float m12 = 2.0 * (tmp1 - tmp2)*invs ;
    Mat R = (Mat_<float>(3,3) << m00, m01, m02, m10, m11, m12, m20, m21, m22);
    return R;
}

bool checkCoherentRotation(cv::Mat& R) {

	if(fabs(determinant(R))-1.0 > 1e-05) return false;
	return true;
}

bool checkCoherentQ(Vec4f& q0, Vec4f& q1)
{
	Vec4f absdelta,reldelta;
	absdiff(q0,q1,absdelta);
	divide(absdelta,q1,reldelta);
	if (reldelta[0]>0.05 ||reldelta[1]>0.05 ||reldelta[2]>0.05 ||reldelta[3]>0.05)
		return false;
	return true;
}

<commit_msg>Make backproject3D signature consistent<commit_after>#include <cmath>
#include <cstdarg>
#include <assert.h>

#include "opencv2/opencv.hpp"
using namespace cv;

#include "structures.hpp"
#include "util.hpp"

void showImage(const char* title, const Mat& img)
{
	std::cout << "\nShowing image: \"" << title << "\"." << std::endl;
	namedWindow(title, CV_WINDOW_NORMAL);
	imshow(title, img);
}

void showImageAndWait(const char* title, const Mat& img)
{
	showImage(title, img);
	std::cout << "Press any key to continue..." << std::endl;
	waitKey(0);
}

Point3f backproject3D(const float x, const float y, const float depth, const Mat& m_cameraMatrix)
{
	Mat new_point = depth * (Mat_<float>(1,3) << x,y,1) * m_cameraMatrix.inv().t();
	return Point3f(new_point);
}

/**
 * Custom logger, instantiate with namespace string to prefix messages with.
 * For example:
 *     Logger _log("Load Images");
 */
Logger::Logger(const char* _namespace)
	: name_space(_namespace), start(ch::system_clock::now())
{}

void Logger::operator() (const char* format, ...)
{
	va_list args;
	va_start(args, format);

	printf("%s>\t", name_space);
	vprintf(format, args);
	printf("\n");

	va_end(args);
}

void Logger::tok()
{
	const clock_t    end = ch::system_clock::now();
	ch::milliseconds dur = ch::duration_cast<ch::milliseconds>(end - start);
	(*this)("Done in %.2fs.", (float)dur.count() / 1e3);
}

/*
 * convert rotation matrix to quaternion
*/
Vec4f R2Quaternion(Mat& R)
{
	assert(R.rows == 3 && R.cols == 3);
	// typedef typename DataType<float>::work_type _wTp;
	if (R.type() != CV_32F) R.convertTo(R, CV_32F);;
	float q0,q1,q2,q3;
	float r00 = R.at<float>(0,0);
	float r01 = R.at<float>(0,1);
	float r02 = R.at<float>(0,2);
	float r10 = R.at<float>(1,0);
	float r11 = R.at<float>(1,1);
	float r12 = R.at<float>(1,2);
	float r20 = R.at<float>(2,0);
	float r21 = R.at<float>(2,1);
	float r22 = R.at<float>(2,2);

	float trace = r00 + r11 + r22;
	if( trace > 0 ){
		float s = 0.5 / sqrt(trace+ 1.0);
    	q0 = 0.25 / s;
    	q1 = ( r21 - r12 ) * s;
    	q2 = ( r02 - r20 ) * s;
    	q3 = ( r10 - r01 ) * s;
	} else {
    	if ( r00 > r11 && r00 > r22 )
    	{
      	float s = 2.0 * sqrt( 1.0 + r00 - r11 - r22);
      	q0 = (r21 - r12 ) / s;
      	q1 = 0.25 * s;
      	q2 = (r01 + r10 ) / s;
      	q3 = (r02 + r20 ) / s;
    	} else if (r11 > r22) {
	    float s = 2.0 * sqrt( 1.0 + r11 - r00 - r22);
	    q0 = (r02 - r20 ) / s;
	    q1 = (r01 + r10 ) / s;
	    q2 = 0.25 * s;
	    q3 = (r12 + r21 ) / s;
    	} else {
      	float s = 2.0 * sqrt( 1.0 + r22 - r00 - r11 );
      	q0 = (r10 - r01 ) / s;
	    q1 = (r02 + r20 ) / s;
	    q2 = (r12 + r21 ) / s;
	    q3 = 0.25 * s;
    	}
	}
	Vec4f q = normalize(Vec4f(q0, q1, q2, q3));
	return q;
}

Mat quat2R(Vec4f& q){

    float sqw = q[0]*q[0];
    float sqx = q[1]*q[1];
    float sqy = q[2]*q[2];
    float sqz = q[3]*q[3];

    // invs (inverse square length) is only required if quaternion is not already normalised
    float invs = 1 / (sqx + sqy + sqz + sqw);
    float m00 = ( sqx - sqy - sqz + sqw)*invs ; // since sqw + sqx + sqy + sqz =1/invs*invs
    float m11 = (-sqx + sqy - sqz + sqw)*invs ;
    float m22 = (-sqx - sqy + sqz + sqw)*invs ;

    float tmp1 = q[1]*q[2];
    float tmp2 = q[3]*q[0];
    float m10 = 2.0 * (tmp1 + tmp2)*invs ;
    float m01 = 2.0 * (tmp1 - tmp2)*invs ;

    tmp1 = q[1]*q[3];
    tmp2 = q[2]*q[0];
    float m20 = 2.0 * (tmp1 - tmp2)*invs ;
    float m02 = 2.0 * (tmp1 + tmp2)*invs ;
    tmp1 = q[2]*q[3];
    tmp2 = q[1]*q[0];
    float m21 = 2.0 * (tmp1 + tmp2)*invs ;
    float m12 = 2.0 * (tmp1 - tmp2)*invs ;
    Mat R = (Mat_<float>(3,3) << m00, m01, m02, m10, m11, m12, m20, m21, m22);
    return R;
}

bool checkCoherentRotation(cv::Mat& R) {

	if(fabs(determinant(R))-1.0 > 1e-05) return false;
	return true;
}

bool checkCoherentQ(Vec4f& q0, Vec4f& q1)
{
	Vec4f absdelta,reldelta;
	absdiff(q0,q1,absdelta);
	divide(absdelta,q1,reldelta);
	if (reldelta[0]>0.05 ||reldelta[1]>0.05 ||reldelta[2]>0.05 ||reldelta[3]>0.05)
		return false;
	return true;
}

<|endoftext|>


<commit_before><commit_msg>attempt blind fix of Macos compile error<commit_after><|endoftext|>


<commit_before>/*
 * Copyright (C) 2009 Toni Gundogdu.
 *
 * This file is part of cclive.
 *
 * cclive is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * cclive is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <algorithm>
#include <fstream>
#include <string>
#include <vector>
#include <map>

#include "hosthandler.h"
#include "opts.h"

const double
Util::fileExists(const std::string& path) {
    std::ifstream f;
    f.open(path.c_str(), std::ios::binary);

    double len = 0;

    if (f.is_open()) {
        f.seekg(0, std::ios::end);
        len = f.tellg();
        f.close();
    }

    return len;
}

const std::string
Util::subStr(const std::string& src,
             const std::string& begin,
             const std::string& end,
             const bool& croak_if_not_found /*=true*/)
{
    const std::string::size_type begin_pos = src.find(begin);
    if (begin_pos == std::string::npos && croak_if_not_found)
        throw HostHandler::ParseException("not found: "+begin);

    const std::string::size_type end_pos =
        src.find(end, begin_pos + begin.length());

    if (end_pos == std::string::npos && croak_if_not_found)
        throw HostHandler::ParseException("not found: "+end);

    const std::string::size_type from =
        begin_pos + begin.length();

    const std::string::size_type len =
        end_pos - begin_pos - begin.length();

    return src.substr(from, len);
}

const std::string
Util::rsubStr(const std::string& src,
        const std::string& begin,
        const std::string& end,
        const bool& croak_if_not_found /*=true*/)
{
    const std::string::size_type end_pos = src.rfind(end);
    if (end_pos == std::string::npos && croak_if_not_found)
        throw HostHandler::ParseException("not found: "+end);

    const std::string::size_type begin_pos =
        src.rfind(begin, end_pos - end.length());

    if (begin_pos == std::string::npos && croak_if_not_found)
        throw HostHandler::ParseException("not found: "+begin);

    const std::string::size_type from =
        begin_pos + begin.length();

    const std::string::size_type len =
        end_pos - begin_pos - begin.length();

    return src.substr(from, len);
}

std::string&
Util::subStrReplace(
    std::string& src,
    const std::string& what,
    const std::string& with)
{
    std::string::size_type pos;

    while ((pos = src.find(what)) != std::string::npos)
        src.replace(pos, what.size(), with);

    return src;
}

std::string&
Util::nocookieToYoutube(std::string& url) {
    // Convert alternate domain youtube-nocookie.com
    // to youtube.com domain.
    return Util::subStrReplace(url, "-nocookie", "");
}

std::string&
Util::embedToPage(std::string& url) {
    typedef std::map<std::string, std::string> mapstr;

    mapstr m;

    m["/v/"]                = "/watch?v=";  // youtube
    m["googleplayer.swf"]   = "videoplay";  // google
    m["/pl/"]               = "/videos/";   // sevenload
    m["/e/"]                = "/view?i=";   // liveleak

    for (mapstr::const_iterator iter = m.begin();
        iter != m.end();
        ++iter)
    {
        Util::subStrReplace(url, iter->first, iter->second);
    }

    return url;
}

std::string&
Util::lastfmToYoutube(std::string& url) {
    const std::string::size_type pos = url.find("+1-");
    if (pos != std::string::npos) {
        const std::string id = url.substr(pos+3);
        url = "http://youtube.com/watch?v=" + id;
    }
    return url;
}

std::string&
Util::toLower(std::string& src) {
    std::transform(src.begin(), src.end(),
        src.begin(), tolower);
    return src;
}

std::vector<std::string>
Util::tokenize(const std::string& src, const std::string& delims) {
    std::string::size_type last = src.find_first_not_of(delims);
    std::string::size_type pos  = src.find_first_of(delims, last);

    std::vector<std::string> v;

    while (std::string::npos != pos || std::string::npos != last) {
        v.push_back( src.substr(last, pos-last) );
        last = src.find_first_not_of(delims, pos);
        pos  = src.find_first_of(delims, last);
    }
    return v;
}

std::string
Util::parseFormatMap(const std::string& host) {

    const Options opts =
        optsmgr.getOptions();

    std::string fmt;

    if (opts.format_map_given) {
        pcrecpp::RE re(host + ":(.*?)(\\||$)");
        re.PartialMatch(opts.format_map_arg, &fmt);
    }

    if (opts.format_given) // Override.
        fmt = opts.format_arg;

    return fmt;
}

<commit_msg>util.cpp: use typedef.<commit_after>/*
 * Copyright (C) 2009 Toni Gundogdu.
 *
 * This file is part of cclive.
 *
 * cclive is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * cclive is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <algorithm>
#include <fstream>
#include <string>
#include <vector>
#include <map>

#include "hosthandler.h"
#include "opts.h"

const double
Util::fileExists(const std::string& path) {
    std::ifstream f;
    f.open(path.c_str(), std::ios::binary);

    double len = 0;

    if (f.is_open()) {
        f.seekg(0, std::ios::end);
        len = f.tellg();
        f.close();
    }

    return len;
}

const std::string
Util::subStr(const std::string& src,
             const std::string& begin,
             const std::string& end,
             const bool& croak_if_not_found /*=true*/)
{
    const std::string::size_type begin_pos = src.find(begin);
    if (begin_pos == std::string::npos && croak_if_not_found)
        throw HostHandler::ParseException("not found: "+begin);

    const std::string::size_type end_pos =
        src.find(end, begin_pos + begin.length());

    if (end_pos == std::string::npos && croak_if_not_found)
        throw HostHandler::ParseException("not found: "+end);

    const std::string::size_type from =
        begin_pos + begin.length();

    const std::string::size_type len =
        end_pos - begin_pos - begin.length();

    return src.substr(from, len);
}

const std::string
Util::rsubStr(const std::string& src,
        const std::string& begin,
        const std::string& end,
        const bool& croak_if_not_found /*=true*/)
{
    const std::string::size_type end_pos = src.rfind(end);
    if (end_pos == std::string::npos && croak_if_not_found)
        throw HostHandler::ParseException("not found: "+end);

    const std::string::size_type begin_pos =
        src.rfind(begin, end_pos - end.length());

    if (begin_pos == std::string::npos && croak_if_not_found)
        throw HostHandler::ParseException("not found: "+begin);

    const std::string::size_type from =
        begin_pos + begin.length();

    const std::string::size_type len =
        end_pos - begin_pos - begin.length();

    return src.substr(from, len);
}

std::string&
Util::subStrReplace(
    std::string& src,
    const std::string& what,
    const std::string& with)
{
    std::string::size_type pos;

    while ((pos = src.find(what)) != std::string::npos)
        src.replace(pos, what.size(), with);

    return src;
}

std::string&
Util::nocookieToYoutube(std::string& url) {
    // Convert alternate domain youtube-nocookie.com
    // to youtube.com domain.
    return Util::subStrReplace(url, "-nocookie", "");
}

std::string&
Util::embedToPage(std::string& url) {
    typedef std::map<std::string, std::string> mapstr;

    mapstr m;

    m["/v/"]                = "/watch?v=";  // youtube
    m["googleplayer.swf"]   = "videoplay";  // google
    m["/pl/"]               = "/videos/";   // sevenload
    m["/e/"]                = "/view?i=";   // liveleak

    for (mapstr::const_iterator iter = m.begin();
        iter != m.end();
        ++iter)
    {
        Util::subStrReplace(url, iter->first, iter->second);
    }

    return url;
}

std::string&
Util::lastfmToYoutube(std::string& url) {
    const std::string::size_type pos = url.find("+1-");
    if (pos != std::string::npos) {
        const std::string id = url.substr(pos+3);
        url = "http://youtube.com/watch?v=" + id;
    }
    return url;
}

std::string&
Util::toLower(std::string& src) {
    std::transform(src.begin(), src.end(),
        src.begin(), tolower);
    return src;
}

typedef std::vector<std::string> STRV;

STRV
Util::tokenize(const std::string& src, const std::string& delims) {
    std::string::size_type last = src.find_first_not_of(delims);
    std::string::size_type pos  = src.find_first_of(delims, last);

    STRV v;

    while (std::string::npos != pos || std::string::npos != last) {
        v.push_back( src.substr(last, pos-last) );
        last = src.find_first_not_of(delims, pos);
        pos  = src.find_first_of(delims, last);
    }
    return v;
}

std::string
Util::parseFormatMap(const std::string& host) {

    const Options opts =
        optsmgr.getOptions();

    std::string fmt;

    if (opts.format_map_given) {
        pcrecpp::RE re(host + ":(.*?)(\\||$)");
        re.PartialMatch(opts.format_map_arg, &fmt);
    }

    if (opts.format_given) // Override.
        fmt = opts.format_arg;

    return fmt;
}

<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: xcl97dum.cxx,v $
 *
 *  $Revision: 1.15 $
 *
 *  last change: $Author: vg $ $Date: 2005-02-21 13:49:34 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  This library is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU Lesser General Public
 *  License version 2.1, as published by the Free Software Foundation.
 *
 *  This library is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this library; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifdef PCH
#include "filt_pch.hxx"
#endif

#pragma hdrstop

#include "xcl97dum.hxx"

// --- ExcDummy8_xx Data ---------------------------------------------

// ... (8+) := neu in Biff8, ... (8*) := anders in Biff8

const BYTE ExcDummy8_00a::pMyData[] = {
    0xe1, 0x00, 0x02, 0x00, 0xb0, 0x04,                     // INTERFACEHDR
    0xc1, 0x00, 0x02, 0x00, 0x00, 0x00,                     // MMS
    0xe2, 0x00, 0x00, 0x00,                                 // INTERFACEEND
    0x5c, 0x00, 0x70, 0x00,                                 // WRITEACCESS (8*)
    0x04, 0x00, 0x00,  'C',  'a',  'l',  'c', 0x20,         // "Calc"
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x42, 0x00, 0x02, 0x00, 0xb0, 0x04,                     // CODEPAGE
    0x61, 0x01, 0x02, 0x00, 0x00, 0x00                      // DSF (8+)
};
const ULONG ExcDummy8_00a::nMyLen = sizeof(ExcDummy8_00a::pMyData);

                                                            // TABID (8+): ExcTabid

const BYTE ExcDummy8_00b::pMyData[] = {
    0x9c, 0x00, 0x02, 0x00, 0x0e, 0x00                      // FNGROUPCOUNT
};
const ULONG ExcDummy8_00b::nMyLen = sizeof(ExcDummy8_00b::pMyData);

const BYTE ExcDummy8_040::pMyData[] = {
    0xaf, 0x01, 0x02, 0x00, 0x00, 0x00,                     // PROT4REV (8+)
    0xbc, 0x01, 0x02, 0x00, 0x00, 0x00,                     // PROT4REVPASS (8+)
//  0x3d, 0x00, 0x12, 0x00, 0xe0, 0x01, 0x5a, 0x00, 0xcf,   // WINDOW1
//  0x3f, 0x4e, 0x2a, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00,
//  0x01, 0x00, 0x58, 0x02,
    0x40, 0x00, 0x02, 0x00, 0x00, 0x00,                     // BACKUP
    0x8d, 0x00, 0x02, 0x00, 0x00, 0x00                      // HIDEOBJ
};
const ULONG ExcDummy8_040::nMyLen = sizeof(ExcDummy8_040::pMyData);

const BYTE ExcDummy8_041::pMyData[] = {
    0x0e, 0x00, 0x02, 0x00, 0x01, 0x00,                     // PRECISION
    0xb7, 0x01, 0x02, 0x00, 0x00, 0x00,                     // REFRESHALL (8+)
    0xda, 0x00, 0x02, 0x00, 0x00, 0x00                      // BOOKBOOL
};
const ULONG ExcDummy8_041::nMyLen = sizeof(ExcDummy8_041::pMyData);

const BYTE ExcDummy8_02::pMyData[] = {
    0x5f, 0x00, 0x02, 0x00, 0x01, 0x00                      // SAVERECALC
    };
const ULONG ExcDummy8_02::nMyLen = sizeof(ExcDummy8_02::pMyData);

const BYTE  XclRefmode::pMyData[] = { 0x0f, 0x00, 0x02, 0x00, 0x01, 0x00 }; // REFMODE
const ULONG XclRefmode::nMyLen = sizeof( XclRefmode::pMyData );

// --- class ExcDummy8_xx --------------------------------------------

ULONG ExcDummy8_00a::GetLen() const
{
    return nMyLen;
}

const BYTE* ExcDummy8_00a::GetData() const
{
    return pMyData;
}

ULONG ExcDummy8_00b::GetLen() const
{
    return nMyLen;
}

const BYTE* ExcDummy8_00b::GetData() const
{
    return pMyData;
}

ULONG ExcDummy8_040::GetLen() const
{
    return nMyLen;
}

const BYTE* ExcDummy8_040::GetData() const
{
    return pMyData;
}

ULONG ExcDummy8_041::GetLen() const
{
    return nMyLen;
}

const BYTE* ExcDummy8_041::GetData() const
{
    return pMyData;
}

ULONG ExcDummy8_02::GetLen() const
{
    return nMyLen;
}

const BYTE* ExcDummy8_02::GetData() const
{
    return pMyData;
}

ULONG XclRefmode::GetLen( void ) const
{
    return nMyLen;
}

const BYTE* XclRefmode::GetData( void ) const
{
    return pMyData;
}

<commit_msg>INTEGRATION: CWS ooo19126 (1.15.146); FILE MERGED 2005/09/05 15:03:15 rt 1.15.146.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: xcl97dum.cxx,v $
 *
 *  $Revision: 1.16 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 19:47:30 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifdef PCH
#include "filt_pch.hxx"
#endif

#pragma hdrstop

#include "xcl97dum.hxx"

// --- ExcDummy8_xx Data ---------------------------------------------

// ... (8+) := neu in Biff8, ... (8*) := anders in Biff8

const BYTE ExcDummy8_00a::pMyData[] = {
    0xe1, 0x00, 0x02, 0x00, 0xb0, 0x04,                     // INTERFACEHDR
    0xc1, 0x00, 0x02, 0x00, 0x00, 0x00,                     // MMS
    0xe2, 0x00, 0x00, 0x00,                                 // INTERFACEEND
    0x5c, 0x00, 0x70, 0x00,                                 // WRITEACCESS (8*)
    0x04, 0x00, 0x00,  'C',  'a',  'l',  'c', 0x20,         // "Calc"
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
    0x42, 0x00, 0x02, 0x00, 0xb0, 0x04,                     // CODEPAGE
    0x61, 0x01, 0x02, 0x00, 0x00, 0x00                      // DSF (8+)
};
const ULONG ExcDummy8_00a::nMyLen = sizeof(ExcDummy8_00a::pMyData);

                                                            // TABID (8+): ExcTabid

const BYTE ExcDummy8_00b::pMyData[] = {
    0x9c, 0x00, 0x02, 0x00, 0x0e, 0x00                      // FNGROUPCOUNT
};
const ULONG ExcDummy8_00b::nMyLen = sizeof(ExcDummy8_00b::pMyData);

const BYTE ExcDummy8_040::pMyData[] = {
    0xaf, 0x01, 0x02, 0x00, 0x00, 0x00,                     // PROT4REV (8+)
    0xbc, 0x01, 0x02, 0x00, 0x00, 0x00,                     // PROT4REVPASS (8+)
//  0x3d, 0x00, 0x12, 0x00, 0xe0, 0x01, 0x5a, 0x00, 0xcf,   // WINDOW1
//  0x3f, 0x4e, 0x2a, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00,
//  0x01, 0x00, 0x58, 0x02,
    0x40, 0x00, 0x02, 0x00, 0x00, 0x00,                     // BACKUP
    0x8d, 0x00, 0x02, 0x00, 0x00, 0x00                      // HIDEOBJ
};
const ULONG ExcDummy8_040::nMyLen = sizeof(ExcDummy8_040::pMyData);

const BYTE ExcDummy8_041::pMyData[] = {
    0x0e, 0x00, 0x02, 0x00, 0x01, 0x00,                     // PRECISION
    0xb7, 0x01, 0x02, 0x00, 0x00, 0x00,                     // REFRESHALL (8+)
    0xda, 0x00, 0x02, 0x00, 0x00, 0x00                      // BOOKBOOL
};
const ULONG ExcDummy8_041::nMyLen = sizeof(ExcDummy8_041::pMyData);

const BYTE ExcDummy8_02::pMyData[] = {
    0x5f, 0x00, 0x02, 0x00, 0x01, 0x00                      // SAVERECALC
    };
const ULONG ExcDummy8_02::nMyLen = sizeof(ExcDummy8_02::pMyData);

const BYTE  XclRefmode::pMyData[] = { 0x0f, 0x00, 0x02, 0x00, 0x01, 0x00 }; // REFMODE
const ULONG XclRefmode::nMyLen = sizeof( XclRefmode::pMyData );

// --- class ExcDummy8_xx --------------------------------------------

ULONG ExcDummy8_00a::GetLen() const
{
    return nMyLen;
}

const BYTE* ExcDummy8_00a::GetData() const
{
    return pMyData;
}

ULONG ExcDummy8_00b::GetLen() const
{
    return nMyLen;
}

const BYTE* ExcDummy8_00b::GetData() const
{
    return pMyData;
}

ULONG ExcDummy8_040::GetLen() const
{
    return nMyLen;
}

const BYTE* ExcDummy8_040::GetData() const
{
    return pMyData;
}

ULONG ExcDummy8_041::GetLen() const
{
    return nMyLen;
}

const BYTE* ExcDummy8_041::GetData() const
{
    return pMyData;
}

ULONG ExcDummy8_02::GetLen() const
{
    return nMyLen;
}

const BYTE* ExcDummy8_02::GetData() const
{
    return pMyData;
}

ULONG XclRefmode::GetLen( void ) const
{
    return nMyLen;
}

const BYTE* XclRefmode::GetData( void ) const
{
    return pMyData;
}

<|endoftext|>


<commit_before>/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2014 Crytek
 *
 * 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 "replay/renderdoc.h"
#include "replay/replay_renderer.h"
#include "core/core.h"
#include "os/os_specific.h"
#include "serialise/serialiser.h"
#include "socket_helpers.h"
#include "replay_proxy.h"

#include <utility>
using std::pair;

enum PacketType
{
	ePacket_Noop,
	ePacket_RemoteDriverList,
	ePacket_CopyCapture,
	ePacket_LogOpenProgress,
	ePacket_LogReady,
};

struct ProgressLoopData
{
	Network::Socket *sock;
	float progress;
	bool killsignal;
};

static void ProgressTicker(void *d)
{
	ProgressLoopData *data = (ProgressLoopData *)d;

	Serialiser ser(L"", Serialiser::WRITING, false);

	while(!data->killsignal)
	{
		ser.Rewind();
		ser.Serialise("", data->progress);

		if(!SendPacket(data->sock, ePacket_LogOpenProgress, ser))
		{
			SAFE_DELETE(data->sock);
			break;
		}
		Threading::Sleep(100);
	}
}

void RenderDoc::BecomeReplayHost(volatile bool &killReplay)
{
	Network::Socket *sock = Network::CreateServerSocket("0.0.0.0", RenderDoc_ReplayNetworkPort, 1);

	if(sock == NULL)
		return;

	Serialiser ser(L"", Serialiser::WRITING, false);

	bool newlyReady = true;

	while(!killReplay)
	{
		if(newlyReady)
		{
			RDCLOG("Replay host ready for requests.");
			newlyReady = false;
		}

		Network::Socket *client = sock->AcceptClient(false);

		if(client == NULL)
		{
			if(!sock->Connected())
			{
				RDCERR("Error in accept - shutting down server");

				SAFE_DELETE(sock);
				return;
			}

			Threading::Sleep(5);

			continue;
		}

		newlyReady = true;

		RDCLOG("Connection received.");

		map<RDCDriver,wstring> drivers = RenderDoc::Inst().GetRemoteDrivers();

		uint32_t count = (uint32_t)drivers.size();
		ser.Serialise("", count);

		for(auto it=drivers.begin(); it != drivers.end(); ++it)
		{
			RDCDriver driver = it->first;
			ser.Serialise("", driver);
			ser.Serialise("", (*it).second);
		}

		if(!SendPacket(client, ePacket_RemoteDriverList, ser))
		{
			RDCERR("Network error sending supported driver list");
			SAFE_DELETE(client);
			continue;
		}

		Threading::Sleep(4);

		// don't care about the result, just want to check that the socket hasn't been gracefully shut down
		client->IsRecvDataWaiting();
		if(!client->Connected())
		{
			RDCLOG("Connection closed after sending remote driver list");
			SAFE_DELETE(client);
			continue;
		}

		wstring cap_file;
		wstring dummy, dummy2;
		FileIO::GetDefaultFiles(L"remotecopy", cap_file, dummy, dummy2);

		Serialiser *ser = NULL;

		if(!RecvChunkedFile(client, ePacket_CopyCapture, cap_file.c_str(), ser, NULL))
		{
			FileIO::UnlinkFileW(cap_file.c_str());

			RDCERR("Network error receiving file");

			SAFE_DELETE(ser);
			SAFE_DELETE(client);
			continue;
		}

		RDCLOG("File received.");

		SAFE_DELETE(ser);

		RDCDriver driverType = RDC_Unknown;
		wstring driverName = L"";
		RenderDoc::Inst().FillInitParams(cap_file.c_str(), driverType, driverName, NULL);

		if(RenderDoc::Inst().HasRemoteDriver(driverType))
		{
			ProgressLoopData data;

			data.sock = client;
			data.killsignal = false;
			data.progress = 0.0f;

			RenderDoc::Inst().SetProgressPtr(&data.progress);

			Threading::ThreadHandle ticker = Threading::CreateThread(ProgressTicker, &data);

			IRemoteDriver *driver = NULL;
			auto status = RenderDoc::Inst().CreateRemoteDriver(driverType, cap_file.c_str(), &driver);

			if(status != eReplayCreate_Success || driver == NULL)
			{
				RDCERR("Failed to create remote driver for driver type %d name %ls", driverType, driverName.c_str());
				SAFE_DELETE(ser);
				SAFE_DELETE(client);
				continue;
			}

			driver->ReadLogInitialisation();

			RenderDoc::Inst().SetProgressPtr(NULL);

			data.killsignal = true;
			Threading::JoinThread(ticker);
			Threading::CloseThread(ticker);

			FileIO::UnlinkFileW(cap_file.c_str());

			SendPacket(client, ePacket_LogReady);

			ProxySerialiser *proxy = new ProxySerialiser(client, driver);

			while(client)
			{
				if(!proxy->Tick() || killReplay)
				{
					SAFE_DELETE(client);
				}
			}

			driver->Shutdown();

			RDCLOG("Closing replay connection");

			SAFE_DELETE(proxy);
			SAFE_DELETE(client);
		}
		else
		{
			RDCERR("File needs driver for %ls which isn't supported!", driverName.c_str());

			FileIO::UnlinkFileW(cap_file.c_str());
		}

		SAFE_DELETE(client);
	}
}

struct RemoteRenderer
{
	public:
		RemoteRenderer(Network::Socket *sock)
			: m_Socket(sock)
		{
			map<RDCDriver,wstring> m = RenderDoc::Inst().GetReplayDrivers();

			m_Proxies.reserve(m.size());
			for(auto it=m.begin(); it != m.end(); ++it) m_Proxies.push_back(*it);

			{
				PacketType type;
				Serialiser *ser = NULL;
				GetPacket(type, &ser);

				m.clear();

				if(ser)
				{
					uint32_t count = 0;
					ser->Serialise("", count);

					for(uint32_t i=0; i < count; i++)
					{
						RDCDriver driver = RDC_Unknown;
						wstring name = L"";
						ser->Serialise("", driver);
						ser->Serialise("", name);

						m[driver] = name;
					}

					delete ser;
				}
			}

			m_RemoteDrivers.reserve(m.size());
			for(auto it=m.begin(); it != m.end(); ++it) m_RemoteDrivers.push_back(*it);

			m_ProxyDriver = NULL;
			m_ProxySerialiser = NULL;
		}
		~RemoteRenderer()
		{
			SAFE_DELETE(m_ProxySerialiser);
			SAFE_DELETE(m_Socket);
		}

		void Shutdown()
		{
			delete this;
		}

		bool Connected() { return m_Socket != NULL && m_Socket->Connected(); }

		bool LocalProxies(rdctype::array<rdctype::wstr> *out)
		{
			if(out == NULL) return false;

			create_array_uninit(*out, m_Proxies.size());

			size_t i=0;
			for(auto it=m_Proxies.begin(); it != m_Proxies.end(); ++it, ++i)
				out->elems[i] = it->second;

			return true;
		}

		bool RemoteSupportedReplays(rdctype::array<rdctype::wstr> *out)
		{
			if(out == NULL) return false;

			create_array_uninit(*out, m_RemoteDrivers.size());

			size_t i=0;
			for(auto it=m_RemoteDrivers.begin(); it != m_RemoteDrivers.end(); ++it, ++i)
				out->elems[i] = it->second;

			return true;
		}

		ReplayCreateStatus CreateProxyRenderer(uint32_t proxyid, const wchar_t *logfile, float *progress, ReplayRenderer **rend)
		{
			if(rend == NULL) return eReplayCreate_InternalError;

			if(proxyid >= m_Proxies.size())
			{
				RDCERR("Invalid proxy driver id %d specified for remote renderer", proxyid);
				return eReplayCreate_InternalError;
			}

			float dummy = 0.0f;
			if(progress == NULL)
				progress = &dummy;

			RDCDriver proxydriver = m_Proxies[proxyid].first;

			Serialiser ser(L"", Serialiser::WRITING, false);

			if(!SendChunkedFile(m_Socket, ePacket_CopyCapture, logfile, ser, progress))
			{
				SAFE_DELETE(m_Socket);
				return eReplayCreate_NetworkIOFailed;
			}

			RDCLOG("Sent file to replay host. Loading...");

			PacketType type = ePacket_Noop;
			while(m_Socket)
			{
				Serialiser *ser;
				GetPacket(type, &ser);

				if(!m_Socket || type != ePacket_LogOpenProgress) break;

				ser->Serialise("", *progress);

				RDCLOG("% 3.0f%%...", (*progress)*100.0f);
			}

			if(!m_Socket || type != ePacket_LogReady)
				return eReplayCreate_NetworkIOFailed;

			*progress = 1.0f;

			RDCLOG("Log ready on replay host");

			m_ProxyDriver = NULL;
			auto status = RenderDoc::Inst().CreateReplayDriver(proxydriver, NULL, &m_ProxyDriver);

			if(status != eReplayCreate_Success || !m_ProxyDriver)
				return status;

			ReplayRenderer *ret = new ReplayRenderer();

			m_ProxySerialiser = new ProxySerialiser(m_Socket, m_ProxyDriver);
			status = ret->SetDevice(m_ProxySerialiser);

			if(status != eReplayCreate_Success)
			{
				SAFE_DELETE(ret);
				SAFE_DELETE(m_ProxySerialiser);
				return status;
			}

			*rend = ret;

			return eReplayCreate_Success;
		}
	private:
		Network::Socket *m_Socket;

		void GetPacket(PacketType &type, Serialiser **ser)
		{
			vector<byte> payload;

			if(!RecvPacket(m_Socket, type, payload))
			{
				SAFE_DELETE(m_Socket);
				if(ser) *ser = NULL;
				return;
			}

			if(ser)	*ser = new Serialiser(payload.size(), &payload[0], false);
		}

		IReplayDriver *m_ProxyDriver;
		ProxySerialiser *m_ProxySerialiser;

		vector< pair<RDCDriver, wstring> > m_Proxies;
		vector< pair<RDCDriver, wstring> > m_RemoteDrivers;
};

extern "C" RENDERDOC_API void RENDERDOC_CC RemoteRenderer_Shutdown(RemoteRenderer *remote)
{	remote->Shutdown(); }

extern "C" RENDERDOC_API bool RENDERDOC_CC RemoteRenderer_LocalProxies(RemoteRenderer *remote, rdctype::array<rdctype::wstr> *out)
{ return remote->LocalProxies(out); }

extern "C" RENDERDOC_API bool RENDERDOC_CC RemoteRenderer_RemoteSupportedReplays(RemoteRenderer *remote, rdctype::array<rdctype::wstr> *out)
{ return remote->RemoteSupportedReplays(out); }

extern "C" RENDERDOC_API ReplayCreateStatus RENDERDOC_CC RemoteRenderer_CreateProxyRenderer(RemoteRenderer *remote, uint32_t proxyid, const wchar_t *logfile, float *progress, ReplayRenderer **rend)
{ return remote->CreateProxyRenderer(proxyid, logfile, progress, rend); }

extern "C" RENDERDOC_API
ReplayCreateStatus RENDERDOC_CC RENDERDOC_CreateRemoteReplayConnection(const wchar_t *host, RemoteRenderer **rend)
{
	if(rend == NULL) return eReplayCreate_InternalError;

	wstring s = L"localhost";
	if(host != NULL && host[0] != L'\0')
		s = host;

	Network::Socket *sock = NULL;

	if(s != L"-")
	{
		sock = Network::CreateClientSocket(s.c_str(), RenderDoc_ReplayNetworkPort, 3000);

		if(sock == NULL)
			return eReplayCreate_NetworkIOFailed;
	}

	*rend = new RemoteRenderer(sock);

	return eReplayCreate_Success;
}
<commit_msg>ReplayRenderer takes over ownership of ProxySerialiser<commit_after>/******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2014 Crytek
 *
 * 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 "replay/renderdoc.h"
#include "replay/replay_renderer.h"
#include "core/core.h"
#include "os/os_specific.h"
#include "serialise/serialiser.h"
#include "socket_helpers.h"
#include "replay_proxy.h"

#include <utility>
using std::pair;

enum PacketType
{
	ePacket_Noop,
	ePacket_RemoteDriverList,
	ePacket_CopyCapture,
	ePacket_LogOpenProgress,
	ePacket_LogReady,
};

struct ProgressLoopData
{
	Network::Socket *sock;
	float progress;
	bool killsignal;
};

static void ProgressTicker(void *d)
{
	ProgressLoopData *data = (ProgressLoopData *)d;

	Serialiser ser(L"", Serialiser::WRITING, false);

	while(!data->killsignal)
	{
		ser.Rewind();
		ser.Serialise("", data->progress);

		if(!SendPacket(data->sock, ePacket_LogOpenProgress, ser))
		{
			SAFE_DELETE(data->sock);
			break;
		}
		Threading::Sleep(100);
	}
}

void RenderDoc::BecomeReplayHost(volatile bool &killReplay)
{
	Network::Socket *sock = Network::CreateServerSocket("0.0.0.0", RenderDoc_ReplayNetworkPort, 1);

	if(sock == NULL)
		return;

	Serialiser ser(L"", Serialiser::WRITING, false);

	bool newlyReady = true;

	while(!killReplay)
	{
		if(newlyReady)
		{
			RDCLOG("Replay host ready for requests.");
			newlyReady = false;
		}

		Network::Socket *client = sock->AcceptClient(false);

		if(client == NULL)
		{
			if(!sock->Connected())
			{
				RDCERR("Error in accept - shutting down server");

				SAFE_DELETE(sock);
				return;
			}

			Threading::Sleep(5);

			continue;
		}

		newlyReady = true;

		RDCLOG("Connection received.");

		map<RDCDriver,wstring> drivers = RenderDoc::Inst().GetRemoteDrivers();

		uint32_t count = (uint32_t)drivers.size();
		ser.Serialise("", count);

		for(auto it=drivers.begin(); it != drivers.end(); ++it)
		{
			RDCDriver driver = it->first;
			ser.Serialise("", driver);
			ser.Serialise("", (*it).second);
		}

		if(!SendPacket(client, ePacket_RemoteDriverList, ser))
		{
			RDCERR("Network error sending supported driver list");
			SAFE_DELETE(client);
			continue;
		}

		Threading::Sleep(4);

		// don't care about the result, just want to check that the socket hasn't been gracefully shut down
		client->IsRecvDataWaiting();
		if(!client->Connected())
		{
			RDCLOG("Connection closed after sending remote driver list");
			SAFE_DELETE(client);
			continue;
		}

		wstring cap_file;
		wstring dummy, dummy2;
		FileIO::GetDefaultFiles(L"remotecopy", cap_file, dummy, dummy2);

		Serialiser *ser = NULL;

		if(!RecvChunkedFile(client, ePacket_CopyCapture, cap_file.c_str(), ser, NULL))
		{
			FileIO::UnlinkFileW(cap_file.c_str());

			RDCERR("Network error receiving file");

			SAFE_DELETE(ser);
			SAFE_DELETE(client);
			continue;
		}

		RDCLOG("File received.");

		SAFE_DELETE(ser);

		RDCDriver driverType = RDC_Unknown;
		wstring driverName = L"";
		RenderDoc::Inst().FillInitParams(cap_file.c_str(), driverType, driverName, NULL);

		if(RenderDoc::Inst().HasRemoteDriver(driverType))
		{
			ProgressLoopData data;

			data.sock = client;
			data.killsignal = false;
			data.progress = 0.0f;

			RenderDoc::Inst().SetProgressPtr(&data.progress);

			Threading::ThreadHandle ticker = Threading::CreateThread(ProgressTicker, &data);

			IRemoteDriver *driver = NULL;
			auto status = RenderDoc::Inst().CreateRemoteDriver(driverType, cap_file.c_str(), &driver);

			if(status != eReplayCreate_Success || driver == NULL)
			{
				RDCERR("Failed to create remote driver for driver type %d name %ls", driverType, driverName.c_str());
				SAFE_DELETE(ser);
				SAFE_DELETE(client);
				continue;
			}

			driver->ReadLogInitialisation();

			RenderDoc::Inst().SetProgressPtr(NULL);

			data.killsignal = true;
			Threading::JoinThread(ticker);
			Threading::CloseThread(ticker);

			FileIO::UnlinkFileW(cap_file.c_str());

			SendPacket(client, ePacket_LogReady);

			ProxySerialiser *proxy = new ProxySerialiser(client, driver);

			while(client)
			{
				if(!proxy->Tick() || killReplay)
				{
					SAFE_DELETE(client);
				}
			}

			driver->Shutdown();

			RDCLOG("Closing replay connection");

			SAFE_DELETE(proxy);
			SAFE_DELETE(client);
		}
		else
		{
			RDCERR("File needs driver for %ls which isn't supported!", driverName.c_str());

			FileIO::UnlinkFileW(cap_file.c_str());
		}

		SAFE_DELETE(client);
	}
}

struct RemoteRenderer
{
	public:
		RemoteRenderer(Network::Socket *sock)
			: m_Socket(sock)
		{
			map<RDCDriver,wstring> m = RenderDoc::Inst().GetReplayDrivers();

			m_Proxies.reserve(m.size());
			for(auto it=m.begin(); it != m.end(); ++it) m_Proxies.push_back(*it);

			{
				PacketType type;
				Serialiser *ser = NULL;
				GetPacket(type, &ser);

				m.clear();

				if(ser)
				{
					uint32_t count = 0;
					ser->Serialise("", count);

					for(uint32_t i=0; i < count; i++)
					{
						RDCDriver driver = RDC_Unknown;
						wstring name = L"";
						ser->Serialise("", driver);
						ser->Serialise("", name);

						m[driver] = name;
					}

					delete ser;
				}
			}

			m_RemoteDrivers.reserve(m.size());
			for(auto it=m.begin(); it != m.end(); ++it) m_RemoteDrivers.push_back(*it);

			m_ProxyDriver = NULL;
		}
		~RemoteRenderer()
		{
			SAFE_DELETE(m_Socket);
		}

		void Shutdown()
		{
			delete this;
		}

		bool Connected() { return m_Socket != NULL && m_Socket->Connected(); }

		bool LocalProxies(rdctype::array<rdctype::wstr> *out)
		{
			if(out == NULL) return false;

			create_array_uninit(*out, m_Proxies.size());

			size_t i=0;
			for(auto it=m_Proxies.begin(); it != m_Proxies.end(); ++it, ++i)
				out->elems[i] = it->second;

			return true;
		}

		bool RemoteSupportedReplays(rdctype::array<rdctype::wstr> *out)
		{
			if(out == NULL) return false;

			create_array_uninit(*out, m_RemoteDrivers.size());

			size_t i=0;
			for(auto it=m_RemoteDrivers.begin(); it != m_RemoteDrivers.end(); ++it, ++i)
				out->elems[i] = it->second;

			return true;
		}

		ReplayCreateStatus CreateProxyRenderer(uint32_t proxyid, const wchar_t *logfile, float *progress, ReplayRenderer **rend)
		{
			if(rend == NULL) return eReplayCreate_InternalError;

			if(proxyid >= m_Proxies.size())
			{
				RDCERR("Invalid proxy driver id %d specified for remote renderer", proxyid);
				return eReplayCreate_InternalError;
			}

			float dummy = 0.0f;
			if(progress == NULL)
				progress = &dummy;

			RDCDriver proxydriver = m_Proxies[proxyid].first;

			Serialiser ser(L"", Serialiser::WRITING, false);

			if(!SendChunkedFile(m_Socket, ePacket_CopyCapture, logfile, ser, progress))
			{
				SAFE_DELETE(m_Socket);
				return eReplayCreate_NetworkIOFailed;
			}

			RDCLOG("Sent file to replay host. Loading...");

			PacketType type = ePacket_Noop;
			while(m_Socket)
			{
				Serialiser *ser;
				GetPacket(type, &ser);

				if(!m_Socket || type != ePacket_LogOpenProgress) break;

				ser->Serialise("", *progress);

				RDCLOG("% 3.0f%%...", (*progress)*100.0f);
			}

			if(!m_Socket || type != ePacket_LogReady)
				return eReplayCreate_NetworkIOFailed;

			*progress = 1.0f;

			RDCLOG("Log ready on replay host");

			m_ProxyDriver = NULL;
			auto status = RenderDoc::Inst().CreateReplayDriver(proxydriver, NULL, &m_ProxyDriver);

			if(status != eReplayCreate_Success || !m_ProxyDriver)
				return status;

			ReplayRenderer *ret = new ReplayRenderer();

			ProxySerialiser *proxy = new ProxySerialiser(m_Socket, m_ProxyDriver);
			status = ret->SetDevice(proxy);

			if(status != eReplayCreate_Success)
			{
				SAFE_DELETE(ret);
				SAFE_DELETE(proxy);
				return status;
			}

			// ReplayRenderer takes ownership of the ProxySerialiser (as IReplayDriver)
			// and it cleans itself up in Shutdown.

			*rend = ret;

			return eReplayCreate_Success;
		}
	private:
		Network::Socket *m_Socket;

		void GetPacket(PacketType &type, Serialiser **ser)
		{
			vector<byte> payload;

			if(!RecvPacket(m_Socket, type, payload))
			{
				SAFE_DELETE(m_Socket);
				if(ser) *ser = NULL;
				return;
			}

			if(ser)	*ser = new Serialiser(payload.size(), &payload[0], false);
		}

		IReplayDriver *m_ProxyDriver;

		vector< pair<RDCDriver, wstring> > m_Proxies;
		vector< pair<RDCDriver, wstring> > m_RemoteDrivers;
};

extern "C" RENDERDOC_API void RENDERDOC_CC RemoteRenderer_Shutdown(RemoteRenderer *remote)
{	remote->Shutdown(); }

extern "C" RENDERDOC_API bool RENDERDOC_CC RemoteRenderer_LocalProxies(RemoteRenderer *remote, rdctype::array<rdctype::wstr> *out)
{ return remote->LocalProxies(out); }

extern "C" RENDERDOC_API bool RENDERDOC_CC RemoteRenderer_RemoteSupportedReplays(RemoteRenderer *remote, rdctype::array<rdctype::wstr> *out)
{ return remote->RemoteSupportedReplays(out); }

extern "C" RENDERDOC_API ReplayCreateStatus RENDERDOC_CC RemoteRenderer_CreateProxyRenderer(RemoteRenderer *remote, uint32_t proxyid, const wchar_t *logfile, float *progress, ReplayRenderer **rend)
{ return remote->CreateProxyRenderer(proxyid, logfile, progress, rend); }

extern "C" RENDERDOC_API
ReplayCreateStatus RENDERDOC_CC RENDERDOC_CreateRemoteReplayConnection(const wchar_t *host, RemoteRenderer **rend)
{
	if(rend == NULL) return eReplayCreate_InternalError;

	wstring s = L"localhost";
	if(host != NULL && host[0] != L'\0')
		s = host;

	Network::Socket *sock = NULL;

	if(s != L"-")
	{
		sock = Network::CreateClientSocket(s.c_str(), RenderDoc_ReplayNetworkPort, 3000);

		if(sock == NULL)
			return eReplayCreate_NetworkIOFailed;
	}

	*rend = new RemoteRenderer(sock);

	return eReplayCreate_Success;
}
<|endoftext|>


<commit_before><commit_msg>dr78: #i43040# correction for BesselI, patch from Regina<commit_after><|endoftext|>


<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#include "main.h"

template<typename ArrayType> void array(const ArrayType& m)
{
  typedef typename ArrayType::Index Index;
  typedef typename ArrayType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;
  typedef Array<Scalar, ArrayType::RowsAtCompileTime, 1> ColVectorType;
  typedef Array<Scalar, 1, ArrayType::ColsAtCompileTime> RowVectorType;

  Index rows = m.rows();
  Index cols = m.cols();

  ArrayType m1 = ArrayType::Random(rows, cols),
             m2 = ArrayType::Random(rows, cols),
             m3(rows, cols);

  ColVectorType cv1 = ColVectorType::Random(rows);
  RowVectorType rv1 = RowVectorType::Random(cols);

  Scalar  s1 = internal::random<Scalar>(),
          s2 = internal::random<Scalar>();

  // scalar addition
  VERIFY_IS_APPROX(m1 + s1, s1 + m1);
  VERIFY_IS_APPROX(m1 + s1, ArrayType::Constant(rows,cols,s1) + m1);
  VERIFY_IS_APPROX(s1 - m1, (-m1)+s1 );
  VERIFY_IS_APPROX(m1 - s1, m1 - ArrayType::Constant(rows,cols,s1));
  VERIFY_IS_APPROX(s1 - m1, ArrayType::Constant(rows,cols,s1) - m1);
  VERIFY_IS_APPROX((m1*Scalar(2)) - s2, (m1+m1) - ArrayType::Constant(rows,cols,s2) );
  m3 = m1;
  m3 += s2;
  VERIFY_IS_APPROX(m3, m1 + s2);
  m3 = m1;
  m3 -= s1;
  VERIFY_IS_APPROX(m3, m1 - s1);

  // scalar operators via Maps
  m3 = m1;
  ArrayType::Map(m1.data(), m1.rows(), m1.cols()) -= ArrayType::Map(m2.data(), m2.rows(), m2.cols());
  VERIFY_IS_APPROX(m1, m3 - m2);

  m3 = m1;
  ArrayType::Map(m1.data(), m1.rows(), m1.cols()) += ArrayType::Map(m2.data(), m2.rows(), m2.cols());
  VERIFY_IS_APPROX(m1, m3 + m2);

  m3 = m1;
  ArrayType::Map(m1.data(), m1.rows(), m1.cols()) *= ArrayType::Map(m2.data(), m2.rows(), m2.cols());
  VERIFY_IS_APPROX(m1, m3 * m2);

  m3 = m1;
  m2 = ArrayType::Random(rows,cols);
  m2 = (m2==0).select(1,m2);
  ArrayType::Map(m1.data(), m1.rows(), m1.cols()) /= ArrayType::Map(m2.data(), m2.rows(), m2.cols());
  VERIFY_IS_APPROX(m1, m3 / m2);

  // reductions
  VERIFY_IS_APPROX(m1.colwise().sum().sum(), m1.sum());
  VERIFY_IS_APPROX(m1.rowwise().sum().sum(), m1.sum());
  if (!internal::isApprox(m1.sum(), (m1+m2).sum()))
    VERIFY_IS_NOT_APPROX(((m1+m2).rowwise().sum()).sum(), m1.sum());
  VERIFY_IS_APPROX(m1.colwise().sum(), m1.colwise().redux(internal::scalar_sum_op<Scalar>()));

  // vector-wise ops
  m3 = m1;
  VERIFY_IS_APPROX(m3.colwise() += cv1, m1.colwise() + cv1);
  m3 = m1;
  VERIFY_IS_APPROX(m3.colwise() -= cv1, m1.colwise() - cv1);
  m3 = m1;
  VERIFY_IS_APPROX(m3.rowwise() += rv1, m1.rowwise() + rv1);
  m3 = m1;
  VERIFY_IS_APPROX(m3.rowwise() -= rv1, m1.rowwise() - rv1);
}

template<typename ArrayType> void comparisons(const ArrayType& m)
{
  typedef typename ArrayType::Index Index;
  typedef typename ArrayType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;
  typedef Array<Scalar, ArrayType::RowsAtCompileTime, 1> VectorType;

  Index rows = m.rows();
  Index cols = m.cols();

  Index r = internal::random<Index>(0, rows-1),
        c = internal::random<Index>(0, cols-1);

  ArrayType m1 = ArrayType::Random(rows, cols),
             m2 = ArrayType::Random(rows, cols),
             m3(rows, cols);

  VERIFY(((m1 + Scalar(1)) > m1).all());
  VERIFY(((m1 - Scalar(1)) < m1).all());
  if (rows*cols>1)
  {
    m3 = m1;
    m3(r,c) += 1;
    VERIFY(! (m1 < m3).all() );
    VERIFY(! (m1 > m3).all() );
  }

  // comparisons to scalar
  VERIFY( (m1 != (m1(r,c)+1) ).any() );
  VERIFY( (m1 > (m1(r,c)-1) ).any() );
  VERIFY( (m1 < (m1(r,c)+1) ).any() );
  VERIFY( (m1 == m1(r,c) ).any() );

  // test Select
  VERIFY_IS_APPROX( (m1<m2).select(m1,m2), m1.cwiseMin(m2) );
  VERIFY_IS_APPROX( (m1>m2).select(m1,m2), m1.cwiseMax(m2) );
  Scalar mid = (m1.cwiseAbs().minCoeff() + m1.cwiseAbs().maxCoeff())/Scalar(2);
  for (int j=0; j<cols; ++j)
  for (int i=0; i<rows; ++i)
    m3(i,j) = internal::abs(m1(i,j))<mid ? 0 : m1(i,j);
  VERIFY_IS_APPROX( (m1.abs()<ArrayType::Constant(rows,cols,mid))
                        .select(ArrayType::Zero(rows,cols),m1), m3);
  // shorter versions:
  VERIFY_IS_APPROX( (m1.abs()<ArrayType::Constant(rows,cols,mid))
                        .select(0,m1), m3);
  VERIFY_IS_APPROX( (m1.abs()>=ArrayType::Constant(rows,cols,mid))
                        .select(m1,0), m3);
  // even shorter version:
  VERIFY_IS_APPROX( (m1.abs()<mid).select(0,m1), m3);

  // count
  VERIFY(((m1.abs()+1)>RealScalar(0.1)).count() == rows*cols);

  typedef Array<typename ArrayType::Index, Dynamic, 1> ArrayOfIndices;

  // TODO allows colwise/rowwise for array
  VERIFY_IS_APPROX(((m1.abs()+1)>RealScalar(0.1)).colwise().count(), ArrayOfIndices::Constant(cols,rows).transpose());
  VERIFY_IS_APPROX(((m1.abs()+1)>RealScalar(0.1)).rowwise().count(), ArrayOfIndices::Constant(rows, cols));
}

template<typename ArrayType> void array_real(const ArrayType& m)
{
  typedef typename ArrayType::Index Index;
  typedef typename ArrayType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;

  Index rows = m.rows();
  Index cols = m.cols();

  ArrayType m1 = ArrayType::Random(rows, cols),
             m2 = ArrayType::Random(rows, cols),
             m3(rows, cols);

  VERIFY_IS_APPROX(m1.sin(), std::sin(m1));
  VERIFY_IS_APPROX(m1.sin(), internal::sin(m1));
  VERIFY_IS_APPROX(m1.cos(), std::cos(m1));
  VERIFY_IS_APPROX(m1.cos(), internal::cos(m1));

  VERIFY_IS_APPROX(internal::cos(m1+RealScalar(3)*m2), internal::cos((m1+RealScalar(3)*m2).eval()));
  VERIFY_IS_APPROX(std::cos(m1+RealScalar(3)*m2), std::cos((m1+RealScalar(3)*m2).eval()));

  VERIFY_IS_APPROX(m1.abs().sqrt(), std::sqrt(std::abs(m1)));
  VERIFY_IS_APPROX(m1.abs().sqrt(), internal::sqrt(internal::abs(m1)));
  VERIFY_IS_APPROX(m1.abs(), internal::sqrt(internal::abs2(m1)));

  VERIFY_IS_APPROX(internal::abs2(internal::real(m1)) + internal::abs2(internal::imag(m1)), internal::abs2(m1));
  VERIFY_IS_APPROX(internal::abs2(std::real(m1)) + internal::abs2(std::imag(m1)), internal::abs2(m1));
  if(!NumTraits<Scalar>::IsComplex)
    VERIFY_IS_APPROX(internal::real(m1), m1);

  VERIFY_IS_APPROX(m1.abs().log(), std::log(std::abs(m1)));
  VERIFY_IS_APPROX(m1.abs().log(), internal::log(internal::abs(m1)));

  VERIFY_IS_APPROX(m1.exp(), std::exp(m1));
  VERIFY_IS_APPROX(m1.exp() * m2.exp(), std::exp(m1+m2));
  VERIFY_IS_APPROX(m1.exp(), internal::exp(m1));
  VERIFY_IS_APPROX(m1.exp() / m2.exp(), std::exp(m1-m2));

  VERIFY_IS_APPROX(m1.pow(2), m1.square());
  VERIFY_IS_APPROX(std::pow(m1,2), m1.square());
  m3 = m1.abs();
  VERIFY_IS_APPROX(m3.pow(RealScalar(0.5)), m3.sqrt());
  VERIFY_IS_APPROX(std::pow(m3,RealScalar(0.5)), m3.sqrt());
}

void test_array()
{
  for(int i = 0; i < g_repeat; i++) {
    //CALL_SUBTEST_1( array(Array<float, 1, 1>()) );
    //CALL_SUBTEST_2( array(Array22f()) );
    //CALL_SUBTEST_3( array(Array44d()) );
    //CALL_SUBTEST_4( array(ArrayXXcf(3, 3)) );
    //CALL_SUBTEST_5( array(ArrayXXf(8, 12)) );
    CALL_SUBTEST_6( array(ArrayXXi(8, 12)) );
  }
  //for(int i = 0; i < g_repeat; i++) {
  //  CALL_SUBTEST_1( comparisons(Array<float, 1, 1>()) );
  //  CALL_SUBTEST_2( comparisons(Array22f()) );
  //  CALL_SUBTEST_3( comparisons(Array44d()) );
  //  CALL_SUBTEST_5( comparisons(ArrayXXf(8, 12)) );
  //  CALL_SUBTEST_6( comparisons(ArrayXXi(8, 12)) );
  //}
  //for(int i = 0; i < g_repeat; i++) {
  //  CALL_SUBTEST_1( array_real(Array<float, 1, 1>()) );
  //  CALL_SUBTEST_2( array_real(Array22f()) );
  //  CALL_SUBTEST_3( array_real(Array44d()) );
  //  CALL_SUBTEST_5( array_real(ArrayXXf(8, 12)) );
  //}

  //VERIFY((internal::is_same< internal::global_math_functions_filtering_base<int>::type, int >::value));
  //VERIFY((internal::is_same< internal::global_math_functions_filtering_base<float>::type, float >::value));
  //VERIFY((internal::is_same< internal::global_math_functions_filtering_base<Array2i>::type, ArrayBase<Array2i> >::value));
  //typedef CwiseUnaryOp<internal::scalar_sum_op<double>, ArrayXd > Xpr;
  //VERIFY((internal::is_same< internal::global_math_functions_filtering_base<Xpr>::type,
  //                         ArrayBase<Xpr>
  //                       >::value));
}
<commit_msg>Uups - re-enabled subtests 1 to 5.<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008-2009 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

#include "main.h"

template<typename ArrayType> void array(const ArrayType& m)
{
  typedef typename ArrayType::Index Index;
  typedef typename ArrayType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;
  typedef Array<Scalar, ArrayType::RowsAtCompileTime, 1> ColVectorType;
  typedef Array<Scalar, 1, ArrayType::ColsAtCompileTime> RowVectorType;

  Index rows = m.rows();
  Index cols = m.cols();

  ArrayType m1 = ArrayType::Random(rows, cols),
             m2 = ArrayType::Random(rows, cols),
             m3(rows, cols);

  ColVectorType cv1 = ColVectorType::Random(rows);
  RowVectorType rv1 = RowVectorType::Random(cols);

  Scalar  s1 = internal::random<Scalar>(),
          s2 = internal::random<Scalar>();

  // scalar addition
  VERIFY_IS_APPROX(m1 + s1, s1 + m1);
  VERIFY_IS_APPROX(m1 + s1, ArrayType::Constant(rows,cols,s1) + m1);
  VERIFY_IS_APPROX(s1 - m1, (-m1)+s1 );
  VERIFY_IS_APPROX(m1 - s1, m1 - ArrayType::Constant(rows,cols,s1));
  VERIFY_IS_APPROX(s1 - m1, ArrayType::Constant(rows,cols,s1) - m1);
  VERIFY_IS_APPROX((m1*Scalar(2)) - s2, (m1+m1) - ArrayType::Constant(rows,cols,s2) );
  m3 = m1;
  m3 += s2;
  VERIFY_IS_APPROX(m3, m1 + s2);
  m3 = m1;
  m3 -= s1;
  VERIFY_IS_APPROX(m3, m1 - s1);

  // scalar operators via Maps
  m3 = m1;
  ArrayType::Map(m1.data(), m1.rows(), m1.cols()) -= ArrayType::Map(m2.data(), m2.rows(), m2.cols());
  VERIFY_IS_APPROX(m1, m3 - m2);

  m3 = m1;
  ArrayType::Map(m1.data(), m1.rows(), m1.cols()) += ArrayType::Map(m2.data(), m2.rows(), m2.cols());
  VERIFY_IS_APPROX(m1, m3 + m2);

  m3 = m1;
  ArrayType::Map(m1.data(), m1.rows(), m1.cols()) *= ArrayType::Map(m2.data(), m2.rows(), m2.cols());
  VERIFY_IS_APPROX(m1, m3 * m2);

  m3 = m1;
  m2 = ArrayType::Random(rows,cols);
  m2 = (m2==0).select(1,m2);
  ArrayType::Map(m1.data(), m1.rows(), m1.cols()) /= ArrayType::Map(m2.data(), m2.rows(), m2.cols());
  VERIFY_IS_APPROX(m1, m3 / m2);

  // reductions
  VERIFY_IS_APPROX(m1.colwise().sum().sum(), m1.sum());
  VERIFY_IS_APPROX(m1.rowwise().sum().sum(), m1.sum());
  if (!internal::isApprox(m1.sum(), (m1+m2).sum()))
    VERIFY_IS_NOT_APPROX(((m1+m2).rowwise().sum()).sum(), m1.sum());
  VERIFY_IS_APPROX(m1.colwise().sum(), m1.colwise().redux(internal::scalar_sum_op<Scalar>()));

  // vector-wise ops
  m3 = m1;
  VERIFY_IS_APPROX(m3.colwise() += cv1, m1.colwise() + cv1);
  m3 = m1;
  VERIFY_IS_APPROX(m3.colwise() -= cv1, m1.colwise() - cv1);
  m3 = m1;
  VERIFY_IS_APPROX(m3.rowwise() += rv1, m1.rowwise() + rv1);
  m3 = m1;
  VERIFY_IS_APPROX(m3.rowwise() -= rv1, m1.rowwise() - rv1);
}

template<typename ArrayType> void comparisons(const ArrayType& m)
{
  typedef typename ArrayType::Index Index;
  typedef typename ArrayType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;
  typedef Array<Scalar, ArrayType::RowsAtCompileTime, 1> VectorType;

  Index rows = m.rows();
  Index cols = m.cols();

  Index r = internal::random<Index>(0, rows-1),
        c = internal::random<Index>(0, cols-1);

  ArrayType m1 = ArrayType::Random(rows, cols),
             m2 = ArrayType::Random(rows, cols),
             m3(rows, cols);

  VERIFY(((m1 + Scalar(1)) > m1).all());
  VERIFY(((m1 - Scalar(1)) < m1).all());
  if (rows*cols>1)
  {
    m3 = m1;
    m3(r,c) += 1;
    VERIFY(! (m1 < m3).all() );
    VERIFY(! (m1 > m3).all() );
  }

  // comparisons to scalar
  VERIFY( (m1 != (m1(r,c)+1) ).any() );
  VERIFY( (m1 > (m1(r,c)-1) ).any() );
  VERIFY( (m1 < (m1(r,c)+1) ).any() );
  VERIFY( (m1 == m1(r,c) ).any() );

  // test Select
  VERIFY_IS_APPROX( (m1<m2).select(m1,m2), m1.cwiseMin(m2) );
  VERIFY_IS_APPROX( (m1>m2).select(m1,m2), m1.cwiseMax(m2) );
  Scalar mid = (m1.cwiseAbs().minCoeff() + m1.cwiseAbs().maxCoeff())/Scalar(2);
  for (int j=0; j<cols; ++j)
  for (int i=0; i<rows; ++i)
    m3(i,j) = internal::abs(m1(i,j))<mid ? 0 : m1(i,j);
  VERIFY_IS_APPROX( (m1.abs()<ArrayType::Constant(rows,cols,mid))
                        .select(ArrayType::Zero(rows,cols),m1), m3);
  // shorter versions:
  VERIFY_IS_APPROX( (m1.abs()<ArrayType::Constant(rows,cols,mid))
                        .select(0,m1), m3);
  VERIFY_IS_APPROX( (m1.abs()>=ArrayType::Constant(rows,cols,mid))
                        .select(m1,0), m3);
  // even shorter version:
  VERIFY_IS_APPROX( (m1.abs()<mid).select(0,m1), m3);

  // count
  VERIFY(((m1.abs()+1)>RealScalar(0.1)).count() == rows*cols);

  typedef Array<typename ArrayType::Index, Dynamic, 1> ArrayOfIndices;

  // TODO allows colwise/rowwise for array
  VERIFY_IS_APPROX(((m1.abs()+1)>RealScalar(0.1)).colwise().count(), ArrayOfIndices::Constant(cols,rows).transpose());
  VERIFY_IS_APPROX(((m1.abs()+1)>RealScalar(0.1)).rowwise().count(), ArrayOfIndices::Constant(rows, cols));
}

template<typename ArrayType> void array_real(const ArrayType& m)
{
  typedef typename ArrayType::Index Index;
  typedef typename ArrayType::Scalar Scalar;
  typedef typename NumTraits<Scalar>::Real RealScalar;

  Index rows = m.rows();
  Index cols = m.cols();

  ArrayType m1 = ArrayType::Random(rows, cols),
             m2 = ArrayType::Random(rows, cols),
             m3(rows, cols);

  VERIFY_IS_APPROX(m1.sin(), std::sin(m1));
  VERIFY_IS_APPROX(m1.sin(), internal::sin(m1));
  VERIFY_IS_APPROX(m1.cos(), std::cos(m1));
  VERIFY_IS_APPROX(m1.cos(), internal::cos(m1));

  VERIFY_IS_APPROX(internal::cos(m1+RealScalar(3)*m2), internal::cos((m1+RealScalar(3)*m2).eval()));
  VERIFY_IS_APPROX(std::cos(m1+RealScalar(3)*m2), std::cos((m1+RealScalar(3)*m2).eval()));

  VERIFY_IS_APPROX(m1.abs().sqrt(), std::sqrt(std::abs(m1)));
  VERIFY_IS_APPROX(m1.abs().sqrt(), internal::sqrt(internal::abs(m1)));
  VERIFY_IS_APPROX(m1.abs(), internal::sqrt(internal::abs2(m1)));

  VERIFY_IS_APPROX(internal::abs2(internal::real(m1)) + internal::abs2(internal::imag(m1)), internal::abs2(m1));
  VERIFY_IS_APPROX(internal::abs2(std::real(m1)) + internal::abs2(std::imag(m1)), internal::abs2(m1));
  if(!NumTraits<Scalar>::IsComplex)
    VERIFY_IS_APPROX(internal::real(m1), m1);

  VERIFY_IS_APPROX(m1.abs().log(), std::log(std::abs(m1)));
  VERIFY_IS_APPROX(m1.abs().log(), internal::log(internal::abs(m1)));

  VERIFY_IS_APPROX(m1.exp(), std::exp(m1));
  VERIFY_IS_APPROX(m1.exp() * m2.exp(), std::exp(m1+m2));
  VERIFY_IS_APPROX(m1.exp(), internal::exp(m1));
  VERIFY_IS_APPROX(m1.exp() / m2.exp(), std::exp(m1-m2));

  VERIFY_IS_APPROX(m1.pow(2), m1.square());
  VERIFY_IS_APPROX(std::pow(m1,2), m1.square());
  m3 = m1.abs();
  VERIFY_IS_APPROX(m3.pow(RealScalar(0.5)), m3.sqrt());
  VERIFY_IS_APPROX(std::pow(m3,RealScalar(0.5)), m3.sqrt());
}

void test_array()
{
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1( array(Array<float, 1, 1>()) );
    CALL_SUBTEST_2( array(Array22f()) );
    CALL_SUBTEST_3( array(Array44d()) );
    CALL_SUBTEST_4( array(ArrayXXcf(3, 3)) );
    CALL_SUBTEST_5( array(ArrayXXf(8, 12)) );
    CALL_SUBTEST_6( array(ArrayXXi(8, 12)) );
  }
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1( comparisons(Array<float, 1, 1>()) );
    CALL_SUBTEST_2( comparisons(Array22f()) );
    CALL_SUBTEST_3( comparisons(Array44d()) );
    CALL_SUBTEST_5( comparisons(ArrayXXf(8, 12)) );
    CALL_SUBTEST_6( comparisons(ArrayXXi(8, 12)) );
  }
  for(int i = 0; i < g_repeat; i++) {
    CALL_SUBTEST_1( array_real(Array<float, 1, 1>()) );
    CALL_SUBTEST_2( array_real(Array22f()) );
    CALL_SUBTEST_3( array_real(Array44d()) );
    CALL_SUBTEST_5( array_real(ArrayXXf(8, 12)) );
  }

  VERIFY((internal::is_same< internal::global_math_functions_filtering_base<int>::type, int >::value));
  VERIFY((internal::is_same< internal::global_math_functions_filtering_base<float>::type, float >::value));
  VERIFY((internal::is_same< internal::global_math_functions_filtering_base<Array2i>::type, ArrayBase<Array2i> >::value));
  typedef CwiseUnaryOp<internal::scalar_sum_op<double>, ArrayXd > Xpr;
  VERIFY((internal::is_same< internal::global_math_functions_filtering_base<Xpr>::type,
                           ArrayBase<Xpr>
                         >::value));
}
<|endoftext|>


<commit_before>// Author: Daniel.Lohner@cern.ch

#include "AliTRDNDFast.h"
#include "TCanvas.h"

extern Double_t langaufunc(Double_t *x, Double_t *par) {

    // needs protection, parameter [3]>0!!!!!
    // needs protection, parameter [4]>0!!!!!

    //Fit parameters:
    //par[0]=Width (scale) parameter of Landau density
    //par[1]=Most Probable (MP, location) parameter of Landau density
    //par[2]=Total area (integral -inf to inf, normalization constant)
    //par[3]=Width (sigma) of convoluted Gaussian function
    //par[4]=Exponential Slope Parameter
    //
    //In the Landau distribution (represented by the CERNLIB approximation),
    //the maximum is located at x=-0.22278298 with the location parameter=0.
    //This shift is corrected within this function, so that the actual
    //maximum is identical to the MP parameter.

    // Numeric constants
    Double_t invsq2pi = 0.3989422804014;   // (2 pi)^(-1/2)
    Double_t mpshift  = -0.22278298;       // Landau maximum location

    // Control constants
    Double_t np = 100.0;      // number of convolution stpdf
    Double_t sc =   5.0;      // convolution extends to +-sc Gaussian sigmas

    // Variables
    Double_t xx;
    Double_t mpc;
    Double_t fland;
    Double_t sum = 0.0;
    Double_t xlow,xupp;
    Double_t step;
    Double_t i;

    // MP shift correction
    mpc = par[1] - mpshift * par[0];

    // Range of convolution integral
    xlow = x[0] - sc * par[3];
    xupp = x[0] + sc * par[3];

    if(xlow<0)xlow=0;
    if(xupp<xlow)cout<<"ERROR: Convolution around Negative MPV"<<endl;

    step = (xupp-xlow) / np;

    // Convolution integral of Landau and Gaussian by sum
    for(i=1.0; i<=np/2; i++) {
	xx = xlow + (i-.5) * step;
	fland = TMath::Landau(xx,mpc,par[0])*TMath::Exp(-par[4]*xx) / par[0];	// mpc taken out
	sum += fland * TMath::Gaus(x[0],xx,par[3]);

	xx = xupp - (i-.5) * step;
	fland = TMath::Landau(xx,mpc,par[0])*TMath::Exp(-par[4]*xx) / par[0];	// mpc taken out
	sum += fland * TMath::Gaus(x[0],xx,par[3]);
    }

    return (par[2] * step * sum * invsq2pi / par[3]);
}

ClassImp(AliTRDNDFast);

AliTRDNDFast::AliTRDNDFast(): TObject(),
    fNDim(0),
    fTitle(""),
    fFunc(NULL),
    fHistos(NULL),
    fPars()
{
    // default constructor
}

AliTRDNDFast::AliTRDNDFast(const char *name,Int_t ndim,Int_t nbins,Double_t xlow,Double_t xup): TObject(),
fNDim(ndim),
fTitle(name),
fFunc(NULL),
fHistos(NULL),
fPars()
{
    Init();
    for(Int_t idim=0;idim<fNDim;idim++){
	fHistos[idim]=new TH1F(Form("%s_axis_%d",fTitle.Data(),idim),Form("%s_axis_%d",fTitle.Data(),idim),nbins,xlow,xup);
	fHistos[idim]->SetDirectory(0);
    }
}

AliTRDNDFast::AliTRDNDFast(const AliTRDNDFast &ref) : TObject(ref),
fNDim(ref.fNDim),
fTitle(ref.fTitle),
fFunc(NULL),
fHistos(NULL),
fPars()
{
    Cleanup();
    Init();
    for(Int_t idim=0;idim<fNDim;idim++){
	fHistos[idim]=(TH1F*)ref.fHistos[idim]->Clone(Form("%s_axis_%d",GetName(),idim));
	fHistos[idim]->SetDirectory(0);
	for(Int_t ipar=0;ipar<kNpar;ipar++)fPars[idim][ipar]=ref.fPars[idim][ipar];
    }
}

AliTRDNDFast &AliTRDNDFast::operator=(const AliTRDNDFast &ref){
    //
    // Assignment operator
    //
    if(this != &ref){
	TObject::operator=(ref);
	fNDim=ref.fNDim;
	fTitle=ref.fTitle;
	fFunc = ref.fFunc;
	fHistos=ref.fHistos;
	for(Int_t idim=0;idim<fNDim;idim++){
	    for(Int_t ipar=0;ipar<kNpar;ipar++)fPars[idim][ipar]=ref.fPars[idim][ipar];
	}
    }
    return *this;
}

AliTRDNDFast::~AliTRDNDFast(){
    Cleanup();

}

void AliTRDNDFast::Init(){

    for(Int_t ipar=0;ipar<kNpar;ipar++)fPars[ipar].Set(fNDim);
    fFunc=new TF1*[fNDim];
    fHistos=new TH1F*[fNDim];
    for(Int_t idim=0;idim<fNDim;idim++){
        fHistos[idim]=NULL;
	for(Int_t ipar=0;ipar<kNpar;ipar++)fPars[ipar].SetAt(0,idim);
	fFunc[idim]=NULL;
    }
}

void AliTRDNDFast::Cleanup(){
    if(fHistos){
	for(Int_t idim=0;idim<fNDim;idim++){
	    if(fHistos[idim]){
		delete fHistos[idim];
		fHistos[idim]=NULL;
	    }
	}
	delete[] fHistos;
	fHistos=NULL;
    }
    if(fPars){
	for(Int_t ipar=0;ipar<kNpar;ipar++){
	    fPars[ipar].Reset();
	}
    }
    if(fFunc){
	for(Int_t idim=0;idim<fNDim;idim++){
	    if(fFunc[idim]){
		delete fFunc[idim];
		fFunc[idim]=NULL;
	    }
	}
	delete[] fFunc;
	fFunc=NULL;
    }
}

void AliTRDNDFast::PrintPars(){
    for(Int_t idim=0;idim<fNDim;idim++){
	for(Int_t ipar=0;ipar<kNpar;ipar++)cout<<idim<<" "<<ipar<<" "<<GetParam(idim,ipar)<<endl;
    }
}

void AliTRDNDFast::ScaleLangauFun(TF1 *func,Double_t mpv){

    Double_t start[kNpar],low[kNpar],high[kNpar];
    for(Int_t ii=0;ii<kNpar;ii++){
	start[ii]=func->GetParameter(ii);
	func->GetParLimits(ii,low[ii],high[ii]);
    }

    Double_t scalefactor=mpv/start[1];

    for(Int_t ii=0;ii<kNpar;ii++){
	Double_t scale=1;
	if(ii==0||ii==1||ii==3)scale=scalefactor;
	if(ii==4)scale=1./scalefactor;
	start[ii]*=scale;
	low[ii]*=scale;
	high[ii]*=scale;
	func->SetParLimits(ii, low[ii], high[ii]);
    }
    func->SetParameters(start);
}

//---------------------------------------------------------------
//---------------------------------------------------------------
TF1 *AliTRDNDFast::GetLangauFun(TString funcname,Double_t range[2],Double_t scalefactor){

    Double_t start[kNpar] = {120, 1000, 1, 100, 1e-5};
    Double_t low[kNpar] = {10, 300, 0.01, 1, 0.};
    Double_t high[kNpar] = {1000, 3000, 100, 1000, 1.};

    TF1 *hlandauE=new TF1(funcname.Data(),langaufunc,0,range[1],kNpar);
    hlandauE->SetParameters(start);
    hlandauE->SetParNames("Width","MP","Area","GSigma","delta");
    for (int i=0; i<kNpar; i++) {
	hlandauE->SetParLimits(i, low[i], high[i]);
    }

    if(scalefactor!=1){ScaleLangauFun(hlandauE,scalefactor*start[1]);}

    return hlandauE;
}

TF1 *AliTRDNDFast::FitLandau(TString name,TH1F *htemp,Double_t range[2],TString option){

    TF1 *fitlandau1D=GetLangauFun(name,range);
    TF1 fit("land","landau");
    Double_t max=htemp->GetXaxis()->GetBinCenter(htemp->GetMaximumBin());
    fit.SetParameter(1,max);
    fit.SetParLimits(1,0,htemp->GetXaxis()->GetXmax());
    fit.SetParameter(2,0.3*max); // MPV may never become negative!!!!!
    htemp->Fit("land",option.Data(),"",range[0],range[1]);
    ScaleLangauFun(fitlandau1D,fit.GetParameter(1));
    htemp->Fit(fitlandau1D,option.Data(),"",range[0],range[1]); // range for references
    return fitlandau1D;
}

void AliTRDNDFast::BuildHistos(){

    for(Int_t idim=0;idim<fNDim;idim++){
        fHistos[idim]->Reset();
	// Fill Histo
	Double_t pars[kNpar];
	for(Int_t ipar=0;ipar<kNpar;ipar++)pars[ipar]=GetParam(idim,ipar);
        // Also Fill overflow bins!!!
	for(Int_t ii=1;ii<=fHistos[idim]->GetNbinsX()+1;ii++){
	    Double_t xval=fHistos[idim]->GetXaxis()->GetBinCenter(ii);
	    Double_t val=langaufunc(&xval,&pars[0]);
	    //Double_t val=fFunc[idim]->Eval(xval);
	    fHistos[idim]->SetBinContent(ii,val);
	}
	// Normalization
	fHistos[idim]->Scale(1./fHistos[idim]->Integral(1,fHistos[idim]->GetNbinsX(),"width"));
    }
}

void AliTRDNDFast::Build(Double_t **pars){
    // pars[ndim][npar]
    for(Int_t idim=0;idim<fNDim;idim++){
	for(Int_t ipar=0;ipar<kNpar;ipar++){
	    fPars[ipar].SetAt(pars[idim][ipar],idim);
	}
    }
    BuildHistos();
}

void AliTRDNDFast::Build(TH1F **hdEdx,TString path){

    Double_t range[2];

    TCanvas *CANV=new TCanvas("a","a");
    if(fNDim==2)CANV->Divide(2,1);
    if(fNDim==3)CANV->Divide(2,2);
    if(fNDim>6)CANV->Divide(3,3);
    // Fit and Extract Parameters
    for(Int_t idim=0;idim<fNDim;idim++){
	CANV->cd(idim+1);
        gPad->SetLogy();
	range[0]=hdEdx[idim]->GetXaxis()->GetXmin();
	range[1]=hdEdx[idim]->GetXaxis()->GetXmax();
	// Norm Histogram
	hdEdx[idim]->Scale(1./hdEdx[idim]->Integral(1,hdEdx[idim]->GetNbinsX(),"width"));
        // Fit Histogram
	fFunc[idim]=FitLandau(Form("fit%d",idim),hdEdx[idim],range,"RMB0");
	// Norm Landau
	fFunc[idim]->SetParameter(2,fFunc[idim]->GetParameter(2)/fFunc[idim]->Integral(range[0],range[1]));
	hdEdx[idim]->DrawCopy();
        fFunc[idim]->DrawCopy("same");
	// Set Pars
	for(Int_t ipar=0;ipar<kNpar;ipar++)fPars[ipar].SetAt(fFunc[idim]->GetParameter(ipar),idim);
    }
    if(path!="")CANV->Print(Form("%s/%s_Build.pdf",path.Data(),fTitle.Data()));
    delete CANV;

    BuildHistos();
}

Double_t AliTRDNDFast::Eval(Double_t *point) const{
    Double_t val=1;
    for(Int_t idim=0;idim<fNDim;idim++){
	Int_t bin=fHistos[idim]->GetXaxis()->FindBin(point[idim]);
	val*=fHistos[idim]->GetBinContent(bin);
    }
    return val;
}

void AliTRDNDFast::Random(Double_t *point) const{
    for(Int_t idim=0;idim<fNDim;idim++){
	point[idim]=fHistos[idim]->GetRandom();
    }
}

void AliTRDNDFast::Random(Double_t *point,AliTRDNDFast *nd0,AliTRDNDFast *nd1,Double_t w0,Double_t w1){
    for(Int_t idim=0;idim<nd0->fNDim;idim++){
	point[idim]=GetRandomInterpolation(nd0->fHistos[idim],nd1->fHistos[idim],w0,w1);
    }
}

Int_t AliTRDNDFast::BinarySearchInterpolation(Int_t start,Int_t end,Double_t *a0,Double_t *a1,Double_t w0,Double_t w1,Double_t val){

    if((end-start)==1)return start;
    Int_t mid=Int_t((end+start)/2);
    Double_t valmid=(w0*a0[mid]+w1*a1[mid])/(w0+w1);
    if(val>=valmid)return BinarySearchInterpolation(mid,end,a0,a1,w0,w1,val);
    return BinarySearchInterpolation(start,mid,a0,a1,w0,w1,val);
}

Double_t AliTRDNDFast::GetRandomInterpolation(TH1F *hist0,TH1F *hist1,Double_t w0,Double_t w1){

    // Draw Random Variable
    Double_t rand=gRandom->Rndm();

    // Get Integral Arrays
    Double_t *integral0=hist0->GetIntegral();
    Double_t *integral1=hist1->GetIntegral();

    Int_t nbinsX=hist0->GetNbinsX();

    Int_t ibin=BinarySearchInterpolation(1,nbinsX+1,integral0,integral1,w0,w1,rand);
    return hist0->GetXaxis()->GetBinCenter(ibin);
}

<commit_msg>coverity fix pachmay <Yvonne.Chiara.Pachmayer@cern.ch><commit_after>// Author: Daniel.Lohner@cern.ch

#include "AliTRDNDFast.h"
#include "TCanvas.h"

extern Double_t langaufunc(Double_t *x, Double_t *par) {

    // needs protection, parameter [3]>0!!!!!
    // needs protection, parameter [4]>0!!!!!

    //Fit parameters:
    //par[0]=Width (scale) parameter of Landau density
    //par[1]=Most Probable (MP, location) parameter of Landau density
    //par[2]=Total area (integral -inf to inf, normalization constant)
    //par[3]=Width (sigma) of convoluted Gaussian function
    //par[4]=Exponential Slope Parameter
    //
    //In the Landau distribution (represented by the CERNLIB approximation),
    //the maximum is located at x=-0.22278298 with the location parameter=0.
    //This shift is corrected within this function, so that the actual
    //maximum is identical to the MP parameter.

    // Numeric constants
    Double_t invsq2pi = 0.3989422804014;   // (2 pi)^(-1/2)
    Double_t mpshift  = -0.22278298;       // Landau maximum location

    // Control constants
    Double_t np = 100.0;      // number of convolution stpdf
    Double_t sc =   5.0;      // convolution extends to +-sc Gaussian sigmas

    // Variables
    Double_t xx;
    Double_t mpc;
    Double_t fland;
    Double_t sum = 0.0;
    Double_t xlow,xupp;
    Double_t step;
    Double_t i;

    // MP shift correction
    mpc = par[1] - mpshift * par[0];

    // Range of convolution integral
    xlow = x[0] - sc * par[3];
    xupp = x[0] + sc * par[3];

    if(xlow<0)xlow=0;
    if(xupp<xlow)cout<<"ERROR: Convolution around Negative MPV"<<endl;

    step = (xupp-xlow) / np;

    // Convolution integral of Landau and Gaussian by sum
    for(i=1.0; i<=np/2; i++) {
	xx = xlow + (i-.5) * step;
	fland = TMath::Landau(xx,mpc,par[0])*TMath::Exp(-par[4]*xx) / par[0];	// mpc taken out
	sum += fland * TMath::Gaus(x[0],xx,par[3]);

	xx = xupp - (i-.5) * step;
	fland = TMath::Landau(xx,mpc,par[0])*TMath::Exp(-par[4]*xx) / par[0];	// mpc taken out
	sum += fland * TMath::Gaus(x[0],xx,par[3]);
    }

    return (par[2] * step * sum * invsq2pi / par[3]);
}

ClassImp(AliTRDNDFast);

AliTRDNDFast::AliTRDNDFast(): TObject(),
    fNDim(0),
    fTitle(""),
    fFunc(NULL),
    fHistos(NULL),
    fPars()
{
    // default constructor
}

AliTRDNDFast::AliTRDNDFast(const char *name,Int_t ndim,Int_t nbins,Double_t xlow,Double_t xup): TObject(),
fNDim(ndim),
fTitle(name),
fFunc(NULL),
fHistos(NULL),
fPars()
{
    Init();
    for(Int_t idim=0;idim<fNDim;idim++){
	fHistos[idim]=new TH1F(Form("%s_axis_%d",fTitle.Data(),idim),Form("%s_axis_%d",fTitle.Data(),idim),nbins,xlow,xup);
	fHistos[idim]->SetDirectory(0);
    }
}

AliTRDNDFast::AliTRDNDFast(const AliTRDNDFast &ref) : TObject(ref),
fNDim(ref.fNDim),
fTitle(ref.fTitle),
fFunc(NULL),
fHistos(NULL),
fPars()
{
    Cleanup();
    Init();
    for(Int_t idim=0;idim<fNDim;idim++){
	fHistos[idim]=(TH1F*)ref.fHistos[idim]->Clone(Form("%s_axis_%d",GetName(),idim));
	fHistos[idim]->SetDirectory(0);
	for(Int_t ipar=0;ipar<kNpar;ipar++)fPars[idim][ipar]=ref.fPars[idim][ipar];
    }
}

AliTRDNDFast &AliTRDNDFast::operator=(const AliTRDNDFast &ref){
    //
    // Assignment operator
    //
    if(this != &ref){
	TObject::operator=(ref);
	fNDim=ref.fNDim;
	fTitle=ref.fTitle;
	fFunc = ref.fFunc;
	for(Int_t idim=0;idim<fNDim;idim++){
	  fHistos[idim]=(TH1F*)ref.fHistos[idim]->Clone(Form("%s_axis_%d",GetName(),idim));
	  fHistos[idim]->SetDirectory(0);
	  for(Int_t ipar=0;ipar<kNpar;ipar++)fPars[idim][ipar]=ref.fPars[idim][ipar];
	}
    }
    return *this;
}

AliTRDNDFast::~AliTRDNDFast(){
    Cleanup();

}

void AliTRDNDFast::Init(){

    for(Int_t ipar=0;ipar<kNpar;ipar++)fPars[ipar].Set(fNDim);
    fFunc=new TF1*[fNDim];
    fHistos=new TH1F*[fNDim];
    for(Int_t idim=0;idim<fNDim;idim++){
        fHistos[idim]=NULL;
	for(Int_t ipar=0;ipar<kNpar;ipar++)fPars[ipar].SetAt(0,idim);
	fFunc[idim]=NULL;
    }
}

void AliTRDNDFast::Cleanup(){
    if(fHistos){
	for(Int_t idim=0;idim<fNDim;idim++){
	    if(fHistos[idim]){
		delete fHistos[idim];
		fHistos[idim]=NULL;
	    }
	}
	delete[] fHistos;
	fHistos=NULL;
    }
    if(fPars){
	for(Int_t ipar=0;ipar<kNpar;ipar++){
	    fPars[ipar].Reset();
	}
    }
    if(fFunc){
	for(Int_t idim=0;idim<fNDim;idim++){
	    if(fFunc[idim]){
		delete fFunc[idim];
		fFunc[idim]=NULL;
	    }
	}
	delete[] fFunc;
	fFunc=NULL;
    }
}

void AliTRDNDFast::PrintPars(){
    for(Int_t idim=0;idim<fNDim;idim++){
	for(Int_t ipar=0;ipar<kNpar;ipar++)cout<<idim<<" "<<ipar<<" "<<GetParam(idim,ipar)<<endl;
    }
}

void AliTRDNDFast::ScaleLangauFun(TF1 *func,Double_t mpv){

    Double_t start[kNpar],low[kNpar],high[kNpar];
    for(Int_t ii=0;ii<kNpar;ii++){
	start[ii]=func->GetParameter(ii);
	func->GetParLimits(ii,low[ii],high[ii]);
    }

    Double_t scalefactor=mpv/start[1];

    for(Int_t ii=0;ii<kNpar;ii++){
	Double_t scale=1;
	if(ii==0||ii==1||ii==3)scale=scalefactor;
	if(ii==4)scale=1./scalefactor;
	start[ii]*=scale;
	low[ii]*=scale;
	high[ii]*=scale;
	func->SetParLimits(ii, low[ii], high[ii]);
    }
    func->SetParameters(start);
}

//---------------------------------------------------------------
//---------------------------------------------------------------
TF1 *AliTRDNDFast::GetLangauFun(TString funcname,Double_t range[2],Double_t scalefactor){

    Double_t start[kNpar] = {120, 1000, 1, 100, 1e-5};
    Double_t low[kNpar] = {10, 300, 0.01, 1, 0.};
    Double_t high[kNpar] = {1000, 3000, 100, 1000, 1.};

    TF1 *hlandauE=new TF1(funcname.Data(),langaufunc,0,range[1],kNpar);
    hlandauE->SetParameters(start);
    hlandauE->SetParNames("Width","MP","Area","GSigma","delta");
    for (int i=0; i<kNpar; i++) {
	hlandauE->SetParLimits(i, low[i], high[i]);
    }

    if(scalefactor!=1){ScaleLangauFun(hlandauE,scalefactor*start[1]);}

    return hlandauE;
}

TF1 *AliTRDNDFast::FitLandau(TString name,TH1F *htemp,Double_t range[2],TString option){

    TF1 *fitlandau1D=GetLangauFun(name,range);
    TF1 fit("land","landau");
    Double_t max=htemp->GetXaxis()->GetBinCenter(htemp->GetMaximumBin());
    fit.SetParameter(1,max);
    fit.SetParLimits(1,0,htemp->GetXaxis()->GetXmax());
    fit.SetParameter(2,0.3*max); // MPV may never become negative!!!!!
    htemp->Fit("land",option.Data(),"",range[0],range[1]);
    ScaleLangauFun(fitlandau1D,fit.GetParameter(1));
    htemp->Fit(fitlandau1D,option.Data(),"",range[0],range[1]); // range for references
    return fitlandau1D;
}

void AliTRDNDFast::BuildHistos(){

    for(Int_t idim=0;idim<fNDim;idim++){
        fHistos[idim]->Reset();
	// Fill Histo
	Double_t pars[kNpar];
	for(Int_t ipar=0;ipar<kNpar;ipar++)pars[ipar]=GetParam(idim,ipar);
        // Also Fill overflow bins!!!
	for(Int_t ii=1;ii<=fHistos[idim]->GetNbinsX()+1;ii++){
	    Double_t xval=fHistos[idim]->GetXaxis()->GetBinCenter(ii);
	    Double_t val=langaufunc(&xval,&pars[0]);
	    //Double_t val=fFunc[idim]->Eval(xval);
	    fHistos[idim]->SetBinContent(ii,val);
	}
	// Normalization
	fHistos[idim]->Scale(1./fHistos[idim]->Integral(1,fHistos[idim]->GetNbinsX(),"width"));
    }
}

void AliTRDNDFast::Build(Double_t **pars){
    // pars[ndim][npar]
    for(Int_t idim=0;idim<fNDim;idim++){
	for(Int_t ipar=0;ipar<kNpar;ipar++){
	    fPars[ipar].SetAt(pars[idim][ipar],idim);
	}
    }
    BuildHistos();
}

void AliTRDNDFast::Build(TH1F **hdEdx,TString path){

    Double_t range[2];

    TCanvas *CANV=new TCanvas("a","a");
    if(fNDim==2)CANV->Divide(2,1);
    if(fNDim==3)CANV->Divide(2,2);
    if(fNDim>6)CANV->Divide(3,3);
    // Fit and Extract Parameters
    for(Int_t idim=0;idim<fNDim;idim++){
	CANV->cd(idim+1);
        gPad->SetLogy();
	range[0]=hdEdx[idim]->GetXaxis()->GetXmin();
	range[1]=hdEdx[idim]->GetXaxis()->GetXmax();
	// Norm Histogram
	hdEdx[idim]->Scale(1./hdEdx[idim]->Integral(1,hdEdx[idim]->GetNbinsX(),"width"));
        // Fit Histogram
	fFunc[idim]=FitLandau(Form("fit%d",idim),hdEdx[idim],range,"RMB0");
	// Norm Landau
	fFunc[idim]->SetParameter(2,fFunc[idim]->GetParameter(2)/fFunc[idim]->Integral(range[0],range[1]));
	hdEdx[idim]->DrawCopy();
        fFunc[idim]->DrawCopy("same");
	// Set Pars
	for(Int_t ipar=0;ipar<kNpar;ipar++)fPars[ipar].SetAt(fFunc[idim]->GetParameter(ipar),idim);
    }
    if(path!="")CANV->Print(Form("%s/%s_Build.pdf",path.Data(),fTitle.Data()));
    delete CANV;

    BuildHistos();
}

Double_t AliTRDNDFast::Eval(Double_t *point) const{
    Double_t val=1;
    for(Int_t idim=0;idim<fNDim;idim++){
	Int_t bin=fHistos[idim]->GetXaxis()->FindBin(point[idim]);
	val*=fHistos[idim]->GetBinContent(bin);
    }
    return val;
}

void AliTRDNDFast::Random(Double_t *point) const{
    for(Int_t idim=0;idim<fNDim;idim++){
	point[idim]=fHistos[idim]->GetRandom();
    }
}

void AliTRDNDFast::Random(Double_t *point,AliTRDNDFast *nd0,AliTRDNDFast *nd1,Double_t w0,Double_t w1){
    for(Int_t idim=0;idim<nd0->fNDim;idim++){
	point[idim]=GetRandomInterpolation(nd0->fHistos[idim],nd1->fHistos[idim],w0,w1);
    }
}

Int_t AliTRDNDFast::BinarySearchInterpolation(Int_t start,Int_t end,Double_t *a0,Double_t *a1,Double_t w0,Double_t w1,Double_t val){

    if((end-start)==1)return start;
    Int_t mid=Int_t((end+start)/2);
    Double_t valmid=(w0*a0[mid]+w1*a1[mid])/(w0+w1);
    if(val>=valmid)return BinarySearchInterpolation(mid,end,a0,a1,w0,w1,val);
    return BinarySearchInterpolation(start,mid,a0,a1,w0,w1,val);
}

Double_t AliTRDNDFast::GetRandomInterpolation(TH1F *hist0,TH1F *hist1,Double_t w0,Double_t w1){

    // Draw Random Variable
    Double_t rand=gRandom->Rndm();

    // Get Integral Arrays
    Double_t *integral0=hist0->GetIntegral();
    Double_t *integral1=hist1->GetIntegral();

    Int_t nbinsX=hist0->GetNbinsX();

    Int_t ibin=BinarySearchInterpolation(1,nbinsX+1,integral0,integral1,w0,w1,rand);
    return hist0->GetXaxis()->GetBinCenter(ibin);
}

<|endoftext|>


<commit_before><commit_msg>Small fix.<commit_after><|endoftext|>