<commit_before>#ifndef INCLUDE_AL_CONVERSION_HPP
#define INCLUDE_AL_CONVERSION_HPP

/*	Allocore --
	Multimedia / virtual environment application class library

	Copyright (C) 2009. AlloSphere Research Group, Media Arts & Technology, UCSB.
	Copyright (C) 2006-2008. The Regents of the University of California (REGENTS).
	All Rights Reserved.

	Permission to use, copy, modify, distribute, and distribute modified versions
	of this software and its documentation without fee and without a signed
	licensing agreement, is hereby granted, provided that the above copyright
	notice, the list of contributors, this paragraph and the following two paragraphs
	appear in all copies, modifications, and distributions.

	IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
	SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
	OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
	BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

	REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
	THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
	PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
	HEREUNDER IS PROVIDED "AS IS". REGENTS HAS  NO OBLIGATION TO PROVIDE
	MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

	File description:
	This is a grab bag of routines for converting between built-in types

	File author(s):
	Lance Putnam, 2010, putnam.lance@gmail.com
*/

#include <stdio.h>
#include <iostream>
#include <limits.h>
#include <sstream>		/* string conversion */
#include "allocore/system/al_Config.h"

namespace al{

#ifndef UINT32_C
#define UINT32_C(v) v ## UL
#endif

#ifndef UINT64_C
#define UINT64_C(v) v ## ULL
#endif

#define CONST(N, vf, vd)\
	template <class T> struct N;\
	template<> struct N< float>{ operator uint32_t() const { return UINT32_C(vf); } };\
	template<> struct N<double>{ operator uint64_t() const { return UINT64_C(vd); } };

	CONST(MaskExpo, 0x7F800000, 0x7FF0000000000000)	// IEEE-754 floating-point exponent bit mask
	CONST(MaskFrac, 0x007FFFFF, 0x000FFFFFFFFFFFFF) // IEEE-754 floating-point fraction bit mask
	CONST(MaskSign, 0x80000000, 0x8000000000000000) // IEEE-754 floating-point sign bit mask
	CONST(Expo1   , 0x3F800000, 0x3FF0000000000000) // IEEE-754 floating-point [1-2) exponent interval
#undef CONST

/// Union for twiddling bits of floats
template<class T> struct Twiddle;

template<> struct Twiddle<float>{
	Twiddle(const float& v): f(v){}
	Twiddle(const uint32_t& v): u(v){}
	Twiddle(const int32_t& v): i(v){}
	union{ int32_t i; uint32_t u; float f; };
};

template<> struct Twiddle<double>{
	Twiddle(const double& v): f(v){}
	Twiddle(const uint64_t& v): u(v){}
	Twiddle(const int64_t& v): i(v){}
	union{ int64_t i; uint64_t u; double f; };
};

/// Convert decimal integer to ascii base-36 character
char base10To36(int dec10);

/// Convert ascii base-36 character to decimal integer
int base36To10(char ascii36);

/// Convert a string of 1s and 0s to an integer.

/// @param[in] strBin	binary string where the first character is the most-significant digit
///
uint32_t bitsToUInt(const char * strBin);

/// Returns zero if argument is subnormal, otherwise returns argument
float blockSubnormal(float v);

/// Returns zero if argument is subnormal, otherwise returns argument
double blockSubnormal(double v);

/// Returns 1 if little endian, 0 if big endian
int endian();

/// Returns biased decimal value of 32-bit float exponent field.

/// The true exponent is the return value minus 127.
/// For example, values in [0.5, 1) return 126 (01111110), so the true
///	exponent is 126 - 127 = -1.
uint32_t floatExponent(float v);

/// Returns mantissa field as float between [0, 1).
float floatMantissa(float v);

/// Converts linear integer phase to fraction

///	2^bits is the effective size of the lookup table. \n
///	Note: the fraction only has 24-bits of precision.
float fraction(uint32_t bits, uint32_t phase);

/// Convert 16-bit signed integer to floating point in [-1, 1)
float intToUnit(int16_t v);

/// Type-pun 32-bit unsigned int to 32-bit float

/// This function uses a union to avoid problems with direct pointer casting
/// when the fstrict-aliasing compiler flag is on.
inline float punUF(uint32_t v){ Twiddle<float> u(v); return u.f; }

/// Type-pun 32-bit float to 32-bit unsigned int

/// This function uses a union to avoid problems with direct pointer casting
/// when the fstrict-aliasing compiler flag is on.
inline uint32_t punFU( float v){ Twiddle< float> u(v); return u.u; }

/// Type-pun 32-bit float to 32-bit signed int
inline  int32_t punFI( float v){ Twiddle< float> u(v); return u.i; }

/// Type-pun 64-bit float to 64-bit unsigned int
inline uint64_t punFU(  double v){ Twiddle<double> u(v); return u.u; }

/// Type-pun 64-bit float to 64-bit signed int
inline  int64_t punFI(  double v){ Twiddle<double> u(v); return u.i; }

/// Type-pun 64-bit unsigned int to 64-bit float
inline   double punUF(uint64_t v){ Twiddle<double> u(v); return u.f; }

/// Type-pun 64-bit signed int to 64-bit float
inline   double punIF( int64_t v){ Twiddle<double> u(v); return u.f; }

/// Convert numerical type to a string
template <class T> std::string toString(const T& v);

/// Convert array of numerical types to a comma separated string
template <class T>
std::string toString(const T * v, int num, int stride=1);

/// Convert 32-bit unsigned integer to unit float in [0, 1)
template<class T> T uintToUnit (uint32_t v);

/// Convert 32-bit unsigned integer to unit float in [-1, 1)
template<class T> T uintToUnitS(uint32_t v);

/// Convert floating point in [0, 1) to unsigned long in [0, 2^32)

/// This conversion is most accurate on a linear scale.
/// Input values outside [0, 1) result in undefined behavior.
uint32_t unitToUInt(float u);

/// Convert floating point in [0, 1) to unsigned long in [0, 2^32)

/// This conversion is most accurate on an exponential scale.
///	Input values outside [-1, 1) return 0.
///	Values in [-1, 0] behave as positive values in [0, 1).
uint32_t unitToUInt2(float u);

/// Convert unit float in [0,1) to 8-bit unsigned int in [0, 256).
uint8_t unitToUInt8(float u);

// Implementation
//------------------------------------------------------------------------------

inline char base10To36(int v){
	static const char * c = "0123456789abcdefghijklmnopqrstuvwxyz";
	if(v>=0 && v<=35) return c[v];
	return '0';
}

inline int base36To10(char v){
	v = tolower(v);
	if(v>='0' && v<='9') return v - '0';
	if(v>='a' && v<='z') return v - 'a' + 10;
	return 0;	// non-alphanumeric
}

inline uint32_t bitsToUInt(const char * string){
	uint32_t v=0; int n = strlen(string);
	for(int i=0; i<n; ++i) if(string[i] == '1') v |= 1<<(n-1-i);
	return v;
}

// alternate version...
//inline uint32_t bitsToUInt(const char * bits){
//	uint32_t i=0, r=0;
//	for(; bits[i] && i<32; ++i) r |= ((bits[i]=='1'?1:0) << (31-i));
//	return r>>(32-i);
//}

/// Sets argument to zero if subnormal
inline float blockSubnormal(float v){
	const uint32_t i = punFU(v);
	const uint32_t frac = i & MaskFrac<float>();
	const uint32_t expo = i & MaskExpo<float>();
	if(expo == 0 && frac != 0) v = 0.f;
	return v;
}

/// Sets argument to zero if subnormal
inline double blockSubnormal(double v){
	const uint64_t i = punFU(v);
	const uint64_t frac = i & MaskFrac<double>();
	const uint64_t expo = i & MaskExpo<double>();
	if(expo == 0 && frac != 0) v = 0.;
	return v;
}

inline int endian(){
	static int x=1;
	return *(char *)&x;
}

inline uint32_t floatExponent(float v){
	return punFU(v) >> 23 & 0xff;
}

inline float floatMantissa(float v){
	uint32_t frac = punFU(v);
	frac = (frac & MaskFrac<float>()) | Expo1<float>();
	return punUF(frac) - 1.f;
}

inline float fraction(uint32_t bits, uint32_t phase){
	phase = phase << bits >> 9 | Expo1<float>();
	return punUF(phase) - 1.f;
}

inline float intToUnit(int16_t v){
	uint32_t vu = (((uint32_t)v) + 0x808000) << 7; // set fraction in float [2, 4)
	return punUF(vu) - 3.f;
}

template <class T>
std::string toString(const T * v, int n, int s){
	std::string r;
	for(int i=0; i<n; ++i){
		r += toString(v[i*s]);
		if(i<(n-1)) r += ", ";
	}
	return r;
}

template <class T>
std::string toString(const T& v){
	using namespace std;
	stringstream ss(stringstream::in | stringstream::out);
	ss << v;
	string r;
	ss >> r;
	return r;
}

template<> inline float uintToUnit<float>(uint32_t v){
	v = v >> 9 | Expo1<float>();	// float in [1, 2)
	return punUF(v) - 1.f;
}

template<> inline float uintToUnitS<float>(uint32_t v){
	v = v >> 9 | 0x40000000;		// float in [2, 4)
	return punUF(v) - 3.f;
}

inline uint32_t unitToUInt(float v){
	++v;	// go into [1,2] range, FP fraction is now result
	return punFU(v) << 9;
}

// TODO: make 64-bit ready
inline uint32_t unitToUInt2(float v){
	uint32_t normalU = punFU(v);
	uint32_t rbs = 126UL - (normalU >> 23UL);
//	printf("%x %lu\n", (normalU | 0x800000) << 8, rbs);
//	printf("%x\n", 0x80000000UL >> rbs);
	return (((normalU | 0x800000UL) << 8UL) & (~ULONG_MAX | 0xffffffffUL)) >> rbs;

//	uint32_t normalU = punFU(v);
//	uint32_t rbs = 118UL - ((normalU >> 23UL) & (~ULONG_MAX | 0x7fffffUL));
////	printf("%x %lu\n", (normalU | 0x800000) << 8, rbs);
////	printf("%x\n", 0x80000000UL >> rbs);
//	return ((normalU & (~ULONG_MAX | 0xffffffUL)) | 0x800000UL) >> rbs;
////	return (((normalU | 0x800000UL) << 8UL) & (~ULONG_MAX | 0xffffffffUL)) >> rbs;

//Her00
//float y = v + 1.f;
//return ((unsigned long&)v) & 0x7FFFFF;      // last 23 bits
}

inline uint8_t unitToUInt8(float u){
	++u;
	return (punFU(u) >> 15) & MaskFrac<float>();
}

} // al::

#endif
<commit_msg>add unit float to 16-bit int function<commit_after>#ifndef INCLUDE_AL_CONVERSION_HPP
#define INCLUDE_AL_CONVERSION_HPP

