<commit_before>#include <stdio.h>
#include "Scanner.h"

int main(int argc, const char *argv[])
{
	Scanner scanner;
	return 0;
}
<commit_msg>something changes in main.cpp<commit_after>#include <stdio.h>
#include "Scanner.h"

int main(int argc, const char *argv[])
{
	printf("Before\r\n");
	Scanner scanner;
	printf("After\r\n");
	return 0;
}
<|endoftext|>


<commit_before>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * adiosComm.inl
 */

#ifndef ADIOS2_HELPER_ADIOSCOMM_INL_
#define ADIOS2_HELPER_ADIOSCOMM_INL_
#ifndef ADIOS2_HELPER_ADIOSCOMM_H_
#error "Inline file should only be included from it's header, never on it's own"
#endif

#include <numeric>   //std::accumulate
#include <stdexcept> //std::runtime_error
#include <utility>   //std::pair

namespace adios2
{
namespace helper
{

// GatherArrays full specializations implemented in 'adiosComm.tcc'.
template <>
void Comm::GatherArrays(const char *source, size_t sourceCount,
                        char *destination, int rankDestination) const;
template <>
void Comm::GatherArrays(const size_t *source, size_t sourceCount,
                        size_t *destination, int rankDestination) const;

template <class T>
std::vector<T> Comm::GatherValues(T source, int rankDestination) const
{
    int rank = this->Rank();
    int size = this->Size();

    std::vector<T> output;

    if (rank == rankDestination) // pre-allocate in destination rank
    {
        output.resize(size);
    }

    T sourceCopy = source; // so we can have an address for rvalues
    this->GatherArrays(&sourceCopy, 1, output.data(), rankDestination);

    return output;
}

// GathervArrays full specializations implemented in 'adiosComm.tcc'.
template <>
void Comm::GathervArrays(const char *source, size_t sourceCount,
                         const size_t *counts, size_t countsSize,
                         char *destination, int rankDestination) const;
template <>
void Comm::GathervArrays(const size_t *source, size_t sourceCount,
                         const size_t *counts, size_t countsSize,
                         size_t *destination, int rankDestination) const;

template <class T>
void Comm::GathervVectors(const std::vector<T> &in, std::vector<T> &out,
                          size_t &position, int rankDestination,
                          size_t extraSize) const
{
    const size_t inSize = in.size();
    const std::vector<size_t> counts =
        this->GatherValues(inSize, rankDestination);

    size_t gatheredSize = 0;

    int rank = this->Rank();

    if (rank == rankDestination) // pre-allocate vector
    {
        gatheredSize = std::accumulate(counts.begin(), counts.end(), size_t(0));

        const size_t newSize = position + gatheredSize;
        try
        {
            out.reserve(newSize + extraSize); // to avoid power of 2 growth
            out.resize(newSize + extraSize);
        }
        catch (...)
        {
            std::throw_with_nested(
                std::runtime_error("ERROR: buffer overflow when resizing to " +
                                   std::to_string(newSize) +
                                   " bytes, in call to GathervVectors\n"));
        }
    }

    this->GathervArrays(in.data(), in.size(), counts.data(), counts.size(),
                        out.data() + position);
    position += gatheredSize;
}

template <class T>
std::vector<T> Comm::AllGatherValues(const T source) const
{
    int size;
    SMPI_Comm_size(m_MPIComm, &size);
    std::vector<T> output(size);

    T sourceCopy = source; // so we can have an address for rvalues
    this->AllGatherArrays(&sourceCopy, 1, output.data());
    return output;
}

// AllGatherArrays full specializations implemented in 'adiosComm.tcc'.
template <>
void Comm::AllGatherArrays(const size_t *source, const size_t sourceCount,
                           size_t *destination) const;

// ReduceValues full specializations implemented in 'adiosComm.tcc'.
template <>
unsigned int Comm::ReduceValues(const unsigned int source, MPI_Op operation,
                                const int rankDestination) const;
template <>
unsigned long int Comm::ReduceValues(const unsigned long int source,
                                     MPI_Op operation,
                                     const int rankDestination) const;
template <>
unsigned long long int Comm::ReduceValues(const unsigned long long int source,
                                          MPI_Op operation,
                                          const int rankDestination) const;

// BroadcastValue full specializations implemented in 'adiosComm.tcc'.
template <>
size_t Comm::BroadcastValue(const size_t &input, const int rankSource) const;
template <>
std::string Comm::BroadcastValue(const std::string &input,
                                 const int rankSource) const;

// BroadcastVector full specializations implemented in 'adiosComm.tcc'.
template <>
void Comm::BroadcastVector(std::vector<char> &vector,
                           const int rankSource) const;
template <>
void Comm::BroadcastVector(std::vector<size_t> &vector,
                           const int rankSource) const;

template <typename TSend, typename TRecv>
void Comm::Allgather(const TSend *sendbuf, size_t sendcount, TRecv *recvbuf,
                     size_t recvcount, const std::string &hint) const
{
    return AllgatherImpl(sendbuf, sendcount, Datatype<TSend>(), recvbuf,
                         recvcount, Datatype<TRecv>(), hint);
}

template <typename T>
void Comm::Allreduce(const T *sendbuf, T *recvbuf, size_t count, MPI_Op op,
                     const std::string &hint) const
{
    return AllreduceImpl(sendbuf, recvbuf, count, Datatype<T>(), op, hint);
}

template <typename T>
void Comm::Bcast(T *buffer, const size_t count, int root,
                 const std::string &hint) const
{
    return BcastImpl(buffer, count, Datatype<T>(), root, hint);
}

template <typename TSend, typename TRecv>
void Comm::Gather(const TSend *sendbuf, size_t sendcount, TRecv *recvbuf,
                  size_t recvcount, int root, const std::string &hint) const
{
    return GatherImpl(sendbuf, sendcount, Datatype<TSend>(), recvbuf, recvcount,
                      Datatype<TRecv>(), root, hint);
}

template <typename TSend, typename TRecv>
void Comm::Gatherv(const TSend *sendbuf, size_t sendcount, TRecv *recvbuf,
                   const size_t *recvcounts, const size_t *displs, int root,
                   const std::string &hint) const
{
    return GathervImpl(sendbuf, sendcount, Datatype<TSend>(), recvbuf,
                       recvcounts, displs, Datatype<TRecv>(), root, hint);
}

template <typename T>
void Comm::Reduce(const T *sendbuf, T *recvbuf, size_t count, MPI_Op op,
                  int root, const std::string &hint) const
{
    return ReduceImpl(sendbuf, recvbuf, count, Datatype<T>(), op, root, hint);
}

template <typename T>
void Comm::ReduceInPlace(T *buf, size_t count, MPI_Op op, int root,
                         const std::string &hint) const
{
    return ReduceInPlaceImpl(buf, count, Datatype<T>(), op, root, hint);
}

template <typename T>
void Comm::Send(const T *buf, size_t count, int dest, int tag,
                const std::string &hint) const
{
    return SendImpl(buf, count, Datatype<T>(), dest, tag, hint);
}

template <typename T>
Comm::Status Comm::Recv(T *buf, size_t count, int source, int tag,
                        const std::string &hint) const
{
    return RecvImpl(buf, count, Datatype<T>(), source, tag, hint);
}

template <typename TSend, typename TRecv>
void Comm::Scatter(const TSend *sendbuf, size_t sendcount, TRecv *recvbuf,
                   size_t recvcount, int root, const std::string &hint) const
{
    return ScatterImpl(sendbuf, sendcount, Datatype<TSend>(), recvbuf,
                       recvcount, Datatype<TRecv>(), root, hint);
}

template <typename T>
Comm::Req Comm::Isend(const T *buffer, const size_t count, int dest, int tag,
                      const std::string &hint) const
{
    return IsendImpl(buffer, count, Datatype<T>(), dest, tag, hint);
}

template <typename T>
Comm::Req Comm::Irecv(T *buffer, const size_t count, int source, int tag,
                      const std::string &hint) const
{
    return IrecvImpl(buffer, count, Datatype<T>(), source, tag, hint);
}

// Datatype full specializations implemented in 'adiosComm.tcc'.
template <>
MPI_Datatype Comm::Datatype<signed char>();
template <>
MPI_Datatype Comm::Datatype<char>();
template <>
MPI_Datatype Comm::Datatype<short>();
template <>
MPI_Datatype Comm::Datatype<int>();
template <>
MPI_Datatype Comm::Datatype<long>();
template <>
MPI_Datatype Comm::Datatype<unsigned char>();
template <>
MPI_Datatype Comm::Datatype<unsigned short>();
template <>
MPI_Datatype Comm::Datatype<unsigned int>();
template <>
MPI_Datatype Comm::Datatype<unsigned long>();
template <>
MPI_Datatype Comm::Datatype<unsigned long long>();
template <>
MPI_Datatype Comm::Datatype<long long>();
template <>
MPI_Datatype Comm::Datatype<double>();
template <>
MPI_Datatype Comm::Datatype<long double>();
template <>
MPI_Datatype Comm::Datatype<std::pair<int, int>>();
template <>
MPI_Datatype Comm::Datatype<std::pair<float, int>>();
template <>
MPI_Datatype Comm::Datatype<std::pair<double, int>>();
template <>
MPI_Datatype Comm::Datatype<std::pair<long double, int>>();
template <>
MPI_Datatype Comm::Datatype<std::pair<short, int>>();

} // end namespace helper
} // end namespace adios2

#endif /* ADIOS2_HELPER_ADIOSCOMM_INL_ */
<commit_msg>helper: Implement Comm::AllGatherValues in terms of our encapsulation<commit_after>/*
 * Distributed under the OSI-approved Apache License, Version 2.0.  See
 * accompanying file Copyright.txt for details.
 *
 * adiosComm.inl
 */

#ifndef ADIOS2_HELPER_ADIOSCOMM_INL_
#define ADIOS2_HELPER_ADIOSCOMM_INL_
#ifndef ADIOS2_HELPER_ADIOSCOMM_H_
#error "Inline file should only be included from it's header, never on it's own"
#endif

#include <numeric>   //std::accumulate
#include <stdexcept> //std::runtime_error
#include <utility>   //std::pair

