text:
// Copyright (c) 2012-2018 The Elastos Open Source Project
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "IDChainSubWallet.h"
#include "SidechainSubWallet.h"
#include "MainchainSubWallet.h"
#include "SubWallet.h"
#include "MasterWallet.h"
#include "TokenchainSubWallet.h"

#include <SDK/Plugin/Transaction/Payload/RegisterIdentification.h>
#include <SDK/Common/Utils.h>
#include <SDK/Common/Log.h>
#include <SDK/Common/ErrorChecker.h>
#include <SDK/WalletCore/BIPs/Mnemonic.h>
#include <SDK/WalletCore/BIPs/Base58.h>
#include <SDK/WalletCore/Crypto/AES.h>
#include <SDK/WalletCore/KeyStore/CoinInfo.h>
#include <SDK/SpvService/Config.h>
#include <CMakeConfig.h>

#include <vector>
#include <boost/filesystem.hpp>

#define COIN_COINFIG_FILE "CoinConfig.json"

namespace fs = boost::filesystem;

namespace Elastos {
	namespace ElaWallet {

		MasterWallet::MasterWallet(const std::string &id,
								   const std::string &rootPath,
								   const std::string &dataPath,
								   bool p2pEnable,
								   MasterWalletInitFrom from) :
				_id(id),
				_rootPath(rootPath),
				_dataPath(dataPath),
				_p2pEnable(p2pEnable),
				_initFrom(from),
				_earliestPeerTime(0) {

			_config = ConfigPtr(new Config(_rootPath));
			_localStore = LocalStorePtr(new LocalStore(_dataPath + "/" + _id));
			_account = AccountPtr(new Account(_localStore));

			if (_account->GetSignType() == Account::MultiSign)
				_idAgentImpl = nullptr;
			else
				_idAgentImpl = boost::shared_ptr<IDAgentImpl>(new IDAgentImpl(this));
		}

		MasterWallet::MasterWallet(const std::string &id,
								   const std::string &mnemonic,
								   const std::string &passphrase,
								   const std::string &payPassword,
								   bool singleAddress,
								   bool p2pEnable,
								   const std::string &rootPath,
								   const std::string &dataPath,
								   time_t earliestPeerTime,
								   MasterWalletInitFrom from) :
				_id(id),
				_rootPath(rootPath),
				_dataPath(dataPath),
				_p2pEnable(p2pEnable),
				_earliestPeerTime(earliestPeerTime),
				_initFrom(from) {

			Mnemonic m(_rootPath);
			ErrorChecker::CheckLogic(!m.Validate(mnemonic), Error::Mnemonic, "Invalid mnemonic");

			_config = ConfigPtr(new Config(_rootPath));
			_localStore = LocalStorePtr(new LocalStore(_dataPath + "/" + _id, mnemonic, passphrase,
													   singleAddress, payPassword));
			_account = AccountPtr(new Account(_localStore));

			_idAgentImpl = boost::shared_ptr<IDAgentImpl>(new IDAgentImpl(this));

			_localStore->Save();
		}

		MasterWallet::MasterWallet(const std::string &id,
								   const nlohmann::json &keystoreContent,
								   const std::string &backupPassword,
								   const std::string &payPassword,
								   const std::string &rootPath,
								   const std::string &dataPath,
								   bool p2pEnable,
								   MasterWalletInitFrom from) :
				_id(id),
				_rootPath(rootPath),
				_dataPath(dataPath),
				_p2pEnable(p2pEnable),
				_earliestPeerTime(0),
				_initFrom(from) {

			KeyStore keystore;
			keystore.Import(keystoreContent, backupPassword);

			_config = ConfigPtr(new Config(_rootPath));
			_localStore = LocalStorePtr(new LocalStore(_dataPath + "/" + _id, keystore.WalletJson(), payPassword));
			_account = AccountPtr(new Account(_localStore));

			if (_account->GetSignType() == Account::MultiSign) {
				_idAgentImpl = nullptr;
			} else {
				_idAgentImpl = boost::shared_ptr<IDAgentImpl>(new IDAgentImpl(this));
			}

			_localStore->Save();
		}

		MasterWallet::MasterWallet(const std::string &id,
								   const nlohmann::json &readonlyWalletJson,
								   const std::string &rootPath,
								   const std::string &dataPath,
								   bool p2pEnable,
								   MasterWalletInitFrom from) :
			_id(id),
			_rootPath(rootPath),
			_dataPath(dataPath),
			_p2pEnable(p2pEnable),
			_initFrom(from),
			_earliestPeerTime(0) {

			KeyStore keyStore;
			keyStore.ImportReadonly(readonlyWalletJson);

			_config = ConfigPtr(new Config(_rootPath));
			_localStore = LocalStorePtr(new LocalStore(_dataPath + "/" + _id, keyStore.WalletJson(), ""));
			_account = AccountPtr(new Account(_localStore));

			if (_account->GetSignType() == Account::MultiSign) {
				_idAgentImpl = nullptr;
			} else {
				_idAgentImpl = boost::shared_ptr<IDAgentImpl>(new IDAgentImpl(this));
			}

			_localStore->Save();
		}

		MasterWallet::MasterWallet(const std::string &id,
								   const nlohmann::json &publicKeys, uint32_t m,
								   const std::string &rootPath,
								   const std::string &dataPath,
								   bool p2pEnable,
								   time_t earliestPeerTime,
								   MasterWalletInitFrom from) :
				_id(id),
				_rootPath(rootPath),
				_dataPath(dataPath),
				_p2pEnable(p2pEnable),
				_initFrom(from),
				_earliestPeerTime(earliestPeerTime),
				_idAgentImpl(nullptr) {
			ErrorChecker::CheckPubKeyJsonArray(publicKeys, 1, "coSigner");
			ErrorChecker::CheckParam(publicKeys.size() < m, Error::InvalidArgument, "Invalid M");

			_config = ConfigPtr(new Config(_rootPath));
			_localStore = LocalStorePtr(new LocalStore(_dataPath + "/" + _id, publicKeys, m));
			_account = AccountPtr(new Account(_localStore));

			_localStore->Save();
		}

		MasterWallet::MasterWallet(const std::string &id, const std::string &xprv, const std::string &payPassword,
								   const nlohmann::json &publicKeys, uint32_t m,
								   const std::string &rootPath, const std::string &dataPath,
								   bool p2pEnable, time_t earliestPeerTime, MasterWalletInitFrom from) :
				_id(id),
				_rootPath(rootPath),
				_dataPath(dataPath),
				_p2pEnable(p2pEnable),
				_initFrom(from),
				_earliestPeerTime(earliestPeerTime),
				_idAgentImpl(nullptr) {

			ErrorChecker::CheckPubKeyJsonArray(publicKeys, 1, "coSigner");
			ErrorChecker::CheckParam(publicKeys.size() + 1 < m, Error::InvalidArgument, "Invalid M");

			_config = ConfigPtr(new Config(_rootPath));
			_localStore = LocalStorePtr(new LocalStore(_dataPath + "/" + _id, xprv, true, payPassword));
			for (nlohmann::json::const_iterator it = publicKeys.cbegin(); it != publicKeys.cend(); ++it) {
				_localStore->AddPublicKeyRing(PublicKeyRing((*it).get<std::string>()));
			}

			_localStore->SetM(m);
			_localStore->SetN(_localStore->GetPublicKeyRing().size());
			_account = AccountPtr(new Account(_localStore));

			_localStore->Save();
		}

		MasterWallet::MasterWallet(const std::string &id, const std::string &mnemonic,
								   const std::string &passphrase, const std::string &payPassword,
								   const nlohmann::json &publicKeys, uint32_t m,
								   bool p2pEnable,
								   const std::string &rootPath,
								   const std::string &dataPath,
								   time_t earliestPeerTime,
								   MasterWalletInitFrom from) :
				_id(id),
				_rootPath(rootPath),
				_dataPath(dataPath),
				_p2pEnable(p2pEnable),
				_initFrom(from),
				_earliestPeerTime(earliestPeerTime),
				_idAgentImpl(nullptr) {

			ErrorChecker::CheckPubKeyJsonArray(publicKeys, 1, "coSigner");
			ErrorChecker::CheckParam(publicKeys.size() + 1 < m, Error::InvalidArgument, "Invalid M");

			_config = ConfigPtr(new Config(_rootPath));
			_localStore = LocalStorePtr(new LocalStore(_dataPath + "/" + _id, mnemonic, passphrase, true, payPassword));
			for (nlohmann::json::const_iterator it = publicKeys.cbegin(); it != publicKeys.cend(); ++it)
				_localStore->AddPublicKeyRing(PublicKeyRing((*it).get<std::string>()));

			_localStore->SetM(m);
			_localStore->SetN(_localStore->GetPublicKeyRing().size());
			_account = AccountPtr(new Account(_localStore));

			_localStore->Save();
		}

		MasterWallet::~MasterWallet() {

		}

		std::string MasterWallet::GenerateMnemonic(const std::string &language, const std::string &rootPath,
		                                           Mnemonic::WordCount wordCount) {
			return Mnemonic(boost::filesystem::path(rootPath)).Create(language, wordCount);
		}

		void MasterWallet::RemoveLocalStore() {
			boost::filesystem::path path = _rootPath;
			path /= GetID();
			if (boost::filesystem::exists(path))
				boost::filesystem::remove_all(path);
		}

		std::string MasterWallet::GetID() const {
			return _id;
		}

		std::string MasterWallet::GetWalletID() const {
			return _id;
		}

		std::vector<ISubWallet *> MasterWallet::GetAllSubWallets() const {
			ArgInfo("{} {}", _id, GetFunName());

			std::vector<ISubWallet *> subwallets;
			for (WalletMap::const_iterator it = _createdWallets.cbegin(); it != _createdWallets.cend(); ++it) {
				subwallets.push_back(it->second);
			}

			std::string result;
			for (size_t i = 0; i < subwallets.size(); ++i)
				result += subwallets[i]->GetChainID() + ",";

			ArgInfo("r => {}", result);
			return subwallets;
		}

		ISubWallet *
		MasterWallet::CreateSubWallet(const std::string &chainID, uint64_t feePerKB) {
			ArgInfo("{} {}", _id, GetFunName());
			ArgInfo("chainID: {}", chainID);
			ArgInfo("feePerKB: {}", feePerKB);

			ErrorChecker::CheckParamNotEmpty(chainID, "Chain ID");
			ErrorChecker::CheckParam(chainID.size() > 128, Error::InvalidArgument, "Chain ID sould less than 128");

			if (_createdWallets.find(chainID) != _createdWallets.end()) {
				ISubWallet *subWallet = _createdWallets[chainID];
				ArgInfo("r => already created");
				return subWallet;
			}

			ChainConfigPtr chainConfig = _config->GetChainConfig(chainID);
			ErrorChecker::CheckLogic(chainConfig == nullptr, Error::InvalidArgument, "Unsupport chain ID: " + chainID);

			CoinInfoPtr info(new CoinInfo());

			info->SetChainID(chainID);
			if (feePerKB > chainConfig->FeePerKB())
				info->SetFeePerKB(feePerKB);
			else
				info->SetFeePerKB(chainConfig->FeePerKB());
			info->SetVisibleAsset(Asset::GetELAAssetID());

			_localStore->AddSubWalletInfoList(info);
			SubWallet *subWallet = SubWalletFactoryMethod(info, chainConfig, this);
			_createdWallets[chainID] = subWallet;
			_localStore->Save();
			startPeerManager(subWallet);

			ArgInfo("r => create subwallet");
			subWallet->GetBasicInfo();

			return subWallet;
		}

		void MasterWallet::CloseAllSubWallets() {
			for (WalletMap::iterator it = _createdWallets.begin(); it != _createdWallets.end(); ) {
				SubWallet *subWallet = dynamic_cast<SubWallet *>(it->second);
				std::string id = _id + ":" + subWallet->GetChainID();
				Log::info("closing subWallet ({})...", id);
				stopPeerManager(subWallet);

				it = _createdWallets.erase(it);

				delete subWallet;
				Log::info("closed subWalelt ({})", id);
			}
		}

