text:
// ------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
// Licensed under the MIT License (MIT). See License.txt in the repo root for license information.
// ------------------------------------------------------------

#include "stdafx.h"

#include <stdlib.h>
#include <boost/test/unit_test.hpp>
#include "Common/boost-taef.h"

/// BackCompatible test for BackupRestore
/// Note: For now, the test only covers <int, int> type of store.
///       RDBug 11728221:BackCompat BackupAndRestore tests: Add cases 1. component states race, 2. backup cross replicas, 3. restore token verify
///       RDBug 11728220:BackCompat BackupAndRestore tests: Move helper functions to replica lib and share helper functions.
/// Test dimension:
///+---------------+--------------+------------------+---------------------+------------------------+----------------+----------------+
///| Backup Option |    Status    |    SM states     | StateProvider Count |      Restore From      | Restore Policy | Target Replica |
///+---------------+--------------+------------------+---------------------+------------------------+----------------+----------------+
///| Full          | LR state     | Empty            |          0          | Log + Empty Checkpoint | Safe           | Clean          |
///+---------------+--------------+------------------+---------------------+------------------------+----------------+----------------+
///| Incremental   | SM state     | Active           |          1          | Log + Checkpoint       | Force          | Dirty          |
///+---------------+--------------+------------------+---------------------+------------------------+----------------+----------------+
///|               | TStore state | Active + Deleted |          4          |                        |                |                |
///+---------------+--------------+------------------+---------------------+------------------------+----------------+----------------+
namespace Data
{
    namespace Integration
    {
        using namespace Common;
        using namespace ktl;
        using namespace Data::Utilities;
        using namespace TxnReplicator;
        using namespace TxnReplicator::TestCommon;

        StringLiteral const TraceComponent("BackCompatibleBackupRestoreTests");
        std::wstring const TestLogFileName(L"BackCompatibleBackupRestoreTests.log");

        class BackCompatibleBackupRestoreTests
        {
        public:
            Awaitable<void> Test_Restore_EmptyBackup_Success(
                __in wstring const & testFolder,
                __in wstring const & backupFolder,
                __in bool isReplicaClean,
                __in int numberOfActiveStateProviders,
                __in int numberOfDeleteStateProviders,
                __in Data::Log::LogManager & logManager,
                __in FABRIC_RESTORE_POLICY policy,
                __in KGuid const & partitionId,
                __in FABRIC_REPLICA_ID replicaId);

            Awaitable<void> Test_Restore_Backup_Success(
                __in wstring const & testFolder,
                __in wstring const & backupFolder,
                __in int dictNum,
                __in Data::Log::LogManager & logManager,
                __in FABRIC_RESTORE_POLICY policy,
                __in KGuid const & partitionId,
                __in FABRIC_REPLICA_ID replicaId);

        protected:
            enum TestCase
            {
                Empty = 0,
                OneDict_Full = 1,
                FourDict_Full = 2,
                FourDict_Full_Checkpointed = 3,
                FourDict_FullAndIncremental = 4,
                FoutDict_FullAndIncremental_Checkpointed = 5,
            };

        protected:
            Awaitable<void> VerifyDictionaryAsync(
                __in wstring dictName,
                __in int dictIndex,
                __in Replica const & replica);

            wstring CreateFileName(
                __in wstring const & folderName);

            KUri::CSPtr GetStateProviderName(
                __in int stateProviderIndex);

            void VerifyIfStateProviderExists(
                __in ITransactionalReplicator & replicator,
                __in KUri const & stateProviderName,
                __in BOOLEAN expectResult);

            void InitializeKtlConfig(
                __in std::wstring workDir,
                __in std::wstring fileName,
                __in KAllocator & allocator,
                __out KtlLogger::SharedLogSettingsSPtr & sharedLogSettings);

            void EndTest();

            wstring SetupBackupFolder(__in TestCase testCase);

        protected:
            CommonConfig config; // load the configuration object as its needed for the tracing to work
            KtlSystem * underlyingSystem_;
        };

        Awaitable<void> BackCompatibleBackupRestoreTests::Test_Restore_EmptyBackup_Success(
            __in wstring const & testFolder,
            __in wstring const & backupFolder,
            __in bool isReplicaClean,
            __in int numberOfActiveStateProviders,
            __in int numberOfDeleteStateProviders,
            __in Data::Log::LogManager & logManager,
            __in FABRIC_RESTORE_POLICY policy,
            __in KGuid const & partitionId,
            __in FABRIC_REPLICA_ID replicaId)
        {
            NTSTATUS status = STATUS_UNSUCCESSFUL;

            KAllocator & allocator = underlyingSystem_->PagedAllocator();

            UpgradeStateProviderFactory::SPtr stateProviderFactory = UpgradeStateProviderFactory::Create(underlyingSystem_->PagedAllocator(), true);

            KString::SPtr backupFolderPath = KPath::CreatePath(backupFolder.c_str(), allocator);

            Data::Utilities::OperationData::SPtr initParams = Data::Utilities::OperationData::Create(allocator);
            Data::Utilities::BinaryWriter bw(allocator);
            bw.Write(L"Initial Value", Data::Utilities::UTF16);
            initParams->Append(*bw.GetBuffer(0));

            KStringView typeName(
                (PWCHAR)TestStateProvider::TypeName.cbegin(),
                (ULONG)TestStateProvider::TypeName.size() + 1,
                (ULONG)TestStateProvider::TypeName.size());

            int lastInsertedStateProviderIndex = -1;
            {
                Replica::SPtr replica = Replica::Create(
                    partitionId,
                    replicaId,
                    testFolder,
                    logManager,
                    allocator,
                    stateProviderFactory.RawPtr());

                co_await replica->OpenAsync();

                // Become Primary after open:
                // 1. Update Status: Pending
                // 2. New Epoch with new data loss number.
                // 3. Change Role to Primary
                // 4. Update Status: Granted.
                replica->SetReadStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_RECONFIGURATION_PENDING);
                replica->SetWriteStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_RECONFIGURATION_PENDING);

                FABRIC_EPOCH epoch1; epoch1.DataLossNumber = 1; epoch1.ConfigurationNumber = 1; epoch1.Reserved = nullptr;
                co_await replica->ChangeRoleAsync(epoch1, FABRIC_REPLICA_ROLE_PRIMARY);