namespace adios2
{
namespace helper
{

// GatherArrays full specializations implemented in 'adiosComm.tcc'.
template <>
void Comm::GatherArrays(const char *source, size_t sourceCount,
                        char *destination, int rankDestination) const;
template <>
void Comm::GatherArrays(const size_t *source, size_t sourceCount,
                        size_t *destination, int rankDestination) const;

template <class T>
std::vector<T> Comm::GatherValues(T source, int rankDestination) const
{
    int rank = this->Rank();
    int size = this->Size();

    std::vector<T> output;

    if (rank == rankDestination) // pre-allocate in destination rank
    {
        output.resize(size);
    }

    T sourceCopy = source; // so we can have an address for rvalues
    this->GatherArrays(&sourceCopy, 1, output.data(), rankDestination);

    return output;
}

// GathervArrays full specializations implemented in 'adiosComm.tcc'.
template <>
void Comm::GathervArrays(const char *source, size_t sourceCount,
                         const size_t *counts, size_t countsSize,
                         char *destination, int rankDestination) const;
template <>
void Comm::GathervArrays(const size_t *source, size_t sourceCount,
                         const size_t *counts, size_t countsSize,
                         size_t *destination, int rankDestination) const;

template <class T>
void Comm::GathervVectors(const std::vector<T> &in, std::vector<T> &out,
                          size_t &position, int rankDestination,
                          size_t extraSize) const
{
    const size_t inSize = in.size();
    const std::vector<size_t> counts =
        this->GatherValues(inSize, rankDestination);

    size_t gatheredSize = 0;

    int rank = this->Rank();

    if (rank == rankDestination) // pre-allocate vector
    {
        gatheredSize = std::accumulate(counts.begin(), counts.end(), size_t(0));

        const size_t newSize = position + gatheredSize;
        try
        {
            out.reserve(newSize + extraSize); // to avoid power of 2 growth
            out.resize(newSize + extraSize);
        }
        catch (...)
        {
            std::throw_with_nested(
                std::runtime_error("ERROR: buffer overflow when resizing to " +
                                   std::to_string(newSize) +
                                   " bytes, in call to GathervVectors\n"));
        }
    }

    this->GathervArrays(in.data(), in.size(), counts.data(), counts.size(),
                        out.data() + position);
    position += gatheredSize;
}

template <class T>
std::vector<T> Comm::AllGatherValues(const T source) const
{
    int size = this->Size();
    std::vector<T> output(size);

    T sourceCopy = source; // so we can have an address for rvalues
    this->AllGatherArrays(&sourceCopy, 1, output.data());
    return output;
}

// AllGatherArrays full specializations implemented in 'adiosComm.tcc'.
template <>
void Comm::AllGatherArrays(const size_t *source, const size_t sourceCount,
                           size_t *destination) const;

// ReduceValues full specializations implemented in 'adiosComm.tcc'.
template <>
unsigned int Comm::ReduceValues(const unsigned int source, MPI_Op operation,
                                const int rankDestination) const;
template <>
unsigned long int Comm::ReduceValues(const unsigned long int source,
                                     MPI_Op operation,
                                     const int rankDestination) const;
template <>
unsigned long long int Comm::ReduceValues(const unsigned long long int source,
                                          MPI_Op operation,
                                          const int rankDestination) const;

// BroadcastValue full specializations implemented in 'adiosComm.tcc'.
template <>
size_t Comm::BroadcastValue(const size_t &input, const int rankSource) const;
template <>
std::string Comm::BroadcastValue(const std::string &input,
                                 const int rankSource) const;

// BroadcastVector full specializations implemented in 'adiosComm.tcc'.
template <>
void Comm::BroadcastVector(std::vector<char> &vector,
                           const int rankSource) const;
template <>
void Comm::BroadcastVector(std::vector<size_t> &vector,
                           const int rankSource) const;

template <typename TSend, typename TRecv>
void Comm::Allgather(const TSend *sendbuf, size_t sendcount, TRecv *recvbuf,
                     size_t recvcount, const std::string &hint) const
{
    return AllgatherImpl(sendbuf, sendcount, Datatype<TSend>(), recvbuf,
                         recvcount, Datatype<TRecv>(), hint);
}

template <typename T>
void Comm::Allreduce(const T *sendbuf, T *recvbuf, size_t count, MPI_Op op,
                     const std::string &hint) const
{
    return AllreduceImpl(sendbuf, recvbuf, count, Datatype<T>(), op, hint);
}

template <typename T>
void Comm::Bcast(T *buffer, const size_t count, int root,
                 const std::string &hint) const
{
    return BcastImpl(buffer, count, Datatype<T>(), root, hint);
}

template <typename TSend, typename TRecv>
void Comm::Gather(const TSend *sendbuf, size_t sendcount, TRecv *recvbuf,
                  size_t recvcount, int root, const std::string &hint) const
{
    return GatherImpl(sendbuf, sendcount, Datatype<TSend>(), recvbuf, recvcount,
                      Datatype<TRecv>(), root, hint);
}

template <typename TSend, typename TRecv>
void Comm::Gatherv(const TSend *sendbuf, size_t sendcount, TRecv *recvbuf,
                   const size_t *recvcounts, const size_t *displs, int root,
                   const std::string &hint) const
{
    return GathervImpl(sendbuf, sendcount, Datatype<TSend>(), recvbuf,
                       recvcounts, displs, Datatype<TRecv>(), root, hint);
}

template <typename T>
void Comm::Reduce(const T *sendbuf, T *recvbuf, size_t count, MPI_Op op,
                  int root, const std::string &hint) const
{
    return ReduceImpl(sendbuf, recvbuf, count, Datatype<T>(), op, root, hint);
}

template <typename T>
void Comm::ReduceInPlace(T *buf, size_t count, MPI_Op op, int root,
                         const std::string &hint) const
{
    return ReduceInPlaceImpl(buf, count, Datatype<T>(), op, root, hint);
}

template <typename T>
void Comm::Send(const T *buf, size_t count, int dest, int tag,
                const std::string &hint) const
{
    return SendImpl(buf, count, Datatype<T>(), dest, tag, hint);
}

template <typename T>
Comm::Status Comm::Recv(T *buf, size_t count, int source, int tag,
                        const std::string &hint) const
{
    return RecvImpl(buf, count, Datatype<T>(), source, tag, hint);
}

template <typename TSend, typename TRecv>
void Comm::Scatter(const TSend *sendbuf, size_t sendcount, TRecv *recvbuf,
                   size_t recvcount, int root, const std::string &hint) const
{
    return ScatterImpl(sendbuf, sendcount, Datatype<TSend>(), recvbuf,
                       recvcount, Datatype<TRecv>(), root, hint);
}

template <typename T>
Comm::Req Comm::Isend(const T *buffer, const size_t count, int dest, int tag,
                      const std::string &hint) const
{
    return IsendImpl(buffer, count, Datatype<T>(), dest, tag, hint);
}

template <typename T>
Comm::Req Comm::Irecv(T *buffer, const size_t count, int source, int tag,
                      const std::string &hint) const
{
    return IrecvImpl(buffer, count, Datatype<T>(), source, tag, hint);
}

// Datatype full specializations implemented in 'adiosComm.tcc'.
template <>
MPI_Datatype Comm::Datatype<signed char>();
template <>
MPI_Datatype Comm::Datatype<char>();
template <>
MPI_Datatype Comm::Datatype<short>();
template <>
MPI_Datatype Comm::Datatype<int>();
template <>
MPI_Datatype Comm::Datatype<long>();
template <>
MPI_Datatype Comm::Datatype<unsigned char>();
template <>
MPI_Datatype Comm::Datatype<unsigned short>();
template <>
MPI_Datatype Comm::Datatype<unsigned int>();
template <>
MPI_Datatype Comm::Datatype<unsigned long>();
template <>
MPI_Datatype Comm::Datatype<unsigned long long>();
template <>
MPI_Datatype Comm::Datatype<long long>();
template <>
MPI_Datatype Comm::Datatype<double>();
template <>
MPI_Datatype Comm::Datatype<long double>();
template <>
MPI_Datatype Comm::Datatype<std::pair<int, int>>();
template <>
MPI_Datatype Comm::Datatype<std::pair<float, int>>();
template <>
MPI_Datatype Comm::Datatype<std::pair<double, int>>();
template <>
MPI_Datatype Comm::Datatype<std::pair<long double, int>>();
template <>
MPI_Datatype Comm::Datatype<std::pair<short, int>>();

} // end namespace helper
} // end namespace adios2

#endif /* ADIOS2_HELPER_ADIOSCOMM_INL_ */
<|endoftext|>


<commit_before>#pragma once
//=====================================================================//
/*!	@file
	@brief	RX64M/RX71M/RX651/RX65N/RX66T/RX72T/RX72N/RX72M グループ・システム制御 @n
			※RX24T は構成が大きく異なるので、RX24T/system_io.hpp に分離しています。@n
			※ USB を使う場合：96MHz, 144MHz, 192MHz, 240MHz のいづれか @n
			RX72x 系では、内部 PLL 回路が追加され、Ethernet などに必要な 25MHz を得る為 @n
			16MHz を使います。@n
			(16MHz x 12.5 -> 200MHz, 16MHz x 15 -> 240MHz)
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2017, 2021 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include "RX600/system.hpp"

#if defined(SIG_RX64M) || defined(SIG_RX71M) || defined(SIG_RX66T) || defined(SIG_RX65N) || defined(SIG_RX72T) || defined(SIG_RX72N) || defined(SIG_RX72M)
#elif
  #error "system_io.hpp: Not available on RX24T"
#endif

namespace device {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  systen_base クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	struct system_base {

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  発信器タイプ @n
					HOCO を使う場合、同時に、BASE_CLOCK_ に周波数（16,18,20 MHz）を設定します。
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		enum class OSC_TYPE {
			XTAL,		///< クリスタル接続
			EXT,		///< クロック入力
			HOCO,		///< 高速オンチップオシレーター
			LOCO,		///< 低速オンチップオシレーター (240KHz)
		};
	};

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  systen_io クラス @n
				INTR_CLOCK は、内部 PLL で扱える最大速度です、@n
				外部クリスタルを微妙な周波数にする場合、その整数倍にしなければなりません。 @n
				RX71M はスーパーバイザモードでの変更が必要なので、「start.s」内で行う。 @n
				RX71M の場合、アセンブラにオプション「--defsym MEMWAIT=1」を渡す。
		@param[in]	OSC_TYPE	発信器タイプを設定（通常、XTAL）
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <auto OSC_TYPE_ = system_base::OSC_TYPE::XTAL>
	struct system_io : public system_base {

		static uint8_t clock_div_(uint32_t clk) noexcept
		{
			uint8_t div = 0;
			while(clk < clock_profile::PLL_BASE) {
				++div;
				clk <<= 1;
			}
			if(div > 0b0110) div = 0b0110;
			return div;
		}

		//-------------------------------------------------------------//
		/*!
			@brief  マスター・クロックのブースト @n
					インストラクション・クロックを最大速度にブーストする。
		*/
		//-------------------------------------------------------------//
		static void boost_master_clock() noexcept
		{
			device::SYSTEM::PRCR = 0xA50B;	// クロック、低消費電力、関係書き込み許可

			device::SYSTEM::MOSCWTCR = 9;	// 1ms wait

			// メインクロック強制発振とドライブ能力設定
			if(OSC_TYPE_ == OSC_TYPE::XTAL) {
				uint8_t modrv2 = 0b11;
				if(clock_profile::BASE > 20'000'000) modrv2 = 0b00;
				else if(clock_profile::BASE > 16'000'000) modrv2 = 0b01;
				else if(clock_profile::BASE > 8'000'000) modrv2 = 0b10;
				device::SYSTEM::MOFCR = device::SYSTEM::MOFCR.MODRV2.b(modrv2);
				device::SYSTEM::MOSCCR.MOSTP = 0;		// メインクロック発振器動作
				while(device::SYSTEM::OSCOVFSR.MOOVF() == 0) { asm("nop"); }
			} else if(OSC_TYPE_ == OSC_TYPE::EXT) {
				device::SYSTEM::MOSCCR.MOSTP = 1;		// メインクロック発振器停止
				device::SYSTEM::MOFCR = device::SYSTEM::MOFCR.MOSEL.b();
			} else if(OSC_TYPE_ == OSC_TYPE::HOCO) {  // 高速オンチップオシレータ
				uint8_t frq;
				if(clock_profile::BASE == 16'000'000) frq = 0b00;
				else if(clock_profile::BASE == 18'000'000) frq = 0b01;
				else if(clock_profile::BASE == 20'000'000) frq = 0b10;
				else frq = 0b00;
				device::SYSTEM::HOCOCR2.HCFRQ = frq;
				device::SYSTEM::HOCOCR.HCSTP = 0;  // 動作
				while(device::SYSTEM::OSCOVFSR.HCOVF() == 0) { asm("nop"); }
				device::SYSTEM::PLLCR.PLLSRCSEL = 1;
			} else {
				device::SYSTEM::PRCR = 0xA500;
				return;
			}

#if defined(SIG_RX65N)
			if(clock_profile::ICLK >= 120'000'000) {  // 120MHz 以上の場合設定
				device::SYSTEM::ROMWT = 0b10;
			} else if(clock_profile::ICLK >= 100'000'000) {
				device::SYSTEM::ROMWT = 0b01;
			} else if(clock_profile::ICLK >= 50'000'000) {
				device::SYSTEM::ROMWT = 0b00;
			}
#endif
			// RX71M はスーパーバイザモードでの変更が必要なので、「start.s」内で行う。
			// RX71M の場合、アセンブラにオプション「--defsym MEMWAIT=1」を渡す。
#if defined(SIG_RX66T) || defined(SIG_RX72M) || defined(SIG_RX72T) || defined(SIG_RX72N)
			if(clock_profile::ICLK > 120'000'000) {  // 120MHz 以上の場合設定
				device::SYSTEM::MEMWAIT = 1;
				volatile auto tmp = device::SYSTEM::MEMWAIT();  // 読み出しを行う
			}
#endif
			// (x10.0) 0b010011, (x10.5) 0b010100, (x11.0) 0b010101, (x11.5) 0b010110
			// ... MAX x30.0
			uint32_t n = clock_profile::PLL_BASE * 2 / clock_profile::BASE;
			if(n < 20) n = 20;
			else if(n > 60) n = 60;
			n -= 20;
			device::SYSTEM::PLLCR.STC = n + 0b010011;  // base x10
			device::SYSTEM::PLLCR2.PLLEN = 0;			// PLL 動作
			while(device::SYSTEM::OSCOVFSR.PLOVF() == 0) { asm("nop"); }

			device::SYSTEM::SCKCR = device::SYSTEM::SCKCR.FCK.b(clock_div_(clock_profile::FCLK))
								  | device::SYSTEM::SCKCR.ICK.b(clock_div_(clock_profile::ICLK))
								  | device::SYSTEM::SCKCR.BCK.b(clock_div_(clock_profile::BCLK))
								  | device::SYSTEM::SCKCR.PCKA.b(clock_div_(clock_profile::PCLKA))
								  | device::SYSTEM::SCKCR.PCKB.b(clock_div_(clock_profile::PCLKB))
								  | device::SYSTEM::SCKCR.PCKC.b(clock_div_(clock_profile::PCLKC))
								  | device::SYSTEM::SCKCR.PCKD.b(clock_div_(clock_profile::PCLKD));
			{  // USB Master Clock の設定
				auto usb_div = clock_profile::PLL_BASE / 48'000'000;
				if(usb_div >= 2 && usb_div <= 5) {
					// 1/2, 1/3, 1/4, 1/5
					device::SYSTEM::SCKCR2.UCK = usb_div - 1;
				}
			}

			device::SYSTEM::SCKCR3.CKSEL = 0b100;   ///< PLL 選択

			if(OSC_TYPE_ == OSC_TYPE::XTAL || OSC_TYPE_ == OSC_TYPE::EXT) {
				device::SYSTEM::LOCOCR.LCSTP = 1;  ///< 低速オンチップオシレータ停止
				device::SYSTEM::HOCOCR.HCSTP = 1;  ///< 高速オンチップオシレータ停止
				device::SYSTEM::HOCOPCR.HOCOPCNT = 1;  ///< 高速オンチップオシレーター電源 OFF
			} else if(OSC_TYPE_ == OSC_TYPE::HOCO) {
				device::SYSTEM::LOCOCR.LCSTP = 1;  ///< 低速オンチップオシレータ停止
			}

			// クロック関係書き込み不許可
			device::SYSTEM::PRCR = 0xA500;

#if defined(SIG_RX65N) || defined(SIG_RX66T) || defined(SIG_RX72M) || defined(SIG_RX72T) || defined(SIG_RX72N)
			// ROM キャッシュを有効（標準）
			device::SYSTEM::ROMCE = 1;
#endif
#if defined(__TFU)
			__init_tfu();
#endif
		}