		void MasterWallet::DestroyWallet(ISubWallet *wallet) {
			ErrorChecker::CheckParam(wallet == nullptr, Error::Wallet, "Destroy wallet can't be null");
			ErrorChecker::CheckParam(_createdWallets.empty(), Error::Wallet, "There is no sub wallet in this wallet.");

			SubWallet *subWallet = dynamic_cast<SubWallet *>(wallet);
			ArgInfo("{} {}", _id, GetFunName());
			ArgInfo("subWallet: {}", subWallet->GetInfoChainID());

			if (_createdWallets.find(subWallet->GetInfoChainID()) == _createdWallets.end())
				ErrorChecker::ThrowParamException(Error::InvalidArgument, "Sub wallet did not created");

			if (_createdWallets[subWallet->GetInfoChainID()] != wallet)
				ErrorChecker::ThrowParamException(Error::InvalidArgument, "Sub wallet does not belong to this master wallet");

			_localStore->RemoveSubWalletInfo(subWallet->_info);
			_localStore->Save();

			stopPeerManager(subWallet);
			WalletMap::iterator it = _createdWallets.find(subWallet->GetInfoChainID());
			_createdWallets.erase(it);

			delete subWallet;

			ArgInfo("{} {} done", _id, GetFunName());
		}

		std::string MasterWallet::GetPublicKey() const {
			ArgInfo("{} {}", _id, GetFunName());

			std::string publicKey = _localStore->GetRequestPubKey();
			ArgInfo("r => {}", publicKey);
			return publicKey;
		}

		nlohmann::json MasterWallet::ExportReadonlyKeyStore() {
			KeyStore keyStore;

			_localStore->GetReadOnlyWalletJson(keyStore.WalletJson());

			return keyStore.ExportReadonly();
		}

		nlohmann::json MasterWallet::exportKeyStore(const std::string &backupPassword,
													const std::string &payPassword) {
			KeyStore keyStore;

			_localStore->GetWalletJson(keyStore.WalletJson(), payPassword);

			return keyStore.Export(backupPassword, true);
		}

		std::string MasterWallet::exportMnemonic(const std::string &payPassword) {
			std::string encryptedMnemonic = _localStore->GetMnemonic();
			bytes_t bytes = AES::DecryptCCM(encryptedMnemonic, payPassword);
			return std::string((char *)bytes.data(), bytes.size());
		}

		std::string MasterWallet::ExportxPrivateKey(const std::string &payPasswd) const {
			ErrorChecker::CheckLogic(_localStore->Readonly(), Error::UnsupportOperation,
									 "Unsupport operation: read-only wallet do not contain xprv");

			if (_localStore->GetxPrivKey().empty())
				_localStore->RegenerateKey(payPasswd);

			ErrorChecker::CheckLogic(_localStore->GetxPrivKey().empty(), Error::InvalidLocalStore, "xprv is empty");

			bytes_t bytes = AES::DecryptCCM(_localStore->GetxPrivKey(), payPasswd);

			return Base58::CheckEncode(bytes);
		}

		std::string MasterWallet::ExportMasterPublicKey() const {
			if (_localStore->GetxPubKey().empty()) {
				ErrorChecker::ThrowLogicException(Error::UnsupportOperation,
												  "Unsupport operation: xpub is empty");
			}

			return _localStore->GetxPubKey();
		}

		void MasterWallet::InitSubWallets() {
			const std::vector<CoinInfoPtr> &info = _localStore->GetSubWalletInfoList();

			if (info.size() == 0) {
				ChainConfigPtr mainchainConfig = _config->GetChainConfig("ELA");
				if (mainchainConfig) {
					CoinInfoPtr defaultInfo(new CoinInfo());
					defaultInfo->SetChainID(mainchainConfig->ID());
					defaultInfo->SetFeePerKB(mainchainConfig->FeePerKB());
					defaultInfo->SetVisibleAsset(Asset::GetELAAssetID());

					ISubWallet *subWallet = SubWalletFactoryMethod(defaultInfo, mainchainConfig, this);
					SubWallet *subWalletImpl = dynamic_cast<SubWallet *>(subWallet);
					ErrorChecker::CheckCondition(subWalletImpl == nullptr, Error::CreateSubWalletError,
												 "Recover sub wallet error");
					startPeerManager(subWalletImpl);
					_createdWallets[subWalletImpl->GetInfoChainID()] = subWallet;

					_localStore->AddSubWalletInfoList(defaultInfo);
					_localStore->Save();
				}
			} else {
				for (int i = 0; i < info.size(); ++i) {
					ChainConfigPtr chainConfig = _config->GetChainConfig(info[i]->GetChainID());
					if (chainConfig == nullptr) {
						Log::error("Can not find config of chain ID: " + info[i]->GetChainID());
						continue;
					}

					ISubWallet *subWallet = SubWalletFactoryMethod(info[i], chainConfig, this);
					SubWallet *subWalletImpl = dynamic_cast<SubWallet *>(subWallet);
					ErrorChecker::CheckCondition(subWalletImpl == nullptr, Error::CreateSubWalletError,
												 "Recover sub wallet error");
					startPeerManager(subWalletImpl);
					_createdWallets[subWalletImpl->GetInfoChainID()] = subWallet;
				}
			}
		}

		std::string MasterWallet::Sign(const std::string &message, const std::string &payPassword) {
			ArgInfo("{} {}", _id, GetFunName());
			ArgInfo("msg: {}", message);
			ArgInfo("payPasswd: *");

			ErrorChecker::CheckParamNotEmpty(message, "Sign message");
			ErrorChecker::CheckPassword(payPassword, "Pay");

			Key key = _account->RequestPrivKey(payPassword);
			std::string hex = key.Sign(message).getHex();

			ArgInfo("r => {}", hex);
			return hex;
		}

		bool MasterWallet::CheckSign(const std::string &publicKey, const std::string &message,
								const std::string &signature) {
			ArgInfo("{} {}", _id, GetFunName());
			ArgInfo("pubkey: {}", publicKey);
			ArgInfo("msg: {}", message);
			ArgInfo("sign: {}", signature);

			Key key;
			key.SetPubKey(bytes_t(publicKey));
			bool result = key.Verify(message, bytes_t(signature));

			ArgInfo("r => {}", result);
			return result;
		}

		bool MasterWallet::IsIDValid(const std::string &id) {
			return Address(id).IsIDAddress();
		}

		SubWallet *MasterWallet::SubWalletFactoryMethod(const CoinInfoPtr &info, const ChainConfigPtr &config,
														MasterWallet *parent) {

			if (_initFrom == CreateNormal) {
				Log::info("Create new master wallet");
				info->SetEaliestPeerTime(config->ChainParameters()->LastCheckpoint().Timestamp());
			} else if (_initFrom == CreateMultiSign) {
				if (_earliestPeerTime != 0) {
					info->SetEaliestPeerTime(_earliestPeerTime);
				} else {
					info->SetEaliestPeerTime(config->ChainParameters()->FirstCheckpoint().Timestamp());
				}
				Log::info("Create new multi-sign master wallet");
			} else if (_initFrom == ImportFromMnemonic) {
				if (_earliestPeerTime != 0) {
					info->SetEaliestPeerTime(_earliestPeerTime);
				} else {
					info->SetEaliestPeerTime(config->ChainParameters()->FirstCheckpoint().Timestamp());
				}
				Log::info("Import master wallet with mnemonic");
			} else if (_initFrom == ImportFromKeyStore) {
				Log::info("Master wallet import with keystore");
			} else if (_initFrom == ImportFromLocalStore) {
				Log::info("Master wallet init from local store");
			} else {
				Log::error("Should not be here");
				info->SetEaliestPeerTime(config->ChainParameters()->FirstCheckpoint().Timestamp());
			}
			Log::info("{}:{} Ealiest peer time: {}", _id, info->GetChainID(), info->GetEarliestPeerTime());

			if (info->GetChainID() == "ELA") {
				return new MainchainSubWallet(info, config, parent);
			} else if (info->GetChainID() == "IDChain") {
				return new IDChainSubWallet(info, config, parent);
			} else if (info->GetChainID() == "TokenChain") {
				return new TokenchainSubWallet(info, config, parent);
			} else {
				ErrorChecker::ThrowLogicException(Error::InvalidChainID, "Invalid chain ID: " + info->GetChainID());
			}

			return nullptr;
		}

		std::string
		MasterWallet::DeriveIDAndKeyForPurpose(uint32_t purpose, uint32_t index) {

			ErrorChecker::CheckLogic(_idAgentImpl == nullptr, Error::UnsupportOperation, "unsupport derive DID");
			return _idAgentImpl->DeriveIDAndKeyForPurpose(purpose, index).String();
		}

		nlohmann::json
		MasterWallet::GenerateProgram(const std::string &id, const std::string &message, const std::string &password) {
			ArgInfo("{} {}", _id, GetFunName());
			ArgInfo("id: {}", id);
			ArgInfo("msg: {}", message);
			ArgInfo("passwd: *");

			RegisterIdentification payload;
			nlohmann::json payLoadJson = nlohmann::json::parse(message);
			payload.FromJson(payLoadJson, 0);

			ByteStream ostream;
			payload.Serialize(ostream, 0);

			nlohmann::json j;
			bytes_t signedData = _idAgentImpl->Sign(id, ostream.GetBytes(), password);

			ostream.Reset();
			ostream.WriteVarBytes(signedData);
			j["Parameter"] = ostream.GetBytes().getHex();
			j["Code"] = _idAgentImpl->GenerateRedeemScript(id, password);

			ArgInfo("r => {}", j.dump());
			return j;
		}

		std::string MasterWallet::Sign(const std::string &id, const std::string &message, const std::string &password) {
			ArgInfo("{} {}", _id, GetFunName());
			ArgInfo("id: {}", id);
			ArgInfo("msg: {}", message);
			ArgInfo("payPasswd: *");

			ErrorChecker::CheckParamNotEmpty(id, "Master wallet id");
			ErrorChecker::CheckParamNotEmpty(message, "Master wallet sign message");
			ErrorChecker::CheckPassword(password, "Master wallet sign");

			std::string data = _idAgentImpl->Sign(id, message, password);

			ArgInfo("r => {}", data);

			return data;
		}

		std::vector<std::string> MasterWallet::GetAllIDs() const {
			if (_idAgentImpl == nullptr)
				return std::vector<std::string>();

			return _idAgentImpl->GetAllIDs();
		}

		std::string MasterWallet::GetPublicKey(const std::string &id) const {
			ArgInfo("{} {}", _id, GetFunName());
			ArgInfo("id: {}", id);

			std::string pubkey = _idAgentImpl->GetPublicKey(id).getHex();

			ArgInfo("r => {}", pubkey);
			return pubkey;
		}

		void MasterWallet::startPeerManager(SubWallet *wallet) {
			if (_p2pEnable)
				wallet->StartP2P();
		}

		void MasterWallet::stopPeerManager(SubWallet *wallet) {
			if (_p2pEnable)
				wallet->StopP2P();
		}

		bool MasterWallet::IsAddressValid(const std::string &address) const {
			ArgInfo("{} {}", _id, GetFunName());
			ArgInfo("addr: {}", address);

			bool result = Address(address).Valid();

			ArgInfo("r => {}", result);
			return result;
		}

		std::vector<std::string> MasterWallet::GetSupportedChains() const {
			ArgInfo("{} {}", _id, GetFunName());

			std::vector<std::string> chainIDs;

			const std::vector<ChainConfigPtr> &chainConfigs = _config->GetChainConfigs();
			for (size_t i = 0; i < chainConfigs.size(); ++i)
				chainIDs.push_back(chainConfigs[i]->ID());

			std::string chainID = "";
			for (size_t i = 0; i < chainIDs.size(); ++i) {
				chainID += chainIDs[i] + ", ";
			}

			ArgInfo("r => size: {} list: {}", chainIDs.size(), chainID);
			return chainIDs;
		}