/*	Allocore --
	Multimedia / virtual environment application class library

	Copyright (C) 2009. AlloSphere Research Group, Media Arts & Technology, UCSB.
	Copyright (C) 2006-2008. The Regents of the University of California (REGENTS).
	All Rights Reserved.

	Permission to use, copy, modify, distribute, and distribute modified versions
	of this software and its documentation without fee and without a signed
	licensing agreement, is hereby granted, provided that the above copyright
	notice, the list of contributors, this paragraph and the following two paragraphs
	appear in all copies, modifications, and distributions.

	IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
	SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING
	OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS
	BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

	REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
	THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
	PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED
	HEREUNDER IS PROVIDED "AS IS". REGENTS HAS  NO OBLIGATION TO PROVIDE
	MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.

	File description:
	This is a grab bag of routines for converting between built-in types

	File author(s):
	Lance Putnam, 2010, putnam.lance@gmail.com
*/

#include <stdio.h>
#include <iostream>
#include <limits.h>
#include <sstream>		/* string conversion */
#include "allocore/system/al_Config.h"

namespace al{

#ifndef UINT32_C
#define UINT32_C(v) v ## UL
#endif

#ifndef UINT64_C
#define UINT64_C(v) v ## ULL
#endif

#define CONST(N, vf, vd)\
	template <class T> struct N;\
	template<> struct N< float>{ operator uint32_t() const { return UINT32_C(vf); } };\
	template<> struct N<double>{ operator uint64_t() const { return UINT64_C(vd); } };

	CONST(MaskExpo, 0x7F800000, 0x7FF0000000000000)	// IEEE-754 floating-point exponent bit mask
	CONST(MaskFrac, 0x007FFFFF, 0x000FFFFFFFFFFFFF) // IEEE-754 floating-point fraction bit mask
	CONST(MaskSign, 0x80000000, 0x8000000000000000) // IEEE-754 floating-point sign bit mask
	CONST(Expo1   , 0x3F800000, 0x3FF0000000000000) // IEEE-754 floating-point [1-2) exponent interval
#undef CONST

/// Union for twiddling bits of floats
template<class T> struct Twiddle;

template<> struct Twiddle<float>{
	Twiddle(const float& v): f(v){}
	Twiddle(const uint32_t& v): u(v){}
	Twiddle(const int32_t& v): i(v){}
	union{ int32_t i; uint32_t u; float f; };
};

template<> struct Twiddle<double>{
	Twiddle(const double& v): f(v){}
	Twiddle(const uint64_t& v): u(v){}
	Twiddle(const int64_t& v): i(v){}
	union{ int64_t i; uint64_t u; double f; };
};

/// Convert decimal integer to ascii base-36 character
char base10To36(int dec10);

/// Convert ascii base-36 character to decimal integer
int base36To10(char ascii36);

/// Convert a string of 1s and 0s to an integer.

/// @param[in] strBin	binary string where the first character is the most-significant digit
///
uint32_t bitsToUInt(const char * strBin);

/// Returns zero if argument is subnormal, otherwise returns argument
float blockSubnormal(float v);

/// Returns zero if argument is subnormal, otherwise returns argument
double blockSubnormal(double v);

/// Returns 1 if little endian, 0 if big endian
int endian();

/// Returns biased decimal value of 32-bit float exponent field.

/// The true exponent is the return value minus 127.
/// For example, values in [0.5, 1) return 126 (01111110), so the true
///	exponent is 126 - 127 = -1.
uint32_t floatExponent(float v);

/// Returns mantissa field as float between [0, 1).
float floatMantissa(float v);

/// Converts linear integer phase to fraction

///	2^bits is the effective size of the lookup table. \n
///	Note: the fraction only has 24-bits of precision.
float fraction(uint32_t bits, uint32_t phase);

/// Convert 16-bit signed integer to floating point in [-1, 1)
float intToUnit(int16_t v);

/// Type-pun 32-bit unsigned int to 32-bit float

/// This function uses a union to avoid problems with direct pointer casting
/// when the fstrict-aliasing compiler flag is on.
inline float punUF(uint32_t v){ Twiddle<float> u(v); return u.f; }

/// Type-pun 32-bit float to 32-bit unsigned int

/// This function uses a union to avoid problems with direct pointer casting
/// when the fstrict-aliasing compiler flag is on.
inline uint32_t punFU( float v){ Twiddle< float> u(v); return u.u; }

/// Type-pun 32-bit float to 32-bit signed int
inline  int32_t punFI( float v){ Twiddle< float> u(v); return u.i; }

/// Type-pun 64-bit float to 64-bit unsigned int
inline uint64_t punFU(  double v){ Twiddle<double> u(v); return u.u; }

/// Type-pun 64-bit float to 64-bit signed int
inline  int64_t punFI(  double v){ Twiddle<double> u(v); return u.i; }

/// Type-pun 64-bit unsigned int to 64-bit float
inline   double punUF(uint64_t v){ Twiddle<double> u(v); return u.f; }

/// Type-pun 64-bit signed int to 64-bit float
inline   double punIF( int64_t v){ Twiddle<double> u(v); return u.f; }

/// Convert numerical type to a string
template <class T> std::string toString(const T& v);

/// Convert array of numerical types to a comma separated string
template <class T>
std::string toString(const T * v, int num, int stride=1);

/// Convert 32-bit unsigned integer to unit float in [0, 1)
template<class T> T uintToUnit (uint32_t v);

/// Convert 32-bit unsigned integer to unit float in [-1, 1)
template<class T> T uintToUnitS(uint32_t v);

/// Convert float in [-1, 1) to 16-bit signed int in [0, 2^16)
int16_t unitToInt16(float v);

/// Convert float in [0, 1) to 32-bit unsigned int in [0, 2^32)

/// This conversion is most accurate on a linear scale.
/// Input values outside [0, 1) result in undefined behavior.
uint32_t unitToUInt(float u);

/// Convert float in [0, 1) to 32-bit unsigned int in [0, 2^32)

/// This conversion is most accurate on an exponential scale.
///	Input values outside [-1, 1) return 0.
///	Values in [-1, 0] behave as positive values in [0, 1).
uint32_t unitToUInt2(float u);

/// Convert float in [0, 1) to 8-bit unsigned int in [0, 256)
uint8_t unitToUInt8(float u);

// Implementation
//------------------------------------------------------------------------------

inline char base10To36(int v){
	static const char * c = "0123456789abcdefghijklmnopqrstuvwxyz";
	if(v>=0 && v<=35) return c[v];
	return '0';
}

inline int base36To10(char v){
	v = tolower(v);
	if(v>='0' && v<='9') return v - '0';
	if(v>='a' && v<='z') return v - 'a' + 10;
	return 0;	// non-alphanumeric
}

inline uint32_t bitsToUInt(const char * string){
	uint32_t v=0; int n = strlen(string);
	for(int i=0; i<n; ++i) if(string[i] == '1') v |= 1<<(n-1-i);
	return v;
}

// alternate version...
//inline uint32_t bitsToUInt(const char * bits){
//	uint32_t i=0, r=0;
//	for(; bits[i] && i<32; ++i) r |= ((bits[i]=='1'?1:0) << (31-i));
//	return r>>(32-i);
//}

/// Sets argument to zero if subnormal
inline float blockSubnormal(float v){
	const uint32_t i = punFU(v);
	const uint32_t frac = i & MaskFrac<float>();
	const uint32_t expo = i & MaskExpo<float>();
	if(expo == 0 && frac != 0) v = 0.f;
	return v;
}

/// Sets argument to zero if subnormal
inline double blockSubnormal(double v){
	const uint64_t i = punFU(v);
	const uint64_t frac = i & MaskFrac<double>();
	const uint64_t expo = i & MaskExpo<double>();
	if(expo == 0 && frac != 0) v = 0.;
	return v;
}

inline int endian(){
	static int x=1;
	return *(char *)&x;
}

inline uint32_t floatExponent(float v){
	return punFU(v) >> 23 & 0xff;
}

inline float floatMantissa(float v){
	uint32_t frac = punFU(v);
	frac = (frac & MaskFrac<float>()) | Expo1<float>();
	return punUF(frac) - 1.f;
}

inline float fraction(uint32_t bits, uint32_t phase){
	phase = phase << bits >> 9 | Expo1<float>();
	return punUF(phase) - 1.f;
}

inline float intToUnit(int16_t v){
	uint32_t vu = (((uint32_t)v) + 0x808000) << 7; // set fraction in float [2, 4)
	return punUF(vu) - 3.f;
}

template <class T>
std::string toString(const T * v, int n, int s){
	std::string r;
	for(int i=0; i<n; ++i){
		r += toString(v[i*s]);
		if(i<(n-1)) r += ", ";
	}
	return r;
}

template <class T>
std::string toString(const T& v){
	using namespace std;
	stringstream ss(stringstream::in | stringstream::out);
	ss << v;
	string r;
	ss >> r;
	return r;
}

template<> inline float uintToUnit<float>(uint32_t v){
	v = v >> 9 | Expo1<float>();	// float in [1, 2)
	return punUF(v) - 1.f;
}

template<> inline float uintToUnitS<float>(uint32_t v){
	v = v >> 9 | 0x40000000;		// float in [2, 4)
	return punUF(v) - 3.f;
}

inline int16_t unitToInt16(float v){
	float r = v + 3.f; // put in [2,4)
	return int16_t((al::punFU(r) >> 7) + (1<<15));
}

inline uint32_t unitToUInt(float v){
	++v;	// go into [1,2] range, FP fraction is now result
	return punFU(v) << 9;
}

// TODO: make 64-bit ready
inline uint32_t unitToUInt2(float v){
	uint32_t normalU = punFU(v);
	uint32_t rbs = 126UL - (normalU >> 23UL);
//	printf("%x %lu\n", (normalU | 0x800000) << 8, rbs);
//	printf("%x\n", 0x80000000UL >> rbs);
	return (((normalU | 0x800000UL) << 8UL) & (~ULONG_MAX | 0xffffffffUL)) >> rbs;

//	uint32_t normalU = punFU(v);
//	uint32_t rbs = 118UL - ((normalU >> 23UL) & (~ULONG_MAX | 0x7fffffUL));
////	printf("%x %lu\n", (normalU | 0x800000) << 8, rbs);
////	printf("%x\n", 0x80000000UL >> rbs);
//	return ((normalU & (~ULONG_MAX | 0xffffffUL)) | 0x800000UL) >> rbs;
////	return (((normalU | 0x800000UL) << 8UL) & (~ULONG_MAX | 0xffffffffUL)) >> rbs;

//Her00
//float y = v + 1.f;
//return ((unsigned long&)v) & 0x7FFFFF;      // last 23 bits
}

inline uint8_t unitToUInt8(float u){
	++u;
	return (punFU(u) >> 15) & MaskFrac<float>();
}

} // al::

#endif
<|endoftext|>