                replica->SetReadStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_GRANTED);
                replica->SetWriteStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_GRANTED);

                if (numberOfActiveStateProviders > 0)
                {
                    for (int i = 0; i < numberOfActiveStateProviders; ++i)
                    {
                        Transaction::SPtr txn;
                        replica->TxnReplicator->CreateTransaction(txn);
                        KFinally([&] {txn->Dispose(); });

                        KUri::CSPtr stateProviderName = GetStateProviderName(i);
                        status = co_await replica->TxnReplicator->AddAsync(
                            *txn,
                            *stateProviderName,
                            typeName,
                            initParams.RawPtr());
                        VERIFY_IS_TRUE(NT_SUCCESS(status));
                        co_await txn->CommitAsync();

                        ++lastInsertedStateProviderIndex;
                    }

                    for (int i = 0; i < numberOfDeleteStateProviders; ++i)
                    {
                        Transaction::SPtr txn;
                        replica->TxnReplicator->CreateTransaction(txn);
                        KFinally([&] {txn->Dispose(); });

                        KUri::CSPtr stateProviderName = GetStateProviderName(i);
                        status = co_await replica->TxnReplicator->RemoveAsync(*txn, *stateProviderName);
                        VERIFY_IS_TRUE(NT_SUCCESS(status));
                        co_await txn->CommitAsync();
                    }

                    // Verify current states are expected
                    for (int i = 0; i <= lastInsertedStateProviderIndex; i++)
                    {
                        this->VerifyIfStateProviderExists(*replica->TxnReplicator, *GetStateProviderName(i), i < numberOfDeleteStateProviders ? FALSE : TRUE);
                    }
                }

                // Close the replica:
                // 1. Update Status: NOT PRIMARY
                // 2. Close
                replica->SetReadStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_NOT_PRIMARY);
                replica->SetWriteStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_NOT_PRIMARY);

                if (isReplicaClean)
                {
                    FABRIC_EPOCH epoch2; epoch2.DataLossNumber = 1; epoch2.ConfigurationNumber = 2; epoch2.Reserved = nullptr;
                    co_await replica->ChangeRoleAsync(epoch2, FABRIC_REPLICA_ROLE_NONE);
                }

                co_await replica->CloseAsync();
            }

            {
                TestDataLossHandler::SPtr dataLossHandler = TestDataLossHandler::Create(
                    allocator,
                    backupFolderPath.RawPtr(),
                    policy);

                Replica::SPtr replica = Replica::Create(
                    partitionId,
                    replicaId,
                    testFolder,
                    logManager,
                    allocator,
                    stateProviderFactory.RawPtr(),
                    nullptr,
                    dataLossHandler.RawPtr());

                status = dataLossHandler->Initialize(*replica->TxnReplicator);
                VERIFY_IS_TRUE(NT_SUCCESS(status));

                // Open the replica.
                co_await replica->OpenAsync();

                // Become Primary after open (For OnDataLossAsync):
                // 1. Update Status: Pending
                // 2. New Epoch with new data loss number.
                // 3. Change Role to Primary
                replica->SetReadStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_RECONFIGURATION_PENDING);
                replica->SetWriteStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_RECONFIGURATION_PENDING);

                FABRIC_EPOCH epoch3; epoch3.DataLossNumber = 2; epoch3.ConfigurationNumber = 2; epoch3.Reserved = nullptr;
                co_await replica->ChangeRoleAsync(epoch3, FABRIC_REPLICA_ROLE_PRIMARY);

                // Get OnDataLossAsync and become fully Primary
                // 1. OnDataLossAsync
                // 2. Update Status: Granted
                // TODO: UpdateCatchupConfig & WaitForQuorumCatchup for 1 replica?
                BOOLEAN isStateChanged = false;
                status = co_await replica->OnDataLossAsync(isStateChanged);
                VERIFY_ARE_EQUAL(status, policy == FABRIC_RESTORE_POLICY_FORCE ? STATUS_SUCCESS : STATUS_INVALID_PARAMETER);
                VERIFY_ARE_EQUAL(isStateChanged, policy == FABRIC_RESTORE_POLICY_FORCE ? TRUE : FALSE);

                replica->SetReadStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_GRANTED);
                replica->SetWriteStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_GRANTED);

                if (policy == FABRIC_RESTORE_POLICY_FORCE)
                {
                    // Verify restored state
                    for (int i = 0; i <= lastInsertedStateProviderIndex; i++)
                    {
                        this->VerifyIfStateProviderExists(*replica->TxnReplicator, *GetStateProviderName(i), FALSE);
                    }
                }

                // Drop the replica:
                // 1. Update Status: NOT PRIMARY
                // 2. Change Role to None
                // 3. Close
                replica->SetReadStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_NOT_PRIMARY);
                replica->SetWriteStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_NOT_PRIMARY);

                FABRIC_EPOCH epoch4; epoch4.DataLossNumber = 2; epoch4.ConfigurationNumber = 3; epoch4.Reserved = nullptr;
                co_await replica->ChangeRoleAsync(epoch4, FABRIC_REPLICA_ROLE_NONE);

                co_await replica->CloseAsync();
            }

            co_return;
        }

        Awaitable<void> BackCompatibleBackupRestoreTests::Test_Restore_Backup_Success(
            __in wstring const & testFolder,
            __in wstring const & backupFolder,
            __in int dictNum,
            __in Data::Log::LogManager & logManager,
            __in FABRIC_RESTORE_POLICY policy,
            __in KGuid const & partitionId,
            __in FABRIC_REPLICA_ID replicaId)
        {
            NTSTATUS status = STATUS_UNSUCCESSFUL;
            KAllocator & allocator = underlyingSystem_->PagedAllocator();

            UpgradeStateProviderFactory::SPtr stateProviderFactory = UpgradeStateProviderFactory::Create(underlyingSystem_->PagedAllocator(), true);
            KString::SPtr backupFolderPath = KPath::CreatePath(backupFolder.c_str(), allocator);

            {
                TestDataLossHandler::SPtr dataLossHandler = TestDataLossHandler::Create(
                    allocator,
                    backupFolderPath.RawPtr(),
                    policy);

                Replica::SPtr replica = Replica::Create(
                    partitionId,
                    replicaId,
                    testFolder,
                    logManager,
                    allocator,
                    stateProviderFactory.RawPtr(),
                    nullptr,
                    dataLossHandler.RawPtr()); // Default FABRIC_TRANSACTIONAL_REPLICATOR_SERIALIZATION_VERSION is managed (0).

                status = dataLossHandler->Initialize(*replica->TxnReplicator);
                VERIFY_IS_TRUE(NT_SUCCESS(status));

                co_await replica->OpenAsync();

                // Become Primary after open (For OnDataLossAsync):
                // 1. Update Status: Pending
                // 2. New Epoch with new data loss number.
                // 3. Change Role to Primary
                replica->SetReadStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_RECONFIGURATION_PENDING);
                replica->SetWriteStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_RECONFIGURATION_PENDING);

                FABRIC_EPOCH epoch1; epoch1.DataLossNumber = 1; epoch1.ConfigurationNumber = 1; epoch1.Reserved = nullptr;
                co_await replica->ChangeRoleAsync(epoch1, FABRIC_REPLICA_ROLE_PRIMARY);

                // Get OnDataLossAsync and become fully Primary
                // 1. OnDataLossAsync
                // 2. Update Status: Granted
                // TODO: UpdateCatchupConfig & WaitForQuorumCatchup for 1 replica?
                BOOLEAN isStateChanged = false;
                status = co_await replica->OnDataLossAsync(isStateChanged);
                VERIFY_IS_TRUE(NT_SUCCESS(status));
                VERIFY_IS_TRUE(isStateChanged == TRUE);

                replica->SetReadStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_GRANTED);
                replica->SetWriteStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_GRANTED);
                wstring dictName = L"fabric:/test/dictionary";

                // Verify restored states
                if (dictNum == 1)
                {
                    co_await this->VerifyDictionaryAsync(dictName, -1, *replica);
                }
                else
                {
                    for(int i = 0; i < dictNum; ++i)
                    {
                        co_await this->VerifyDictionaryAsync(dictName, i, *replica);
                    }
                }

                replica->SetReadStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_NOT_PRIMARY);
                replica->SetWriteStatus(FABRIC_SERVICE_PARTITION_ACCESS_STATUS_NOT_PRIMARY);
                FABRIC_EPOCH epoch2; epoch2.DataLossNumber = 1; epoch2.ConfigurationNumber = 2; epoch2.Reserved = nullptr;
                co_await replica->ChangeRoleAsync(epoch2, FABRIC_REPLICA_ROLE_NONE);
                co_await replica->CloseAsync();
            }

            co_return;
        }

        Awaitable<void> BackCompatibleBackupRestoreTests::VerifyDictionaryAsync(
            __in wstring dictName,
            __in int dictIndex,
            __in Replica const & replica)
        {
            NTSTATUS status = STATUS_UNSUCCESSFUL;
            if (dictIndex > -1)
            {
                dictName.append(std::to_wstring(dictIndex));
            }

            {
                KUri::CSPtr dictionaryName;
                status = KUri::Create(dictName.c_str(), underlyingSystem_->PagedAllocator(), dictionaryName);
                VERIFY_IS_TRUE(NT_SUCCESS(status));

                IStateProvider2::SPtr stateProvider2;
                status = replica.TxnReplicator->Get(*dictionaryName, stateProvider2);
                VERIFY_IS_TRUE(NT_SUCCESS(status));
                VERIFY_IS_NOT_NULL(stateProvider2);
            }

            {
                KUri::CSPtr dataStoreName;
                wstring dataStoreString = dictName + L"/dataStore";
                status = KUri::Create(dataStoreString.c_str(), underlyingSystem_->PagedAllocator(), dataStoreName);
                VERIFY_IS_TRUE(NT_SUCCESS(status));

                IStateProvider2::SPtr stateProvider2;
                status = replica.TxnReplicator->Get(*dataStoreName, stateProvider2);
                VERIFY_IS_TRUE(NT_SUCCESS(status));
                VERIFY_IS_NOT_NULL(stateProvider2);
                TStore::IStore <int, int> & store = dynamic_cast<Data::TStore::IStore<int, int> &>(*stateProvider2);
                VERIFY_ARE_EQUAL(2, store.Count);
                {
                    Transaction::SPtr txn = nullptr;
                    status = replica.TxnReplicator->CreateTransaction(txn);
                    VERIFY_IS_TRUE(NT_SUCCESS(status));
                    KFinally([&] { txn->Dispose(); });

                    Data::TStore::IStoreTransaction<int, int>::SPtr storeTxn;
                    store.CreateOrFindTransaction(*txn, storeTxn);

                    int key1 = 0;
                    int key2 = 1;

                    KeyValuePair<FABRIC_SEQUENCE_NUMBER, int> value1;
                    bool isKey1Found = co_await store.ConditionalGetAsync(*storeTxn, key1, TimeSpan::MaxValue, value1, CancellationToken::None);
                    VERIFY_IS_TRUE(isKey1Found);
                    VERIFY_ARE_EQUAL(key1, value1.Value)

                        KeyValuePair<FABRIC_SEQUENCE_NUMBER, int> value2;
                    bool isKey2Found = co_await store.ConditionalGetAsync(*storeTxn, key2, TimeSpan::MaxValue, value2, CancellationToken::None);
                    VERIFY_IS_TRUE(isKey2Found);
                    VERIFY_ARE_EQUAL(key2, value2.Value)

                        status = txn->Abort();
                    VERIFY_IS_TRUE(NT_SUCCESS(status));
                }
            }

            co_return;
        }

        void BackCompatibleBackupRestoreTests::VerifyIfStateProviderExists(
            __in ITransactionalReplicator & replicator,
            __in KUri const & stateProviderName,
            __in BOOLEAN expectResult)
        {
            IStateProvider2::SPtr stateProvider;
            NTSTATUS status = replicator.Get(stateProviderName, stateProvider);
            VERIFY_ARE_EQUAL(status, expectResult ? STATUS_SUCCESS : SF_STATUS_NAME_DOES_NOT_EXIST);
            VERIFY_ARE_EQUAL(expectResult, stateProvider != nullptr);
        }

        wstring BackCompatibleBackupRestoreTests::CreateFileName(
            __in wstring const & folderName)
        {
            wstring testFolderPath = Directory::GetCurrentDirectoryW();
            Path::CombineInPlace(testFolderPath, folderName);
            return testFolderPath;
        }

        void BackCompatibleBackupRestoreTests::InitializeKtlConfig(
            __in std::wstring workDir,
            __in std::wstring fileName,
            __in KAllocator & allocator,
            __out KtlLogger::SharedLogSettingsSPtr & sharedLogSettings)
        {
            auto settings = std::make_unique<KtlLogManager::SharedLogContainerSettings>();

            KString::SPtr sharedLogFileName = KPath::CreatePath(workDir.c_str(), allocator);
            KPath::CombineInPlace(*sharedLogFileName, fileName.c_str());

            if (!Common::Directory::Exists(workDir))
            {
                Common::Directory::Create(workDir);
            }

            KInvariant(sharedLogFileName->LengthInBytes() + sizeof(WCHAR) < 512 * sizeof(WCHAR)); // check to make sure there is space for the null terminator
            KMemCpySafe(&settings->Path[0], 512 * sizeof(WCHAR), sharedLogFileName->operator PVOID(), sharedLogFileName->LengthInBytes());
            settings->Path[sharedLogFileName->LengthInBytes() / sizeof(WCHAR)] = L'\0'; // set the null terminator
            settings->LogContainerId.GetReference().CreateNew();
            settings->LogSize = 1024 * 1024 * 512; // 512 MB.
            settings->MaximumNumberStreams = 0;
            settings->MaximumRecordSize = 0;
            settings->Flags = static_cast<ULONG>(Data::Log::LogCreationFlags::UseSparseFile);
            sharedLogSettings = make_shared<KtlLogger::SharedLogSettings>(std::move(settings));
        }

        KUri::CSPtr BackCompatibleBackupRestoreTests::GetStateProviderName(
            __in int stateProviderIndex)
        {
            wstring stateProviderName = wformatString(L"fabric:/store/{0}", stateProviderIndex);

            KUri::CSPtr spName;
            NTSTATUS status = KUri::Create(KStringView(stateProviderName.c_str()), underlyingSystem_->PagedAllocator(), spName);
            VERIFY_IS_TRUE(NT_SUCCESS(status));

            return spName;
        }

        void BackCompatibleBackupRestoreTests::EndTest()
        {
        }

        wstring BackCompatibleBackupRestoreTests::SetupBackupFolder(__in BackCompatibleBackupRestoreTests::TestCase testCase)
        {
            wstring backupFolder = Common::Directory::GetCurrentDirectoryW();
            Path::CombineInPlace(backupFolder, L"BackupContainer");
            Directory::Delete_WithRetry(backupFolder, true, true);

            wstring restorePath = Common::Directory::GetCurrentDirectoryW();
#ifdef PLATFORM_UNIX
            Path::CombineInPlace(restorePath, L"data_upgrade");
#else
            Path::CombineInPlace(restorePath, L"UpgradeTests");
#endif
            Path::CombineInPlace(restorePath, L"5.1");
            Path::CombineInPlace(restorePath, L"NativeStateManager");
            Path::CombineInPlace(restorePath, L"ManagedBackupFolder");

            switch (testCase)
            {
            case TestCase::Empty:
                Path::CombineInPlace(restorePath, L"Empty");
                break;
            case OneDict_Full:
                Path::CombineInPlace(restorePath, L"OneDict_Full");
                break;
            case FourDict_Full:
                Path::CombineInPlace(restorePath, L"FourDict_Full");
                break;
            case FourDict_Full_Checkpointed:
                Path::CombineInPlace(restorePath, L"FourDict_Full_Checkpointed");
                break;
            case FourDict_FullAndIncremental:
                Path::CombineInPlace(restorePath, L"FourDict_FullAndIncremental");
                break;
            case FoutDict_FullAndIncremental_Checkpointed:
                Path::CombineInPlace(restorePath, L"FoutDict_FullAndIncremental_Checkpointed");
                break;
            default:
                ASSERT_IF(true, "BackCompatibleBackupRestoreTests test case is invalid.")
            }

            ErrorCode error = Common::Directory::Copy(restorePath.c_str(), backupFolder.c_str(), true);
            VERIFY_IS_TRUE(error.IsSuccess());

            return backupFolder;
        }

        BOOST_FIXTURE_TEST_SUITE(BackCompatibleBackupRestoreTestSuite, BackCompatibleBackupRestoreTests);

        // Restore to the empty backup from managed, and current state manager has no states.
        BOOST_AUTO_TEST_CASE(Restore_EmptyBackup_NoState_Success)
        {
            // Setup
            wstring testName(L"Restore_EmptyBackup_NoState_Success");
            wstring testFolderPath = CreateFileName(testName);

            // Start up cleanup.
            Directory::Delete_WithRetry(testFolderPath, true, true);

            wstring workFolder = Path::Combine(testFolderPath, L"work");
            wstring backupFolder = SetupBackupFolder(TestCase::Empty);

            KGuid partitionId;
            partitionId.CreateNew();
            FABRIC_REPLICA_ID const replicaId = 17;

            TEST_TRACE_BEGIN(testName)
            {
                // Test Setup
                KtlLogger::SharedLogSettingsSPtr sharedLogSettings;
                InitializeKtlConfig(testFolderPath, TestLogFileName, underlyingSystem_->NonPagedAllocator(), sharedLogSettings);

                Data::Log::LogManager::SPtr logManager;
                status = Data::Log::LogManager::Create(underlyingSystem_->NonPagedAllocator(), logManager);
                VERIFY_IS_TRUE(NT_SUCCESS(status));

                status = SyncAwait(logManager->OpenAsync(CancellationToken::None, sharedLogSettings));
                VERIFY_IS_TRUE(NT_SUCCESS(status));

                // Test call
                SyncAwait(Test_Restore_EmptyBackup_Success(
                    workFolder,
                    backupFolder,
                    false,
                    0,
                    0,
                    *logManager,
                    FABRIC_RESTORE_POLICY_FORCE,
                    partitionId,
                    replicaId));

                status = SyncAwait(logManager->CloseAsync(CancellationToken::None));
                VERIFY_IS_TRUE(NT_SUCCESS(status));
                logManager = nullptr;
            }

            // Post-clean up
            if (Directory::Exists(testFolderPath))
            {
                Directory::Delete_WithRetry(testFolderPath, true, true);
            }
        }

        // Restore to the empty backup from managed, and current state manager has active states.
        BOOST_AUTO_TEST_CASE(Restore_EmptyBackup_ActiveStates_Success)
        {
            // Setup
            wstring testName(L"Restore_EmptyBackup_ActiveStates_Success");
            wstring testFolderPath = CreateFileName(testName);

            // Start up cleanup.
            Directory::Delete_WithRetry(testFolderPath, true, true);

            wstring workFolder = Path::Combine(testFolderPath, L"work");
            wstring backupFolder = SetupBackupFolder(TestCase::Empty);

            KGuid partitionId;
            partitionId.CreateNew();
            FABRIC_REPLICA_ID const replicaId = 17;

            TEST_TRACE_BEGIN(testName)
            {
                // Test Setup
                KtlLogger::SharedLogSettingsSPtr sharedLogSettings;
                InitializeKtlConfig(testFolderPath, TestLogFileName, underlyingSystem_->NonPagedAllocator(), sharedLogSettings);

                Data::Log::LogManager::SPtr logManager;
                status = Data::Log::LogManager::Create(underlyingSystem_->NonPagedAllocator(), logManager);
                VERIFY_IS_TRUE(NT_SUCCESS(status));

                status = SyncAwait(logManager->OpenAsync(CancellationToken::None, sharedLogSettings));
                VERIFY_IS_TRUE(NT_SUCCESS(status));

                // Test call
                SyncAwait(Test_Restore_EmptyBackup_Success(
                    workFolder,
                    backupFolder,
                    false,
                    8,
                    0,
                    *logManager,
                    FABRIC_RESTORE_POLICY_FORCE,
                    partitionId,
                    replicaId));

                status = SyncAwait(logManager->CloseAsync(CancellationToken::None));
                VERIFY_IS_TRUE(NT_SUCCESS(status));
                logManager = nullptr;
            }

            // Post-clean up
            if (Directory::Exists(testFolderPath))
            {
                Directory::Delete_WithRetry(testFolderPath, true, true);
            }
        }

        // Restore to the empty backup from managed, and current state manager has active and deleted states.
        BOOST_AUTO_TEST_CASE(Restore_EmptyBackup_ActiveAndDeletedStates_Success)
        {
            // Setup
            wstring testName(L"Restore_EmptyBackup_ActiveAndDeletedStates_Success");
            wstring testFolderPath = CreateFileName(testName);

            // Start up cleanup.
            Directory::Delete_WithRetry(testFolderPath, true, true);

            wstring workFolder = Path::Combine(testFolderPath, L"work");
            wstring backupFolder = SetupBackupFolder(TestCase::Empty);

            KGuid partitionId;
            partitionId.CreateNew();
            FABRIC_REPLICA_ID const replicaId = 17;

            TEST_TRACE_BEGIN(testName)
            {
                // Test Setup
                KtlLogger::SharedLogSettingsSPtr sharedLogSettings;
                InitializeKtlConfig(testFolderPath, TestLogFileName, underlyingSystem_->NonPagedAllocator(), sharedLogSettings);

                Data::Log::LogManager::SPtr logManager;
                status = Data::Log::LogManager::Create(underlyingSystem_->NonPagedAllocator(), logManager);
                VERIFY_IS_TRUE(NT_SUCCESS(status));

                status = SyncAwait(logManager->OpenAsync(CancellationToken::None, sharedLogSettings));
                VERIFY_IS_TRUE(NT_SUCCESS(status));

                // Test call
                SyncAwait(Test_Restore_EmptyBackup_Success(
                    workFolder,
                    backupFolder,
                    false,
                    8,
                    4,
                    *logManager,
                    FABRIC_RESTORE_POLICY_FORCE,
                    partitionId,
                    replicaId));

                status = SyncAwait(logManager->CloseAsync(CancellationToken::None));
                VERIFY_IS_TRUE(NT_SUCCESS(status));
                logManager = nullptr;
            }

            // Post-clean up
            if (Directory::Exists(testFolderPath))
            {
                Directory::Delete_WithRetry(testFolderPath, true, true);
            }
        }

        // Restore to the empty backup from managed, and current state manager has clean state.
        BOOST_AUTO_TEST_CASE(Restore_EmptyBackup_CleanStates_Success)
        {
            // Setup
            wstring testName(L"Restore_EmptyBackup_CleanStates_Success");
            wstring testFolderPath = CreateFileName(testName);

            // Start up cleanup.
            Directory::Delete_WithRetry(testFolderPath, true, true);

            wstring workFolder = Path::Combine(testFolderPath, L"work");
            wstring backupFolder = SetupBackupFolder(TestCase::Empty);

            KGuid partitionId;
            partitionId.CreateNew();
            FABRIC_REPLICA_ID const replicaId = 17;

            TEST_TRACE_BEGIN(testName)
            {
                // Test Setup
                KtlLogger::SharedLogSettingsSPtr sharedLogSettings;
                InitializeKtlConfig(testFolderPath, TestLogFileName, underlyingSystem_->NonPagedAllocator(), sharedLogSettings);

                Data::Log::LogManager::SPtr logManager;
                status = Data::Log::LogManager::Create(underlyingSystem_->NonPagedAllocator(), logManager);
                VERIFY_IS_TRUE(NT_SUCCESS(status));

                status = SyncAwait(logManager->OpenAsync(CancellationToken::None, sharedLogSettings));
                VERIFY_IS_TRUE(NT_SUCCESS(status));

                // Test call
                SyncAwait(Test_Restore_EmptyBackup_Success(
                    workFolder,
                    backupFolder,
                    true,
                    8,
                    4,
                    *logManager,
                    FABRIC_RESTORE_POLICY_FORCE,
                    partitionId,
                    replicaId));

                status = SyncAwait(logManager->CloseAsync(CancellationToken::None));
                VERIFY_IS_TRUE(NT_SUCCESS(status));
                logManager = nullptr;
            }

            // Post-clean up
            if (Directory::Exists(testFolderPath))
            {
                Directory::Delete_WithRetry(testFolderPath, true, true);
            }
        }

        // Restore to the empty backup from managed, and current state manager has dirty states. Since the restore policy is set to safe,
        // restore should fail.
        BOOST_AUTO_TEST_CASE(RestoreSafe_EmptyBackup_DirtyStates_Success)
        {
            // Setup
            wstring testName(L"RestoreSafe_EmptyBackup_DirtyStates_Success");
            wstring testFolderPath = CreateFileName(testName);

            // Start up cleanup.
            Directory::Delete_WithRetry(testFolderPath, true, true);

            wstring workFolder = Path::Combine(testFolderPath, L"work");
            wstring backupFolder = SetupBackupFolder(TestCase::Empty);

            KGuid partitionId;
            partitionId.CreateNew();
            FABRIC_REPLICA_ID const replicaId = 17;

            TEST_TRACE_BEGIN(testName)
            {
                // Test Setup
                KtlLogger::SharedLogSettingsSPtr sharedLogSettings;
                InitializeKtlConfig(testFolderPath, TestLogFileName, underlyingSystem_->NonPagedAllocator(), sharedLogSettings);

                Data::Log::LogManager::SPtr logManager;
                status = Data::Log::LogManager::Create(underlyingSystem_->NonPagedAllocator(), logManager);
                VERIFY_IS_TRUE(NT_SUCCESS(status));

                status = SyncAwait(logManager->OpenAsync(CancellationToken::None, sharedLogSettings));
                VERIFY_IS_TRUE(NT_SUCCESS(status));

                // Test call
                SyncAwait(Test_Restore_EmptyBackup_Success(
                    workFolder,
                    backupFolder,
                    false,
                    8,
                    4,
                    *logManager,
                    FABRIC_RESTORE_POLICY_SAFE,
                    partitionId,
                    replicaId));

                status = SyncAwait(logManager->CloseAsync(CancellationToken::None));
                VERIFY_IS_TRUE(NT_SUCCESS(status));
                logManager = nullptr;
            }

            // Post-clean up
            if (Directory::Exists(testFolderPath))
            {
                Directory::Delete_WithRetry(testFolderPath, true, true);
            }
        }

        // Restore to the Full Backup with one item from managed.
        BOOST_AUTO_TEST_CASE(Restore_OneItem_WithoutCheckpoint_Success)
        {
            // Setup
            wstring testName(L"Restore_OneItem_WithoutCheckpoint_Success");
            wstring testFolderPath = CreateFileName(testName);

            // Start up cleanup.
            Directory::Delete_WithRetry(testFolderPath, true, true);

            wstring workFolder = Path::Combine(testFolderPath, L"work");
            wstring backupFolder = SetupBackupFolder(TestCase::OneDict_Full);

            KGuid partitionId;
            partitionId.CreateNew();
            FABRIC_REPLICA_ID const replicaId = 17;

            TEST_TRACE_BEGIN(testName)
            {
                // Test Setup
                KtlLogger::SharedLogSettingsSPtr sharedLogSettings;
                InitializeKtlConfig(testFolderPath, TestLogFileName, underlyingSystem_->NonPagedAllocator(), sharedLogSettings);

                Data::Log::LogManager::SPtr logManager;
                status = Data::Log::LogManager::Create(underlyingSystem_->NonPagedAllocator(), logManager);
                VERIFY_IS_TRUE(NT_SUCCESS(status));

                status = SyncAwait(logManager->OpenAsync(CancellationToken::None, sharedLogSettings));
                VERIFY_IS_TRUE(NT_SUCCESS(status));

                // Test call
                SyncAwait(Test_Restore_Backup_Success(
                    workFolder,
                    backupFolder,
                    1,
                    *logManager,
                    FABRIC_RESTORE_POLICY_SAFE,
                    partitionId,
                    replicaId));

                status = SyncAwait(logManager->CloseAsync(CancellationToken::None));
                VERIFY_IS_TRUE(NT_SUCCESS(status));
                logManager = nullptr;
            }

            // Post-clean up
            if (Directory::Exists(testFolderPath))
            {
                Directory::Delete_WithRetry(testFolderPath, true, true);
            }
        }

        // Restore to the Full Backup with four items from managed.
        BOOST_AUTO_TEST_CASE(Restore_FourItems_WithoutCheckpoint_Success)
        {
            // Setup
            wstring testName(L"Restore_FourItems_WithoutCheckpoint_Success");
            wstring testFolderPath = CreateFileName(testName);

            // Start up cleanup.
            Directory::Delete_WithRetry(testFolderPath, true, true);

            wstring workFolder = Path::Combine(testFolderPath, L"work");
            wstring backupFolder = SetupBackupFolder(TestCase::FourDict_Full);

            KGuid partitionId;
            partitionId.CreateNew();
            FABRIC_REPLICA_ID const replicaId = 17;

            TEST_TRACE_BEGIN(testName)
            {
                // Test Setup
                KtlLogger::SharedLogSettingsSPtr sharedLogSettings;
                InitializeKtlConfig(testFolderPath, TestLogFileName, underlyingSystem_->NonPagedAllocator(), sharedLogSettings);

                Data::Log::LogManager::SPtr logManager;
                status = Data::Log::LogManager::Create(underlyingSystem_->NonPagedAllocator(), logManager);
                VERIFY_IS_TRUE(NT_SUCCESS(status));

                status = SyncAwait(logManager->OpenAsync(CancellationToken::None, sharedLogSettings));
                VERIFY_IS_TRUE(NT_SUCCESS(status));

                // Test call
                SyncAwait(Test_Restore_Backup_Success(
                    workFolder,
                    backupFolder,
                    4,
                    *logManager,
                    FABRIC_RESTORE_POLICY_SAFE,
                    partitionId,
                    replicaId));

                status = SyncAwait(logManager->CloseAsync(CancellationToken::None));
                VERIFY_IS_TRUE(NT_SUCCESS(status));
                logManager = nullptr;
            }

            // Post-clean up
            if (Directory::Exists(testFolderPath))
            {
                Directory::Delete_WithRetry(testFolderPath, true, true);
            }
        }

        // Restore to the Full Backup with four checkpointed items from managed.
        BOOST_AUTO_TEST_CASE(Restore_Backup_Four_Checkpointed_Success)
        {
            // Setup
            wstring testName(L"Restore_Backup_Four_Checkpointed_Success");
            wstring testFolderPath = CreateFileName(testName);

            // Start up cleanup.
            Directory::Delete_WithRetry(testFolderPath, true, true);

            wstring workFolder = Path::Combine(testFolderPath, L"work");
            wstring backupFolder = SetupBackupFolder(TestCase::FourDict_Full_Checkpointed);

            KGuid partitionId;
            partitionId.CreateNew();
            FABRIC_REPLICA_ID const replicaId = 17;

            TEST_TRACE_BEGIN(testName)
            {
                // Test Setup
                KtlLogger::SharedLogSettingsSPtr sharedLogSettings;
                InitializeKtlConfig(testFolderPath, TestLogFileName, underlyingSystem_->NonPagedAllocator(), sharedLogSettings);

                Data::Log::LogManager::SPtr logManager;
                status = Data::Log::LogManager::Create(underlyingSystem_->NonPagedAllocator(), logManager);
                VERIFY_IS_TRUE(NT_SUCCESS(status));

                status = SyncAwait(logManager->OpenAsync(CancellationToken::None, sharedLogSettings));
                VERIFY_IS_TRUE(NT_SUCCESS(status));

                // Test call
                SyncAwait(Test_Restore_Backup_Success(
                    workFolder,
                    backupFolder,
                    4,
                    *logManager,
                    FABRIC_RESTORE_POLICY_SAFE,
                    partitionId,
                    replicaId));

                status = SyncAwait(logManager->CloseAsync(CancellationToken::None));
                VERIFY_IS_TRUE(NT_SUCCESS(status));
                logManager = nullptr;
            }

            // Post-clean up
            if (Directory::Exists(testFolderPath))
            {
                Directory::Delete_WithRetry(testFolderPath, true, true);
            }
        }

        // Restore to the Full and Incremental Backup with four items from managed.
        BOOST_AUTO_TEST_CASE(Restore_Backup_FullAndIncremental_Success)
        {
            // Setup
            wstring testName(L"Restore_Backup_FullAndIncremental_Success");
            wstring testFolderPath = CreateFileName(testName);

            wstring workFolder = Path::Combine(testFolderPath, L"work");
            wstring backupFolder = SetupBackupFolder(TestCase::FourDict_FullAndIncremental);

            KGuid partitionId;
            partitionId.CreateNew();
            FABRIC_REPLICA_ID const replicaId = 17;

            TEST_TRACE_BEGIN(testName)
            {
                // Test Setup
                KtlLogger::SharedLogSettingsSPtr sharedLogSettings;
                InitializeKtlConfig(testFolderPath, TestLogFileName, underlyingSystem_->NonPagedAllocator(), sharedLogSettings);

                Data::Log::LogManager::SPtr logManager;
                status = Data::Log::LogManager::Create(underlyingSystem_->NonPagedAllocator(), logManager);
                VERIFY_IS_TRUE(NT_SUCCESS(status));

                status = SyncAwait(logManager->OpenAsync(CancellationToken::None, sharedLogSettings));
                VERIFY_IS_TRUE(NT_SUCCESS(status));

                // Test call
                SyncAwait(Test_Restore_Backup_Success(
                    workFolder,
                    backupFolder,
                    4,
                    *logManager,
                    FABRIC_RESTORE_POLICY_SAFE,
                    partitionId,
                    replicaId));

                status = SyncAwait(logManager->CloseAsync(CancellationToken::None));
                VERIFY_IS_TRUE(NT_SUCCESS(status));
                logManager = nullptr;
            }

            // Post-clean up
            if (Directory::Exists(testFolderPath))
            {
                Directory::Delete_WithRetry(testFolderPath, true, true);
            }
        }

        // Restore to the Full and Incremental Backup with four checkpointed items from managed.
        BOOST_AUTO_TEST_CASE(Restore_Backup_FullAndIncremental_Checkpointed_Success)
        {
            // Setup
            wstring testName(L"Restore_Backup_FullAndIncremental_Checkpointed_Success");
            wstring testFolderPath = CreateFileName(testName);

            wstring workFolder = Path::Combine(testFolderPath, L"work");
            wstring backupFolder = SetupBackupFolder(TestCase::FoutDict_FullAndIncremental_Checkpointed);

            KGuid partitionId;
            partitionId.CreateNew();
            FABRIC_REPLICA_ID const replicaId = 17;

            TEST_TRACE_BEGIN(testName)
            {
                // Test Setup
                KtlLogger::SharedLogSettingsSPtr sharedLogSettings;
                InitializeKtlConfig(testFolderPath, TestLogFileName, underlyingSystem_->NonPagedAllocator(), sharedLogSettings);

                Data::Log::LogManager::SPtr logManager;
                status = Data::Log::LogManager::Create(underlyingSystem_->NonPagedAllocator(), logManager);
                VERIFY_IS_TRUE(NT_SUCCESS(status));

                status = SyncAwait(logManager->OpenAsync(CancellationToken::None, sharedLogSettings));
                VERIFY_IS_TRUE(NT_SUCCESS(status));

                // Test call
                SyncAwait(Test_Restore_Backup_Success(
                    workFolder,
                    backupFolder,
                    4,
                    *logManager,
                    FABRIC_RESTORE_POLICY_SAFE,
                    partitionId,
                    replicaId));

                status = SyncAwait(logManager->CloseAsync(CancellationToken::None));
                VERIFY_IS_TRUE(NT_SUCCESS(status));
                logManager = nullptr;
            }

            // Post-clean up
            if (Directory::Exists(testFolderPath))
            {
                Directory::Delete_WithRetry(testFolderPath, true, true);
            }
        }

        BOOST_AUTO_TEST_SUITE_END();
    }
}