#if defined(SIG_RX72M) || defined(SIG_RX72N)
		//-------------------------------------------------------------//
		/*!
			@brief  PPLL 制御を使って PHY 向け 25MHz を出力する。
			@return 成功なら「true」
		*/
		//-------------------------------------------------------------//
		static bool setup_phy25() noexcept
		{
			if(clock_profile::BASE != 16'000'000) {  // ベースクロックが 16MHz 以外は、生成不可とする。
				return false;
			}

			bool ret = true;
			device::SYSTEM::PRCR = 0xA50B;	// クロック、低消費電力、関係書き込み許可

			device::SYSTEM::PACKCR.OUTCKSEL = 1;

			// PPLIDIV: 1/2, PPLSTC: x12.5 (100MHz)
			device::SYSTEM::PPLLCR  = device::SYSTEM::PPLLCR.PPLIDIV.b(0b01)
								    | device::SYSTEM::PPLLCR.PPLSTC.b(0b011000);
			device::SYSTEM::PPLLCR2 = device::SYSTEM::PPLLCR2.PPLLEN.b(1);  // 発信許可

			// PPLL 安定待ち
			while(device::SYSTEM::OSCOVFSR.PPLOVF() == 0) { asm("nop"); }

			// PPLLCR3: 1/4 (25MHz)
			device::SYSTEM::PPLLCR3 = device::SYSTEM::PPLLCR3.PPLCK.b(0b0011);

			// クロック関係書き込み不許可
			device::SYSTEM::PRCR = 0xA500;

			// ポート・マッピングを行う必要があるが、あえて、ここでは許可しない。
			// ※このヘッダーに、port_map.hpp の依存を無くす為。
			// deveice::port_map::turn_CLKOUT25M();

			return true;
		}
#endif
	};

	//-------------------------------------------------------------//
	/*!
		@brief  ソフト・リセットの起動
	*/
	//-------------------------------------------------------------//
	inline void assert_soft_reset()
	{
		device::SYSTEM::PRCR = 0xA502;
		device::SYSTEM::SWRR = 0xA501;
		device::SYSTEM::PRCR = 0xA500;
	}
}
<commit_msg>Update: setting flash clock value register<commit_after>#pragma once
//=====================================================================//
/*!	@file
	@brief	RX64M/RX71M/RX651/RX65N/RX66T/RX72T/RX72N/RX72M グループ・システム制御 @n
			※RX24T は構成が大きく異なるので、RX24T/system_io.hpp に分離しています。@n
			※ USB を使う場合：96MHz, 144MHz, 192MHz, 240MHz のいづれか @n
			RX72x 系では、内部 PLL 回路が追加され、Ethernet などに必要な 25MHz を得る為 @n
			16MHz を使います。@n
			(16MHz x 12.5 -> 200MHz, 16MHz x 15 -> 240MHz)
    @author 平松邦仁 (hira@rvf-rc45.net)
	@copyright	Copyright (C) 2017, 2022 Kunihito Hiramatsu @n
				Released under the MIT license @n
				https://github.com/hirakuni45/RX/blob/master/LICENSE
*/
//=====================================================================//
#include "RX600/system.hpp"

#if defined(SIG_RX64M) || defined(SIG_RX71M) || defined(SIG_RX66T) || defined(SIG_RX65N) || defined(SIG_RX72T) || defined(SIG_RX72N) || defined(SIG_RX72M)
#elif
  #error "system_io.hpp: Not available on RX24T"
#endif

#if defined(SIG_RX72N) || defined(SIG_RX72M)
#include "RX600/flash.hpp"
#endif

namespace device {

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  systen_base クラス
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	struct system_base {

		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		/*!
			@brief  発信器タイプ @n
					HOCO を使う場合、同時に、BASE_CLOCK_ に周波数（16,18,20 MHz）を設定します。
		*/
		//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
		enum class OSC_TYPE {
			XTAL,		///< クリスタル接続
			EXT,		///< クロック入力
			HOCO,		///< 高速オンチップオシレーター
			LOCO,		///< 低速オンチップオシレーター (240KHz)
		};
	};

	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	/*!
		@brief  systen_io クラス @n
				INTR_CLOCK は、内部 PLL で扱える最大速度です、@n
				外部クリスタルを微妙な周波数にする場合、その整数倍にしなければなりません。 @n
				RX71M はスーパーバイザモードでの変更が必要なので、「start.s」内で行う。 @n
				RX71M の場合、アセンブラにオプション「--defsym MEMWAIT=1」を渡す。
		@param[in]	OSC_TYPE	発信器タイプを設定（通常、XTAL）
	*/
	//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++//
	template <auto OSC_TYPE_ = system_base::OSC_TYPE::XTAL>
	struct system_io : public system_base {

		static uint8_t clock_div_(uint32_t clk) noexcept
		{
			uint8_t div = 0;
			while(clk < clock_profile::PLL_BASE) {
				++div;
				clk <<= 1;
			}
			if(div > 0b0110) div = 0b0110;
			return div;
		}