<commit_before>// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "bin/dartdev_utils.h"

#include <memory>

#include "bin/directory.h"
#include "bin/exe_utils.h"
#include "bin/file.h"
#include "platform/utils.h"

namespace dart {
namespace bin {

bool DartDevUtils::ShouldParseCommand(const char* script_uri) {
  // If script_uri is not a file path or of a known URI scheme, we can assume
  // that this is a DartDev command.
  return (!File::ExistsUri(nullptr, script_uri) &&
          (strncmp(script_uri, "http://", 7) != 0) &&
          (strncmp(script_uri, "https://", 8) != 0) &&
          (strncmp(script_uri, "file://", 7) != 0) &&
          (strncmp(script_uri, "google3://", 10) != 0));
}

bool DartDevUtils::TryResolveDartDevSnapshotPath(char** script_name) {
  // |dir_prefix| includes the last path seperator.
  auto dir_prefix = std::unique_ptr<char, void (*)(void*)>(
      EXEUtils::GetDirectoryPrefixFromExeName(), free);

  // First assume we're in dart-sdk/bin.
  char* snapshot_path =
      Utils::SCreate("%s/snapshots/dartdev.dart.snapshot", dir_prefix.get());
  if (File::Exists(nullptr, snapshot_path)) {
    *script_name = snapshot_path;
    return true;
  }
  free(snapshot_path);

  // If we're not in dart-sdk/bin, we might be in one of the $SDK/out/*
  // directories. Try to use a snapshot from a previously built SDK.
  snapshot_path = Utils::SCreate(
      "%s/dart-sdk/bin/snapshots/dartdev.dart.snapshot", dir_prefix.get());
  if (File::Exists(nullptr, snapshot_path)) {
    *script_name = snapshot_path;
    return true;
  }
  free(snapshot_path);
  return false;
}

}  // namespace bin
}  // namespace dart
<commit_msg>[vm] Fix command line inspection to allow package: scripts<commit_after>// Copyright (c) 2020, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "bin/dartdev_utils.h"

#include <memory>

#include "bin/directory.h"
#include "bin/exe_utils.h"
#include "bin/file.h"
#include "platform/utils.h"

namespace dart {
namespace bin {

bool DartDevUtils::ShouldParseCommand(const char* script_uri) {
  // If script_uri is not a file path or of a known URI scheme, we can assume
  // that this is a DartDev command.
  return (!File::ExistsUri(nullptr, script_uri) &&
          (strncmp(script_uri, "http://", 7) != 0) &&
          (strncmp(script_uri, "https://", 8) != 0) &&
          (strncmp(script_uri, "file://", 7) != 0) &&
          (strncmp(script_uri, "package:", 8) != 0) &&
          (strncmp(script_uri, "google3://", 10) != 0));
}

bool DartDevUtils::TryResolveDartDevSnapshotPath(char** script_name) {
  // |dir_prefix| includes the last path seperator.
  auto dir_prefix = std::unique_ptr<char, void (*)(void*)>(
      EXEUtils::GetDirectoryPrefixFromExeName(), free);

  // First assume we're in dart-sdk/bin.
  char* snapshot_path =
      Utils::SCreate("%s/snapshots/dartdev.dart.snapshot", dir_prefix.get());
  if (File::Exists(nullptr, snapshot_path)) {
    *script_name = snapshot_path;
    return true;
  }
  free(snapshot_path);

  // If we're not in dart-sdk/bin, we might be in one of the $SDK/out/*
  // directories. Try to use a snapshot from a previously built SDK.
  snapshot_path = Utils::SCreate(
      "%s/dart-sdk/bin/snapshots/dartdev.dart.snapshot", dir_prefix.get());
  if (File::Exists(nullptr, snapshot_path)) {
    *script_name = snapshot_path;
    return true;
  }
  free(snapshot_path);
  return false;
}

}  // namespace bin
}  // namespace dart
<|endoftext|>


<commit_before>/* Copyright 2019 Benjamin Worpitz, René Widera
 *
 * This file is part of alpaka.
 *
 * 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/.
 */

#pragma once

#ifdef ALPAKA_ACC_ANY_BT_OMP5_ENABLED

#if _OPENMP < 201307
    #error If ALPAKA_ACC_ANY_BT_OMP5_ENABLED is set, the compiler has to support OpenMP 4.0 or higher!
#endif

// Specialized traits.
#include <alpaka/acc/Traits.hpp>
#include <alpaka/dev/Traits.hpp>
#include <alpaka/dim/Traits.hpp>
#include <alpaka/pltf/Traits.hpp>
#include <alpaka/idx/Traits.hpp>

// Implementation details.
#include <alpaka/acc/AccOmp5.hpp>
#include <alpaka/core/Decay.hpp>
#include <alpaka/dev/DevOmp5.hpp>
#include <alpaka/idx/MapIdx.hpp>
#include <alpaka/kernel/Traits.hpp>
#include <alpaka/workdiv/WorkDivMembers.hpp>

#include <alpaka/meta/ApplyTuple.hpp>

#include <omp.h>

#include <functional>
#include <stdexcept>
#include <tuple>
#include <type_traits>
#include <algorithm>
#if ALPAKA_DEBUG >= ALPAKA_DEBUG_MINIMAL
    #include <iostream>
#endif

namespace alpaka
{
    namespace kernel
    {
        //#############################################################################
        //! The OpenMP 5.0 accelerator execution task.
        template<
            typename TDim,
            typename TIdx,
            typename TKernelFnObj,
            typename... TArgs>
        class TaskKernelOmp5 final :
            public workdiv::WorkDivMembers<TDim, TIdx>
        {
        public:
            //-----------------------------------------------------------------------------
            template<
                typename TWorkDiv>
            ALPAKA_FN_HOST TaskKernelOmp5(
                TWorkDiv && workDiv,
                TKernelFnObj const & kernelFnObj,
                TArgs && ... args) :
                    workdiv::WorkDivMembers<TDim, TIdx>(std::forward<TWorkDiv>(workDiv)),
                    m_kernelFnObj(kernelFnObj),
                    m_args(std::forward<TArgs>(args)...)
            {
                static_assert(
                    dim::Dim<std::decay_t<TWorkDiv>>::value == TDim::value,
                    "The work division and the execution task have to be of the same dimensionality!");
            }
            //-----------------------------------------------------------------------------
            TaskKernelOmp5(TaskKernelOmp5 const & other) = default;
            //-----------------------------------------------------------------------------
            TaskKernelOmp5(TaskKernelOmp5 && other) = default;
            //-----------------------------------------------------------------------------
            auto operator=(TaskKernelOmp5 const &) -> TaskKernelOmp5 & = default;
            //-----------------------------------------------------------------------------
            auto operator=(TaskKernelOmp5 &&) -> TaskKernelOmp5 & = default;
            //-----------------------------------------------------------------------------
            ~TaskKernelOmp5() = default;

            //-----------------------------------------------------------------------------
            //! Executes the kernel function object.
            ALPAKA_FN_HOST auto operator()(
                    const
                    dev::DevOmp5& dev
                ) const
            -> void
            {
                ALPAKA_DEBUG_MINIMAL_LOG_SCOPE;

                auto const gridBlockExtent(
                    workdiv::getWorkDiv<Grid, Blocks>(*this));
                auto const blockThreadExtent(
                    workdiv::getWorkDiv<Block, Threads>(*this));
                auto const threadElemExtent(
                    workdiv::getWorkDiv<Thread, Elems>(*this));

#if ALPAKA_DEBUG >= ALPAKA_DEBUG_MINIMAL
                std::cout << "m_gridBlockExtent=" << this->m_gridBlockExtent << "\tgridBlockExtent=" << gridBlockExtent << std::endl;
                std::cout << "m_blockThreadExtent=" << this->m_blockThreadExtent << "\tblockThreadExtent=" << blockThreadExtent << std::endl;
                std::cout << "m_threadElemExtent=" << this->m_threadElemExtent << "\tthreadElemExtent=" << threadElemExtent << std::endl;
#endif

                // Get the size of the block shared dynamic memory.
                auto const blockSharedMemDynSizeBytes(
                    meta::apply(
                        [&](ALPAKA_DECAY_T(TArgs) const & ... args)
                        {
                            return
                                kernel::getBlockSharedMemDynSizeBytes<
                                    acc::AccOmp5<TDim, TIdx>>(
                                        m_kernelFnObj,
                                        blockThreadExtent,
                                        threadElemExtent,
                                        args...);
                        },
                        m_args));

#if ALPAKA_DEBUG >= ALPAKA_DEBUG_FULL
                std::cout << __func__
                    << " blockSharedMemDynSizeBytes: " << blockSharedMemDynSizeBytes << " B" << std::endl;
#endif
                // We have to make sure, that the OpenMP runtime keeps enough threads for executing a block in parallel.
                TIdx const maxOmpThreadCount(static_cast<TIdx>(::omp_get_max_threads()));
                // The number of blocks in the grid.
                TIdx const gridBlockCount(gridBlockExtent.prod());
                // The number of threads in a block.
                TIdx const blockThreadCount(blockThreadExtent.prod());

#if ALPAKA_DEBUG >= ALPAKA_DEBUG_MINIMAL
                if(maxOmpThreadCount < blockThreadExtent.prod())
                    std::cout << "Warning: TaskKernelOmp5: maxOmpThreadCount smaller than blockThreadCount requested by caller:" <<
                        maxOmpThreadCount << " < " << blockThreadExtent.prod() << std::endl;
#endif
                // make sure there is at least on team
                TIdx const teamCount(std::max(std::min(static_cast<TIdx>(maxOmpThreadCount/blockThreadCount), gridBlockCount), static_cast<TIdx>(1u)));
#if ALPAKA_DEBUG >= ALPAKA_DEBUG_FULL
                std::cout << "threadElemCount=" << threadElemExtent[0u] << std::endl;
                std::cout << "teamCount=" << teamCount << "\tgridBlockCount=" << gridBlockCount << std::endl;
#endif

                if(::omp_in_parallel() != 0)
                {
                    throw std::runtime_error("The OpenMP 5.0 backend can not be used within an existing parallel region!");
                }

                // Force the environment to use the given number of threads.
                int const ompIsDynamic(::omp_get_dynamic());
                ::omp_set_dynamic(0);

                // `When an if(scalar-expression) evaluates to false, the structured block is executed on the host.`
                auto argsD = m_args;
                auto kernelFnObj = m_kernelFnObj;
                const auto iDevice = dev.iDevice();
                #pragma omp target device(iDevice)
                {
                    #pragma omp teams num_teams(teamCount) thread_limit(blockThreadCount)
                    {
#if ALPAKA_DEBUG >= ALPAKA_DEBUG_MINIMAL
                        // The first team does some checks ...
                        if((::omp_get_team_num() == 0))
                        {
                            int const iNumTeams(::omp_get_num_teams());
                            printf("%s omp_get_num_teams: %d\n", __func__, iNumTeams);
                        }
                        printf("threadElemCount_dev %d\n", int(threadElemExtent[0u]));
#endif
                        // iterate over groups of teams to stay withing thread limit
                        for(TIdx t = 0u; t < gridBlockCount; t+=teamCount)
                        {
                            acc::AccOmp5<TDim, TIdx> acc(
                                gridBlockExtent,
                                blockThreadExtent,
                                threadElemExtent,
                                t,
                                blockSharedMemDynSizeBytes);

                            // printf("acc->threadElemCount %d\n"
                            //         , int(acc.m_threadElemExtent[0]));

                            const TIdx bsup = std::min(static_cast<TIdx>(t + teamCount), gridBlockCount);
                            #pragma omp distribute
                            for(TIdx b = t; b<bsup; ++b)
                            {
                                vec::Vec<dim::DimInt<1u>, TIdx> const gridBlockIdx(b);
                                // When this is not repeated here:
                                // error: gridBlockExtent referenced in target region does not have a mappable type
                                auto const gridBlockExtent2(
                                    workdiv::getWorkDiv<Grid, Blocks>(*static_cast<workdiv::WorkDivMembers<TDim, TIdx> const *>(this)));
                                acc.m_gridBlockIdx = idx::mapIdx<TDim::value>(
                                    gridBlockIdx,
                                    gridBlockExtent2);

                                // Execute the threads in parallel.

                                // Parallel execution of the threads in a block is required because when syncBlockThreads is called all of them have to be done with their work up to this line.
                                // So we have to spawn one OS thread per thread in a block.
                                // 'omp for' is not useful because it is meant for cases where multiple iterations are executed by one thread but in our case a 1:1 mapping is required.
                                // Therefore we use 'omp parallel' with the specified number of threads in a block.
#ifndef __ibmxl_vrm__
                                // setting num_threads to any value leads XL to run only one thread per team
                                omp_set_num_threads(static_cast<int>(blockThreadCount));
#endif
                                #pragma omp parallel
                                {
#if ALPAKA_DEBUG >= ALPAKA_DEBUG_MINIMAL
                                    // The first thread does some checks in the first block executed.
                                    if((::omp_get_thread_num() == 0) && (b == 0))
                                    {
                                        int const numThreads(::omp_get_num_threads());
                                        printf("%s omp_get_num_threads: %d\n", __func__, numThreads);
                                        if(numThreads != static_cast<int>(blockThreadCount))
                                        {
                                            printf("ERROR: The OpenMP runtime did not use the number of threads that had been requested!\n");
                                        }
                                    }
#endif
                                    meta::apply(
                                        [kernelFnObj, &acc](typename std::decay<TArgs>::type const & ... args)
                                        {
                                            kernelFnObj(
                                                    acc,
                                                    args...);
                                        },
                                        argsD);

                                    // Wait for all threads to finish before deleting the shared memory.
                                    // This is done by default if the omp 'nowait' clause is missing
                                    //block::sync::syncBlockThreads(acc);
                                }

                                // After a block has been processed, the shared memory has to be deleted.
                                block::shared::st::freeMem(acc);
                            }
                        }
                    }
                }

                // Reset the dynamic thread number setting.
                ::omp_set_dynamic(ompIsDynamic);
            }

        private:
            TKernelFnObj m_kernelFnObj;
            std::tuple<std::decay_t<TArgs>...> m_args;
        };
    }