max_stars_repo_name: AnthonyM/service-fabric

max_issues_repo_name: AnthonyM/service-fabric

max_forks_repo_name: AnthonyM/service-fabric


text:
// Copyright (c) 2018 The Chratos Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include "dividendledgermodel.h"
#include "dividend/dividendledger.h"
#include "dividend/dividendtx.h"
#include "main.h"
#include <boost/bind.hpp>
#include "dividendtablemodel.h"
#include "walletmodel.h"
#include "wallet/wallet.h"
#include "optionsmodel.h"
#include "chratosgui.h"
#include "guiutil.h"

DividendLedgerModel::DividendLedgerModel(
  const PlatformStyle *platformStyle,
  CDividendLedger *ledger,
  WalletModel *walletModel,
  OptionsModel *optionsModel,
  QObject *parent
) : QObject(parent), ledger(ledger), optionsModel(optionsModel),
  walletModel(walletModel), fForceCheckDividendChanged(true),
  dividendTableModel(nullptr) {
}

CAmount DividendLedgerModel::getTotalDividendFund() const {
  return ledger->GetBalance();
}

OptionsModel *DividendLedgerModel::getOptionsModel() {
  return optionsModel;
}

int DividendLedgerModel::getCount() const {
  return ledger->GetOrdered().size();
}