		void MasterWallet::ChangePassword(const std::string &oldPassword, const std::string &newPassword) {
			ArgInfo("{} {}", _id, GetFunName());
			ArgInfo("old: *");
			ArgInfo("new: *");

			_account->ChangePassword(oldPassword, newPassword);
		}

		IIDAgent *MasterWallet::GetIIDAgent() {
			ArgInfo("{} {}", _id, GetFunName());

			ArgInfo("r => get iid agent");
			return this;
		}

		nlohmann::json MasterWallet::GetBasicInfo() const {
			ArgInfo("{} {}", _id, GetFunName());

			nlohmann::json info = _account->GetBasicInfo();

			ArgInfo("r => {}", info.dump());
			return info;
		}

		bool MasterWallet::IsEqual(const MasterWallet &wallet) const {
			return _account->Equal(*wallet._account);
		}

		void MasterWallet::FlushData() {
			for (WalletMap::const_iterator it = _createdWallets.cbegin(); it != _createdWallets.cend(); ++it) {
				SubWallet *subWallet = dynamic_cast<SubWallet*>(it->second);
				subWallet->FlushData();
			}
		}

	}
}


text:
///////////////////////////////////////////////////////////////////////////////
// BSD 3-Clause License
//
// Copyright (c) 2019, OpenROAD
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice, this
//   list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
//   this list of conditions and the following disclaimer in the documentation
//   and/or other materials provided with the distribution.
//
// * Neither the name of the copyright holder nor the names of its
//   contributors may be used to endorse or promote products derived from
//   this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.

#include "gui/gui.h"

#include <QApplication>
#include <QDebug>
#include <boost/algorithm/string/predicate.hpp>
#include <sstream>
#include <stdexcept>
#include <string>

#include "db.h"
#include "dbShape.h"
#include "defin.h"
#include "lefin.h"
#include "mainWindow.h"
#include "openroad/OpenRoad.hh"

namespace gui {

static odb::dbBlock* getBlock(odb::dbDatabase* db)
{
  if (!db) {
    return nullptr;
  }

  auto chip = db->getChip();
  if (!chip) {
    return nullptr;
  }

  return chip->getBlock();
}

// This provides the link for Gui::redraw to the widget
static gui::MainWindow* mainWindow;

Gui* Gui::singleton_ = nullptr;

Gui* Gui::get()
{
  if (mainWindow == nullptr) {
    return nullptr;  // batch mode
  }

  if (!singleton_) {
    singleton_ = new Gui();
  }

  return singleton_;
}

void Gui::register_renderer(Renderer* renderer)
{
  renderers_.insert(renderer);
  redraw();
}

void Gui::unregister_renderer(Renderer* renderer)
{
  renderers_.erase(renderer);
  redraw();
}

void Gui::redraw()
{
  mainWindow->redraw();
}

void Gui::status(const std::string& message)
{
  mainWindow->status(message);
}

void Gui::pause()
{
  mainWindow->pause();
}

void Gui::addSelectedNet(const char* name)
{
  auto block = getBlock(mainWindow->getDb());
  if (!block) {
    return;
  }

  auto net = block->findNet(name);
  if (!net) {
    return;
  }

  mainWindow->addSelected(Selected(net, OpenDbDescriptor::get()));
}

void Gui::addSelectedNets(const char* pattern,
                          bool matchCase,
                          bool matchRegEx,
                          bool addToHighlightSet)
{
  auto block = getBlock(mainWindow->getDb());
  if (!block) {
    return;
  }

  QRegExp re(pattern, Qt::CaseSensitive, QRegExp::Wildcard);
  SelectionSet nets;
  if (matchRegEx == true) {
    QRegExp re(pattern,
               matchCase == true ? Qt::CaseSensitive : Qt::CaseInsensitive,
               QRegExp::Wildcard);

    for (auto* net : block->getNets()) {
      if (re.exactMatch(net->getConstName())) {
        nets.emplace(net, OpenDbDescriptor::get());
      }
    }
  } else if (matchCase == false) {
    for (auto* net : block->getNets()) {
      if (boost::iequals(pattern, net->getConstName()))
        nets.emplace(net, OpenDbDescriptor::get());
    }
  } else {
    for (auto* net : block->getNets()) {
      if (pattern == net->getConstName()) {
        nets.emplace(net, OpenDbDescriptor::get());
      }
    }
  }

  mainWindow->addSelected(nets);
  if (addToHighlightSet == true)
    mainWindow->addHighlighted(nets);
}  // namespace gui

void Gui::addSelectedInst(const char* name)
{
  auto block = getBlock(mainWindow->getDb());
  if (!block) {
    return;
  }

  auto inst = block->findInst(name);
  if (!inst) {
    return;
  }

  mainWindow->addSelected(Selected(inst, OpenDbDescriptor::get()));
}

void Gui::addSelectedInsts(const char* pattern,
                           bool matchCase,
                           bool matchRegEx,
                           bool addToHighlightSet)
{
  auto block = getBlock(mainWindow->getDb());
  if (!block) {
    return;
  }

  SelectionSet insts;
  if (matchRegEx) {
    QRegExp re(pattern,
               matchCase == true ? Qt::CaseSensitive : Qt::CaseInsensitive,
               QRegExp::Wildcard);
    for (auto* inst : block->getInsts()) {
      if (re.exactMatch(inst->getConstName())) {
        insts.emplace(inst, OpenDbDescriptor::get());
      }
    }
  } else if (matchCase == false) {
    for (auto* inst : block->getInsts()) {
      if (boost::iequals(inst->getConstName(), pattern))
        insts.emplace(inst, OpenDbDescriptor::get());
    }
  } else {
    for (auto* inst : block->getInsts()) {
      if (pattern == inst->getConstName()) {
        insts.emplace(inst, OpenDbDescriptor::get());
        break;  // There can't be two insts with the same name
      }
    }
  }

  mainWindow->addSelected(insts);
  if (addToHighlightSet == true)
    mainWindow->addHighlighted(insts);
}

void Gui::zoomTo(const odb::Rect& rect_dbu)
{
  mainWindow->zoomTo(rect_dbu);
}

Renderer::~Renderer()
{
  gui::Gui::get()->unregister_renderer(this);
}

OpenDbDescriptor* OpenDbDescriptor::singleton_ = nullptr;
OpenDbDescriptor* OpenDbDescriptor::get()
{
  if (!singleton_) {
    singleton_ = new OpenDbDescriptor();
  }

  return singleton_;
}

std::string OpenDbDescriptor::getName(void* object) const
{
  odb::dbObject* db_obj = static_cast<odb::dbObject*>(object);
  switch (db_obj->getObjectType()) {
    case odb::dbNetObj:
      return "Net: " + static_cast<odb::dbNet*>(db_obj)->getName();
    case odb::dbInstObj:
      return "Inst: " + static_cast<odb::dbInst*>(db_obj)->getName();
    default:
      return db_obj->getObjName();
  }
}

std::string OpenDbDescriptor::getLocation(void* object) const
{
  odb::dbObject* db_obj = static_cast<odb::dbObject*>(object);
  auto block = getBlock(mainWindow->getDb());
  auto toMicrons = block->getDbUnitsPerMicron();
  switch (db_obj->getObjectType()) {
    case odb::dbNetObj: {
      auto net = static_cast<odb::dbNet*>(db_obj);
      auto wire = net->getWire();
      odb::Rect wireBBox;
      if (wire->getBBox(wireBBox)) {
        std::stringstream ss;
        ss << "[(" << wireBBox.xMin() / toMicrons << ","
           << wireBBox.yMin() / toMicrons << "), ("
           << wireBBox.xMax() / toMicrons << "," << wireBBox.yMax() / toMicrons
           << ")]";
        return ss.str();
      }
      return std::string("NA");
    } break;
    case odb::dbInstObj: {
      auto instObj = static_cast<odb::dbInst*>(db_obj);
      auto instBBox = instObj->getBBox();
      auto placementStatus = instObj->getPlacementStatus().getString();
      auto instOrient = instObj->getOrient().getString();
      std::stringstream ss;
      ss << "[(" << instBBox->xMin() / toMicrons << ","
         << instBBox->yMin() / toMicrons << "), ("
         << instBBox->xMax() / toMicrons << "," << instBBox->yMax() / toMicrons
         << ")], " << instOrient << ": " << placementStatus;
      return ss.str();
    } break;
    default:
      return std::string("NA");
  }
}

bool OpenDbDescriptor::getBBox(void* object, odb::Rect& bbox) const
{
  odb::dbObject* db_obj = static_cast<odb::dbObject*>(object);
  switch (db_obj->getObjectType()) {
    case odb::dbNetObj: {
      auto net = static_cast<odb::dbNet*>(db_obj);
      auto wire = net->getWire();
      if (wire->getBBox(bbox)) {
        return true;
      }
      return false;
    }
    case odb::dbInstObj: {
      auto instObj = static_cast<odb::dbInst*>(db_obj);
      auto instBBox = instObj->getBBox();
      bbox.set_xlo(instBBox->xMin());
      bbox.set_ylo(instBBox->yMin());
      bbox.set_xhi(instBBox->xMax());
      bbox.set_yhi(instBBox->yMax());
      return true;
    }
  }
  return false;
}

void OpenDbDescriptor::highlight(void* object,
                                 Painter& painter,
                                 bool selectFlag) const
{
  if (selectFlag == true) {
    painter.setPen(Painter::highlight, true);
    painter.setBrush(Painter::transparent);
  } else {
    painter.setPen(Painter::persistHighlight, true);
  }
  odb::dbObject* db_obj = static_cast<odb::dbObject*>(object);
  switch (db_obj->getObjectType()) {
    case odb::dbNetObj: {
      auto net = static_cast<odb::dbNet*>(db_obj);

      // Draw regular routing
      odb::Rect rect;
      odb::dbWire* wire = net->getWire();
      if (wire) {
        odb::dbWireShapeItr it;
        it.begin(wire);
        odb::dbShape shape;
        while (it.next(shape)) {
          shape.getBox(rect);
          painter.drawRect(rect);
        }
      }

      // Draw special (i.e. geometric) routing
      for (auto swire : net->getSWires()) {
        for (auto sbox : swire->getWires()) {
          sbox->getBox(rect);
          painter.drawGeomShape(sbox->getGeomShape());
          // painter.drawRect(rect);
        }
      }
      break;
    }
    case odb::dbInstObj: {
      auto inst = static_cast<odb::dbInst*>(db_obj);
      odb::dbPlacementStatus status = inst->getPlacementStatus();
      if (status == odb::dbPlacementStatus::NONE
          || status == odb::dbPlacementStatus::UNPLACED) {
        return;
      }
      odb::dbBox* bbox = inst->getBBox();
      odb::Rect rect;
      bbox->getBox(rect);
      painter.drawRect(rect);
      break;
    }
    default:
      throw std::runtime_error("Unsupported type for highlighting");
  }
}

// This is the main entry point to start the GUI.  It only
// returns when the GUI is done.
int start_gui(int argc, char* argv[])
{
  QApplication app(argc, argv);

  // Default to 12 point for easier reading
  QFont font = QApplication::font();
  font.setPointSize(12);
  QApplication::setFont(font);

  gui::MainWindow win;
  mainWindow = &win;
  auto* open_road = ord::OpenRoad::openRoad();
  win.setDb(open_road->getDb());
  open_road->addObserver(&win);
  win.show();

  // Exit the app if someone chooses exit from the menu in the window
  QObject::connect(&win, SIGNAL(exit()), &app, SLOT(quit()));

  // Save the window's status into the settings when quitting.
  QObject::connect(&app, SIGNAL(aboutToQuit()), &win, SLOT(saveSettings()));

  return app.exec();
}

}  // namespace gui