    namespace acc
    {
        namespace traits
        {
            //#############################################################################
            //! The OpenMP 5.0 execution task accelerator type trait specialization.
            template<
                typename TDim,
                typename TIdx,
                typename TKernelFnObj,
                typename... TArgs>
            struct AccType<
                kernel::TaskKernelOmp5<TDim, TIdx, TKernelFnObj, TArgs...>>
            {
                using type = acc::AccOmp5<TDim, TIdx>;
            };
        }
    }
    namespace dev
    {
        namespace traits
        {
            //#############################################################################
            //! The OpenMP 5.0 execution task device type trait specialization.
            template<
                typename TDim,
                typename TIdx,
                typename TKernelFnObj,
                typename... TArgs>
            struct DevType<
                kernel::TaskKernelOmp5<TDim, TIdx, TKernelFnObj, TArgs...>>
            {
                using type = dev::DevOmp5;
            };
        }
    }
    namespace dim
    {
        namespace traits
        {
            //#############################################################################
            //! The OpenMP 5.0 execution task dimension getter trait specialization.
            template<
                typename TDim,
                typename TIdx,
                typename TKernelFnObj,
                typename... TArgs>
            struct DimType<
                kernel::TaskKernelOmp5<TDim, TIdx, TKernelFnObj, TArgs...>>
            {
                using type = TDim;
            };
        }
    }
    namespace pltf
    {
        namespace traits
        {
            //#############################################################################
            //! The OpenMP 5.0 execution task platform type trait specialization.
            template<
                typename TDim,
                typename TIdx,
                typename TKernelFnObj,
                typename... TArgs>
            struct PltfType<
                kernel::TaskKernelOmp5<TDim, TIdx, TKernelFnObj, TArgs...>>
            {
                using type = pltf::PltfOmp5;
            };
        }
    }
    namespace idx
    {
        namespace traits
        {
            //#############################################################################
            //! The OpenMP 5.0 execution task idx type trait specialization.
            template<
                typename TDim,
                typename TIdx,
                typename TKernelFnObj,
                typename... TArgs>
            struct IdxType<
                kernel::TaskKernelOmp5<TDim, TIdx, TKernelFnObj, TArgs...>>
            {
                using type = TIdx;
            };
        }
    }

    namespace queue
    {
        namespace traits
        {
            template<
                typename TDim,
                typename TIdx,
                typename TKernelFnObj,
                typename... TArgs>
            struct Enqueue<
                queue::QueueOmp5Blocking,
                kernel::TaskKernelOmp5<TDim, TIdx, TKernelFnObj, TArgs...> >
            {
                ALPAKA_FN_HOST static auto enqueue(
                    queue::QueueOmp5Blocking& queue,
                    kernel::TaskKernelOmp5<TDim, TIdx, TKernelFnObj, TArgs...> const & task)
                -> void
                {
                    std::lock_guard<std::mutex> lk(queue.m_spQueueImpl->m_mutex);

                    queue.m_spQueueImpl->m_bCurrentlyExecutingTask = true;

                    task(
                            queue.m_spQueueImpl->m_dev
                        );

                    queue.m_spQueueImpl->m_bCurrentlyExecutingTask = false;
                }
            };

            template<
                typename TDim,
                typename TIdx,
                typename TKernelFnObj,
                typename... TArgs>
            struct Enqueue<
                queue::QueueOmp5NonBlocking,
                kernel::TaskKernelOmp5<TDim, TIdx, TKernelFnObj, TArgs...> >
            {
                //-----------------------------------------------------------------------------
                ALPAKA_FN_HOST static auto enqueue(
                    queue::QueueOmp5NonBlocking& queue,
                    kernel::TaskKernelOmp5<TDim, TIdx, TKernelFnObj, TArgs...> const & task)
                -> void
                {
                    queue.m_spQueueImpl->m_workerThread.enqueueTask(
                        [&queue, task]()
                        {
                            task(
                                    queue.m_spQueueImpl->m_dev
                                );
                        });
                }
            };
        }
    }
}

#endif
<commit_msg>TaskKernelOmp5: use num_threads clause ...<commit_after>/* Copyright 2019 Benjamin Worpitz, René Widera
 *
 * This file is part of alpaka.
 *
 * 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/.
 */

#pragma once

#ifdef ALPAKA_ACC_ANY_BT_OMP5_ENABLED

#if _OPENMP < 201307
    #error If ALPAKA_ACC_ANY_BT_OMP5_ENABLED is set, the compiler has to support OpenMP 4.0 or higher!
#endif

// Specialized traits.
#include <alpaka/acc/Traits.hpp>
#include <alpaka/dev/Traits.hpp>
#include <alpaka/dim/Traits.hpp>
#include <alpaka/pltf/Traits.hpp>
#include <alpaka/idx/Traits.hpp>

// Implementation details.
#include <alpaka/acc/AccOmp5.hpp>
#include <alpaka/core/Decay.hpp>
#include <alpaka/dev/DevOmp5.hpp>
#include <alpaka/idx/MapIdx.hpp>
#include <alpaka/kernel/Traits.hpp>
#include <alpaka/workdiv/WorkDivMembers.hpp>

#include <alpaka/meta/ApplyTuple.hpp>

#include <omp.h>

#include <functional>
#include <stdexcept>
#include <tuple>
#include <type_traits>
#include <algorithm>
#if ALPAKA_DEBUG >= ALPAKA_DEBUG_MINIMAL
    #include <iostream>
#endif