		//-------------------------------------------------------------//
		/*!
			@brief  マスター・クロックのブースト @n
					インストラクション・クロックを最大速度にブーストする。
		*/
		//-------------------------------------------------------------//
		static void boost_master_clock() noexcept
		{
			device::SYSTEM::PRCR = 0xA50B;	// クロック、低消費電力、関係書き込み許可

			device::SYSTEM::MOSCWTCR = 9;	// 1ms wait

			// メインクロック強制発振とドライブ能力設定
			if(OSC_TYPE_ == OSC_TYPE::XTAL) {
				uint8_t modrv2 = 0b11;
				if(clock_profile::BASE > 20'000'000) modrv2 = 0b00;
				else if(clock_profile::BASE > 16'000'000) modrv2 = 0b01;
				else if(clock_profile::BASE > 8'000'000) modrv2 = 0b10;
				device::SYSTEM::MOFCR = device::SYSTEM::MOFCR.MODRV2.b(modrv2);
				device::SYSTEM::MOSCCR.MOSTP = 0;		// メインクロック発振器動作
				while(device::SYSTEM::OSCOVFSR.MOOVF() == 0) { asm("nop"); }
			} else if(OSC_TYPE_ == OSC_TYPE::EXT) {
				device::SYSTEM::MOSCCR.MOSTP = 1;		// メインクロック発振器停止
				device::SYSTEM::MOFCR = device::SYSTEM::MOFCR.MOSEL.b();
			} else if(OSC_TYPE_ == OSC_TYPE::HOCO) {  // 高速オンチップオシレータ
				uint8_t frq;
				if(clock_profile::BASE == 16'000'000) frq = 0b00;
				else if(clock_profile::BASE == 18'000'000) frq = 0b01;
				else if(clock_profile::BASE == 20'000'000) frq = 0b10;
				else frq = 0b00;
				device::SYSTEM::HOCOCR2.HCFRQ = frq;
				device::SYSTEM::HOCOCR.HCSTP = 0;  // 動作
				while(device::SYSTEM::OSCOVFSR.HCOVF() == 0) { asm("nop"); }
				device::SYSTEM::PLLCR.PLLSRCSEL = 1;
			} else {
				device::SYSTEM::PRCR = 0xA500;
				return;
			}

#if defined(SIG_RX65N)
			if(clock_profile::ICLK >= 120'000'000) {  // 120MHz 以上の場合設定
				device::SYSTEM::ROMWT = 0b10;
			} else if(clock_profile::ICLK >= 100'000'000) {
				device::SYSTEM::ROMWT = 0b01;
			} else if(clock_profile::ICLK >= 50'000'000) {
				device::SYSTEM::ROMWT = 0b00;
			}
#endif
			// RX71M はスーパーバイザモードでの変更が必要なので、「start.s」内で行う。
			// RX71M の場合、アセンブラにオプション「--defsym MEMWAIT=1」を渡す。
#if defined(SIG_RX66T) || defined(SIG_RX72M) || defined(SIG_RX72T) || defined(SIG_RX72N)
			if(clock_profile::ICLK > 120'000'000) {  // 120MHz 以上の場合設定
				device::SYSTEM::MEMWAIT = 1;
				volatile auto tmp = device::SYSTEM::MEMWAIT();  // 読み出しを行う
			}
#endif
			// (x10.0) 0b010011, (x10.5) 0b010100, (x11.0) 0b010101, (x11.5) 0b010110
			// ... MAX x30.0
			uint32_t n = clock_profile::PLL_BASE * 2 / clock_profile::BASE;
			if(n < 20) n = 20;
			else if(n > 60) n = 60;
			n -= 20;
			device::SYSTEM::PLLCR.STC = n + 0b010011;  // base x10
			device::SYSTEM::PLLCR2.PLLEN = 0;			// PLL 動作
			while(device::SYSTEM::OSCOVFSR.PLOVF() == 0) { asm("nop"); }

			device::SYSTEM::SCKCR = device::SYSTEM::SCKCR.FCK.b(clock_div_(clock_profile::FCLK))
								  | device::SYSTEM::SCKCR.ICK.b(clock_div_(clock_profile::ICLK))
								  | device::SYSTEM::SCKCR.BCK.b(clock_div_(clock_profile::BCLK))
								  | device::SYSTEM::SCKCR.PCKA.b(clock_div_(clock_profile::PCLKA))
								  | device::SYSTEM::SCKCR.PCKB.b(clock_div_(clock_profile::PCLKB))
								  | device::SYSTEM::SCKCR.PCKC.b(clock_div_(clock_profile::PCLKC))
								  | device::SYSTEM::SCKCR.PCKD.b(clock_div_(clock_profile::PCLKD));
			{  // USB Master Clock の設定
				auto usb_div = clock_profile::PLL_BASE / 48'000'000;
				if(usb_div >= 2 && usb_div <= 5) {
					// 1/2, 1/3, 1/4, 1/5
					device::SYSTEM::SCKCR2.UCK = usb_div - 1;
				}
			}

#if defined(SIG_RX72N) || defined(SIG_RX72M)
			{
				// Set for DataFlash memory access clocks
				uint32_t clk = ((static_cast<uint32_t>(clock_profile::FCLK) / 500'000) + 1) >> 1;
				if(clk > 60) {
					clk = 60;
				}
				device::FLASH::EEPFCLK = clk;
				while(device::FLASH::EEPFCLK() != clk) { asm("nop"); }
			}
#endif

			device::SYSTEM::SCKCR3.CKSEL = 0b100;   ///< PLL 選択

			if(OSC_TYPE_ == OSC_TYPE::XTAL || OSC_TYPE_ == OSC_TYPE::EXT) {
				device::SYSTEM::LOCOCR.LCSTP = 1;  ///< 低速オンチップオシレータ停止
				device::SYSTEM::HOCOCR.HCSTP = 1;  ///< 高速オンチップオシレータ停止
				device::SYSTEM::HOCOPCR.HOCOPCNT = 1;  ///< 高速オンチップオシレーター電源 OFF
			} else if(OSC_TYPE_ == OSC_TYPE::HOCO) {
				device::SYSTEM::LOCOCR.LCSTP = 1;  ///< 低速オンチップオシレータ停止
			}

			// クロック関係書き込み不許可
			device::SYSTEM::PRCR = 0xA500;

#if defined(SIG_RX65N) || defined(SIG_RX66T) || defined(SIG_RX72M) || defined(SIG_RX72T) || defined(SIG_RX72N)
			// ROM キャッシュを有効（標準）
			device::SYSTEM::ROMCE = 1;
#endif
#if defined(__TFU)
			__init_tfu();
#endif
		}

#if defined(SIG_RX72M) || defined(SIG_RX72N)
		//-------------------------------------------------------------//
		/*!
			@brief  PPLL 制御を使って PHY 向け 25MHz を出力する。
			@return 成功なら「true」
		*/
		//-------------------------------------------------------------//
		static bool setup_phy25() noexcept
		{
			if(clock_profile::BASE != 16'000'000) {  // ベースクロックが 16MHz 以外は、生成不可とする。
				return false;
			}

			bool ret = true;
			device::SYSTEM::PRCR = 0xA50B;	// クロック、低消費電力、関係書き込み許可

			device::SYSTEM::PACKCR.OUTCKSEL = 1;

			// PPLIDIV: 1/2, PPLSTC: x12.5 (100MHz)
			device::SYSTEM::PPLLCR  = device::SYSTEM::PPLLCR.PPLIDIV.b(0b01)
								    | device::SYSTEM::PPLLCR.PPLSTC.b(0b011000);
			device::SYSTEM::PPLLCR2 = device::SYSTEM::PPLLCR2.PPLLEN.b(1);  // 発信許可

			// PPLL 安定待ち
			while(device::SYSTEM::OSCOVFSR.PPLOVF() == 0) { asm("nop"); }

			// PPLLCR3: 1/4 (25MHz)
			device::SYSTEM::PPLLCR3 = device::SYSTEM::PPLLCR3.PPLCK.b(0b0011);

			// クロック関係書き込み不許可
			device::SYSTEM::PRCR = 0xA500;

			// ポート・マッピングを行う必要があるが、あえて、ここでは許可しない。
			// ※このヘッダーに、port_map.hpp の依存を無くす為。
			// deveice::port_map::turn_CLKOUT25M();

			return true;
		}
#endif
	};

	//-------------------------------------------------------------//
	/*!
		@brief  ソフト・リセットの起動
	*/
	//-------------------------------------------------------------//
	inline void assert_soft_reset()
	{
		device::SYSTEM::PRCR = 0xA502;
		device::SYSTEM::SWRR = 0xA501;
		device::SYSTEM::PRCR = 0xA500;
	}
}
<|endoftext|>


<commit_before>/****************************************************************/
/*               DO NOT MODIFY THIS HEADER                      */
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*           (c) 2010 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/

#include "RestartableDataIO.h"
#include "MooseUtils.h"
#include "RestartableData.h"
#include "FEProblem.h"

#include <stdio.h>

RestartableDataIO::RestartableDataIO(FEProblem & fe_problem) :
    _fe_problem(fe_problem)
{
}

void
RestartableDataIO::writeRestartableData(std::string base_file_name)
{
  unsigned int n_threads = libMesh::n_threads();
  unsigned int n_procs = libMesh::n_processors();

  for(unsigned int tid=0; tid<n_threads; tid++)
  {
    std::map<std::string, RestartableDataValue *> restartable_data = _fe_problem._restartable_data[tid];

    if(restartable_data.size())
    {
      const unsigned int file_version = 1;

      std::ofstream out;

      std::ostringstream file_name_stream;
      file_name_stream << base_file_name;

      if(n_threads > 1)
        file_name_stream << "-" << tid;

      std::string file_name = file_name_stream.str();

      if (libMesh::processor_id() == 0)
      {
        out.open(file_name.c_str(), std::ios::out | std::ios::binary);

        char id[2];

        // header
        id[0] = 'R';
        id[1] = 'D';

        out.write(id, 2);
        out.write((const char *)&file_version, sizeof(file_version));

        out.write((const char *)&n_procs, sizeof(n_procs));
        out.write((const char *)&n_threads, sizeof(n_threads));

        // number of RestartableData
        unsigned int n_data = restartable_data.size();
        out.write((const char *) &n_data, sizeof(n_data));

        // data names
        for(std::map<std::string, RestartableDataValue *>::iterator it = restartable_data.begin();
            it != restartable_data.end();
            ++it)
        {
          std::string name = it->second->name();
          out.write(name.c_str(), name.length() + 1); // trailing 0!
        }

        out.close();
      }

      // now each process dump its part, appending into the file
      for (unsigned int proc = 0; proc < n_procs; proc++)
      {
        if (libMesh::processor_id() == proc)
        {
          out.open(file_name.c_str(), std::ios::app | std::ios::binary);

          std::ostringstream data_blk;

          for(std::map<std::string, RestartableDataValue *>::iterator it = restartable_data.begin();
              it != restartable_data.end();
              ++it)
          {
            // std::cout<<"Storing "<<it->first<<std::endl;

            std::ostringstream data;
            it->second->store(data);

            // Store the size of the data then the data
            unsigned int data_size = data.tellp();
            data_blk.write((const char *) &data_size, sizeof(data_size));
            data_blk << data.str();
          }

          // Write out this proc's block size
          unsigned int data_blk_size = data_blk.tellp();
          out.write((const char *) &data_blk_size, sizeof(data_blk_size));

          // Write out the values
          out << data_blk.str();

          out.close();
        }

        libMesh::Parallel::barrier(libMesh::CommWorld);
      }
    }
  }

}

void
RestartableDataIO::readRestartableData(std::string base_file_name)
{
  unsigned int n_threads = libMesh::n_threads();
  unsigned int n_procs = libMesh::n_processors();

  std::vector<std::string> ignored_data;

  for(unsigned int tid=0; tid<n_threads; tid++)
  {
    std::map<std::string, RestartableDataValue *> restartable_data = _fe_problem._restartable_data[tid];

    if(restartable_data.size())
    {
      std::ostringstream file_name_stream;
      file_name_stream << base_file_name;

      if(n_threads > 1)
        file_name_stream << "-" << tid;

      std::string file_name = file_name_stream.str();

      MooseUtils::checkFileReadable(file_name);

      const unsigned int file_version = 1;

      std::ifstream in(file_name.c_str(), std::ios::in | std::ios::binary);

      // header
      char id[2];
      in.read(id, 2);

      unsigned int this_file_version;
      in.read((char *)&this_file_version, sizeof(this_file_version));

      unsigned int this_n_procs = 0;
      unsigned int this_n_threads = 0;

      in.read((char *)&this_n_procs, sizeof(this_n_procs));
      in.read((char *)&this_n_threads, sizeof(this_n_threads));

      // check the header
      if(id[0] != 'R' || id[1] != 'D')
        mooseError("Corrupted restartable data file!");

      // check the file version
      if(this_file_version > file_version)
        mooseError("Trying to restart from a newer file version - you need to update MOOSE");

      if(this_file_version < file_version)
        mooseError("Trying to restart from an older file version - you need to checkout an older version of MOOSE.");

      if(this_n_procs != n_procs)
        mooseError("Cannot restart using a different number of processors!");

      if(this_n_threads != n_threads)
        mooseError("Cannot restart using a different number of threads!");

      // number of data
      unsigned int n_data = 0;
      in.read((char *) &n_data, sizeof(n_data));

      // data names
      std::vector<std::string> data_names(n_data);

      for(unsigned int i=0; i < n_data; i++)
      {
        std::string data_name;
        char ch = 0;
        do {
          in.read(&ch, 1);
          if (ch != '\0')
            data_name += ch;
        } while (ch != '\0');
        data_names[i] = data_name;
      }

      // Read each data value
      for (unsigned int proc = 0; proc < libMesh::n_processors(); proc++)
      {
        // Grab this processor's block size
        unsigned int data_blk_size = 0;
        in.read((char *) &data_blk_size, sizeof(data_blk_size));

        if (libMesh::processor_id() == proc)
        {
          for(unsigned int i=0; i < n_data; i++)
          {
            std::string current_name = data_names[i];

            unsigned int data_size = 0;
            in.read((char *) &data_size, sizeof(data_size));

            if(restartable_data.find(current_name) != restartable_data.end()) // Only restore values if they're currently being used
            {
              // std::cout<<"Loading "<<current_name<<std::endl;

              RestartableDataValue * current_data = restartable_data[current_name];
              current_data->load(in);
            }
            else
            {
              // Skip this piece of data
              in.seekg(data_size, std::ios_base::cur);
              ignored_data.push_back(current_name);
            }
          }
        }
        else // Skip this block
          in.seekg(data_blk_size, std::ios_base::cur);

        libMesh::Parallel::barrier(libMesh::CommWorld);
      }

      in.close();
    }
  }

  if(ignored_data.size())
  {
    std::ostringstream names;

    for(unsigned int i=0; i<ignored_data.size(); i++)
      names << ignored_data[i] << "\n";

    mooseWarning("The following RestorableData was found in restart file but is being ignored:\n" << names.str());
  }
}
<commit_msg>move to restartable data being written separately on each processor refs #1169<commit_after>/****************************************************************/
/*               DO NOT MODIFY THIS HEADER                      */
/* MOOSE - Multiphysics Object Oriented Simulation Environment  */
/*                                                              */
/*           (c) 2010 Battelle Energy Alliance, LLC             */
/*                   ALL RIGHTS RESERVED                        */
/*                                                              */
/*          Prepared by Battelle Energy Alliance, LLC           */
/*            Under Contract No. DE-AC07-05ID14517              */
/*            With the U. S. Department of Energy               */
/*                                                              */
/*            See COPYRIGHT for full restrictions               */
/****************************************************************/

#include "RestartableDataIO.h"
#include "MooseUtils.h"
#include "RestartableData.h"
#include "FEProblem.h"

#include <stdio.h>

RestartableDataIO::RestartableDataIO(FEProblem & fe_problem) :
    _fe_problem(fe_problem)
{
}

void
RestartableDataIO::writeRestartableData(std::string base_file_name)
{
  unsigned int n_threads = libMesh::n_threads();
  unsigned int n_procs = libMesh::n_processors();
  unsigned int proc_id = libMesh::processor_id();

  for(unsigned int tid=0; tid<n_threads; tid++)
  {
    std::map<std::string, RestartableDataValue *> restartable_data = _fe_problem._restartable_data[tid];

    if(restartable_data.size())
    {
      const unsigned int file_version = 1;

      std::ofstream out;

      std::ostringstream file_name_stream;
      file_name_stream << base_file_name;

      file_name_stream << "-" << proc_id;

      if(n_threads > 1)
        file_name_stream << "-" << tid;

      std::string file_name = file_name_stream.str();

      { // Write out header
        out.open(file_name.c_str(), std::ios::out | std::ios::binary);

        char id[2];

        // header
        id[0] = 'R';
        id[1] = 'D';

        out.write(id, 2);
        out.write((const char *)&file_version, sizeof(file_version));

        out.write((const char *)&n_procs, sizeof(n_procs));
        out.write((const char *)&n_threads, sizeof(n_threads));

        // number of RestartableData
        unsigned int n_data = restartable_data.size();
        out.write((const char *) &n_data, sizeof(n_data));

        // data names
        for(std::map<std::string, RestartableDataValue *>::iterator it = restartable_data.begin();
            it != restartable_data.end();
            ++it)
        {
          std::string name = it->second->name();
          out.write(name.c_str(), name.length() + 1); // trailing 0!
        }
      }
      {
        std::ostringstream data_blk;

        for(std::map<std::string, RestartableDataValue *>::iterator it = restartable_data.begin();
            it != restartable_data.end();
            ++it)
        {
          // std::cout<<"Storing "<<it->first<<std::endl;

          std::ostringstream data;
          it->second->store(data);

          // Store the size of the data then the data
          unsigned int data_size = data.tellp();
          data_blk.write((const char *) &data_size, sizeof(data_size));
          data_blk << data.str();
        }

        // Write out this proc's block size
        unsigned int data_blk_size = data_blk.tellp();
        out.write((const char *) &data_blk_size, sizeof(data_blk_size));

        // Write out the values
        out << data_blk.str();

        out.close();
      }
    }
  }
}

void
RestartableDataIO::readRestartableData(std::string base_file_name)
{
  unsigned int n_threads = libMesh::n_threads();
  unsigned int n_procs = libMesh::n_processors();
  unsigned int proc_id = libMesh::processor_id();

  std::vector<std::string> ignored_data;

  for(unsigned int tid=0; tid<n_threads; tid++)
  {
    std::map<std::string, RestartableDataValue *> restartable_data = _fe_problem._restartable_data[tid];

    if(restartable_data.size())
    {
      std::ostringstream file_name_stream;
      file_name_stream << base_file_name;

      file_name_stream << "-" << proc_id;

      if(n_threads > 1)
        file_name_stream << "-" << tid;

      std::string file_name = file_name_stream.str();

      MooseUtils::checkFileReadable(file_name);

      const unsigned int file_version = 1;

      std::ifstream in(file_name.c_str(), std::ios::in | std::ios::binary);

      // header
      char id[2];
      in.read(id, 2);

      unsigned int this_file_version;
      in.read((char *)&this_file_version, sizeof(this_file_version));

      unsigned int this_n_procs = 0;
      unsigned int this_n_threads = 0;

      in.read((char *)&this_n_procs, sizeof(this_n_procs));
      in.read((char *)&this_n_threads, sizeof(this_n_threads));

      // check the header
      if(id[0] != 'R' || id[1] != 'D')
        mooseError("Corrupted restartable data file!");

      // check the file version
      if(this_file_version > file_version)
        mooseError("Trying to restart from a newer file version - you need to update MOOSE");

      if(this_file_version < file_version)
        mooseError("Trying to restart from an older file version - you need to checkout an older version of MOOSE.");

      if(this_n_procs != n_procs)
        mooseError("Cannot restart using a different number of processors!");

      if(this_n_threads != n_threads)
        mooseError("Cannot restart using a different number of threads!");

      // number of data
      unsigned int n_data = 0;
      in.read((char *) &n_data, sizeof(n_data));

      // data names
      std::vector<std::string> data_names(n_data);

      for(unsigned int i=0; i < n_data; i++)
      {
        std::string data_name;
        char ch = 0;
        do {
          in.read(&ch, 1);
          if (ch != '\0')
            data_name += ch;
        } while (ch != '\0');
        data_names[i] = data_name;
      }

      // Grab this processor's block size
      unsigned int data_blk_size = 0;
      in.read((char *) &data_blk_size, sizeof(data_blk_size));

      for(unsigned int i=0; i < n_data; i++)
      {
        std::string current_name = data_names[i];

        unsigned int data_size = 0;
        in.read((char *) &data_size, sizeof(data_size));

        if(restartable_data.find(current_name) != restartable_data.end()) // Only restore values if they're currently being used
        {
          // std::cout<<"Loading "<<current_name<<std::endl;

          RestartableDataValue * current_data = restartable_data[current_name];
          current_data->load(in);
        }
        else
        {
          // Skip this piece of data
          in.seekg(data_size, std::ios_base::cur);
          ignored_data.push_back(current_name);
        }
      }

      in.close();
    }
  }

  if(ignored_data.size())
  {
    std::ostringstream names;

    for(unsigned int i=0; i<ignored_data.size(); i++)
      names << ignored_data[i] << "\n";

    mooseWarning("The following RestorableData was found in restart file but is being ignored:\n" << names.str());
  }
}
<|endoftext|>


<commit_before>
#include <gloperate/stages/base/MixerStage.h>

#include <glbinding/gl/gl.h>

#include <globjects/base/File.h>
#include <globjects/base/StringTemplate.h>
#include <globjects/Framebuffer.h>
#include <globjects/VertexArray.h>
#include <globjects/VertexAttributeBinding.h>
#include <globjects/Buffer.h>
#include <globjects/Program.h>
#include <globjects/Shader.h>
#include <globjects/Texture.h>

#include <gloperate/base/Environment.h>
#include <gloperate/base/ResourceManager.h>

#include <gloperate/gloperate.h>

namespace gloperate
{

CPPEXPOSE_COMPONENT(MixerStage, gloperate::Stage)

MixerStage::MixerStage(Environment * environment, const std::string & name)
: Stage(environment, "MixerStage", name)
, viewport      ("viewport", this)
, targetFBO     ("targetFBO", this)
, texture       ("texture", this)
, vertexShader  ("vertexShader", this)
, geometryShader("geometryShader", this)
, fragmentShader("fragmentShader", this)
, rendered      ("rendered", this)
, fboOut        ("fboOut", this)
, m_rebuildProgram(false)
{
    // Get data path
    std::string dataPath = gloperate::dataPath();

    // Set default values
    vertexShader  .setValue(dataPath + "/gloperate/shaders/Mixer/Mixer.vert");
    fragmentShader.setValue(dataPath + "/gloperate/shaders/Mixer/Mixer.frag");
}

MixerStage::~MixerStage()
{
}

void MixerStage::onContextInit(AbstractGLContext *)
{
}

void MixerStage::onContextDeinit(AbstractGLContext *)
{
    m_vao = nullptr;
    m_buffer = nullptr;
    m_vertexShader = nullptr;
    m_geometryShader = nullptr;
    m_fragmentShader = nullptr;
    m_program = nullptr;
}

void MixerStage::onProcess(AbstractGLContext *)
{
    // Check if geometry needs to be built
    if (!m_vao.get())
    {
        buildGeometry();
    }

    // Check if program needs to be (re-)built
    if (!m_program.get() || m_rebuildProgram)
    {
        buildProgram();
    }

    // Activate FBO
    globjects::Framebuffer * fbo = *targetFBO;
    assert(fbo);

    fbo->bind(gl::GL_FRAMEBUFFER);

    // Set viewport
    gl::glViewport(viewport->x, viewport->y, viewport->z, viewport->w);

    // Disable depth test for screen-aligned quad
    gl::glDisable(gl::GL_DEPTH_TEST);

    // Enable blending
    gl::glEnable(gl::GL_BLEND);

    // Restore OpenGL states
    gl::glEnable(gl::GL_DEPTH_TEST);

    // Bind texture
    if (*texture) {
        gl::glActiveTexture(gl::GL_TEXTURE0 + 0);
        texture->bind();
    }

    // Draw screen-aligned quad
    m_program->use();
    m_vao->drawArrays(gl::GL_TRIANGLE_STRIP, 0, 4);
    m_vao->unbind();
    m_program->release();

    // Unbind texture
    if (*texture) {
        texture->unbind();
    }

    // Unbind FBO, bind default FBO
    if (*targetFBO) {
        targetFBO->unbind(gl::GL_FRAMEBUFFER);
        globjects::Framebuffer::defaultFBO()->bind(gl::GL_FRAMEBUFFER);
    }

    // Indicate change to the output FBO
    fboOut.setValue(fbo);

    // Signal that output is valid
    rendered.setValue(true);
}

void MixerStage::onInputValueChanged(AbstractSlot * slot)
{
    // Rebuild program when shader files have changed
    if (slot == &vertexShader || slot == &fragmentShader)
    {
        m_rebuildProgram = true;
    }

    // Invalidate all outputs
    invalidateOutputs();
}

void MixerStage::buildGeometry()
{
    // Static vertices
    static const std::array<glm::vec2, 4> vertices { {
          glm::vec2( +1.f, -1.f )
        , glm::vec2( +1.f, +1.f )
        , glm::vec2( -1.f, -1.f )
        , glm::vec2( -1.f, +1.f ) } };

    // Create vertex buffer
    m_buffer = cppassist::make_unique<globjects::Buffer>();
    m_buffer->setData(vertices, gl::GL_STATIC_DRAW); // needed for some drivers

    // Create VAO
    m_vao = cppassist::make_unique<globjects::VertexArray>();

    auto binding = m_vao->binding(0);
    binding->setAttribute(0);
    binding->setBuffer(m_buffer.get(), 0, sizeof(glm::vec2));
    binding->setFormat(2, gl::GL_FLOAT, gl::GL_FALSE, 0);
    m_vao->enable(0);
}

void MixerStage::buildProgram()
{
    // Create program and load shaders
    m_program = cppassist::make_unique<globjects::Program>();
    if (auto shader = environment()->resourceManager()->load<globjects::Shader>(vertexShader.value()))
    {
        m_vertexShader = std::unique_ptr<globjects::Shader>(shader);
        m_program->attach(m_vertexShader.get());
    }
    if (auto shader = environment()->resourceManager()->load<globjects::Shader>(geometryShader.value()))
    {
        m_geometryShader = std::unique_ptr<globjects::Shader>(shader);
        m_program->attach(m_geometryShader.get());
    }
    if (auto shader = environment()->resourceManager()->load<globjects::Shader>(fragmentShader.value()))
    {
        m_fragmentShader = std::unique_ptr<globjects::Shader>(shader);
        m_program->attach(m_fragmentShader.get());
    }

    // Set uniforms
    m_program->setUniform("texColor", 0);

    // Program has been built
    m_rebuildProgram = false;
}

} // namespace gloperate
<commit_msg>MixerStage: Disable backface culling (fixes rendering on Windows)<commit_after>
#include <gloperate/stages/base/MixerStage.h>

#include <glbinding/gl/gl.h>

#include <globjects/base/File.h>
#include <globjects/base/StringTemplate.h>
#include <globjects/Framebuffer.h>
#include <globjects/VertexArray.h>
#include <globjects/VertexAttributeBinding.h>
#include <globjects/Buffer.h>
#include <globjects/Program.h>
#include <globjects/Shader.h>
#include <globjects/Texture.h>

#include <gloperate/base/Environment.h>
#include <gloperate/base/ResourceManager.h>

#include <gloperate/gloperate.h>

namespace gloperate
{

CPPEXPOSE_COMPONENT(MixerStage, gloperate::Stage)

MixerStage::MixerStage(Environment * environment, const std::string & name)
: Stage(environment, "MixerStage", name)
, viewport      ("viewport", this)
, targetFBO     ("targetFBO", this)
, texture       ("texture", this)
, vertexShader  ("vertexShader", this)
, geometryShader("geometryShader", this)
, fragmentShader("fragmentShader", this)
, rendered      ("rendered", this)
, fboOut        ("fboOut", this)
, m_rebuildProgram(false)
{
    // Get data path
    std::string dataPath = gloperate::dataPath();

    // Set default values
    vertexShader  .setValue(dataPath + "/gloperate/shaders/Mixer/Mixer.vert");
    fragmentShader.setValue(dataPath + "/gloperate/shaders/Mixer/Mixer.frag");
}

MixerStage::~MixerStage()
{
}

void MixerStage::onContextInit(AbstractGLContext *)
{
}

void MixerStage::onContextDeinit(AbstractGLContext *)
{
    m_vao = nullptr;
    m_buffer = nullptr;
    m_vertexShader = nullptr;
    m_geometryShader = nullptr;
    m_fragmentShader = nullptr;
    m_program = nullptr;
}

void MixerStage::onProcess(AbstractGLContext *)
{
    // Check if geometry needs to be built
    if (!m_vao.get())
    {
        buildGeometry();
    }

    // Check if program needs to be (re-)built
    if (!m_program.get() || m_rebuildProgram)
    {
        buildProgram();
    }

    // Activate FBO
    globjects::Framebuffer * fbo = *targetFBO;
    assert(fbo);

    fbo->bind(gl::GL_FRAMEBUFFER);

    // Set viewport
    gl::glViewport(viewport->x, viewport->y, viewport->z, viewport->w);

    // Set OpenGL states
    gl::glDisable(gl::GL_CULL_FACE);
    gl::glDisable(gl::GL_DEPTH_TEST);
    gl::glEnable(gl::GL_BLEND);

    // Bind texture
    if (*texture) {
        gl::glActiveTexture(gl::GL_TEXTURE0 + 0);
        texture->bind();
    }

    // Draw screen-aligned quad
    m_program->use();
    m_vao->drawArrays(gl::GL_TRIANGLE_STRIP, 0, 4);
    m_vao->unbind();
    m_program->release();

    // Unbind texture
    if (*texture) {
        texture->unbind();
    }

    // Unbind FBO, bind default FBO
    if (*targetFBO) {
        targetFBO->unbind(gl::GL_FRAMEBUFFER);
        globjects::Framebuffer::defaultFBO()->bind(gl::GL_FRAMEBUFFER);
    }

    // Indicate change to the output FBO
    fboOut.setValue(fbo);

    // Signal that output is valid
    rendered.setValue(true);
}

void MixerStage::onInputValueChanged(AbstractSlot * slot)
{
    // Rebuild program when shader files have changed
    if (slot == &vertexShader || slot == &fragmentShader)
    {
        m_rebuildProgram = true;
    }

    // Invalidate all outputs
    invalidateOutputs();
}

void MixerStage::buildGeometry()
{
    // Static vertices
    static const std::array<glm::vec2, 4> vertices { {
          glm::vec2( +1.f, -1.f )
        , glm::vec2( +1.f, +1.f )
        , glm::vec2( -1.f, -1.f )
        , glm::vec2( -1.f, +1.f ) } };

    // Create vertex buffer
    m_buffer = cppassist::make_unique<globjects::Buffer>();
    m_buffer->setData(vertices, gl::GL_STATIC_DRAW); // needed for some drivers

    // Create VAO
    m_vao = cppassist::make_unique<globjects::VertexArray>();

    auto binding = m_vao->binding(0);
    binding->setAttribute(0);
    binding->setBuffer(m_buffer.get(), 0, sizeof(glm::vec2));
    binding->setFormat(2, gl::GL_FLOAT, gl::GL_FALSE, 0);
    m_vao->enable(0);
}

void MixerStage::buildProgram()
{
    // Create program and load shaders
    m_program = cppassist::make_unique<globjects::Program>();
    if (auto shader = environment()->resourceManager()->load<globjects::Shader>(vertexShader.value()))
    {
        m_vertexShader = std::unique_ptr<globjects::Shader>(shader);
        m_program->attach(m_vertexShader.get());
    }
    if (auto shader = environment()->resourceManager()->load<globjects::Shader>(geometryShader.value()))
    {
        m_geometryShader = std::unique_ptr<globjects::Shader>(shader);
        m_program->attach(m_geometryShader.get());
    }
    if (auto shader = environment()->resourceManager()->load<globjects::Shader>(fragmentShader.value()))
    {
        m_fragmentShader = std::unique_ptr<globjects::Shader>(shader);
        m_program->attach(m_fragmentShader.get());
    }

    // Set uniforms
    m_program->setUniform("texColor", 0);

    // Program has been built
    m_rebuildProgram = false;
}

} // namespace gloperate
<|endoftext|>


<commit_before>//
// PROJECT:         Aspia
// FILE:            client/ui/desktop_widget.cc
// LICENSE:         GNU General Public License 3
// PROGRAMMERS:     Dmitry Chapyshev (dmitry@aspia.ru)
//

#include "client/ui/desktop_widget.h"

#include <QDebug>
#include <QPainter>
#include <QWheelEvent>

#if defined(Q_OS_WIN)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif // defined(Q_OS_WIN)

#include "base/keycode_converter.h"
#include "desktop_capture/desktop_frame_qimage.h"
#include "protocol/desktop_session.pb.h"

namespace aspia {

namespace {

constexpr quint32 kWheelMask =
    proto::desktop::PointerEvent::WHEEL_DOWN | proto::desktop::PointerEvent::WHEEL_UP;

bool isNumLockActivated()
{
#if defined(Q_OS_WIN)
    return GetKeyState(VK_NUMLOCK) != 0;
#else
#error Platform support not implemented
#endif // defined(Q_OS_WIN)
}

bool isCapsLockActivated()
{
#if defined(Q_OS_WIN)
    return GetKeyState(VK_CAPITAL) != 0;
#else
#error Platform support not implemented
#endif // defined(Q_OS_WIN)
}

} // namespace

DesktopWidget::DesktopWidget(QWidget* parent)
    : QWidget(parent)
{
    setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    setFocusPolicy(Qt::StrongFocus);
    setAttribute(Qt::WA_OpaquePaintEvent);
    setAttribute(Qt::WA_NoSystemBackground);
    setMouseTracking(true);
}

void DesktopWidget::resizeDesktopFrame(const QSize& screen_size)
{
    frame_ = DesktopFrameQImage::create(screen_size);
    resize(screen_size);
}

DesktopFrame* DesktopWidget::desktopFrame()
{
    return frame_.get();
}

void DesktopWidget::doMouseEvent(QEvent::Type event_type,
                                 const Qt::MouseButtons& buttons,
                                 const QPoint& pos,
                                 const QPoint& delta)
{
    if (!frame_ || !frame_->contains(pos.x(), pos.y()))
        return;

    quint32 mask;

    if (event_type == QMouseEvent::MouseMove)
    {
        mask = prev_mask_;
    }
    else
    {
        mask = 0;

        if (buttons & Qt::LeftButton)
            mask |= proto::desktop::PointerEvent::LEFT_BUTTON;

        if (buttons & Qt::MiddleButton)
            mask |= proto::desktop::PointerEvent::MIDDLE_BUTTON;

        if (buttons & Qt::RightButton)
            mask |= proto::desktop::PointerEvent::RIGHT_BUTTON;
    }

    int wheel_steps = 0;

    if (event_type == QEvent::Wheel)
    {
        if (delta.y() < 0)
        {
            mask |= proto::desktop::PointerEvent::WHEEL_DOWN;
            wheel_steps = -delta.y() / QWheelEvent::DefaultDeltasPerStep;
        }
        else
        {
            mask |= proto::desktop::PointerEvent::WHEEL_UP;
            wheel_steps = delta.y() / QWheelEvent::DefaultDeltasPerStep;
        }

        if (!wheel_steps)
            wheel_steps = 1;
    }

    if (prev_pos_ != pos || prev_mask_ != mask)
    {
        prev_pos_ = pos;
        prev_mask_ = mask & ~kWheelMask;

        if (mask & kWheelMask)
        {
            for (int i = 0; i < wheel_steps; ++i)
            {
                emit sendPointerEvent(pos, mask);
                emit sendPointerEvent(pos, mask & ~kWheelMask);
            }
        }
        else
        {
            emit sendPointerEvent(pos, mask);
        }
    }
}

void DesktopWidget::doKeyEvent(QKeyEvent* event)
{
    int key = event->key();
    if (key == Qt::Key_CapsLock || key == Qt::Key_NumLock)
        return;

    quint32 flags = ((event->type() == QEvent::KeyPress) ? proto::desktop::KeyEvent::PRESSED : 0);

    flags |= (isCapsLockActivated() ? proto::desktop::KeyEvent::CAPSLOCK : 0);
    flags |= (isNumLockActivated() ? proto::desktop::KeyEvent::NUMLOCK : 0);

    quint32 usb_keycode = KeycodeConverter::nativeKeycodeToUsbKeycode(event->nativeScanCode());
    if (usb_keycode == KeycodeConverter::invalidUsbKeycode())
        return;

    emit sendKeyEvent(usb_keycode, flags);
}

void DesktopWidget::executeKeySequense(int key_sequence)
{
    const quint32 kUsbCodeLeftAlt = 0x0700e2;
    const quint32 kUsbCodeLeftCtrl = 0x0700e0;
    const quint32 kUsbCodeLeftShift = 0x0700e1;
    const quint32 kUsbCodeLeftMeta = 0x0700e3;

    QVector<int> keys;

    if (key_sequence & Qt::AltModifier)
        keys.push_back(kUsbCodeLeftAlt);

    if (key_sequence & Qt::ControlModifier)
        keys.push_back(kUsbCodeLeftCtrl);

    if (key_sequence & Qt::ShiftModifier)
        keys.push_back(kUsbCodeLeftShift);

    if (key_sequence & Qt::MetaModifier)
        keys.push_back(kUsbCodeLeftMeta);

    quint32 key = KeycodeConverter::qtKeycodeToUsbKeycode(key_sequence & ~Qt::KeyboardModifierMask);
    if (key == KeycodeConverter::invalidUsbKeycode())
        return;

    keys.push_back(key);

    quint32 flags = proto::desktop::KeyEvent::PRESSED;

    flags |= (isCapsLockActivated() ? proto::desktop::KeyEvent::CAPSLOCK : 0);
    flags |= (isNumLockActivated() ? proto::desktop::KeyEvent::NUMLOCK : 0);

    for (auto it = keys.begin(); it != keys.end(); ++it)
        emit sendKeyEvent(*it, flags);

    flags ^= proto::desktop::KeyEvent::PRESSED;

    for (auto it = keys.rbegin(); it != keys.rend(); ++it)
        emit sendKeyEvent(*it, flags);
}

void DesktopWidget::paintEvent(QPaintEvent* /* event */)
{
    if (frame_)
    {
        QPainter painter(this);
        painter.drawImage(rect(), frame_->constImage());
    }
}

void DesktopWidget::mouseMoveEvent(QMouseEvent* event)
{
    doMouseEvent(event->type(), event->buttons(), event->pos());
}

void DesktopWidget::mousePressEvent(QMouseEvent* event)
{
    doMouseEvent(event->type(), event->buttons(), event->pos());
}

void DesktopWidget::mouseReleaseEvent(QMouseEvent* event)
{
    doMouseEvent(event->type(), event->buttons(), event->pos());
}

void DesktopWidget::mouseDoubleClickEvent(QMouseEvent* event)
{
    doMouseEvent(event->type(), event->buttons(), event->pos());
}

void DesktopWidget::wheelEvent(QWheelEvent* event)
{
    doMouseEvent(event->type(), event->buttons(), event->pos(), event->angleDelta());
}

void DesktopWidget::keyPressEvent(QKeyEvent* event)
{
    doKeyEvent(event);
}

void DesktopWidget::keyReleaseEvent(QKeyEvent* event)
{
    doKeyEvent(event);
}

void DesktopWidget::leaveEvent(QEvent* event)
{
    // When the mouse cursor leaves the widget area, release all the mouse buttons.
    if (prev_mask_ != 0)
    {
        emit sendPointerEvent(prev_pos_, 0);
        prev_mask_ = 0;
    }

    QWidget::leaveEvent(event);
}

} // namespace aspia
<commit_msg>- Using const iterators.<commit_after>//
// PROJECT:         Aspia
// FILE:            client/ui/desktop_widget.cc
// LICENSE:         GNU General Public License 3
// PROGRAMMERS:     Dmitry Chapyshev (dmitry@aspia.ru)
//

#include "client/ui/desktop_widget.h"

#include <QDebug>
#include <QPainter>
#include <QWheelEvent>

#if defined(Q_OS_WIN)
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif // defined(Q_OS_WIN)

#include "base/keycode_converter.h"
#include "desktop_capture/desktop_frame_qimage.h"
#include "protocol/desktop_session.pb.h"

namespace aspia {

namespace {

constexpr quint32 kWheelMask =
    proto::desktop::PointerEvent::WHEEL_DOWN | proto::desktop::PointerEvent::WHEEL_UP;

bool isNumLockActivated()
{
#if defined(Q_OS_WIN)
    return GetKeyState(VK_NUMLOCK) != 0;
#else
#error Platform support not implemented
#endif // defined(Q_OS_WIN)
}

bool isCapsLockActivated()
{
#if defined(Q_OS_WIN)
    return GetKeyState(VK_CAPITAL) != 0;
#else
#error Platform support not implemented
#endif // defined(Q_OS_WIN)
}

} // namespace

DesktopWidget::DesktopWidget(QWidget* parent)
    : QWidget(parent)
{
    setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
    setFocusPolicy(Qt::StrongFocus);
    setAttribute(Qt::WA_OpaquePaintEvent);
    setAttribute(Qt::WA_NoSystemBackground);
    setMouseTracking(true);
}

void DesktopWidget::resizeDesktopFrame(const QSize& screen_size)
{
    frame_ = DesktopFrameQImage::create(screen_size);
    resize(screen_size);
}

DesktopFrame* DesktopWidget::desktopFrame()
{
    return frame_.get();
}

void DesktopWidget::doMouseEvent(QEvent::Type event_type,
                                 const Qt::MouseButtons& buttons,
                                 const QPoint& pos,
                                 const QPoint& delta)
{
    if (!frame_ || !frame_->contains(pos.x(), pos.y()))
        return;

    quint32 mask;

    if (event_type == QMouseEvent::MouseMove)
    {
        mask = prev_mask_;
    }
    else
    {
        mask = 0;

        if (buttons & Qt::LeftButton)
            mask |= proto::desktop::PointerEvent::LEFT_BUTTON;

        if (buttons & Qt::MiddleButton)
            mask |= proto::desktop::PointerEvent::MIDDLE_BUTTON;

        if (buttons & Qt::RightButton)
            mask |= proto::desktop::PointerEvent::RIGHT_BUTTON;
    }

    int wheel_steps = 0;

    if (event_type == QEvent::Wheel)
    {
        if (delta.y() < 0)
        {
            mask |= proto::desktop::PointerEvent::WHEEL_DOWN;
            wheel_steps = -delta.y() / QWheelEvent::DefaultDeltasPerStep;
        }
        else
        {
            mask |= proto::desktop::PointerEvent::WHEEL_UP;
            wheel_steps = delta.y() / QWheelEvent::DefaultDeltasPerStep;
        }

        if (!wheel_steps)
            wheel_steps = 1;
    }

    if (prev_pos_ != pos || prev_mask_ != mask)
    {
        prev_pos_ = pos;
        prev_mask_ = mask & ~kWheelMask;

        if (mask & kWheelMask)
        {
            for (int i = 0; i < wheel_steps; ++i)
            {
                emit sendPointerEvent(pos, mask);
                emit sendPointerEvent(pos, mask & ~kWheelMask);
            }
        }
        else
        {
            emit sendPointerEvent(pos, mask);
        }
    }
}

void DesktopWidget::doKeyEvent(QKeyEvent* event)
{
    int key = event->key();
    if (key == Qt::Key_CapsLock || key == Qt::Key_NumLock)
        return;

    quint32 flags = ((event->type() == QEvent::KeyPress) ? proto::desktop::KeyEvent::PRESSED : 0);

    flags |= (isCapsLockActivated() ? proto::desktop::KeyEvent::CAPSLOCK : 0);
    flags |= (isNumLockActivated() ? proto::desktop::KeyEvent::NUMLOCK : 0);

    quint32 usb_keycode = KeycodeConverter::nativeKeycodeToUsbKeycode(event->nativeScanCode());
    if (usb_keycode == KeycodeConverter::invalidUsbKeycode())
        return;

    emit sendKeyEvent(usb_keycode, flags);
}

void DesktopWidget::executeKeySequense(int key_sequence)
{
    const quint32 kUsbCodeLeftAlt = 0x0700e2;
    const quint32 kUsbCodeLeftCtrl = 0x0700e0;
    const quint32 kUsbCodeLeftShift = 0x0700e1;
    const quint32 kUsbCodeLeftMeta = 0x0700e3;

    QVector<int> keys;

    if (key_sequence & Qt::AltModifier)
        keys.push_back(kUsbCodeLeftAlt);

    if (key_sequence & Qt::ControlModifier)
        keys.push_back(kUsbCodeLeftCtrl);

    if (key_sequence & Qt::ShiftModifier)
        keys.push_back(kUsbCodeLeftShift);

    if (key_sequence & Qt::MetaModifier)
        keys.push_back(kUsbCodeLeftMeta);

    quint32 key = KeycodeConverter::qtKeycodeToUsbKeycode(key_sequence & ~Qt::KeyboardModifierMask);
    if (key == KeycodeConverter::invalidUsbKeycode())
        return;

    keys.push_back(key);

    quint32 flags = proto::desktop::KeyEvent::PRESSED;

    flags |= (isCapsLockActivated() ? proto::desktop::KeyEvent::CAPSLOCK : 0);
    flags |= (isNumLockActivated() ? proto::desktop::KeyEvent::NUMLOCK : 0);

    for (auto it = keys.cbegin(); it != keys.cend(); ++it)
        emit sendKeyEvent(*it, flags);

    flags ^= proto::desktop::KeyEvent::PRESSED;

    for (auto it = keys.crbegin(); it != keys.crend(); ++it)
        emit sendKeyEvent(*it, flags);
}

void DesktopWidget::paintEvent(QPaintEvent* /* event */)
{
    if (frame_)
    {
        QPainter painter(this);
        painter.drawImage(rect(), frame_->constImage());
    }
}

void DesktopWidget::mouseMoveEvent(QMouseEvent* event)
{
    doMouseEvent(event->type(), event->buttons(), event->pos());
}

void DesktopWidget::mousePressEvent(QMouseEvent* event)
{
    doMouseEvent(event->type(), event->buttons(), event->pos());
}

void DesktopWidget::mouseReleaseEvent(QMouseEvent* event)
{
    doMouseEvent(event->type(), event->buttons(), event->pos());
}

void DesktopWidget::mouseDoubleClickEvent(QMouseEvent* event)
{
    doMouseEvent(event->type(), event->buttons(), event->pos());
}

void DesktopWidget::wheelEvent(QWheelEvent* event)
{
    doMouseEvent(event->type(), event->buttons(), event->pos(), event->angleDelta());
}

void DesktopWidget::keyPressEvent(QKeyEvent* event)
{
    doKeyEvent(event);
}

void DesktopWidget::keyReleaseEvent(QKeyEvent* event)
{
    doKeyEvent(event);
}

void DesktopWidget::leaveEvent(QEvent* event)
{
    // When the mouse cursor leaves the widget area, release all the mouse buttons.
    if (prev_mask_ != 0)
    {
        emit sendPointerEvent(prev_pos_, 0);
        prev_mask_ = 0;
    }

    QWidget::leaveEvent(event);
}

} // namespace aspia
<|endoftext|>


<commit_before>#include "details/pass/build-ast-to-ir/scope.h"
#include "details/grammar/nany.h"
#include "libnanyc-config.h"

using namespace Yuni;

namespace Nany
{
namespace IR
{
namespace Producer
{