namespace ord {

extern "C" {
extern int Gui_Init(Tcl_Interp* interp);
}

void initGui(OpenRoad* openroad)
{
  // Define swig TCL commands.
  Gui_Init(openroad->tclInterp());
  if (gui::mainWindow) {
    gui::mainWindow->setLogger(openroad->getLogger());
  }
}

}  // namespace ord

ext: cpp

max_stars_repo_name: donn/OpenROAD

max_issues_repo_name: donn/OpenROAD

max_forks_repo_name: donn/OpenROAD


text:
#ifndef __CRAB_CFG_LANGUAGE_HH_
#define __CRAB_CFG_LANGUAGE_HH_

/*
 * Definition of the Crab CFG language with llvm::Value* as variables
 * and llvm::BasicBlock* as basic block labels.
 */

#include "llvm/IR/Value.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/Support/raw_ostream.h"

#include "crab/cfg/cfg.hpp"
#include "crab/cfg/var_factory.hpp"
#include "crab/common/bignums.hpp"

#include <boost/functional/hash.hpp>

namespace crab_llvm {

  // This wrapper is needed because we can have crab blocks which do
  // not correspond to llvm blocks.
  class llvm_basic_block_wrapper {

    const llvm::BasicBlock *m_bb;
    std::string m_name;

  public:

    llvm_basic_block_wrapper(const llvm::BasicBlock *b):
	 m_bb(b), m_name(b->getName()) {
      assert(b->hasName());
    }

    explicit llvm_basic_block_wrapper(std::string name):
      m_bb(nullptr), m_name(name){}

    llvm_basic_block_wrapper(): m_bb(nullptr), m_name("") {}

    std::string get_name() const { return m_name; }

    const llvm::BasicBlock* get_basic_block() const { return m_bb; }

    bool operator==(const llvm_basic_block_wrapper &other) const
    { return m_name == other.m_name; }

    bool operator!=(const llvm_basic_block_wrapper &other) const
    { return !(this->operator==(other)); }

    bool operator<(const llvm_basic_block_wrapper &other) const
    { return m_name < other.m_name; }

    std::size_t index() const {
      boost::hash<std::string> hasher;
      return hasher(m_name);
    }
  };

  inline llvm::raw_ostream& operator<<(llvm::raw_ostream &o,
				       const llvm_basic_block_wrapper& b) {
    o << b.get_name();
    return o;
  }

  inline crab::crab_os& operator<<(crab::crab_os &o,
				   const llvm_basic_block_wrapper& b) {
    o << b.get_name();
    return o;
  }

  inline std::size_t hash_value (const llvm_basic_block_wrapper &b)
  { return b.index(); }
}

namespace crab {
  namespace cfg {
    namespace var_factory_impl {
      namespace indexed_string_impl {
        // To print variable names
        template<> inline std::string get_str(const llvm::Value *v)
        {return v->getName().str();}
      }
    }
  }
  namespace cfg_impl {
     // To print basic block labels
     template<> inline std::string get_label_str(crab_llvm::llvm_basic_block_wrapper b)
     { return b.get_name (); }

  }
}

namespace crab_llvm {

     // Variable factory from llvm::Value's
     class llvm_variable_factory :
      public crab::cfg::var_factory_impl::
             variable_factory<const llvm::Value*> {
       typedef crab::cfg::var_factory_impl::
               variable_factory<const llvm::Value*> variable_factory_t;
      public:

       typedef variable_factory_t::varname_t varname_t;
       typedef variable_factory_t::const_var_range const_var_range;

       llvm_variable_factory(): variable_factory_t() {}
     };

     typedef llvm_variable_factory variable_factory_t;
     typedef typename variable_factory_t::varname_t varname_t;

     // CFG over integers
     typedef ikos::z_number number_t;
     typedef ikos::variable<number_t, varname_t> var_t;
     typedef ikos::variable_ref<number_t, varname_t> var_ref_t;
     typedef llvm_basic_block_wrapper basic_block_label_t;
     typedef crab::cfg::Cfg<basic_block_label_t,varname_t,number_t> cfg_t;
     typedef boost::shared_ptr<cfg_t> cfg_ptr_t;
     typedef crab::cfg::cfg_ref<cfg_t> cfg_ref_t;
     typedef cfg_t::basic_block_t basic_block_t;
     typedef typename cfg_t::basic_block_t::lin_exp_t lin_exp_t;
     typedef typename cfg_t::basic_block_t::lin_cst_t lin_cst_t;
     typedef ikos::linear_constraint_system<number_t, varname_t> lin_cst_sys_t;
     typedef crab::pointer_constraint<var_t> ptr_cst_t;

} // end namespace crab_llvm

namespace {
  inline llvm::raw_ostream& operator<<(llvm::raw_ostream& o,
				       const crab_llvm::cfg_t& cfg) {
    crab::crab_string_os s;
    s << cfg;
    o << s.str ();
    return o;
  }

  inline llvm::raw_ostream& operator<<(llvm::raw_ostream& o,
				       crab_llvm::cfg_ref_t cfg) {
    crab::crab_string_os s;
    s << cfg;
    o << s.str ();
    return o;
  }
}
#endif

ext: hh

max_stars_repo_name: cvrac/crab-llvm

max_issues_repo_name: cvrac/crab-llvm

max_forks_repo_name: cvrac/crab-llvm


text:
/******************************************************************************
 *                                                                            *
 *    Copyright 2020   Lawrence Livermore National Security, LLC and other    *
 *    Whole Cell Simulator Project Developers. See the top-level COPYRIGHT    *
 *    file for details.                                                       *
 *                                                                            *
 *    SPDX-License-Identifier: MIT                                            *
 *                                                                            *
 ******************************************************************************/

#ifndef __WCS_BGL_HPP__
#define __WCS_BGL_HPP__

#if !defined(__clang__) && defined(__GNUC__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wmaybe-uninitialized"
#endif

#include <boost/config.hpp> // for BOOST_LIKELY
#include <type_traits>

// To suppress the gcc compiler warning 'maybe-uninitialized'
// from the boost graph source code.
// clang does not recognize this particular diagnostic flag.
#include <boost/graph/adjacency_list.hpp>
#if !defined(__clang__) && defined(__GNUC__)
#pragma GCC diagnostic pop
#endif

#if defined(WCS_HAS_CONFIG)
#include "wcs_config.hpp"
#endif

namespace wcs {
/** \addtogroup wcs_global
 *  @{ */

template<typename S = void>
struct adjlist_selector_t {
  using type = ::boost::vecS;
  using ordered = std::true_type;
};

template<> struct adjlist_selector_t<::boost::vecS> {
  using type = ::boost::vecS;
  using ordered = std::true_type;
};

template<> struct adjlist_selector_t<::boost::listS> {
  using type = ::boost::listS;
  using ordered = std::true_type;
};

template<> struct adjlist_selector_t<::boost::setS> {
  using type = ::boost::setS;
  using ordered = std::true_type;
};

template<> struct adjlist_selector_t<::boost::multisetS> {
  using type = ::boost::multisetS;
  using ordered = std::true_type;
};

template<> struct adjlist_selector_t<::boost::hash_setS> {
  using type = ::boost::hash_setS;
  using ordered = std::false_type;
};

#ifndef WCS_VERTEX_LIST_TYPE
using wcs_vertex_list_t = adjlist_selector_t<>::type;
using is_vertex_list_ordered = adjlist_selector_t<>::ordered;
#else
using wcs_vertex_list_t = adjlist_selector_t<WCS_VERTEX_LIST_TYPE>::type;
using is_vertex_list_ordered = adjlist_selector_t<WCS_VERTEX_LIST_TYPE>::ordered;
#endif

#ifndef WCS_OUT_EDGE_LIST_TYPE
using wcs_out_edge_list_t = adjlist_selector_t<>::type;
#else
using wcs_out_edge_list_t = adjlist_selector_t<WCS_OUT_EDGE_LIST_TYPE>::type;
#endif

/**@}*/
} // end of namespace wcs

#endif // __WCS_BGL_HPP__

ext: hpp

max_stars_repo_name: JaeseungYeom/wcs

max_issues_repo_name: JaeseungYeom/wcs

max_forks_repo_name: JaeseungYeom/wcs


text:
// Copyright (c) 2010 Satoshi Nakamoto
// Copyright (c) 2009-2013 The Bitcoin developers
// Distributed under the MIT/X11 software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "base58.h"
#include "clientversion.h"
#include "init.h"
#include "main.h"
#include "net.h"
#include "netbase.h"
#include "rpcserver.h"
#include "spork.h"
#include "stealth.h"
#include "timedata.h"
#include "util.h"
#ifdef ENABLE_WALLET
#include "wallet.h"
#include "walletdb.h"
#endif

#include <stdint.h>

#include <boost/assign/list_of.hpp>

#include <univalue.h>

using namespace boost;
using namespace boost::assign;
using namespace std;

/**
 * @note Do not add or change anything in the information returned by this
 * method. `getinfo` exists for backwards-compatibilty only. It combines
 * information from wildly different sources in the program, which is a mess,
 * and is thus planned to be deprecated eventually.
 *
 * Based on the source of the information, new information should be added to:
 * - `getblockchaininfo`,
 * - `getnetworkinfo` or
 * - `getwalletinfo`
 *
 * Or alternatively, create a specific query method for the information.
 **/