namespace alpaka
{
    namespace kernel
    {
        //#############################################################################
        //! The OpenMP 5.0 accelerator execution task.
        template<
            typename TDim,
            typename TIdx,
            typename TKernelFnObj,
            typename... TArgs>
        class TaskKernelOmp5 final :
            public workdiv::WorkDivMembers<TDim, TIdx>
        {
        public:
            //-----------------------------------------------------------------------------
            template<
                typename TWorkDiv>
            ALPAKA_FN_HOST TaskKernelOmp5(
                TWorkDiv && workDiv,
                TKernelFnObj const & kernelFnObj,
                TArgs && ... args) :
                    workdiv::WorkDivMembers<TDim, TIdx>(std::forward<TWorkDiv>(workDiv)),
                    m_kernelFnObj(kernelFnObj),
                    m_args(std::forward<TArgs>(args)...)
            {
                static_assert(
                    dim::Dim<std::decay_t<TWorkDiv>>::value == TDim::value,
                    "The work division and the execution task have to be of the same dimensionality!");
            }
            //-----------------------------------------------------------------------------
            TaskKernelOmp5(TaskKernelOmp5 const & other) = default;
            //-----------------------------------------------------------------------------
            TaskKernelOmp5(TaskKernelOmp5 && other) = default;
            //-----------------------------------------------------------------------------
            auto operator=(TaskKernelOmp5 const &) -> TaskKernelOmp5 & = default;
            //-----------------------------------------------------------------------------
            auto operator=(TaskKernelOmp5 &&) -> TaskKernelOmp5 & = default;
            //-----------------------------------------------------------------------------
            ~TaskKernelOmp5() = default;

            //-----------------------------------------------------------------------------
            //! Executes the kernel function object.
            ALPAKA_FN_HOST auto operator()(
                    const
                    dev::DevOmp5& dev
                ) const
            -> void
            {
                ALPAKA_DEBUG_MINIMAL_LOG_SCOPE;

                auto const gridBlockExtent(
                    workdiv::getWorkDiv<Grid, Blocks>(*this));
                auto const blockThreadExtent(
                    workdiv::getWorkDiv<Block, Threads>(*this));
                auto const threadElemExtent(
                    workdiv::getWorkDiv<Thread, Elems>(*this));

#if ALPAKA_DEBUG >= ALPAKA_DEBUG_MINIMAL
                std::cout << "m_gridBlockExtent=" << this->m_gridBlockExtent << "\tgridBlockExtent=" << gridBlockExtent << std::endl;
                std::cout << "m_blockThreadExtent=" << this->m_blockThreadExtent << "\tblockThreadExtent=" << blockThreadExtent << std::endl;
                std::cout << "m_threadElemExtent=" << this->m_threadElemExtent << "\tthreadElemExtent=" << threadElemExtent << std::endl;
#endif

                // Get the size of the block shared dynamic memory.
                auto const blockSharedMemDynSizeBytes(
                    meta::apply(
                        [&](ALPAKA_DECAY_T(TArgs) const & ... args)
                        {
                            return
                                kernel::getBlockSharedMemDynSizeBytes<
                                    acc::AccOmp5<TDim, TIdx>>(
                                        m_kernelFnObj,
                                        blockThreadExtent,
                                        threadElemExtent,
                                        args...);
                        },
                        m_args));

#if ALPAKA_DEBUG >= ALPAKA_DEBUG_FULL
                std::cout << __func__
                    << " blockSharedMemDynSizeBytes: " << blockSharedMemDynSizeBytes << " B" << std::endl;
#endif
                // We have to make sure, that the OpenMP runtime keeps enough threads for executing a block in parallel.
                TIdx const maxOmpThreadCount(static_cast<TIdx>(::omp_get_max_threads()));
                // The number of blocks in the grid.
                TIdx const gridBlockCount(gridBlockExtent.prod());
                // The number of threads in a block.
                TIdx const blockThreadCount(blockThreadExtent.prod());

#if ALPAKA_DEBUG >= ALPAKA_DEBUG_MINIMAL
                if(maxOmpThreadCount < blockThreadExtent.prod())
                    std::cout << "Warning: TaskKernelOmp5: maxOmpThreadCount smaller than blockThreadCount requested by caller:" <<
                        maxOmpThreadCount << " < " << blockThreadExtent.prod() << std::endl;
#endif
                // make sure there is at least on team
                TIdx const teamCount(std::max(std::min(static_cast<TIdx>(maxOmpThreadCount/blockThreadCount), gridBlockCount), static_cast<TIdx>(1u)));
#if ALPAKA_DEBUG >= ALPAKA_DEBUG_FULL
                std::cout << "threadElemCount=" << threadElemExtent[0u] << std::endl;
                std::cout << "teamCount=" << teamCount << "\tgridBlockCount=" << gridBlockCount << std::endl;
#endif

                if(::omp_in_parallel() != 0)
                {
                    throw std::runtime_error("The OpenMP 5.0 backend can not be used within an existing parallel region!");
                }

                // Force the environment to use the given number of threads.
                int const ompIsDynamic(::omp_get_dynamic());
                ::omp_set_dynamic(0);

                // `When an if(scalar-expression) evaluates to false, the structured block is executed on the host.`
                auto argsD = m_args;
                auto kernelFnObj = m_kernelFnObj;
                const auto iDevice = dev.iDevice();
                #pragma omp target device(iDevice)
                {
                    #pragma omp teams num_teams(teamCount) //thread_limit(blockThreadCount)
                    {
#if ALPAKA_DEBUG >= ALPAKA_DEBUG_MINIMAL
                        // The first team does some checks ...
                        if((::omp_get_team_num() == 0))
                        {
                            int const iNumTeams(::omp_get_num_teams());
                            printf("%s omp_get_num_teams: %d\n", __func__, iNumTeams);
                        }
                        printf("threadElemCount_dev %d\n", int(threadElemExtent[0u]));
#endif
                        // iterate over groups of teams to stay withing thread limit
                        for(TIdx t = 0u; t < gridBlockCount; t+=teamCount)
                        {
                            acc::AccOmp5<TDim, TIdx> acc(
                                gridBlockExtent,
                                blockThreadExtent,
                                threadElemExtent,
                                t,
                                blockSharedMemDynSizeBytes);

                            // printf("acc->threadElemCount %d\n"
                            //         , int(acc.m_threadElemExtent[0]));

                            const TIdx bsup = std::min(static_cast<TIdx>(t + teamCount), gridBlockCount);
                            #pragma omp distribute
                            for(TIdx b = t; b<bsup; ++b)
                            {
                                vec::Vec<dim::DimInt<1u>, TIdx> const gridBlockIdx(b);
                                // When this is not repeated here:
                                // error: gridBlockExtent referenced in target region does not have a mappable type
                                auto const gridBlockExtent2(
                                    workdiv::getWorkDiv<Grid, Blocks>(*static_cast<workdiv::WorkDivMembers<TDim, TIdx> const *>(this)));
                                acc.m_gridBlockIdx = idx::mapIdx<TDim::value>(
                                    gridBlockIdx,
                                    gridBlockExtent2);

                                // Execute the threads in parallel.

                                // Parallel execution of the threads in a block is required because when syncBlockThreads is called all of them have to be done with their work up to this line.
                                // So we have to spawn one OS thread per thread in a block.
                                // 'omp for' is not useful because it is meant for cases where multiple iterations are executed by one thread but in our case a 1:1 mapping is required.
                                // Therefore we use 'omp parallel' with the specified number of threads in a block.
#ifndef __ibmxl_vrm__
                                // setting num_threads to any value leads XL to run only one thread per team
                                #pragma omp parallel num_threads(blockThreadCount)
#else
                                #pragma omp parallel
#endif
                                {
#if ALPAKA_DEBUG >= ALPAKA_DEBUG_MINIMAL
                                    // The first thread does some checks in the first block executed.
                                    if((::omp_get_thread_num() == 0) && (b == 0))
                                    {
                                        int const numThreads(::omp_get_num_threads());
                                        printf("%s omp_get_num_threads: %d\n", __func__, numThreads);
                                        if(numThreads != static_cast<int>(blockThreadCount))
                                        {
                                            printf("ERROR: The OpenMP runtime did not use the number of threads that had been requested!\n");
                                        }
                                    }
#endif
                                    meta::apply(
                                        [kernelFnObj, &acc](typename std::decay<TArgs>::type const & ... args)
                                        {
                                            kernelFnObj(
                                                    acc,
                                                    args...);
                                        },
                                        argsD);

                                    // Wait for all threads to finish before deleting the shared memory.
                                    // This is done by default if the omp 'nowait' clause is missing
                                    //block::sync::syncBlockThreads(acc);
                                }

                                // After a block has been processed, the shared memory has to be deleted.
                                block::shared::st::freeMem(acc);
                            }
                        }
                    }
                }

                // Reset the dynamic thread number setting.
                ::omp_set_dynamic(ompIsDynamic);
            }

        private:
            TKernelFnObj m_kernelFnObj;
            std::tuple<std::decay_t<TArgs>...> m_args;
        };
    }

    namespace acc
    {
        namespace traits
        {
            //#############################################################################
            //! The OpenMP 5.0 execution task accelerator type trait specialization.
            template<
                typename TDim,
                typename TIdx,
                typename TKernelFnObj,
                typename... TArgs>
            struct AccType<
                kernel::TaskKernelOmp5<TDim, TIdx, TKernelFnObj, TArgs...>>
            {
                using type = acc::AccOmp5<TDim, TIdx>;
            };
        }
    }
    namespace dev
    {
        namespace traits
        {
            //#############################################################################
            //! The OpenMP 5.0 execution task device type trait specialization.
            template<
                typename TDim,
                typename TIdx,
                typename TKernelFnObj,
                typename... TArgs>
            struct DevType<
                kernel::TaskKernelOmp5<TDim, TIdx, TKernelFnObj, TArgs...>>
            {
                using type = dev::DevOmp5;
            };
        }
    }
    namespace dim
    {
        namespace traits
        {
            //#############################################################################
            //! The OpenMP 5.0 execution task dimension getter trait specialization.
            template<
                typename TDim,
                typename TIdx,
                typename TKernelFnObj,
                typename... TArgs>
            struct DimType<
                kernel::TaskKernelOmp5<TDim, TIdx, TKernelFnObj, TArgs...>>
            {
                using type = TDim;
            };
        }
    }
    namespace pltf
    {
        namespace traits
        {
            //#############################################################################
            //! The OpenMP 5.0 execution task platform type trait specialization.
            template<
                typename TDim,
                typename TIdx,
                typename TKernelFnObj,
                typename... TArgs>
            struct PltfType<
                kernel::TaskKernelOmp5<TDim, TIdx, TKernelFnObj, TArgs...>>
            {
                using type = pltf::PltfOmp5;
            };
        }
    }
    namespace idx
    {
        namespace traits
        {
            //#############################################################################
            //! The OpenMP 5.0 execution task idx type trait specialization.
            template<
                typename TDim,
                typename TIdx,
                typename TKernelFnObj,
                typename... TArgs>
            struct IdxType<
                kernel::TaskKernelOmp5<TDim, TIdx, TKernelFnObj, TArgs...>>
            {
                using type = TIdx;
            };
        }
    }

    namespace queue
    {
        namespace traits
        {
            template<
                typename TDim,
                typename TIdx,
                typename TKernelFnObj,
                typename... TArgs>
            struct Enqueue<
                queue::QueueOmp5Blocking,
                kernel::TaskKernelOmp5<TDim, TIdx, TKernelFnObj, TArgs...> >
            {
                ALPAKA_FN_HOST static auto enqueue(
                    queue::QueueOmp5Blocking& queue,
                    kernel::TaskKernelOmp5<TDim, TIdx, TKernelFnObj, TArgs...> const & task)
                -> void
                {
                    std::lock_guard<std::mutex> lk(queue.m_spQueueImpl->m_mutex);

                    queue.m_spQueueImpl->m_bCurrentlyExecutingTask = true;

                    task(
                            queue.m_spQueueImpl->m_dev
                        );

                    queue.m_spQueueImpl->m_bCurrentlyExecutingTask = false;
                }
            };

            template<
                typename TDim,
                typename TIdx,
                typename TKernelFnObj,
                typename... TArgs>
            struct Enqueue<
                queue::QueueOmp5NonBlocking,
                kernel::TaskKernelOmp5<TDim, TIdx, TKernelFnObj, TArgs...> >
            {
                //-----------------------------------------------------------------------------
                ALPAKA_FN_HOST static auto enqueue(
                    queue::QueueOmp5NonBlocking& queue,
                    kernel::TaskKernelOmp5<TDim, TIdx, TKernelFnObj, TArgs...> const & task)
                -> void
                {
                    queue.m_spQueueImpl->m_workerThread.enqueueTask(
                        [&queue, task]()
                        {
                            task(
                                    queue.m_spQueueImpl->m_dev
                                );
                        });
                }
            };
        }
    }
}

#endif
<|endoftext|>