	void Scope::emitDebugpos(AST::Node& node)
	{
		if (node.offset > 0)
		{
			auto it = context.offsetToLine.lower_bound(node.offset);
			if (it != context.offsetToLine.end())
			{
				if (it->first == node.offset or (--it != context.offsetToLine.end()))
					addDebugCurrentPosition(it->second, node.offset - it->first);
			}
		}
	}

	void Scope::doEmitTmplParameters()
	{
		if (!!lastPushedTmplParams)
		{
			if (not lastPushedTmplParams->empty())
			{
				auto& outIR = sequence();
				for (auto& pair: *lastPushedTmplParams)
				{
					if (pair.second.empty())
						outIR.emitTPush(pair.first);
					else
						outIR.emitTPush(pair.first, pair.second);
				}
			}
			// clear
			lastPushedTmplParams = nullptr;
		}
	}

	AnyString Scope::getSymbolNameFromASTNode(AST::Node& node)
	{
		assert(node.rule == AST::rgSymbolName);
		assert(node.children.size() == 1);

		auto& identifier = node.children.front();
		if (unlikely(identifier.rule != AST::rgIdentifier))
		{
			unexpectedNode(node, "expected identifier");
			return AnyString{};
		}

		if (unlikely(identifier.text.size() > Config::maxSymbolNameLength))
		{
			auto err = error(node) << "identifier name too long";
			err.message.origins.location.pos.offsetEnd = err.message.origins.location.pos.offset + identifier.text.size();
			return AnyString{};
		}
		return identifier.text;
	}