std::map<uint256, CDividendTx> DividendLedgerModel::getTransactions() const {
  return ledger->GetMapLedger();
}

static void NotifyDividendChanged(
  DividendLedgerModel *model,
  CDividendLedger *ledger,
  const uint256 &hash,
  ChangeType status
) {
  QMetaObject::invokeMethod(
    model, "updateDividend", Qt::QueuedConnection,
    Q_ARG(uint256, hash), Q_ARG(ChangeType, status)
  );
}

void DividendLedgerModel::subscribeToCoreSignals() {
  ledger->NotifyDividendChanged.connect(
    boost::bind(NotifyDividendChanged, this, _1, _2, _3)
  );
}

void DividendLedgerModel::unsubscribeFromCoreSignals() {
  ledger->NotifyDividendChanged.disconnect(boost::bind(NotifyDividendChanged, this, _1, _2, _3));
}

void DividendLedgerModel::updateDividend(
  const uint256 &hash, const ChangeType &status
) {
  fForceCheckDividendChanged = true;
  auto mi = ledger->GetMapLedger().find(hash);

  if (status == ChangeType::CT_NEW && mi != ledger->GetMapLedger().end()) {
    auto tx = (*mi).second;
    QString date = GUIUtil::dateTimeStr(tx.GetBlockTime());

    auto unit = optionsModel->getDisplayUnit();
    auto amount = walletModel->getWallet()->GetCreditFromDividend(tx);
    Q_EMIT incomingDividend(date, unit, amount);
  }

}

void DividendLedgerModel::pollDividendChange() {
  TRY_LOCK(cs_main, lockMain);
  if (!lockMain) { return; }

  TRY_LOCK(ledger->cs_ledger, lockLedger);
  if (!lockLedger) { return; }

  if (fForceCheckDividendChanged || chainActive.Height() != cachedNumBlocks) {
    fForceCheckDividendChanged = false;

    if (dividendTableModel) {
      dividendTableModel->updateConfirmations();
    }
  }
}

CDividendLedger *DividendLedgerModel::getLedger() const {
  return ledger;
}

void DividendLedgerModel::setDividendTableModel(
  DividendTableModel *dividendTableModel
) {
  this->dividendTableModel = dividendTableModel;
}

CAmount DividendLedgerModel::getAmountReceived(const CDividendTx &tx) const {
  if (this->walletModel && this->walletModel->getWallet()) {
    return this->walletModel->getWallet()->GetCreditFromDividend(tx);
  } else {
    return 0;
  }
}

void DividendLedgerModel::setChratosGUI(ChratosGUI *gui) {
  if (gui) {
    connect(this,
      SIGNAL(incomingDividend(const QString &, int, const CAmount &)),
      gui,
      SLOT(dividendReceived(const QString &, int, const CAmount &))
    );
  }
}

ext: cpp

max_stars_repo_name: chratos-system/chratos-core

max_issues_repo_name: chratos-system/chratos-core

max_forks_repo_name: chratos-system/chratos-core


text:
/**
 *	\file
 */

#pragma once

#include "directory_entry_filter.hpp"
#include <boost/filesystem.hpp>

namespace module_loader {

/**
 *	Filters boost::filesystem::directory_entry objects
 *	such that only regular files or symlinks to regular
 *	files which have the appropriate extension to be
 *	shared libraries are included.
 */
class shared_library_directory_entry_filter : public directory_entry_filter {
public:
	virtual bool check (const boost::filesystem::directory_entry &) override;
};

}

ext: hpp

max_stars_repo_name: RobertLeahy/Module-Loader

max_issues_repo_name: RobertLeahy/Module-Loader

max_forks_repo_name: RobertLeahy/Module-Loader


text:
//
// Test that a const rvalue can't be passed to ref()
//
// Copyright 2014 Agustin Berge
//
// Distributed under the Boost Software License, Version 1.0.
// See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt
//

#include <boost/ref.hpp>

#if !defined(BOOST_NO_CXX11_RVALUE_REFERENCES)

struct X {};

X const crv() { return X(); }

int main()
{
    boost::reference_wrapper<X const> r = boost::ref( crv() ); // this should produce an ERROR
    (void)r;
}

#else
#  error To fail, this test requires rvalue references
#endif


text:
/*
 * Copyright (C) 2020 Jaslo Ziska
 *
 * This file is part of cuda-wrapper.
 *
 * This software may be modified and distributed under the terms of the
 * 3-clause BSD license.  See accompanying file LICENSE for details.
 */

#define BOOST_TEST_MODULE allocator
#include <boost/test/unit_test.hpp>

#include <boost/test/data/monomorphic.hpp>
#include <boost/test/data/test_case.hpp>

#include <cuda_wrapper/cuda_wrapper.hpp>

#include "test.hpp"

#define TEST_CASE(type, dataset)                                               \
    type A;                                                                    \
    BOOST_DATA_TEST_CASE(allocate, dataset, n) {                               \
        type::value_type* ptr = A.allocate(n);                                 \
        BOOST_TEST(ptr == A.address(*ptr));                                    \
        A.deallocate(ptr, n);                                                  \
    }

struct x
{
    int a;
    float b;
    double c = 0;

    x(int a, float b) : a(a), b(b) {}

    double d() { return a + b + c; }
    int e(int f, float g) { return f * g; }
};

class y
{
    int a;
    float b;
    double c = 0;

    double d() { return a + b + c; }
    int e(int f, float g) { return f * g; }
};

auto dataset = boost::unit_test::data::make<unsigned int>({
    0, 1, 3, 10, 57, 111, 999, 4321, 10000, 31415, 100000
});

#define TEST(allocator)                                                        \
    BOOST_AUTO_TEST_SUITE(type_int)                                            \
        TEST_CASE(allocator<int>, dataset)                                     \
    BOOST_AUTO_TEST_SUITE_END()                                                \
                                                                               \
    BOOST_AUTO_TEST_SUITE(type_unsigned_long_long)                             \
        TEST_CASE(allocator<unsigned long long>, dataset)                      \
    BOOST_AUTO_TEST_SUITE_END()                                                \
                                                                               \
    BOOST_AUTO_TEST_SUITE(type_float)                                          \
        TEST_CASE(allocator<float>, dataset)                                   \
    BOOST_AUTO_TEST_SUITE_END()                                                \
                                                                               \
    BOOST_AUTO_TEST_SUITE(type_double)                                         \
        TEST_CASE(allocator<double>, dataset)                                  \
    BOOST_AUTO_TEST_SUITE_END()                                                \
                                                                               \
    BOOST_AUTO_TEST_SUITE(type_struct)                                         \
        TEST_CASE(allocator<x>, dataset)                                       \
    BOOST_AUTO_TEST_SUITE_END()                                                \
                                                                               \
    BOOST_AUTO_TEST_SUITE(type_class)                                          \
        TEST_CASE(allocator<y>, dataset)                                       \
    BOOST_AUTO_TEST_SUITE_END()

BOOST_AUTO_TEST_SUITE(managed)
    TEST(cuda::memory::managed::allocator)
BOOST_AUTO_TEST_SUITE_END()

BOOST_AUTO_TEST_SUITE(device)
    TEST(cuda::memory::device::allocator)
BOOST_AUTO_TEST_SUITE_END()

BOOST_AUTO_TEST_SUITE(host)
    TEST(cuda::memory::host::allocator)
BOOST_AUTO_TEST_SUITE_END()

max_stars_repo_name: jspaaks/cuda-wrapper

max_issues_repo_name: jspaaks/cuda-wrapper

max_forks_repo_name: jspaaks/cuda-wrapper


text:
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/bind.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/foreach.hpp>
#include <boost/type_traits.hpp>

#define foreach BOOST_FOREACH

#include <vector>
#include <string>
#include <algorithm>
#include <iostream>

using namespace std;

struct Person
{
	string name;
    Person(const string& n) : name(n) {}
	virtual ~Person() {}
};

ostream& operator<< (ostream& o, const Person& person)
{ return o << person.name; }

struct Developer : public Person
{
    Developer(const string& n) : Person(n) {}
	virtual ~Developer() {}
};

bool did_find_john(const vector<boost::shared_ptr<Person> >& items,
		boost::function<string (const boost::shared_ptr<Person>&)> get_field)
{
	return find_if(items.begin(), items.end(),
			boost::bind(get_field, _1) != "John") != items.end();
}