<commit_before>/*******************************************************************************
 * include/construction/building_blocks.hpp
 *
 * Copyright (C) 2018 Marvin Löbel <loebel.marvin@gmail.com>
 *
 * All rights reserved. Published under the BSD-2 license in the LICENSE file.
 ******************************************************************************/

#pragma once

template <typename level_bv_t, typename loop_body_t>
inline void write_bits_wordwise(uint64_t start,
                                uint64_t size,
                                level_bv_t const& level_bv,
                                loop_body_t body) {
  uint64_t cur_pos = start;
  for (; cur_pos + 64 <= size; cur_pos += 64) {
    uint64_t word = 0ULL;
    for (uint64_t i = 0; i < 64; ++i) {
      uint64_t const bit = body(cur_pos + i);
      word <<= 1;
      word |= bit;
    }
    level_bv[cur_pos >> 6] = word;
  }
  if (size & 63ULL) {
    uint64_t word = 0ULL;
    for (uint64_t i = cur_pos; i < size; ++i) {
      uint64_t const bit = body(i);
      word <<= 1;
      word |= bit;
    }
    word <<= (64 - (size & 63ULL));
    level_bv[size >> 6] = word;
  }
}

template <typename text_t, typename ctx_t, typename bv_t>
inline void
scan_text_compute_first_level_bv_and_last_level_hist(text_t const& text,
                                                     size_t const size,
                                                     uint64_t const levels,
                                                     bv_t& bv,
                                                     ctx_t& ctx) {
  auto&& hist = ctx.hist_at_level(levels);
  write_bits_wordwise(0, size, bv[0], [&](uint64_t i) {
    ++hist[text[i]];
    uint64_t const bit = ((text[i] >> (levels - 1)) & 1ULL);
    return bit;
  });
}

template <typename ctx_t>
inline void bottom_up_compute_hist_and_borders_and_optional_zeros(
    uint64_t const size, uint64_t const levels, ctx_t& ctx) {
  for (uint64_t level = levels - 1; level > 0; --level) {
    auto&& hist = ctx.hist_at_level(level);
    auto&& next_hist = ctx.hist_at_level(level + 1);
    auto&& borders = ctx.borders_at_level(level);

    for (uint64_t pos = 0; pos < ctx.hist_size(level); ++pos) {
      hist[pos] = next_hist[pos << 1] + next_hist[(pos << 1) + 1];
    }

    borders[0] = 0;
    for (uint64_t pos = 1; pos < ctx.hist_size(level); ++pos) {
      auto const prev_rho = ctx.rho(level, pos - 1);

      borders[ctx.rho(level, pos)] = borders[prev_rho] + hist[prev_rho];
    }

    // The number of 0s is the position of the first 1 in the previous level
    if constexpr (ctx_t::compute_zeros) {
      ctx.zeros()[level - 1] = borders[1];
    }
  }
  ctx.hist_at_level(0)[0] = size;
}

template <typename ctx_t>
inline void compute_borders_and_optional_zeros_and_optional_rho(uint64_t level,
                                                                uint64_t blocks,
                                                                ctx_t& ctx) {
  auto&& borders = ctx.borders_at_level(level);
  auto&& hist = ctx.hist_at_level(level);

  // Compute the starting positions of characters with respect to their
  // bit prefixes and the bit-reversal permutation
  borders[0] = 0;
  for (uint64_t i = 1; i < blocks; ++i) {
    auto const prev_block = ctx.rho(level, i - 1);
    auto const this_block = ctx.rho(level, i);

    borders[this_block] = borders[prev_block] + hist[prev_block];
    // NB: The above calulcation produces _wrong_ border offsets
    // for huffman codes that are one-shorter than the current level.
    //
    // Since those codes will not be used in the loop below, this does not
    // produce wrong or out-of-bound accesses.

    if (ctx_t::compute_rho) {
      ctx.set_rho(level - 1, i - 1, prev_block >> 1);
    }
  }

  if (ctx_t::compute_zeros) {
    // If we compute zeros, we are working on a WM instead of a WT.
    // For a WM, borders is permuted with rho such that
    // borders[1] contains the position of the first 1-bit block.
    ctx.zeros()[level - 1] = borders[1];
  }
}
<commit_msg>optimize write_bits_wordwise<commit_after>/*******************************************************************************
 * include/construction/building_blocks.hpp
 *
 * Copyright (C) 2018 Marvin Löbel <loebel.marvin@gmail.com>
 *
 * All rights reserved. Published under the BSD-2 license in the LICENSE file.
 ******************************************************************************/

#pragma once

#include <omp.h>

#include "arrays/span.hpp"

// NB: This formulation as an inline-always function
// has been roghly tested to produce the least amount of machine code if
// used from `write_bits_wordwise()`.
template <typename level_bv_t, typename loop_body_t>
inline __attribute__((always_inline)) void
write_bits_word(uint64_t const start,
                uint64_t const size,
                level_bv_t const& level_bv,
                loop_body_t body) {
  DCHECK(size <= 64);
  uint64_t word = 0ULL;
  for (uint64_t i = 0; i < size; ++i) {
    uint64_t const bit = body(start + i);
    word <<= 1;
    word |= bit;
  }

  // NB. This gets optimized out if size is a constant 64
  word <<= (64 - size);

  level_bv[start >> 6] = word;
}

template <typename level_bv_t, typename loop_body_t>
inline void write_bits_wordwise(uint64_t start,
                                uint64_t size,
                                level_bv_t const& level_bv,
                                loop_body_t body) {
  for (uint64_t cur_pos = start; cur_pos + 64 <= size; cur_pos += 64) {
    write_bits_word(cur_pos, 64, level_bv, body);
  }
  uint64_t const remainder = size & 63ULL;
  if (remainder) {
    write_bits_word(size - remainder, remainder, level_bv, body);
  }
}

template <typename level_bv_t, typename loop_body_t>
inline void omp_write_bits_wordwise(uint64_t start,
                                    uint64_t size,
                                    level_bv_t const& level_bv,
                                    loop_body_t body) {
  const auto omp_rank = omp_get_thread_num();
  const auto omp_size = omp_get_num_threads();

  #pragma omp for
  for (int64_t scur_pos = start; scur_pos <= (int64_t(size) - 64);
       scur_pos += 64) {
    DCHECK(scur_pos >= 0);
    write_bits_word(scur_pos, 64, level_bv, body);
  }
  uint64_t const remainder = size & 63ULL;
  if (remainder && ((omp_rank + 1) == omp_size)) {
    write_bits_word(size - remainder, remainder, level_bv, body);
  }
}

template <typename text_t, typename ctx_t, typename bv_t>
inline void
scan_text_compute_first_level_bv_and_last_level_hist(text_t const& text,
                                                     size_t const size,
                                                     uint64_t const levels,
                                                     bv_t& bv,
                                                     ctx_t& ctx) {
  auto&& hist = ctx.hist_at_level(levels);
  write_bits_wordwise(0, size, bv[0], [&](uint64_t i) {
    ++hist[text[i]];
    uint64_t const bit = ((text[i] >> (levels - 1)) & 1ULL);
    return bit;
  });
}

template <typename ctx_t>
inline void bottom_up_compute_hist_and_borders_and_optional_zeros(
    uint64_t const size, uint64_t const levels, ctx_t& ctx) {
  for (uint64_t level = levels - 1; level > 0; --level) {
    auto&& hist = ctx.hist_at_level(level);
    auto&& next_hist = ctx.hist_at_level(level + 1);
    auto&& borders = ctx.borders_at_level(level);

    for (uint64_t pos = 0; pos < ctx.hist_size(level); ++pos) {
      hist[pos] = next_hist[pos << 1] + next_hist[(pos << 1) + 1];
    }

    borders[0] = 0;
    for (uint64_t pos = 1; pos < ctx.hist_size(level); ++pos) {
      auto const prev_rho = ctx.rho(level, pos - 1);

      borders[ctx.rho(level, pos)] = borders[prev_rho] + hist[prev_rho];
    }

    // The number of 0s is the position of the first 1 in the previous level
    if constexpr (ctx_t::compute_zeros) {
      ctx.zeros()[level - 1] = borders[1];
    }
  }
  ctx.hist_at_level(0)[0] = size;
}

template <typename ctx_t>
inline void compute_borders_and_optional_zeros_and_optional_rho(uint64_t level,
                                                                uint64_t blocks,
                                                                ctx_t& ctx) {
  auto&& borders = ctx.borders_at_level(level);
  auto&& hist = ctx.hist_at_level(level);

  // Compute the starting positions of characters with respect to their
  // bit prefixes and the bit-reversal permutation
  borders[0] = 0;
  for (uint64_t i = 1; i < blocks; ++i) {
    auto const prev_block = ctx.rho(level, i - 1);
    auto const this_block = ctx.rho(level, i);

    borders[this_block] = borders[prev_block] + hist[prev_block];
    // NB: The above calulcation produces _wrong_ border offsets
    // for huffman codes that are one-shorter than the current level.
    //
    // Since those codes will not be used in the loop below, this does not
    // produce wrong or out-of-bound accesses.

    if (ctx_t::compute_rho) {
      ctx.set_rho(level - 1, i - 1, prev_block >> 1);
    }
  }

  if (ctx_t::compute_zeros) {
    // If we compute zeros, we are working on a WM instead of a WT.
    // For a WM, borders is permuted with rho such that
    // borders[1] contains the position of the first 1-bit block.
    ctx.zeros()[level - 1] = borders[1];
  }
}
<|endoftext|>


<commit_before>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2015 Francois Beaune, The appleseedhq Organization
//
// 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.
//

// Interface header.
#include "orthographiccamera.h"

// appleseed.renderer headers.
#include "renderer/global/globallogger.h"
#include "renderer/global/globaltypes.h"
#include "renderer/kernel/shading/shadingray.h"
#include "renderer/modeling/camera/camera.h"
#include "renderer/modeling/frame/frame.h"
#include "renderer/modeling/project/project.h"
#include "renderer/utility/transformsequence.h"

// appleseed.foundation headers.
#include "foundation/image/canvasproperties.h"
#include "foundation/image/image.h"
#include "foundation/math/intersection/planesegment.h"
#include "foundation/math/dual.h"
#include "foundation/math/matrix.h"
#include "foundation/math/transform.h"
#include "foundation/math/vector.h"
#include "foundation/platform/compiler.h"
#include "foundation/utility/containers/specializedarrays.h"
#include "foundation/utility/autoreleaseptr.h"

// Standard headers.
#include <cstddef>

// Forward declarations.
namespace foundation    { class IAbortSwitch; }

using namespace foundation;
using namespace std;

namespace renderer
{

namespace
{
    //
    // Orthographic camera.
    //

    const char* Model = "orthographic_camera";