UniValue getinfo(const UniValue& params, bool fHelp)
{
    if (fHelp || params.size() != 0)
        throw runtime_error(
            "getinfo\n"
            "Returns an object containing various state info."
            "\nResult:\n"
            "{\n"
            "  \"version\": xxxxx,           (numeric) the server version\n"
            "  \"protocolversion\": xxxxx,   (numeric) the protocol version\n"
            "  \"walletversion\": xxxxx,     (numeric) the wallet version\n"
            "  \"balance\": xxxxxxx,         (numeric) the total Metrix balance of the wallet\n"
            "  \"newmint\": xxxxxxx,         (numeric) the immature balance\n"
            "  \"stake\": xxxxxxx            (numeric) the balance of the in progress stake\n"
            "  \"blocks\": xxxxxx,           (numeric) the current number of blocks processed in the server\n"
            "  \"timeoffset\": xxxxx,        (numeric) the time offset\n"
            "  \"moneysupply\": xxxxx,       (numeric) the currently circulating supply\n"
            "  \"connections\": xxxxx,       (numeric) the number of connections\n"
            "  \"proxy\": \"host:port\",     (string, optional) the proxy used by the server\n"
            "  \"ip\": xxxxx,                (string) the ip address as seen by peers\n"
            "  \"difficulty\": xxxxxx,       (numeric) the current difficulty\n"
            "  \"testnet\": true|false,      (boolean) if the server is using testnet or not\n"
            "  \"keypoololdest\": xxxxxx,    (numeric) the timestamp (seconds since GMT epoch) of the oldest pre-generated key in the key pool\n"
            "  \"keypoolsize\": xxxx,        (numeric) how many new keys are pre-generated\n"
            "  \"mininput\": xxxx,           (numeric) minimum input value\n"
            "  \"unlocked_until\": ttt,      (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n"
            "  \"encryption status\": xxxx,  (string) status of the wallet encryption\n"
            "  \"paytxfee\": x.xxxx,         (numeric) the transaction fee set in MRX\n"
            "  \"relayfee\": x.xxxx,         (numeric) minimum relay fee for non-free transactions in MRX/kb\n"
            "  \"stakesplitthreshold\":xx,   (numeric) Staking outputs will split above this threshold in MRX\n"
            "  \"errors\": \"...\"           (string) any error messages\n"
            "}\n"
            "\nExamples:\n" +
            HelpExampleCli("getinfo", "") + HelpExampleRpc("getinfo", ""));

    proxyType proxy;
    GetProxy(NET_IPV4, proxy);

    UniValue obj(UniValue::VOBJ);
    UniValue diff(UniValue::VOBJ);
    obj.push_back(Pair("version", FormatFullVersion()));
    obj.push_back(Pair("protocolversion", PROTOCOL_VERSION));
#ifdef ENABLE_WALLET
    if (pwalletMain) {
        obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
        obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
        obj.push_back(Pair("newmint", ValueFromAmount(pwalletMain->GetNewMint())));
        obj.push_back(Pair("stake", ValueFromAmount(pwalletMain->GetStake())));
    }
#endif
    obj.push_back(Pair("blocks", (int)chainActive.Height()));
    obj.push_back(Pair("timeoffset", GetTimeOffset()));
    obj.push_back(Pair("moneysupply", ValueFromAmount(chainActive.Tip()->nMoneySupply)));
    obj.push_back(Pair("connections", (int)vNodes.size()));
    obj.push_back(Pair("proxy", (proxy.IsValid() ? proxy.ToStringIPPort() : string())));
    obj.push_back(Pair("ip", GetLocalAddress(NULL).ToStringIP()));

    diff.push_back(Pair("proof-of-work", GetDifficulty()));
    diff.push_back(Pair("proof-of-stake", GetDifficulty(GetLastBlockIndex(chainActive.Tip(), true))));
    obj.push_back(Pair("difficulty", diff));

    obj.push_back(Pair("testnet", Params().TestnetToBeDeprecatedFieldRPC()));
#ifdef ENABLE_WALLET
    if (pwalletMain) {
        obj.push_back(Pair("keypoololdest", pwalletMain->GetOldestKeyPoolTime()));
        obj.push_back(Pair("keypoolsize", (int)pwalletMain->GetKeyPoolSize()));
    }
    obj.push_back(Pair("mininput", ValueFromAmount(nMinimumInputValue)));
    // get lock/encryption status
    if (pwalletMain) {
        if (pwalletMain->IsCrypted())
            obj.push_back(Pair("unlocked_until", nWalletUnlockTime));

        if (!pwalletMain->IsCrypted())
            obj.push_back(Pair("encryption_status", "Unencrypted"));
        else if (pwalletMain->IsLocked(true))
            obj.push_back(Pair("encryption_status", "Locked"));
        else if (pwalletMain->IsLocked())
            obj.push_back(Pair("encryption_status", "LockedForStaking"));
        else if (pwalletMain->fWalletUnlockAnonymizeOnly)
            obj.push_back(Pair("encryption_status", "UnlockedForAnonymizationOnly"));
        else
            obj.push_back(Pair("encryption_status", "Unlocked"));
    }
    obj.push_back(Pair("paytxfee", ValueFromAmount(payTxFee.GetFeePerK())));
#endif
    obj.push_back(Pair("relayfee", ValueFromAmount(::minRelayTxFee.GetFeePerK())));
    obj.push_back(Pair("stakesplitthreshold", pwalletMain->nStakeSplitThreshold));
    obj.push_back(Pair("errors", GetWarnings("statusbar")));
    return obj;
}

#ifdef ENABLE_WALLET
class DescribeAddressVisitor : public boost::static_visitor<UniValue>
{
private:
    isminetype mine;

public:
    DescribeAddressVisitor(isminetype mineIn) : mine(mineIn) {}

    UniValue operator()(const CNoDestination &dest) const { return UniValue(UniValue::VOBJ); }

    UniValue operator()(const CKeyID &keyID) const {
        UniValue obj(UniValue::VOBJ);
        CPubKey vchPubKey;
        obj.push_back(Pair("isscript", false));
        if (mine == ISMINE_SPENDABLE) {
            pwalletMain->GetPubKey(keyID, vchPubKey);
            obj.push_back(Pair("pubkey", HexStr(vchPubKey)));
            obj.push_back(Pair("iscompressed", vchPubKey.IsCompressed()));
        }
        return obj;
    }

    UniValue operator()(const CScriptID &scriptID) const {
        UniValue obj(UniValue::VOBJ);
        obj.push_back(Pair("isscript", true));
        if (mine != ISMINE_NO) {
            CScript subscript;
            pwalletMain->GetCScript(scriptID, subscript);
            std::vector<CTxDestination> addresses;
            txnouttype whichType;
            int nRequired;
            ExtractDestinations(subscript, whichType, addresses, nRequired);
            obj.push_back(Pair("script", GetTxnOutputType(whichType)));
            obj.push_back(Pair("hex", HexStr(subscript.begin(), subscript.end())));
            UniValue a(UniValue::VARR);
            BOOST_FOREACH (const CTxDestination& addr, addresses)
                a.push_back(CBitcoinAddress(addr).ToString());
            obj.push_back(Pair("addresses", a));
            if (whichType == TX_MULTISIG)
                obj.push_back(Pair("sigsrequired", nRequired));
        }
        return obj;
    }

    UniValue operator()(const CStealthAddress& stxAddr) const
    {
        UniValue obj(UniValue::VOBJ);
        obj.push_back(Pair("todo", true));
        return obj;
    }
};
#endif

UniValue validateaddress(const UniValue& params, bool fHelp)
{
    if (fHelp || params.size() != 1)
        throw runtime_error(
            "validateaddress <Metrixaddress>\n"
            "Return information about <Metrixaddress>.");

    CBitcoinAddress address(params[0].get_str());
    bool isValid = address.IsValid();

    UniValue ret(UniValue::VOBJ);
    ret.push_back(Pair("isvalid", isValid));
    if (isValid) {
        CTxDestination dest = address.Get();
        string currentAddress = address.ToString();
        ret.push_back(Pair("address", currentAddress));
#ifdef ENABLE_WALLET
        isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : ISMINE_NO;
        ret.push_back(Pair("ismine", (mine & ISMINE_SPENDABLE) ? true : false));
        if (mine != ISMINE_NO) {
            ret.push_back(Pair("iswatchonly", (mine & ISMINE_WATCH_ONLY) ? true : false));
            UniValue detail = boost::apply_visitor(DescribeAddressVisitor(mine), dest);
            ret.pushKVs(detail);
        }
        if (pwalletMain && pwalletMain->mapAddressBook.count(dest))
            ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name));
#endif
    }
    return ret;
}

UniValue validatepubkey(const UniValue& params, bool fHelp)
{
    if (fHelp || !params.size() || params.size() > 2)
        throw runtime_error(
            "validatepubkey <Metrixpubkey>\n"
            "Return information about <Metrixpubkey>.");

    std::vector<unsigned char> vchPubKey = ParseHex(params[0].get_str());
    CPubKey pubKey(vchPubKey);

    bool isValid = pubKey.IsValid();
    bool isCompressed = pubKey.IsCompressed();
    CKeyID keyID = pubKey.GetID();

    CBitcoinAddress address;
    address.Set(keyID);

    UniValue ret(UniValue::VOBJ);
    ret.push_back(Pair("isvalid", isValid));
    if (isValid) {
        CTxDestination dest = address.Get();
        string currentAddress = address.ToString();
        ret.push_back(Pair("address", currentAddress));
        ret.push_back(Pair("iscompressed", isCompressed));
#ifdef ENABLE_WALLET
        isminetype mine = pwalletMain ? IsMine(*pwalletMain, dest) : ISMINE_NO;
        ret.push_back(Pair("ismine", mine != ISMINE_NO));
        if (mine != ISMINE_NO) {
            ret.push_back(Pair("watchonly", mine == ISMINE_WATCH_ONLY));
            UniValue detail = boost::apply_visitor(DescribeAddressVisitor(mine), dest);
            ret.pushKVs(detail);
        }
        if (pwalletMain && pwalletMain->mapAddressBook.count(dest))
            ret.push_back(Pair("account", pwalletMain->mapAddressBook[dest].name));
#endif
    }
    return ret;
}

UniValue verifymessage(const UniValue& params, bool fHelp)
{
    if (fHelp || params.size() != 3)
        throw runtime_error(
            "verifymessage <Metrixaddress> <signature> <message>\n"
            "Verify a signed message");

    string strAddress = params[0].get_str();
    string strSign = params[1].get_str();
    string strMessage = params[2].get_str();

    CBitcoinAddress addr(strAddress);
    if (!addr.IsValid())
        throw JSONRPCError(RPC_TYPE_ERROR, "Invalid address");

    CKeyID keyID;
    if (!addr.GetKeyID(keyID))
        throw JSONRPCError(RPC_TYPE_ERROR, "Address does not refer to key");

    bool fInvalid = false;
    vector<unsigned char> vchSig = DecodeBase64(strSign.c_str(), &fInvalid);

    if (fInvalid)
        throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Malformed base64 encoding");

    CHashWriter ss(SER_GETHASH, 0);
    ss << strMessageMagic;
    ss << strMessage;

    CPubKey pubkey;
    if (!pubkey.RecoverCompact(ss.GetHash(), vchSig))
        return false;

    return (pubkey.GetID() == keyID);
}

/*
    Used for updating/reading spork settings on the network
*/
UniValue spork(const UniValue& params, bool fHelp)
{
    if (params.size() == 1 && params[0].get_str() == "show") {
        std::map<int, CSporkMessage>::iterator it = mapSporksActive.begin();

        UniValue ret(UniValue::VOBJ);
        while (it != mapSporksActive.end()) {
            ret.push_back(Pair(sporkManager.GetSporkNameByID(it->second.nSporkID), it->second.nValue));
            it++;
        }
        return ret;
    } else if (params.size() == 2) {
        int nSporkID = sporkManager.GetSporkIDByName(params[0].get_str());
        if (nSporkID == -1) {
            return "Invalid spork name";
        }

        //! SPORK VALUE
        int64_t nValue = params[1].get_int();

        //! broadcast new spork
        if (sporkManager.UpdateSpork(nSporkID, nValue)) {
            return "success";
        } else {
            return "failure";
        }
    }

    throw runtime_error(
        "spork <name> [<value>]\n"
        "<name> is the corresponding spork name, or 'show' to show all current spork settings"
        "<value> is a epoch datetime to enable or disable spork" +
        HelpRequiringPassphrase());
}


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

#pragma once

//libraries
#include <Eigen/Eigen>

//local
#include "cwise_binary.hpp"
#include "checks.hpp"
#include "../error_handling/throw_assert.hpp"

namespace math {

template<typename ScalarMajor, typename ScalarMinor>
Eigen::Matrix<ScalarMajor, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>
scale(const Eigen::Matrix<ScalarMajor, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>& container, ScalarMinor factor){
	return factor * container;
}

template<typename ScalarMajor, typename ScalarMinor>
Eigen::Tensor<ScalarMajor, 3, Eigen::ColMajor>
scale(const Eigen::Tensor<ScalarMajor, 3, Eigen::ColMajor>& container, ScalarMinor factor){
	Eigen::Tensor<ScalarMajor, 3, Eigen::ColMajor> result = Eigen::Tensor<ScalarMajor, 3, Eigen::ColMajor>(container.dimensions());
#pragma omp parallel for
	for (Eigen::Index i_element = 0; i_element < container.size(); i_element++){
		result(i_element) = container(i_element) * factor;
	}
	return result;
}

template<typename ScalarMajor, typename ScalarMinor>
Eigen::Matrix<ScalarMajor, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>
cwise_product(
		const Eigen::Matrix<ScalarMajor, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>& container_a,
		const Eigen::Matrix<ScalarMinor, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>& container_b){
	return container_a.cwiseProduct(container_b);
}

template<typename ScalarMajor, typename ScalarMinor>
Eigen::Tensor<ScalarMajor, 3, Eigen::ColMajor>
cwise_product(
		const Eigen::Tensor<ScalarMajor, 3, Eigen::ColMajor>& container_a,
		const Eigen::Tensor<ScalarMinor, 3, Eigen::ColMajor>& container_b){

	throw_assert(math::are_dimensions_equal(container_a,container_b), "Tensor dimensions differ.");
	Eigen::Tensor<ScalarMajor, 3, Eigen::ColMajor> result = Eigen::Tensor<ScalarMajor, 3, Eigen::ColMajor>(container_a.dimensions());

#pragma omp parallel for
	for (Eigen::Index i_element = 0; i_element < container_a.size(); i_element++){
		result(i_element) = container_a(i_element) * container_b(i_element);
	}
	return result;
}

template<typename Scalar>
Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>
cwise_add_constant(const Eigen::Matrix<Scalar, Eigen::Dynamic, Eigen::Dynamic, Eigen::ColMajor>& container, Scalar constant){
	return (container.array() + constant).matrix();
}

template<typename Scalar>
Eigen::Tensor<Scalar, 3, Eigen::ColMajor>
cwise_add_constant(const Eigen::Tensor<Scalar, 3, Eigen::ColMajor>& container, Scalar constant){
	return (container + container.constant(constant));
}

}  // namespace math