	void Scope::checkForUnknownAttributes() const
	{
		assert(!!attributes);

		if (unlikely(not attributes->flags.empty()))
		{
			if (unlikely(context.ignoreAtoms))
				return;
			auto& attrs = *attributes;
			auto& node  = attrs.node;

			if (unlikely(attrs.flags(Attributes::Flag::pushSynthetic)))
				error(node, "invalid use of expr attribute '__nanyc_synthetic'");

			if (attrs.flags(Attributes::Flag::shortcircuit))
				error(node, "invalid use of func attribute 'shortcircuit'");

			if (attrs.flags(Attributes::Flag::doNotSuggest))
				error(node, "invalid use of func attribute 'nosuggest'");

			if (attrs.flags(Attributes::Flag::builtinAlias))
				error(node, "invalid use of func attribute 'builtinalias'");

			if (attrs.flags(Attributes::Flag::threadproc))
				error(node, "invalid use of func attribute 'thread'");
		}
	}

} // namespace Producer
} // namespace IR
} // namespace Nany
<commit_msg>ast2ir: fixed crash when the iterator is already at the begining (clang)<commit_after>#include "details/pass/build-ast-to-ir/scope.h"
#include "details/grammar/nany.h"
#include "libnanyc-config.h"

using namespace Yuni;

namespace Nany
{
namespace IR
{
namespace Producer
{