    class OrthographicCamera
      : public Camera
    {
      public:
        OrthographicCamera(
            const char*         name,
            const ParamArray&   params)
          : Camera(name, params)
        {
        }

        virtual void release() APPLESEED_OVERRIDE
        {
            delete this;
        }

        virtual const char* get_model() const APPLESEED_OVERRIDE
        {
            return Model;
        }

        virtual bool on_frame_begin(
            const Project&      project,
            IAbortSwitch*       abort_switch) APPLESEED_OVERRIDE
        {
            if (!Camera::on_frame_begin(project, abort_switch))
                return false;

            // Extract the film dimensions from the camera parameters.
            m_film_dimensions = extract_film_dimensions();

            // Extract the abscissa of the near plane from the camera parameters.
            m_near_z = extract_near_z();

            // Precompute reciprocals of film dimensions.
            m_rcp_film_width = 1.0 / m_film_dimensions[0];
            m_rcp_film_height = 1.0 / m_film_dimensions[1];

            // Precompute pixel area.
            const size_t pixel_count = project.get_frame()->image().properties().m_pixel_count;
            m_rcp_pixel_area = pixel_count / (m_film_dimensions[0] * m_film_dimensions[1]);

            print_settings();

            return true;
        }

        virtual void spawn_ray(
            SamplingContext&    sampling_context,
            const Dual2d&       ndc,
            ShadingRay&         ray) const APPLESEED_OVERRIDE
        {
            // Initialize the ray.
            initialize_ray(sampling_context, ray);

            // Retrieve the camera transform.
            Transformd tmp;
            const Transformd& transform =
                m_transform_sequence.evaluate(ray.m_time.m_absolute, tmp);

            // Compute ray origin and direction.
            ray.m_org = transform.point_to_parent(ndc_to_camera(ndc.get_value()));
            ray.m_dir = normalize(transform.vector_to_parent(Vector3d(0.0, 0.0, -1.0)));

            // Compute ray derivatives.
            if (ndc.has_derivatives())
            {
                const Vector2d px(ndc.get_value() + ndc.get_dx());
                const Vector2d py(ndc.get_value() + ndc.get_dy());

                ray.m_rx.m_org = transform.point_to_parent(ndc_to_camera(px));
                ray.m_ry.m_org = transform.point_to_parent(ndc_to_camera(py));

                ray.m_rx.m_dir = ray.m_dir;
                ray.m_ry.m_dir = ray.m_dir;

                ray.m_has_differentials = true;
            }
        }

        virtual bool connect_vertex(
            SamplingContext&    sampling_context,
            const double        time,
            const Vector3d&     point,
            Vector2d&           ndc,
            Vector3d&           outgoing,
            double&             importance) const APPLESEED_OVERRIDE
        {
            // Retrieve the camera transform.
            Transformd tmp;
            const Transformd& transform = m_transform_sequence.evaluate(time, tmp);

            // Transform the input point to camera space.
            const Vector3d p = transform.point_to_local(point);

            // Compute the normalized device coordinates of the film point.
            ndc[0] = 0.5 + p[0];
            ndc[1] = 0.5 - p[1];

            // The connection is impossible if the projected point lies outside the film.
            if (ndc[0] < 0.0 || ndc[0] >= 1.0 ||
                ndc[1] < 0.0 || ndc[1] >= 1.0)
                return false;

            // Compute the outgoing direction vector in world space.
            outgoing = transform.vector_to_parent(Vector3d(0.0, 0.0, p.z));

            // Compute the emitted importance.
            importance = m_rcp_pixel_area;

            // The connection was possible.
            return true;
        }

        virtual bool project_camera_space_point(
            const Vector3d&     point,
            Vector2d&           ndc) const APPLESEED_OVERRIDE
        {
            // Cannot project the point if it is behind the near plane.
            if (point.z > m_near_z)
                return false;

            // Project the point onto the film plane.
            ndc = camera_to_ndc(point);

            // Projection was successful.
            return true;
        }

        virtual bool project_segment(
            const double        time,
            const Vector3d&     a,
            const Vector3d&     b,
            Vector2d&           a_ndc,
            Vector2d&           b_ndc) const APPLESEED_OVERRIDE
        {
            // Retrieve the camera transform.
            Transformd tmp;
            const Transformd& transform = m_transform_sequence.evaluate(time, tmp);

            // Transform the segment to camera space.
            Vector3d local_a = transform.point_to_local(a);
            Vector3d local_b = transform.point_to_local(b);

            // Clip the segment against the near plane.
            if (!clip(Vector4d(0.0, 0.0, 1.0, -m_near_z), local_a, local_b))
                return false;

            // Project the segment onto the film plane.
            a_ndc = camera_to_ndc(local_a);
            b_ndc = camera_to_ndc(local_b);

            // Projection was successful.
            return true;
        }

      private:
        // Parameters.
        Vector2d    m_film_dimensions;      // film dimensions in camera space, in meters
        double      m_near_z;               // Z value of the near plane in camera space, in meters

        // Precomputed values.
        double      m_rcp_film_width;       // film width reciprocal in camera space
        double      m_rcp_film_height;      // film height reciprocal in camera space
        double      m_rcp_pixel_area;       // reciprocal of pixel area in camera space

        void print_settings() const
        {
            RENDERER_LOG_INFO(
                "camera settings:\n"
                "  model            %s\n"
                "  film width       %f\n"
                "  film height      %f\n"
                "  near z           %f\n"
                "  shutter open     %f\n"
                "  shutter close    %f",
                Model,
                m_film_dimensions[0],
                m_film_dimensions[1],
                m_near_z,
                m_shutter_open_time,
                m_shutter_close_time);
        }

        Vector3d ndc_to_camera(const Vector2d& point) const
        {
            return
                Vector3d(
                    (point.x - 0.5) * m_film_dimensions[0],
                    (0.5 - point.y) * m_film_dimensions[1],
                    0.0);
        }

        Vector2d camera_to_ndc(const Vector3d& point) const
        {
            return
                Vector2d(
                    0.5 + point.x * m_rcp_film_width,
                    0.5 - point.y * m_rcp_film_height);
        }
    };
}

//
// OrthographicCameraFactory class implementation.
//

const char* OrthographicCameraFactory::get_model() const
{
    return Model;
}

Dictionary OrthographicCameraFactory::get_model_metadata() const
{
    return
        Dictionary()
            .insert("name", Model)
            .insert("label", "Orthographic Camera");
}

DictionaryArray OrthographicCameraFactory::get_input_metadata() const
{
    DictionaryArray metadata = CameraFactory::get_input_metadata();

    metadata.push_back(
        Dictionary()
            .insert("name", "film_dimensions")
            .insert("label", "Film Dimensions")
            .insert("type", "text")
            .insert("use", "required"));

    metadata.push_back(
        Dictionary()
            .insert("name", "film_width")
            .insert("label", "Film Width")
            .insert("type", "text")
            .insert("use", "required"));

    metadata.push_back(
        Dictionary()
            .insert("name", "film_height")
            .insert("label", "Film Height")
            .insert("type", "text")
            .insert("use", "required"));

    metadata.push_back(
        Dictionary()
            .insert("name", "aspect_ratio")
            .insert("label", "Aspect Ratio")
            .insert("type", "text")
            .insert("use", "required"));

    metadata.push_back(
        Dictionary()
            .insert("name", "near_z")
            .insert("label", "Near Z")
            .insert("type", "text")
            .insert("use", "optional")
            .insert("default", "-0.001"));

    return metadata;
}

auto_release_ptr<Camera> OrthographicCameraFactory::create(
    const char*         name,
    const ParamArray&   params) const
{
    return auto_release_ptr<Camera>(new OrthographicCamera(name, params));
}

}   // namespace renderer
<commit_msg>Fix orthographic camera position<commit_after>
//
// This source file is part of appleseed.
// Visit http://appleseedhq.net/ for additional information and resources.
//
// This software is released under the MIT license.
//
// Copyright (c) 2015 Francois Beaune, The appleseedhq Organization
//
// 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.
//

// Interface header.
#include "orthographiccamera.h"

// appleseed.renderer headers.
#include "renderer/global/globallogger.h"
#include "renderer/global/globaltypes.h"
#include "renderer/kernel/shading/shadingray.h"
#include "renderer/modeling/camera/camera.h"
#include "renderer/modeling/frame/frame.h"
#include "renderer/modeling/project/project.h"
#include "renderer/modeling/scene/scene.h"
#include "renderer/utility/transformsequence.h"

// appleseed.foundation headers.
#include "foundation/image/canvasproperties.h"
#include "foundation/image/image.h"
#include "foundation/math/intersection/planesegment.h"
#include "foundation/math/dual.h"
#include "foundation/math/matrix.h"
#include "foundation/math/transform.h"
#include "foundation/math/vector.h"
#include "foundation/platform/compiler.h"
#include "foundation/utility/containers/specializedarrays.h"
#include "foundation/utility/autoreleaseptr.h"

// Standard headers.
#include <cstddef>

// Forward declarations.
namespace foundation    { class IAbortSwitch; }

using namespace foundation;
using namespace std;

namespace renderer
{

namespace
{
    //
    // Orthographic camera.
    //

    const char* Model = "orthographic_camera";