template <typename Item, typename Result>
Result map_reduce(const vector<boost::shared_ptr<Item> >& items,
		boost::function<Result (const boost::shared_ptr<Item>&)> function)
{
	Result result;
	foreach (boost::shared_ptr<Item> item, items) {
		result += function(item);
	}
	return result;
}

template <typename T>
typename boost::enable_if<boost::is_pod<T>, void>::type
print(const T value)
{ cout << value << " is a POD type" << endl; }

template <typename T>
typename boost::disable_if<boost::is_pod<T>, void>::type
print(const T& value)
{ cout << value << " is not a POD type" << endl; }

int main()
{
	vector<boost::shared_ptr<Person> > persons;
	persons.push_back(boost::make_shared<Developer>("John"));
	persons.push_back(boost::make_shared<Person>("Joe"));

	cout << "Did find John? "
		<< (did_find_john(persons, &Person::name) ? "yes" : "no")
		<< endl;

	cout << "Concatenated usernames: "
		<< map_reduce<Person, string>(persons, &Person::name)
		<< endl;

	print(1);
	print(*persons[0]);

	return 0;
}

max_stars_repo_name: mrts/boost-bootstrap

max_issues_repo_name: mrts/boost-bootstrap

max_forks_repo_name: mrts/boost-bootstrap


text:
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// (C) Copyright 2007 Anthony Williams
// (C) Copyright 2011-2012 Vicente J. Botet Escriba

#ifndef BOOST_THREAD_LOCK_ALGORITHMS_HPP
#define BOOST_THREAD_LOCK_ALGORITHMS_HPP

#include <boost/thread/detail/config.hpp>
#include <boost/thread/lock_types.hpp>
#include <boost/thread/lockable_traits.hpp>

#include <algorithm>
#include <iterator>

#include <boost/config/abi_prefix.hpp>

namespace lslboost
{
  namespace detail
  {
    template <typename MutexType1, typename MutexType2>
    unsigned try_lock_internal(MutexType1& m1, MutexType2& m2)
    {
      lslboost::unique_lock<MutexType1> l1(m1, lslboost::try_to_lock);
      if (!l1)
      {
        return 1;
      }
      if (!m2.try_lock())
      {
        return 2;
      }
      l1.release();
      return 0;
    }

    template <typename MutexType1, typename MutexType2, typename MutexType3>
    unsigned try_lock_internal(MutexType1& m1, MutexType2& m2, MutexType3& m3)
    {
      lslboost::unique_lock<MutexType1> l1(m1, lslboost::try_to_lock);
      if (!l1)
      {
        return 1;
      }
      if (unsigned const failed_lock=try_lock_internal(m2,m3))
      {
        return failed_lock + 1;
      }
      l1.release();
      return 0;
    }

    template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4>
    unsigned try_lock_internal(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4)
    {
      lslboost::unique_lock<MutexType1> l1(m1, lslboost::try_to_lock);
      if (!l1)
      {
        return 1;
      }
      if (unsigned const failed_lock=try_lock_internal(m2,m3,m4))
      {
        return failed_lock + 1;
      }
      l1.release();
      return 0;
    }

    template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4, typename MutexType5>
    unsigned try_lock_internal(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4, MutexType5& m5)
    {
      lslboost::unique_lock<MutexType1> l1(m1, lslboost::try_to_lock);
      if (!l1)
      {
        return 1;
      }
      if (unsigned const failed_lock=try_lock_internal(m2,m3,m4,m5))
      {
        return failed_lock + 1;
      }
      l1.release();
      return 0;
    }

    template <typename MutexType1, typename MutexType2>
    unsigned lock_helper(MutexType1& m1, MutexType2& m2)
    {
      lslboost::unique_lock<MutexType1> l1(m1);
      if (!m2.try_lock())
      {
        return 1;
      }
      l1.release();
      return 0;
    }

    template <typename MutexType1, typename MutexType2, typename MutexType3>
    unsigned lock_helper(MutexType1& m1, MutexType2& m2, MutexType3& m3)
    {
      lslboost::unique_lock<MutexType1> l1(m1);
      if (unsigned const failed_lock=try_lock_internal(m2,m3))
      {
        return failed_lock;
      }
      l1.release();
      return 0;
    }

    template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4>
    unsigned lock_helper(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4)
    {
      lslboost::unique_lock<MutexType1> l1(m1);
      if (unsigned const failed_lock=try_lock_internal(m2,m3,m4))
      {
        return failed_lock;
      }
      l1.release();
      return 0;
    }

    template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4, typename MutexType5>
    unsigned lock_helper(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4, MutexType5& m5)
    {
      lslboost::unique_lock<MutexType1> l1(m1);
      if (unsigned const failed_lock=try_lock_internal(m2,m3,m4,m5))
      {
        return failed_lock;
      }
      l1.release();
      return 0;
    }
  }

  namespace detail
  {
    template <bool x>
    struct is_mutex_type_wrapper
    {
    };

    template <typename MutexType1, typename MutexType2>
    void lock_impl(MutexType1& m1, MutexType2& m2, is_mutex_type_wrapper<true> )
    {
      unsigned const lock_count = 2;
      unsigned lock_first = 0;
      for (;;)
      {
        switch (lock_first)
        {
        case 0:
          lock_first = detail::lock_helper(m1, m2);
          if (!lock_first) return;
          break;
        case 1:
          lock_first = detail::lock_helper(m2, m1);
          if (!lock_first) return;
          lock_first = (lock_first + 1) % lock_count;
          break;
        }
      }
    }

    template <typename Iterator>
    void lock_impl(Iterator begin, Iterator end, is_mutex_type_wrapper<false> );
  }

  template <typename MutexType1, typename MutexType2>
  void lock(MutexType1& m1, MutexType2& m2)
  {
    detail::lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
  }

  template <typename MutexType1, typename MutexType2>
  void lock(const MutexType1& m1, MutexType2& m2)
  {
    detail::lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
  }

  template <typename MutexType1, typename MutexType2>
  void lock(MutexType1& m1, const MutexType2& m2)
  {
    detail::lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
  }

  template <typename MutexType1, typename MutexType2>
  void lock(const MutexType1& m1, const MutexType2& m2)
  {
    detail::lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
  }

  template <typename MutexType1, typename MutexType2, typename MutexType3>
  void lock(MutexType1& m1, MutexType2& m2, MutexType3& m3)
  {
    unsigned const lock_count = 3;
    unsigned lock_first = 0;
    for (;;)
    {
      switch (lock_first)
      {
      case 0:
        lock_first = detail::lock_helper(m1, m2, m3);
        if (!lock_first) return;
        break;
      case 1:
        lock_first = detail::lock_helper(m2, m3, m1);
        if (!lock_first) return;
        lock_first = (lock_first + 1) % lock_count;
        break;
      case 2:
        lock_first = detail::lock_helper(m3, m1, m2);
        if (!lock_first) return;
        lock_first = (lock_first + 2) % lock_count;
        break;
      }
    }
  }

  template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4>
  void lock(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4)
  {
    unsigned const lock_count = 4;
    unsigned lock_first = 0;
    for (;;)
    {
      switch (lock_first)
      {
      case 0:
        lock_first = detail::lock_helper(m1, m2, m3, m4);
        if (!lock_first) return;
        break;
      case 1:
        lock_first = detail::lock_helper(m2, m3, m4, m1);
        if (!lock_first) return;
        lock_first = (lock_first + 1) % lock_count;
        break;
      case 2:
        lock_first = detail::lock_helper(m3, m4, m1, m2);
        if (!lock_first) return;
        lock_first = (lock_first + 2) % lock_count;
        break;
      case 3:
        lock_first = detail::lock_helper(m4, m1, m2, m3);
        if (!lock_first) return;
        lock_first = (lock_first + 3) % lock_count;
        break;
      }
    }
  }

  template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4, typename MutexType5>
  void lock(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4, MutexType5& m5)
  {
    unsigned const lock_count = 5;
    unsigned lock_first = 0;
    for (;;)
    {
      switch (lock_first)
      {
      case 0:
        lock_first = detail::lock_helper(m1, m2, m3, m4, m5);
        if (!lock_first) return;
        break;
      case 1:
        lock_first = detail::lock_helper(m2, m3, m4, m5, m1);
        if (!lock_first) return;
        lock_first = (lock_first + 1) % lock_count;
        break;
      case 2:
        lock_first = detail::lock_helper(m3, m4, m5, m1, m2);
        if (!lock_first) return;
        lock_first = (lock_first + 2) % lock_count;
        break;
      case 3:
        lock_first = detail::lock_helper(m4, m5, m1, m2, m3);
        if (!lock_first) return;
        lock_first = (lock_first + 3) % lock_count;
        break;
      case 4:
        lock_first = detail::lock_helper(m5, m1, m2, m3, m4);
        if (!lock_first) return;
        lock_first = (lock_first + 4) % lock_count;
        break;
      }
    }
  }

  namespace detail
  {
    template <typename Mutex, bool x = is_mutex_type<Mutex>::value>
    struct try_lock_impl_return
    {
      typedef int type;
    };

    template <typename Iterator>
    struct try_lock_impl_return<Iterator, false>
    {
      typedef Iterator type;
    };

    template <typename MutexType1, typename MutexType2>
    int try_lock_impl(MutexType1& m1, MutexType2& m2, is_mutex_type_wrapper<true> )
    {
      return ((int) detail::try_lock_internal(m1, m2)) - 1;
    }

    template <typename Iterator>
    Iterator try_lock_impl(Iterator begin, Iterator end, is_mutex_type_wrapper<false> );
  }

  template <typename MutexType1, typename MutexType2>
  typename detail::try_lock_impl_return<MutexType1>::type try_lock(MutexType1& m1, MutexType2& m2)
  {
    return detail::try_lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
  }

  template <typename MutexType1, typename MutexType2>
  typename detail::try_lock_impl_return<MutexType1>::type try_lock(const MutexType1& m1, MutexType2& m2)
  {
    return detail::try_lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
  }

  template <typename MutexType1, typename MutexType2>
  typename detail::try_lock_impl_return<MutexType1>::type try_lock(MutexType1& m1, const MutexType2& m2)
  {
    return detail::try_lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
  }

  template <typename MutexType1, typename MutexType2>
  typename detail::try_lock_impl_return<MutexType1>::type try_lock(const MutexType1& m1, const MutexType2& m2)
  {
    return detail::try_lock_impl(m1, m2, detail::is_mutex_type_wrapper<is_mutex_type<MutexType1>::value>());
  }

  template <typename MutexType1, typename MutexType2, typename MutexType3>
  int try_lock(MutexType1& m1, MutexType2& m2, MutexType3& m3)
  {
    return ((int) detail::try_lock_internal(m1, m2, m3)) - 1;
  }

  template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4>
  int try_lock(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4)
  {
    return ((int) detail::try_lock_internal(m1, m2, m3, m4)) - 1;
  }

  template <typename MutexType1, typename MutexType2, typename MutexType3, typename MutexType4, typename MutexType5>
  int try_lock(MutexType1& m1, MutexType2& m2, MutexType3& m3, MutexType4& m4, MutexType5& m5)
  {
    return ((int) detail::try_lock_internal(m1, m2, m3, m4, m5)) - 1;
  }

  namespace detail
  {
    template <typename Iterator>
    struct range_lock_guard
    {
      Iterator begin;
      Iterator end;

      range_lock_guard(Iterator begin_, Iterator end_) :
        begin(begin_), end(end_)
      {
        lslboost::lock(begin, end);
      }

      void release()
      {
        begin = end;
      }

      ~range_lock_guard()
      {
        for (; begin != end; ++begin)
        {
          begin->unlock();
        }
      }
    };

    template <typename Iterator>
    Iterator try_lock_impl(Iterator begin, Iterator end, is_mutex_type_wrapper<false> )

    {
      if (begin == end)
      {
        return end;
      }
      typedef typename std::iterator_traits<Iterator>::value_type lock_type;
      unique_lock<lock_type> guard(*begin, try_to_lock);

      if (!guard.owns_lock())
      {
        return begin;
      }
      Iterator const failed = lslboost::try_lock(++begin, end);
      if (failed == end)
      {
        guard.release();
      }

      return failed;
    }
  }

  namespace detail
  {
    template <typename Iterator>
    void lock_impl(Iterator begin, Iterator end, is_mutex_type_wrapper<false> )
    {
      typedef typename std::iterator_traits<Iterator>::value_type lock_type;

      if (begin == end)
      {
        return;
      }
      bool start_with_begin = true;
      Iterator second = begin;
      ++second;
      Iterator next = second;

      for (;;)
      {
        unique_lock<lock_type> begin_lock(*begin, defer_lock);
        if (start_with_begin)
        {
          begin_lock.lock();
          Iterator const failed_lock = lslboost::try_lock(next, end);
          if (failed_lock == end)
          {
            begin_lock.release();
            return;
          }
          start_with_begin = false;
          next = failed_lock;
        }
        else
        {
          detail::range_lock_guard<Iterator> guard(next, end);
          if (begin_lock.try_lock())
          {
            Iterator const failed_lock = lslboost::try_lock(second, next);
            if (failed_lock == next)
            {
              begin_lock.release();
              guard.release();
              return;
            }
            start_with_begin = false;
            next = failed_lock;
          }
          else
          {
            start_with_begin = true;
            next = second;
          }
        }
      }
    }

  }

}
#include <boost/config/abi_suffix.hpp>