	void Scope::emitDebugpos(AST::Node& node)
	{
		if (node.offset > 0)
		{
			auto it = context.offsetToLine.lower_bound(node.offset);
			if (it != context.offsetToLine.end())
			{
				bool emit = (it->first == node.offset);
				if (not emit and context.offsetToLine.begin() != it)
					emit = (--it != context.offsetToLine.end());
				if (emit)
					addDebugCurrentPosition(it->second, node.offset - it->first);
			}
		}
	}

	void Scope::doEmitTmplParameters()
	{
		if (!!lastPushedTmplParams)
		{
			if (not lastPushedTmplParams->empty())
			{
				auto& outIR = sequence();
				for (auto& pair: *lastPushedTmplParams)
				{
					if (pair.second.empty())
						outIR.emitTPush(pair.first);
					else
						outIR.emitTPush(pair.first, pair.second);
				}
			}
			// clear
			lastPushedTmplParams = nullptr;
		}
	}

	AnyString Scope::getSymbolNameFromASTNode(AST::Node& node)
	{
		assert(node.rule == AST::rgSymbolName);
		assert(node.children.size() == 1);

		auto& identifier = node.children.front();
		if (unlikely(identifier.rule != AST::rgIdentifier))
		{
			unexpectedNode(node, "expected identifier");
			return AnyString{};
		}

		if (unlikely(identifier.text.size() > Config::maxSymbolNameLength))
		{
			auto err = error(node) << "identifier name too long";
			err.message.origins.location.pos.offsetEnd = err.message.origins.location.pos.offset + identifier.text.size();
			return AnyString{};
		}
		return identifier.text;
	}

