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

#ifndef ASMITH_REFLECTION_FUNCTION_HPP
#define ASMITH_REFLECTION_FUNCTION_HPP

#include <string>

namespace asmith {

	class reflection_class;

	class reflection_function {
	protected:
		virtual void call_(void*, void*, const void*) const = 0;
	public:
		virtual ~reflection_function() {}

		virtual const char* get_name() const = 0;
		virtual size_t get_parameter_count() const = 0;
		virtual const reflection_class& get_parameter(size_t) const = 0;
		virtual const reflection_class& get_return() const = 0;
		virtual size_t get_modifiers() const = 0;

		template<class R, class T>
		R call(T& aObject) const {
			//! \todo Check return type
			R tmp;
			call_(&aObject, &tmp, nullptr);
			return tmp;
		}

		template<class R, class T, class P1>
		R call(T& aObject, P1 p1) const {
			//! \todo Check return and parameter types
			R tmp;
			call_(&aObject, &tmp, &p1);
			return tmp;
		}

		template<class R, class T, class P1, class P2>
		R call(T& aObject, P1 p1, P2 p2) const {
			//! \todo Check return and parameter types
			R tmp;
			call_(&aObject, &tmp, &p1);
			return tmp;
		}

		template<class R, class T, class P1, class P2, class P3>
		R call(T& aObject, P1 p1, P2 p2, P3 p3) const {
			//! \todo Check return and parameter types
			R tmp;
			call_(&aObject, &tmp, &p1);
			return tmp;
		}

		template<class R, class T, class P1, class P2, class P3, class P4>
		R call(T& aObject, P1 p1, P2 p2, P3 p3, P4 p4) const {
			//! \todo Check return and parameter types
			R tmp;
			call_(&aObject, &tmp, &p1);
			return tmp;
		}

		template<class R, class T, class P1, class P2, class P3, class P4, class P5>
		R call(T& aObject, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const {
			//! \todo Check return and parameter types
			R tmp;
			call_(&aObject, &tmp, &p1);
			return tmp;
		}
	};

	template<class CLASS, class RETURN, class... PARAMS>
	class auto_reflection_function : public reflection_function {
	public:
		typedef RETURN(CLASS::*ptr_t)(PARAMS...);
	private:
		const std::string mName;
		const ptr_t mPointer;
		const size_t mModifiers;

		//! \todo Implement for void return functions

		template<class R>
		void call__(void* aObject, void* aReturn, const void* aParams) const {
			CLASS& obj = *reinterpret_cast<CLASS*>(aObject);
			R& ret = *reinterpret_cast<RETURN*>(aReturn);
			ret = ((obj).*(mPointer))();
		}

		template<class R, class P1>
		void call__(void* aObject, void* aReturn, const void* aParams) const {
			CLASS& obj = *reinterpret_cast<CLASS*>(aObject);
			R& ret = *reinterpret_cast<RETURN*>(aReturn);
			const P1* const p1 = reinterpret_cast<const P1*>(aParams);
			ret = ((obj).*(mPointer))(*p1);
		}

		template<class R, class P1, class P2>
		void call__(void* aObject, void* aReturn, const void* aParams) const {
			CLASS& obj = *reinterpret_cast<CLASS*>(aObject);
			R& ret = *reinterpret_cast<RETURN*>(aReturn);
			const P1* const p1 = reinterpret_cast<const P1*>(aParams);
			const P2* const p2 = reinterpret_cast<const P2*>(reinterpret_cast<const uint8_t*>(p1) + sizeof(P1));
			ret = ((obj).*(mPointer))(*p1, *p2);
		}

		template<class R, class P1, class P2, class P3>
		void call__(void* aObject, void* aReturn, const void* aParams) const {
			CLASS& obj = *reinterpret_cast<CLASS*>(aObject);
			R& ret = *reinterpret_cast<RETURN*>(aReturn);
			const P1* const p1 = reinterpret_cast<const P1*>(aParams);
			const P2* const p2 = reinterpret_cast<const P2*>(reinterpret_cast<const uint8_t*>(p1) + sizeof(P1));
			const P3* const p3 = reinterpret_cast<const P3*>(reinterpret_cast<const uint8_t*>(p2) + sizeof(P2));
			ret = ((obj).*(mPointer))(*p1, *p2, *p3);
		}

		template<class R, class P1, class P2, class P3, class P4>
		void call__(void* aObject, void* aReturn, const void* aParams) const {
			CLASS& obj = *reinterpret_cast<CLASS*>(aObject);
			R& ret = *reinterpret_cast<RETURN*>(aReturn);
			const P1* const p1 = reinterpret_cast<const P1*>(aParams);
			const P2* const p2 = reinterpret_cast<const P2*>(reinterpret_cast<const uint8_t*>(p1) + sizeof(P1));
			const P3* const p3 = reinterpret_cast<const P3*>(reinterpret_cast<const uint8_t*>(p2) + sizeof(P2));
			const P4* const p3 = reinterpret_cast<const P4*>(reinterpret_cast<const uint8_t*>(p3) + sizeof(P3));
			ret = ((obj).*(mPointer))(*p1, *p2, *p3, *p4);
		}

		template<class R, class P1, class P2, class P3, class P4, class P5>
		void call__(void* aObject, void* aReturn, const void* aParams) const {
			CLASS& obj = *reinterpret_cast<CLASS*>(aObject);
			R& ret = *reinterpret_cast<RETURN*>(aReturn);
			const P1* const p1 = reinterpret_cast<const P1*>(aParams);
			const P2* const p2 = reinterpret_cast<const P2*>(reinterpret_cast<const uint8_t*>(p1) + sizeof(P1));
			const P3* const p3 = reinterpret_cast<const P3*>(reinterpret_cast<const uint8_t*>(p2) + sizeof(P2));
			const P4* const p3 = reinterpret_cast<const P4*>(reinterpret_cast<const uint8_t*>(p3) + sizeof(P3));
			const P5* const p3 = reinterpret_cast<const P5*>(reinterpret_cast<const uint8_t*>(p4) + sizeof(P4));
			ret = ((obj).*(mPointer))(*p1, *p2, *p3, *p4, *p5);
		}
	protected:
		// Inherited from reflection_function
		void call_(void* aObject, void* aReturn, const void* aParams) const override {
			call__<RETURN, PARAMS...>(aObject, aReturn, aParams);
		}
	public:
		auto_reflection_function(const std::string& aName, const ptr_t aPtr, const size_t aModifiers) :
			mName(aName),
			mModifiers(aModifiers),
			mPointer(aPtr)
		{}

		// Inherited from reflection_function
		const char* get_name() const override {
			return mName.c_str();
		}

		size_t get_parameter_count() const override {
			return sizeof...(PARAMS);
		}

		const reflection_class& get_parameter(size_t aIndex) const override {
			//! \todo Implement
			throw 0;
		};

		const reflection_class& get_return() const override {
			//! \todo Implement
			throw 0;
		};

		size_t get_modifiers() const override {
			return mModifiers;
		};
	};
}

#endif<commit_msg>Void returing functions implemented<commit_after>//	Copyright 2017 Adam Smith
//	Licensed under the Apache License, Version 2.0 (the "License");
//	you may not use this file except in compliance with the License.
//	You may obtain a copy of the License at
//
//	http://www.apache.org/licenses/LICENSE-2.0
//
//	Unless required by applicable law or agreed to in writing, software
//	distributed under the License is distributed on an "AS IS" BASIS,
//	WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//	See the License for the specific language governing permissions and
//	limitations under the License.

#ifndef ASMITH_REFLECTION_FUNCTION_HPP
#define ASMITH_REFLECTION_FUNCTION_HPP

#include <string>

namespace asmith {

	class reflection_class;

	class reflection_function {
	protected:
		virtual void call_(void*, void*, const void*) const = 0;
	public:
		virtual ~reflection_function() {}

		virtual const char* get_name() const = 0;
		virtual size_t get_parameter_count() const = 0;
		virtual const reflection_class& get_parameter(size_t) const = 0;
		virtual const reflection_class& get_return() const = 0;
		virtual size_t get_modifiers() const = 0;

		template<class R, class T>
		R call(T& aObject) const {
			//! \todo Check return type
			R tmp;
			call_(&aObject, &tmp, nullptr);
			return tmp;
		}

		template<class R, class T, class P1>
		R call(T& aObject, P1 p1) const {
			//! \todo Check return and parameter types
			R tmp;
			call_(&aObject, &tmp, &p1);
			return tmp;
		}

		template<class R, class T, class P1, class P2>
		R call(T& aObject, P1 p1, P2 p2) const {
			//! \todo Check return and parameter types
			R tmp;
			call_(&aObject, &tmp, &p1);
			return tmp;
		}

		template<class R, class T, class P1, class P2, class P3>
		R call(T& aObject, P1 p1, P2 p2, P3 p3) const {
			//! \todo Check return and parameter types
			R tmp;
			call_(&aObject, &tmp, &p1);
			return tmp;
		}

		template<class R, class T, class P1, class P2, class P3, class P4>
		R call(T& aObject, P1 p1, P2 p2, P3 p3, P4 p4) const {
			//! \todo Check return and parameter types
			R tmp;
			call_(&aObject, &tmp, &p1);
			return tmp;
		}

		template<class R, class T, class P1, class P2, class P3, class P4, class P5>
		R call(T& aObject, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5) const {
			//! \todo Check return and parameter types
			R tmp;
			call_(&aObject, &tmp, &p1);
			return tmp;
		}
	};

	template<class CLASS, class RETURN, class... PARAMS>
	class auto_reflection_function : public reflection_function {
	public:
		typedef RETURN(CLASS::*ptr_t)(PARAMS...);
	private:
		const std::string mName;
		const ptr_t mPointer;
		const size_t mModifiers;

		template<class R>
		typename std::enable_if<std::is_same<R, void>::value, void>::type call__(void* aObject, void* aReturn, const void* aParams) const {
			CLASS& obj = *reinterpret_cast<CLASS*>(aObject);
			((obj).*(mPointer))();
		}

		template<class R, class P1>
		typename std::enable_if<std::is_same<R, void>::value, void>::type call__(void* aObject, void* aReturn, const void* aParams) const {
			CLASS& obj = *reinterpret_cast<CLASS*>(aObject);
			const P1* const p1 = reinterpret_cast<const P1*>(aParams);
			((obj).*(mPointer))(*p1);
		}

		template<class R, class P1, class P2>
		typename std::enable_if<std::is_same<R, void>::value, void>::type call__(void* aObject, void* aReturn, const void* aParams) const {
			CLASS& obj = *reinterpret_cast<CLASS*>(aObject);
			const P1* const p1 = reinterpret_cast<const P1*>(aParams);
			const P2* const p2 = reinterpret_cast<const P2*>(reinterpret_cast<const uint8_t*>(p1) + sizeof(P1));
			((obj).*(mPointer))(*p1, *p2);
		}

		template<class R, class P1, class P2, class P3>
		typename std::enable_if<std::is_same<R, void>::value, void>::type call__(void* aObject, void* aReturn, const void* aParams) const {
			CLASS& obj = *reinterpret_cast<CLASS*>(aObject);
			const P1* const p1 = reinterpret_cast<const P1*>(aParams);
			const P2* const p2 = reinterpret_cast<const P2*>(reinterpret_cast<const uint8_t*>(p1) + sizeof(P1));
			const P3* const p3 = reinterpret_cast<const P3*>(reinterpret_cast<const uint8_t*>(p2) + sizeof(P2));
			((obj).*(mPointer))(*p1, *p2, *p3);
		}