#endif

max_stars_repo_name: samuelpowell/liblsl

max_issues_repo_name: samuelpowell/liblsl

max_forks_repo_name: samuelpowell/liblsl


text:
/**
 * Copyright 2016 (c) 10gen Inc.
 *
 * This program is free software: you can redistribute it and/or  modify
 * it under the terms of the GNU Affero General Public License, version 3,
 * as published by the Free Software Foundation.
 *
 * 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
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * 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 GNU Affero General 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.
 */

#include "mongo/platform/basic.h"

#include "mongo/db/pipeline/document_source_single_document_transformation.h"

#include <boost/smart_ptr/intrusive_ptr.hpp>

#include "mongo/db/pipeline/document.h"
#include "mongo/db/pipeline/document_source_limit.h"
#include "mongo/db/pipeline/document_source_skip.h"
#include "mongo/db/pipeline/expression.h"
#include "mongo/db/pipeline/value.h"

namespace mongo {

using boost::intrusive_ptr;

DocumentSourceSingleDocumentTransformation::DocumentSourceSingleDocumentTransformation(
    const intrusive_ptr<ExpressionContext>& pExpCtx,
    std::unique_ptr<TransformerInterface> parsedTransform,
    std::string name,
    bool isIndependentOfAnyCollection)
    : DocumentSource(pExpCtx),
      _parsedTransform(std::move(parsedTransform)),
      _name(std::move(name)),
      _isIndependentOfAnyCollection(isIndependentOfAnyCollection) {}

const char* DocumentSourceSingleDocumentTransformation::getSourceName() const {
    return _name.c_str();
}

DocumentSource::GetNextResult DocumentSourceSingleDocumentTransformation::getNext() {
    pExpCtx->checkForInterrupt();

    // Get the next input document.
    auto input = pSource->getNext();
    if (!input.isAdvanced()) {
        return input;
    }

    // Apply and return the document with added fields.
    return _parsedTransform->applyTransformation(input.releaseDocument());
}

intrusive_ptr<DocumentSource> DocumentSourceSingleDocumentTransformation::optimize() {
    _parsedTransform->optimize();
    return this;
}

void DocumentSourceSingleDocumentTransformation::doDispose() {
    if (_parsedTransform) {
        // Cache the stage options document in case this stage is serialized after disposing.
        _cachedStageOptions = _parsedTransform->serializeTransformation(pExpCtx->explain);
        _parsedTransform.reset();
    }
}

Value DocumentSourceSingleDocumentTransformation::serialize(
    boost::optional<ExplainOptions::Verbosity> explain) const {
    return Value(Document{{getSourceName(),
                           _parsedTransform ? _parsedTransform->serializeTransformation(explain)
                                            : _cachedStageOptions}});
}

Pipeline::SourceContainer::iterator DocumentSourceSingleDocumentTransformation::doOptimizeAt(
    Pipeline::SourceContainer::iterator itr, Pipeline::SourceContainer* container) {
    invariant(*itr == this);
    auto nextSkip = dynamic_cast<DocumentSourceSkip*>((*std::next(itr)).get());

    if (nextSkip) {
        std::swap(*itr, *std::next(itr));
        return itr == container->begin() ? itr : std::prev(itr);
    }
    return std::next(itr);
}

DepsTracker::State DocumentSourceSingleDocumentTransformation::getDependencies(
    DepsTracker* deps) const {
    // Each parsed transformation is responsible for adding its own dependencies, and returning
    // the correct dependency return type for that transformation.
    return _parsedTransform->addDependencies(deps);
}

DocumentSource::GetModPathsReturn DocumentSourceSingleDocumentTransformation::getModifiedPaths()
    const {
    return _parsedTransform->getModifiedPaths();
}

}  // namespace mongo


text:
// Distributed under the MIT License.
// See LICENSE.txt for details.

// Defines the class BulgedCube.

#pragma once

#include <array>
#include <boost/optional.hpp>
#include <cstddef>
#include <limits>

#include "DataStructures/Tensor/TypeAliases.hpp"
#include "Utilities/TypeTraits/RemoveReferenceWrapper.hpp"

/// \cond
namespace PUP {
class er;
}  // namespace PUP
/// \endcond