ext: tpp

max_stars_repo_name: Algomorph/LevelSetFusionExperimentsCPP

max_issues_repo_name: Algomorph/LevelSetFusionExperimentsCPP

max_forks_repo_name: Algomorph/LevelSetFusionExperimentsCPP


text:
/**
 * @example sensors/test/beam_pattern_test.cc
 */

#include <boost/test/unit_test.hpp>
#include <usml/sensors/beams.h>
#include <fstream>
#include <cstdlib>
#include <ctime>

BOOST_AUTO_TEST_SUITE(beam_pattern_test)

using namespace boost::unit_test ;
using namespace usml::sensors ;

/**
 * @ingroup sensors_test
 * @{
 */

/**
 * Test the functionality of the omni-directional
 * beam pattern class. The beam_level should always be 1.0
 * and directivity index should be 0 dB.
 *
 * A check for the directivity index, as computed
 * using a Simpson's rule approximation, fails if it
 * is different from zero by 0.02 dB or more.
 */
BOOST_AUTO_TEST_CASE( omni_pattern_test ) {
    cout << "=== beam_pattern_test/omni_pattern_test ===" << endl ;
    vector<double> freq( 1, 900.0 ) ;
    beam_pattern_omni omni ;
    vector<double> r(3,0) ;
    r(0) = 1.0 ;
    orientation orient( 0, 0, 0, r ) ;

    vector<double> level( freq.size(), 0.0 ) ;
    double total = 0 ;
    for(int az=0; az<=360; ++az) {
        for(int de=-90; de<=90; ++de) {
            double de_rad = de * M_PI/180.0 ;
            double az_rad = az * M_PI/180.0 ;
            omni.beam_level( de_rad, az_rad, orient, freq, &level ) ;
            total += level(0)*cos(de_rad)*(M_PI/180.0)*(M_PI/180.0) ;
            BOOST_CHECK_EQUAL( level(0), 1.0 ) ;
        }
    }

    total = 10.0 * log10( 4.0*M_PI / total ) ;
    omni.directivity_index( freq, &level ) ;
    cout << "Directivity index: " << total << endl ;
    BOOST_CHECK_SMALL( level(0)-total, 0.02 ) ;

}

/**
 * Test the functionality of the sine-directional
 * beam pattern class. The beam_level should have a maximum
 * response in the East and West directions.
 *
 * This test fails if the maximum response axis differs from
 * the North (AZ=90) and South (AZ=270) directions. Also,
 * if the directivity index, as computed using a Simpson's
 * rule approximation, is different from the analytic solution
 * by 1% the test fails.
 */
BOOST_AUTO_TEST_CASE( sine_pattern_test ) {
    cout << "=== beam_pattern_test/sine_pattern_test ===" << endl ;
    const char* csvname = USML_TEST_DIR "/sensors/test/beam_pattern_sine.csv" ;
    vector<double> freq( 1, 900.0 ) ;
    beam_pattern_sine sine ;

    int pitch = 62 ;
    int heading = 31 ;
    int roll = 57 ;
    double dr = M_PI / 180.0 ;
    orientation orient( pitch, heading, roll, sine.reference_axis() ) ;

    int _t = orient.theta()/dr ;
    int _p = orient.phi()/dr ;
    std::ofstream of( csvname ) ;
    cout << "Saving beam data to " << csvname << endl ;
    vector<double> level( freq.size(), 0.0 ) ;
    double total = 0.0 ;
    for(int az=0; az<=360; ++az) {
        for(int de=-90; de<=90; ++de) {
            double de_rad = de * dr ;
            double az_rad = az * dr ;
            sine.beam_level( de_rad, az_rad, orient, freq, &level ) ;
            of << level(0) ;
            if( de!=90 ) of << "," ;
            total += level(0)*cos(de_rad)*dr*dr ;
            if( (az==360-_p && de==-_t) || (az==(180-_p) && de==_t) )
                BOOST_CHECK_CLOSE( abs(level(0)), 1.0, 0.2 ) ;
        }
        of << endl ;
    }
    total = 10.0*log10( 4*M_PI / total ) ;
    sine.directivity_index( freq, &level ) ;
    cout << "Directivity index" << endl ;
    cout << "analytic: " << level(0) << "\napproximation: " << total << endl ;
    BOOST_CHECK_CLOSE( level(0), total, 0.5 ) ;
}

/**
 * Test the functionality of the cosine-directional
 * beam pattern class. The beam_level should have a maximum
 * response in the North and South directions.
 *
 * This test fails if the maximum response axis differs from
 * the East (AZ=0) and West (AZ=180) directions. Also,
 * if the directivity index, as computed using a Simpson's
 * rule approximation, is different from the analytic solution
 * by 1% the test fails.
 */
BOOST_AUTO_TEST_CASE( cosine_pattern_test ) {
    cout << "=== beam_pattern_test/cosine_pattern_test ===" << endl ;
    const char* csvname = USML_TEST_DIR "/sensors/test/beam_pattern_cosine.csv" ;
    vector<double> freq( 1, 900.0 ) ;
    double l = -10.0 ;
    beam_pattern_cosine cosine(l) ;

    int pitch = 21 ;
    int heading = 57 ;
    int roll = 33 ;
    double dr = M_PI / 180.0 ;
    orientation orient( pitch, heading, roll, cosine.reference_axis() ) ;

//    int _t = orient.theta()/dr ;
//    int _p = orient.phi()/dr ;
    std::ofstream of( csvname ) ;
    cout << "Saving beam data to " << csvname << endl ;
    vector<double> level( freq.size(), 0.0 ) ;
    double total = 0.0 ;
    for(int az=0; az<=360; ++az) {
        for(int de=-90; de<=90; ++de) {
            double de_rad = de * dr ;
            double az_rad = az * dr ;
            cosine.beam_level( de_rad, az_rad, orient, freq, &level ) ;
            of << level(0) ;
            if( de!=90 ) of << "," ;
            total += level(0)*cos(de_rad)*dr*dr ;
        }
        of << endl ;
    }
    orient.update_orientation( 0.0, 0.0, 0.0 ) ;
    cosine.beam_level( 0.0, 63.6*dr, orient, freq, &level ) ;
    BOOST_CHECK_CLOSE( abs(level(0)), 0.5, 0.5 ) ;

    total = 10.0*log10( 4*M_PI / total ) ;
    cosine.directivity_index( freq, &level ) ;
    cout << "Directivity index" << endl ;
    cout << "analytic: " << level(0) << "\napproximation: " << total << endl ;
    BOOST_CHECK_CLOSE( level(0), total, 0.5 ) ;
}

/**
 * Test the basic features of the beam_pattern_model using
 * a vertical array of elements model. Data is save to a
 * file and support matlab code is provided to verify the
 * spatial orientation of the beam pattern is correct.
 *
 * The test fails if either the following are false:
 *
 *  - The main lobe is in the correct is not in the correct
 *    direction. If the maximum response is not in the
 *    correct direction, the beam level will differ from
 *    1.0 by greater than 1e-4%
 *  - The Directivity index is also differs from a
 *    a Simpson's rule integration approximation of
 *    directivity index from beam level, by more than
 *    1.0%.
 */
BOOST_AUTO_TEST_CASE( vertical_array_test ) {
    cout << "===== beam_pattern_test/vertical_array_test =====" << endl ;
    const char* envname = USML_TEST_DIR "/sensors/test/vertical_array_parameters.csv" ;
    const char* csvname = USML_TEST_DIR "/sensors/test/vertical_array_beam_pattern.csv" ;

    // Physical and Environmental parameters concerning the array
    double c0 = 1500.0 ;
    double d = 0.75 ;
    double n = 5 ;
    double steering = M_PI/8.0 ;
    vector<double> freq( 1, 900.0 ) ;
    beam_pattern_VLA array( c0, d, n, steering ) ;

    int pitch = -10 ;
    int heading = 37 ;
    int roll = 55 ;
    double dr = M_PI / 180.0 ;
    orientation orient( pitch, heading, roll, array.reference_axis() ) ;

    std::ofstream of( csvname ) ;
    cout << "Saving beam data to " << csvname << endl ;
    vector<double> level( freq.size(), 0.0 ) ;
    double total = 0 ;
    for(int az=0; az<=360; ++az) {
        for(int de=-90; de<=90; ++de) {
            double de_rad = de * dr ;
            double az_rad = az * dr ;
            array.beam_level( de_rad, az_rad, orient, freq, &level ) ;
            of << level(0) ;
            if( de!=90 ) of << "," ;
            total += level(0)*cos(de_rad)*dr*dr ;
        }
        of << endl ;
    }

    // check that the main lobe is at the correct position
//    array.beam_level( theta-steering, phi, theta, phi, freq, &level ) ;
//    BOOST_CHECK_CLOSE( level(0), 1.0, 1e-4 ) ;

    std::ofstream ef( envname ) ;
    cout << "Saving environmental and array parameters to " << envname << endl ;
    ef << "c0,d,n,pitch,heading,roll,steering,freq" << endl ;
    ef << c0 << ","
       << d << ","
       << n << ","
       << pitch << ","
       << heading << ","
       << roll << ","
       << steering << "," ;
    for(int i=0; i<freq.size(); ++i) {
        ef << freq(i) ;
        if( i != freq.size()-1 ) ef << "," ;
    }
    ef << endl ;

    total = 10.0*log10( (4*M_PI)/total ) ;
    array.directivity_index( freq, &level ) ;
    cout << "Directivity index" << endl ;
    cout << "analytic: " << level(0) << "\napproximation: " << total << endl ;
    BOOST_CHECK_CLOSE( level(0), total, 0.5 ) ;
}

/**
 * Test the basic features of the beam_pattern_model using
 * a horizontal array of elements model. Data is save to a
 * file and support matlab code is provided to verify the
 * spatial orientation of the beam pattern is correct.
 *
 * The test fails if either the following are false:
 *
 *  - The main lobe is in the correct is not in the correct
 *    direction. If the maximum response is not in the
 *    correct direction, the beam level will differ from
 *    1.0 by greater than 1e-4%
 *  - The Directivity index is also differs from a
 *    a Simpson's rule integration approximation of
 *    directivity index from beam level, by more than
 *    1.0%.
 */