		template<class R, class P1, class P2, class P3, class P4>
		typename std::enable_if<std::is_same<R, void>::value, void>::type call__(void* aObject, void* aReturn, const void* aParams) const {
			CLASS& obj = *reinterpret_cast<CLASS*>(aObject);
			const P1* const p1 = reinterpret_cast<const P1*>(aParams);
			const P2* const p2 = reinterpret_cast<const P2*>(reinterpret_cast<const uint8_t*>(p1) + sizeof(P1));
			const P3* const p3 = reinterpret_cast<const P3*>(reinterpret_cast<const uint8_t*>(p2) + sizeof(P2));
			const P4* const p3 = reinterpret_cast<const P4*>(reinterpret_cast<const uint8_t*>(p3) + sizeof(P3));
			((obj).*(mPointer))(*p1, *p2, *p3, *p4);
		}

		template<class R, class P1, class P2, class P3, class P4, class P5>
		typename std::enable_if<std::is_same<R, void>::value, void>::type call__(void* aObject, void* aReturn, const void* aParams) const {
			CLASS& obj = *reinterpret_cast<CLASS*>(aObject);
			const P1* const p1 = reinterpret_cast<const P1*>(aParams);
			const P2* const p2 = reinterpret_cast<const P2*>(reinterpret_cast<const uint8_t*>(p1) + sizeof(P1));
			const P3* const p3 = reinterpret_cast<const P3*>(reinterpret_cast<const uint8_t*>(p2) + sizeof(P2));
			const P4* const p3 = reinterpret_cast<const P4*>(reinterpret_cast<const uint8_t*>(p3) + sizeof(P3));
			const P5* const p3 = reinterpret_cast<const P5*>(reinterpret_cast<const uint8_t*>(p4) + sizeof(P4));
			((obj).*(mPointer))(*p1, *p2, *p3, *p4, *p5);
		}

		template<class R>
		typename std::enable_if<! std::is_same<R,void>::value, void>::type call__(void* aObject, void* aReturn, const void* aParams) const {
			CLASS& obj = *reinterpret_cast<CLASS*>(aObject);
			R& ret = *reinterpret_cast<RETURN*>(aReturn);
			ret = ((obj).*(mPointer))();
		}

		template<class R, class P1>
		typename std::enable_if<!std::is_same<R, void>::value, void>::type call__(void* aObject, void* aReturn, const void* aParams) const {
			CLASS& obj = *reinterpret_cast<CLASS*>(aObject);
			R& ret = *reinterpret_cast<RETURN*>(aReturn);
			const P1* const p1 = reinterpret_cast<const P1*>(aParams);
			ret = ((obj).*(mPointer))(*p1);
		}

		template<class R, class P1, class P2>
		typename std::enable_if<!std::is_same<R, void>::value, void>::type call__(void* aObject, void* aReturn, const void* aParams) const {
			CLASS& obj = *reinterpret_cast<CLASS*>(aObject);
			R& ret = *reinterpret_cast<RETURN*>(aReturn);
			const P1* const p1 = reinterpret_cast<const P1*>(aParams);
			const P2* const p2 = reinterpret_cast<const P2*>(reinterpret_cast<const uint8_t*>(p1) + sizeof(P1));
			ret = ((obj).*(mPointer))(*p1, *p2);
		}

		template<class R, class P1, class P2, class P3>
		typename std::enable_if<!std::is_same<R, void>::value, void>::type call__(void* aObject, void* aReturn, const void* aParams) const {
			CLASS& obj = *reinterpret_cast<CLASS*>(aObject);
			R& ret = *reinterpret_cast<RETURN*>(aReturn);
			const P1* const p1 = reinterpret_cast<const P1*>(aParams);
			const P2* const p2 = reinterpret_cast<const P2*>(reinterpret_cast<const uint8_t*>(p1) + sizeof(P1));
			const P3* const p3 = reinterpret_cast<const P3*>(reinterpret_cast<const uint8_t*>(p2) + sizeof(P2));
			ret = ((obj).*(mPointer))(*p1, *p2, *p3);
		}

		template<class R, class P1, class P2, class P3, class P4>
		typename std::enable_if<!std::is_same<R, void>::value, void>::type call__(void* aObject, void* aReturn, const void* aParams) const {
			CLASS& obj = *reinterpret_cast<CLASS*>(aObject);
			R& ret = *reinterpret_cast<RETURN*>(aReturn);
			const P1* const p1 = reinterpret_cast<const P1*>(aParams);
			const P2* const p2 = reinterpret_cast<const P2*>(reinterpret_cast<const uint8_t*>(p1) + sizeof(P1));
			const P3* const p3 = reinterpret_cast<const P3*>(reinterpret_cast<const uint8_t*>(p2) + sizeof(P2));
			const P4* const p3 = reinterpret_cast<const P4*>(reinterpret_cast<const uint8_t*>(p3) + sizeof(P3));
			ret = ((obj).*(mPointer))(*p1, *p2, *p3, *p4);
		}

		template<class R, class P1, class P2, class P3, class P4, class P5>
		typename std::enable_if<!std::is_same<R, void>::value, void>::type call__(void* aObject, void* aReturn, const void* aParams) const {
			CLASS& obj = *reinterpret_cast<CLASS*>(aObject);
			R& ret = *reinterpret_cast<RETURN*>(aReturn);
			const P1* const p1 = reinterpret_cast<const P1*>(aParams);
			const P2* const p2 = reinterpret_cast<const P2*>(reinterpret_cast<const uint8_t*>(p1) + sizeof(P1));
			const P3* const p3 = reinterpret_cast<const P3*>(reinterpret_cast<const uint8_t*>(p2) + sizeof(P2));
			const P4* const p3 = reinterpret_cast<const P4*>(reinterpret_cast<const uint8_t*>(p3) + sizeof(P3));
			const P5* const p3 = reinterpret_cast<const P5*>(reinterpret_cast<const uint8_t*>(p4) + sizeof(P4));
			ret = ((obj).*(mPointer))(*p1, *p2, *p3, *p4, *p5);
		}
	protected:
		// Inherited from reflection_function
		void call_(void* aObject, void* aReturn, const void* aParams) const override {
			call__<RETURN, PARAMS...>(aObject, aReturn, aParams);
		}
	public:
		auto_reflection_function(const std::string& aName, const ptr_t aPtr, const size_t aModifiers) :
			mName(aName),
			mModifiers(aModifiers),
			mPointer(aPtr)
		{}

		// Inherited from reflection_function
		const char* get_name() const override {
			return mName.c_str();
		}

		size_t get_parameter_count() const override {
			return sizeof...(PARAMS);
		}

		const reflection_class& get_parameter(size_t aIndex) const override {
			//! \todo Implement
			throw 0;
		};

		const reflection_class& get_return() const override {
			//! \todo Implement
			throw 0;
		};