namespace domain {
namespace CoordinateMaps {

/*!
 *  \ingroup CoordinateMapsGroup
 *
 *  \brief Three dimensional map from the cube to a bulged cube.
 *  The cube is shaped such that the surface is compatible
 *  with the inner surface of Wedge3D.
 *  The shape of the object can be chosen to be cubical,
 *  if the sphericity is set to 0, or to a sphere, if
 *  the sphericity is set to 1. The sphericity can
 *  be set to any number between 0 and 1 for a bulged cube.
 *
 *  \details The volume map from the cube to a bulged cube is obtained by
 *  interpolating between six surface maps, twelve bounding curves, and
 *  eight corners. The surface map for the upper +z axis is obtained by
 *  interpolating between a cubical surface and a spherical surface. The
 *  two surfaces are chosen such that the latter circumscribes the former.
 *
 *  We make a choice here as to whether we wish to use the logical coordinates
 *  parameterizing these surface as they are, in which case we have the
 *  equidistant choice of coordinates, or whether to apply a tangent map to them
 *  which leads us to the equiangular choice of coordinates. In terms of the
 *  logical coordinates, the equiangular coordinates are:
 *
 *  \f[\textrm{equiangular xi} : \Xi(\xi) = \textrm{tan}(\xi\pi/4)\f]
 *
 *  \f[\textrm{equiangular eta}  : \mathrm{H}(\eta) = \textrm{tan}(\eta\pi/4)\f]
 *
 *  With derivatives:
 *
 *  \f[\Xi'(\xi) = \frac{\pi}{4}(1+\Xi^2)\f]
 *
 *  \f[\mathrm{H}'(\eta) = \frac{\pi}{4}(1+\mathrm{H}^2)\f]
 *
 *  The equidistant coordinates are:
 *
 *  \f[ \textrm{equidistant xi}  : \Xi = \xi\f]
 *
 *  \f[ \textrm{equidistant eta}  : \mathrm{H} = \eta\f]
 *
 *  with derivatives:
 *
 *  \f$\Xi'(\xi) = 1\f$, and \f$\mathrm{H}'(\eta) = 1\f$
 *
 *  We also define the variable \f$\rho\f$, given by:
 *
 *  \f[\rho = \sqrt{1+\Xi^2+\mathrm{H}^2}\f]
 *
 *  ### The Spherical Face Map
 *  The surface map for the spherical face of radius \f$R\f$ lying in the
 *  \f$+z\f$
 *  direction in either choice of coordinates is then given by:
 *
 *  \f[
 *  \vec{\sigma}_{spherical}(\xi,\eta) =
 *  \begin{bmatrix}
 *  x(\xi,\eta)\\
 *  y(\xi,\eta)\\
 *  z(\xi,\eta)\\
 *  \end{bmatrix}  = \frac{R}{\rho}
 *  \begin{bmatrix}
 *  \Xi\\
 *  \mathrm{H}\\
 *  1\\
 *  \end{bmatrix}
 *  \f]
 *
 *  ### The Cubical Face Map
 *  The surface map for the cubical face of side length \f$2L\f$ lying in the
 *  \f$+z\f$ direction is given by:
 *
 *  \f[
 *  \vec{\sigma}_{cubical}(\xi,\eta) =
 *  \begin{bmatrix}
 *  x(\xi,\eta)\\
 *  y(\xi,\eta)\\
 *  L\\
 *  \end{bmatrix}  = L
 *  \begin{bmatrix}
 *  \Xi\\
 *  \mathrm{H}\\
 *  1\\
 *  \end{bmatrix}
 *  \f]
 *
 *  ### The Bulged Face Map
 *  To construct the bulged map we interpolate between a cubical face map of
 *  side length \f$2L\f$ and a spherical face map of radius \f$R\f$, with the
 *  interpolation parameter being \f$s\f$, the `sphericity`.
 *  The surface map for the bulged face lying in the \f$+z\f$ direction is then
 *  given by:
 *
 *  \f[
 *  \vec{\sigma}_{+\zeta}(\xi,\eta) = \left\{(1-s)L + \frac{sR}{\rho}\right\}
 *  \begin{bmatrix}
 *  \Xi\\
 *  \mathrm{H}\\
 *  1\\
 *  \end{bmatrix}
 *  \f]
 *
 *  This equation defines the upper-z map \f$\vec{\sigma}_{+\zeta}\f$, and we
 *  similarly define the other five surface maps \f$\vec{\sigma}_{+\eta}\f$,
 *  \f$\vec{\sigma}_{+\xi}\f$, and so on by appropriate rotations.
 *  We constrain L by demanding that the spherical face circumscribe the cube.
 *  With this condition, we have \f$L = R/\sqrt3\f$.
 *
 *  ### The General Formula for 3D Isoparametric Maps
 *  The general formula is given by Eq. 1 in section 2.1 of Hesthaven's paper
 *  "A Stable Penalty Method For The Compressible Navier-Stokes Equations III.
 *  Multidimensional Domain Decomposition Schemes" available
 *   here .
 *
 *  Hesthaven's formula is general in the degree of the shape functions used,
 *  so for our purposes we take the special case where the shape functions are
 *  linear in the interpolation variable, and define new variables accordingly.
 *  However, our interpolation variables do not necessarily have to be the
 *  logical coordinates themselves, though they often are. To make this
 *  distinction clear, we will define the new interpolation variables
 *  \f$\{\tilde{\xi},\tilde{\eta},\tilde{\zeta}\}\f$, which may either be the
 *  logical coordinates themselves or a invertible transformation of them. For
 *  the purposes of the bulged cube map, this transformation will be the same
 *  transformation that takes the logical coordinates into the equiangular
 *  coordinates. We will later see how this choice can lead to simplifications
 *  in the final map.
 *
 *  We define the following variables for
 *  \f$\alpha, \beta, \gamma \in\{\tilde{\xi},\tilde{\eta},\tilde{\zeta}\}\f$:
 *
 *  \f[
 *  f^{\pm}_{\alpha} = \frac{1}{2}(1\pm\alpha)\\
 *  f^{\pm\pm}_{\alpha \ \beta} = \frac{1}{4}(1\pm\alpha)(1\pm\beta)\\
 *  f^{\pm\pm\pm}_{\alpha \ \beta \ \gamma} =
 *  \frac{1}{8}(1\pm\alpha)(1\pm\beta)(1\pm\gamma)
 *  \f]
 *
 *  The formula involves six surfaces, which we will denote by
 *  \f$\vec{\sigma}\f$, twelve curves, denoted by \f$\vec{\Gamma}\f$, and eight
 *  vertices, denoted by \f$\vec{\pi}\f$, with the subscripts denoting which
 *  face(s) these objects belong to. The full volume map is given by:
 *
 *  \f{align*}
 *  \vec{x}(\xi,\eta,\zeta) = &
 *  f^{+}_{\tilde{\zeta}}\vec{\sigma}_{+\zeta}(\xi, \eta)+
 *  f^{-}_{\tilde{\zeta}}\vec{\sigma}_{-\zeta}(\xi, \eta)\\
 *  &+ f^{+}_{\tilde{\eta}}\vec{\sigma}_{+\eta}(\xi, \zeta)+
 *  f^{-}_{\tilde{\eta}}\vec{\sigma}_{-\eta}(\xi, \zeta)+
 *  f^{+}_{\tilde{\xi}}\vec{\sigma}_{+\xi}(\eta, \zeta)+
 *  f^{-}_{\tilde{\xi}}\vec{\sigma}_{-\xi}(\eta, \zeta)\\
 *  &- f^{++}_{\tilde{\xi} \ \tilde{\eta}}\vec{\Gamma}_{+\xi +\eta}(\zeta)-
 *  f^{-+}_{\tilde{\xi} \ \tilde{\eta}}\vec{\Gamma}_{-\xi +\eta}(\zeta)-
 *  f^{+-}_{\tilde{\xi} \ \tilde{\eta}}\vec{\Gamma}_{+\xi -\eta}(\zeta)-
 *  f^{--}_{\tilde{\xi} \ \tilde{\eta}}\vec{\Gamma}_{-\xi -\eta}(\zeta)\\
 *  &- f^{++}_{\tilde{\xi} \ \tilde{\zeta}}\vec{\Gamma}_{+\xi +\zeta}(\eta)-
 *  f^{-+}_{\tilde{\xi} \ \tilde{\zeta}}\vec{\Gamma}_{-\xi +\zeta}(\eta)-
 *  f^{+-}_{\tilde{\xi} \ \tilde{\zeta}}\vec{\Gamma}_{+\xi -\zeta}(\eta)-
 *  f^{--}_{\tilde{\xi} \ \tilde{\zeta}}\vec{\Gamma}_{-\xi -\zeta}(\eta)\\
 *  &- f^{++}_{\tilde{\eta} \ \tilde{\zeta}}\vec{\Gamma}_{+\eta +\zeta}(\xi)-
 *  f^{-+}_{\tilde{\eta} \ \tilde{\zeta}}\vec{\Gamma}_{-\eta +\zeta}(\xi)-
 *  f^{+-}_{\tilde{\eta} \ \tilde{\zeta}}\vec{\Gamma}_{+\eta -\zeta}(\xi)-
 *  f^{--}_{\tilde{\eta} \tilde{\zeta}}\vec{\Gamma}_{-\eta -\zeta}(\xi)\\
 *  &+ f^{+++}_{\tilde{\xi} \ \tilde{\eta} \ \tilde{\zeta}}\vec{\pi}_{+\xi +\eta
 * +\zeta}+ f^{-++}_{\tilde{\xi} \ \tilde{\eta} \ \tilde{\zeta}}\vec{\pi}_{-\xi
 * +\eta +\zeta}+ f^{+-+}_{\tilde{\xi} \ \tilde{\eta} \
 * \tilde{\zeta}}\vec{\pi}_{+\xi -\eta +\zeta}+
 *  f^{--+}_{\tilde{\xi} \ \tilde{\eta} \ \tilde{\zeta}}\vec{\pi}_{-\xi -\eta
 * +\zeta}\\
 *  &+ f^{++-}_{\tilde{\xi} \ \tilde{\eta} \ \tilde{\zeta}}\vec{\pi}_{+\xi +\eta
 * -\zeta}+ f^{-+-}_{\tilde{\xi} \ \tilde{\eta} \ \tilde{\zeta}}\vec{\pi}_{-\xi
 * +\eta -\zeta}+ f^{+--}_{\tilde{\xi} \ \tilde{\eta} \
 * \tilde{\zeta}}\vec{\pi}_{+\xi -\eta -\zeta}+ f^{---}_{\tilde{\xi} \
 * \tilde{\eta} \ \tilde{\zeta}}\vec{\pi}_{-\xi -\eta -\zeta} \f}
 *
 *
 *  ### The Special Case for Octahedral Symmetry
 *  The general formula is for the case in which there are six independently
 *  specified bounding surfaces. In our case, the surfaces are obtained by
 *  rotations and reflections of the upper-\f$\zeta\f$ face.
 *
 * We define the matrices corresponding to these transformations to be:
 *
 * \f[
 * S_{xy} =
 *  \begin{bmatrix}
 *  0 & 1 & 0\\
 *  1 & 0 & 0\\
 *  0 & 0 & 1\\
 *  \end{bmatrix},\
 *
 * S_{xz} =
 *  \begin{bmatrix}
 *  0 & 0 & 1\\
 *  0 & 1 & 0\\
 *  1 & 0 & 0\\
 *  \end{bmatrix},\
 *
 * S_{yz} =
 *  \begin{bmatrix}
 *  1 & 0 & 0\\
 *  0 & 0 & 1\\
 *  0 & 1 & 0\\
 *  \end{bmatrix}\f]
 *
 * \f[C_{zxy} =
 *  \begin{bmatrix}
 *  0 & 0 & 1\\
 *  1 & 0 & 0\\
 *  0 & 1 & 0\\
 *  \end{bmatrix},\
 *
 * C_{yzx} =
 *  \begin{bmatrix}
 *  0 & 1 & 0\\
 *  0 & 0 & 1\\
 *  1 & 0 & 0\\
 *  \end{bmatrix}\f]
 *
 * \f[N_{x} =
 *  \begin{bmatrix}
 *  -1 & 0 & 0\\
 *  0 & 1 & 0\\
 *  0 & 0 & 1\\
 *  \end{bmatrix},\
 *
 * N_{y} =
 *  \begin{bmatrix}
 *  1 & 0 & 0\\
 *  0 & -1 & 0\\
 *  0 & 0 & 1\\
 *  \end{bmatrix},\
 *
 * N_{z} =
 *  \begin{bmatrix}
 *  1 & 0 & 0\\
 *  0 & 1 & 0\\
 *  0 & 0 & -1\\
 *  \end{bmatrix}
 *  \f]
 *
 * The surface maps can now all be written in terms of
 * \f$\vec{\sigma}_{+\zeta}\f$ and these matrices:
 *
 * \f$\vec{\sigma}_{-\zeta}(\xi, \eta) = N_z\vec{\sigma}_{+\zeta}(\xi, \eta)\\
 * \vec{\sigma}_{+\eta}(\xi, \zeta) = S_{yz}\vec{\sigma}_{+\zeta}(\xi, \zeta)\\
 * \vec{\sigma}_{-\eta}(\xi, \zeta) = N_yS_{yz}\vec{\sigma}_{+\zeta}(\xi,
 * \zeta)\\
 * \vec{\sigma}_{+\xi}(\eta, \zeta) = C_{zxy}\vec{\sigma}_{+\zeta}(\eta,
 * \zeta)\\
 * \vec{\sigma}_{-\xi}(\eta, \zeta) = N_xC_{zyx}\vec{\sigma}_{+\zeta}(\eta,
 * \zeta)\f$
 *
 *
 * The four bounding curves \f$\vec{\Gamma}\f$ on the \f$+\zeta\f$ face are
 * given by:
 *
 *
 * \f$\vec{\Gamma}_{+\xi,+\zeta}(\eta) = \vec{\sigma}_{+\zeta}(+1,\eta)\\
 * \vec{\Gamma}_{-\xi,+\zeta}(\eta) = \vec{\sigma}_{+\zeta}(-1,\eta)
 * = N_x\vec{\sigma}_{+\zeta}(+1, \eta)\\
 * \vec{\Gamma}_{+\eta,+\zeta}(\xi) = \vec{\sigma}_{+\zeta}(\xi,+1)
 * = S_{xy}\vec{\sigma}_{+\zeta}(+1, \xi)\\
 * \vec{\Gamma}_{-\eta,+\zeta}(\xi) = \vec{\sigma}_{+\zeta}(\xi,-1)
 * = N_yS_{xy}\vec{\sigma}_{+\zeta}(+1,\xi)\f$
 *
 *
 * The bounding curves on the other surfaces can be obtained by transformations
 * on the \f$+\zeta\f$ face:
 *
 *
 * \f$\vec{\Gamma}_{+\xi,-\zeta}(\eta) = N_z\vec{\sigma}_{+\zeta}(+1,\eta)\\
 * \vec{\Gamma}_{-\xi,-\zeta}(\eta) = N_z\vec{\sigma}_{+\zeta}(-1,\eta)
 * = N_zN_x\vec{\sigma}_{+\zeta}(+1,\eta)\\
 * \vec{\Gamma}_{+\eta,-\zeta}(\xi) = N_z\vec{\sigma}_{+\zeta}(\xi,+1)
 * = N_zS_{xy}\vec{\sigma}_{+\zeta}(+1, \xi)\\
 * \vec{\Gamma}_{-\eta,-\zeta}(\xi) = N_z\vec{\sigma}_{+\zeta}(\xi,-1)
 * = N_zN_yS_{xy}\vec{\sigma}_{+\zeta}(+1, \xi)\\
 * \vec{\Gamma}_{+\xi,+\eta}(\zeta) =
 * C_{zxy}\vec{\sigma}_{+\zeta}(+1,\zeta)\\
 * \vec{\Gamma}_{-\xi,+\eta}(\zeta) =
 * N_xC_{zxy}\vec{\sigma}_{+\zeta}(+1,\zeta)\\
 * \vec{\Gamma}_{+\xi,-\eta}(\zeta) = C_{zxy}\vec{\sigma}_{+\zeta}(-1,\zeta)
 * = C_{zxy}N_x\vec{\sigma}_{+\zeta}(+1,\zeta)\\
 * \vec{\Gamma}_{-\xi,-\eta}(\zeta) = N_xC_{zxy}\vec{\sigma}_{+\zeta}(-1,\zeta)
 * = N_xC_{zxy}N_x\vec{\sigma}_{+\zeta}(+1,\zeta)\f$
 *
 *
 * Now we can write the volume map in terms of
 * \f$\vec{\sigma}_{+\zeta}\f$ only:
 * \f{align*}\vec{x}(\xi,\eta,\zeta) = &
 * (f^{+}_{\tilde{\zeta}} + f^{-}_{\tilde{\zeta}}N_z)
 * \vec{\sigma}_{+\zeta}(\xi, \eta)\\
 * &+ (f^{+}_{\tilde{\eta}} + f^{-}_{\tilde{\eta}}N_y)
 * S_{yz}\vec{\sigma}_{+\zeta}(\xi, \zeta)\\
 * &+ (f^{+}_{\tilde{\xi}} + f^{-}_{\tilde{\xi}}N_x)
 * C_{zxy}\vec{\sigma}_{+\zeta}(\eta, \zeta)\\
 * &- (f^{+}_{\tilde{\xi}}+f^{-}_{\tilde{\xi}}N_x)
 * (f^{+}_{\tilde{\eta}}+f^{-}_{\tilde{\eta}}N_y)
 * C_{zxy}\vec{\sigma}_{+\zeta}(+1, \zeta)\\
 * &- (f^{+}_{\tilde{\zeta}}+f^{-}_{\tilde{\zeta}}N_z)\left\{
 * (f^{+}_{\tilde{\xi}}+f^{-}_{\tilde{\xi}}N_x)\vec{\sigma}_{+\zeta}(+1, \eta)+
 * (f^{+}_{\tilde{\eta}}+f^{-}_{\tilde{\eta}}N_y)S_{xy}\vec{\sigma}_{+\zeta}(+1,
 * \xi)\right\}\\
 * &+ \frac{r}{\sqrt{3}}\vec{\tilde{\xi}}
 *  \f}
 *
 * Note that we can now absorb all of the \f$f\f$s into the matrix prefactors
 * in the above equation and obtain a final set of matrices. We define the
 * following *blending matrices*:
 *
 *  \f[
 *  B_{\tilde{\xi}} =
 *  \begin{bmatrix}
 *  0 & 0 & \tilde{\xi}\\
 *  1 & 0 & 0\\
 *  0 & 1 & 0\\
 *  \end{bmatrix},\
 *
 *  B_{\tilde{\eta}} =
 *  \begin{bmatrix}
 *  1 & 0 & 0\\
 *  0 & 0 & \tilde{\eta}\\
 *  0 & 1 & 0\\
 *  \end{bmatrix},\
 *
 *  B_{\tilde{\zeta}} =
 *  \begin{bmatrix}
 *  1 & 0 & 0\\
 *  0 & 1 & 0\\
 *  0 & 0 & \tilde{\zeta}\\
 *  \end{bmatrix}\\
 *
 *  B_{\tilde{\xi}\tilde{\eta}} =
 *  \begin{bmatrix}
 *  0 & 0 & \tilde{\xi}\\
 *  \tilde{\eta} & 0 & 0\\
 *  0 & 1 & 0\\
 *  \end{bmatrix},\
 *
 *  B_{\tilde{\xi}\tilde{\zeta}} =
 *  \begin{bmatrix}
 *  \tilde{\xi} & 0 & 0\\
 *  0 & 1 & 0\\
 *  0 & 0 & \tilde{\zeta}\\
 *  \end{bmatrix},\
 *
 *  B_{\tilde{\eta}\tilde{\zeta}} =
 *  \begin{bmatrix}
 *  0 & 1 & 0\\
 *  \tilde{\eta} & 0 & 0\\
 *  0 & 0 & \tilde{\zeta}\\
 *  \end{bmatrix}\\
 *
 *  B_{\tilde{\xi}\tilde{\eta}\tilde{\zeta}} =
 *  \begin{bmatrix}
 *  \tilde{\xi} & 0 & 0\\
 *  0 & \tilde{\eta} & 0\\
 *  0 & 0 & \tilde{\zeta}\\
 *  \end{bmatrix}
 *  \f]
 *
 *  Now we can write the volume map in these terms:
 *
 * \f{align*}
 * \vec{x}(\xi,\eta,\zeta) = &
 * B_{\tilde{\zeta}}
 * \vec{\sigma}_{+\zeta}(\xi, \eta)\\& +
 * B_{\tilde{\eta}}
 * \vec{\sigma}_{+\zeta}(\xi, \zeta)+
 * B_{\tilde{\xi}}
 * \vec{\sigma}_{+\zeta}(\eta, \zeta)\\& -
 * B_{\tilde{\xi} \tilde{\eta}}
 * \vec{\sigma}_{+\zeta}(+1, \zeta)-
 * B_{\tilde{\xi} \tilde{\zeta}}
 * \vec{\sigma}_{+\zeta}(+1, \eta)+
 * B_{\tilde{\eta} \tilde{\zeta}}
 * \vec{\sigma}_{+\zeta}(+1, \xi)\\& +
 * B_{\tilde{\xi} \tilde{\eta} \tilde{\zeta}}
 * \vec{\sigma}_{+\zeta}(+1, +1)
 * \f}
 *
 * ### The Bulged Cube Map
 * We now use the result above to provide the mapping for the bulged cube.
 * First we will define the variables \f$\rho_A\f$ and \f$\rho_{AB}\f$, for
 * \f$A, B \in \{\Xi,\mathrm{H}, \mathrm{Z}\} \f$, where \f$\mathrm{Z}\f$
 * is \f$\tan(\zeta\pi/4)\f$ in the equiangular case and \f$\zeta\f$ in the
 * equidistant case:
 *
 * \f[
 * \rho_A = \sqrt{2 + A^2}\\
 * \rho_{AB} = \sqrt{1 + A^2 + B^2}
 * \f]
 * The final mapping is then:
 * \f[
 * \vec{x}(\xi,\eta,\zeta) = \frac{(1-s)R}{\sqrt{3}}
 * \begin{bmatrix}
 * \Xi\\
 * \mathrm{H}\\
 * \mathrm{Z}\\
 * \end{bmatrix} +
 * \frac{sR}{\sqrt{3}}
 * \begin{bmatrix}
 * \tilde{\xi}\\
 * \tilde{\eta}\\
 * \tilde{\zeta}\\
 * \end{bmatrix} + sR
 * \begin{bmatrix}
 * \tilde{\xi} & \Xi & \Xi\\
 * \mathrm{H} & \tilde{\eta} &\mathrm{H}\\
 * \mathrm{Z} & \mathrm{Z} & \tilde{\zeta}\\
 * \end{bmatrix}
 * \begin{bmatrix}
 * 1/\rho_{\mathrm{H}\mathrm{Z}}\\
 * 1/\rho_{\Xi\mathrm{Z}}\\
 * 1/\rho_{\Xi\mathrm{H}}\\
 * \end{bmatrix} - sR
 * \begin{bmatrix}
 * \Xi & \tilde{\xi} & \tilde{\xi}\\
 * \tilde{\eta} & \mathrm{H} &\tilde{\eta}\\
 * \tilde{\zeta} & \tilde{\zeta} & \mathrm{Z}\\
 * \end{bmatrix}
 * \begin{bmatrix}
 * 1/\rho_{\Xi}\\
 * 1/\rho_{\mathrm{H}}\\
 * 1/\rho_{\mathrm{Z}}\\
 * \end{bmatrix}
 * \f]
 *
 * Recall that the lower case Greek letters with tildes are the variables
 * used for the linear interpolation between the six bounding surfaces, and
 * that the upper case Greek letters are the coordinates along these surfaces -
 * both of which can be specified to be either
 * equidistant or equiangular. In the case where the
 * interpolation variable is chosen to match that of the
 * coordinates along the surface, we have \f$\tilde{\xi} = \Xi\f$, etc. In this
 * case, the formula reduces further. The reduced formula below is the one used
 * for this CoordinateMap. It is given by:
 *
 * \f[
 * \vec{x}(\xi,\eta,\zeta) =
 * \left\{
 * \frac{R}{\sqrt{3}}
 * + sR
 * \left(
 * 1/\rho_{\mathrm{H}\mathrm{Z}}+
 * 1/\rho_{\Xi\mathrm{Z}}+
 * 1/\rho_{\Xi\mathrm{H}}-
 * 1/\rho_{\Xi}-
 * 1/\rho_{\mathrm{H}}-
 * 1/\rho_{\mathrm{Z}}
 * \right)
 * \right\}
 * \begin{bmatrix}
 * \Xi\\
 * \mathrm{H}\\
 * \mathrm{Z}\\
 * \end{bmatrix}
 * \f]
 *
 * The inverse mapping is analytic in the angular directions. A root find
 * must be performed for the inverse mapping in the radial direction. This
 * one-dimensional formula is obtained by taking the magnitude of both sides
 * of the mapping, and changing variables from \f$\xi, \eta, \zeta\f$ to
 * \f$x, y, z\f$ and introducing \f$\rho^2 := \sqrt{\xi^2+\eta^2+\zeta^2}\f$.
 */
class BulgedCube {
 public:
  static constexpr size_t dim = 3;
  BulgedCube(double radius, double sphericity,
             bool use_equiangular_map) noexcept;
  BulgedCube() noexcept = default;
  ~BulgedCube() noexcept = default;
  BulgedCube(BulgedCube&&) noexcept = default;
  BulgedCube(const BulgedCube&) noexcept = default;
  BulgedCube& operator=(const BulgedCube&) noexcept = default;
  BulgedCube& operator=(BulgedCube&&) noexcept = default;