BOOST_AUTO_TEST_CASE( horizontal_array_test ) {
    cout << "===== beam_pattern_test/horizontal_array_test =====" << endl ;
    const char* envname = USML_TEST_DIR "/sensors/test/horizontal_array_parameters.csv" ;
    const char* csvname = USML_TEST_DIR "/sensors/test/horizontal_array_beam_pattern.csv" ;

    // Physical and Environmental parameters concerning the array
    double c0 = 1500.0 ;
    double d = 0.75 ;
    double n = 6 ;
    double steering = -M_PI/4.0 ;
    vector<double> freq( 1, 900.0 ) ;
    beam_pattern_HLA array( c0, d, n, steering ) ;

    int pitch = -61 ;
    int heading = 57 ;
    int roll = 23 ;
    double dr = M_PI / 180.0 ;
    orientation orient( pitch, heading, roll, array.reference_axis() ) ;
    cout << "theta: " << orient.theta()/dr << " phi: " << orient.phi()/dr << endl ;

    std::ofstream of( csvname ) ;
    cout << "Saving beam data to " << csvname << endl ;
    vector<double> level( freq.size(), 0.0 ) ;
    double total = 0 ;
    for(int az=0; az<=360; ++az) {
        for(int de=-90; de<=90; ++de) {
            double de_rad = de * dr ;
            double az_rad = az * dr ;
            array.beam_level( de_rad, az_rad, orient, freq, &level ) ;
            of << level(0) ;
            if( de!=90 ) of << "," ;
            total += level(0)*cos(de_rad)*dr*dr ;
        }
        of << endl ;
    }

    // check that the main lobe is at the correct position
//    array.beam_level( theta-M_PI_2, phi, theta, phi, freq, &level ) ;
//    BOOST_CHECK_CLOSE( level(0), 1.0, 1e-3 ) ;

    std::ofstream ef( envname ) ;
    cout << "Saving environmental and array parameters to " << envname << endl ;
    ef << "c0,d,n,pitch,heading,roll,steering,freq" << endl ;
    ef << c0 << ","
       << d << ","
       << n << ","
       << pitch << ","
       << heading << ","
       << roll << ","
       << steering << "," ;
    for(int i=0; i<freq.size(); ++i) {
        ef << freq(i) ;
        if( i != freq.size()-1 ) ef << "," ;
    }
    ef << endl ;

    total = 10.0*log10( (4*M_PI)/total ) ;
    array.directivity_index( freq, &level ) ;
    cout << "Directivity index" << endl ;
    cout << "analytic: " << level(0) << "\napproximation: " << total << endl ;
    BOOST_CHECK_CLOSE( level(0), total, 0.5 ) ;
}

/**
 * Test the basic features of the beam_pattern_model using
 * a beam pattern function of solid angle.
 *
 * The test fails if either the following are false:
 *
 *  - The main lobe is in the correct is not in the correct
 *    direction. If the maximum response is not in the
 *    correct direction, the beam level will differ from
 *    1.0 by greater than 1e-4%
 *  - The Directivity index is also differs from a
 *    a Simpson's rule integration approximation of
 *    directivity index from beam level, by more than
 *    1.0%.
 */
BOOST_AUTO_TEST_CASE( solid_pattern_test ) {
    cout << "===== beam_pattern_test/solid_pattern_test =====" << endl ;
    const char* envname = USML_TEST_DIR "/sensors/test/solid_pattern_parameters.csv" ;
    const char* csvname = USML_TEST_DIR "/sensors/test/beam_pattern_solid.csv" ;

    // Physical and Environmental parameters concerning the array
    double max_de = 20.0 ;
    double min_de = -20.0 ;
    double max_az = 135.0 ;
    double min_az = 45.0 ;
    vector<double> freq( 1, 900.0 ) ;
    beam_pattern_solid solid( max_de, min_de, max_az, min_az ) ;
    vector<double> raxis(3,0) ;
    raxis(2) = 1.0 ;
    solid.reference_axis( raxis ) ;

    int pitch = 41 ;
    int heading = 17 ;
    int roll = 31 ;
    double dr = M_PI / 180.0 ;
    orientation orient( pitch, heading, roll, solid.reference_axis() ) ;

    std::ofstream of( csvname ) ;
    cout << "Saving beam data to " << csvname << endl ;
    vector<double> level( freq.size(), 0.0 ) ;
    double total = 0 ;
    for(int az=0; az<=360; ++az) {
        for(int de=-90; de<=90; ++de) {
            double de_rad = de * dr ;
            double az_rad = az * dr ;
            solid.beam_level( de_rad, az_rad, orient, freq, &level ) ;
            of << level(0) ;
            if( de!=90 ) of << "," ;
            total += level(0)*cos(de_rad)*dr*dr ;
//            double result = 0.0 ;
//            if( (de<(max_de-pitch)) && (de>=(min_de-pitch)) ) {
//                if( (az<=(max_az+heading)) && (az>=(min_az+heading)) ) {
//                    result = 1.0 ;
//                }
//            }
//            BOOST_CHECK_EQUAL( level(0), result ) ;
        }
        of << endl ;
    }

    std::ofstream ef( envname ) ;
    cout << "Saving environmental and array parameters to " << envname << endl ;
    ef << "pitch,heading,roll,freq" << endl ;
    ef << pitch << ","
       << heading << ","
       << roll << "," ;
    for(int i=0; i<freq.size(); ++i) {
        ef << freq(i) ;
        if( i != freq.size()-1 ) ef << "," ;
    }
    ef << endl ;

    cout << "Directivity index" << endl ;
    total = 10.0*log10( (4*M_PI)/total ) ;
    solid.directivity_index( freq, &level ) ;
    cout << "analytic: " << level(0) << "\napproximation: " << total << endl ;
    BOOST_CHECK_CLOSE( level(0), total, 0.5 ) ;
}

/**
 * Tests the ability to produce a multi-pattern beam
 */
BOOST_AUTO_TEST_CASE( multi_pattern_test ) {
    cout << "==== beam_pattern_test/multi_pattern_test ====" << endl ;
    std::list<beam_pattern_model*> beam_list ;
    beam_list.push_back( new beam_pattern_sine ) ;
    beam_list.push_back( new beam_pattern_cosine ) ;
    beam_pattern_multi multi( beam_list ) ;

    const char* csvname = USML_TEST_DIR "/sensors/test/beam_pattern_multi.csv" ;
    vector<double> freq( 1, 900.0 ) ;

    int pitch = 62 ;
    int heading = 31 ;
    int roll = 57 ;
    double dr = M_PI / 180.0 ;
    vector<double> raxis(3,0) ;
    raxis(0) = 1.0 ;
    orientation orient( pitch, heading, roll, raxis ) ;

    std::ofstream of( csvname ) ;
    cout << "Saving beam data to " << csvname << endl ;
    vector<double> level( freq.size(), 0.0 ) ;
    double total = 0.0 ;
    for(int az=0; az<=360; ++az) {
        for(int de=-90; de<=90; ++de) {
            double de_rad = de * dr ;
            double az_rad = az * dr ;
            multi.beam_level( de_rad, az_rad, orient, freq, &level ) ;
            total += level(0)*cos(de_rad)*dr*dr ;
            of << level(0) ;
            if( de!=90 ) of << "," ;
        }
        of << endl ;
    }
    total = 10.0*log10( 4*M_PI / total ) ;
    multi.directivity_index( freq, &level ) ;
    cout << "Directivity index" << endl ;
    cout << "analytic: " << level(0) << "\napproximation: " << total << endl ;
//    BOOST_CHECK_CLOSE( level(0), total, 1.0 ) ;
}

/**
 * Test for a mesh beam pattern for a 1-D beam pattern. With
 * 1-D beam patterns the beam_level and directivity_index are
 * the same values. This test fails if any values that are
 * passed back are different from the data points for either
 * directivity_index or beam_level.
 */
BOOST_AUTO_TEST_CASE( grid_pattern_1d_test ) {
    cout << "===== beam_pattern_test/grid_pattern_1d_test =====" << endl ;

    typedef beam_pattern_grid<double,1>     grid_type ;

    const double tmp_data[] = { 1.0, 0.75, 0.5, 0.5, 0.75, 1.0 } ;
    int N = sizeof(tmp_data)/sizeof(double) ;
    vector<double> freq(N) ;
    double axis_data[] = { 10.1, 57.0, 79.0, 81.5, 100.7, 152.7 } ;
//    seq_vector* axes = new seq_log( 10.0, 10.0, N ) ;
    const seq_vector* axes[1] ;
    axes[0] = new seq_data( axis_data, N ) ;
    double* data = new double[N] ;
    for(int i=0; i<N; ++i) {
        freq[i] = (*axes[0])[i] ;
        data[i] = tmp_data[i] ;
    }

    grid_type test_grid( axes, data, grid_type::POWER_UNITS ) ;
    orientation orient ;
    cout << "frequencies: " << freq << endl ;

    const char* grid_file = "beam_pattern_grid1_test.nc" ;
    cout << "Writing data_grid to disk, " << grid_file << endl ;
    test_grid.write_netcdf( grid_file ) ;

    vector<double> level( N, 0.0 ) ;
    test_grid.beam_level( 0.0, 0.0, orient, freq, &level ) ;
    for(int i=0; i<level.size(); ++i) {
        BOOST_CHECK_CLOSE( tmp_data[i], level(i), 1e-8 ) ;
    }
    cout << "beam level: " << level << endl ;
    test_grid.directivity_index( freq, &level ) ;
    for(int i=0; i<level.size(); ++i) {
        double result = 10.0*log10( tmp_data[i] ) ;
        BOOST_CHECK_EQUAL( result, level(i) ) ;
    }
    cout << "Directivity index: " << level << endl ;

    delete axes[0] ;
    delete[] data ;
}

/**
 * Test for a mesh beam pattern for a 2-D beam pattern.
 * This test fails if any values that are passed back are
 * different from the data points for either directivity
 * index or beam level.
 */
BOOST_AUTO_TEST_CASE( grid_pattern_2d_test ) {
    cout << "===== beam_pattern_test/grid_pattern_2d_test =====" << endl ;

    typedef beam_pattern_grid<double,2>     grid_type ;

    // ----> axis0
    // |
    // |
    // v axis1
    const double tmp_data[] = { 1.0, 0.75, 0.5, 0.75, 0.81,
                                0.87, 0.75, 0.5, 0.75, 0.41,
                                0.2, 0.75, 0.5, 0.75, 0.33,
                                0.61, 0.75, 0.5, 0.75, 0.97,
                                0.53, 0.75, 0.5, 0.75, 0.53 } ;
    int N = sizeof(tmp_data)/sizeof(double) ;
    int n = sqrt((double)N) ;
    seq_linear* frequencies = new seq_linear( 100.0, 100.0, n ) ;
    vector<double> freq = *frequencies ;
    seq_vector* de = new seq_linear( to_radians(-2.0), to_radians(1.0), n ) ;
    const seq_vector* axes[2] ;
    axes[0] = frequencies ;
    axes[1] = de ;
    double* data = new double[N] ;
    for(int i=0; i<N; ++i) {
        data[i] = tmp_data[i] ;
    }

    grid_type test_grid( axes, data, grid_type::POWER_UNITS ) ;
    orientation orient ;
    cout << "frequencies: " << freq << endl ;

    const char* grid_file = "beam_pattern_grid2_test.nc" ;
    cout << "Writing data_grid to disk, " << grid_file << endl ;
    test_grid.write_netcdf( grid_file ) ;

    vector<double> level( freq.size(), 0.0 ) ;
    for(int i=0; i<de->size(); ++i) {
        test_grid.beam_level( (*de)[i], 0.0, orient, freq, &level ) ;
        for(int j=0; j<level.size(); ++j) {
            BOOST_CHECK_CLOSE( tmp_data[j*n+i], level(j), 1e-5 ) ;
        }
    }
    cout << "beam level: " << level << endl ;
    test_grid.directivity_index( freq, &level ) ;
    vector<double> sum( n, 0.0 ) ;
    for(int i=0; i<n; ++i) {
        for(int j=0; j<n; ++j) {
            sum[i] += tmp_data[i*n+j] * cos( (*de)[j] ) * de->increment(j) ;
        }
    }
    for(int i=0; i<level.size(); ++i) {
        double result = 10.0*log10( 2.0 / sum[i] ) ;
        BOOST_CHECK_EQUAL( result, level(i) ) ;
    }
    cout << "Directivity index: " << level << endl ;

    delete frequencies ;
    delete de ;
    delete[] data ;
}

/**
 * Test for a mesh beam pattern for a 3-D beam pattern.
 * This test fails if any values that are passed back are
 * different from the data points for either directivity
 * index or beam level.
 */
