<commit_before>#pragma once
//=====================================================================//
/*!	@file
	@brief	RX グループ・RSPI I/O 制御
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2016, 2020 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include "common/renesas.hpp"
#include "common/vect.h"

namespace device {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  RSPI 制御クラス
		@param[in]	RSPI	RSPI 定義クラス
		@param[in]	PSEL	ポート候補
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class RSPI, port_map::option PSEL = port_map::option::FIRST>
	class rspi_io {
	public:

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  データ、クロック位相タイプ型
					TYPE1(MODE0): CPOL:0 CPHA:0 @n
					TYPE2(MODE1): CPOL:0 CPHA:1 @n
					TYPE3(MODE2): CPOL:1 CPHA:0 @n
					TYPE4(MODE3): CPOL:1 CPHA:1
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		enum class PHASE : uint8_t {
			TYPE1,  ///< タイプ１
			TYPE2,  ///< タイプ２
			TYPE3,  ///< タイプ３
			TYPE4,  ///< タイプ４ (SD カードアクセス）
		};

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  データ長型
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		enum class DLEN : uint8_t {
			W8  = 0b0111,	///< 8 Bits
			W9  = 0b1000,	///< 9 Bits
			W10 = 0b1001,	///< 10 Bits
			W11 = 0b1010,	///< 11 Bits
			W12 = 0b1011,	///< 12 Bits
			W13 = 0b1100,	///< 13 Bits
			W14 = 0b1101,	///< 14 Bits
			W15 = 0b1110,	///< 15 Bits
			W16 = 0b1111,	///< 16 Bits
			W20 = 0b0000,	///< 20 Bits
			W24 = 0b0001,	///< 24 Bits
			W32 = 0b0011,	///< 32 Bits
		};

	private:

		uint8_t	level_;

		// 便宜上のスリープ
		void sleep_() { asm("nop"); }

		bool clock_div_(uint32_t speed, uint8_t& brdv, uint8_t& spbr) {
///			utils::format("PCLK: %d\n") % static_cast<uint32_t>(PCLK_);
			uint32_t br = static_cast<uint32_t>(RSPI::PCLK) / speed;
			uint8_t dv = 0;
			while(br > 512) {
				br >>= 1;
				++dv;
				if(dv > 3) {
					brdv = 3;
					spbr = 255;
					return false;
				}
			}
			brdv = dv;
			if(br & 1) {
				br >>= 1;
				++br;
			} else {
				br >>= 1;
			}
			if(br) --br;
			spbr = br;
			return true;
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
		*/
		//-----------------------------------------------------------------//
		rspi_io() noexcept : level_(0) { }

		//-----------------------------------------------------------------//
		/*!
			@brief  設定可能な最大速度を返す @n
					・RX24T: 20MHz @n
					・RX64M: 40MHz
			@return 最大速度
		*/
		//-----------------------------------------------------------------//
		uint32_t get_max_speed() const noexcept {
			uint32_t clk = RSPI::PCLK;
#ifdef SEEDA
			while(clk > 20000000) {  // 15MHz
//			while(clk > 10000000) {  // 7MHz
#else
			while(clk > 40000000) {
#endif
				clk >>= 1;
			}
			return clk;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  通信速度を設定して、CSI を有効にする
			@param[in]	speed	通信速度
			@param[in]	ctype	クロック位相タイプ
			@param[in]	dlen	データ長設定
			@param[in]	level	割り込みレベル（１～２）、０の場合はポーリング
			@return エラー（速度設定範囲外）なら「false」
		*/
		//-----------------------------------------------------------------//
		bool start(uint32_t speed, PHASE ctype, DLEN dlen, uint8_t level = 0) noexcept
		{
			level_ = level;

			power_mgr::turn(RSPI::PERIPHERAL);

			// デバイスを不許可
			RSPI::SPCR = 0x00;

			// ポートを有効にする
			port_map::turn(RSPI::PERIPHERAL, true, PSEL);

			bool f = true;
			uint8_t brdv;
			uint8_t spbr;
			if(!clock_div_(speed, brdv, spbr)) {
				f = false;
			}

			// 設定
		    RSPI::SPBR = spbr;

			RSPI::SPPCR = 0x00;	// Fixed idle value, disable loop-back
			RSPI::SPSCR = 0x00;	// disable sequence control
			RSPI::SPDCR = 0x20;	// SPLW=1 (long word access)
///			RSPI::SPCMD0 = RSPI::SPCMD0.LSBF.b() | RSPI::SPCMD0.BRDV.b(brdv) | RSPI::SPCMD0.SPB.b(0b0100);
			bool cpol = 0;
			bool cpha = 0;
			switch(ctype) {
			case PHASE::TYPE1:
				break;
			case PHASE::TYPE2:
				cpha = 1;
				break;
			case PHASE::TYPE3:
				cpol = 1;
				break;
			case PHASE::TYPE4:
				cpol = 1;
				cpha = 1;
				break;
			default:
				break;
			}
			RSPI::SPCMD0 = RSPI::SPCMD0.BRDV.b(brdv)
				| RSPI::SPCMD0.SPB.b(static_cast<uint8_t>(dlen))
				| RSPI::SPCMD0.CPOL.b(cpol) | RSPI::SPCMD0.CPHA.b(cpha);

			RSPI::SPCR.SPMS = 1;
			RSPI::SPCR.MSTR = 1;

			RSPI::SPCR.SPE = 1;

			return f;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  ＳＤカード用設定を有効にする
			@param[in]	speed	通信速度
			@return エラー（速度設定範囲外）なら「false」
		*/
		//-----------------------------------------------------------------//
		bool start_sdc(uint32_t speed) noexcept
		{
			level_ = 0;

			power_mgr::turn(RSPI::PERIPHERAL);

			RSPI::SPCR = 0x00;

			bool f = true;
			uint8_t brdv;
			uint8_t spbr;
			if(!clock_div_(speed, brdv, spbr)) {
				f = false;
			}
			port_map::turn(RSPI::PERIPHERAL, true, PSEL);
#if 0
			utils::format("RSPI Request Speed: %u [Hz]\n") % speed;
			utils::format("RSPI SPBR: %d\n") % static_cast<uint32_t>(spbr);
			utils::format("RSPI BRDV: %d\n") % static_cast<uint32_t>(brdv);
#endif
		    RSPI::SPBR = spbr;

			// 実際のクロックを表示
#if 0
			static const uint8_t n[4] = { 1, 2, 4, 8 };
			uint32_t z = static_cast<uint32_t>(PCLK_)
					/ (2 * static_cast<uint32_t>(spbr + 1) * static_cast<uint32_t>(n[brdv]));
			utils::format("RSPI Real Speed: %u [Hz]\n") % z;
#endif
			RSPI::SPPCR = 0x00;	// Fixed idle value, disable loop-back
			RSPI::SPSCR = 0x00;	// disable sequence control
			RSPI::SPDCR = 0x20;	// SPLW=1 (long word access)
			RSPI::SPCMD0 = RSPI::SPCMD0.BRDV.b(brdv) | RSPI::SPCMD0.SPB.b(0b0100);
///				| RSPI::SPCMD0.CPHA.b(0) | RSPI::SPCMD0.CPOL.b(1);

			RSPI::SPCR.SPMS = 1;
			RSPI::SPCR.MSTR = 1;

			RSPI::SPCR.SPE = 1;

			return f;
		}

		//----------------------------------------------------------------//
		/*!
			@brief	リード・ライト
			@param[in]	data	書き込みデータ
			@return 読み出しデータ
		*/
		//----------------------------------------------------------------//
		uint8_t xchg(uint8_t data = 0xff) noexcept
		{
			RSPI::SPDR = static_cast<uint32_t>(data);
			while(RSPI::SPSR.SPRF() == 0) sleep_();
		    return RSPI::SPDR();
		}

		//----------------------------------------------------------------//
		/*!
			@brief	通信レジスタへ書き込み @n
					※通信幅は最大３２ビット（通信モード設定による）
			@param[in]	data	書き込みデータ
		*/
		//----------------------------------------------------------------//
		inline void xchg32_start(uint32_t data = 0) noexcept
		{
			RSPI::SPDR = static_cast<uint32_t>(data);
		}

		//----------------------------------------------------------------//
		/*!
			@brief	通信の同期とレジスタからの読み出し @n
					※通信幅は最大３２ビット（通信モード設定による）
			@return	読み出しデータ
		*/
		//----------------------------------------------------------------//
		inline uint32_t xchg32_sync() noexcept
		{
			while(RSPI::SPSR.SPRF() == 0) sleep_();
		    return RSPI::SPDR();
		}

		//----------------------------------------------------------------//
		/*!
			@brief	リード・ライト
			@param[in]	data	書き込みデータ
			@return 読み出しデータ
		*/
		//----------------------------------------------------------------//
		inline uint32_t xchg32(uint32_t data = 0) noexcept
		{
			xchg32_start(data);
			return xchg32_sync();
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  シリアル送信
			@param[in]	src	送信ソース
			@param[in]	cnt	送信サイズ
		*/
		//-----------------------------------------------------------------//
		void send(const void* src, uint32_t size) noexcept
		{
			auto ptr = static_cast<const uint8_t*>(src);
			while(size > 0) {
				xchg(*ptr);
				++ptr;
				size--;
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  シリアル受信
			@param[out]	dst	受信先
			@param[in]	cnt	受信サイズ
		*/
		//-----------------------------------------------------------------//
		void recv(void* dst, uint32_t size) noexcept
		{
			auto ptr = static_cast<uint8_t*>(dst);
			while(size > 0) {
				*ptr = xchg();
				++ptr;
				size--;
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  RSPIを無効にして、パワーダウンする
			@param[in]	power パワーダウンをしない場合「false」
		*/
		//-----------------------------------------------------------------//
		void destroy(bool power = true) noexcept
		{
			RSPI::SPCR = 0x00;
			port_map::turn(RSPI::PERIPHERAL, false);
			if(power) power_mgr::turn(RSPI::PERIPHERAL, false);
		}
	};
}
<commit_msg>Update: cleanup<commit_after>#pragma once
//=====================================================================//
/*!	@file
	@brief	RX グループ・RSPI I/O 制御
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2016, 2020 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include "common/renesas.hpp"
#include "common/vect.h"

namespace device {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  RSPI 制御クラス
		@param[in]	RSPI	RSPI 定義クラス
		@param[in]	PSEL	ポート候補
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class RSPI, port_map::option PSEL = port_map::option::FIRST>
	class rspi_io {
	public:

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  データ、クロック位相タイプ型
					TYPE1(MODE0): CPOL:0 CPHA:0 @n
					TYPE2(MODE1): CPOL:0 CPHA:1 @n
					TYPE3(MODE2): CPOL:1 CPHA:0 @n
					TYPE4(MODE3): CPOL:1 CPHA:1
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		enum class PHASE : uint8_t {
			TYPE1,  ///< タイプ１
			TYPE2,  ///< タイプ２
			TYPE3,  ///< タイプ３
			TYPE4,  ///< タイプ４ (SD カードアクセス）
		};

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  データ長型
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		enum class DLEN : uint8_t {
			W8  = 0b0111,	///< 8 Bits
			W9  = 0b1000,	///< 9 Bits
			W10 = 0b1001,	///< 10 Bits
			W11 = 0b1010,	///< 11 Bits
			W12 = 0b1011,	///< 12 Bits
			W13 = 0b1100,	///< 13 Bits
			W14 = 0b1101,	///< 14 Bits
			W15 = 0b1110,	///< 15 Bits
			W16 = 0b1111,	///< 16 Bits
			W20 = 0b0000,	///< 20 Bits
			W24 = 0b0001,	///< 24 Bits
			W32 = 0b0011,	///< 32 Bits
		};

	private:

		uint8_t	level_;

		// 便宜上のスリープ
		void sleep_() { asm("nop"); }

		bool clock_div_(uint32_t speed, uint8_t& brdv, uint8_t& spbr) {
///			utils::format("PCLK: %d\n") % static_cast<uint32_t>(RSPI::PCLK);
			uint32_t br = static_cast<uint32_t>(RSPI::PCLK) / speed;
			uint8_t dv = 0;
			while(br > 512) {
				br >>= 1;
				++dv;
				if(dv > 3) {
					brdv = 3;
					spbr = 255;
					return false;
				}
			}
			brdv = dv;
			if(br & 1) {
				br >>= 1;
				++br;
			} else {
				br >>= 1;
			}
			if(br) --br;
			spbr = br;
			return true;
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
		*/
		//-----------------------------------------------------------------//
		rspi_io() noexcept : level_(0) { }

		//-----------------------------------------------------------------//
		/*!
			@brief  設定可能な最大速度を返す @n
					・RX24T: 20MHz @n
					・RX64M: 40MHz
			@return 最大速度
		*/
		//-----------------------------------------------------------------//
		uint32_t get_max_speed() const noexcept {
			uint32_t clk = RSPI::PCLK;
#ifdef SEEDA
			while(clk > 20000000) {  // 15MHz
//			while(clk > 10000000) {  // 7MHz
#else
			while(clk > 40000000) {
#endif
				clk >>= 1;
			}
			return clk;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  通信速度を設定して、CSI を有効にする
			@param[in]	speed	通信速度
			@param[in]	ctype	クロック位相タイプ
			@param[in]	dlen	データ長設定
			@param[in]	level	割り込みレベル、０の場合はポーリング
			@return エラー（速度設定範囲外）なら「false」
		*/
		//-----------------------------------------------------------------//
		bool start(uint32_t speed, PHASE ctype, DLEN dlen, uint8_t level = 0) noexcept
		{
			level_ = level;

			uint8_t brdv;
			uint8_t spbr;
			if(!clock_div_(speed, brdv, spbr)) {
				return false;
			}

			power_mgr::turn(RSPI::PERIPHERAL);

			// デバイスを不許可
			RSPI::SPCR = 0x00;

			// ポートを有効にする
			port_map::turn(RSPI::PERIPHERAL, true, PSEL);

			// 設定
		    RSPI::SPBR = spbr;

			RSPI::SPPCR = 0x00;	// Fixed idle value, disable loop-back
			RSPI::SPSCR = 0x00;	// disable sequence control
			RSPI::SPDCR = 0x20;	// SPLW=1 (long word access)

			bool cpol = 0;
			bool cpha = 0;
			switch(ctype) {
			case PHASE::TYPE1:
				break;
			case PHASE::TYPE2:
				cpha = 1;
				break;
			case PHASE::TYPE3:
				cpol = 1;
				break;
			case PHASE::TYPE4:
				cpol = 1;
				cpha = 1;
				break;
			default:
				break;
			}
			RSPI::SPCMD0 = RSPI::SPCMD0.BRDV.b(brdv)
				| RSPI::SPCMD0.SPB.b(static_cast<uint8_t>(dlen))
				| RSPI::SPCMD0.CPOL.b(cpol) | RSPI::SPCMD0.CPHA.b(cpha);

			RSPI::SPCR.SPMS = 1;
			RSPI::SPCR.MSTR = 1;

			RSPI::SPCR.SPE = 1;

			return true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  ＳＤカード用設定を有効にする
			@param[in]	speed	通信速度
			@return エラー（速度設定範囲外）なら「false」
		*/
		//-----------------------------------------------------------------//
		bool start_sdc(uint32_t speed) noexcept
		{
			level_ = 0;

			uint8_t brdv;
			uint8_t spbr;
			if(!clock_div_(speed, brdv, spbr)) {
				return false;
			}

			power_mgr::turn(RSPI::PERIPHERAL);

			RSPI::SPCR = 0x00;

			port_map::turn(RSPI::PERIPHERAL, true, PSEL);
#if 0
			utils::format("RSPI Request Speed: %u [Hz]\n") % speed;
			utils::format("RSPI SPBR: %d\n") % static_cast<uint32_t>(spbr);
			utils::format("RSPI BRDV: %d\n") % static_cast<uint32_t>(brdv);
#endif
		    RSPI::SPBR = spbr;

			// 実際のクロックを表示
#if 0
			static const uint8_t n[4] = { 1, 2, 4, 8 };
			uint32_t z = static_cast<uint32_t>(RSPI::PCLK)
					/ (2 * static_cast<uint32_t>(spbr + 1) * static_cast<uint32_t>(n[brdv]));
			utils::format("RSPI Real Speed: %u [Hz]\n") % z;
#endif
			RSPI::SPPCR = 0x00;	 // Fixed idle value, disable loop-back
			RSPI::SPSCR = 0x00;	 // disable sequence control
			RSPI::SPDCR = 0x20;	 // SPLW=1 (data register 32bits access)
			RSPI::SPCMD0 = RSPI::SPCMD0.BRDV.b(brdv)
				| RSPI::SPCMD0.SPB.b(static_cast<uint8_t>(DLEN::W8))
				| RSPI::SPCMD0.CPHA.b(0) | RSPI::SPCMD0.CPOL.b(0);

			// 3 線式（SSLAx を使わない）、Master
			RSPI::SPCR = RSPI::SPCR.SPMS.b(1) | RSPI::SPCR.MSTR.b(1);

			RSPI::SPCR.SPE = 1;

			return true;
		}

		//----------------------------------------------------------------//
		/*!
			@brief	リード・ライト
			@param[in]	data	書き込みデータ
			@return 読み出しデータ
		*/
		//----------------------------------------------------------------//
		uint8_t xchg(uint8_t data = 0xff) noexcept
		{
			RSPI::SPDR = static_cast<uint32_t>(data);
			while(RSPI::SPSR.SPRF() == 0) sleep_();
		    return RSPI::SPDR();
		}

		//----------------------------------------------------------------//
		/*!
			@brief	通信レジスタへ書き込み @n
					※通信幅は最大３２ビット（通信モード設定による）
			@param[in]	data	書き込みデータ
		*/
		//----------------------------------------------------------------//
		inline void xchg32_start(uint32_t data = 0) noexcept
		{
			RSPI::SPDR = static_cast<uint32_t>(data);
		}

		//----------------------------------------------------------------//
		/*!
			@brief	通信の同期とレジスタからの読み出し @n
					※通信幅は最大３２ビット（通信モード設定による）
			@return	読み出しデータ
		*/
		//----------------------------------------------------------------//
		inline uint32_t xchg32_sync() noexcept
		{
			while(RSPI::SPSR.SPRF() == 0) sleep_();
		    return RSPI::SPDR();
		}

		//----------------------------------------------------------------//
		/*!
			@brief	リード・ライト
			@param[in]	data	書き込みデータ
			@return 読み出しデータ
		*/
		//----------------------------------------------------------------//
		inline uint32_t xchg32(uint32_t data = 0) noexcept
		{
			xchg32_start(data);
			return xchg32_sync();
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  シリアル送信
			@param[in]	src	送信ソース
			@param[in]	cnt	送信サイズ
		*/
		//-----------------------------------------------------------------//
		void send(const void* src, uint32_t size) noexcept
		{
			auto ptr = static_cast<const uint8_t*>(src);
			while(size > 0) {
				xchg(*ptr);
				++ptr;
				size--;
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  シリアル受信
			@param[out]	dst	受信先
			@param[in]	cnt	受信サイズ
		*/
		//-----------------------------------------------------------------//
		void recv(void* dst, uint32_t size) noexcept
		{
			auto ptr = static_cast<uint8_t*>(dst);
			while(size > 0) {
				*ptr = xchg();
				++ptr;
				size--;
			}
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  RSPIを無効にして、パワーダウンする
			@param[in]	power パワーダウンをしない場合「false」
		*/
		//-----------------------------------------------------------------//
		void destroy(bool power = true) noexcept
		{
			RSPI::SPCR = 0x00;
			port_map::turn(RSPI::PERIPHERAL, false);
			if(power) power_mgr::turn(RSPI::PERIPHERAL, false);
		}
	};
}
<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*!	@file
	@brief	ソフト制御 I2C テンプレートクラス
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2017 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include <cstdint>
#include "common/delay.hpp"

namespace device {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  I2C テンプレートクラス @n
		@param[in]	SDA	SDA ポート定義クラス
		@param[in]	SCL	SCL ポート定義クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class SDA, class SCL>
	class si2c_io {
	public:
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  I2C の速度タイプ
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		enum class speed : uint8_t {
			standard,	///< 100K b.p.s. (Standard mode)
			fast,		///< 400K b.p.s. (Fast mode)
			fast_plus,	///< 1M b.p.s. (Fast plus mode)
		};

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  I2C のエラー
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		enum class error : uint8_t {
			none,		///< エラー無し
			start,		///< スタート（初期化）
			bus_open,	///< バス・オープン
			address,	///< アドレス転送
			send_data,	///< 送信データ転送
			recv_data,	///< 受信データ転送
			stop,		///< ストップ・コンディション
		};

	private:
		uint8_t		clock_;
		error		error_;
		uint16_t	busy_;

		static const uint8_t slow_clock_ = 10 / 2;
		static const uint8_t fast_clock_ = 4 / 2;

		void start_() const {
			SDA::P = 0;
			utils::delay::micro_second(clock_);
			SCL::P = 0;
			utils::delay::micro_second(clock_);
		}

		bool ack_() const {
			SDA::P = 1;
			utils::delay::micro_second(clock_);
			SCL::P = 1;
			SDA::DIR = 0;
			utils::delay::micro_second(clock_);
			bool f = SDA::P();
			SDA::P = 0;
			SDA::DIR = 1;
			SCL::P = 0;
			return f;
		}

		void out_ack_(bool b) const {
			utils::delay::micro_second(clock_);
			SDA::P = b;
			SCL::P = 1;
			utils::delay::micro_second(clock_);
			SCL::P = 0;
		}

		bool wait_() const {
			uint16_t cnt = busy_;
			SCL::DIR = 0;
			while(SCL::P() == 0) {
				utils::delay::micro_second(1);
				if(cnt) {
					--cnt;
				} else {
					SCL::DIR = 1;
					return false;  // wait stall
				}
			}
			SCL::DIR = 1;
			return true;
		}

		void stop_() const {
			utils::delay::micro_second(clock_);
			SCL::P = 1;
			utils::delay::micro_second(clock_);
			SDA::P = 1;
		}

		bool write_(uint8_t val, bool sync) const {
			for(uint8_t n = 0; n < 8; ++n) {
				SDA::P = (val & 0x80) != 0 ? 1 : 0;
				utils::delay::micro_second(clock_);
				SCL::P = 1;
				if(n == 0 && sync) {
					if(!wait_()) return false;
				}
				val <<= 1;
				utils::delay::micro_second(clock_);
				SCL::P = 0;
			}
			return true;
		}

		bool write_(uint8_t data) const {
			if(!write_(data, true)) {
				stop_();
				return false;
			}
			if(ack_()) {
				stop_();
				return false;
			}
			return true;
		}

		bool write_(const uint8_t* src, uint8_t num) const {
			for(uint8_t n = 0; n < num; ++n) {
				if(!write_(*src, true)) {
					stop_();
					return false;
				}
				++src;
				if(ack_()) {
					stop_();
					return false;
				}
			}
			return true;
		}

		bool read_(uint8_t& val, bool sync) const {
			SDA::DIR = 0;
			for(uint8_t n = 0; n < 8; ++n) {
				utils::delay::micro_second(clock_);
				val <<= 1;
				SCL::P = 1;
				if(n == 0 && sync) {
					if(!wait_()) {
						SDA::DIR = 1;
						return false;
					}
				}
				utils::delay::micro_second(clock_);
				if(SDA::P()) val |= 1;
				SCL::P = 0;
			}
			SDA::DIR = 1;
			return true;
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
		*/
		//-----------------------------------------------------------------//
		si2c_io() : clock_(slow_clock_), error_(error::none), busy_(200) { }

		//-----------------------------------------------------------------//
		/*!
			@brief  初期化
			@param[in]	spd	スピード
			@return 成功なら「true」
		*/
		//-----------------------------------------------------------------//
		bool start(speed spd)
		{
			SCL::OD = 1;
			SDA::OD = 1;
			SCL::DIR = 1;
			SDA::DIR = 1;
			SCL::P = 1;
			SDA::P = 1;
			if(spd == speed::standard) {
				set_standard();
			} else if(spd == speed::fast) {
				set_fast();
			} else {
				error_ = error::start;
				return false;
			}
			return true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  クロック設定
			@param[in]	clock	パルス５０％待ち時間（単位マイクロ秒）
		*/
		//-----------------------------------------------------------------//
		void set_clock(uint8_t clock) { clock_ = clock; }

		//-----------------------------------------------------------------//
		/*!
			@brief  標準速度指定（maybe 100KBPS）
		*/
		//-----------------------------------------------------------------//
		void set_standard() { clock_ = slow_clock_; }

		//-----------------------------------------------------------------//
		/*!
			@brief  高速指定（maybe 400KBPS）
		*/
		//-----------------------------------------------------------------//
		void set_fast() { clock_ = fast_clock_; }

		//-----------------------------------------------------------------//
		/*!
			@brief  スレーブデバイスの「待ち」時間の最大値を設定
			@param[in]	busy	待ち時間（単位マイクロ秒）
		*/
		//-----------------------------------------------------------------//
		void set_busy(uint16_t busy) { busy_ = busy; }

		//-----------------------------------------------------------------//
		/*!
			@brief	最終エラーの取得
			@return エラー・タイプ
		 */
		//-----------------------------------------------------------------//
		error get_last_error() const { return error_; }

		//-----------------------------------------------------------------//
		/*!
			@brief  受信（リード）
			@param[in] address スレーブアドレス（７ビット）
			@param[out]	dst	先
			@param[in]	num	数
			@return 失敗なら「false」が返る
		*/
		//-----------------------------------------------------------------//
		bool recv(uint8_t address, uint8_t* dst, uint8_t num) {
			start_();
			write_((address << 1) | 1, false);
			if(ack_()) {
				stop_();
				error_ = error::address;
				return false;
			}

			for(uint8_t n = 0; n < num; ++n) {
				if(!read_(*dst, true)) {
					stop_();
					error_ = error::recv_data;
					return false;
				}
				bool f = 0;
				if(n == (num - 1)) f = 1;
				out_ack_(f);
				++dst;
			}
			stop_();
			return true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  送信（ライト）
			@param[in] address スレーブアドレス（７ビット）
			@param[in]	src	元
			@param[in]	num	数
			@return 失敗なら「false」が返る
		*/
		//-----------------------------------------------------------------//
		bool send(uint8_t address, const uint8_t* src, uint8_t num) {
			start_();
			write_(address << 1, false);
			if(ack_()) {
				stop_();
				error_ = error::address;
				return false;
			}

			if(!write_(src, num)) {
				stop_();
				error_ = error::send_data;
				return false;
			}
			stop_();
			return true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  送信（ライト）
			@param[in] address スレーブアドレス（７ビット）
			@param[in]	first	ファーストデータ
			@param[in]	src	元
			@param[in]	num	数
			@return 失敗なら「false」が返る
		*/
		//-----------------------------------------------------------------//
		bool send(uint8_t address, uint8_t first, const uint8_t* src, uint8_t num) {
			start_();
			write_(address << 1, false);
			if(ack_()) {
				stop_();
				error_ = error::address;
				return false;
			}

			if(!write_(first)) {
				stop_();
				error_ = error::send_data;
				return false;
			}

			if(!write_(src, num)) {
				stop_();
				error_ = error::send_data;
				return false;
			}
			stop_();
			return true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  送信（ライト）
			@param[in] address スレーブアドレス（７ビット）
			@param[in]	first	ファースト・データ
			@param[in]	second	セカンド・データ
			@param[in]	src	元
			@param[in]	num	数
			@return 失敗なら「false」が返る
		*/
		//-----------------------------------------------------------------//
		bool send(uint8_t address, uint8_t first, uint8_t second, const uint8_t* src, uint8_t num) {
			start_();
			write_(address << 1, false);
			if(ack_()) {
				stop_();
				error_ = error::address;
				return false;
			}

			if(!write_(first)) {
				stop_();
				error_ = error::send_data;
				return false;
			}
			if(!write_(second)) {
				stop_();
				error_ = error::send_data;
				return false;
			}
			if(!write_(src, num)) {
				stop_();
				error_ = error::send_data;
				return false;
			}
			stop_();
			return true;
		}
	};
}
<commit_msg>update: cleanup soft I2C<commit_after>#pragma once
//=====================================================================//
/*!	@file
	@brief	ソフト制御 I2C テンプレートクラス
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2017, 2018 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include <cstdint>
#include "common/delay.hpp"

namespace device {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  I2C テンプレートクラス @n
		@param[in]	SDA	SDA ポート定義クラス
		@param[in]	SCL	SCL ポート定義クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <class SDA, class SCL>
	class si2c_io {
	public:
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  I2C の速度タイプ
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		enum class SPEED : uint8_t {
			STANDARD,	///< 100K b.p.s. (Standard mode)
			FAST,		///< 400K b.p.s. (Fast mode)
			FAST_PLUS,	///< 1M b.p.s. (Fast plus mode)
		};

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  I2C のエラー
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		enum class error : uint8_t {
			none,		///< エラー無し
			start,		///< スタート（初期化）
			bus_open,	///< バス・オープン
			address,	///< アドレス転送
			send_data,	///< 送信データ転送
			recv_data,	///< 受信データ転送
			stop,		///< ストップ・コンディション
		};

	private:
		uint8_t		clock_;
		error		error_;
		uint16_t	busy_;

		static const uint8_t slow_clock_ = 10 / 2;
		static const uint8_t fast_clock_ = 4 / 2;

		void start_() const {
			SDA::P = 0;
			utils::delay::micro_second(clock_);
			SCL::P = 0;
			utils::delay::micro_second(clock_);
		}

		bool ack_() const {
			SDA::P = 1;
			utils::delay::micro_second(clock_);
			SCL::P = 1;
			SDA::DIR = 0;
			utils::delay::micro_second(clock_);
			bool f = SDA::P();
			SDA::P = 0;
			SDA::DIR = 1;
			SCL::P = 0;
			return f;
		}

		void out_ack_(bool b) const {
			utils::delay::micro_second(clock_);
			SDA::P = b;
			SCL::P = 1;
			utils::delay::micro_second(clock_);
			SCL::P = 0;
		}

		bool wait_() const {
			uint16_t cnt = busy_;
			SCL::DIR = 0;
			while(SCL::P() == 0) {
				utils::delay::micro_second(1);
				if(cnt) {
					--cnt;
				} else {
					SCL::DIR = 1;
					return false;  // wait stall
				}
			}
			SCL::DIR = 1;
			return true;
		}

		void stop_() const {
			utils::delay::micro_second(clock_);
			SCL::P = 1;
			utils::delay::micro_second(clock_);
			SDA::P = 1;
		}

		bool write_(uint8_t val, bool sync) const {
			for(uint8_t n = 0; n < 8; ++n) {
				SDA::P = (val & 0x80) != 0 ? 1 : 0;
				utils::delay::micro_second(clock_);
				SCL::P = 1;
				if(n == 0 && sync) {
					if(!wait_()) return false;
				}
				val <<= 1;
				utils::delay::micro_second(clock_);
				SCL::P = 0;
			}
			return true;
		}

		bool write_(uint8_t data) const {
			if(!write_(data, true)) {
				stop_();
				return false;
			}
			if(ack_()) {
				stop_();
				return false;
			}
			return true;
		}

		bool write_(const uint8_t* src, uint8_t num) const {
			for(uint8_t n = 0; n < num; ++n) {
				if(!write_(*src, true)) {
					stop_();
					return false;
				}
				++src;
				if(ack_()) {
					stop_();
					return false;
				}
			}
			return true;
		}

		bool read_(uint8_t& val, bool sync) const {
			SDA::DIR = 0;
			for(uint8_t n = 0; n < 8; ++n) {
				utils::delay::micro_second(clock_);
				val <<= 1;
				SCL::P = 1;
				if(n == 0 && sync) {
					if(!wait_()) {
						SDA::DIR = 1;
						return false;
					}
				}
				utils::delay::micro_second(clock_);
				if(SDA::P()) val |= 1;
				SCL::P = 0;
			}
			SDA::DIR = 1;
			return true;
		}

	public:
		//-----------------------------------------------------------------//
		/*!
			@brief  コンストラクター
		*/
		//-----------------------------------------------------------------//
		si2c_io() : clock_(slow_clock_), error_(error::none), busy_(200) { }

		//-----------------------------------------------------------------//
		/*!
			@brief  初期化
			@param[in]	spd	スピード
			@return 成功なら「true」
		*/
		//-----------------------------------------------------------------//
		bool start(SPEED spd)
		{
			SCL::OD = 1;
			SDA::OD = 1;
			SCL::DIR = 1;
			SDA::DIR = 1;
			SCL::P = 1;
			SDA::P = 1;
			if(spd == SPEED::STANDARD) {
				set_standard();
			} else if(spd == SPEED::FAST) {
				set_fast();
			} else {
				error_ = error::start;
				return false;
			}
			return true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  クロック設定
			@param[in]	clock	パルス５０％待ち時間（単位マイクロ秒）
		*/
		//-----------------------------------------------------------------//
		void set_clock(uint8_t clock) { clock_ = clock; }

		//-----------------------------------------------------------------//
		/*!
			@brief  標準速度指定（maybe 100KBPS）
		*/
		//-----------------------------------------------------------------//
		void set_standard() { clock_ = slow_clock_; }

		//-----------------------------------------------------------------//
		/*!
			@brief  高速指定（maybe 400KBPS）
		*/
		//-----------------------------------------------------------------//
		void set_fast() { clock_ = fast_clock_; }

		//-----------------------------------------------------------------//
		/*!
			@brief  スレーブデバイスの「待ち」時間の最大値を設定
			@param[in]	busy	待ち時間（単位マイクロ秒）
		*/
		//-----------------------------------------------------------------//
		void set_busy(uint16_t busy) { busy_ = busy; }

		//-----------------------------------------------------------------//
		/*!
			@brief	最終エラーの取得
			@return エラー・タイプ
		 */
		//-----------------------------------------------------------------//
		error get_last_error() const { return error_; }

		//-----------------------------------------------------------------//
		/*!
			@brief  受信（リード）
			@param[in] address スレーブアドレス（７ビット）
			@param[out]	dst	先
			@param[in]	num	数
			@return 失敗なら「false」が返る
		*/
		//-----------------------------------------------------------------//
		bool recv(uint8_t address, uint8_t* dst, uint8_t num) {
			start_();
			write_((address << 1) | 1, false);
			if(ack_()) {
				stop_();
				error_ = error::address;
				return false;
			}

			for(uint8_t n = 0; n < num; ++n) {
				if(!read_(*dst, true)) {
					stop_();
					error_ = error::recv_data;
					return false;
				}
				bool f = 0;
				if(n == (num - 1)) f = 1;
				out_ack_(f);
				++dst;
			}
			stop_();
			return true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  送信（ライト）
			@param[in] address スレーブアドレス（７ビット）
			@param[in]	src	元
			@param[in]	num	数
			@return 失敗なら「false」が返る
		*/
		//-----------------------------------------------------------------//
		bool send(uint8_t address, const uint8_t* src, uint8_t num) {
			start_();
			write_(address << 1, false);
			if(ack_()) {
				stop_();
				error_ = error::address;
				return false;
			}

			if(!write_(src, num)) {
				stop_();
				error_ = error::send_data;
				return false;
			}
			stop_();
			return true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  送信（ライト）
			@param[in] address スレーブアドレス（７ビット）
			@param[in]	first	ファーストデータ
			@param[in]	src	元
			@param[in]	num	数
			@return 失敗なら「false」が返る
		*/
		//-----------------------------------------------------------------//
		bool send(uint8_t address, uint8_t first, const uint8_t* src, uint8_t num) {
			start_();
			write_(address << 1, false);
			if(ack_()) {
				stop_();
				error_ = error::address;
				return false;
			}

			if(!write_(first)) {
				stop_();
				error_ = error::send_data;
				return false;
			}

			if(!write_(src, num)) {
				stop_();
				error_ = error::send_data;
				return false;
			}
			stop_();
			return true;
		}

		//-----------------------------------------------------------------//
		/*!
			@brief  送信（ライト）
			@param[in] address スレーブアドレス（７ビット）
			@param[in]	first	ファースト・データ
			@param[in]	second	セカンド・データ
			@param[in]	src	元
			@param[in]	num	数
			@return 失敗なら「false」が返る
		*/
		//-----------------------------------------------------------------//
		bool send(uint8_t address, uint8_t first, uint8_t second, const uint8_t* src, uint8_t num) {
			start_();
			write_(address << 1, false);
			if(ack_()) {
				stop_();
				error_ = error::address;
				return false;
			}

			if(!write_(first)) {
				stop_();
				error_ = error::send_data;
				return false;
			}
			if(!write_(second)) {
				stop_();
				error_ = error::send_data;
				return false;
			}
			if(!write_(src, num)) {
				stop_();
				error_ = error::send_data;
				return false;
			}
			stop_();
			return true;
		}
	};
}
<|endoftext|>


<commit_before>#include "gl/impl/backend/vk2/hardware/queue.hpp"
#if TZ_VULKAN
#include "gl/impl/backend/vk2/descriptors.hpp"

namespace tz::gl::vk2
{
	DescriptorLayoutBindlessFlagsInfo::NativeType DescriptorLayoutBindlessFlagsInfo::native() const
	{
		return
		{
			.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO,
			.pNext = nullptr,
			.bindingCount = static_cast<std::uint32_t>(this->binding_flags.length()),
			.pBindingFlags = this->binding_flags.data()
		};
	}

	DescriptorLayoutBuilder::DescriptorLayoutBuilder(const LogicalDevice& logical_device):
	logical_device(&logical_device),
	descriptors()
	{}

	DescriptorLayoutBuilder& DescriptorLayoutBuilder::with_descriptor(DescriptorType desc)
	{
		this->descriptors.push_back(desc);
		return *this;
	}

	DescriptorLayoutInfo DescriptorLayoutBuilder::build() const
	{
		DescriptorLayoutInfo info;
		info.context = DescriptorContext::Classic;
		info.bindings.resize(this->descriptors.size());
		for(std::size_t i = 0; i < this->descriptors.size(); i++)
		{
			VkDescriptorSetLayoutBinding& binding = info.bindings[i];
			binding.binding = i;
			binding.descriptorType = static_cast<VkDescriptorType>(this->descriptors[i]);
			binding.descriptorCount = 1;
			// TODO: Improve
			binding.stageFlags = VK_SHADER_STAGE_ALL;
			// TODO: Improve
			binding.pImmutableSamplers = nullptr;
		}
		info.logical_device = this->logical_device;
		return info;
	}

	DescriptorLayoutBuilderBindless::DescriptorLayoutBuilderBindless(const LogicalDevice& logical_device):
	logical_device(&logical_device),
	descriptors(){}

	DescriptorLayoutBuilderBindless& DescriptorLayoutBuilderBindless::with_descriptor(DescriptorType desc, std::size_t descriptor_count)
	{
		this->descriptors.push_back({.type = desc, .count = static_cast<std::uint32_t>(descriptor_count)});
		return *this;
	}

	DescriptorLayoutInfo DescriptorLayoutBuilderBindless::build() const
	{
		constexpr VkDescriptorBindingFlags vk_bindless_flags_head =
			VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT &
			VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT &
			VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT;
		constexpr VkDescriptorBindingFlags vk_bindless_flags_tail =
			VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT &
			VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT &
			VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT &
			VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT;

		DescriptorLayoutBindlessFlagsInfo bindless_flags;
		bindless_flags.binding_flags.resize(this->descriptors.size());
		// binding_flags = {head, head, head, ..., head, head, tail}
		std::for_each(bindless_flags.binding_flags.begin(), bindless_flags.binding_flags.end(),
		[](VkDescriptorBindingFlags& flags){flags = vk_bindless_flags_head;});
		bindless_flags.binding_flags.back() = vk_bindless_flags_tail;

		DescriptorLayoutInfo info;
		info.context = DescriptorContext::Bindless;
		info.maybe_bindless_flags = bindless_flags;
		info.bindings.resize(this->descriptors.size());
		for(std::size_t i = 0; i < this->descriptors.size(); i++)
		{
			const DescriptorLayoutElementInfo& elem = this->descriptors[i];

			VkDescriptorSetLayoutBinding& binding = info.bindings[i];
			binding.binding = i;
			binding.descriptorType = static_cast<VkDescriptorType>(elem.type);
			binding.descriptorCount = elem.count;
			// TODO: Improve
			binding.stageFlags = VK_SHADER_STAGE_ALL;
			// TODO: Improve
			binding.pImmutableSamplers = nullptr;
		}
		info.logical_device = this->logical_device;
		return info;
	}

	DescriptorLayout::DescriptorLayout(const DescriptorLayoutInfo& info):
	descriptor_layout(VK_NULL_HANDLE),
	logical_device(info.logical_device)
	{
		VkDescriptorSetLayoutCreateInfo create{};
		VkDescriptorSetLayoutBindingFlagsCreateInfo create_bindless{};
		switch(info.context)
		{
			case DescriptorContext::Classic:
				create =
				{
					.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
					.pNext = nullptr,
					.flags = 0,
					.bindingCount = static_cast<std::uint32_t>(info.bindings.length()),
					.pBindings = info.bindings.data()
				};
			break;
			case DescriptorContext::Bindless:
				tz_assert(info.maybe_bindless_flags.has_value(), "DescriptorLayoutInfo contains DescriptorContext::Bindless, but no bindless flags were specified. Please submit a bug report");
				create_bindless = info.maybe_bindless_flags.value().native();
				create =
				{
					.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
					.pNext = &create_bindless,
					.bindingCount = static_cast<std::uint32_t>(info.bindings.length()),
					.pBindings = info.bindings.data()
				};
			break;
			default:
				tz_error("Unrecognised DescriptorContext");
			break;
		}

		VkResult res = vkCreateDescriptorSetLayout(this->logical_device->native(), &create, nullptr, &this->descriptor_layout);
		switch(res)
		{
			case VK_SUCCESS:
				// do nothing
			break;
			case VK_ERROR_OUT_OF_HOST_MEMORY:
				tz_error("Failed to create DescriptorLayout because we ran out of host memory (RAM). Please ensure that your system meets the minimum requirements.");
			break;
			case VK_ERROR_OUT_OF_DEVICE_MEMORY:
				tz_error("Failed to create DescriptorLayout because we ran out of device memory (VRAM). Please ensure that your system meets the minimum requirements.");
			break;
			default:
				tz_error("Failed to create DescriptorSetLayout but cannot determine why. Please submit a bug report.");
			break;
		}
	}

	DescriptorLayout::DescriptorLayout(DescriptorLayout&& move):
	descriptor_layout(VK_NULL_HANDLE),
	logical_device(nullptr)
	{
		*this = std::move(move);
	}

	DescriptorLayout::~DescriptorLayout()
	{
		if(this->descriptor_layout != VK_NULL_HANDLE)
		{
			tz_assert(this->logical_device != nullptr && !this->logical_device->is_null(), "Cannot destroy DescriptorLayout because LogicalDevice provided is nullptr or a null device.");
			vkDestroyDescriptorSetLayout(this->logical_device->native(), this->descriptor_layout, nullptr);
			this->descriptor_layout = VK_NULL_HANDLE;
		}
	}

	DescriptorLayout& DescriptorLayout::operator=(DescriptorLayout&& rhs)
	{
		std::swap(this->descriptor_layout, rhs.descriptor_layout);
		std::swap(this->logical_device, rhs.logical_device);
		return *this;
	}

	DescriptorLayout::NativeType DescriptorLayout::native() const
	{
		return this->descriptor_layout;
	}
}

#endif // TZ_VULKAN
<commit_msg>* More bindless support work<commit_after>#include "gl/impl/backend/vk2/hardware/queue.hpp"
#if TZ_VULKAN
#include "gl/impl/backend/vk2/descriptors.hpp"

namespace tz::gl::vk2
{
	DescriptorLayoutBindlessFlagsInfo::NativeType DescriptorLayoutBindlessFlagsInfo::native() const
	{
		return
		{
			.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO,
			.pNext = nullptr,
			.bindingCount = static_cast<std::uint32_t>(this->binding_flags.length()),
			.pBindingFlags = this->binding_flags.data()
		};
	}

	DescriptorLayoutBuilder::DescriptorLayoutBuilder(const LogicalDevice& logical_device):
	logical_device(&logical_device),
	descriptors()
	{}

	DescriptorLayoutBuilder& DescriptorLayoutBuilder::with_descriptor(DescriptorType desc)
	{
		this->descriptors.push_back(desc);
		return *this;
	}

	DescriptorLayoutInfo DescriptorLayoutBuilder::build() const
	{
		DescriptorLayoutInfo info;
		info.context = DescriptorContext::Classic;
		info.bindings.resize(this->descriptors.size());
		for(std::size_t i = 0; i < this->descriptors.size(); i++)
		{
			VkDescriptorSetLayoutBinding& binding = info.bindings[i];
			binding.binding = i;
			binding.descriptorType = static_cast<VkDescriptorType>(this->descriptors[i]);
			binding.descriptorCount = 1;
			// TODO: Improve
			binding.stageFlags = VK_SHADER_STAGE_ALL;
			// TODO: Improve
			binding.pImmutableSamplers = nullptr;
		}
		info.logical_device = this->logical_device;
		return info;
	}

	DescriptorLayoutBuilderBindless::DescriptorLayoutBuilderBindless(const LogicalDevice& logical_device):
	logical_device(&logical_device),
	descriptors(){}

	DescriptorLayoutBuilderBindless& DescriptorLayoutBuilderBindless::with_descriptor(DescriptorType desc, std::size_t descriptor_count)
	{
		this->descriptors.push_back({.type = desc, .count = static_cast<std::uint32_t>(descriptor_count)});
		return *this;
	}

	DescriptorLayoutInfo DescriptorLayoutBuilderBindless::build() const
	{
		constexpr VkDescriptorBindingFlags vk_bindless_flags_head =
			VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT |
			VK_DESCRIPTOR_BINDING_UPDATE_UNUSED_WHILE_PENDING_BIT |
			VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT;
		constexpr VkDescriptorBindingFlags vk_bindless_flags_tail =
			vk_bindless_flags_head |
			VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT;

		DescriptorLayoutBindlessFlagsInfo bindless_flags;
		bindless_flags.binding_flags.resize(this->descriptors.size());
		// binding_flags = {head, head, head, ..., head, head, tail}
		std::for_each(bindless_flags.binding_flags.begin(), bindless_flags.binding_flags.end(),
		[](VkDescriptorBindingFlags& flags){flags = vk_bindless_flags_head;});
		bindless_flags.binding_flags.back() = vk_bindless_flags_tail;

		DescriptorLayoutInfo info;
		info.context = DescriptorContext::Bindless;
		info.maybe_bindless_flags = bindless_flags;
		info.bindings.resize(this->descriptors.size());
		for(std::size_t i = 0; i < this->descriptors.size(); i++)
		{
			const DescriptorLayoutElementInfo& elem = this->descriptors[i];

			VkDescriptorSetLayoutBinding& binding = info.bindings[i];
			binding.binding = i;
			binding.descriptorType = static_cast<VkDescriptorType>(elem.type);
			binding.descriptorCount = elem.count;
			// TODO: Improve
			binding.stageFlags = VK_SHADER_STAGE_ALL;
			// TODO: Improve
			binding.pImmutableSamplers = nullptr;
		}
		info.logical_device = this->logical_device;
		return info;
	}

	DescriptorLayout::DescriptorLayout(const DescriptorLayoutInfo& info):
	descriptor_layout(VK_NULL_HANDLE),
	logical_device(info.logical_device)
	{
		VkDescriptorSetLayoutCreateInfo create{};
		VkDescriptorSetLayoutBindingFlagsCreateInfo create_bindless{};
		switch(info.context)
		{
			case DescriptorContext::Classic:
				create =
				{
					.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
					.pNext = nullptr,
					.flags = 0,
					.bindingCount = static_cast<std::uint32_t>(info.bindings.length()),
					.pBindings = info.bindings.data()
				};
			break;
			case DescriptorContext::Bindless:
				tz_assert(info.maybe_bindless_flags.has_value(), "DescriptorLayoutInfo contains DescriptorContext::Bindless, but no bindless flags were specified. Please submit a bug report");
				create_bindless = info.maybe_bindless_flags.value().native();
				create =
				{
					.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
					.pNext = &create_bindless,
					.flags = VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT,
					.bindingCount = static_cast<std::uint32_t>(info.bindings.length()),
					.pBindings = info.bindings.data()
				};
			break;
			default:
				tz_error("Unrecognised DescriptorContext");
			break;
		}

		VkResult res = vkCreateDescriptorSetLayout(this->logical_device->native(), &create, nullptr, &this->descriptor_layout);
		switch(res)
		{
			case VK_SUCCESS:
				// do nothing
			break;
			case VK_ERROR_OUT_OF_HOST_MEMORY:
				tz_error("Failed to create DescriptorLayout because we ran out of host memory (RAM). Please ensure that your system meets the minimum requirements.");
			break;
			case VK_ERROR_OUT_OF_DEVICE_MEMORY:
				tz_error("Failed to create DescriptorLayout because we ran out of device memory (VRAM). Please ensure that your system meets the minimum requirements.");
			break;
			default:
				tz_error("Failed to create DescriptorSetLayout but cannot determine why. Please submit a bug report.");
			break;
		}
	}

	DescriptorLayout::DescriptorLayout(DescriptorLayout&& move):
	descriptor_layout(VK_NULL_HANDLE),
	logical_device(nullptr)
	{
		*this = std::move(move);
	}

	DescriptorLayout::~DescriptorLayout()
	{
		if(this->descriptor_layout != VK_NULL_HANDLE)
		{
			tz_assert(this->logical_device != nullptr && !this->logical_device->is_null(), "Cannot destroy DescriptorLayout because LogicalDevice provided is nullptr or a null device.");
			vkDestroyDescriptorSetLayout(this->logical_device->native(), this->descriptor_layout, nullptr);
			this->descriptor_layout = VK_NULL_HANDLE;
		}
	}

	DescriptorLayout& DescriptorLayout::operator=(DescriptorLayout&& rhs)
	{
		std::swap(this->descriptor_layout, rhs.descriptor_layout);
		std::swap(this->logical_device, rhs.logical_device);
		return *this;
	}

	DescriptorLayout::NativeType DescriptorLayout::native() const
	{
		return this->descriptor_layout;
	}
}

#endif // TZ_VULKAN
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: i_ce.hxx,v $
 *
 *  $Revision: 1.3 $
 *
 *  last change: $Author: hr $ $Date: 2007-11-02 15:05:28 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    This library is free software; you can redistribute it and/or
 *    modify it under the terms of the GNU Lesser General Public
 *    License version 2.1, as published by the Free Software Foundation.
 *
 *    This library is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 *    Lesser General Public License for more details.
 *
 *    You should have received a copy of the GNU Lesser General Public
 *    License along with this library; if not, write to the Free Software
 *    Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef ARY_IDL_I_CE_HXX
#define ARY_IDL_I_CE_HXX

// BASE CLASSES
#include <ary/entity.hxx>
// USED SERVICES
#include <ary/doc/d_docu.hxx>
#include <ary/idl/i_ce2s.hxx>
#include <ary/idl/i_types4idl.hxx>

namespace ary
{
namespace idl
{

/** @resp Base class for all IDL code entities.

    A @->CodeEntity is a namespace, type, data or function, which occures in
    the parsed UNO IDL code and is described and/or commented within the
    Autodoc repository.

    This is a storage base class, where more special classes are
    derived from.
*/
class CodeEntity : public ary::Entity
{
  public:
    // LIFECYCLE
    virtual             ~CodeEntity();

    // OPERATION

    // INQUIRY
    Ce_id               CeId() const            { return Ce_id(Id()); }
    const String &      LocalName() const;
    Ce_id               NameRoom() const;
    Ce_id               Owner() const;
    E_SightLevel        SightLevel() const;

    const ary::doc::Documentation &
                        Docu() const;
    const Ce_2s &       Secondaries() const;

    static const CodeEntity &
                        Null_();
    // ACCESS
    void                Set_Docu(
                            DYN ary::doc::Node &
                                                pass_data );
    Ce_2s &             Secondaries();

  protected:
                        CodeEntity();
  private:
    // Locals
    virtual const String &  inq_LocalName() const = 0;
    virtual Ce_id           inq_NameRoom() const = 0;
    virtual Ce_id           inq_Owner() const = 0;
    virtual E_SightLevel    inq_SightLevel() const = 0;

    // DATA
    ary::doc::Documentation
                        aDocu;
    Dyn<Ce_2s>          p2s;
};

// IMPLEMENTATION
inline const String &
CodeEntity::LocalName() const
    { return inq_LocalName(); }

inline Ce_id
CodeEntity::NameRoom() const
    { return inq_NameRoom(); }

inline Ce_id
CodeEntity::Owner() const
    { return inq_Owner(); }

inline E_SightLevel
CodeEntity::SightLevel() const
    { return inq_SightLevel(); }

inline const ary::doc::Documentation &
CodeEntity::Docu() const
    { return aDocu; }

inline void
CodeEntity::Set_Docu(DYN ary::doc::Node & pass_data)
{
    aDocu.Set_Data(pass_data);
}

}   // namespace idl
}   // namespace ary
#endif
<commit_msg>INTEGRATION: CWS changefileheader (1.3.22); FILE MERGED 2008/03/28 16:01:13 rt 1.3.22.1: #i87441# Change license header to LPGL v3.<commit_after>/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: i_ce.hxx,v $
 * $Revision: 1.4 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/

#ifndef ARY_IDL_I_CE_HXX
#define ARY_IDL_I_CE_HXX

// BASE CLASSES
#include <ary/entity.hxx>
// USED SERVICES
#include <ary/doc/d_docu.hxx>
#include <ary/idl/i_ce2s.hxx>
#include <ary/idl/i_types4idl.hxx>

namespace ary
{
namespace idl
{

/** @resp Base class for all IDL code entities.

    A @->CodeEntity is a namespace, type, data or function, which occures in
    the parsed UNO IDL code and is described and/or commented within the
    Autodoc repository.

    This is a storage base class, where more special classes are
    derived from.
*/
class CodeEntity : public ary::Entity
{
  public:
    // LIFECYCLE
    virtual             ~CodeEntity();

    // OPERATION

    // INQUIRY
    Ce_id               CeId() const            { return Ce_id(Id()); }
    const String &      LocalName() const;
    Ce_id               NameRoom() const;
    Ce_id               Owner() const;
    E_SightLevel        SightLevel() const;

    const ary::doc::Documentation &
                        Docu() const;
    const Ce_2s &       Secondaries() const;

    static const CodeEntity &
                        Null_();
    // ACCESS
    void                Set_Docu(
                            DYN ary::doc::Node &
                                                pass_data );
    Ce_2s &             Secondaries();

  protected:
                        CodeEntity();
  private:
    // Locals
    virtual const String &  inq_LocalName() const = 0;
    virtual Ce_id           inq_NameRoom() const = 0;
    virtual Ce_id           inq_Owner() const = 0;
    virtual E_SightLevel    inq_SightLevel() const = 0;

    // DATA
    ary::doc::Documentation
                        aDocu;
    Dyn<Ce_2s>          p2s;
};

// IMPLEMENTATION
inline const String &
CodeEntity::LocalName() const
    { return inq_LocalName(); }

inline Ce_id
CodeEntity::NameRoom() const
    { return inq_NameRoom(); }

inline Ce_id
CodeEntity::Owner() const
    { return inq_Owner(); }

inline E_SightLevel
CodeEntity::SightLevel() const
    { return inq_SightLevel(); }

inline const ary::doc::Documentation &
CodeEntity::Docu() const
    { return aDocu; }

inline void
CodeEntity::Set_Docu(DYN ary::doc::Node & pass_data)
{
    aDocu.Set_Data(pass_data);
}

}   // namespace idl
}   // namespace ary
#endif
<|endoftext|>


<commit_before>
#include "integrators/explicit_embedded_runge_kutta_nyström_integrator.hpp"

#include "base/macros.hpp"
#include "glog/logging.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "quantities/si.hpp"
#include "testing_utilities/integration.hpp"

namespace principia {

using quantities::Abs;
using quantities::Length;
using si::Metre;
using si::Milli;
using si::Second;
using testing_utilities::ComputeHarmonicOscillatorAcceleration;
using ::std::placeholders::_1;
using ::std::placeholders::_2;
using ::std::placeholders::_3;

namespace integrators {

namespace {

double HarmonicOscillatorToleranceRatio(
    Time const& h,
    std::vector<Length> const& q_error_estimate,
    std::vector<Speed> const& v_error_estimate,
    Length const& q_tolerance,
    Speed const& v_tolerance) {
  double const r = std::min(q_tolerance / Abs(q_error_estimate[0]),
                            v_tolerance / Abs(v_error_estimate[0]));
  LOG(ERROR) << (r > 1.0 ? "Accepting" : "REJECTING") << " step size "
             << h << " with ratio " << r;
  return r;
}

}  // namespace

class ExplicitEmbeddedRungeKuttaNyströmIntegratorTest
    : public ::testing::Test {};

TEST_F(ExplicitEmbeddedRungeKuttaNyströmIntegratorTest, Dummy) {
  ExplicitEmbeddedRungeKuttaNyströmIntegrator const& integrator =
      DormandElMikkawyPrince1986RKN434FM();

  ExplicitEmbeddedRungeKuttaNyströmIntegrator::Solution<Length, Speed> solution;
  integrator.Solve<Length>(
      ComputeHarmonicOscillatorAcceleration,
      {{1 * Metre}, {0 * Metre / Second}, 0 * Second},
      10 * π * Second,
      10 * π * Second,
      std::bind(HarmonicOscillatorToleranceRatio,
                _1, _2, _3, 1 * Milli(Metre), 1 * Milli(Metre) / Second),
      0.9,
      &solution);
  LOG(ERROR) << solution.back().positions[0].value;
  LOG(ERROR) << solution.back().momenta[0].value;
  LOG(ERROR) << solution.back().time.value;
  integrator.Solve<Length>(
      ComputeHarmonicOscillatorAcceleration,
      solution.back(),
      0 * Second,
      -10 * π * Second,
      std::bind(HarmonicOscillatorToleranceRatio,
                _1, _2, _3, 1 * Milli(Metre), 1 * Milli(Metre) / Second),
      0.9,
      &solution);
  LOG(ERROR) << solution.back().positions[0].value;
  LOG(ERROR) << solution.back().momenta[0].value;
  LOG(ERROR) << solution.back().time.value;
}

}  // namespace integrators
}  // namespace principia
<commit_msg>actually test things<commit_after>
#include "integrators/explicit_embedded_runge_kutta_nyström_integrator.hpp"

#include "base/macros.hpp"
#include "glog/logging.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "quantities/si.hpp"
#include "testing_utilities/integration.hpp"
#include "testing_utilities/numerics.hpp"

namespace principia {

using quantities::Abs;
using quantities::Length;
using si::Centi;
using si::Metre;
using si::Milli;
using si::Second;
using testing_utilities::AbsoluteError;
using testing_utilities::ComputeHarmonicOscillatorAcceleration;
using ::std::placeholders::_1;
using ::std::placeholders::_2;
using ::std::placeholders::_3;
using ::testing::AllOf;
using ::testing::Ge;
using ::testing::Le;

namespace integrators {

namespace {

double HarmonicOscillatorToleranceRatio(
    Time const& h,
    std::vector<Length> const& q_error_estimate,
    std::vector<Speed> const& v_error_estimate,
    Length const& q_tolerance,
    Speed const& v_tolerance) {
  double const r = std::min(q_tolerance / Abs(q_error_estimate[0]),
                            v_tolerance / Abs(v_error_estimate[0]));
  LOG(INFO) << (r > 1.0 ? "Accepting" : "Rejecting") << " step size "
             << h << " with ratio " << r;
  return r;
}

}  // namespace

class ExplicitEmbeddedRungeKuttaNyströmIntegratorTest
    : public ::testing::Test {};

TEST_F(ExplicitEmbeddedRungeKuttaNyströmIntegratorTest,
       HarmonicOscillatorBackAndForth) {
  ExplicitEmbeddedRungeKuttaNyströmIntegrator const& integrator =
      DormandElMikkawyPrince1986RKN434FM();
  Length const x_0 = 1 * Metre;
  Speed const v_0 = 0 * Metre / Second;
  Time const period = 2 * π * Second;
  Time const t_0 = 0 * Second;
  Time const t_final = 10 * period;

  ExplicitEmbeddedRungeKuttaNyströmIntegrator::Solution<Length, Speed> solution;
  integrator.Solve<Length>(
      ComputeHarmonicOscillatorAcceleration,
      {{x_0}, {v_0}, t_0},
      t_final,
      t_final - t_0,
      std::bind(HarmonicOscillatorToleranceRatio,
                _1, _2, _3, 1 * Milli(Metre), 1 * Milli(Metre) / Second),
      0.9,
      &solution);
  EXPECT_THAT(AbsoluteError(x_0, solution.back().positions[0].value),
              AllOf(Ge(1 * Milli(Metre)), Le(2 * Milli(Metre))));
  EXPECT_THAT(AbsoluteError(v_0, solution.back().momenta[0].value),
              AllOf(Ge(1 * Centi(Metre) / Second),
                    Le(2 * Centi(Metre) / Second)));
  EXPECT_EQ(t_final, solution.back().time.value);
  integrator.Solve<Length>(
      ComputeHarmonicOscillatorAcceleration,
      solution.back(),
      t_0,
      t_0 - t_final,
      std::bind(HarmonicOscillatorToleranceRatio,
                _1, _2, _3, 1 * Milli(Metre), 1 * Milli(Metre) / Second),
      0.9,
      &solution);
  EXPECT_THAT(AbsoluteError(x_0, solution.back().positions[0].value),
              AllOf(Ge(3 * Milli(Metre)), Le(4 * Milli(Metre))));
  EXPECT_THAT(AbsoluteError(v_0, solution.back().momenta[0].value),
              AllOf(Ge(1E-5 * Metre / Second),
                    Le(1E-4 * Centi(Metre) / Second)));
  EXPECT_EQ(t_0, solution.back().time.value);
}

}  // namespace integrators
}  // namespace principia
<|endoftext|>


<commit_before>// $Id$
// -*-C++-*-
// * BeginRiceCopyright *****************************************************
//
// Copyright ((c)) 2002, Rice University
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
//
// * Neither the name of Rice University (RICE) nor the names of its
//   contributors may be used to endorse or promote products derived from
//   this software without specific prior written permission.
//
// This software is provided by RICE and contributors "as is" and any
// express or implied warranties, including, but not limited to, the
// implied warranties of merchantability and fitness for a particular
// purpose are disclaimed. In no event shall RICE or contributors be
// liable for any direct, indirect, incidental, special, exemplary, or
// consequential damages (including, but not limited to, procurement of
// substitute goods or services; loss of use, data, or profits; or
// business interruption) however caused and on any theory of liability,
// whether in contract, strict liability, or tort (including negligence
// or otherwise) arising in any way out of the use of this software, even
// if advised of the possibility of such damage.
//
// ******************************************************* EndRiceCopyright *

//***************************************************************************
//
// File:
//    PCProfileUtils.C
//
// Purpose:
//    [The purpose of this file]
//
// Description:
//    [The set of functions, macros, etc. defined in the file]
//
//***************************************************************************

//************************* System Include Files ****************************

#include <iostream>
#include <fstream>
#include <map>

#ifdef NO_STD_CHEADERS
# include <string.h>
#else
# include <cstring>
using namespace std; // For compatibility with non-std C headers
#endif

//*************************** User Include Files ****************************

#include <include/general.h>

#include "PCProfileUtils.h"
#include "PCProfile.h"

#include <lib/binutils/LoadModule.h>
#include <lib/binutils/Section.h>
#include <lib/binutils/Procedure.h>
#include <lib/binutils/Instruction.h>
#include <lib/binutils/PCToSrcLineMap.h>
#include <lib/binutils/BinUtils.h>
#include <lib/support/String.h>
#include <lib/xml/xml.h>

//*************************** Forward Declarations ***************************

using namespace xml;

using std::ostream;
using std::cerr;
using std::endl;
using std::hex;
using std::dec;

// LineToPCProfileVecMap

struct lt_SrcLineX
{
  // return true if s1 < s2; false otherwise
  bool operator()(const SrcLineX* s1, const SrcLineX* s2) const
  {
    if (s1->GetSrcLine() == s2->GetSrcLine()) {
      return (s1->GetSrcLineX() < s2->GetSrcLineX());
    } else {
      return (s1->GetSrcLine() < s2->GetSrcLine());
    }
  }
};

typedef std::map<SrcLineX*, PCProfileVec*, lt_SrcLineX> LineToPCProfileVecMap;
typedef std::map<SrcLineX*, PCProfileVec*, lt_SrcLineX>::iterator
  LineToPCProfileVecMapIt;
typedef std::map<SrcLineX*, PCProfileVec*>::value_type
  LineToPCProfileVecMapVal;

void DumpFuncLineMap(ostream& ofile, LineToPCProfileVecMap& map,
		     PCProfile* profData,
		     const char* func, const char* file);
void ClearFuncLineMap(LineToPCProfileVecMap& map);

//****************************************************************************
// Combine 'PCProfile' with symbolic info and dump
//****************************************************************************

void
DumpWithSymbolicInfo(ostream& os, PCProfile* profData, LoadModuleInfo* modInfo)
{
  const char* profiledFile = profData->GetProfiledFile();
  PCProfileMetric* m = profData->GetMetric(0);
  const Addr txtStart = m->GetTxtStart();       // All metrics guaranteed to
  const Addr txtEnd = txtStart + m->GetTxtSz(); //   have identical values.
  const unsigned long numMetrics = profData->GetMetricVecSz();

  // ------------------------------------------------------------------------
  // Dump header info
  // ------------------------------------------------------------------------
  DumpProfileHeader(os);
  os << "<PROFILE version=\"3.0\">\n";
  os << "<PROFILEHDR>\n" << profData->GetHdrInfo() << "</PROFILEHDR>\n";
  os << "<PROFILEPARAMS>\n";
  {
    os << "<TARGET name"; WriteAttrStr(os, profiledFile); os << "/>\n";
    os << "<METRICS>\n";
    for (suint i = 0; i < numMetrics; i++) {
      m = profData->GetMetric(i);
      os << "<METRIC shortName"; WriteAttrNum(os, i);
      os << " nativeName";       WriteAttrNum(os, m->GetName());
      os << " period";           WriteAttrNum(os, m->GetPeriod());
      // os << " count_total";   WriteAttrNum(os, m->GetTotalCount());
      os << "/>\n";
    }
    os << "</METRICS>\n";
    os << "</PROFILEPARAMS>\n";
  }

  // ------------------------------------------------------------------------
  // Iterate through the PC values of the text section, collect
  //   symbolic information on a source line basis, and output the results
  // ------------------------------------------------------------------------

  os << "<PROFILESCOPETREE>\n";
  os << "<PGM n"; WriteAttrStr(os, profiledFile); os << ">\n";

  // 'funcLineMap' maps a line number to a 'PCProfileVec'.  It should
  //   contain information only for the current function, 'theFunc'.
  LineToPCProfileVecMap funcLineMap;

  for (LoadModuleSectionIterator it(*modInfo->GetLM()); it.IsValid(); ++it) {
    Section* sec = it.Current();
    if (sec->GetType() != Section::Text) { continue; }

    // We have a 'TextSection'.  Iterate over procedures.
    TextSection* tsec = dynamic_cast<TextSection*>(sec);
    for (TextSectionProcedureIterator it(*tsec); it.IsValid(); ++it) {
      Procedure* p = it.Current();
      String pName = GetBestFuncName(p->GetName());

      // We have a 'Procedure'.  Iterate over PC values
      String theFunc = pName, theFile;
      for (ProcedureInstructionIterator it(*p); it.IsValid(); ++it) {
	Instruction* inst = it.Current();
	Addr pc = inst->GetPC();

	// We want to iterate only over PC values for which counts are
	// recorded.  Note: Every metric in 'profData' has entries for
	// the same pc values.
	if (profData->GetMetric(0)->Find(pc) == PCProfileDatum_NIL) {
	  continue;
	}

	// --------------------------------------------------
	// Attempt to find symbolic information
	// --------------------------------------------------
	String func, file;
	SrcLineX srcLn;
	modInfo->GetSymbolicInfo(pc, inst->GetOpIndex(), func, file, srcLn);

	if (theFile.Empty() && !file.Empty()) { theFile = file; }

	// Bad line numbers: cannot fix; advance iteration
	if (!IsValidLine(srcLn.GetSrcLine())) {
	  continue; // No useful symbolic information; advance iteration
	}

	// Bad/Different func name: ignore for now and use 'theFunc' (FIXME)
	// Bad file name: ignore and use 'theFile' (FIXME)

	// --------------------------------------------------
	// Update 'funcLineMap'
	// --------------------------------------------------
	LineToPCProfileVecMapIt it1 = funcLineMap.find(&srcLn);
	if (it1 != funcLineMap.end()) { // found -- update counts
	  PCProfileVec* vec = (*it1).second;
	  for (unsigned long i = 0; i < numMetrics; i++) {
	    m = profData->GetMetric(i);
	    (*vec)[i] += m->Find(pc);
	    BriefAssertion(m->Find(pc) != PCProfileDatum_NIL);
	  }
	} else { // no entry found -- assign counts
	  PCProfileVec* vec = new PCProfileVec(numMetrics);
	  for (unsigned long i = 0; i < numMetrics; i++) {
	    m = profData->GetMetric(i);
	    (*vec)[i] = m->Find(pc);
	    BriefAssertion(m->Find(pc) != PCProfileDatum_NIL);
	  }

	  // Don't keep 'vec' if all pc counts are 0.
	  if (!vec->IsZeroed()) {
	    funcLineMap.insert(LineToPCProfileVecMapVal(new SrcLineX(srcLn),
							vec));
	  } else {
	    delete vec;
	  }
	}
      }

      // --------------------------------------------------
      // Dump the contents of 'funcLineMap'
      // --------------------------------------------------
      if (funcLineMap.size() > 0 && !theFunc.Empty() && !theFile.Empty()) {
	DumpFuncLineMap(os, funcLineMap, profData, theFunc, theFile);
      }
      ClearFuncLineMap(funcLineMap); // clears map and memory

    }
  }

  os << "</PGM>\n";
  os << "</PROFILESCOPETREE>\n";

  // ------------------------------------------------------------------------
  // Dump footer
  // ------------------------------------------------------------------------

  os << "</PROFILE>\n";
  DumpProfileFooter(os);
}

//****************************************************************************
//
//****************************************************************************

const char *PROFILEdtd =
#include <lib/xml/PROFILE.dtd.h>

void DumpProfileHeader(ostream& os)
{
  os << "<?xml version=\"1.0\"?>" << endl;
  os << "<!DOCTYPE PROFILE [\n" << PROFILEdtd << "]>" << endl;
  os.flush();
}

void DumpProfileFooter(ostream& os)
{
  /* nothing to do */
}

// Output should be in increasing order by line number.
void DumpFuncLineMap(ostream& os, LineToPCProfileVecMap& map,
		     PCProfile* profData, const char* func, const char* file)
{
  // 'func' will be different than the last call; 'file' may be the same
  static String theFile; // initializes to empty string

  if (strcmp(theFile, file) != 0) {
    // close and begin new file
    // (but don't close if this is the first time (theFile is empty)...
  }

  static const char* I[] = { "", // Indent levels (0 - 5)
			     "  ",
			     "    ",
			     "      ",
			     "        ",
			     "          " };

  os << I[1] << "<F n";  WriteAttrStr(os, file); os << ">\n";

  // Output 'func'
  os << I[2] << "<P n";  WriteAttrStr(os, func); os << ">\n";

  LineToPCProfileVecMapIt it;
  for (it = map.begin(); it != map.end(); ++it) {
    SrcLineX* srcLn = (*it).first;
    PCProfileVec* vec = (*it).second;

    os << I[3] << "<S b"; WriteAttrNum(os, srcLn->GetSrcLine());
    os << " id";     WriteAttrNum(os, srcLn->GetSrcLineX());
    os << ">\n";
    for (suint i = 0; i < vec->GetSz(); ++i) {
      if ( (*vec)[i] != 0 ) {
	PCProfileMetric* e = profData->GetMetric(i);
	double v = (double)(*vec)[i] * (double)e->GetPeriod();

	os << I[4] << "<M n"; WriteAttrNum(os, i);
	os << " v";   WriteAttrNum(os, v);
	os << "/>\n";
      }
    }
    os << I[3] << "</S>" << endl;
  }

  os << I[2] << "</P>" << endl;
  os << I[1] << "</F>\n";
}

void ClearFuncLineMap(LineToPCProfileVecMap& map)
{
  LineToPCProfileVecMapIt it;
  for (it = map.begin(); it != map.end(); ++it) {
    delete (*it).first;
    delete (*it).second;
  }
  map.clear();
}

//***************************************************************************
<commit_msg>Renaming to ProfileWriter.C.<commit_after><|endoftext|>


<commit_before>// $Id$
// -*-C++-*-
// * BeginRiceCopyright *****************************************************
//
// Copyright ((c)) 2002, Rice University
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
//   notice, this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright
//   notice, this list of conditions and the following disclaimer in the
//   documentation and/or other materials provided with the distribution.
//
// * Neither the name of Rice University (RICE) nor the names of its
//   contributors may be used to endorse or promote products derived from
//   this software without specific prior written permission.
//
// This software is provided by RICE and contributors "as is" and any
// express or implied warranties, including, but not limited to, the
// implied warranties of merchantability and fitness for a particular
// purpose are disclaimed. In no event shall RICE or contributors be
// liable for any direct, indirect, incidental, special, exemplary, or
// consequential damages (including, but not limited to, procurement of
// substitute goods or services; loss of use, data, or profits; or
// business interruption) however caused and on any theory of liability,
// whether in contract, strict liability, or tort (including negligence
// or otherwise) arising in any way out of the use of this software, even
// if advised of the possibility of such damage.
//
// ******************************************************* EndRiceCopyright *

//***************************************************************************
//
// File:
//    PCProfileUtils.h
//
// Purpose:
//    [The purpose of this file]
//
// Description:
//    [The set of functions, macros, etc. defined in the file]
//
//***************************************************************************

#ifndef PCProfileUtils_H
#define PCProfileUtils_H

//************************* System Include Files ****************************

#include <fstream>

//*************************** User Include Files ****************************

#include <include/general.h>

#include <lib/binutils/PCToSrcLineMap.h>
#include <lib/binutils/LoadModuleInfo.h>

//*************************** Forward Declarations ***************************

class PCProfile;
class Executable;

//****************************************************************************

void DumpWithSymbolicInfo(std::ostream& os, PCProfile* profData,
			  LoadModuleInfo* modInfo);

void DumpProfileHeader(std::ostream& os);
void DumpProfileFooter(std::ostream& os);

//****************************************************************************

#endif
<commit_msg>Renaming to ProfileWriter.h<commit_after><|endoftext|>


<commit_before><commit_msg>Disabled mipmap generation and fixed memory allocation in constructor.<commit_after><|endoftext|>


<commit_before>
#include <boost/test/unit_test.hpp>

#include "SoftXMT.hpp"

BOOST_AUTO_TEST_SUITE( Delegate_tests );

int64_t some_data = 1234;

void user_main( thread * me, void * args )
{
  BOOST_MESSAGE( "Spawning user main thread " << (void *) current_thread <<
                 " " << me <<
                 " on node " << SoftXMT_mynode() );

  BOOST_CHECK_EQUAL( 2, SoftXMT_nodes() );
  // try read
  some_data = 1111;
  int64_t remote_data = SoftXMT_delegate_read_word( make_global(&some_data,1) );
  BOOST_CHECK_EQUAL( 1234, remote_data );
  BOOST_CHECK_EQUAL( 1111, some_data );

  // write
  SoftXMT_delegate_write_word( make_global(&some_data,1), 2345 );
  BOOST_CHECK_EQUAL( 1111, some_data );

  // verify write
  remote_data = SoftXMT_delegate_read_word( make_global(&some_data,1) );
  BOOST_CHECK_EQUAL( 2345, remote_data );

  // fetch and add
  remote_data = SoftXMT_delegate_fetch_and_add_word( make_global(&some_data,1), 1 );
  BOOST_CHECK_EQUAL( 1111, some_data );
  BOOST_CHECK_EQUAL( 2345, remote_data );

  // verify write
  remote_data = SoftXMT_delegate_read_word( make_global(&some_data,1) );
  BOOST_CHECK_EQUAL( 2346, remote_data );

  SoftXMT_signal_done();
}

BOOST_AUTO_TEST_CASE( test1 ) {

  SoftXMT_init( &(boost::unit_test::framework::master_test_suite().argc),
                &(boost::unit_test::framework::master_test_suite().argv) );

  SoftXMT_activate();

  SoftXMT_run_user_main( &user_main, NULL );
  BOOST_CHECK( SoftXMT_done() == true );

  SoftXMT_finish( 0 );
}

BOOST_AUTO_TEST_SUITE_END();

<commit_msg>Whoops, this should have been included in the delegate commit yesterday<commit_after>
#include <boost/test/unit_test.hpp>

#include "SoftXMT.hpp"
#include "Delegate.hpp"

BOOST_AUTO_TEST_SUITE( Delegate_tests );

int64_t some_data = 1234;

void user_main( thread * me, void * args )
{
  BOOST_MESSAGE( "Spawning user main thread " << (void *) current_thread <<
                 " " << me <<
                 " on node " << SoftXMT_mynode() );

  BOOST_CHECK_EQUAL( 2, SoftXMT_nodes() );
  // try read
  some_data = 1111;
  int64_t remote_data = SoftXMT_delegate_read_word( make_global(&some_data,1) );
  BOOST_CHECK_EQUAL( 1234, remote_data );
  BOOST_CHECK_EQUAL( 1111, some_data );

  // write
  SoftXMT_delegate_write_word( make_global(&some_data,1), 2345 );
  BOOST_CHECK_EQUAL( 1111, some_data );

  // verify write
  remote_data = SoftXMT_delegate_read_word( make_global(&some_data,1) );
  BOOST_CHECK_EQUAL( 2345, remote_data );

  // fetch and add
  remote_data = SoftXMT_delegate_fetch_and_add_word( make_global(&some_data,1), 1 );
  BOOST_CHECK_EQUAL( 1111, some_data );
  BOOST_CHECK_EQUAL( 2345, remote_data );

  // verify write
  remote_data = SoftXMT_delegate_read_word( make_global(&some_data,1) );
  BOOST_CHECK_EQUAL( 2346, remote_data );

  SoftXMT_signal_done();
}

BOOST_AUTO_TEST_CASE( test1 ) {

  SoftXMT_init( &(boost::unit_test::framework::master_test_suite().argc),
                &(boost::unit_test::framework::master_test_suite().argv) );

  SoftXMT_activate();

  SoftXMT_run_user_main( &user_main, NULL );
  BOOST_CHECK( SoftXMT_done() == true );

  SoftXMT_finish( 0 );
}

BOOST_AUTO_TEST_SUITE_END();

<|endoftext|>


<commit_before>// nonpareil_sampling - Part of the nonpareil package
// @author Luis M. Rodriguez-R <lmrodriguezr at gmail dot com>
// @license artistic 2.0
// @version 1.0

#define _MULTI_THREADED
#include <iostream>
#include <fstream>
#include <unistd.h>
#include <stdio.h>
#include <math.h>
#include <pthread.h>
#include <vector>
#include <algorithm>

#include "universal.h"
// #include "multinode.h"
#include "sequence.h"
#include "nonpareil_sampling.h"

//extern int processID;
//extern int processes;

#define LARGEST_LABEL	128
#define LARGEST_LINE	2048

using namespace std;

int nonpareil_sample_portion(double *&result, int threads, samplepar_t samplepar){
   // Vars
   if(samplepar.replicates<threads) threads = samplepar.replicates;
   samplejob_t		samplejob[threads];
   pthread_t		thread[threads];
   pthread_mutex_t	mutex = PTHREAD_MUTEX_INITIALIZER;
   int			rc, samples_per_thr, launched_replicates=0;

   // Blank result
   result = new double[samplepar.replicates];
   for(int a=0; a<samplepar.replicates; a++) result[a] = 0.0;

   // Set sample
   //if(processID==0)
   say("4sfs^", "Sampling at ", samplepar.portion*100, "%");
   samples_per_thr = (int)ceil((double)samplepar.replicates/(double)threads);
   threads = (int)ceil((double)samplepar.replicates/samples_per_thr);

   // Launch samplings
   for(int thr=0; thr<threads; thr++){
      samplejob[thr].id = thr;
      samplejob[thr].from_in_result = thr*samples_per_thr; // Zero-based index to start at in the results array
      samplejob[thr].number = samplejob[thr].from_in_result+samples_per_thr > samplepar.replicates ? samplepar.replicates-samplejob[thr].from_in_result : samples_per_thr;
      samplejob[thr].samplepar = samplepar;
      samplejob[thr].result = &result;
      samplejob[thr].mutex = &mutex;
      launched_replicates += samplejob[thr].number;

      if((rc=pthread_create(&thread[thr], NULL, &nonpareil_sample_portion_thr, (void *)&samplejob[thr]  )))
	 error("Thread creation failed", (char)rc);
   }

   // Gather jobs
   for(int thr=0; thr<threads; thr++){
      //if(thr%processes == processID)
      pthread_join(thread[thr], NULL);
   }

   // Return
   return launched_replicates;
}

void *nonpareil_sample_portion_thr(void *samplejob_ref){
   // Vars
   samplejob_t	*samplejob = (samplejob_t *)samplejob_ref;
   int		*&mates_ref = *samplejob->samplepar.mates, n;
   double	*result_cp = new double[samplejob->number], p, p_gt_0;

   // Sample
   for(int i=0; i<samplejob->number; i++){
      int	found=0, sample_size=0;
      // For each read with known number of mates
      for(int j=0; j<samplejob->samplepar.mates_size; j++){
         // Include the read in the sample?
	 if(((double)rand()/(double)RAND_MAX) < samplejob->samplepar.portion){
	    sample_size++;
	    // Does the sample contain at least one mate?
	    // if((double)rand()/(double)RAND_MAX < 1.0-pow(1-samplejob->samplepar.portion, mates_ref[j]-1)) found++;
	    n=(int)floor((samplejob->samplepar.total_reads)*samplejob->samplepar.portion)-1; // -1 because we exclude the query read from the sample
	    if(n<0) n=0;
	    p=(double)(mates_ref[j]-1.0)/(samplejob->samplepar.total_reads-1.0); // Again, -1 in both terms because of the query read
	    p_gt_0 = 1.0 - pow(1.0-p, n);
	    //cout << "n=" << n << ", p=" << p << "P(X>0)=" << p_gt_0 << endl;
	    if((double)rand()/(double)RAND_MAX < p_gt_0) found++;
	 }
      }
      result_cp[i] = sample_size==0 ? 0.0 : (double)found/(double)sample_size;
   }

   // Transfer results to the external vector
   pthread_mutex_lock( samplejob->mutex );
      double *&result_ref = *samplejob->result;
      //					        v--> position + first of the thread
      for(int i=0; i<samplejob->number; i++) result_ref[i + samplejob->from_in_result] = result_cp[i];
   pthread_mutex_unlock( samplejob->mutex );

   return (void *)0;
}

sample_t nonpareil_sample_summary(double *&sample_result, int sample_number, char *alldata, char *outfile, samplepar_t samplepar){
   // Vars
   double		x2=0;
   vector<double>	dataPoints;
   FILE			*alldatah, *summaryh;
   bool			reportAllData=false;
   int			reportSummary=0;
   char			*text, *label, *sep, *header=(char*)"";
   sample_t		s;

   s.portion = samplepar.portion;

   // File handlers
   if(alldata && strlen(alldata)>0){
      alldatah = fopen(alldata, (samplepar.portion==samplepar.portion_min ? "w" : "a+"));
      if(alldatah==NULL) error("I cannot write on all-data file", alldata);
      reportAllData=true;
   }
   if(strlen(outfile)>0 && strcmp(outfile, "-")!=0){
      summaryh = fopen(outfile, (samplepar.portion==samplepar.portion_min ? "w" : "a+"));
      if(summaryh==NULL) error("I cannot write on summary file", outfile);
      reportSummary=1;
   }else if(strlen(outfile)>0){
      reportSummary=2;
   }

   if(samplepar.portion==samplepar.portion_min){
      header = new char[LARGEST_LINE];
      if(samplepar.type == 1) {
      sprintf(header, "# @impl: Nonpareil\n# @version: %.2f\n# @maxL: %d\n# @L: %.3f\n# @R: %llu\n# @overlap: %.2f\n# @divide: %.2f\n",
                samplepar.k,
                samplepar.np_version,
                samplepar.max_read_len,
      		      samplepar.avg_read_len,
		            samplepar.total_reads,
		            samplepar.seq_overlap*100.0,
		            samplepar.divide);
      }
      else if(samplepar.type == 2) {
        sprintf(header, "# @ksize: %d\n# @impl: Nonpareil\n# @version: %.2f\n# @L: %.3f\n# @AL: %.3f\n# @R: %llu\n# @overlap: %.2f\n# @divide: %.2f\n",
                  samplepar.k,
                  samplepar.np_version,
        		      samplepar.avg_read_len,
                  samplepar.adj_avg_read_len,
  		            samplepar.total_reads,
  		            samplepar.seq_overlap*100.0,
  		            samplepar.divide);
      }
   }

   if(sample_number>0){
      // Average & SD
      s.avg = s.sd = x2 = 0.0;
      for(int a=0; a<sample_number; a++){
	 s.avg += (double)sample_result[a];
	 x2  += pow((double)sample_result[a], 2.0);
	 dataPoints.push_back(sample_result[a]);
	 if(reportAllData) fprintf(alldatah, "%.2f\t%d\t%.10f\n", samplepar.portion, a, sample_result[a]);
      }
      fclose(alldatah);
      s.avg /= (double)sample_number;
      x2    /= (double)sample_number;
      s.sd   = sqrt(x2-pow(s.avg, 2.0));

      // Quartiles
      vector<double>::iterator	firstDatum = dataPoints.begin();
      vector<double>::iterator	lastDatum = dataPoints.end();
      vector<double>::iterator	q1Datum = firstDatum + (lastDatum - firstDatum) / 4;
      vector<double>::iterator	q2Datum = firstDatum + (lastDatum - firstDatum) / 2;
      vector<double>::iterator	q3Datum = firstDatum + (lastDatum - firstDatum) * 3 / 4;
      nth_element(firstDatum, q1Datum, lastDatum);
      nth_element(firstDatum, q2Datum, lastDatum);
      nth_element(firstDatum, q3Datum, lastDatum);
      s.q1 = *q1Datum;
      s.q2 = *q2Datum;
      s.q3 = *q3Datum;
   }else{
      s.avg = 0;
      s.sd  = 0;
      s.q1  = 0;
      s.q2  = 0;
      s.q3  = 0;
   }

   // Report summary
   if(reportSummary==0) return s;
   label = new char[LARGEST_LABEL];
   text = new char[LARGEST_LINE];
   sep = (char *)"\t";
   sprintf(label, (samplepar.portion_as_label ? "%.6f" : "%.0f"), samplepar.portion*(samplepar.portion_as_label? 1.0 : samplepar.total_reads ));
   sprintf(text, "%s%s%.5f%s%.5f%s%.5f%s%.5f%s%.5f",
   		label, sep, s.avg, sep, s.sd, sep, s.q1, sep, s.q2, sep, s.q3);
   if(reportSummary==1) {
      fprintf(summaryh, "%s%s\n", header, text);
      fclose(summaryh);
   } else if(reportSummary==2) printf("%s%s\n", header, text);

   return s;
}
<commit_msg>Clean compilation in OS X<commit_after>// nonpareil_sampling - Part of the nonpareil package
// @author Luis M. Rodriguez-R <lmrodriguezr at gmail dot com>
// @license artistic 2.0
// @version 1.0

#define _MULTI_THREADED
#include <iostream>
#include <fstream>
#include <unistd.h>
#include <stdio.h>
#include <math.h>
#include <pthread.h>
#include <vector>
#include <algorithm>

#include "universal.h"
// #include "multinode.h"
#include "sequence.h"
#include "nonpareil_sampling.h"

//extern int processID;
//extern int processes;

#define LARGEST_LABEL	128
#define LARGEST_LINE	2048

using namespace std;

int nonpareil_sample_portion(double *&result, int threads, samplepar_t samplepar){
   // Vars
   if(samplepar.replicates<threads) threads = samplepar.replicates;
   samplejob_t		samplejob[threads];
   pthread_t		thread[threads];
   pthread_mutex_t	mutex = PTHREAD_MUTEX_INITIALIZER;
   int			rc, samples_per_thr, launched_replicates=0;

   // Blank result
   result = new double[samplepar.replicates];
   for(int a=0; a<samplepar.replicates; a++) result[a] = 0.0;

   // Set sample
   //if(processID==0)
   say("4sfs^", "Sampling at ", samplepar.portion*100, "%");
   samples_per_thr = (int)ceil((double)samplepar.replicates/(double)threads);
   threads = (int)ceil((double)samplepar.replicates/samples_per_thr);

   // Launch samplings
   for(int thr=0; thr<threads; thr++){
      samplejob[thr].id = thr;
      samplejob[thr].from_in_result = thr*samples_per_thr; // Zero-based index to start at in the results array
      samplejob[thr].number = samplejob[thr].from_in_result+samples_per_thr > samplepar.replicates ? samplepar.replicates-samplejob[thr].from_in_result : samples_per_thr;
      samplejob[thr].samplepar = samplepar;
      samplejob[thr].result = &result;
      samplejob[thr].mutex = &mutex;
      launched_replicates += samplejob[thr].number;

      if((rc=pthread_create(&thread[thr], NULL, &nonpareil_sample_portion_thr, (void *)&samplejob[thr]  )))
	 error("Thread creation failed", (char)rc);
   }

   // Gather jobs
   for(int thr=0; thr<threads; thr++){
      //if(thr%processes == processID)
      pthread_join(thread[thr], NULL);
   }

   // Return
   return launched_replicates;
}

void *nonpareil_sample_portion_thr(void *samplejob_ref){
   // Vars
   samplejob_t	*samplejob = (samplejob_t *)samplejob_ref;
   int		*&mates_ref = *samplejob->samplepar.mates, n;
   double	*result_cp = new double[samplejob->number], p, p_gt_0;

   // Sample
   for(int i=0; i<samplejob->number; i++){
      int	found=0, sample_size=0;
      // For each read with known number of mates
      for(int j=0; j<samplejob->samplepar.mates_size; j++){
         // Include the read in the sample?
	 if(((double)rand()/(double)RAND_MAX) < samplejob->samplepar.portion){
	    sample_size++;
	    // Does the sample contain at least one mate?
	    // if((double)rand()/(double)RAND_MAX < 1.0-pow(1-samplejob->samplepar.portion, mates_ref[j]-1)) found++;
	    n=(int)floor((samplejob->samplepar.total_reads)*samplejob->samplepar.portion)-1; // -1 because we exclude the query read from the sample
	    if(n<0) n=0;
	    p=(double)(mates_ref[j]-1.0)/(samplejob->samplepar.total_reads-1.0); // Again, -1 in both terms because of the query read
	    p_gt_0 = 1.0 - pow(1.0-p, n);
	    //cout << "n=" << n << ", p=" << p << "P(X>0)=" << p_gt_0 << endl;
	    if((double)rand()/(double)RAND_MAX < p_gt_0) found++;
	 }
      }
      result_cp[i] = sample_size==0 ? 0.0 : (double)found/(double)sample_size;
   }

   // Transfer results to the external vector
   pthread_mutex_lock( samplejob->mutex );
      double *&result_ref = *samplejob->result;
      //					        v--> position + first of the thread
      for(int i=0; i<samplejob->number; i++) result_ref[i + samplejob->from_in_result] = result_cp[i];
   pthread_mutex_unlock( samplejob->mutex );

   return (void *)0;
}

sample_t nonpareil_sample_summary(double *&sample_result, int sample_number, char *alldata, char *outfile, samplepar_t samplepar){
   // Vars
   double		x2=0;
   vector<double>	dataPoints;
   FILE			*alldatah, *summaryh;
   bool			reportAllData=false;
   int			reportSummary=0;
   char			*text, *label, *sep, *header=(char*)"";
   sample_t		s;

   s.portion = samplepar.portion;

   // File handlers
   if(alldata && strlen(alldata)>0){
      alldatah = fopen(alldata, (samplepar.portion==samplepar.portion_min ? "w" : "a+"));
      if(alldatah==NULL) error("I cannot write on all-data file", alldata);
      reportAllData=true;
   }
   if(strlen(outfile)>0 && strcmp(outfile, "-")!=0){
      summaryh = fopen(outfile, (samplepar.portion==samplepar.portion_min ? "w" : "a+"));
      if(summaryh==NULL) error("I cannot write on summary file", outfile);
      reportSummary=1;
   }else if(strlen(outfile)>0){
      reportSummary=2;
   }

   if(samplepar.portion==samplepar.portion_min){
      header = new char[LARGEST_LINE];
      if(samplepar.type == 1) {
        sprintf(header, "# @impl: Nonpareil\n# @ksize: %d\n# @version: %.2f\n# @maxL: %d\n# @L: %.3f\n# @R: %llu\n# @overlap: %.2f\n# @divide: %.2f\n",
                samplepar.k,
                samplepar.np_version,
                samplepar.max_read_len,
      		      samplepar.avg_read_len,
		            samplepar.total_reads,
		            samplepar.seq_overlap*100.0,
		            samplepar.divide);
      }
      else if(samplepar.type == 2) {
        sprintf(header, "# @impl: Nonpareil\n# @ksize: %d\n# @version: %.2f\n# @L: %.3f\n# @AL: %.3f\n# @R: %llu\n# @overlap: %.2f\n# @divide: %.2f\n",
                  samplepar.k,
                  samplepar.np_version,
        		      samplepar.avg_read_len,
                  samplepar.adj_avg_read_len,
  		            samplepar.total_reads,
  		            samplepar.seq_overlap*100.0,
  		            samplepar.divide);
      }
   }

   if(sample_number>0){
      // Average & SD
      s.avg = s.sd = x2 = 0.0;
      for(int a=0; a<sample_number; a++){
	 s.avg += (double)sample_result[a];
	 x2  += pow((double)sample_result[a], 2.0);
	 dataPoints.push_back(sample_result[a]);
	 if(reportAllData) fprintf(alldatah, "%.2f\t%d\t%.10f\n", samplepar.portion, a, sample_result[a]);
      }
      fclose(alldatah);
      s.avg /= (double)sample_number;
      x2    /= (double)sample_number;
      s.sd   = sqrt(x2-pow(s.avg, 2.0));

      // Quartiles
      vector<double>::iterator	firstDatum = dataPoints.begin();
      vector<double>::iterator	lastDatum = dataPoints.end();
      vector<double>::iterator	q1Datum = firstDatum + (lastDatum - firstDatum) / 4;
      vector<double>::iterator	q2Datum = firstDatum + (lastDatum - firstDatum) / 2;
      vector<double>::iterator	q3Datum = firstDatum + (lastDatum - firstDatum) * 3 / 4;
      nth_element(firstDatum, q1Datum, lastDatum);
      nth_element(firstDatum, q2Datum, lastDatum);
      nth_element(firstDatum, q3Datum, lastDatum);
      s.q1 = *q1Datum;
      s.q2 = *q2Datum;
      s.q3 = *q3Datum;
   }else{
      s.avg = 0;
      s.sd  = 0;
      s.q1  = 0;
      s.q2  = 0;
      s.q3  = 0;
   }

   // Report summary
   if(reportSummary==0) return s;
   label = new char[LARGEST_LABEL];
   text = new char[LARGEST_LINE];
   sep = (char *)"\t";
   sprintf(label, (samplepar.portion_as_label ? "%.6f" : "%.0f"), samplepar.portion*(samplepar.portion_as_label? 1.0 : samplepar.total_reads ));
   sprintf(text, "%s%s%.5f%s%.5f%s%.5f%s%.5f%s%.5f",
   		label, sep, s.avg, sep, s.sd, sep, s.q1, sep, s.q2, sep, s.q3);
   if(reportSummary==1) {
      fprintf(summaryh, "%s%s\n", header, text);
      fclose(summaryh);
   } else if(reportSummary==2) printf("%s%s\n", header, text);

   return s;
}
<|endoftext|>


<commit_before>// Source : https://oj.leetcode.com/problems/single-number-ii/
// Author : Hao Chen
// Date   : 2014-06-17

/**********************************************************************************
*
* Given an array of integers, every element appears three times except for one. Find that single one.
*
* Note:
* Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
*
*
**********************************************************************************/

class Solution {
public:
    Solution(){
        srand(time(0));
    }

    //random invoker
    int singleNumber(int A[], int n) {
        if (rand()%2){
            return singleNumber_1(A, n);
        }
        return singleNumber_2(A, n);
    }

    /*
     *  This solution is clear & straightforward implementation.
     *
     *  We use an array of 32 length(e.g. count[32]) to count the the bits for all of numbers.
     *
     *  Because the same number appear 3 times, which means the sum of i-th bits for all numbers should be 3 times.
     *
     *  In other word, the sum of i-th bits mod 3, it must be 0 or 1. 1 means that is the single number bit.
     *
     * This solution can be easy to extend to "every element appears k times except for one."
     *
     */
    int singleNumber_1(int A[], int n) {
        int count[32] = {0};
        int result = 0;
        for (int i = 0; i < 32; i++) {
            for (int j = 0; j < n; j++) {
                if ((A[j] >> i) & 1) {
                    count[i]++;
                }
            }
            result |= ((count[i] % 3) << i);
        }
        return result;
    }

    /*
     *   The following solution is popular solution on Internet, but it looks it's not easy to understand.
     *
     *   Actually, it just optimizes the above soultion.
     *
     *   Let's see how it improve the above.
     *
     *   We use three bitmask,
     *    1) `ones` represent the i-th bit had apear once.
     *    2) `twos` represent the i-th bit had apear twice.
     *    3) `threes` represent the i-th bit had apear three times.
     *
     *    When the i-th bit had appeared for the third time, clear the i-th bit of both `ones` and `twos` to 0.
     *    The final answer will be the value of `ones`
     *
     */
    int singleNumber_2(int A[], int n) {
        int ones = 0, twos = 0, threes = 0;
        for (int i = 0; i < n; i++) {
            twos |= ones & A[i];
            ones ^= A[i];
            threes = ones & twos;
            ones &= ~threes;
            twos &= ~threes;
        }
        return ones;
    }

};
<commit_msg>improve the comments (resolves #29)<commit_after>// Source : https://oj.leetcode.com/problems/single-number-ii/
// Author : Hao Chen
// Date   : 2014-06-17

/**********************************************************************************
*
* Given an array of integers, every element appears three times except for one. Find that single one.
*
* Note:
* Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
*
*
**********************************************************************************/

class Solution {
public:
    Solution(){
        srand(time(0));
    }

    //random invoker
    int singleNumber(int A[], int n) {
        if (rand()%2){
            return singleNumber_1(A, n);
        }
        return singleNumber_2(A, n);
    }

    /*
     *  This solution is clear & straightforward implementation.
     *
     *  We use an array of 32 length(e.g. count[32]) to count the the bits for all of numbers.
     *
     *  Because the same number appear 3 times, which means the sum of i-th bits for all numbers should be 3 times.
     *
     *  In other word, the sum of the i-th bits mod 3, it must be 0 or 1. 1 means that is the single number bit.
     *
     * This solution can be easy to extend to "every element appears k times except for one."
     *
     */
    int singleNumber_1(int A[], int n) {
        int count[32] = {0};
        int result = 0;
        for (int i = 0; i < 32; i++) {
            for (int j = 0; j < n; j++) {
                if ((A[j] >> i) & 1) {
                    count[i]++;
                }
            }
            result |= ((count[i] % 3) << i);
        }
        return result;
    }

    /*
     *   The following solution is popular solution on Internet, but it looks it's not easy to understand.
     *
     *   Actually, it just optimizes the above soultion.
     *
     *   Let's see how it improve the above.
     *
     *   We use three bitmasks,
     *    1) `ones`     as a bitmask which represents the i-th bit had appeared once.
     *    2) `twos`     as a bitmask which represents the i-th bit had appeared twice.
     *    3) `threes`   as a bit mask which represents the i-th bit had appeared three times.
     *
     *    When the i-th bit had appeared for the third time, clear the i-th bit of both `ones` and `twos` to 0.
     *    The final answer will be the value of `ones`
     *
     */
    int singleNumber_2(int A[], int n) {
        int ones = 0, twos = 0, threes = 0;
        for (int i = 0; i < n; i++) {
            // `ones & A[i]` the result is the bitmask which the bits appeared twice
            twos |= ones & A[i];
            // XOR means remove the bit which appeared twice int `ones`
            ones ^= A[i];
            // count the `three`
            threes = ones & twos;
            // clear the `ones` and `twos` if the i-th bit had appeared three times.
            ones &= ~threes;
            twos &= ~threes;
        }
        return ones;
    }

};
<|endoftext|>