  template <typename T>
  std::array<tt::remove_cvref_wrap_t<T>, 3> operator()(
      const std::array<T, 3>& source_coords) const noexcept;

  boost::optional<std::array<double, 3>> inverse(
      const std::array<double, 3>& target_coords) const noexcept;

  template <typename T>
  tnsr::Ij<tt::remove_cvref_wrap_t<T>, 3, Frame::NoFrame> jacobian(
      const std::array<T, 3>& source_coords) const noexcept;

  template <typename T>
  tnsr::Ij<tt::remove_cvref_wrap_t<T>, 3, Frame::NoFrame> inv_jacobian(
      const std::array<T, 3>& source_coords) const noexcept;

  // clang-tidy: google runtime references
  void pup(PUP::er& p) noexcept;  // NOLINT

  bool is_identity() const noexcept { return is_identity_; }

 private:
  template <typename T>
  std::array<tt::remove_cvref_wrap_t<T>, 3> xi_derivative(
      const std::array<T, 3>& source_coords) const noexcept;
  friend bool operator==(const BulgedCube& lhs, const BulgedCube& rhs) noexcept;

  double radius_{std::numeric_limits<double>::signaling_NaN()};
  double sphericity_{std::numeric_limits<double>::signaling_NaN()};
  bool use_equiangular_map_ = false;
  bool is_identity_ = false;
};

bool operator!=(const BulgedCube& lhs, const BulgedCube& rhs) noexcept;
}  // namespace CoordinateMaps
}  // namespace domain

max_stars_repo_name: keefemitman/spectre

max_issues_repo_name: keefemitman/spectre

max_forks_repo_name: keefemitman/spectre


text:
/* ----------------------------------------------------------------------------

 * GTSAM Copyright 2010, Georgia Tech Research Corporation,
 * Atlanta, Georgia 30332-0415
 * All Rights Reserved
 * Authors: Frank Dellaert, et al. (see THANKS for the full author list)

 * See LICENSE for the license information

 * -------------------------------------------------------------------------- */

/**
 * @file    testBarometricFactor.cpp
 * @brief   Unit test for BarometricFactor
 * @author  Peter Milani
 * @date   16 Dec, 2021
 */

#include <CppUnitLite/TestHarness.h>
#include <gtsam/base/Testable.h>
#include <gtsam/base/numericalDerivative.h>
#include <gtsam/navigation/BarometricFactor.h>

#include <boost/bind/bind.hpp>

using namespace std::placeholders;
using namespace std;
using namespace gtsam;

// *************************************************************************
namespace example {}

double metersToBaro(const double& meters) {
    double temp = 15.04 - 0.00649 * meters;
    return 101.29 * std::pow(((temp + 273.1) / 288.08), 5.256);
}

// *************************************************************************
TEST(BarometricFactor, Constructor) {
    using namespace example;

    // meters to barometric.

    double baroMeasurement = metersToBaro(10.);

    // Factor
    Key key(1);
    Key key2(2);
    SharedNoiseModel model = noiseModel::Isotropic::Sigma(1, 0.25);
    BarometricFactor factor(key, key2, baroMeasurement, model);

    // Create a linearization point at zero error
    Pose3 T(Rot3::RzRyRx(0., 0., 0.), Point3(0., 0., 10.));
    double baroBias = 0.;
    Vector1 zero;
    zero << 0.;
    EXPECT(assert_equal(zero, factor.evaluateError(T, baroBias), 1e-5));

    // Calculate numerical derivatives
    Matrix expectedH = numericalDerivative21<Vector, Pose3, double>(
        std::bind(&BarometricFactor::evaluateError, &factor,
                  std::placeholders::_1, std::placeholders::_2, boost::none,
                  boost::none),
        T, baroBias);

    Matrix expectedH2 = numericalDerivative22<Vector, Pose3, double>(
        std::bind(&BarometricFactor::evaluateError, &factor,
                  std::placeholders::_1, std::placeholders::_2, boost::none,
                  boost::none),
        T, baroBias);

    // Use the factor to calculate the derivative
    Matrix actualH, actualH2;
    factor.evaluateError(T, baroBias, actualH, actualH2);

    // Verify we get the expected error
    EXPECT(assert_equal(expectedH, actualH, 1e-8));
    EXPECT(assert_equal(expectedH2, actualH2, 1e-8));
}

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

//***************************************************************************
TEST(BarometricFactor, nonZero) {
    using namespace example;

    // meters to barometric.

    double baroMeasurement = metersToBaro(10.);

    // Factor
    Key key(1);
    Key key2(2);
    SharedNoiseModel model = noiseModel::Isotropic::Sigma(1, 0.25);
    BarometricFactor factor(key, key2, baroMeasurement, model);

    Pose3 T(Rot3::RzRyRx(0.5, 1., 1.), Point3(20., 30., 1.));
    double baroBias = 5.;

    // Calculate numerical derivatives
    Matrix expectedH = numericalDerivative21<Vector, Pose3, double>(
        std::bind(&BarometricFactor::evaluateError, &factor,
                  std::placeholders::_1, std::placeholders::_2, boost::none,
                  boost::none),
        T, baroBias);

    Matrix expectedH2 = numericalDerivative22<Vector, Pose3, double>(
        std::bind(&BarometricFactor::evaluateError, &factor,
                  std::placeholders::_1, std::placeholders::_2, boost::none,
                  boost::none),
        T, baroBias);

    // Use the factor to calculate the derivative and the error
    Matrix actualH, actualH2;
    Vector error = factor.evaluateError(T, baroBias, actualH, actualH2);
    Vector actual = (Vector(1) << -4.0).finished();

    // Verify we get the expected error
    EXPECT(assert_equal(expectedH, actualH, 1e-8));
    EXPECT(assert_equal(expectedH2, actualH2, 1e-8));
    EXPECT(assert_equal(error, actual, 1e-8));
}

// *************************************************************************
int main() {
    TestResult tr;
    return TestRegistry::runAllTests(tr);
}
// *************************************************************************

max_stars_repo_name: h-rover/gtsam

max_issues_repo_name: h-rover/gtsam

max_forks_repo_name: h-rover/gtsam


text:
#ifndef LIBGCT_INCLUDE_PHYSICAL_DEVICE_HPP
#define LIBGCT_INCLUDE_PHYSICAL_DEVICE_HPP

#include <memory>
#include <vector>
#include <boost/container/static_vector.hpp>
#include <nlohmann/json.hpp>
#include <vulkan/vulkan.hpp>
#include <gct/physical_device_properties.hpp>
#include <gct/physical_device_features.hpp>
#include <gct/queue_requirement.hpp>
#include <gct/created_from.hpp>

namespace gct {
  class instance_t;

  class physical_device_t : public created_from< instance_t > {
  public:
    physical_device_t(
      const std::shared_ptr< instance_t > &instance_,
      vk::PhysicalDevice handle_,
      const std::vector< const char* > &device_layers
    );
    physical_device_t(
      const std::shared_ptr< instance_t > &instance_,
      vk::PhysicalDevice handle_,
      const std::vector< const char* > &device_layers,
      const std::vector< const char* > &device_ext
    );
    vk::PhysicalDevice &operator*() { return handle; }
    const vk::PhysicalDevice &operator*() const { return handle; }
    vk::PhysicalDevice *operator->() { return &handle; }
    const vk::PhysicalDevice *operator->() const { return &handle; }
    const physical_device_properties_t &get_props() const { return props; }
    const physical_device_features_t &get_features() const { return features; }
    physical_device_features_t &get_features() { return features; }
    physical_device_t with_extensions(
      const std::vector< const char* > &exts
    );
  private:
    vk::PhysicalDevice handle;
    physical_device_properties_t props;
    physical_device_features_t features;
  };
  using physical_devices_t =
    boost::container::static_vector<
      std::shared_ptr< physical_device_t >,
      VK_MAX_DEVICE_GROUP_SIZE
    >;
  class device_t;
  class device_create_info_t;
  struct device_group_t {
  public:
    device_group_t with_extensions(
      const std::vector< const char* > &exts
    );
    std::shared_ptr< device_t > create_device(
      const std::vector< queue_requirement_t > &queue_requirements,
      const device_create_info_t &create_info
    );
    physical_devices_t devices;
    bool subset_allocation;
  };
  using device_groups_t =
    std::vector< device_group_t >;

  void to_json( nlohmann::json&, const physical_device_t &v );
  void to_json( nlohmann::json&, const physical_devices_t &v );
  void to_json( nlohmann::json&, const device_group_t &v );
}

#endif

max_stars_repo_name: Fadis/gct

max_issues_repo_name: Fadis/gct

max_forks_repo_name: Fadis/gct