	void Scope::checkForUnknownAttributes() const
	{
		assert(!!attributes);

		if (unlikely(not attributes->flags.empty()))
		{
			if (unlikely(context.ignoreAtoms))
				return;
			auto& attrs = *attributes;
			auto& node  = attrs.node;

			if (unlikely(attrs.flags(Attributes::Flag::pushSynthetic)))
				error(node, "invalid use of expr attribute '__nanyc_synthetic'");

			if (attrs.flags(Attributes::Flag::shortcircuit))
				error(node, "invalid use of func attribute 'shortcircuit'");

			if (attrs.flags(Attributes::Flag::doNotSuggest))
				error(node, "invalid use of func attribute 'nosuggest'");

			if (attrs.flags(Attributes::Flag::builtinAlias))
				error(node, "invalid use of func attribute 'builtinalias'");

			if (attrs.flags(Attributes::Flag::threadproc))
				error(node, "invalid use of func attribute 'thread'");
		}
	}

} // namespace Producer
} // namespace IR
} // namespace Nany
<|endoftext|>


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

#include <QSqlDatabase>
#include <QSqlQuery>
#include <QSqlRecord>
#include <QSqlError>
#include <QVariant>
#include <vector>
#include "gams.h"
#include <iostream>

using namespace std;
using namespace gams;

string getModelText()
{
    return " Sets                                                                       \n"
           "      i   canning plants                                                    \n"
           "      j   markets                                                           \n"
           "                                                                            \n"
           " Parameters                                                                 \n"
           "      a(i)   capacity of plant i in cases                                   \n"
           "      b(j)   demand at market j in cases                                    \n"
           "      d(i,j) distance in thousands of miles                                 \n"
           " Scalar f  freight in dollars per case per thousand miles /90/;             \n"
           "                                                                            \n"
           "$if not set gdxincname $abort 'no include file name for data file provided' \n"
           "$gdxin %gdxincname%                                                         \n"
           "$load i j a b d                                                             \n"
           "$gdxin                                                                      \n"
           "                                                                            \n"
           " Parameter c(i,j)  transport cost in thousands of dollars per case ;        \n"
           "                                                                            \n"
           "           c(i,j) = f * d(i,j) / 1000 ;                                     \n"
           "                                                                            \n"
           " Variables                                                                  \n"
           "      x(i,j)  shipment quantities in cases                                  \n"
           "      z       total transportation costs in thousands of dollars ;          \n"
           "                                                                            \n"
           " Positive Variable x ;                                                      \n"
           "                                                                            \n"
           " Equations                                                                  \n"
           "      cost        define objective function                                 \n"
           "      supply(i)   observe supply limit at plant i                           \n"
           "      demand(j)   satisfy demand at market j ;                              \n"
           "                                                                            \n"
           " cost ..        z  =e=  sum((i,j), c(i,j)*x(i,j)) ;                         \n"
           "                                                                            \n"
           " supply(i) ..   sum(j, x(i,j))  =l=  a(i) ;                                 \n"
           "                                                                            \n"
           " demand(j) ..   sum(i, x(i,j))  =g=  b(j) ;                                 \n"
           "                                                                            \n"
           " Model transport /all/ ;                                                    \n"
           "                                                                            \n"
           " Solve transport using lp minimizing z ;                                    \n"
           "                                                                            \n"
           " Display x.l, x.m ;                                                         \n"
           "                                                                            \n";
}

void readSet(QSqlDatabase sqlDb, GAMSDatabase db, string strAccessSelect, string setName, int setDim, string setExp = "")
{
    QSqlQuery query(sqlDb);
    if (!query.exec(strAccessSelect.c_str()))
    {
        cout << "Error executing query on set '" << setName << "'" << endl;
        cout << query.lastError().text().toStdString() << endl;
        exit(1);
    }
    if (query.size() && (query.record().count() != setDim))
    {
        cout << "Number of fields in select statement does not match setDim" << endl;
        exit(1);
    }

    GAMSSet i = db.addSet(setName, setDim, setExp);
    vector<string> keys = vector<string>(setDim);

    while (query.next())
    {
        for (int idx = 0; idx < setDim; idx++)
            keys[idx] = query.value(idx).toString().toStdString();
        i.addRecord(keys);
    }
}

void readParameter(QSqlDatabase sqlDb, GAMSDatabase db, string strAccessSelect, string parName, int parDim, string parExp = "")
{
    QSqlQuery query(sqlDb);
    if (!query.exec(strAccessSelect.c_str()))
    {
        cout << "Error executing query on parameter '" << parName << "'" << endl;
        cout << query.lastError().text().toStdString() << endl;
        exit(1);
    }
    if (query.size() && (query.record().count() != parDim+1))
    {
        cout << "Number of fields in select statement does not match parDim" << endl;
        exit(1);
    }

    GAMSParameter a = db.addParameter(parName, parDim, parExp);
    vector<string> keys = vector<string>(parDim);

    while (query.next())
    {
        for (int idx = 0; idx < parDim; idx++)
            keys[idx] = query.value(idx).toString().toStdString();
        a.addRecord(keys).setValue(query.value(parDim).toDouble());
    }
}

GAMSDatabase readFromAccess(GAMSWorkspace ws)
{
    GAMSDatabase db = ws.addDatabase();

    QSqlDatabase sqlDb = QSqlDatabase::addDatabase("QODBC", "readConnection");

    QString strAccessConn = ("Driver={Microsoft Access Driver (*.mdb, *.accdb)};DSN='';DBQ=" + ws.systemDirectory() \
                             + cPathSep + "apifiles" + cPathSep + "Data" + cPathSep + "transport.accdb").c_str();
    sqlDb.setDatabaseName(strAccessConn);

    if(sqlDb.open())
    {
        // read GAMS sets
        readSet(sqlDb, db, "SELECT Plant FROM Plant", "i", 1, "canning plants");
        readSet(sqlDb, db, "SELECT Market FROM Market", "j", 1, "markets");

        // read GAMS parameters
        readParameter(sqlDb, db, "SELECT Plant,Capacity FROM Plant", "a", 1, "capacity of plant i in cases");
        readParameter(sqlDb, db, "SELECT Market,Demand FROM Market", "b", 1, "demand at market j in cases");
        readParameter(sqlDb, db, "SELECT Plant,Market,Distance FROM Distance", "d", 2, "distance in thousands of miles");
        sqlDb.close();
    }
    else
    {
        cout << "Error: Failed to create a database connection. " << sqlDb.lastError().text().toStdString() << endl;
        exit(1);
    }
    return db;
}

void writeVariable(QSqlDatabase sqlDb, GAMSDatabase db, string varName, vector<string> domains)
{
    GAMSVariable var = db.getVariable(varName);
    if(domains.size() != var.dim())
    {
        cout << "Number of column names does not match the dimension of the variable." << endl;
        exit(1);
    }

    // delete table varName if it exists already
    QSqlQuery query(sqlDb);
    query.exec(("drop table " + varName).c_str());

    string queryStr = "create table " + varName + "(";
    for (string dom : domains)
        queryStr += dom + " varchar(64), ";
    queryStr += "lvl double)";

    query.exec(queryStr.c_str());

    for (GAMSVariableRecord rec : var)
    {
        queryStr = "insert into " + varName + "(";
        for (string dom : domains)
            queryStr += dom + ", ";
        queryStr += "lvl) values (";
        for (string key : rec.keys())
            queryStr += "'" + key + "', ";
        queryStr += std::to_string(rec.level()) + ")";
        if(!query.exec(queryStr.c_str()))
        {
            cout << "Error: Failed to write variable to the database" << endl;
            cout << sqlDb.lastError().text().toStdString() << endl;
            exit(1);
        }
    }
}

void writeToAccess(GAMSWorkspace ws, GAMSDatabase db)
{
    // connect to database
    QSqlDatabase sqlDb = QSqlDatabase::addDatabase("QODBC", "writeConnection");

    QString strAccessConn = ("Driver={Microsoft Access Driver (*.mdb, *.accdb)};DSN='';DBQ=" + ws.systemDirectory() \
                             + cPathSep + "apifiles" + cPathSep + "Data" + cPathSep + "transport.accdb").c_str();
    sqlDb.setDatabaseName(strAccessConn);

    if(sqlDb.open())
    {
        // write levels of variable x
        vector<string> domains{"i", "j"};
        writeVariable(sqlDb, db, "x", domains);
        sqlDb.close();
    }
    else
    {
        cout << "Error: Failed to create a database connection. " << sqlDb.lastError().text().toStdString() << endl;
        exit(1);
    }
}

int main(int argc, char* argv[])
{
    cout << "---------- Transport 9 --------------" << endl;

    GAMSWorkspaceInfo wsInfo;
    if (argc > 1)
        wsInfo.setSystemDirectory(argv[1]);
    GAMSWorkspace ws(wsInfo);

    // fill GAMSDatabase by reading from Access
    GAMSDatabase db = readFromAccess(ws);

    // run job
    GAMSOptions opt = ws.addOptions();
    GAMSJob t9 = ws.addJobFromString(getModelText());
    opt.setDefine("gdxincname", db.name());
    opt.setAllModelTypes("xpress");
    t9.run(opt, db);
    for (GAMSVariableRecord rec : t9.outDB().getVariable("x"))
        cout << "x(" << rec.key(0) << "," << rec.key(1) << "):" << " level=" << rec.level() << " marginal=" << rec.marginal() << endl;
    // write results into Access file
    writeToAccess(ws, t9.outDB());

    return 0;
}

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

#include <QtSql>
#include <vector>
#include "gams.h"
#include <iostream>

using namespace std;
using namespace gams;

string getModelText()
{
    return " Sets                                                                       \n"
           "      i   canning plants                                                    \n"
           "      j   markets                                                           \n"
           "                                                                            \n"
           " Parameters                                                                 \n"
           "      a(i)   capacity of plant i in cases                                   \n"
           "      b(j)   demand at market j in cases                                    \n"
           "      d(i,j) distance in thousands of miles                                 \n"
           " Scalar f  freight in dollars per case per thousand miles /90/;             \n"
           "                                                                            \n"
           "$if not set gdxincname $abort 'no include file name for data file provided' \n"
           "$gdxin %gdxincname%                                                         \n"
           "$load i j a b d                                                             \n"
           "$gdxin                                                                      \n"
           "                                                                            \n"
           " Parameter c(i,j)  transport cost in thousands of dollars per case ;        \n"
           "                                                                            \n"
           "           c(i,j) = f * d(i,j) / 1000 ;                                     \n"
           "                                                                            \n"
           " Variables                                                                  \n"
           "      x(i,j)  shipment quantities in cases                                  \n"
           "      z       total transportation costs in thousands of dollars ;          \n"
           "                                                                            \n"
           " Positive Variable x ;                                                      \n"
           "                                                                            \n"
           " Equations                                                                  \n"
           "      cost        define objective function                                 \n"
           "      supply(i)   observe supply limit at plant i                           \n"
           "      demand(j)   satisfy demand at market j ;                              \n"
           "                                                                            \n"
           " cost ..        z  =e=  sum((i,j), c(i,j)*x(i,j)) ;                         \n"
           "                                                                            \n"
           " supply(i) ..   sum(j, x(i,j))  =l=  a(i) ;                                 \n"
           "                                                                            \n"
           " demand(j) ..   sum(i, x(i,j))  =g=  b(j) ;                                 \n"
           "                                                                            \n"
           " Model transport /all/ ;                                                    \n"
           "                                                                            \n"
           " Solve transport using lp minimizing z ;                                    \n"
           "                                                                            \n"
           " Display x.l, x.m ;                                                         \n"
           "                                                                            \n";
}

void readSet(QSqlDatabase sqlDb, GAMSDatabase db, string strAccessSelect, string setName, int setDim, string setExp = "")
{
    QSqlQuery query(sqlDb);
    if (!query.exec(strAccessSelect.c_str()))
    {
        cout << "Error executing query on set '" << setName << "'" << endl;
        cout << query.lastError().text().toStdString() << endl;
        exit(1);
    }
    if (query.size() && (query.record().count() != setDim))
    {
        cout << "Number of fields in select statement does not match setDim" << endl;
        exit(1);
    }

    GAMSSet i = db.addSet(setName, setDim, setExp);
    vector<string> keys = vector<string>(setDim);

    while (query.next())
    {
        for (int idx = 0; idx < setDim; idx++)
            keys[idx] = query.value(idx).toString().toStdString();
        i.addRecord(keys);
    }
}

void readParameter(QSqlDatabase sqlDb, GAMSDatabase db, string strAccessSelect, string parName, int parDim, string parExp = "")
{
    QSqlQuery query(sqlDb);
    if (!query.exec(strAccessSelect.c_str()))
    {
        cout << "Error executing query on parameter '" << parName << "'" << endl;
        cout << query.lastError().text().toStdString() << endl;
        exit(1);
    }
    if (query.size() && (query.record().count() != parDim+1))
    {
        cout << "Number of fields in select statement does not match parDim" << endl;
        exit(1);
    }

    GAMSParameter a = db.addParameter(parName, parDim, parExp);
    vector<string> keys = vector<string>(parDim);

    while (query.next())
    {
        for (int idx = 0; idx < parDim; idx++)
            keys[idx] = query.value(idx).toString().toStdString();
        a.addRecord(keys).setValue(query.value(parDim).toDouble());
    }
}

GAMSDatabase readFromAccess(GAMSWorkspace ws)
{
    GAMSDatabase db = ws.addDatabase();

    QSqlDatabase sqlDb = QSqlDatabase::addDatabase("QODBC", "readConnection");

    QString strAccessConn = ("Driver={Microsoft Access Driver (*.mdb, *.accdb)};DSN='';DBQ=" + ws.systemDirectory() \
                             + cPathSep + "apifiles" + cPathSep + "Data" + cPathSep + "transport.accdb").c_str();
    sqlDb.setDatabaseName(strAccessConn);

    if(sqlDb.open())
    {
        // read GAMS sets
        readSet(sqlDb, db, "SELECT Plant FROM Plant", "i", 1, "canning plants");
        readSet(sqlDb, db, "SELECT Market FROM Market", "j", 1, "markets");

        // read GAMS parameters
        readParameter(sqlDb, db, "SELECT Plant,Capacity FROM Plant", "a", 1, "capacity of plant i in cases");
        readParameter(sqlDb, db, "SELECT Market,Demand FROM Market", "b", 1, "demand at market j in cases");
        readParameter(sqlDb, db, "SELECT Plant,Market,Distance FROM Distance", "d", 2, "distance in thousands of miles");
        sqlDb.close();
    }
    else
    {
        cout << "Error: Failed to create a database connection. " << sqlDb.lastError().text().toStdString() << endl;
        exit(1);
    }
    return db;
}

void writeVariable(QSqlDatabase sqlDb, GAMSDatabase db, string varName, vector<string> domains)
{
    GAMSVariable var = db.getVariable(varName);
    if(domains.size() != var.dim())
    {
        cout << "Number of column names does not match the dimension of the variable." << endl;
        exit(1);
    }

    // delete table varName if it exists already
    QSqlQuery query(sqlDb);
    query.exec(("drop table " + varName).c_str());

    string queryStr = "create table " + varName + "(";
    for (string dom : domains)
        queryStr += dom + " varchar(64), ";
    queryStr += "lvl double)";

    query.exec(queryStr.c_str());

    for (GAMSVariableRecord rec : var)
    {
        queryStr = "insert into " + varName + "(";
        for (string dom : domains)
            queryStr += dom + ", ";
        queryStr += "lvl) values (";
        for (string key : rec.keys())
            queryStr += "'" + key + "', ";
        queryStr += std::to_string(rec.level()) + ")";
        if(!query.exec(queryStr.c_str()))
        {
            cout << "Error: Failed to write variable to the database" << endl;
            cout << sqlDb.lastError().text().toStdString() << endl;
            exit(1);
        }
    }
}

void writeToAccess(GAMSWorkspace ws, GAMSDatabase db)
{
    // connect to database
    QSqlDatabase sqlDb = QSqlDatabase::addDatabase("QODBC", "writeConnection");

    QString strAccessConn = ("Driver={Microsoft Access Driver (*.mdb, *.accdb)};DSN='';DBQ=" + ws.systemDirectory() \
                             + cPathSep + "apifiles" + cPathSep + "Data" + cPathSep + "transport.accdb").c_str();
    sqlDb.setDatabaseName(strAccessConn);

    if(sqlDb.open())
    {
        // write levels of variable x
        vector<string> domains{"i", "j"};
        writeVariable(sqlDb, db, "x", domains);
        sqlDb.close();
    }
    else
    {
        cout << "Error: Failed to create a database connection. " << sqlDb.lastError().text().toStdString() << endl;
        exit(1);
    }
}

int main(int argc, char* argv[])
{
    cout << "---------- Transport 9 --------------" << endl;

    GAMSWorkspaceInfo wsInfo;
    if (argc > 1)
        wsInfo.setSystemDirectory(argv[1]);
    GAMSWorkspace ws(wsInfo);

    // fill GAMSDatabase by reading from Access
    GAMSDatabase db = readFromAccess(ws);

    // run job
    GAMSOptions opt = ws.addOptions();
    GAMSJob t9 = ws.addJobFromString(getModelText());
    opt.setDefine("gdxincname", db.name());
    opt.setAllModelTypes("xpress");
    t9.run(opt, db);
    for (GAMSVariableRecord rec : t9.outDB().getVariable("x"))
        cout << "x(" << rec.key(0) << "," << rec.key(1) << "):" << " level=" << rec.level() << " marginal=" << rec.marginal() << endl;
    // write results into Access file
    writeToAccess(ws, t9.outDB());

    return 0;
}

<|endoftext|>