BOOST_AUTO_TEST_CASE( grid_pattern_3d_test ) {
    cout << "===== beam_pattern_test/grid_pattern_3d_test =====" << endl ;

    typedef beam_pattern_grid<double,3>     grid_type ;
    typedef grid_type::size_type            size_type ;

    // ----> axis0
    // |
    // |
    // v axis1
    // * axis2

    int n = 5 ;
    int N = n*n*n ;
    seq_linear frequencies( 100.0, 100.0, n ) ;
    vector<double> freq = frequencies ;
    seq_linear de( to_radians(-2.0), to_radians(1.0), n ) ;
    seq_linear az( to_radians(0.0), to_radians(5.0), n ) ;
    const seq_vector* axes[3] ;
    axes[0] = &frequencies ;
    axes[1] = &de ;
    axes[2] = &az ;
    double* data = new double[N] ;
    std::srand(1) ;
    for(int i=0; i<N; ++i) {
        double v = std::rand() ;
        data[i] = v/RAND_MAX ;
    }

    grid_type test_grid( axes, data, grid_type::POWER_UNITS ) ;
    orientation orient ;
    cout << "frequencies: " << freq << endl ;

    const char* grid_file = "beam_pattern_grid3_test.nc" ;
    cout << "Writing data_grid to disk, " << grid_file << endl ;
    test_grid.write_netcdf( grid_file ) ;

    size_type num_freq( freq.size() ) ;
    size_type num_de( de.size() ) ;
    size_type num_az( az.size() ) ;
    vector<double> level( num_freq, 0.0 ) ;
    for(size_type i=0; i<num_de; ++i) {
        for(size_type j=0; j<num_az; ++j) {
            test_grid.beam_level( de[i], az[j], orient, freq, &level ) ;
            for(int k=0; k<num_freq; ++k) {
                size_type index = j + num_az*(i + num_de*k) ;
                BOOST_CHECK_CLOSE( data[index], level(k), 1e-3 ) ;
            }
        }
    }
    cout << "beam level: " << level << endl ;
    test_grid.directivity_index( freq, &level ) ;
    vector<double> sum( num_freq, 0.0 ) ;
    for(size_type i=0; i<num_de; ++i) {
        for(size_type j=0; j<num_az; ++j) {
            for(size_type k=0; k<num_freq; ++k) {
                size_type index = j + num_az*(i + num_de*k) ;
                sum[k] += data[index] * cos( de[i] )
                        * de.increment(i) * az.increment(j) ;
            }
        }
    }
    for(int i=0; i<num_freq; ++i) {
        double result = 10.0*log10( (4.0*M_PI) / sum[i] ) ;
        BOOST_CHECK_CLOSE( result, level(i), 1e-8 ) ;
    }
    cout << "Directivity index: " << level << endl ;

    delete[] data ;
}

BOOST_AUTO_TEST_SUITE_END()

ext: cc

max_stars_repo_name: fraclipe/UnderSeaModelingLibrary

max_issues_repo_name: Wolframy-NUDT/UnderSeaModelingLibrary

max_forks_repo_name: Wolframy-NUDT/UnderSeaModelingLibrary


text:
/**
 * Copyright Soramitsu Co., Ltd. All Rights Reserved.
 * SPDX-License-Identifier: Apache-2.0
 */

#ifndef KAGOME_CORE_CRYPTO_MP_UTILS_HPP
#define KAGOME_CORE_CRYPTO_MP_UTILS_HPP

#include <boost/multiprecision/cpp_int.hpp>
#include <gsl/span>

namespace kagome::common {

  namespace detail {
    template <size_t size, typename uint>
    std::array<uint8_t, size> uint_to_bytes(uint &&i);

    template <size_t size, typename uint>
    uint bytes_to_uint(gsl::span<uint8_t, size> bytes);
  }  // namespace detail

  std::array<uint8_t, 8> uint64_t_to_bytes(uint64_t number);

  uint64_t bytes_to_uint64_t(gsl::span<uint8_t, 8> bytes);

  std::array<uint8_t, 16> uint128_t_to_bytes(
      const boost::multiprecision::uint128_t &i);

  boost::multiprecision::uint128_t bytes_to_uint128_t(
      gsl::span<uint8_t, 16> bytes);

  std::array<uint8_t, 32> uint256_t_to_bytes(
      const boost::multiprecision::uint256_t &i);

  boost::multiprecision::uint256_t bytes_to_uint256_t(
      gsl::span<uint8_t, 32> bytes);

}  // namespace kagome::common

#endif  // KAGOME_CORE_CRYPTO_MP_UTILS_HPP

max_stars_repo_name: FlorianFranzen/kagome

max_issues_repo_name: FlorianFranzen/kagome

max_forks_repo_name: FlorianFranzen/kagome


text:
/**
 *    Copyright (C) 2018-present MongoDB, Inc.
 *
 *    This program is free software: you can redistribute it and/or modify
 *    it under the terms of the Server Side Public License, version 1,
 *    as published by MongoDB, Inc.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    Server Side Public License for more details.
 *
 *    You should have received a copy of the Server Side Public License
 *    along with this program. If not, see
 *    <http://www.mongodb.com/licensing/server-side-public-license>.
 *
 *    As a special exception, the copyright holders give permission to link the
 *    code of portions of this program with the OpenSSL library under certain
 *    conditions as described in each individual source file and distribute
 *    linked combinations including the program with the OpenSSL library. You
 *    must comply with the Server Side Public License in all respects for
 *    all of the code used other than as permitted herein. If you modify file(s)
 *    with this exception, you may extend this exception to your version of the
 *    file(s), but you are not obligated to do so. If you do not wish to do so,
 *    delete this exception statement from your version. If you delete this
 *    exception statement from all source files in the program, then also delete
 *    it in the license file.
 */

//
// This file contains tests for mongo/db/exec/queued_data_stage.cpp
//

#include "mongo/db/exec/queued_data_stage.h"

#include <boost/optional.hpp>
#include <memory>

#include "mongo/db/exec/working_set.h"
#include "mongo/db/namespace_string.h"
#include "mongo/db/operation_context.h"
#include "mongo/db/service_context_d_test_fixture.h"
#include "mongo/unittest/unittest.h"
#include "mongo/util/clock_source_mock.h"

using namespace mongo;

namespace {

using std::unique_ptr;

const static NamespaceString kNss("db.dummy");

class QueuedDataStageTest : public ServiceContextMongoDTest {
public:
    QueuedDataStageTest() : ServiceContextMongoDTest(Options{}.useMockClock(true)) {
        _opCtx = makeOperationContext();
    }

protected:
    OperationContext* opCtx() {
        return _opCtx.get();
    }

private:
    ServiceContext::UniqueOperationContext _opCtx;
};

//
// Basic test that we get out valid stats objects.
//
TEST_F(QueuedDataStageTest, getValidStats) {
    WorkingSet ws;
    auto expCtx = make_intrusive<ExpressionContext>(opCtx(), nullptr, kNss);
    auto mock = std::make_unique<QueuedDataStage>(expCtx.get(), &ws);
    const CommonStats* commonStats = mock->getCommonStats();
    ASSERT_EQUALS(commonStats->works, static_cast<size_t>(0));
    const SpecificStats* specificStats = mock->getSpecificStats();
    ASSERT(specificStats);
    unique_ptr<PlanStageStats> allStats(mock->getStats());
    ASSERT_EQUALS(allStats->stageType, mock->stageType());
}

//
// Test that our stats are updated as we perform operations.
//
TEST_F(QueuedDataStageTest, ValidateStats) {
    WorkingSet ws;
    WorkingSetID wsID;
    auto expCtx = make_intrusive<ExpressionContext>(opCtx(), nullptr, kNss);
    auto mock = std::make_unique<QueuedDataStage>(expCtx.get(), &ws);

    // make sure that we're at all zero
    const CommonStats* stats = mock->getCommonStats();
    ASSERT_EQUALS(stats->yields, 0U);
    ASSERT_EQUALS(stats->unyields, 0U);
    ASSERT_EQUALS(stats->works, 0U);
    ASSERT_EQUALS(stats->needTime, 0U);
    ASSERT_EQUALS(stats->advanced, 0U);
    ASSERT_FALSE(stats->isEOF);

    // advanced, with pushed data
    WorkingSetID id = ws.allocate();
    mock->pushBack(id);
    mock->work(&wsID);
    ASSERT_EQUALS(stats->works, 1U);
    ASSERT_EQUALS(stats->advanced, 1U);

    // yields
    mock->saveState();
    ASSERT_EQUALS(stats->yields, 1U);

    // unyields
    mock->restoreState({nullptr});
    ASSERT_EQUALS(stats->unyields, 1U);

    // and now we are d1U, but must trigger EOF with getStats()
    ASSERT_FALSE(stats->isEOF);
    unique_ptr<PlanStageStats> allStats(mock->getStats());
    ASSERT_TRUE(stats->isEOF);
}
}  // namespace

max_stars_repo_name: benety/mongo

max_issues_repo_name: benety/mongo

max_forks_repo_name: benety/mongo


text:
/**
 * @file sarah_test.cpp
 * @author Marcus Edel
 *
 * Test file for SARAH and SARAH+.
 *
 * mlpack is free software; you may redistribute it and/or modify it under the
 * terms of the 3-clause BSD license.  You should have received a copy of the
 * 3-clause BSD license along with mlpack.  If not, see
 * http://www.opensource.org/licenses/BSD-3-Clause for more information.
 */
#include <mlpack/core.hpp>
#include <mlpack/core/optimizers/sarah/sarah.hpp>

#include <boost/test/unit_test.hpp>
#include "test_tools.hpp"
#include "test_function_tools.hpp"

using namespace mlpack;
using namespace mlpack::optimization;

BOOST_AUTO_TEST_SUITE(SARAHTest);

/**
 * Run SARAH on logistic regression and make sure the results are
 * acceptable.
 */
BOOST_AUTO_TEST_CASE(SAHRALogisticRegressionTest)
{
  arma::mat data, testData, shuffledData;
  arma::Row<size_t> responses, testResponses, shuffledResponses;

  LogisticRegressionTestData(data, testData, shuffledData,
      responses, testResponses, shuffledResponses);

  // Now run big-batch SGD with a couple of batch sizes.
  for (size_t batchSize = 35; batchSize < 45; batchSize += 5)
  {
    SARAH optimizer(0.01, batchSize, 250, 0, 1e-5, true);
    LogisticRegression<> lr(shuffledData, shuffledResponses, optimizer, 0.5);

    // Ensure that the error is close to zero.
    const double acc = lr.ComputeAccuracy(data, responses);
    BOOST_REQUIRE_CLOSE(acc, 100.0, 1.5); // 1.5% error tolerance.

    const double testAcc = lr.ComputeAccuracy(testData, testResponses);
    BOOST_REQUIRE_CLOSE(testAcc, 100.0, 1.5); // 1.5% error tolerance.
  }
}

/**
 * Run SARAH_Plus on logistic regression and make sure the results are
 * acceptable.
 */
BOOST_AUTO_TEST_CASE(SAHRAPlusLogisticRegressionTest)
{
  arma::mat data, testData, shuffledData;
  arma::Row<size_t> responses, testResponses, shuffledResponses;

  LogisticRegressionTestData(data, testData, shuffledData,
      responses, testResponses, shuffledResponses);

  // Now run big-batch SGD with a couple of batch sizes.
  for (size_t batchSize = 35; batchSize < 45; batchSize += 5)
  {
    SARAH_Plus optimizer(0.01, batchSize, 250, 0, 1e-5, true);
    LogisticRegression<> lr(shuffledData, shuffledResponses, optimizer, 0.5);

    // Ensure that the error is close to zero.
    const double acc = lr.ComputeAccuracy(data, responses);
    BOOST_REQUIRE_CLOSE(acc, 100.0, 1.5); // 1.5% error tolerance.

    const double testAcc = lr.ComputeAccuracy(testData, testResponses);
    BOOST_REQUIRE_CLOSE(testAcc, 100.0, 1.5); // 1.5% error tolerance.
  }
}

BOOST_AUTO_TEST_SUITE_END();

max_stars_repo_name: chigur/mlpack

max_issues_repo_name: chigur/mlpack

max_forks_repo_name: chigur/mlpack