		size_t get_modifiers() const override {
			return mModifiers;
		};
	};
}

#endif<|endoftext|>


<commit_before>/******************************************************************************
** Copyright (c) 2014-2015, Intel Corporation                                **
** All rights reserved.                                                      **
**                                                                           **
** Redistribution and use in source and binary forms, with or without        **
** modification, are permitted provided that the following conditions        **
** are met:                                                                  **
** 1. Redistributions of source code must retain the above copyright         **
**    notice, this list of conditions and the following disclaimer.          **
** 2. 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.   **
** 3. Neither the name of the copyright holder 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      **
** HOLDER 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.              **
******************************************************************************/
/* Hans Pabst (Intel Corp.)
******************************************************************************/
#include <libxstream_begin.h>
#include <stdexcept>
#include <algorithm>
#include <cstdio>
#if defined(_OPENMP)
# include <omp.h>
#endif
#include <libxstream_end.h>

#define COPY_ISYNC

int main(int argc, char* argv[])
{
  try {
#if defined(_OPENMP)
    const int nthreads = std::min(std::max(1 < argc ? std::atoi(argv[1]) : 1, 1), omp_get_max_threads());
#else
    const int nthreads = std::min(std::max(1 < argc ? std::atoi(argv[1]) : 1, 1), 1);
    LIBXSTREAM_PRINT0(1, "OpenMP support needed for performance results!");
    libxstream_use_sink(&nthreads);
#endif
    const int nstreams = std::min(std::max(2 < argc ? std::atoi(argv[2]) : 1, 1), LIBXSTREAM_MAX_NSTREAMS);
    const size_t maxsize = static_cast<size_t>(std::min(std::max(3 < argc ? std::atoi(argv[3]) : 2048, 1), 8192)) * (1 << 20), minsize = 8;
    int nrepeat = std::min(std::max(4 < argc ? std::atoi(argv[4]) : 7, 3), 100);

    size_t ndevices = 0;
    if (LIBXSTREAM_ERROR_NONE != libxstream_get_ndevices(&ndevices) || 0 == ndevices) {
      throw std::runtime_error("no device found!");
    }

    const size_t stride = 2;
    for (size_t size = minsize, n = 1; size <= maxsize; size <<= 1, ++n) {
      if (0 == (n % stride)) {
        nrepeat <<= 1;
      }
    }

    void *buffer = 0;
    LIBXSTREAM_CHECK_CALL_THROW(libxstream_mem_allocate(-1, &buffer, maxsize, 0));

    struct {
      libxstream_stream* stream;
      void* buffer;
    } copy[LIBXSTREAM_MAX_NSTREAMS];
    for (int i = 0; i < nstreams; ++i) {
      char name[128];
      LIBXSTREAM_SNPRINTF(name, sizeof(name), "Stream %i", i + 1);
      LIBXSTREAM_CHECK_CALL_THROW(libxstream_stream_create(&copy[i].stream, 0, 0, name));
      LIBXSTREAM_CHECK_CALL_THROW(libxstream_mem_allocate(0/*device*/, &copy[i].buffer, maxsize, 0));
    }

    int n = 1;
    double runavg = 0, runlns = 0;
    for (size_t size = minsize; size <= maxsize; size <<= 1, ++n) {
      if (0 == (n % stride)) {
        nrepeat >>= 1;
      }

#if defined(_OPENMP)
      const double start = omp_get_wtime();
#     pragma omp parallel for num_threads(nthreads) schedule(dynamic)
#endif
      for (int i = 0; i < nrepeat; ++i) {
        const int j = i % nstreams;
        LIBXSTREAM_CHECK_CALL_ASSERT(libxstream_memcpy_h2d(buffer, copy[j].buffer, size, copy[j].stream));

#if defined(COPY_ISYNC)
        const int k = (j + 1) % nstreams;
        LIBXSTREAM_CHECK_CALL_ASSERT(libxstream_stream_sync(copy[k].stream));
#endif
      }

      // sync all streams to complete any pending work
      LIBXSTREAM_CHECK_CALL_THROW(libxstream_stream_sync(0));

#if defined(_OPENMP)
      const double duration = omp_get_wtime() - start;
      LIBXSTREAM_FLOCK(stdout);
      fprintf(stdout, "%lu Byte x %i: ", static_cast<unsigned long>(size), nrepeat);
      if (0 < duration) {
        const double bandwidth = (1.0 * size * nrepeat) / ((1ul << 20) * duration), factor = 1 < n ? 0.5 : 1.0;
        fprintf(stdout, "%.1f MB/s\n", bandwidth);
        runavg = (runavg + bandwidth) * factor;
        runlns = (runlns + std::log(bandwidth)) * factor;
      }
      else {
        fprintf(stdout, "-\n");
      }
      LIBXSTREAM_FUNLOCK(stdout);
#endif
    }

    if (1 < n) {
      fprintf(stdout, "runavg=%.0f rungeo=%.0f MB/s\n", runavg, std::exp(runlns));
    }
    fprintf(stdout, "Finished\n");
  }
  catch(const std::exception& e) {
    fprintf(stderr, "Error: %s\n", e.what());
    return EXIT_FAILURE;
  }
  catch(...) {
    fprintf(stderr, "Error: unknown exception caught!\n");
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}
<commit_msg>Implemented copy-out benchmark and extended the command line interface accordingly.<commit_after>/******************************************************************************
** Copyright (c) 2014-2015, Intel Corporation                                **
** All rights reserved.                                                      **
**                                                                           **
** Redistribution and use in source and binary forms, with or without        **
** modification, are permitted provided that the following conditions        **
** are met:                                                                  **
** 1. Redistributions of source code must retain the above copyright         **
**    notice, this list of conditions and the following disclaimer.          **
** 2. 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.   **
** 3. Neither the name of the copyright holder 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      **
** HOLDER 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.              **
******************************************************************************/
/* Hans Pabst (Intel Corp.)
******************************************************************************/
#include <libxstream_begin.h>
#include <stdexcept>
#include <algorithm>
#include <cstdio>
#if defined(_OPENMP)
# include <omp.h>
#endif
#include <libxstream_end.h>

#define COPY_ISYNC

int main(int argc, char* argv[])
{
  try {
    const bool copyin = 1 < argc ? ('i' == *argv[1]) : true;
#if defined(_OPENMP)
    const int nthreads = std::min(std::max(2 < argc ? std::atoi(argv[2]) : 1, 1), omp_get_max_threads());
#else
    const int nthreads = std::min(std::max(2 < argc ? std::atoi(argv[2]) : 1, 1), 1);
    LIBXSTREAM_PRINT0(1, "OpenMP support needed for performance results!");
    libxstream_use_sink(&nthreads);
#endif
    const int nstreams = std::min(std::max(3 < argc ? std::atoi(argv[3]) : 1, 1), LIBXSTREAM_MAX_NSTREAMS);
    const size_t maxsize = static_cast<size_t>(std::min(std::max(4 < argc ? std::atoi(argv[4]) : 2048, 1), 8192)) * (1 << 20), minsize = 8;
    int nrepeat = std::min(std::max(5 < argc ? std::atoi(argv[5]) : 7, 3), 100);

    size_t ndevices = 0;
    if (LIBXSTREAM_ERROR_NONE != libxstream_get_ndevices(&ndevices) || 0 == ndevices) {
      throw std::runtime_error("no device found!");
    }

    const size_t stride = 2;
    for (size_t size = minsize, n = 1; size <= maxsize; size <<= 1, ++n) {
      if (0 == (n % stride)) {
        nrepeat <<= 1;
      }
    }

    struct {
      libxstream_stream* stream;
      void *mem_hst, *mem_dev;
    } copy[LIBXSTREAM_MAX_NSTREAMS];
    for (int i = 0; i < nstreams; ++i) {
      char name[128];
      LIBXSTREAM_SNPRINTF(name, sizeof(name), "Stream %i", i + 1);
      LIBXSTREAM_CHECK_CALL_THROW(libxstream_stream_create(&copy[i].stream, 0, 0, name));
      if (copyin) {
        if (0 == i) {
          LIBXSTREAM_CHECK_CALL_THROW(libxstream_mem_allocate(-1/*host*/, &copy[i].mem_hst, maxsize, 0));
        }
        else {
          copy[i].mem_hst = copy[0].mem_hst;
        }
        LIBXSTREAM_CHECK_CALL_THROW(libxstream_mem_allocate(0/*device*/, &copy[i].mem_dev, maxsize, 0));
      }
      else { // copy-out
        LIBXSTREAM_CHECK_CALL_THROW(libxstream_mem_allocate(-1/*host*/, &copy[i].mem_hst, maxsize, 0));
        if (0 == i) {
          LIBXSTREAM_CHECK_CALL_THROW(libxstream_mem_allocate(0/*device*/, &copy[i].mem_dev, maxsize, 0));
        }
        else {
          copy[i].mem_dev = copy[0].mem_dev;
        }
      }
    }

    int n = 1;
    double runavg = 0, runlns = 0;
    for (size_t size = minsize; size <= maxsize; size <<= 1, ++n) {
      if (0 == (n % stride)) {
        nrepeat >>= 1;
      }

#if defined(_OPENMP)
      const double start = omp_get_wtime();
#     pragma omp parallel for num_threads(nthreads) schedule(dynamic)
#endif
      for (int i = 0; i < nrepeat; ++i) {
        const int j = i % nstreams;
        if (copyin) {
          LIBXSTREAM_CHECK_CALL_ASSERT(libxstream_memcpy_h2d(copy[j].mem_hst, copy[j].mem_dev, size, copy[j].stream));
        }
        else {
          LIBXSTREAM_CHECK_CALL_ASSERT(libxstream_memcpy_d2h(copy[j].mem_dev, copy[j].mem_hst, size, copy[j].stream));
        }

#if defined(COPY_ISYNC)
        const int k = (j + 1) % nstreams;
        LIBXSTREAM_CHECK_CALL_ASSERT(libxstream_stream_sync(copy[k].stream));
#endif
      }

      // sync all streams to complete any pending work
      LIBXSTREAM_CHECK_CALL_THROW(libxstream_stream_sync(0));

#if defined(_OPENMP)
      const double duration = omp_get_wtime() - start;
      fprintf(stdout, "%lu Byte x %i: ", static_cast<unsigned long>(size), nrepeat);
      if (0 < duration) {
        const double bandwidth = (1.0 * size * nrepeat) / ((1ul << 20) * duration), factor = 1 < n ? 0.5 : 1.0;
        fprintf(stdout, "%.1f MB/s\n", bandwidth);
        runavg = (runavg + bandwidth) * factor;
        runlns = (runlns + std::log(bandwidth)) * factor;
      }
      else {
        fprintf(stdout, "-\n");
      }
      fflush(stdout);
#endif
    }

    if (1 < n) {
      fprintf(stdout, "runavg=%.0f rungeo=%.0f MB/s\n", runavg, std::exp(runlns));
    }
    fprintf(stdout, "Finished\n");
  }
  catch(const std::exception& e) {
    fprintf(stderr, "Error: %s\n", e.what());
    return EXIT_FAILURE;
  }
  catch(...) {
    fprintf(stderr, "Error: unknown exception caught!\n");
    return EXIT_FAILURE;
  }

  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>#include <sksat/common.hpp>

namespace sksat {

using opt_func = int (*)(int, char**);
class optparse {
public:
	struct option {
		char s_opt;
		sksat::string l_opt, desc;
		opt_func func;
	};

	optparse() : argc(0), argv(nullptr) {}

	void add_opt(optparse::option o){
		opts.push_back(o);
	}

	void add_opt(char s_opt, sksat::string l_opt, sksat::string desc, opt_func func){
		option o = {
			.s_opt = s_opt,
			.l_opt = l_opt,
			.desc  = desc,
			.func  = func
		};

		add_opt(o);
	}

	void add_opt(char s_opt, sksat::string desc, opt_func func){
		option o = {
			.s_opt = s_opt,
			.l_opt = "",
			.desc  = desc,
			.func  = func
		};
		add_opt(o);
	}

	int search_short_opt(char c){
		for(int i=0;i<opts.size();i++){
			if(opts[i].s_opt == c) return i;
		}
		return -1;
	}

	int search_long_opt(sksat::string str){
		if(str == "") return -1;
		for(int i=0;i<opts.size();i++){
			if(opts[i].l_opt == str) return i;
		}
		return -1;
	}

	bool parse(int argc, char **argv){
		this->argc = argc;
		this->argv = argv;
		if(argc == 1) return false;
		argc--;
		argv++;
		for(int i=0;i<argc;i++){
			int opt_num = -1;
			if(argv[0][0] == '-'){ // option?
				if(argv[0][1] == '-'){ // long option
					opt_num = search_long_opt(argv[0]+2);
				}else{ // short option
					opt_num = search_short_opt(argv[0][1]);
				}
			}
			if(opt_num > -1){ // option found
				opt_func f = opts[opt_num].func;
				int ret = f(argc-i, argv);
				i += ret;
				argv+=ret;
			}
			argv++;
		}
	}

private:
	int argc;
	char **argv;
	sksat::vector<option> opts;
};

}
<commit_msg>[FIX]<commit_after>#include <sksat/common.hpp>

namespace sksat {

using opt_func = int (*)(int, char**);
class optparse {
public:
	struct option {
		char s_opt;
		sksat::string l_opt, desc;
		opt_func func;
	};

	optparse() : argc(0), argv(nullptr) {}

	void add_opt(optparse::option o){
		opts.push_back(o);
	}

	void add_opt(char s_opt, sksat::string l_opt, sksat::string desc, opt_func func){
		option o = {
			.s_opt = s_opt,
			.l_opt = l_opt,
			.desc  = desc,
			.func  = func
		};

		add_opt(o);
	}

	void add_opt(char s_opt, sksat::string desc, opt_func func){
		option o = {
			.s_opt = s_opt,
			.l_opt = "",
			.desc  = desc,
			.func  = func
		};
		add_opt(o);
	}

	int search_short_opt(char c){
		for(int i=0;i<opts.size();i++){
			if(opts[i].s_opt == c) return i;
		}
		return -1;
	}

	int search_long_opt(sksat::string str){
		if(str == "") return -1;
		for(int i=0;i<opts.size();i++){
			if(opts[i].l_opt == str) return i;
		}
		return -1;
	}

	bool parse(int argc, char **argv){
		this->argc = argc;
		this->argv = argv;
		if(argc == 1) return false;
		argc--;
		argv++;
		for(int i=0;i<argc;i++){
			int opt_num = -1;
			if(argv[0][0] == '-'){ // option?
				if(argv[0][1] == '-'){ // long option
					opt_num = search_long_opt(argv[0]+2);
				}else{ // short option
					if(argv[0][1] != '\0'){
						if(argv[0][2] == '\0')
							opt_num = search_short_opt(argv[0][1]);
					}
				}
			}
			if(opt_num > -1){ // option found
				opt_func f = opts[opt_num].func;
				int ret = f(argc-i, argv);
				i += ret;
				argv+=ret;
			}
			argv++;
		}
	}

private:
	int argc;
	char **argv;
	sksat::vector<option> opts;
};

}
<|endoftext|>


<commit_before>/*
* Copyright (C) 2007-2013 German Aerospace Center (DLR/SC)
*
* Created: 2013-09-03 Martin Siggel <Martin.Siggel@dlr.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "CCPACSFarField.h"
#include "CTiglError.h"
#include "CTiglLogging.h"
#include "CCPACSConfiguration.h"

#include <string>
#include <cmath>

#include <gp_Ax2.hxx>
#include <BRepPrimAPI_MakeSphere.hxx>
#include <BRepPrimAPI_MakeBox.hxx>
#include <TopExp_Explorer.hxx>

#ifdef TIGL_USE_XCAF
#include <XCAFDoc_ShapeTool.hxx>
#include <XCAFApp_Application.hxx>
#include <XCAFDoc_DocumentTool.hxx>
#include <TDataStd_Name.hxx>
#include <TDataXtd_Shape.hxx>
#endif

namespace tigl
{

CCPACSFarField::CCPACSFarField()
{
    init();
}

CCPACSFarField::~CCPACSFarField() {}

void CCPACSFarField::init()
{
    fieldType = NONE;
    fieldSize = 0.;
    loft.Nullify();
    SetUID("FarField");
}

TiglFarFieldType CCPACSFarField::GetFieldType()
{
    return fieldType;
}

void CCPACSFarField::ReadCPACS(TixiDocumentHandle tixiHandle)
{
    init();

    std::string prefix = "/cpacs/toolspecific/cFD/farField";
    if (tixiCheckElement(tixiHandle, prefix.c_str()) != SUCCESS) {
        LOG(INFO) << "No far-field defined.";
        fieldType = NONE;
        return;
    }

    // get field type
    std::string typePath = prefix + "/type";
    char * tmpstr = NULL;
    if (tixiGetTextElement(tixiHandle, typePath.c_str(), &tmpstr) != SUCCESS) {
        fieldType = NONE;
        return;
    }
    else {
        if (strcmp(tmpstr, "halfSphere") == 0){
            fieldType = HALF_SPHERE;
        }
        else if (strcmp(tmpstr, "fullSphere") == 0){
            fieldType = FULL_SPHERE;
        }
        else if (strcmp(tmpstr, "halfCube") == 0){
            fieldType = HALF_CUBE;
        }
        else if (strcmp(tmpstr, "fullCube") == 0){
            fieldType = FULL_CUBE;
        }
        else {
            fieldType = NONE;
            return;
        }
    }

    // get reference length
    std::string refLenPath = prefix + "/referenceLength";
    if (tixiGetDoubleElement(tixiHandle, refLenPath.c_str(), &fieldSize) != SUCCESS) {
        fieldSize = 0.;
        throw tigl::CTiglError("No reference length defined for far-field!");
    }

    // get multiplier
    std::string multiplierPath = prefix + "/multiplier";
    double multiplier = 1.;
    if (tixiGetDoubleElement(tixiHandle, multiplierPath.c_str(), &multiplier) != SUCCESS) {
        fieldSize = 0.;
        throw tigl::CTiglError("No multiplier defined for far-field!");
    }
    else {
        fieldSize *= multiplier;
    }
}

TopoDS_Shape CCPACSFarField::BuildLoft(void)
{
    TopoDS_Shape shape;
    shape.Nullify();
    gp_Pnt center(0,0,0);

    switch(fieldType){
    case NONE:
        return shape;
    case FULL_SPHERE:
        shape = BRepPrimAPI_MakeSphere(center, fieldSize).Shape();
        break;
    case FULL_CUBE:
        shape = BRepPrimAPI_MakeBox(gp_Pnt(center.X()-fieldSize, center.Y()-fieldSize, center.Z()-fieldSize),
                                    fieldSize*2., fieldSize*2., fieldSize*2.).Shape();
        break;
    case HALF_CUBE:
        shape = BRepPrimAPI_MakeBox(gp_Pnt(center.X()-fieldSize, center.Y(), center.Z()-fieldSize),
                                    fieldSize*2., fieldSize, fieldSize*2.).Shape();
        break;
    case HALF_SPHERE:
        shape = BRepPrimAPI_MakeSphere(gp_Ax2(center, gp_Dir(0,1,0)), fieldSize, 0., M_PI_2).Shape();
        break;
    default:
        shape.Nullify();
    }

    return shape;
}

TiglGeometricComponentType CCPACSFarField::GetComponentType(void)
{
    return TIGL_COMPONENT_LOGICAL;
}

#ifdef TIGL_USE_XCAF
// builds data structure for a TDocStd_Application
// mostly used for export
TDF_Label CCPACSFarField::ExportDataStructure(CCPACSConfiguration&, Handle_XCAFDoc_ShapeTool &myAssembly, TDF_Label& label)
{
    // add faces of current shape
    TopExp_Explorer faceExplorer;
    int iface = 1;
    for (faceExplorer.Init(GetLoft(), TopAbs_FACE); faceExplorer.More(); faceExplorer.Next()) {
        const TopoDS_Face& currentFace = TopoDS::Face(faceExplorer.Current());

        TDF_Label aLabel = myAssembly->AddShape(currentFace, false);
        std::stringstream stream;
        stream << GetUID() << "_face" << iface++;
        TDataStd_Name::Set (aLabel, stream.str().c_str());

    }

    return label;
}
#endif

} // namespace tigl

<commit_msg>Style fix<commit_after>/*
* Copyright (C) 2007-2013 German Aerospace Center (DLR/SC)
*
* Created: 2013-09-03 Martin Siggel <Martin.Siggel@dlr.de>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

#include "CCPACSFarField.h"
#include "CTiglError.h"
#include "CTiglLogging.h"
#include "CCPACSConfiguration.h"

#include <string>
#include <cmath>

#include <gp_Ax2.hxx>
#include <BRepPrimAPI_MakeSphere.hxx>
#include <BRepPrimAPI_MakeBox.hxx>
#include <TopExp_Explorer.hxx>

#ifdef TIGL_USE_XCAF
#include <XCAFDoc_ShapeTool.hxx>
#include <XCAFApp_Application.hxx>
#include <XCAFDoc_DocumentTool.hxx>
#include <TDataStd_Name.hxx>
#include <TDataXtd_Shape.hxx>
#endif

namespace tigl
{

CCPACSFarField::CCPACSFarField()
{
    init();
}

CCPACSFarField::~CCPACSFarField() {}

void CCPACSFarField::init()
{
    fieldType = NONE;
    fieldSize = 0.;
    loft.Nullify();
    SetUID("FarField");
}

TiglFarFieldType CCPACSFarField::GetFieldType()
{
    return fieldType;
}

void CCPACSFarField::ReadCPACS(TixiDocumentHandle tixiHandle)
{
    init();

    std::string prefix = "/cpacs/toolspecific/cFD/farField";
    if (tixiCheckElement(tixiHandle, prefix.c_str()) != SUCCESS) {
        LOG(INFO) << "No far-field defined.";
        fieldType = NONE;
        return;
    }

    // get field type
    std::string typePath = prefix + "/type";
    char * tmpstr = NULL;
    if (tixiGetTextElement(tixiHandle, typePath.c_str(), &tmpstr) != SUCCESS) {
        fieldType = NONE;
        return;
    }
    else {
        if (strcmp(tmpstr, "halfSphere") == 0){
            fieldType = HALF_SPHERE;
        }
        else if (strcmp(tmpstr, "fullSphere") == 0){
            fieldType = FULL_SPHERE;
        }
        else if (strcmp(tmpstr, "halfCube") == 0){
            fieldType = HALF_CUBE;
        }
        else if (strcmp(tmpstr, "fullCube") == 0){
            fieldType = FULL_CUBE;
        }
        else {
            fieldType = NONE;
            return;
        }
    }

    // get reference length
    std::string refLenPath = prefix + "/referenceLength";
    if (tixiGetDoubleElement(tixiHandle, refLenPath.c_str(), &fieldSize) != SUCCESS) {
        fieldSize = 0.;
        throw tigl::CTiglError("No reference length defined for far-field!");
    }

    // get multiplier
    std::string multiplierPath = prefix + "/multiplier";
    double multiplier = 1.;
    if (tixiGetDoubleElement(tixiHandle, multiplierPath.c_str(), &multiplier) != SUCCESS) {
        fieldSize = 0.;
        throw tigl::CTiglError("No multiplier defined for far-field!");
    }
    else {
        fieldSize *= multiplier;
    }
}

TopoDS_Shape CCPACSFarField::BuildLoft(void)
{
    TopoDS_Shape shape;
    shape.Nullify();
    gp_Pnt center(0,0,0);

    switch (fieldType) {
    case NONE:
        return shape;
    case FULL_SPHERE:
        shape = BRepPrimAPI_MakeSphere(center, fieldSize).Shape();
        break;
    case FULL_CUBE:
        shape = BRepPrimAPI_MakeBox(gp_Pnt(center.X()-fieldSize, center.Y()-fieldSize, center.Z()-fieldSize),
                                    fieldSize*2., fieldSize*2., fieldSize*2.).Shape();
        break;
    case HALF_CUBE:
        shape = BRepPrimAPI_MakeBox(gp_Pnt(center.X()-fieldSize, center.Y(), center.Z()-fieldSize),
                                    fieldSize*2., fieldSize, fieldSize*2.).Shape();
        break;
    case HALF_SPHERE:
        shape = BRepPrimAPI_MakeSphere(gp_Ax2(center, gp_Dir(0,1,0)), fieldSize, 0., M_PI_2).Shape();
        break;
    default:
        shape.Nullify();
    }

    return shape;
}

TiglGeometricComponentType CCPACSFarField::GetComponentType(void)
{
    return TIGL_COMPONENT_LOGICAL;
}

#ifdef TIGL_USE_XCAF
// builds data structure for a TDocStd_Application
// mostly used for export
TDF_Label CCPACSFarField::ExportDataStructure(CCPACSConfiguration&, Handle_XCAFDoc_ShapeTool &myAssembly, TDF_Label& label)
{
    // add faces of current shape
    TopExp_Explorer faceExplorer;
    int iface = 1;
    for (faceExplorer.Init(GetLoft(), TopAbs_FACE); faceExplorer.More(); faceExplorer.Next()) {
        const TopoDS_Face& currentFace = TopoDS::Face(faceExplorer.Current());

        TDF_Label aLabel = myAssembly->AddShape(currentFace, false);
        std::stringstream stream;
        stream << GetUID() << "_face" << iface++;
        TDataStd_Name::Set (aLabel, stream.str().c_str());

    }

    return label;
}
#endif

} // namespace tigl

<|endoftext|>


<commit_before>#include "BoundingBox.hpp"

namespace fast {

void BoundingBox::createCorners(Float3 pos, Float3 size) {
    // Create corners
    float corners[8][3] = {
        {pos.x(),pos.y(),pos.z()},
        {pos.x()+size.x(),pos.y(),pos.z()},
        {pos.x()+size.x(),pos.y()+size.y(),pos.z()},
        {pos.x()+size.x(),pos.y()+size.y(),pos.z()+size.z()},
        {pos.x(),pos.y()+size.y(),pos.z()+size.z()},
        {pos.x(),pos.y(),pos.z()+size.z()},
        {pos.x()+size.x(),pos.y(),pos.z()+size.z()},
        {pos.x(),pos.y()+size.y(),pos.z()}
    };

    for(int c = 0; c < 8; c++) {
        for(int i = 0; i < 3; i++) {
            mCorners[c][i] = corners[c][i];
        }
    }
}

BoundingBox::BoundingBox(Float3 pos, Float3 size) {
    mIsInitialized = true;
    createCorners(pos, size);
}

BoundingBox::BoundingBox(Float3 size) {
    mIsInitialized = true;
    Float3 pos;
    pos[0] = 0;
    pos[1] = 0;
    pos[2] = 0;
    createCorners(pos, size);
}

BoundingBox::BoundingBox(Vector<Float3, 8> corners) {
    mIsInitialized = true;
    mCorners = corners; // copy
}

BoundingBox::BoundingBox() {
    mIsInitialized = false;
}

Vector<Float3, 8> BoundingBox::getCorners() {
    if(!mIsInitialized)
        throw Exception("Cannot getCorners because bounding box was not initialized.");
    return mCorners;
}

BoundingBox::BoundingBox(std::vector<Float3> coordinates) {
    // Find min and max of all the coordinates
    Float3 minimum(coordinates[0].x(), coordinates[0].y(), coordinates[0].z());
    Float3 maximum(coordinates[0].x(), coordinates[0].y(), coordinates[0].z());
    for(uint i = 1; i < coordinates.size(); i++) {
        Float3 coordinate = coordinates[0];
        for(uint j = 0; j < 4; j++) {
            if(coordinate[j] < minimum[j]) {
                minimum[j] = coordinate[j];
            }
            if(coordinate[j] > maximum[j]) {
                maximum[j] = coordinate[j];
            }
        }
    }

    // Make new bounding box
    Float3 size(maximum.x()-minimum.x(), maximum.y()-minimum.y(), maximum.z()-minimum.z());
    BoundingBox(minimum, size);
}

BoundingBox BoundingBox::getTransformedBoundingBox(
        LinearTransformation transform) {
    if(!mIsInitialized)
        throw Exception("Cannot getTransformedBoundingBox because bounding box was not initialized.");
    Vector<Float3, 8> newCorners;
    for(uint i = 0; i < 8; i++) {
        Float3 vertex = mCorners[i];
        Float3 transformedVertex = transform*vertex;
        newCorners[i] = transformedVertex;
    }
    return BoundingBox(newCorners);
}

std::ostream &operator<<(std::ostream &os, BoundingBox &object) {
    os << std::endl << "Bounding box" << std::endl;

    Vector<Float3, 8> corners = object.getCorners();

    for(uint i = 0; i < 8; i++) {
        os << "Corner " << i << ": " << corners[i][0] << ", " << corners[i][1] << ", " << corners[i][2] << std::endl;
    }

    return os;

}

} // end namespace fast

<commit_msg>fixed some bugs in the BoundingBox implementation<commit_after>#include "BoundingBox.hpp"

namespace fast {

void BoundingBox::createCorners(Float3 pos, Float3 size) {
    // Create corners
    float corners[8][3] = {
        {pos.x(),pos.y(),pos.z()},
        {pos.x()+size.x(),pos.y(),pos.z()},
        {pos.x()+size.x(),pos.y()+size.y(),pos.z()},
        {pos.x()+size.x(),pos.y()+size.y(),pos.z()+size.z()},
        {pos.x(),pos.y()+size.y(),pos.z()+size.z()},
        {pos.x(),pos.y(),pos.z()+size.z()},
        {pos.x()+size.x(),pos.y(),pos.z()+size.z()},
        {pos.x(),pos.y()+size.y(),pos.z()}
    };

    for(int c = 0; c < 8; c++) {
        for(int i = 0; i < 3; i++) {
            mCorners[c][i] = corners[c][i];
        }
    }
}

BoundingBox::BoundingBox(Float3 pos, Float3 size) {
    mIsInitialized = true;
    createCorners(pos, size);
}

BoundingBox::BoundingBox(Float3 size) {
    mIsInitialized = true;
    Float3 pos;
    pos[0] = 0;
    pos[1] = 0;
    pos[2] = 0;
    createCorners(pos, size);
}

BoundingBox::BoundingBox(Vector<Float3, 8> corners) {
    mIsInitialized = true;
    mCorners = corners; // copy
}

BoundingBox::BoundingBox() {
    mIsInitialized = false;
}

Vector<Float3, 8> BoundingBox::getCorners() {
    if(!mIsInitialized)
        throw Exception("Cannot getCorners because bounding box was not initialized.");
    return mCorners;
}

BoundingBox::BoundingBox(std::vector<Float3> coordinates) {
    // Find min and max of all the coordinates
    Float3 minimum(coordinates[0].x(), coordinates[0].y(), coordinates[0].z());
    Float3 maximum(coordinates[0].x(), coordinates[0].y(), coordinates[0].z());
    for(uint i = 1; i < coordinates.size(); i++) {
        Float3 coordinate = coordinates[i];
        for(uint j = 0; j < 4; j++) {
            if(coordinate[j] < minimum[j]) {
                minimum[j] = coordinate[j];
            }
            if(coordinate[j] > maximum[j]) {
                maximum[j] = coordinate[j];
            }
        }
    }

    // Make new bounding box
    Float3 size(maximum.x()-minimum.x(), maximum.y()-minimum.y(), maximum.z()-minimum.z());
    mIsInitialized = true;
    std::cout << minimum[0] << " " << minimum[1] << std::endl;
    std::cout << maximum[0] << " " << maximum[1] << std::endl;
    std::cout << size[0] << " " << size[1] << std::endl;
    createCorners(minimum, size);
}

BoundingBox BoundingBox::getTransformedBoundingBox(
        LinearTransformation transform) {
    if(!mIsInitialized)
        throw Exception("Cannot getTransformedBoundingBox because bounding box was not initialized.");
    Vector<Float3, 8> newCorners;
    for(uint i = 0; i < 8; i++) {
        Float3 vertex = mCorners[i];
        Float3 transformedVertex = transform*vertex;
        newCorners[i] = transformedVertex;
    }
    return BoundingBox(newCorners);
}

std::ostream &operator<<(std::ostream &os, BoundingBox &object) {
    os << std::endl << "Bounding box" << std::endl;

    Vector<Float3, 8> corners = object.getCorners();

    for(uint i = 0; i < 8; i++) {
        os << "Corner " << i << ": " << corners[i][0] << ", " << corners[i][1] << ", " << corners[i][2] << std::endl;
    }

    return os;

}

} // end namespace fast

<|endoftext|>


<commit_before>// RUN: %clang -target x86_64-unknown-nacl -ccc-echo %s -emit-llvm-only -c -o %t.o 2>&1 | FileCheck %s -check-prefix=ECHO
// RUN: %clang -target x86_64-unknown-nacl %s -emit-llvm -S -c -o - | FileCheck %s
// RUN: %clang -target x86_64-unknown-nacl %s -emit-llvm -S -c -pthread -o - | FileCheck %s -check-prefix=THREADS

// ECHO: {{.*}} -cc1 {{.*}}x86_64-nacl-defines.c

// Check platform defines

// CHECK: __LITTLE_ENDIAN__defined
#ifdef __LITTLE_ENDIAN__
void __LITTLE_ENDIAN__defined() {}
#endif

// CHECK: __native_client__defined
#ifdef __native_client__
void __native_client__defined() {}
#endif

// CHECK: __x86_64__defined
#ifdef __x86_64__
void __x86_64__defined() {}
#endif

// CHECK: unixdefined
#ifdef unix
void unixdefined() {}
#endif

// CHECK: __ELF__defined
#ifdef __ELF__
void __ELF__defined() {}
#endif

// CHECK: _GNU_SOURCEdefined
#ifdef _GNU_SOURCE
void _GNU_SOURCEdefined() {}
#endif

// THREADS: _REENTRANTdefined
// CHECK: _REENTRANTundefined
#ifdef _REENTRANT
void _REENTRANTdefined() {}
#else
void _REENTRANTundefined() {}
#endif
<commit_msg>Use -### instead of -ccc-echo.<commit_after>// RUN: %clang -target x86_64-unknown-nacl -### %s -emit-llvm-only -c -o %t.o 2>&1 | FileCheck %s -check-prefix=ECHO
// RUN: %clang -target x86_64-unknown-nacl %s -emit-llvm -S -c -o - | FileCheck %s
// RUN: %clang -target x86_64-unknown-nacl %s -emit-llvm -S -c -pthread -o - | FileCheck %s -check-prefix=THREADS

// ECHO: {{.*}} -cc1 {{.*}}x86_64-nacl-defines.c

// Check platform defines

// CHECK: __LITTLE_ENDIAN__defined
#ifdef __LITTLE_ENDIAN__
void __LITTLE_ENDIAN__defined() {}
#endif

// CHECK: __native_client__defined
#ifdef __native_client__
void __native_client__defined() {}
#endif

// CHECK: __x86_64__defined
#ifdef __x86_64__
void __x86_64__defined() {}
#endif

// CHECK: unixdefined
#ifdef unix
void unixdefined() {}
#endif

// CHECK: __ELF__defined
#ifdef __ELF__
void __ELF__defined() {}
#endif

// CHECK: _GNU_SOURCEdefined
#ifdef _GNU_SOURCE
void _GNU_SOURCEdefined() {}
#endif

// THREADS: _REENTRANTdefined
// CHECK: _REENTRANTundefined
#ifdef _REENTRANT
void _REENTRANTdefined() {}
#else
void _REENTRANTundefined() {}
#endif
<|endoftext|>


<commit_before>// ========================================================================== //
// This file is part of DO++, a basic set of libraries in C++ for computer
// vision.
//
// Copyright (C) 2013 David Ok <david.ok8@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at http://mozilla.org/MPL/2.0/.
// ========================================================================== //

#include <DO/Graphics.hpp>

using namespace DO;

struct Bresenham
{
  template <typename Color>
  static inline void putColor(Image<Color>& image, int x, int y,
                              const Color& color)
  {
    if (x < 0 || x >= image.width() || y < 0 || y >= image.height())
      return;
    image(x,y) = color;
  }

  template <typename Color>
  static void drawLine(Image<Color>& image, int x0, int y0, int x1, int y1,
                       const Color& color)
  {
    const int dx = abs(x1-x0);
    const int dy = abs(y1-y0);
    const int sx = x0 < x1 ? 1 : -1;
    const int sy = y0 < y1 ? 1 : -1;
    int err = dx-dy;

    while (true)
    {
      // Put color to image at current point $(x_0, y_0)$
      putColor(image, x0, y0, color);

      // Stop drawing when we reach the end point $(x_1, y_1)$
      if (x0 == x1 && y0 == y1)
        return;
      const int e2 = 2*err;
      if (e2 > -dy)
      {
        err -= dy;
        x0 += sx;
      }

      // Stop drawing when we reach the end point $(x_1, y_1)$
      if (x0 == x1 && y0 == y1)
      {
        putColor(image, x0, y0, color);
        return;
      }
      if (e2 < dx)
      {
        err += dx;
        y0 += sy;
      }
    }
  }

  template <typename Color>
  static void drawCircle(Image<Color>& image, int x1, int y1, int r,
                         const Color& color)
  {

  }

  template <typename Color>
  static void drawEllipse(Image<Color>& image, int x1, int y1, int r1, int r2,
                          const Color& color)
  {

  }
};

int main()
{
  Image<Rgb8> img(300, 300);
  img.array().fill(White8);

  const float max_slope_value = 50.f;
  // Check line drawing when "start point < end point"
  for (float i = 0; i < max_slope_value; i += 0.2f)
    Bresenham::drawLine(img, 10, 10, 290, 290*i+10, Black8);

  // Check line drawing when "start point > end point"
  for (float i = 0.1f; i < max_slope_value; i += 0.2f)
    Bresenham::drawLine(img, 290, 290*i+10, 10, 10, Red8);

  viewImage(img);

  return 0;
}

struct Wu
{
  template <typename T>
  void drawLine(Image<T>& image, int x1, int y1, int x2, int y2, const T& Color)
  {

  }

  template <typename T>
  void drawCircle(Image<T>& image, int x1, int y1, int r, const T& Color)
  {

  }

  template <typename T>
  void drawEllipse(Image<T>& image, int x1, int y1, int r1, int r2, const T& Color)
  {

  }
};
<commit_msg>Development of image drawing in progress<commit_after>// ========================================================================== //
// This file is part of DO++, a basic set of libraries in C++ for computer
// vision.
//
// Copyright (C) 2013 David Ok <david.ok8@gmail.com>
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License v. 2.0. If a copy of the MPL was not distributed with this file,
// you can obtain one at http://mozilla.org/MPL/2.0/.
// ========================================================================== //

#include <DO/Graphics.hpp>
#include "ImageDrawing.hpp"

using namespace DO;

int main()
{
  Image<Rgb8> img(300, 300);
  img.array().fill(White8);

  const float max_slope_value = 50.f;
  // Check line drawing when "start point < end point"
  for (float i = 0; i < max_slope_value; i += 0.2f)
    Bresenham::drawLine(img, 10, 10, 290, 290*i+10, Black8);
  // Check line drawing when "start point > end point"
  for (float i = 0.1f; i < max_slope_value; i += 0.2f)
    Bresenham::drawLine(img, 290, 290*i+10, 10, 10, Red8);

  viewImage(img);

  return 0;
}<|endoftext|>


<commit_before>//
// Copyright (c) 2008-2016 the Urho3D project.
//
// 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.
//

#ifdef URHO3D_ANGELSCRIPT
#include <Urho3D/AngelScript/ScriptFile.h>
#include <Urho3D/AngelScript/Script.h>
#endif
#include <Urho3D/Core/Main.h>
#include <Urho3D/Engine/Engine.h>
#include <Urho3D/IO/FileSystem.h>
#include <Urho3D/IO/Log.h>
#ifdef URHO3D_LUA
#include <Urho3D/LuaScript/LuaScript.h>
#endif
#include <Urho3D/Resource/ResourceCache.h>
#include <Urho3D/Resource/ResourceEvents.h>

#include "Urho3DPlayer.h"

#include <Urho3D/DebugNew.h>

URHO3D_DEFINE_APPLICATION_MAIN(Urho3DPlayer);

Urho3DPlayer::Urho3DPlayer(Context* context) :
    Application(context)
{
}

void Urho3DPlayer::Setup()
{
    FileSystem* filesystem = GetSubsystem<FileSystem>();

    // Web platform depends on the resource system to read any data files. Skip parsing the command line now
    // and try later when the resource system is live
#ifndef EMSCRIPTEN
    // Read command line from a file if no arguments given. This is primarily intended for mobile platforms.
    // Note that the command file name uses a hardcoded path that does not utilize the resource system
    // properly (including resource path prefix), as the resource system is not yet initialized at this point
    const String commandFileName = filesystem->GetProgramDir() + "Data/CommandLine.txt";
    if (GetArguments().Empty() && filesystem->FileExists(commandFileName))
    {
        SharedPtr<File> commandFile(new File(context_, commandFileName));
        String commandLine = commandFile->ReadLine();
        commandFile->Close();
        ParseArguments(commandLine, false);
        // Reparse engine startup parameters now
        engineParameters_ = Engine::ParseParameters(GetArguments());
    }

    // Check for script file name from the arguments
    GetScriptFileName();

    // Show usage if not found
    if (scriptFileName_.Empty())
    {
        ErrorExit("Usage: Urho3DPlayer <scriptfile> [options]\n\n"
            "The script file should implement the function void Start() for initializing the "
            "application and subscribing to all necessary events, such as the frame update.\n"
            #ifndef WIN32
            "\nCommand line options:\n"
            "-x <res>     Horizontal resolution\n"
            "-y <res>     Vertical resolution\n"
            "-m <level>   Enable hardware multisampling\n"
            "-v           Enable vertical sync\n"
            "-t           Enable triple buffering\n"
            "-w           Start in windowed mode\n"
            "-s           Enable resizing when in windowed mode\n"
            "-hd          Enable high DPI, only supported by Apple platforms (OSX, iOS, and tvOS)\n"
            "-q           Enable quiet mode which does not log to standard output stream\n"
            "-b <length>  Sound buffer length in milliseconds\n"
            "-r <freq>    Sound mixing frequency in Hz\n"
            "-p <paths>   Resource path(s) to use, separated by semicolons\n"
            "-ap <paths>  Autoload resource path(s) to use, seperated by semicolons\n"
            "-log <level> Change the log level, valid 'level' values are 'debug', 'info', 'warning', 'error'\n"
            "-ds <file>   Dump used shader variations to a file for precaching\n"
            "-mq <level>  Material quality level, default 2 (high)\n"
            "-tq <level>  Texture quality level, default 2 (high)\n"
            "-tf <level>  Texture filter mode, default 2 (trilinear)\n"
            "-af <level>  Texture anisotropy level, default 4. Also sets anisotropic filter mode\n"
            "-gl2         Force OpenGL 2 use even if OpenGL 3 is available\n"
            "-flushgpu    Flush GPU command queue each frame. Effective only on Direct3D\n"
            "-borderless  Borderless window mode\n"
            "-headless    Headless mode. No application window will be created\n"
            "-landscape   Use landscape orientations (iOS only, default)\n"
            "-portrait    Use portrait orientations (iOS only)\n"
            "-prepass     Use light pre-pass rendering\n"
            "-deferred    Use deferred rendering\n"
            "-renderpath <name> Use the named renderpath (must enter full resource name)\n"
            "-lqshadows   Use low-quality (1-sample) shadow filtering\n"
            "-noshadows   Disable shadow rendering\n"
            "-nolimit     Disable frame limiter\n"
            "-nothreads   Disable worker threads\n"
            "-nosound     Disable sound output\n"
            "-noip        Disable sound mixing interpolation\n"
            "-touch       Touch emulation on desktop platform\n"
            #endif
        );
    }
    else
    {
        // Use the script file name as the base name for the log file
        engineParameters_["LogName"] = filesystem->GetAppPreferencesDir("urho3d", "logs") + GetFileNameAndExtension(scriptFileName_) + ".log";
    }
#else
    // On Web platform setup a default windowed resolution similar to the executable samples
    engineParameters_["FullScreen"]  = false;
#endif

    // Construct a search path to find the resource prefix with two entries:
    // The first entry is an empty path which will be substituted with program/bin directory -- this entry is for binary when it is still in build tree
    // The second and third entries are possible relative paths from the installed program/bin directory to the asset directory -- these entries are for binary when it is in the Urho3D SDK installation location
    if (!engineParameters_.Contains("ResourcePrefixPaths"))
        engineParameters_["ResourcePrefixPaths"] = ";../share/Resources;../share/Urho3D/Resources";
}

void Urho3DPlayer::Start()
{
    // Reattempt reading the command line now on Web platform
#ifdef EMSCRIPTEN
    if (GetArguments().Empty())
    {
        SharedPtr<File> commandFile = GetSubsystem<ResourceCache>()->GetFile("CommandLine.txt", false);
        if (commandFile)
        {
            String commandLine = commandFile->ReadLine();
            commandFile->Close();
            ParseArguments(commandLine, false);
            GetScriptFileName();
        }
    }

    if (scriptFileName_.Empty())
    {
        ErrorExit("Script file name not specified; cannot proceed");
        return;
    }
#endif

    String extension = GetExtension(scriptFileName_);
    if (extension != ".lua" && extension != ".luc")
    {
#ifdef URHO3D_ANGELSCRIPT
        // Instantiate and register the AngelScript subsystem
        context_->RegisterSubsystem(new Script(context_));

        // Hold a shared pointer to the script file to make sure it is not unloaded during runtime
        scriptFile_ = GetSubsystem<ResourceCache>()->GetResource<ScriptFile>(scriptFileName_);

        /// \hack If we are running the editor, also instantiate Lua subsystem to enable editing Lua ScriptInstances
#ifdef URHO3D_LUA
        if (scriptFileName_.Contains("Editor.as", false))
            context_->RegisterSubsystem(new LuaScript(context_));
#endif
        // If script loading is successful, proceed to main loop
        if (scriptFile_ && scriptFile_->Execute("void Start()"))
        {
            // Subscribe to script's reload event to allow live-reload of the application
            SubscribeToEvent(scriptFile_, E_RELOADSTARTED, URHO3D_HANDLER(Urho3DPlayer, HandleScriptReloadStarted));
            SubscribeToEvent(scriptFile_, E_RELOADFINISHED, URHO3D_HANDLER(Urho3DPlayer, HandleScriptReloadFinished));
            SubscribeToEvent(scriptFile_, E_RELOADFAILED, URHO3D_HANDLER(Urho3DPlayer, HandleScriptReloadFailed));
            return;
        }
#else
        ErrorExit("AngelScript is not enabled!");
        return;
#endif
    }
    else
    {
#ifdef URHO3D_LUA
        // Instantiate and register the Lua script subsystem
        LuaScript* luaScript = new LuaScript(context_);
        context_->RegisterSubsystem(luaScript);

        // If script loading is successful, proceed to main loop
        if (luaScript->ExecuteFile(scriptFileName_))
        {
            luaScript->ExecuteFunction("Start");
            return;
        }
#else
        ErrorExit("Lua is not enabled!");
        return;
#endif
    }

    // The script was not successfully loaded. Show the last error message and do not run the main loop
    ErrorExit();
}

void Urho3DPlayer::Stop()
{
#ifdef URHO3D_ANGELSCRIPT
    if (scriptFile_)
    {
        // Execute the optional stop function
        if (scriptFile_->GetFunction("void Stop()"))
            scriptFile_->Execute("void Stop()");
    }
#else
    if (false)
    {
    }
#endif

#ifdef URHO3D_LUA
    else
    {
        LuaScript* luaScript = GetSubsystem<LuaScript>();
        if (luaScript && luaScript->GetFunction("Stop", true))
            luaScript->ExecuteFunction("Stop");
    }
#endif
}

void Urho3DPlayer::HandleScriptReloadStarted(StringHash eventType, VariantMap& eventData)
{
#ifdef URHO3D_ANGELSCRIPT
    if (scriptFile_->GetFunction("void Stop()"))
        scriptFile_->Execute("void Stop()");
#endif
}

void Urho3DPlayer::HandleScriptReloadFinished(StringHash eventType, VariantMap& eventData)
{
#ifdef URHO3D_ANGELSCRIPT
    // Restart the script application after reload
    if (!scriptFile_->Execute("void Start()"))
    {
        scriptFile_.Reset();
        ErrorExit();
    }
#endif
}

void Urho3DPlayer::HandleScriptReloadFailed(StringHash eventType, VariantMap& eventData)
{
#ifdef URHO3D_ANGELSCRIPT
    scriptFile_.Reset();
    ErrorExit();
#endif
}

void Urho3DPlayer::GetScriptFileName()
{
    const Vector<String>& arguments = GetArguments();
    if (arguments.Size() && arguments[0][0] != '-')
        scriptFileName_ = GetInternalPath(arguments[0]);
}<commit_msg>Fix logic for getting the script file name in web Urho3DPlayer in case arguments were already specified and the command line file is not used.<commit_after>//
// Copyright (c) 2008-2016 the Urho3D project.
//
// 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.
//

#ifdef URHO3D_ANGELSCRIPT
#include <Urho3D/AngelScript/ScriptFile.h>
#include <Urho3D/AngelScript/Script.h>
#endif
#include <Urho3D/Core/Main.h>
#include <Urho3D/Engine/Engine.h>
#include <Urho3D/IO/FileSystem.h>
#include <Urho3D/IO/Log.h>
#ifdef URHO3D_LUA
#include <Urho3D/LuaScript/LuaScript.h>
#endif
#include <Urho3D/Resource/ResourceCache.h>
#include <Urho3D/Resource/ResourceEvents.h>

#include "Urho3DPlayer.h"

#include <Urho3D/DebugNew.h>

URHO3D_DEFINE_APPLICATION_MAIN(Urho3DPlayer);

Urho3DPlayer::Urho3DPlayer(Context* context) :
    Application(context)
{
}

void Urho3DPlayer::Setup()
{
    // Web platform depends on the resource system to read any data files. Skip parsing the command line file now
    // and try later when the resource system is live
#ifndef EMSCRIPTEN
    // Read command line from a file if no arguments given. This is primarily intended for mobile platforms.
    // Note that the command file name uses a hardcoded path that does not utilize the resource system
    // properly (including resource path prefix), as the resource system is not yet initialized at this point
    FileSystem* filesystem = GetSubsystem<FileSystem>();
    const String commandFileName = filesystem->GetProgramDir() + "Data/CommandLine.txt";
    if (GetArguments().Empty() && filesystem->FileExists(commandFileName))
    {
        SharedPtr<File> commandFile(new File(context_, commandFileName));
        String commandLine = commandFile->ReadLine();
        commandFile->Close();
        ParseArguments(commandLine, false);
        // Reparse engine startup parameters now
        engineParameters_ = Engine::ParseParameters(GetArguments());
    }

    // Check for script file name from the arguments
    GetScriptFileName();

    // Show usage if not found
    if (scriptFileName_.Empty())
    {
        ErrorExit("Usage: Urho3DPlayer <scriptfile> [options]\n\n"
            "The script file should implement the function void Start() for initializing the "
            "application and subscribing to all necessary events, such as the frame update.\n"
            #ifndef WIN32
            "\nCommand line options:\n"
            "-x <res>     Horizontal resolution\n"
            "-y <res>     Vertical resolution\n"
            "-m <level>   Enable hardware multisampling\n"
            "-v           Enable vertical sync\n"
            "-t           Enable triple buffering\n"
            "-w           Start in windowed mode\n"
            "-s           Enable resizing when in windowed mode\n"
            "-hd          Enable high DPI, only supported by Apple platforms (OSX, iOS, and tvOS)\n"
            "-q           Enable quiet mode which does not log to standard output stream\n"
            "-b <length>  Sound buffer length in milliseconds\n"
            "-r <freq>    Sound mixing frequency in Hz\n"
            "-p <paths>   Resource path(s) to use, separated by semicolons\n"
            "-ap <paths>  Autoload resource path(s) to use, seperated by semicolons\n"
            "-log <level> Change the log level, valid 'level' values are 'debug', 'info', 'warning', 'error'\n"
            "-ds <file>   Dump used shader variations to a file for precaching\n"
            "-mq <level>  Material quality level, default 2 (high)\n"
            "-tq <level>  Texture quality level, default 2 (high)\n"
            "-tf <level>  Texture filter mode, default 2 (trilinear)\n"
            "-af <level>  Texture anisotropy level, default 4. Also sets anisotropic filter mode\n"
            "-gl2         Force OpenGL 2 use even if OpenGL 3 is available\n"
            "-flushgpu    Flush GPU command queue each frame. Effective only on Direct3D\n"
            "-borderless  Borderless window mode\n"
            "-headless    Headless mode. No application window will be created\n"
            "-landscape   Use landscape orientations (iOS only, default)\n"
            "-portrait    Use portrait orientations (iOS only)\n"
            "-prepass     Use light pre-pass rendering\n"
            "-deferred    Use deferred rendering\n"
            "-renderpath <name> Use the named renderpath (must enter full resource name)\n"
            "-lqshadows   Use low-quality (1-sample) shadow filtering\n"
            "-noshadows   Disable shadow rendering\n"
            "-nolimit     Disable frame limiter\n"
            "-nothreads   Disable worker threads\n"
            "-nosound     Disable sound output\n"
            "-noip        Disable sound mixing interpolation\n"
            "-touch       Touch emulation on desktop platform\n"
            #endif
        );
    }
    else
    {
        // Use the script file name as the base name for the log file
        engineParameters_["LogName"] = filesystem->GetAppPreferencesDir("urho3d", "logs") + GetFileNameAndExtension(scriptFileName_) + ".log";
    }
#else
    // On Web platform setup a default windowed resolution similar to the executable samples
    engineParameters_["FullScreen"]  = false;
#endif

    // Construct a search path to find the resource prefix with two entries:
    // The first entry is an empty path which will be substituted with program/bin directory -- this entry is for binary when it is still in build tree
    // The second and third entries are possible relative paths from the installed program/bin directory to the asset directory -- these entries are for binary when it is in the Urho3D SDK installation location
    if (!engineParameters_.Contains("ResourcePrefixPaths"))
        engineParameters_["ResourcePrefixPaths"] = ";../share/Resources;../share/Urho3D/Resources";
}

void Urho3DPlayer::Start()
{
    // Reattempt reading the command line now on Web platform
#ifdef EMSCRIPTEN
    if (GetArguments().Empty())
    {
        SharedPtr<File> commandFile = GetSubsystem<ResourceCache>()->GetFile("CommandLine.txt", false);
        if (commandFile)
        {
            String commandLine = commandFile->ReadLine();
            commandFile->Close();
            ParseArguments(commandLine, false);
        }
    }

    GetScriptFileName();

    if (scriptFileName_.Empty())
    {
        ErrorExit("Script file name not specified; cannot proceed");
        return;
    }
#endif

    String extension = GetExtension(scriptFileName_);
    if (extension != ".lua" && extension != ".luc")
    {
#ifdef URHO3D_ANGELSCRIPT
        // Instantiate and register the AngelScript subsystem
        context_->RegisterSubsystem(new Script(context_));

        // Hold a shared pointer to the script file to make sure it is not unloaded during runtime
        scriptFile_ = GetSubsystem<ResourceCache>()->GetResource<ScriptFile>(scriptFileName_);

        /// \hack If we are running the editor, also instantiate Lua subsystem to enable editing Lua ScriptInstances
#ifdef URHO3D_LUA
        if (scriptFileName_.Contains("Editor.as", false))
            context_->RegisterSubsystem(new LuaScript(context_));
#endif
        // If script loading is successful, proceed to main loop
        if (scriptFile_ && scriptFile_->Execute("void Start()"))
        {
            // Subscribe to script's reload event to allow live-reload of the application
            SubscribeToEvent(scriptFile_, E_RELOADSTARTED, URHO3D_HANDLER(Urho3DPlayer, HandleScriptReloadStarted));
            SubscribeToEvent(scriptFile_, E_RELOADFINISHED, URHO3D_HANDLER(Urho3DPlayer, HandleScriptReloadFinished));
            SubscribeToEvent(scriptFile_, E_RELOADFAILED, URHO3D_HANDLER(Urho3DPlayer, HandleScriptReloadFailed));
            return;
        }
#else
        ErrorExit("AngelScript is not enabled!");
        return;
#endif
    }
    else
    {
#ifdef URHO3D_LUA
        // Instantiate and register the Lua script subsystem
        LuaScript* luaScript = new LuaScript(context_);
        context_->RegisterSubsystem(luaScript);

        // If script loading is successful, proceed to main loop
        if (luaScript->ExecuteFile(scriptFileName_))
        {
            luaScript->ExecuteFunction("Start");
            return;
        }
#else
        ErrorExit("Lua is not enabled!");
        return;
#endif
    }

    // The script was not successfully loaded. Show the last error message and do not run the main loop
    ErrorExit();
}

void Urho3DPlayer::Stop()
{
#ifdef URHO3D_ANGELSCRIPT
    if (scriptFile_)
    {
        // Execute the optional stop function
        if (scriptFile_->GetFunction("void Stop()"))
            scriptFile_->Execute("void Stop()");
    }
#else
    if (false)
    {
    }
#endif

#ifdef URHO3D_LUA
    else
    {
        LuaScript* luaScript = GetSubsystem<LuaScript>();
        if (luaScript && luaScript->GetFunction("Stop", true))
            luaScript->ExecuteFunction("Stop");
    }
#endif
}

void Urho3DPlayer::HandleScriptReloadStarted(StringHash eventType, VariantMap& eventData)
{
#ifdef URHO3D_ANGELSCRIPT
    if (scriptFile_->GetFunction("void Stop()"))
        scriptFile_->Execute("void Stop()");
#endif
}

void Urho3DPlayer::HandleScriptReloadFinished(StringHash eventType, VariantMap& eventData)
{
#ifdef URHO3D_ANGELSCRIPT
    // Restart the script application after reload
    if (!scriptFile_->Execute("void Start()"))
    {
        scriptFile_.Reset();
        ErrorExit();
    }
#endif
}

void Urho3DPlayer::HandleScriptReloadFailed(StringHash eventType, VariantMap& eventData)
{
#ifdef URHO3D_ANGELSCRIPT
    scriptFile_.Reset();
    ErrorExit();
#endif
}

void Urho3DPlayer::GetScriptFileName()
{
    const Vector<String>& arguments = GetArguments();
    if (arguments.Size() && arguments[0][0] != '-')
        scriptFileName_ = GetInternalPath(arguments[0]);
}<|endoftext|>


<commit_before>#include <QTimer>
#include <QsLog.h>
#include "inverter_gateway.h"
#include "abstract_detector.h"
#include "settings.h"
#include "fronius_udp_detector.h"

static const int MaxSimultaneousRequests = 32;

InverterGateway::InverterGateway(Settings *settings, QObject *parent) :
	QObject(parent),
	mSettings(settings),
	mTimer(new QTimer(this)),
	mUdpDetector(new FroniusUdpDetector(this)),
	mAutoDetect(false),
	mScanType(None)
{
	Q_ASSERT(settings != 0);
	mAddressGenerator.setNetMaskLimit(QHostAddress(0xFFFFF000));
	mTimer->setInterval(60000);
	connect(mTimer, SIGNAL(timeout()), this, SLOT(onTimer()));
	connect(mUdpDetector, SIGNAL(finished()), this, SLOT(continueScan()));
}

void InverterGateway::addDetector(AbstractDetector *detector) {
	mDetectors.append(detector);
}

bool InverterGateway::autoDetect() const
{
	return mAutoDetect;
}

void InverterGateway::setAutoDetect(bool b)
{
	if (mAutoDetect == b)
		return;
	mAutoDetect = b;
	emit autoDetectChanged();
}

int InverterGateway::scanProgress() const
{
	return mAutoDetect ? mAddressGenerator.progress(mActiveHosts.count()) : 100;
}

void InverterGateway::initializeSettings()
{
	connect(mSettings, SIGNAL(portNumberChanged()), this, SLOT(onPortNumberChanged()));
	connect(mSettings, SIGNAL(ipAddressesChanged()), this, SLOT(onIpAddressesChanged()));
}

void InverterGateway::startDetection()
{
	// startDetection is called as soon as localsettings comes up. So this
	// is a good spot to start our period re-scan timer.
	mTimer->start();

	// Do a priorityScan, followed by a fullScan if not all hosts are found
	scan(TryPriority);
}

void InverterGateway::fullScan()
{
	scan(Full);
}

void InverterGateway::scan(enum ScanType scanType)
{
	mScanType = scanType;
	mDevicesFound.clear();
	setAutoDetect(mScanType == Full);

	// Do a UDP scan
	mUdpDetector->start();
}

void InverterGateway::continueScan()
{
	// Start with any addresses found by the fast UDP scan.
	QList<QHostAddress> addresses = mUdpDetector->devicesFound();

	// Initialise address generator with priority addresses
	foreach (QHostAddress a, mSettings->ipAddresses() + mSettings->knownIpAddresses()) {
		if (!addresses.contains(a)) {
			addresses.append(a);
		}
	}

	// If priority scan and no known PV-inverters, then we're done
	if (mScanType == Priority && addresses.isEmpty())
		return;

	QLOG_TRACE() << "Starting IP scan (" << mScanType << ")";
	mAddressGenerator.setPriorityAddresses(addresses);
	mAddressGenerator.setPriorityOnly(mScanType != Full);
	mAddressGenerator.reset();

	while (mActiveHosts.size() < MaxSimultaneousRequests && mAddressGenerator.hasNext()) {
		QString host = mAddressGenerator.next().toString();
		QLOG_TRACE() << "Starting scan for" << host;
		scanHost(host);
	}
}

void InverterGateway::scanHost(QString hostName)
{
	HostScan *host = new HostScan(mDetectors, hostName);
	mActiveHosts.append(host);
	connect(host, SIGNAL(finished()), this, SLOT(onDetectionDone()));
	connect(host, SIGNAL(deviceFound(const DeviceInfo &)),
			this, SLOT(onInverterFound(const DeviceInfo &)));
	host->scan();
}

void InverterGateway::onInverterFound(const DeviceInfo &deviceInfo)
{
	QList<QHostAddress> addresses = mSettings->knownIpAddresses();
	QHostAddress addr(deviceInfo.hostName);
	mDevicesFound.insert(addr);
	if (!addresses.contains(addr)) {
		addresses.append(addr);
		mSettings->setKnownIpAddresses(addresses);
	}
	emit inverterFound(deviceInfo);
}

void InverterGateway::onDetectionDone()
{
	HostScan *host = static_cast<HostScan *>(sender());
	QLOG_TRACE() << "Done scanning" << host->hostName();
	mActiveHosts.removeOne(host);
	host->deleteLater();
	updateScanProgress();

	if (mScanType > None && mAddressGenerator.hasNext()) {
		// Scan the next available host
		scanHost(mAddressGenerator.next().toString());
	} else if(mActiveHosts.size() == 0) {
		// Scan is complete
		enum ScanType scanType = mScanType;
		mScanType = None;

		// Did we get what we came for? For full and priority scans, this is it.
		// For TryPriority scans, we switch to a full scan if we're a few
		// piggies short, and if autoScan is enabled.
		if ((scanType == TryPriority) && mSettings->autoScan()) {
			// FIXME only check that we found all known ones, not all priority
			// ones. Otherwise we do a full scan whenever a manually defined one
			// is missing
			QSet<QHostAddress> addresses = QSet<QHostAddress>::fromList(
					mAddressGenerator.priorityAddresses());

			// Do a full scan if not all devices were found
			if ((addresses - mDevicesFound).size()) {
				QLOG_INFO() << "Not all devices found, starting full IP scan";
				mScanType = Full;
				setAutoDetect(true);
				continueScan();
				return;
			}
		}

		setAutoDetect(false);
		QLOG_INFO() << "Auto IP scan completed. Detection finished";
	}
}

void InverterGateway::onPortNumberChanged()
{
	// If the port was changed, assume that the IP addresses did not, and
	// scan the priority addresses first, then fall back to a full scan.
	scan(TryPriority);
}

void InverterGateway::onIpAddressesChanged()
{
	// If the IP addresses changed, do a priority scan. That will scan
	// the new addresses too, and avoid a full scan.
	scan(Priority);
}

void InverterGateway::onTimer()
{
	// If we are in the middle of a sweep, don't start another one.
	if (mScanType > None)
		return;
	scan(TryPriority);
}

void InverterGateway::updateScanProgress()
{
	emit scanProgressChanged();
}

HostScan::HostScan(QList<AbstractDetector *> detectors, QString hostname, QObject *parent) :
	QObject(parent),
	mDetectors(detectors),
	mHostname(hostname)
{
}

void HostScan::scan()
{
	if (mDetectors.size()) {
		DetectorReply *reply = mDetectors.takeFirst()->start(mHostname);
		connect(reply, SIGNAL(deviceFound(const DeviceInfo &)),
			this, SLOT(onDeviceFound(const DeviceInfo &)));
		connect(reply, SIGNAL(finished()), this, SLOT(continueScan()));
	} else {
		emit finished();
	}
}

void HostScan::continueScan() {
	DetectorReply *reply = static_cast<DetectorReply *>(sender());
	reply->deleteLater();
	scan(); // Try next detector
}

void HostScan::onDeviceFound(const DeviceInfo &deviceInfo)
{
	mDetectors.clear(); // Found an inverter on this host, we're done.
	emit deviceFound(deviceInfo);
}
<commit_msg>Don't mix manually configured and autodetected ips<commit_after>#include <QTimer>
#include <QsLog.h>
#include "inverter_gateway.h"
#include "abstract_detector.h"
#include "settings.h"
#include "fronius_udp_detector.h"

static const int MaxSimultaneousRequests = 32;

InverterGateway::InverterGateway(Settings *settings, QObject *parent) :
	QObject(parent),
	mSettings(settings),
	mTimer(new QTimer(this)),
	mUdpDetector(new FroniusUdpDetector(this)),
	mAutoDetect(false),
	mScanType(None)
{
	Q_ASSERT(settings != 0);
	mAddressGenerator.setNetMaskLimit(QHostAddress(0xFFFFF000));
	mTimer->setInterval(60000);
	connect(mTimer, SIGNAL(timeout()), this, SLOT(onTimer()));
	connect(mUdpDetector, SIGNAL(finished()), this, SLOT(continueScan()));
}

void InverterGateway::addDetector(AbstractDetector *detector) {
	mDetectors.append(detector);
}

bool InverterGateway::autoDetect() const
{
	return mAutoDetect;
}

void InverterGateway::setAutoDetect(bool b)
{
	if (mAutoDetect == b)
		return;
	mAutoDetect = b;
	emit autoDetectChanged();
}

int InverterGateway::scanProgress() const
{
	return mAutoDetect ? mAddressGenerator.progress(mActiveHosts.count()) : 100;
}

void InverterGateway::initializeSettings()
{
	connect(mSettings, SIGNAL(portNumberChanged()), this, SLOT(onPortNumberChanged()));
	connect(mSettings, SIGNAL(ipAddressesChanged()), this, SLOT(onIpAddressesChanged()));
}

void InverterGateway::startDetection()
{
	// startDetection is called as soon as localsettings comes up. So this
	// is a good spot to start our period re-scan timer.
	mTimer->start();

	// Do a priorityScan, followed by a fullScan if not all hosts are found
	scan(TryPriority);
}

void InverterGateway::fullScan()
{
	scan(Full);
}

void InverterGateway::scan(enum ScanType scanType)
{
	mScanType = scanType;
	mDevicesFound.clear();
	setAutoDetect(mScanType == Full);

	// Do a UDP scan
	mUdpDetector->start();
}

void InverterGateway::continueScan()
{
	// Start with any addresses found by the fast UDP scan.
	QList<QHostAddress> addresses = mUdpDetector->devicesFound();

	// Initialise address generator with priority addresses
	foreach (QHostAddress a, mSettings->ipAddresses() + mSettings->knownIpAddresses()) {
		if (!addresses.contains(a)) {
			addresses.append(a);
		}
	}

	// If priority scan and no known PV-inverters, then we're done
	if (mScanType == Priority && addresses.isEmpty())
		return;

	QLOG_TRACE() << "Starting IP scan (" << mScanType << ")";
	mAddressGenerator.setPriorityAddresses(addresses);
	mAddressGenerator.setPriorityOnly(mScanType != Full);
	mAddressGenerator.reset();

	while (mActiveHosts.size() < MaxSimultaneousRequests && mAddressGenerator.hasNext()) {
		QString host = mAddressGenerator.next().toString();
		QLOG_TRACE() << "Starting scan for" << host;
		scanHost(host);
	}
}

void InverterGateway::scanHost(QString hostName)
{
	HostScan *host = new HostScan(mDetectors, hostName);
	mActiveHosts.append(host);
	connect(host, SIGNAL(finished()), this, SLOT(onDetectionDone()));
	connect(host, SIGNAL(deviceFound(const DeviceInfo &)),
			this, SLOT(onInverterFound(const DeviceInfo &)));
	host->scan();
}

void InverterGateway::onInverterFound(const DeviceInfo &deviceInfo)
{
	QHostAddress addr(deviceInfo.hostName);
	mDevicesFound.insert(addr);

	// If the found address is already in the list of manually configured
	// addresses, do not append it to the list of discovered addresses.
	if (!mSettings->ipAddresses().contains(addr)) {
		QList<QHostAddress> addresses = mSettings->knownIpAddresses();
		if (!addresses.contains(addr)) {
			addresses.append(addr);
			mSettings->setKnownIpAddresses(addresses);
		}
	}
	emit inverterFound(deviceInfo);
}

void InverterGateway::onDetectionDone()
{
	HostScan *host = static_cast<HostScan *>(sender());
	QLOG_TRACE() << "Done scanning" << host->hostName();
	mActiveHosts.removeOne(host);
	host->deleteLater();
	updateScanProgress();

	if (mScanType > None && mAddressGenerator.hasNext()) {
		// Scan the next available host
		scanHost(mAddressGenerator.next().toString());
	} else if(mActiveHosts.size() == 0) {
		// Scan is complete
		enum ScanType scanType = mScanType;
		mScanType = None;

		// Did we get what we came for? For full and priority scans, this is it.
		// For TryPriority scans, we switch to a full scan if we're a few
		// piggies short, and if autoScan is enabled.
		if ((scanType == TryPriority) && mSettings->autoScan()) {
			// FIXME only check that we found all known ones, not all priority
			// ones. Otherwise we do a full scan whenever a manually defined one
			// is missing
			QSet<QHostAddress> addresses = QSet<QHostAddress>::fromList(
					mAddressGenerator.priorityAddresses());

			// Do a full scan if not all devices were found
			if ((addresses - mDevicesFound).size()) {
				QLOG_INFO() << "Not all devices found, starting full IP scan";
				mScanType = Full;
				setAutoDetect(true);
				continueScan();
				return;
			}
		}

		setAutoDetect(false);
		QLOG_INFO() << "Auto IP scan completed. Detection finished";
	}
}

void InverterGateway::onPortNumberChanged()
{
	// If the port was changed, assume that the IP addresses did not, and
	// scan the priority addresses first, then fall back to a full scan.
	scan(TryPriority);
}

void InverterGateway::onIpAddressesChanged()
{
	// If the IP addresses changed, do a priority scan. That will scan
	// the new addresses too, and avoid a full scan.
	scan(Priority);
}

void InverterGateway::onTimer()
{
	// If we are in the middle of a sweep, don't start another one.
	if (mScanType > None)
		return;
	scan(TryPriority);
}

void InverterGateway::updateScanProgress()
{
	emit scanProgressChanged();
}

HostScan::HostScan(QList<AbstractDetector *> detectors, QString hostname, QObject *parent) :
	QObject(parent),
	mDetectors(detectors),
	mHostname(hostname)
{
}

void HostScan::scan()
{
	if (mDetectors.size()) {
		DetectorReply *reply = mDetectors.takeFirst()->start(mHostname);
		connect(reply, SIGNAL(deviceFound(const DeviceInfo &)),
			this, SLOT(onDeviceFound(const DeviceInfo &)));
		connect(reply, SIGNAL(finished()), this, SLOT(continueScan()));
	} else {
		emit finished();
	}
}

void HostScan::continueScan() {
	DetectorReply *reply = static_cast<DetectorReply *>(sender());
	reply->deleteLater();
	scan(); // Try next detector
}

void HostScan::onDeviceFound(const DeviceInfo &deviceInfo)
{
	mDetectors.clear(); // Found an inverter on this host, we're done.
	emit deviceFound(deviceInfo);
}
<|endoftext|>