    class OrthographicCamera
      : public Camera
    {
      public:
        OrthographicCamera(
            const char*         name,
            const ParamArray&   params)
          : Camera(name, params)
        {
        }

        virtual void release() APPLESEED_OVERRIDE
        {
            delete this;
        }

        virtual const char* get_model() const APPLESEED_OVERRIDE
        {
            return Model;
        }

        virtual bool on_frame_begin(
            const Project&      project,
            IAbortSwitch*       abort_switch) APPLESEED_OVERRIDE
        {
            if (!Camera::on_frame_begin(project, abort_switch))
                return false;

            // Extract the film dimensions from the camera parameters.
            m_film_dimensions = extract_film_dimensions();

            // Extract the abscissa of the near plane from the camera parameters.
            m_near_z = extract_near_z();

            // Retrieve the scene diameter that will be used to position the camera.
            const Scene::CachedInfo* scene_info = project.get_scene()->get_cached_info();
            assert(scene_info);
            m_safe_scene_diameter = scene_info->m_safe_diameter;

            // Precompute reciprocals of film dimensions.
            m_rcp_film_width = 1.0 / m_film_dimensions[0];
            m_rcp_film_height = 1.0 / m_film_dimensions[1];

            // Precompute pixel area.
            const size_t pixel_count = project.get_frame()->image().properties().m_pixel_count;
            m_rcp_pixel_area = pixel_count / (m_film_dimensions[0] * m_film_dimensions[1]);

            print_settings();

            return true;
        }

        virtual void spawn_ray(
            SamplingContext&    sampling_context,
            const Dual2d&       ndc,
            ShadingRay&         ray) const APPLESEED_OVERRIDE
        {
            // Initialize the ray.
            initialize_ray(sampling_context, ray);

            // Retrieve the camera transform.
            Transformd tmp;
            const Transformd& transform =
                m_transform_sequence.evaluate(ray.m_time.m_absolute, tmp);

            // Compute ray origin and direction.
            ray.m_org = transform.point_to_parent(ndc_to_camera(ndc.get_value()));
            ray.m_dir = normalize(transform.vector_to_parent(Vector3d(0.0, 0.0, -1.0)));

            // Compute ray derivatives.
            if (ndc.has_derivatives())
            {
                const Vector2d px(ndc.get_value() + ndc.get_dx());
                const Vector2d py(ndc.get_value() + ndc.get_dy());

                ray.m_rx.m_org = transform.point_to_parent(ndc_to_camera(px));
                ray.m_ry.m_org = transform.point_to_parent(ndc_to_camera(py));

                ray.m_rx.m_dir = ray.m_dir;
                ray.m_ry.m_dir = ray.m_dir;

                ray.m_has_differentials = true;
            }
        }

        virtual bool connect_vertex(
            SamplingContext&    sampling_context,
            const double        time,
            const Vector3d&     point,
            Vector2d&           ndc,
            Vector3d&           outgoing,
            double&             importance) const APPLESEED_OVERRIDE
        {
            // Retrieve the camera transform.
            Transformd tmp;
            const Transformd& transform = m_transform_sequence.evaluate(time, tmp);

            // Transform the input point to camera space.
            const Vector3d p = transform.point_to_local(point);

            // Compute the normalized device coordinates of the film point.
            ndc[0] = 0.5 + p[0];
            ndc[1] = 0.5 - p[1];

            // The connection is impossible if the projected point lies outside the film.
            if (ndc[0] < 0.0 || ndc[0] >= 1.0 ||
                ndc[1] < 0.0 || ndc[1] >= 1.0)
                return false;

            // Compute the outgoing direction vector in world space.
            outgoing = transform.vector_to_parent(Vector3d(0.0, 0.0, p.z));

            // Compute the emitted importance.
            importance = m_rcp_pixel_area;

            // The connection was possible.
            return true;
        }

        virtual bool project_camera_space_point(
            const Vector3d&     point,
            Vector2d&           ndc) const APPLESEED_OVERRIDE
        {
            // Cannot project the point if it is behind the near plane.
            if (point.z > m_near_z)
                return false;

            // Project the point onto the film plane.
            ndc = camera_to_ndc(point);

            // Projection was successful.
            return true;
        }

        virtual bool project_segment(
            const double        time,
            const Vector3d&     a,
            const Vector3d&     b,
            Vector2d&           a_ndc,
            Vector2d&           b_ndc) const APPLESEED_OVERRIDE
        {
            // Retrieve the camera transform.
            Transformd tmp;
            const Transformd& transform = m_transform_sequence.evaluate(time, tmp);

            // Transform the segment to camera space.
            Vector3d local_a = transform.point_to_local(a);
            Vector3d local_b = transform.point_to_local(b);

            // Clip the segment against the near plane.
            if (!clip(Vector4d(0.0, 0.0, 1.0, -m_near_z), local_a, local_b))
                return false;

            // Project the segment onto the film plane.
            a_ndc = camera_to_ndc(local_a);
            b_ndc = camera_to_ndc(local_b);

            // Projection was successful.
            return true;
        }

      private:
        // Parameters.
        Vector2d    m_film_dimensions;      // film dimensions in camera space, in meters
        double      m_near_z;               // Z value of the near plane in camera space, in meters

        // Precomputed values.
        double      m_safe_scene_diameter;  // scene diameter plus a safety margin
        double      m_rcp_film_width;       // film width reciprocal in camera space
        double      m_rcp_film_height;      // film height reciprocal in camera space
        double      m_rcp_pixel_area;       // reciprocal of pixel area in camera space

        void print_settings() const
        {
            RENDERER_LOG_INFO(
                "camera settings:\n"
                "  model            %s\n"
                "  film width       %f\n"
                "  film height      %f\n"
                "  near z           %f\n"
                "  shutter open     %f\n"
                "  shutter close    %f",
                Model,
                m_film_dimensions[0],
                m_film_dimensions[1],
                m_near_z,
                m_shutter_open_time,
                m_shutter_close_time);
        }

        Vector3d ndc_to_camera(const Vector2d& point) const
        {
            return
                Vector3d(
                    (point.x - 0.5) * m_film_dimensions[0],
                    (0.5 - point.y) * m_film_dimensions[1],
                    m_safe_scene_diameter);
        }

        Vector2d camera_to_ndc(const Vector3d& point) const
        {
            return
                Vector2d(
                    0.5 + point.x * m_rcp_film_width,
                    0.5 - point.y * m_rcp_film_height);
        }
    };
}

//
// OrthographicCameraFactory class implementation.
//

const char* OrthographicCameraFactory::get_model() const
{
    return Model;
}

Dictionary OrthographicCameraFactory::get_model_metadata() const
{
    return
        Dictionary()
            .insert("name", Model)
            .insert("label", "Orthographic Camera");
}

DictionaryArray OrthographicCameraFactory::get_input_metadata() const
{
    DictionaryArray metadata = CameraFactory::get_input_metadata();

    metadata.push_back(
        Dictionary()
            .insert("name", "film_dimensions")
            .insert("label", "Film Dimensions")
            .insert("type", "text")
            .insert("use", "required"));

    metadata.push_back(
        Dictionary()
            .insert("name", "film_width")
            .insert("label", "Film Width")
            .insert("type", "text")
            .insert("use", "required"));

    metadata.push_back(
        Dictionary()
            .insert("name", "film_height")
            .insert("label", "Film Height")
            .insert("type", "text")
            .insert("use", "required"));

    metadata.push_back(
        Dictionary()
            .insert("name", "aspect_ratio")
            .insert("label", "Aspect Ratio")
            .insert("type", "text")
            .insert("use", "required"));

    metadata.push_back(
        Dictionary()
            .insert("name", "near_z")
            .insert("label", "Near Z")
            .insert("type", "text")
            .insert("use", "optional")
            .insert("default", "-0.001"));

    return metadata;
}

auto_release_ptr<Camera> OrthographicCameraFactory::create(
    const char*         name,
    const ParamArray&   params) const
{
    return auto_release_ptr<Camera>(new OrthographicCamera(name, params));
}

}   // namespace renderer
<|endoftext|>


<commit_before>//最长公共子序列
//longest_common_subsequence.cpp

//求两长度相同的序列s1，s2的最长公共子序列的长度
//子序列中相邻的两个成员在原序列中可以是不相邻的，但在原序列中的相对顺序不变

//子序列中相邻的两个成员在原序列中可以是不相邻的，但在原序列中的相对顺序不变
//这意味着可以出现这样的情况，对于序列s1(1, 2, 3, 4, 5)和s2(1, 4, 0, 2, 3)
//它们的最长公共子序列是(1, 4)，其中成员1和4在原序列s1中不相邻，但相对顺序不变
//
//设置f[i][j]表示s1中前i个元素，s2中前j个元素的最长公共子列长度
//本章中的所有动态规划在解题时都会使用f数组来存储决策结果
//状态转移方程：
//f[i][j] =	| 0								 i == 0 || j == 0
//			| f[i - 1][j - 1] + 1			 i > 0 && j > 0 && s1[i] == s2[j]
//			| max(f[i][j - 1], f[i - 1][j])	 i > 0 && j > 0 && s1[i] != s2[j]
//初始条件：f[i][0]和f[0][i]为0，0 <= i <= n
//
//本章中使用数组的方式与其他章节不太一样
//一般情况下我会将一个数组长度设为n，其中成员设为从0到n-1
//但在本章的所有算法中，数组的长度都被设置为n+1，成员都是从1到n，而把0空出来
//这是为了给状态转移方程中的初始状态留出一个位置，请留意这个细节
//本章的所有算法都会这样处理数组，以后不再特别说明

#include "general_head.h"

int longest_common_subsequence(int *s1, int *s2, int n)
{//序列s1，s2的长度都为n+1，下标从1到n，空出0位置
 //返回s1，s2的最长公共子序列的长度
	int f[MAX + 1][MAX + 1];
	for(int i = 0; i <= n; ++ i)
		f[0][i] = 0, f[i][0] = 0;
	for(int i = 1; i <= n; ++ i)
		for(int j = 1; j <= n; ++ j){
			if(s1[i] == s2[j])
				f[i][j] = f[i - 1][j - 1] + 1;
			else
				f[i][j] = max(f[i][j - 1], f[i - 1][j]);
		}
	return(f[n][n]);
}

<commit_msg>Update 1_longest_common_subsequence.cpp<commit_after>//最长公共子序列
//longest_common_subsequence.cpp

//求两长度相同的序列s1，s2的最长公共子序列的长度
//子序列中相邻的两个成员在原序列中可以是不相邻的，但在原序列中的相对顺序不变

//子序列中相邻的两个成员在原序列中可以是不相邻的，但在原序列中的相对顺序不变
//这意味着可以出现这样的情况，对于序列s1(1, 2, 3, 4, 5)和s2(1, 4, 0, 7, 8)
//它们的最长公共子序列是(1, 4)，其中成员1和4在原序列s1中不相邻，但相对顺序不变
//
//设置f[i][j]表示s1中前i个元素，s2中前j个元素的最长公共子列长度
//本章中的所有动态规划在解题时都会使用f数组来存储决策结果
//状态转移方程：
//f[i][j] =	| 0								 i == 0 || j == 0
//			| f[i - 1][j - 1] + 1			 i > 0 && j > 0 && s1[i] == s2[j]
//			| max(f[i][j - 1], f[i - 1][j])	 i > 0 && j > 0 && s1[i] != s2[j]
//初始条件：f[i][0]和f[0][i]为0，0 <= i <= n
//
//本章中使用数组的方式与其他章节不太一样
//一般情况下我会将一个数组长度设为n，其中成员设为从0到n-1
//但在本章的所有算法中，数组的长度都被设置为n+1，成员都是从1到n，而把0空出来
//这是为了给状态转移方程中的初始状态留出一个位置，请留意这个细节
//本章的所有算法都会这样处理数组，以后不再特别说明

#include "general_head.h"

int longest_common_subsequence(int *s1, int *s2, int n)
{//序列s1，s2的长度都为n+1，下标从1到n，空出0位置
 //返回s1，s2的最长公共子序列的长度
	int f[MAX + 1][MAX + 1];
	for(int i = 0; i <= n; ++ i)
		f[0][i] = 0, f[i][0] = 0;
	for(int i = 1; i <= n; ++ i)
		for(int j = 1; j <= n; ++ j){
			if(s1[i] == s2[j])
				f[i][j] = f[i - 1][j - 1] + 1;
			else
				f[i][j] = max(f[i][j - 1], f[i - 1][j]);
		}
	return(f[n][n]);
}

<|endoftext|>


<commit_before><commit_msg>Call InitLogging() for courgette.<commit_after><|endoftext|>