<commit_before>#include <stdlib.h>

#include <fstream>

#include "env.h"

#include "gtest/gtest.h"
#include "ir/ir.h"
#include "helpers.h"
#include "lib/log.h"

#include "frontends/common/parseInput.h"

#include "backends/p4test/version.h"

#include "p4/createBuiltins.h"
#include "p4/typeChecking/typeChecker.h"

#include "frontends/common/constantFolding.h"
#include "frontends/common/resolveReferences/resolveReferences.h"
#include "frontends/p4/evaluator/evaluator.h"
#include "frontends/p4/fromv1.0/v1model.h"
#include "frontends/p4/moveDeclarations.h"
#include "frontends/p4/simplify.h"
#include "frontends/p4/typeChecking/typeChecker.h"
#include "frontends/p4/simplifyParsers.h"
#include "frontends/p4/strengthReduction.h"
#include "frontends/p4/toP4/toP4.h"
#include "frontends/p4/typeMap.h"
#include "frontends/p4/uniqueNames.h"
#include "frontends/p4/unusedDeclarations.h"
#include "midend/actionSynthesis.h"
#include "midend/compileTimeOps.h"
#include "midend/complexComparison.h"
#include "midend/copyStructures.h"
#include "midend/eliminateTuples.h"
#include "midend/eliminateNewtype.h"
#include "midend/eliminateSerEnums.h"
#include "midend/eliminateSwitch.h"
#include "midend/flattenHeaders.h"
#include "midend/flattenInterfaceStructs.h"
#include "midend/replaceSelectRange.h"
#include "midend/expandEmit.h"
#include "midend/expandLookahead.h"
#include "midend/local_copyprop.h"
#include "midend/midEndLast.h"
#include "midend/nestedStructs.h"
#include "midend/noMatch.h"
#include "midend/predication.h"
#include "midend/removeExits.h"
#include "midend/removeMiss.h"
#include "midend/removeParameters.h"
#include "midend/removeSelectBooleans.h"
#include "midend/simplifyKey.h"
#include "midend/simplifySelectCases.h"
#include "midend/simplifySelectList.h"
#include "midend/tableHit.h"
#include "midend/removeAssertAssume.h"
#include "midend/parserUnroll.h"

using namespace P4;

namespace Test {

class P4TestOptions : public CompilerOptions {
 public:
    P4TestOptions() {
     }
};

using P4TestContext = P4CContextWithOptions<P4TestOptions>;

class P4CParserUnroll : public P4CTest { };

class SkipControls : public P4::ActionSynthesisPolicy {
    const std::set<cstring> *skip;

 public:
    explicit SkipControls(const std::set<cstring> *skip) : skip(skip) { CHECK_NULL(skip); }
    bool convert(const Visitor::Context *, const IR::P4Control* control) override {
        if (skip->find(control->name) != skip->end())
            return false;
        return true;
    }
};

class MidEnd : public PassManager {
 public:
    P4::ReferenceMap    refMap;
    P4::TypeMap         typeMap;
    IR::ToplevelBlock   *toplevel = nullptr;

    explicit MidEnd(CompilerOptions& options, std::ostream* outStream = nullptr) {
        bool isv1 = options.langVersion == CompilerOptions::FrontendVersion::P4_14;
        refMap.setIsV1(isv1);
        auto evaluator = new P4::EvaluatorPass(&refMap, &typeMap);
        setName("MidEnd");

        auto v1controls = new std::set<cstring>();

        addPasses({
            options.ndebug ? new P4::RemoveAssertAssume(&refMap, &typeMap) : nullptr,
            new P4::RemoveMiss(&refMap, &typeMap),
            new P4::EliminateNewtype(&refMap, &typeMap),
            new P4::EliminateSerEnums(&refMap, &typeMap),
            new P4::RemoveActionParameters(&refMap, &typeMap),
            new P4::SimplifyKey(&refMap, &typeMap,
                                new P4::OrPolicy(
                                    new P4::IsValid(&refMap, &typeMap),
                                    new P4::IsLikeLeftValue())),
            new P4::RemoveExits(&refMap, &typeMap),
            new P4::ConstantFolding(&refMap, &typeMap),
            new P4::SimplifySelectCases(&refMap, &typeMap, false),  // non-constant keysets
            new P4::ExpandLookahead(&refMap, &typeMap),
            new P4::ExpandEmit(&refMap, &typeMap),
            new P4::HandleNoMatch(&refMap),
            new P4::SimplifyParsers(&refMap),
            new P4::StrengthReduction(&refMap, &typeMap),
            new P4::EliminateTuples(&refMap, &typeMap),
            new P4::SimplifyComparisons(&refMap, &typeMap),
            new P4::CopyStructures(&refMap, &typeMap),
            new P4::NestedStructs(&refMap, &typeMap),
            new P4::SimplifySelectList(&refMap, &typeMap),
            new P4::RemoveSelectBooleans(&refMap, &typeMap),
            new P4::FlattenHeaders(&refMap, &typeMap),
            new P4::FlattenInterfaceStructs(&refMap, &typeMap),
            new P4::ReplaceSelectRange(&refMap, &typeMap),
            new P4::Predication(&refMap),
            new P4::MoveDeclarations(),  // more may have been introduced
            new P4::ConstantFolding(&refMap, &typeMap),
            new P4::LocalCopyPropagation(&refMap, &typeMap),
            new P4::ConstantFolding(&refMap, &typeMap),
            new P4::StrengthReduction(&refMap, &typeMap),
            new P4::MoveDeclarations(),  // more may have been introduced
            new P4::SimplifyControlFlow(&refMap, &typeMap),
            new P4::CompileTimeOperations(),
            new P4::TableHit(&refMap, &typeMap),
            new P4::EliminateSwitch(&refMap, &typeMap),
            evaluator,
            [v1controls, evaluator](const IR::Node *root) -> const IR::Node * {
                auto toplevel = evaluator->getToplevelBlock();
                auto main = toplevel->getMain();
                if (main == nullptr)
                    // nothing further to do
                    return nullptr;
                // Special handling when compiling for v1model.p4
                if (main->type->name == P4V1::V1Model::instance.sw.name) {
                    if (main->getConstructorParameters()->size() != 6)
                        return root;
                    auto verify = main->getParameterValue(P4V1::V1Model::instance.sw.verify.name);
                    auto update = main->getParameterValue(
                        P4V1::V1Model::instance.sw.compute.name);
                    auto deparser = main->getParameterValue(
                                    P4V1::V1Model::instance.sw.deparser.name);
                    if (verify == nullptr || update == nullptr || deparser == nullptr ||
                        !verify->is<IR::ControlBlock>() || !update->is<IR::ControlBlock>() ||
                        !deparser->is<IR::ControlBlock>()) {
                        return root;
                    }
                    v1controls->emplace(verify->to<IR::ControlBlock>()->container->name);
                    v1controls->emplace(update->to<IR::ControlBlock>()->container->name);
                    v1controls->emplace(deparser->to<IR::ControlBlock>()->container->name);
                }
                return root; },
            new P4::SynthesizeActions(&refMap, &typeMap, new SkipControls(v1controls)),
            new P4::MoveActionsToTables(&refMap, &typeMap),
            options.loopsUnrolling ? new ParsersUnroll(true, &refMap, &typeMap) : nullptr,
            evaluator,
            [this, evaluator]() {
                toplevel = evaluator->getToplevelBlock();
            },
            new P4::MidEndLast()
        });
        if (options.listMidendPasses) {
            listPasses(*outStream, "\n");
            *outStream << std::endl;
            return;
        }
        if (options.excludeMidendPasses) {
            removePasses(options.passesToExcludeMidend);
        }
        toplevel = evaluator->getToplevelBlock();
    }
    IR::ToplevelBlock* process(const IR::P4Program *&program) {
        program = program->apply(*this);
        return toplevel; }
};

// #define PARSER_UNROLL_TIME_CHECKING

#ifdef PARSER_UNROLL_TIME_CHECKING
    #include <chrono>
#endif

const IR::P4Parser* getParser(const IR::P4Program* program) {
    cstring parserName = "MyParser";
   /* std::function<bool(const IR::IDeclaration*)> filter =
            [parserName](const IR::IDeclaration* d)
            { CHECK_NULL(d); return d->getName().name.find(parserName.c_str()) != nullptr; };*/
    std::function<bool(const IR::IDeclaration*)> filter =
            [parserName](const IR::IDeclaration* d)
            { CHECK_NULL(d); return d->is<IR::P4Parser>(); };
    const auto* newDeclVector = program->getDeclarations()->where(filter)->toVector();
    return (*newDeclVector)[0]->to<IR::P4Parser>();
}

/// Rewrites parser
std::pair<const IR::P4Parser*, const IR::P4Parser*> rewriteParser(const IR::P4Program* program,
                                                                  CompilerOptions& options) {
    P4::FrontEnd frontend;
    program = frontend.run(options, program);
    P4::ReferenceMap    refMap;
    P4::TypeMap         typeMap;

#ifdef PARSER_UNROLL_TIME_CHECKING
    using std::chrono::high_resolution_clock;
    using std::chrono::duration_cast;
    using std::chrono::duration;
    using std::chrono::milliseconds;
    auto t1 = high_resolution_clock::now();
#endif
    MidEnd midEnd(options);
    const IR::P4Program* res = program;
    midEnd.process(res);
#ifdef PARSER_UNROLL_TIME_CHECKING
    auto t2 = high_resolution_clock::now();
    auto msInt = duration_cast<milliseconds>(t2 - t1);
    std::cout << msInt.count() << std::endl;
#endif
    return std::make_pair(getParser(program), getParser(res));
}

/// Loads example from a file
const IR::P4Program* load_model(const char* curFile, CompilerOptions& options) {
    std::string includeDir = std::string(relPath) + std::string("p4include");
    setenv("P4C_16_INCLUDE_PATH", includeDir.c_str(), 1);
    options.loopsUnrolling = true;
    options.compilerVersion = P4TEST_VERSION_STRING;
    options.file = relPath;
    options.file += "testdata/p4_16_samples/";
    options.file += curFile;
    return P4::parseP4File(options);
}

std::pair<const IR::P4Parser*, const IR::P4Parser*> loadExample(const char *file,
        CompilerOptions::FrontendVersion langVersion =
        CompilerOptions::FrontendVersion::P4_16) {
    AutoCompileContext autoP4TestContext(new P4TestContext);
    auto& options = P4TestContext::get().options();
    const char* argv = "./gtestp4c";
    options.process(1, (char* const*)&argv);
    options.langVersion = langVersion;
    const IR::P4Program* program = load_model(file, options);
    if (!program)
        return std::make_pair(nullptr, nullptr);
    return rewriteParser(program, options);
}

TEST_F(P4CParserUnroll, test1) {
    auto parsers = loadExample("parser-unroll-test1.p4");
    ASSERT_TRUE(parsers.first);
    ASSERT_TRUE(parsers.second);
    // 2 - exclude accept and reject states
    // adding MAX_HOPS and outOfBound states
    ASSERT_EQ(parsers.first->states.size(), parsers.second->states.size() - 3 - 1);
}

TEST_F(P4CParserUnroll, test2) {
    auto parsers = loadExample("parser-unroll-test2.p4");
    ASSERT_TRUE(parsers.first);
    ASSERT_TRUE(parsers.second);
    ASSERT_EQ(parsers.first->states.size(),  parsers.second->states.size() - 3 - 1);
}

TEST_F(P4CParserUnroll, test3) {
    auto parsers = loadExample("parser-unroll-test3.p4");
    ASSERT_TRUE(parsers.first);
    ASSERT_TRUE(parsers.second);
    ASSERT_EQ(parsers.first->states.size(), parsers.second->states.size() - 4);
}

TEST_F(P4CParserUnroll, switch_20160512) {
    auto parsers =  loadExample("../p4_14_samples/switch_20160512/switch.p4",
        CompilerOptions::FrontendVersion::P4_14);
    ASSERT_TRUE(parsers.first);
    ASSERT_TRUE(parsers.second);
    ASSERT_EQ(parsers.first->states.size(), parsers.second->states.size() - 22 - 4 - 2);
}

TEST_F(P4CParserUnroll, header_stack_access_remover) {
    auto parsers =  loadExample("parser-unroll-test4.p4");
    ASSERT_TRUE(parsers.first);
    ASSERT_TRUE(parsers.second);
    ASSERT_EQ(parsers.first->states.size(), parsers.second->states.size() - 3);
}

TEST_F(P4CParserUnroll, noLoopsAndHeaderStacks) {
    auto parsers =  loadExample("parser-unroll-test5.p4");
    ASSERT_TRUE(parsers.first);
    ASSERT_TRUE(parsers.second);
    ASSERT_EQ(parsers.first->states.size(), parsers.second->states.size());
}

TEST_F(P4CParserUnroll, t1_Cond) {
    auto parsers =  loadExample("parser-unroll-t1-cond.p4");
    ASSERT_TRUE(parsers.first);
    ASSERT_TRUE(parsers.second);
    ASSERT_EQ(parsers.first->states.size(), parsers.second->states.size());
}

}  // namespace Test
<commit_msg>Parser unroll gtest now does not modify environment (#2750)<commit_after>#include <stdlib.h>

#include <fstream>

#include "env.h"

#include "gtest/gtest.h"
#include "ir/ir.h"
#include "helpers.h"
#include "lib/log.h"

#include "frontends/common/parseInput.h"

#include "backends/p4test/version.h"

#include "p4/createBuiltins.h"
#include "p4/typeChecking/typeChecker.h"

#include "frontends/common/constantFolding.h"
#include "frontends/common/resolveReferences/resolveReferences.h"
#include "frontends/p4/evaluator/evaluator.h"
#include "frontends/p4/fromv1.0/v1model.h"
#include "frontends/p4/moveDeclarations.h"
#include "frontends/p4/simplify.h"
#include "frontends/p4/typeChecking/typeChecker.h"
#include "frontends/p4/simplifyParsers.h"
#include "frontends/p4/strengthReduction.h"
#include "frontends/p4/toP4/toP4.h"
#include "frontends/p4/typeMap.h"
#include "frontends/p4/uniqueNames.h"
#include "frontends/p4/unusedDeclarations.h"
#include "midend/actionSynthesis.h"
#include "midend/compileTimeOps.h"
#include "midend/complexComparison.h"
#include "midend/copyStructures.h"
#include "midend/eliminateTuples.h"
#include "midend/eliminateNewtype.h"
#include "midend/eliminateSerEnums.h"
#include "midend/eliminateSwitch.h"
#include "midend/flattenHeaders.h"
#include "midend/flattenInterfaceStructs.h"
#include "midend/replaceSelectRange.h"
#include "midend/expandEmit.h"
#include "midend/expandLookahead.h"
#include "midend/local_copyprop.h"
#include "midend/midEndLast.h"
#include "midend/nestedStructs.h"
#include "midend/noMatch.h"
#include "midend/predication.h"
#include "midend/removeExits.h"
#include "midend/removeMiss.h"
#include "midend/removeParameters.h"
#include "midend/removeSelectBooleans.h"
#include "midend/simplifyKey.h"
#include "midend/simplifySelectCases.h"
#include "midend/simplifySelectList.h"
#include "midend/tableHit.h"
#include "midend/removeAssertAssume.h"
#include "midend/parserUnroll.h"

using namespace P4;

namespace Test {

class P4TestOptions : public CompilerOptions {
 public:
    P4TestOptions() {
     }
};

using P4TestContext = P4CContextWithOptions<P4TestOptions>;

class P4CParserUnroll : public P4CTest { };

class SkipControls : public P4::ActionSynthesisPolicy {
    const std::set<cstring> *skip;

 public:
    explicit SkipControls(const std::set<cstring> *skip) : skip(skip) { CHECK_NULL(skip); }
    bool convert(const Visitor::Context *, const IR::P4Control* control) override {
        if (skip->find(control->name) != skip->end())
            return false;
        return true;
    }
};

class MidEnd : public PassManager {
 public:
    P4::ReferenceMap    refMap;
    P4::TypeMap         typeMap;
    IR::ToplevelBlock   *toplevel = nullptr;

    explicit MidEnd(CompilerOptions& options, std::ostream* outStream = nullptr) {
        bool isv1 = options.langVersion == CompilerOptions::FrontendVersion::P4_14;
        refMap.setIsV1(isv1);
        auto evaluator = new P4::EvaluatorPass(&refMap, &typeMap);
        setName("MidEnd");

        auto v1controls = new std::set<cstring>();

        addPasses({
            options.ndebug ? new P4::RemoveAssertAssume(&refMap, &typeMap) : nullptr,
            new P4::RemoveMiss(&refMap, &typeMap),
            new P4::EliminateNewtype(&refMap, &typeMap),
            new P4::EliminateSerEnums(&refMap, &typeMap),
            new P4::RemoveActionParameters(&refMap, &typeMap),
            new P4::SimplifyKey(&refMap, &typeMap,
                                new P4::OrPolicy(
                                    new P4::IsValid(&refMap, &typeMap),
                                    new P4::IsLikeLeftValue())),
            new P4::RemoveExits(&refMap, &typeMap),
            new P4::ConstantFolding(&refMap, &typeMap),
            new P4::SimplifySelectCases(&refMap, &typeMap, false),  // non-constant keysets
            new P4::ExpandLookahead(&refMap, &typeMap),
            new P4::ExpandEmit(&refMap, &typeMap),
            new P4::HandleNoMatch(&refMap),
            new P4::SimplifyParsers(&refMap),
            new P4::StrengthReduction(&refMap, &typeMap),
            new P4::EliminateTuples(&refMap, &typeMap),
            new P4::SimplifyComparisons(&refMap, &typeMap),
            new P4::CopyStructures(&refMap, &typeMap),
            new P4::NestedStructs(&refMap, &typeMap),
            new P4::SimplifySelectList(&refMap, &typeMap),
            new P4::RemoveSelectBooleans(&refMap, &typeMap),
            new P4::FlattenHeaders(&refMap, &typeMap),
            new P4::FlattenInterfaceStructs(&refMap, &typeMap),
            new P4::ReplaceSelectRange(&refMap, &typeMap),
            new P4::Predication(&refMap),
            new P4::MoveDeclarations(),  // more may have been introduced
            new P4::ConstantFolding(&refMap, &typeMap),
            new P4::LocalCopyPropagation(&refMap, &typeMap),
            new P4::ConstantFolding(&refMap, &typeMap),
            new P4::StrengthReduction(&refMap, &typeMap),
            new P4::MoveDeclarations(),  // more may have been introduced
            new P4::SimplifyControlFlow(&refMap, &typeMap),
            new P4::CompileTimeOperations(),
            new P4::TableHit(&refMap, &typeMap),
            new P4::EliminateSwitch(&refMap, &typeMap),
            evaluator,
            [v1controls, evaluator](const IR::Node *root) -> const IR::Node * {
                auto toplevel = evaluator->getToplevelBlock();
                auto main = toplevel->getMain();
                if (main == nullptr)
                    // nothing further to do
                    return nullptr;
                // Special handling when compiling for v1model.p4
                if (main->type->name == P4V1::V1Model::instance.sw.name) {
                    if (main->getConstructorParameters()->size() != 6)
                        return root;
                    auto verify = main->getParameterValue(P4V1::V1Model::instance.sw.verify.name);
                    auto update = main->getParameterValue(
                        P4V1::V1Model::instance.sw.compute.name);
                    auto deparser = main->getParameterValue(
                                    P4V1::V1Model::instance.sw.deparser.name);
                    if (verify == nullptr || update == nullptr || deparser == nullptr ||
                        !verify->is<IR::ControlBlock>() || !update->is<IR::ControlBlock>() ||
                        !deparser->is<IR::ControlBlock>()) {
                        return root;
                    }
                    v1controls->emplace(verify->to<IR::ControlBlock>()->container->name);
                    v1controls->emplace(update->to<IR::ControlBlock>()->container->name);
                    v1controls->emplace(deparser->to<IR::ControlBlock>()->container->name);
                }
                return root; },
            new P4::SynthesizeActions(&refMap, &typeMap, new SkipControls(v1controls)),
            new P4::MoveActionsToTables(&refMap, &typeMap),
            options.loopsUnrolling ? new ParsersUnroll(true, &refMap, &typeMap) : nullptr,
            evaluator,
            [this, evaluator]() {
                toplevel = evaluator->getToplevelBlock();
            },
            new P4::MidEndLast()
        });
        if (options.listMidendPasses) {
            listPasses(*outStream, "\n");
            *outStream << std::endl;
            return;
        }
        if (options.excludeMidendPasses) {
            removePasses(options.passesToExcludeMidend);
        }
        toplevel = evaluator->getToplevelBlock();
    }
    IR::ToplevelBlock* process(const IR::P4Program *&program) {
        program = program->apply(*this);
        return toplevel; }
};

// #define PARSER_UNROLL_TIME_CHECKING

#ifdef PARSER_UNROLL_TIME_CHECKING
    #include <chrono>
#endif

const IR::P4Parser* getParser(const IR::P4Program* program) {
    cstring parserName = "MyParser";
   /* std::function<bool(const IR::IDeclaration*)> filter =
            [parserName](const IR::IDeclaration* d)
            { CHECK_NULL(d); return d->getName().name.find(parserName.c_str()) != nullptr; };*/
    std::function<bool(const IR::IDeclaration*)> filter =
            [parserName](const IR::IDeclaration* d)
            { CHECK_NULL(d); return d->is<IR::P4Parser>(); };
    const auto* newDeclVector = program->getDeclarations()->where(filter)->toVector();
    return (*newDeclVector)[0]->to<IR::P4Parser>();
}

/// Rewrites parser
std::pair<const IR::P4Parser*, const IR::P4Parser*> rewriteParser(const IR::P4Program* program,
                                                                  CompilerOptions& options) {
    P4::FrontEnd frontend;
    program = frontend.run(options, program);
    P4::ReferenceMap    refMap;
    P4::TypeMap         typeMap;

#ifdef PARSER_UNROLL_TIME_CHECKING
    using std::chrono::high_resolution_clock;
    using std::chrono::duration_cast;
    using std::chrono::duration;
    using std::chrono::milliseconds;
    auto t1 = high_resolution_clock::now();
#endif
    MidEnd midEnd(options);
    const IR::P4Program* res = program;
    midEnd.process(res);
#ifdef PARSER_UNROLL_TIME_CHECKING
    auto t2 = high_resolution_clock::now();
    auto msInt = duration_cast<milliseconds>(t2 - t1);
    std::cout << msInt.count() << std::endl;
#endif
    return std::make_pair(getParser(program), getParser(res));
}

/// Loads example from a file
const IR::P4Program* load_model(const char* curFile, CompilerOptions& options) {
    std::string includeDir = std::string(relPath) + std::string("p4include");
    auto originalEnv = getenv("P4C_16_INCLUDE_PATH");
    setenv("P4C_16_INCLUDE_PATH", includeDir.c_str(), 1);
    options.loopsUnrolling = true;
    options.compilerVersion = P4TEST_VERSION_STRING;
    options.file = relPath;
    options.file += "testdata/p4_16_samples/";
    options.file += curFile;
    auto program = P4::parseP4File(options);
    if (!originalEnv)
        unsetenv("P4C_16_INCLUDE_PATH");
    else
        setenv("P4C_16_INCLUDE_PATH", originalEnv, 1);
    return program;
}

std::pair<const IR::P4Parser*, const IR::P4Parser*> loadExample(const char *file,
        CompilerOptions::FrontendVersion langVersion =
        CompilerOptions::FrontendVersion::P4_16) {
    AutoCompileContext autoP4TestContext(new P4TestContext);
    auto& options = P4TestContext::get().options();
    const char* argv = "./gtestp4c";
    options.process(1, (char* const*)&argv);
    options.langVersion = langVersion;
    const IR::P4Program* program = load_model(file, options);
    if (!program)
        return std::make_pair(nullptr, nullptr);
    return rewriteParser(program, options);
}

TEST_F(P4CParserUnroll, test1) {
    auto parsers = loadExample("parser-unroll-test1.p4");
    ASSERT_TRUE(parsers.first);
    ASSERT_TRUE(parsers.second);
    // 2 - exclude accept and reject states
    // adding MAX_HOPS and outOfBound states
    ASSERT_EQ(parsers.first->states.size(), parsers.second->states.size() - 3 - 1);
}

TEST_F(P4CParserUnroll, test2) {
    auto parsers = loadExample("parser-unroll-test2.p4");
    ASSERT_TRUE(parsers.first);
    ASSERT_TRUE(parsers.second);
    ASSERT_EQ(parsers.first->states.size(),  parsers.second->states.size() - 3 - 1);
}

TEST_F(P4CParserUnroll, test3) {
    auto parsers = loadExample("parser-unroll-test3.p4");
    ASSERT_TRUE(parsers.first);
    ASSERT_TRUE(parsers.second);
    ASSERT_EQ(parsers.first->states.size(), parsers.second->states.size() - 4);
}

TEST_F(P4CParserUnroll, switch_20160512) {
    auto parsers =  loadExample("../p4_14_samples/switch_20160512/switch.p4",
        CompilerOptions::FrontendVersion::P4_14);
    ASSERT_TRUE(parsers.first);
    ASSERT_TRUE(parsers.second);
    ASSERT_EQ(parsers.first->states.size(), parsers.second->states.size() - 22 - 4 - 2);
}

TEST_F(P4CParserUnroll, header_stack_access_remover) {
    auto parsers =  loadExample("parser-unroll-test4.p4");
    ASSERT_TRUE(parsers.first);
    ASSERT_TRUE(parsers.second);
    ASSERT_EQ(parsers.first->states.size(), parsers.second->states.size() - 3);
}

TEST_F(P4CParserUnroll, noLoopsAndHeaderStacks) {
    auto parsers =  loadExample("parser-unroll-test5.p4");
    ASSERT_TRUE(parsers.first);
    ASSERT_TRUE(parsers.second);
    ASSERT_EQ(parsers.first->states.size(), parsers.second->states.size());
}

TEST_F(P4CParserUnroll, t1_Cond) {
    auto parsers =  loadExample("parser-unroll-t1-cond.p4");
    ASSERT_TRUE(parsers.first);
    ASSERT_TRUE(parsers.second);
    ASSERT_EQ(parsers.first->states.size(), parsers.second->states.size());
}

}  // namespace Test
<|endoftext|>


<commit_before>// Catch
#include <catch.hpp>

// C++ Standard Library
#include <cstdlib>
#include <cmath>
#include <array>

// Armadillo
#include <armadillo>

// Mantella
#include <mantella>

TEST_CASE("Circle circle intersection", "") {
  arma::Col<double>::fixed<2> result;
  arma::Col<double>::fixed<2> expected;

  result = mant::getCircleCircleIntersection({-2.0, 3.0}, 1.3, {-1.5, 2.4}, 1.2);
  expected = {-2.5522451636, 1.8231290303};
  for (std::size_t n = 0; n < expected.n_elem; ++n) {
    CHECK(result.at(n) == Approx(expected.at(n)));
  }

  result = mant::getCircleCircleIntersection({1.8, -2.5}, 4.0, {-3.0, 2.0}, 3.0);
  expected = {-0.1804143359, 0.9753358195};
  for (std::size_t n = 0; n < expected.n_elem; ++n) {
    CHECK(result.at(n) == Approx(expected.at(n)));
  }
}

TEST_CASE("Circle sphere intersection", "") {
  arma::Col<double>::fixed<3> result;
  arma::Col<double>::fixed<3> expected;

  result = mant::getCircleSphereIntersection({-2.0, 0.0, 0.0}, 1.2, {0.0, 0.0, 1.0}, {-3.0, 0.0, 0.0}, 1.5);
  expected = {-2.095, 1.1962336728, 0.0};
  for (std::size_t n = 0; n < expected.n_elem; ++n) {
    CHECK(result.at(n) == Approx(expected.at(n)));
  }

  result = mant::getCircleSphereIntersection({-2.0, 3.0, 0.0}, 1.3, {0.0, 0.0, 1.0}, {-1.5, 2.4, 0.0}, 1.2);
  expected = {-2.5522451636, 1.8231290303, 0.0};
  for (std::size_t n = 0; n < expected.n_elem; ++n) {
    CHECK(result.at(n) == Approx(expected.at(n)));
  }

  result = mant::getCircleSphereIntersection({1.8, -2.5, 0.0}, 4.0, {0.0, 0.0, 1.0}, {-3.0, 2.0, 0.0}, 3.0);
  expected = {-0.1804143359, 0.9753358195, 0.0};
  for (std::size_t n = 0; n < expected.n_elem; ++n) {
    CHECK(result.at(n) == Approx(expected.at(n)));
  }
}

TEST_CASE("2D rotation matrix", "") {
  std::array<double, 15> angles = {0.0,  45.0, 90.0, 135.0, 180.0, 225.0, 270.0, 315.0, 360.0, -0.0, -45.0, -90.0, -180.0, -225.0, -315.0};

  for (const auto& angle : angles) {
    arma::Mat<double> result = mant::get2DRotationMatrix(angle);

    arma::Mat<double>::fixed<2, 2> expected({
      std::cos(angle), -std::sin(angle),
      std::sin(angle), std::cos(angle)
    });

    CHECK(result.n_rows == 2);
    CHECK(result.n_cols == 2);

    for (std::size_t n = 0; n < expected.n_elem; ++n) {
      CHECK(result.at(n) == Approx(expected.at(n)));
    }
  }
}

TEST_CASE("3D rotation matrix", "") {
  std::array<double, 14> rollAngles = {0.0, 45.0, 90.0, 135.0, 180.0, 225, 270, 315, 360, -0, -45, 276, -56, -45.89};
  std::array<double, 14> pitchAngles = {0.0, 45.0, 90.0, 135.0, 180.0, 225, 270, 315, 360, -0, -90, -89, 78, -245};
  std::array<double, 14> yawAngles = {0.0, 45.0, 90.0, 135.0, 180.0, 225, 270, 315, 360, -0, -225, -310, -90, 345};

  for (const auto& rollAngle : rollAngles) {
    for (const auto& pitchAngle : pitchAngles) {
      for (const auto& yawAngle : yawAngles) {
        arma::Mat<double> result = mant::get3DRotationMatrix(rollAngle, pitchAngle, yawAngle);

        arma::Mat<double>::fixed<3, 3> expectedRoll({
          1.0, 0.0, 0.0,
          0.0, std::cos(rollAngle), -std::sin(rollAngle),
          0.0, std::sin(rollAngle), std::cos(rollAngle),
        });

        arma::Mat<double>::fixed<3, 3> expectedPitch({
          std::cos(pitchAngle), 0.0, std::sin(pitchAngle),
          0.0, 1.0, 0.0,
          -std::sin(pitchAngle), 0.0, std::cos(pitchAngle)
        });

        arma::Mat<double>::fixed<3, 3> expectedYaw({
          std::cos(yawAngle), -std::sin(yawAngle), 0.0,
          std::sin(yawAngle), std::cos(yawAngle), 0.0,
          0.0, 0.0, 1.0
        });

        arma::Mat<double>::fixed<3, 3> expected = expectedRoll * expectedPitch * expectedYaw;

        CHECK(result.n_rows == 3);
        CHECK(result.n_cols == 3);

        for (std::size_t n = 0; n < expected.n_elem; ++n) {
          CHECK(result.at(n) == Approx(expected.at(n)));
        }
      }
    }
  }
}

<commit_msg>fix: resolve warnings<commit_after>// Catch
#include <catch.hpp>

// C++ Standard Library
#include <cstdlib>
#include <cmath>
#include <array>

// Armadillo
#include <armadillo>

// Mantella
#include <mantella>

TEST_CASE("Circle circle intersection", "") {
  arma::Col<double>::fixed<2> result;
  arma::Col<double>::fixed<2> expected;

  result = mant::getCircleCircleIntersection({-2.0, 3.0}, 1.3, {-1.5, 2.4}, 1.2);
  expected = {-2.5522451636, 1.8231290303};
  for (std::size_t n = 0; n < expected.n_elem; ++n) {
    CHECK(result.at(n) == Approx(expected.at(n)));
  }

  result = mant::getCircleCircleIntersection({1.8, -2.5}, 4.0, {-3.0, 2.0}, 3.0);
  expected = {-0.1804143359, 0.9753358195};
  for (std::size_t n = 0; n < expected.n_elem; ++n) {
    CHECK(result.at(n) == Approx(expected.at(n)));
  }
}

TEST_CASE("Circle sphere intersection", "") {
  arma::Col<double>::fixed<3> result;
  arma::Col<double>::fixed<3> expected;

  result = mant::getCircleSphereIntersection({-2.0, 0.0, 0.0}, 1.2, {0.0, 0.0, 1.0}, {-3.0, 0.0, 0.0}, 1.5);
  expected = {-2.095, 1.1962336728, 0.0};
  for (std::size_t n = 0; n < expected.n_elem; ++n) {
    CHECK(result.at(n) == Approx(expected.at(n)));
  }

  result = mant::getCircleSphereIntersection({-2.0, 3.0, 0.0}, 1.3, {0.0, 0.0, 1.0}, {-1.5, 2.4, 0.0}, 1.2);
  expected = {-2.5522451636, 1.8231290303, 0.0};
  for (std::size_t n = 0; n < expected.n_elem; ++n) {
    CHECK(result.at(n) == Approx(expected.at(n)));
  }

  result = mant::getCircleSphereIntersection({1.8, -2.5, 0.0}, 4.0, {0.0, 0.0, 1.0}, {-3.0, 2.0, 0.0}, 3.0);
  expected = {-0.1804143359, 0.9753358195, 0.0};
  for (std::size_t n = 0; n < expected.n_elem; ++n) {
    CHECK(result.at(n) == Approx(expected.at(n)));
  }
}

TEST_CASE("2D rotation matrix", "") {
  std::array<double, 15> angles = {{0.0,  45.0, 90.0, 135.0, 180.0, 225.0, 270.0, 315.0, 360.0, -0.0, -45.0, -90.0, -180.0, -225.0, -315.0}};

  for (const auto& angle : angles) {
    arma::Mat<double> result = mant::get2DRotationMatrix(angle);

    arma::Mat<double>::fixed<2, 2> expected({
      std::cos(angle), -std::sin(angle),
      std::sin(angle), std::cos(angle)
    });

    CHECK(result.n_rows == 2);
    CHECK(result.n_cols == 2);

    for (std::size_t n = 0; n < expected.n_elem; ++n) {
      CHECK(result.at(n) == Approx(expected.at(n)));
    }
  }
}

TEST_CASE("3D rotation matrix", "") {
  std::array<double, 14> rollAngles = {{0.0, 45.0, 90.0, 135.0, 180.0, 225, 270, 315, 360, -0, -45, 276, -56, -45.89}};
  std::array<double, 14> pitchAngles = {{0.0, 45.0, 90.0, 135.0, 180.0, 225, 270, 315, 360, -0, -90, -89, 78, -245}};
  std::array<double, 14> yawAngles = {{0.0, 45.0, 90.0, 135.0, 180.0, 225, 270, 315, 360, -0, -225, -310, -90, 345}};

  for (const auto& rollAngle : rollAngles) {
    for (const auto& pitchAngle : pitchAngles) {
      for (const auto& yawAngle : yawAngles) {
        arma::Mat<double> result = mant::get3DRotationMatrix(rollAngle, pitchAngle, yawAngle);

        arma::Mat<double>::fixed<3, 3> expectedRoll({
          1.0, 0.0, 0.0,
          0.0, std::cos(rollAngle), -std::sin(rollAngle),
          0.0, std::sin(rollAngle), std::cos(rollAngle),
        });

        arma::Mat<double>::fixed<3, 3> expectedPitch({
          std::cos(pitchAngle), 0.0, std::sin(pitchAngle),
          0.0, 1.0, 0.0,
          -std::sin(pitchAngle), 0.0, std::cos(pitchAngle)
        });

        arma::Mat<double>::fixed<3, 3> expectedYaw({
          std::cos(yawAngle), -std::sin(yawAngle), 0.0,
          std::sin(yawAngle), std::cos(yawAngle), 0.0,
          0.0, 0.0, 1.0
        });

        arma::Mat<double>::fixed<3, 3> expected = expectedRoll * expectedPitch * expectedYaw;

        CHECK(result.n_rows == 3);
        CHECK(result.n_cols == 3);

        for (std::size_t n = 0; n < expected.n_elem; ++n) {
          CHECK(result.at(n) == Approx(expected.at(n)));
        }
      }
    }
  }
}

<|endoftext|>


<commit_before>//======================================================================
//-----------------------------------------------------------------------
/**
 * @file		iutest_logger_tests.cpp
 * @brief		logger テスト
 *
 * @author		t.sirayanagi
 * @version		1.0
 *
 * @par			copyright
 * Copyright (C) 2014, Takazumi Shirayanagi\n
 * This software is released under the new BSD License,
 * see LICENSE
*/
//-----------------------------------------------------------------------
//======================================================================

//======================================================================
// include
#include "../include/iutest.hpp"

#if !defined(IUTEST_USE_GTEST)

class TestLogger : public ::iutest::detail::iuLogger
{
	::std::string m_log;
public:
	virtual void voutput(const char* fmt, va_list va)
	{
		va_list va2;
#ifndef va_copy
		va2 = va;
#else
		va_copy(va2, va);
#endif
		char buf[4096];
		vsprintf(buf, fmt, va2);
		va_end(va2);
		m_log += buf;
		::iutest::detail::iuConsole::voutput(fmt, va);
	}
	void clear(void) { m_log.clear(); }
public:
	const char* c_str(void) const { return m_log.c_str(); }
};

#endif
<commit_msg>update r511<commit_after>//======================================================================
//-----------------------------------------------------------------------
/**
 * @file		iutest_logger_tests.cpp
 * @brief		logger テスト
 *
 * @author		t.sirayanagi
 * @version		1.0
 *
 * @par			copyright
 * Copyright (C) 2014, Takazumi Shirayanagi\n
 * This software is released under the new BSD License,
 * see LICENSE
*/
//-----------------------------------------------------------------------
//======================================================================

//======================================================================
// include
#include "../include/iutest.hpp"

#if !defined(IUTEST_USE_GTEST)

class TestLogger : public ::iutest::detail::iuLogger
{
	::std::string m_log;
public:
	virtual void voutput(const char* fmt, va_list va)
	{
#ifdef va_copy
		va_list va2;
		va_copy(va2, va);
		char buf[4096];
		vsprintf(buf, fmt, va2);
		va_end(va2);
		m_log += buf;
		::iutest::detail::iuConsole::voutput(fmt, va);
#else
		char buf[4096];
		vsprintf(buf, fmt, va);
		m_log += buf;
		::iutest::detail::iuConsole::output(buf);
#endif
	}
	void clear(void) { m_log.clear(); }
public:
	const char* c_str(void) const { return m_log.c_str(); }
};

#endif
<|endoftext|>


<commit_before>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

static int nb_temporaries;

#define EIGEN_DEBUG_MATRIX_CTOR(MTYPE) { \
    if(MTYPE::SizeAtCompileTime==Dynamic) \
      nb_temporaries++; \
 }

#include "main.h"
#include <Eigen/Array>

#define VERIFY_EVALUATION_COUNT(XPR,N) {\
    nb_temporaries = 0; \
    XPR; \
    if(nb_temporaries!=N) std::cerr << "nb_temporaries == " << nb_temporaries << "\n"; \
    VERIFY( (#XPR) && nb_temporaries==N ); \
  }

template<typename MatrixType> void product_notemporary(const MatrixType& m)
{
  /* This test checks the number of tempories created
   * during the evaluation of a complex expression */

  typedef typename MatrixType::Scalar Scalar;
  typedef Matrix<Scalar, 1, Dynamic> RowVectorType;
  typedef Matrix<Scalar, Dynamic, 1> ColVectorType;
  typedef Matrix<Scalar, Dynamic, Dynamic, RowMajor> RowMajorMatrixType;

  int rows = m.rows();
  int cols = m.cols();

  MatrixType m1 = MatrixType::Random(rows, cols),
             m2 = MatrixType::Random(rows, cols),
             m3(rows, cols);
  RowVectorType rv1 = RowVectorType::Random(rows), rvres(rows);
  ColVectorType vc2 = ColVectorType::Random(cols), cvres(cols);
  RowMajorMatrixType rm3(rows, cols);

  Scalar s1 = ei_random<Scalar>(),
         s2 = ei_random<Scalar>(),
         s3 = ei_random<Scalar>();

  int c0 = ei_random<int>(4,cols-8),
      c1 = ei_random<int>(8,cols-c0),
      r0 = ei_random<int>(4,cols-8),
      r1 = ei_random<int>(8,rows-r0);

  VERIFY_EVALUATION_COUNT( m3 = (m1 * m2.adjoint()), 1);
  VERIFY_EVALUATION_COUNT( m3 = (m1 * m2.adjoint()).lazy(), 0);
  VERIFY_EVALUATION_COUNT( m3.noalias() = m1 * m2.adjoint(), 0);

  // NOTE in this case the slow product is used:
  // FIXME:
  VERIFY_EVALUATION_COUNT( m3.noalias() = s1 * (m1 * m2.transpose()), 0);

  VERIFY_EVALUATION_COUNT( m3.noalias() = s1 * m1 * s2 * m2.adjoint(), 0);
  VERIFY_EVALUATION_COUNT( m3.noalias() = s1 * m1 * s2 * (m1*s3+m2*s2).adjoint(), 1);
  VERIFY_EVALUATION_COUNT( m3.noalias() = (s1 * m1).adjoint() * s2 * m2, 0);
  VERIFY_EVALUATION_COUNT( m3 += (s1 * (-m1*s3).adjoint() * (s2 * m2 * s3)).lazy(), 0);
  VERIFY_EVALUATION_COUNT( m3.noalias() += s1 * (-m1*s3).adjoint() * (s2 * m2 * s3), 0);
  VERIFY_EVALUATION_COUNT( m3 -= (s1 * (m1.transpose() * m2)).lazy(), 0);
  VERIFY_EVALUATION_COUNT( m3.noalias() -= s1 * (m1.transpose() * m2), 0);

  VERIFY_EVALUATION_COUNT(( m3.block(r0,r0,r1,r1).noalias() += -m1.block(r0,c0,r1,c1) * (s2*m2.block(r0,c0,r1,c1)).adjoint() ), 0);
  VERIFY_EVALUATION_COUNT(( m3.block(r0,r0,r1,r1).noalias() -= s1 * m1.block(r0,c0,r1,c1) * m2.block(c0,r0,c1,r1) ), 0);

  // NOTE this is because the Block expression is not handled yet by our expression analyser
  VERIFY_EVALUATION_COUNT(( m3.block(r0,r0,r1,r1) = (s1 * m1.block(r0,c0,r1,c1) * (s1*m2).block(c0,r0,c1,r1)).lazy() ), 1);

  VERIFY_EVALUATION_COUNT( m3.noalias() -= (s1 * m1).template triangularView<LowerTriangular>() * m2, 0);
  VERIFY_EVALUATION_COUNT( rm3.noalias() = (s1 * m1.adjoint()).template triangularView<UpperTriangular>() * (m2+m2), 1);
  VERIFY_EVALUATION_COUNT( rm3.noalias() = (s1 * m1.adjoint()).template triangularView<UnitUpperTriangular>() * m2.adjoint(), 0);

  VERIFY_EVALUATION_COUNT( rm3.col(c0).noalias() = (s1 * m1.adjoint()).template triangularView<UnitUpperTriangular>() * (s2*m2.row(c0)).adjoint(), 0);

  VERIFY_EVALUATION_COUNT( m1.template triangularView<LowerTriangular>().solveInPlace(m3), 0);
  VERIFY_EVALUATION_COUNT( m1.adjoint().template triangularView<LowerTriangular>().solveInPlace(m3.transpose()), 0);

  VERIFY_EVALUATION_COUNT( m3.noalias() -= (s1 * m1).adjoint().template selfadjointView<LowerTriangular>() * (-m2*s3).adjoint(), 0);
  VERIFY_EVALUATION_COUNT( m3.noalias() = s2 * m2.adjoint() * (s1 * m1.adjoint()).template selfadjointView<UpperTriangular>(), 0);
  VERIFY_EVALUATION_COUNT( rm3.noalias() = (s1 * m1.adjoint()).template selfadjointView<LowerTriangular>() * m2.adjoint(), 0);

  VERIFY_EVALUATION_COUNT( m3.col(c0).noalias() = (s1 * m1).adjoint().template selfadjointView<LowerTriangular>() * (-m2.row(c0)*s3).adjoint(), 0);
  VERIFY_EVALUATION_COUNT( m3.col(c0).noalias() -= (s1 * m1).adjoint().template selfadjointView<UpperTriangular>() * (-m2.row(c0)*s3).adjoint(), 0);

  VERIFY_EVALUATION_COUNT( m3.block(r0,c0,r1,c1).noalias() += m1.block(r0,r0,r1,r1).template selfadjointView<UpperTriangular>() * (s1*m2.block(r0,c0,r1,c1)), 0);
  VERIFY_EVALUATION_COUNT( m3.block(r0,c0,r1,c1).noalias() = m1.block(r0,r0,r1,r1).template selfadjointView<UpperTriangular>() * m2.block(r0,c0,r1,c1), 0);

  VERIFY_EVALUATION_COUNT( m3.template selfadjointView<LowerTriangular>().rankUpdate(m2.adjoint()), 0);

  m3.resize(1,1);
  VERIFY_EVALUATION_COUNT( m3.noalias() = m1.block(r0,r0,r1,r1).template selfadjointView<LowerTriangular>() * m2.block(r0,c0,r1,c1), 0);
  m3.resize(1,1);
  VERIFY_EVALUATION_COUNT( m3.noalias() = m1.block(r0,r0,r1,r1).template triangularView<UnitUpperTriangular>()  * m2.block(r0,c0,r1,c1), 0);
}

void test_product_notemporary()
{
  int s;
  for(int i = 0; i < g_repeat; i++) {
    s = ei_random<int>(16,320);
    CALL_SUBTEST( product_notemporary(MatrixXf(s, s)) );
    s = ei_random<int>(16,120);
    CALL_SUBTEST( product_notemporary(MatrixXcd(s,s)) );
  }
}
<commit_msg>Remove last lazyness warnings.<commit_after>// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2006-2008 Benoit Jacob <jacob.benoit.1@gmail.com>
//
// Eigen is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 3 of the License, or (at your option) any later version.
//
// Alternatively, you can redistribute it and/or
// modify it under the terms of the GNU General Public License as
// published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Eigen is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License or the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License and a copy of the GNU General Public License along with
// Eigen. If not, see <http://www.gnu.org/licenses/>.

static int nb_temporaries;

#define EIGEN_DEBUG_MATRIX_CTOR(MTYPE) { \
    if(MTYPE::SizeAtCompileTime==Dynamic) \
      nb_temporaries++; \
 }

#include "main.h"
#include <Eigen/Array>

#define VERIFY_EVALUATION_COUNT(XPR,N) {\
    nb_temporaries = 0; \
    XPR; \
    if(nb_temporaries!=N) std::cerr << "nb_temporaries == " << nb_temporaries << "\n"; \
    VERIFY( (#XPR) && nb_temporaries==N ); \
  }

template<typename MatrixType> void product_notemporary(const MatrixType& m)
{
  /* This test checks the number of tempories created
   * during the evaluation of a complex expression */

  typedef typename MatrixType::Scalar Scalar;
  typedef Matrix<Scalar, 1, Dynamic> RowVectorType;
  typedef Matrix<Scalar, Dynamic, 1> ColVectorType;
  typedef Matrix<Scalar, Dynamic, Dynamic, RowMajor> RowMajorMatrixType;

  int rows = m.rows();
  int cols = m.cols();

  MatrixType m1 = MatrixType::Random(rows, cols),
             m2 = MatrixType::Random(rows, cols),
             m3(rows, cols);
  RowVectorType rv1 = RowVectorType::Random(rows), rvres(rows);
  ColVectorType vc2 = ColVectorType::Random(cols), cvres(cols);
  RowMajorMatrixType rm3(rows, cols);

  Scalar s1 = ei_random<Scalar>(),
         s2 = ei_random<Scalar>(),
         s3 = ei_random<Scalar>();

  int c0 = ei_random<int>(4,cols-8),
      c1 = ei_random<int>(8,cols-c0),
      r0 = ei_random<int>(4,cols-8),
      r1 = ei_random<int>(8,rows-r0);

  VERIFY_EVALUATION_COUNT( m3 = (m1 * m2.adjoint()), 1);
  VERIFY_EVALUATION_COUNT( m3.noalias() = m1 * m2.adjoint(), 0);

  // NOTE in this case the slow product is used:
  // FIXME:
  VERIFY_EVALUATION_COUNT( m3.noalias() = s1 * (m1 * m2.transpose()), 0);

  VERIFY_EVALUATION_COUNT( m3.noalias() = s1 * m1 * s2 * m2.adjoint(), 0);
  VERIFY_EVALUATION_COUNT( m3.noalias() = s1 * m1 * s2 * (m1*s3+m2*s2).adjoint(), 1);
  VERIFY_EVALUATION_COUNT( m3.noalias() = (s1 * m1).adjoint() * s2 * m2, 0);
  VERIFY_EVALUATION_COUNT( m3.noalias() += s1 * (-m1*s3).adjoint() * (s2 * m2 * s3), 0);
  VERIFY_EVALUATION_COUNT( m3.noalias() -= s1 * (m1.transpose() * m2), 0);

  VERIFY_EVALUATION_COUNT(( m3.block(r0,r0,r1,r1).noalias() += -m1.block(r0,c0,r1,c1) * (s2*m2.block(r0,c0,r1,c1)).adjoint() ), 0);
  VERIFY_EVALUATION_COUNT(( m3.block(r0,r0,r1,r1).noalias() -= s1 * m1.block(r0,c0,r1,c1) * m2.block(c0,r0,c1,r1) ), 0);

  // NOTE this is because the Block expression is not handled yet by our expression analyser
  VERIFY_EVALUATION_COUNT(( m3.block(r0,r0,r1,r1).noalias() = s1 * m1.block(r0,c0,r1,c1) * (s1*m2).block(c0,r0,c1,r1) ), 1);

  VERIFY_EVALUATION_COUNT( m3.noalias() -= (s1 * m1).template triangularView<LowerTriangular>() * m2, 0);
  VERIFY_EVALUATION_COUNT( rm3.noalias() = (s1 * m1.adjoint()).template triangularView<UpperTriangular>() * (m2+m2), 1);
  VERIFY_EVALUATION_COUNT( rm3.noalias() = (s1 * m1.adjoint()).template triangularView<UnitUpperTriangular>() * m2.adjoint(), 0);

  VERIFY_EVALUATION_COUNT( rm3.col(c0).noalias() = (s1 * m1.adjoint()).template triangularView<UnitUpperTriangular>() * (s2*m2.row(c0)).adjoint(), 0);

  VERIFY_EVALUATION_COUNT( m1.template triangularView<LowerTriangular>().solveInPlace(m3), 0);
  VERIFY_EVALUATION_COUNT( m1.adjoint().template triangularView<LowerTriangular>().solveInPlace(m3.transpose()), 0);

  VERIFY_EVALUATION_COUNT( m3.noalias() -= (s1 * m1).adjoint().template selfadjointView<LowerTriangular>() * (-m2*s3).adjoint(), 0);
  VERIFY_EVALUATION_COUNT( m3.noalias() = s2 * m2.adjoint() * (s1 * m1.adjoint()).template selfadjointView<UpperTriangular>(), 0);
  VERIFY_EVALUATION_COUNT( rm3.noalias() = (s1 * m1.adjoint()).template selfadjointView<LowerTriangular>() * m2.adjoint(), 0);

  VERIFY_EVALUATION_COUNT( m3.col(c0).noalias() = (s1 * m1).adjoint().template selfadjointView<LowerTriangular>() * (-m2.row(c0)*s3).adjoint(), 0);
  VERIFY_EVALUATION_COUNT( m3.col(c0).noalias() -= (s1 * m1).adjoint().template selfadjointView<UpperTriangular>() * (-m2.row(c0)*s3).adjoint(), 0);

  VERIFY_EVALUATION_COUNT( m3.block(r0,c0,r1,c1).noalias() += m1.block(r0,r0,r1,r1).template selfadjointView<UpperTriangular>() * (s1*m2.block(r0,c0,r1,c1)), 0);
  VERIFY_EVALUATION_COUNT( m3.block(r0,c0,r1,c1).noalias() = m1.block(r0,r0,r1,r1).template selfadjointView<UpperTriangular>() * m2.block(r0,c0,r1,c1), 0);

  VERIFY_EVALUATION_COUNT( m3.template selfadjointView<LowerTriangular>().rankUpdate(m2.adjoint()), 0);

  m3.resize(1,1);
  VERIFY_EVALUATION_COUNT( m3.noalias() = m1.block(r0,r0,r1,r1).template selfadjointView<LowerTriangular>() * m2.block(r0,c0,r1,c1), 0);
  m3.resize(1,1);
  VERIFY_EVALUATION_COUNT( m3.noalias() = m1.block(r0,r0,r1,r1).template triangularView<UnitUpperTriangular>()  * m2.block(r0,c0,r1,c1), 0);
}

void test_product_notemporary()
{
  int s;
  for(int i = 0; i < g_repeat; i++) {
    s = ei_random<int>(16,320);
    CALL_SUBTEST( product_notemporary(MatrixXf(s, s)) );
    s = ei_random<int>(16,120);
    CALL_SUBTEST( product_notemporary(MatrixXcd(s,s)) );
  }
}
<|endoftext|>


<commit_before>/*
    __ _____ _____ _____
 __|  |   __|     |   | |  JSON for Modern C++ (test suite)
|  |  |__   |  |  | | | |  version 2.1.1
|_____|_____|_____|_|___|  https://github.com/nlohmann/json

Licensed under the MIT License <http://opensource.org/licenses/MIT>.
Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.

Permission is hereby  granted, free of charge, to any  person obtaining a copy
of this software and associated  documentation files (the "Software"), to deal
in the Software  without restriction, including without  limitation the rights
to  use, copy,  modify, merge,  publish, distribute,  sublicense, and/or  sell
copies  of  the Software,  and  to  permit persons  to  whom  the Software  is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE  IS PROVIDED "AS  IS", WITHOUT WARRANTY  OF ANY KIND,  EXPRESS OR
IMPLIED,  INCLUDING BUT  NOT  LIMITED TO  THE  WARRANTIES OF  MERCHANTABILITY,
FITNESS FOR  A PARTICULAR PURPOSE AND  NONINFRINGEMENT. IN NO EVENT  SHALL THE
AUTHORS  OR COPYRIGHT  HOLDERS  BE  LIABLE FOR  ANY  CLAIM,  DAMAGES OR  OTHER
LIABILITY, WHETHER IN AN ACTION OF  CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE  OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

#include "catch.hpp"

#include "json.hpp"
using nlohmann::json;

TEST_CASE("algorithms")
{
    json j_array = {13, 29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz"};
    json j_object = {{"one", 1}, {"two", 2}};

    SECTION("non-modifying sequence operations")
    {
        SECTION("std::all_of")
        {
            CHECK(std::all_of(j_array.begin(), j_array.end(), [](const json & value)
            {
                return value.size() > 0;
            }));
            CHECK(std::all_of(j_object.begin(), j_object.end(), [](const json & value)
            {
                return value.type() == json::value_t::number_integer;
            }));
        }

        SECTION("std::any_of")
        {
            CHECK(std::any_of(j_array.begin(), j_array.end(), [](const json & value)
            {
                return value.is_string() and value.get<std::string>() == "foo";
            }));
            CHECK(std::any_of(j_object.begin(), j_object.end(), [](const json & value)
            {
                return value.get<int>() > 1;
            }));
        }

        SECTION("std::none_of")
        {
            CHECK(std::none_of(j_array.begin(), j_array.end(), [](const json & value)
            {
                return value.size() == 0;
            }));
            CHECK(std::none_of(j_object.begin(), j_object.end(), [](const json & value)
            {
                return value.get<int>() <= 0;
            }));
        }

        SECTION("std::for_each")
        {
            SECTION("reading")
            {
                int sum = 0;

                std::for_each(j_array.cbegin(), j_array.cend(), [&sum](const json & value)
                {
                    if (value.is_number())
                    {
                        sum += static_cast<int>(value);
                    }
                });

                CHECK(sum == 45);
            }

            SECTION("writing")
            {
                auto add17 = [](json & value)
                {
                    if (value.is_array())
                    {
                        value.push_back(17);
                    }
                };

                std::for_each(j_array.begin(), j_array.end(), add17);

                CHECK(j_array[6] == json({1, 2, 3, 17}));
            }
        }

        SECTION("std::count")
        {
            CHECK(std::count(j_array.begin(), j_array.end(), json(true)) == 1);
        }

        SECTION("std::count_if")
        {
            CHECK(std::count_if(j_array.begin(), j_array.end(), [](const json & value)
            {
                return (value.is_number());
            }) == 3);
            CHECK(std::count_if(j_array.begin(), j_array.end(), [](const json&)
            {
                return true;
            }) == 9);
        }

        SECTION("std::mismatch")
        {
            json j_array2 = {13, 29, 3, {{"one", 1}, {"two", 2}, {"three", 3}}, true, false, {1, 2, 3}, "foo", "baz"};
            auto res = std::mismatch(j_array.begin(), j_array.end(), j_array2.begin());
            CHECK(*res.first == json({{"one", 1}, {"two", 2}}));
            CHECK(*res.second == json({{"one", 1}, {"two", 2}, {"three", 3}}));
        }

        SECTION("std::equal")
        {
            SECTION("using operator==")
            {
                CHECK(std::equal(j_array.begin(), j_array.end(), j_array.begin()));
                CHECK(std::equal(j_object.begin(), j_object.end(), j_object.begin()));
                CHECK(not std::equal(j_array.begin(), j_array.end(), j_object.begin()));
            }

            SECTION("using user-defined comparison")
            {
                // compare objects only by size of its elements
                json j_array2 = {13, 29, 3, {"Hello", "World"}, true, false, {{"one", 1}, {"two", 2}, {"three", 3}}, "foo", "baz"};
                CHECK(not std::equal(j_array.begin(), j_array.end(), j_array2.begin()));
                CHECK(std::equal(j_array.begin(), j_array.end(), j_array2.begin(),
                                 [](const json & a, const json & b)
                {
                    return (a.size() == b.size());
                }));
            }
        }

        SECTION("std::find")
        {
            auto it = std::find(j_array.begin(), j_array.end(), json(false));
            CHECK(std::distance(j_array.begin(), it) == 5);
        }

        SECTION("std::find_if")
        {
            auto it = std::find_if(j_array.begin(), j_array.end(),
                                   [](const json & value)
            {
                return value.is_boolean();
            });
            CHECK(std::distance(j_array.begin(), it) == 4);
        }

        SECTION("std::find_if_not")
        {
            auto it = std::find_if_not(j_array.begin(), j_array.end(),
                                       [](const json & value)
            {
                return value.is_number();
            });
            CHECK(std::distance(j_array.begin(), it) == 3);
        }

        SECTION("std::adjacent_find")
        {
            CHECK(std::adjacent_find(j_array.begin(), j_array.end()) == j_array.end());
            CHECK(std::adjacent_find(j_array.begin(), j_array.end(),
                                     [](const json & v1, const json & v2)
            {
                return v1.type() == v2.type();
            }) == j_array.begin());
        }
    }

    SECTION("modifying sequence operations")
    {
        SECTION("std::reverse")
        {
            std::reverse(j_array.begin(), j_array.end());
            CHECK(j_array == json({"baz", "foo", {1, 2, 3}, false, true, {{"one", 1}, {"two", 2}}, 3, 29, 13}));
        }

        SECTION("std::rotate")
        {
            std::rotate(j_array.begin(), j_array.begin() + 1, j_array.end());
            CHECK(j_array == json({29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz", 13}));
        }

        SECTION("std::partition")
        {
            auto it = std::partition(j_array.begin(), j_array.end(), [](const json & v)
            {
                return v.is_string();
            });
            CHECK(std::distance(j_array.begin(), it) == 2);
            CHECK(not it[2].is_string());
        }
    }

    SECTION("sorting operations")
    {
        SECTION("std::sort")
        {
            SECTION("with standard comparison")
            {
                json j = {13, 29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz", nullptr};
                std::sort(j.begin(), j.end());
                CHECK(j == json({nullptr, false, true, 3, 13, 29, {{"one", 1}, {"two", 2}}, {1, 2, 3}, "baz", "foo"}));
            }

            SECTION("with user-defined comparison")
            {
                json j = {3, {{"one", 1}, {"two", 2}}, {1, 2, 3}, nullptr};
                std::sort(j.begin(), j.end(), [](const json & a, const json & b)
                {
                    return a.size() < b.size();
                });
                CHECK(j == json({nullptr, 3, {{"one", 1}, {"two", 2}}, {1, 2, 3}}));
            }

            SECTION("sorting an object")
            {
                json j({{"one", 1}, {"two", 2}});
                CHECK_THROWS_AS(std::sort(j.begin(), j.end()), json::invalid_iterator&);
                CHECK_THROWS_WITH(std::sort(j.begin(), j.end()),
                                  "[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
            }
        }

        SECTION("std::partial_sort")
        {
            json j = {13, 29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz", nullptr};
            std::partial_sort(j.begin(), j.begin() + 4, j.end());
            CHECK(j == json({nullptr, false, true, 3, {{"one", 1}, {"two", 2}}, 29, {1, 2, 3}, "foo", "baz", 13}));
        }
    }

    SECTION("set operations")
    {
        /*
        SECTION("std::merge")
        {
            {
                json j1 = {2, 4, 6, 8};
                json j2 = {1, 2, 3, 5, 7};
                json j3;

                std::merge(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
                CHECK(j3 == json({1, 2, 2, 3, 4, 5, 6, 7, 8}));
            }
        }
        */

        SECTION("std::set_difference")
        {
            json j1 = {1, 2, 3, 4, 5, 6, 7, 8};
            json j2 = {1, 2, 3, 5, 7};
            json j3;

            std::set_difference(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
            CHECK(j3 == json({4, 6, 8}));
        }

        SECTION("std::set_intersection")
        {
            json j1 = {1, 2, 3, 4, 5, 6, 7, 8};
            json j2 = {1, 2, 3, 5, 7};
            json j3;

            std::set_intersection(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
            CHECK(j3 == json({1, 2, 3, 5, 7}));
        }

        /*
        SECTION("std::set_union")
        {
            json j1 = {2, 4, 6, 8};
            json j2 = {1, 2, 3, 5, 7};
            json j3;

            std::set_union(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
            CHECK(j3 == json({1, 2, 3, 4, 5, 6, 7, 8}));
        }

        SECTION("std::set_symmetric_difference")
        {
            json j1 = {2, 4, 6, 8};
            json j2 = {1, 2, 3, 5, 7};
            json j3;

            std::set_symmetric_difference(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
            CHECK(j3 == json({1, 3, 4, 5, 6, 7, 8}));
        }
        */
    }

    SECTION("heap operations")
    {
        std::make_heap(j_array.begin(), j_array.end());
        CHECK(std::is_heap(j_array.begin(), j_array.end()));
        std::sort_heap(j_array.begin(), j_array.end());
        CHECK(j_array == json({false, true, 3, 13, 29, {{"one", 1}, {"two", 2}}, {1, 2, 3}, "baz", "foo"}));
    }
}
<commit_msg>:white_check_mark: re-added tests for algorithms<commit_after>/*
    __ _____ _____ _____
 __|  |   __|     |   | |  JSON for Modern C++ (test suite)
|  |  |__   |  |  | | | |  version 2.1.1
|_____|_____|_____|_|___|  https://github.com/nlohmann/json

Licensed under the MIT License <http://opensource.org/licenses/MIT>.
Copyright (c) 2013-2017 Niels Lohmann <http://nlohmann.me>.

Permission is hereby  granted, free of charge, to any  person obtaining a copy
of this software and associated  documentation files (the "Software"), to deal
in the Software  without restriction, including without  limitation the rights
to  use, copy,  modify, merge,  publish, distribute,  sublicense, and/or  sell
copies  of  the Software,  and  to  permit persons  to  whom  the Software  is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE  IS PROVIDED "AS  IS", WITHOUT WARRANTY  OF ANY KIND,  EXPRESS OR
IMPLIED,  INCLUDING BUT  NOT  LIMITED TO  THE  WARRANTIES OF  MERCHANTABILITY,
FITNESS FOR  A PARTICULAR PURPOSE AND  NONINFRINGEMENT. IN NO EVENT  SHALL THE
AUTHORS  OR COPYRIGHT  HOLDERS  BE  LIABLE FOR  ANY  CLAIM,  DAMAGES OR  OTHER
LIABILITY, WHETHER IN AN ACTION OF  CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE  OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/

#include "catch.hpp"

#include "json.hpp"
using nlohmann::json;

TEST_CASE("algorithms")
{
    json j_array = {13, 29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz"};
    json j_object = {{"one", 1}, {"two", 2}};

    SECTION("non-modifying sequence operations")
    {
        SECTION("std::all_of")
        {
            CHECK(std::all_of(j_array.begin(), j_array.end(), [](const json & value)
            {
                return value.size() > 0;
            }));
            CHECK(std::all_of(j_object.begin(), j_object.end(), [](const json & value)
            {
                return value.type() == json::value_t::number_integer;
            }));
        }

        SECTION("std::any_of")
        {
            CHECK(std::any_of(j_array.begin(), j_array.end(), [](const json & value)
            {
                return value.is_string() and value.get<std::string>() == "foo";
            }));
            CHECK(std::any_of(j_object.begin(), j_object.end(), [](const json & value)
            {
                return value.get<int>() > 1;
            }));
        }

        SECTION("std::none_of")
        {
            CHECK(std::none_of(j_array.begin(), j_array.end(), [](const json & value)
            {
                return value.size() == 0;
            }));
            CHECK(std::none_of(j_object.begin(), j_object.end(), [](const json & value)
            {
                return value.get<int>() <= 0;
            }));
        }

        SECTION("std::for_each")
        {
            SECTION("reading")
            {
                int sum = 0;

                std::for_each(j_array.cbegin(), j_array.cend(), [&sum](const json & value)
                {
                    if (value.is_number())
                    {
                        sum += static_cast<int>(value);
                    }
                });

                CHECK(sum == 45);
            }

            SECTION("writing")
            {
                auto add17 = [](json & value)
                {
                    if (value.is_array())
                    {
                        value.push_back(17);
                    }
                };

                std::for_each(j_array.begin(), j_array.end(), add17);

                CHECK(j_array[6] == json({1, 2, 3, 17}));
            }
        }

        SECTION("std::count")
        {
            CHECK(std::count(j_array.begin(), j_array.end(), json(true)) == 1);
        }

        SECTION("std::count_if")
        {
            CHECK(std::count_if(j_array.begin(), j_array.end(), [](const json & value)
            {
                return (value.is_number());
            }) == 3);
            CHECK(std::count_if(j_array.begin(), j_array.end(), [](const json&)
            {
                return true;
            }) == 9);
        }

        SECTION("std::mismatch")
        {
            json j_array2 = {13, 29, 3, {{"one", 1}, {"two", 2}, {"three", 3}}, true, false, {1, 2, 3}, "foo", "baz"};
            auto res = std::mismatch(j_array.begin(), j_array.end(), j_array2.begin());
            CHECK(*res.first == json({{"one", 1}, {"two", 2}}));
            CHECK(*res.second == json({{"one", 1}, {"two", 2}, {"three", 3}}));
        }

        SECTION("std::equal")
        {
            SECTION("using operator==")
            {
                CHECK(std::equal(j_array.begin(), j_array.end(), j_array.begin()));
                CHECK(std::equal(j_object.begin(), j_object.end(), j_object.begin()));
                CHECK(not std::equal(j_array.begin(), j_array.end(), j_object.begin()));
            }

            SECTION("using user-defined comparison")
            {
                // compare objects only by size of its elements
                json j_array2 = {13, 29, 3, {"Hello", "World"}, true, false, {{"one", 1}, {"two", 2}, {"three", 3}}, "foo", "baz"};
                CHECK(not std::equal(j_array.begin(), j_array.end(), j_array2.begin()));
                CHECK(std::equal(j_array.begin(), j_array.end(), j_array2.begin(),
                                 [](const json & a, const json & b)
                {
                    return (a.size() == b.size());
                }));
            }
        }

        SECTION("std::find")
        {
            auto it = std::find(j_array.begin(), j_array.end(), json(false));
            CHECK(std::distance(j_array.begin(), it) == 5);
        }

        SECTION("std::find_if")
        {
            auto it = std::find_if(j_array.begin(), j_array.end(),
                                   [](const json & value)
            {
                return value.is_boolean();
            });
            CHECK(std::distance(j_array.begin(), it) == 4);
        }

        SECTION("std::find_if_not")
        {
            auto it = std::find_if_not(j_array.begin(), j_array.end(),
                                       [](const json & value)
            {
                return value.is_number();
            });
            CHECK(std::distance(j_array.begin(), it) == 3);
        }

        SECTION("std::adjacent_find")
        {
            CHECK(std::adjacent_find(j_array.begin(), j_array.end()) == j_array.end());
            CHECK(std::adjacent_find(j_array.begin(), j_array.end(),
                                     [](const json & v1, const json & v2)
            {
                return v1.type() == v2.type();
            }) == j_array.begin());
        }
    }

    SECTION("modifying sequence operations")
    {
        SECTION("std::reverse")
        {
            std::reverse(j_array.begin(), j_array.end());
            CHECK(j_array == json({"baz", "foo", {1, 2, 3}, false, true, {{"one", 1}, {"two", 2}}, 3, 29, 13}));
        }

        SECTION("std::rotate")
        {
            std::rotate(j_array.begin(), j_array.begin() + 1, j_array.end());
            CHECK(j_array == json({29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz", 13}));
        }

        SECTION("std::partition")
        {
            auto it = std::partition(j_array.begin(), j_array.end(), [](const json & v)
            {
                return v.is_string();
            });
            CHECK(std::distance(j_array.begin(), it) == 2);
            CHECK(not it[2].is_string());
        }
    }

    SECTION("sorting operations")
    {
        SECTION("std::sort")
        {
            SECTION("with standard comparison")
            {
                json j = {13, 29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz", nullptr};
                std::sort(j.begin(), j.end());
                CHECK(j == json({nullptr, false, true, 3, 13, 29, {{"one", 1}, {"two", 2}}, {1, 2, 3}, "baz", "foo"}));
            }

            SECTION("with user-defined comparison")
            {
                json j = {3, {{"one", 1}, {"two", 2}}, {1, 2, 3}, nullptr};
                std::sort(j.begin(), j.end(), [](const json & a, const json & b)
                {
                    return a.size() < b.size();
                });
                CHECK(j == json({nullptr, 3, {{"one", 1}, {"two", 2}}, {1, 2, 3}}));
            }

            SECTION("sorting an object")
            {
                json j({{"one", 1}, {"two", 2}});
                CHECK_THROWS_AS(std::sort(j.begin(), j.end()), json::invalid_iterator&);
                CHECK_THROWS_WITH(std::sort(j.begin(), j.end()),
                                  "[json.exception.invalid_iterator.209] cannot use offsets with object iterators");
            }
        }

        SECTION("std::partial_sort")
        {
            json j = {13, 29, 3, {{"one", 1}, {"two", 2}}, true, false, {1, 2, 3}, "foo", "baz", nullptr};
            std::partial_sort(j.begin(), j.begin() + 4, j.end());
            CHECK(j == json({nullptr, false, true, 3, {{"one", 1}, {"two", 2}}, 29, {1, 2, 3}, "foo", "baz", 13}));
        }
    }

    SECTION("set operations")
    {
        SECTION("std::merge")
        {
            {
                json j1 = {2, 4, 6, 8};
                json j2 = {1, 2, 3, 5, 7};
                json j3;

                std::merge(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
                CHECK(j3 == json({1, 2, 2, 3, 4, 5, 6, 7, 8}));
            }
        }

        SECTION("std::set_difference")
        {
            json j1 = {1, 2, 3, 4, 5, 6, 7, 8};
            json j2 = {1, 2, 3, 5, 7};
            json j3;

            std::set_difference(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
            CHECK(j3 == json({4, 6, 8}));
        }

        SECTION("std::set_intersection")
        {
            json j1 = {1, 2, 3, 4, 5, 6, 7, 8};
            json j2 = {1, 2, 3, 5, 7};
            json j3;

            std::set_intersection(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
            CHECK(j3 == json({1, 2, 3, 5, 7}));
        }

        SECTION("std::set_union")
        {
            json j1 = {2, 4, 6, 8};
            json j2 = {1, 2, 3, 5, 7};
            json j3;

            std::set_union(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
            CHECK(j3 == json({1, 2, 3, 4, 5, 6, 7, 8}));
        }

        SECTION("std::set_symmetric_difference")
        {
            json j1 = {2, 4, 6, 8};
            json j2 = {1, 2, 3, 5, 7};
            json j3;

            std::set_symmetric_difference(j1.begin(), j1.end(), j2.begin(), j2.end(), std::back_inserter(j3));
            CHECK(j3 == json({1, 3, 4, 5, 6, 7, 8}));
        }
    }

    SECTION("heap operations")
    {
        std::make_heap(j_array.begin(), j_array.end());
        CHECK(std::is_heap(j_array.begin(), j_array.end()));
        std::sort_heap(j_array.begin(), j_array.end());
        CHECK(j_array == json({false, true, 3, 13, 29, {{"one", 1}, {"two", 2}}, {1, 2, 3}, "baz", "foo"}));
    }
}
<|endoftext|>


<commit_before>/*
 *  Copyright (c) 2016 The WebM project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <limits>

#include "third_party/googletest/src/include/gtest/gtest.h"

#include "./vp9_rtcd.h"
#include "test/acm_random.h"
#include "test/buffer.h"
#include "test/register_state_check.h"
#include "vpx_ports/vpx_timer.h"

namespace {

using ::libvpx_test::ACMRandom;
using ::libvpx_test::Buffer;

typedef void (*TemporalFilterFunc)(const uint8_t *a, unsigned int stride,
                                   const uint8_t *b, unsigned int w,
                                   unsigned int h, int filter_strength,
                                   int filter_weight, unsigned int *accumulator,
                                   uint16_t *count);

// Calculate the difference between 'a' and 'b', sum in blocks of 9, and apply
// filter based on strength and weight. Store the resulting filter amount in
// 'count' and apply it to 'b' and store it in 'accumulator'.
void reference_filter(const Buffer<uint8_t> &a, const Buffer<uint8_t> &b, int w,
                      int h, int filter_strength, int filter_weight,
                      Buffer<unsigned int> *accumulator,
                      Buffer<uint16_t> *count) {
  Buffer<int> diff_sq = Buffer<int>(w, h, 0);
  ASSERT_TRUE(diff_sq.Init());
  diff_sq.Set(0);

  int rounding = 0;
  if (filter_strength > 0) {
    rounding = 1 << (filter_strength - 1);
  }

  // Calculate all the differences. Avoids re-calculating a bunch of extra
  // values.
  for (int height = 0; height < h; ++height) {
    for (int width = 0; width < w; ++width) {
      int diff = a.TopLeftPixel()[height * a.stride() + width] -
                 b.TopLeftPixel()[height * b.stride() + width];
      diff_sq.TopLeftPixel()[height * diff_sq.stride() + width] = diff * diff;
    }
  }

  // For any given point, sum the neighboring values and calculate the
  // modifier.
  for (int height = 0; height < h; ++height) {
    for (int width = 0; width < w; ++width) {
      // Determine how many values are being summed.
      int summed_values = 9;

      if (height == 0 || height == (h - 1)) {
        summed_values -= 3;
      }

      if (width == 0 || width == (w - 1)) {
        if (summed_values == 6) {  // corner
          summed_values -= 2;
        } else {
          summed_values -= 3;
        }
      }

      // Sum the diff_sq of the surrounding values.
      int sum = 0;
      for (int idy = -1; idy <= 1; ++idy) {
        for (int idx = -1; idx <= 1; ++idx) {
          const int y = height + idy;
          const int x = width + idx;

          // If inside the border.
          if (y >= 0 && y < h && x >= 0 && x < w) {
            sum += diff_sq.TopLeftPixel()[y * diff_sq.stride() + x];
          }
        }
      }

      sum *= 3;
      sum /= summed_values;
      sum += rounding;
      sum >>= filter_strength;

      // Clamp the value and invert it.
      if (sum > 16) sum = 16;
      sum = 16 - sum;

      sum *= filter_weight;

      count->TopLeftPixel()[height * count->stride() + width] += sum;
      accumulator->TopLeftPixel()[height * accumulator->stride() + width] +=
          sum * b.TopLeftPixel()[height * b.stride() + width];
    }
  }
}

class TemporalFilterTest : public ::testing::TestWithParam<TemporalFilterFunc> {
 public:
  virtual void SetUp() {
    filter_func_ = GetParam();
    rnd_.Reset(ACMRandom::DeterministicSeed());
  }

 protected:
  TemporalFilterFunc filter_func_;
  ACMRandom rnd_;
};

TEST_P(TemporalFilterTest, SizeCombinations) {
  // Depending on subsampling this function may be called with values of 8 or 16
  // for width and height, in any combination.
  Buffer<uint8_t> a = Buffer<uint8_t>(16, 16, 8);
  ASSERT_TRUE(a.Init());

  const int filter_weight = 2;
  const int filter_strength = 6;

  for (int width = 8; width <= 16; width += 8) {
    for (int height = 8; height <= 16; height += 8) {
      // The second buffer must not have any border.
      Buffer<uint8_t> b = Buffer<uint8_t>(width, height, 0);
      ASSERT_TRUE(b.Init());
      Buffer<unsigned int> accum_ref = Buffer<unsigned int>(width, height, 0);
      ASSERT_TRUE(accum_ref.Init());
      Buffer<unsigned int> accum_chk = Buffer<unsigned int>(width, height, 0);
      ASSERT_TRUE(accum_chk.Init());
      Buffer<uint16_t> count_ref = Buffer<uint16_t>(width, height, 0);
      ASSERT_TRUE(count_ref.Init());
      Buffer<uint16_t> count_chk = Buffer<uint16_t>(width, height, 0);
      ASSERT_TRUE(count_chk.Init());

      // The difference between the buffers must be small to pass the threshold
      // to apply the filter.
      a.Set(&rnd_, 0, 7);
      b.Set(&rnd_, 0, 7);

      accum_ref.Set(rnd_.Rand8());
      accum_chk.CopyFrom(accum_ref);
      count_ref.Set(rnd_.Rand8());
      count_chk.CopyFrom(count_ref);
      reference_filter(a, b, width, height, filter_strength, filter_weight,
                       &accum_ref, &count_ref);
      ASM_REGISTER_STATE_CHECK(
          filter_func_(a.TopLeftPixel(), a.stride(), b.TopLeftPixel(), width,
                       height, filter_strength, filter_weight,
                       accum_chk.TopLeftPixel(), count_chk.TopLeftPixel()));
      EXPECT_TRUE(accum_chk.CheckValues(accum_ref));
      EXPECT_TRUE(count_chk.CheckValues(count_ref));
      if (HasFailure()) {
        printf("Width: %d Height: %d\n", width, height);
        count_chk.PrintDifference(count_ref);
        accum_chk.PrintDifference(accum_ref);
        return;
      }
    }
  }
}

TEST_P(TemporalFilterTest, CompareReferenceRandom) {
  for (int width = 8; width <= 16; width += 8) {
    for (int height = 8; height <= 16; height += 8) {
      Buffer<uint8_t> a = Buffer<uint8_t>(width, height, 8);
      ASSERT_TRUE(a.Init());
      // The second buffer must not have any border.
      Buffer<uint8_t> b = Buffer<uint8_t>(width, height, 0);
      ASSERT_TRUE(b.Init());
      Buffer<unsigned int> accum_ref = Buffer<unsigned int>(width, height, 0);
      ASSERT_TRUE(accum_ref.Init());
      Buffer<unsigned int> accum_chk = Buffer<unsigned int>(width, height, 0);
      ASSERT_TRUE(accum_chk.Init());
      Buffer<uint16_t> count_ref = Buffer<uint16_t>(width, height, 0);
      ASSERT_TRUE(count_ref.Init());
      Buffer<uint16_t> count_chk = Buffer<uint16_t>(width, height, 0);
      ASSERT_TRUE(count_chk.Init());

      for (int filter_strength = 0; filter_strength <= 6; ++filter_strength) {
        for (int filter_weight = 0; filter_weight <= 2; ++filter_weight) {
          for (int repeat = 0; repeat < 100; ++repeat) {
            if (repeat < 50) {
              a.Set(&rnd_, 0, 7);
              b.Set(&rnd_, 0, 7);
            } else {
              // Check large (but close) values as well.
              a.Set(&rnd_, std::numeric_limits<uint8_t>::max() - 7,
                    std::numeric_limits<uint8_t>::max());
              b.Set(&rnd_, std::numeric_limits<uint8_t>::max() - 7,
                    std::numeric_limits<uint8_t>::max());
            }

            accum_ref.Set(rnd_.Rand8());
            accum_chk.CopyFrom(accum_ref);
            count_ref.Set(rnd_.Rand8());
            count_chk.CopyFrom(count_ref);
            reference_filter(a, b, width, height, filter_strength,
                             filter_weight, &accum_ref, &count_ref);
            ASM_REGISTER_STATE_CHECK(filter_func_(
                a.TopLeftPixel(), a.stride(), b.TopLeftPixel(), width, height,
                filter_strength, filter_weight, accum_chk.TopLeftPixel(),
                count_chk.TopLeftPixel()));
            EXPECT_TRUE(accum_chk.CheckValues(accum_ref));
            EXPECT_TRUE(count_chk.CheckValues(count_ref));
            if (HasFailure()) {
              printf("Weight: %d Strength: %d\n", filter_weight,
                     filter_strength);
              count_chk.PrintDifference(count_ref);
              accum_chk.PrintDifference(accum_ref);
              return;
            }
          }
        }
      }
    }
  }
}

TEST_P(TemporalFilterTest, DISABLED_Speed) {
  Buffer<uint8_t> a = Buffer<uint8_t>(16, 16, 8);
  ASSERT_TRUE(a.Init());

  const int filter_weight = 2;
  const int filter_strength = 6;

  for (int width = 8; width <= 16; width += 8) {
    for (int height = 8; height <= 16; height += 8) {
      // The second buffer must not have any border.
      Buffer<uint8_t> b = Buffer<uint8_t>(width, height, 0);
      ASSERT_TRUE(b.Init());
      Buffer<unsigned int> accum_ref = Buffer<unsigned int>(width, height, 0);
      ASSERT_TRUE(accum_ref.Init());
      Buffer<unsigned int> accum_chk = Buffer<unsigned int>(width, height, 0);
      ASSERT_TRUE(accum_chk.Init());
      Buffer<uint16_t> count_ref = Buffer<uint16_t>(width, height, 0);
      ASSERT_TRUE(count_ref.Init());
      Buffer<uint16_t> count_chk = Buffer<uint16_t>(width, height, 0);
      ASSERT_TRUE(count_chk.Init());

      a.Set(&rnd_, 0, 7);
      b.Set(&rnd_, 0, 7);

      accum_chk.Set(0);
      count_chk.Set(0);

      vpx_usec_timer timer;
      vpx_usec_timer_start(&timer);
      for (int i = 0; i < 10000; ++i) {
        filter_func_(a.TopLeftPixel(), a.stride(), b.TopLeftPixel(), width,
                     height, filter_strength, filter_weight,
                     accum_chk.TopLeftPixel(), count_chk.TopLeftPixel());
      }
      vpx_usec_timer_mark(&timer);
      const int elapsed_time = static_cast<int>(vpx_usec_timer_elapsed(&timer));
      printf("Temporal filter %dx%d time: %5d us\n", width, height,
             elapsed_time);
    }
  }
}

INSTANTIATE_TEST_CASE_P(C, TemporalFilterTest,
                        ::testing::Values(&vp9_temporal_filter_apply_c));

#if HAVE_SSE4_1
INSTANTIATE_TEST_CASE_P(SSE4_1, TemporalFilterTest,
                        ::testing::Values(&vp9_temporal_filter_apply_sse4_1));
#endif  // HAVE_SSE4_1
}  // namespace
<commit_msg>Fix scan_build warnings in temporal_filter_test.cc<commit_after>/*
 *  Copyright (c) 2016 The WebM project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include <limits>

#include "third_party/googletest/src/include/gtest/gtest.h"

#include "./vp9_rtcd.h"
#include "test/acm_random.h"
#include "test/buffer.h"
#include "test/register_state_check.h"
#include "vpx_ports/vpx_timer.h"

namespace {

using ::libvpx_test::ACMRandom;
using ::libvpx_test::Buffer;

typedef void (*TemporalFilterFunc)(const uint8_t *a, unsigned int stride,
                                   const uint8_t *b, unsigned int w,
                                   unsigned int h, int filter_strength,
                                   int filter_weight, unsigned int *accumulator,
                                   uint16_t *count);

// Calculate the difference between 'a' and 'b', sum in blocks of 9, and apply
// filter based on strength and weight. Store the resulting filter amount in
// 'count' and apply it to 'b' and store it in 'accumulator'.
void reference_filter(const Buffer<uint8_t> &a, const Buffer<uint8_t> &b, int w,
                      int h, int filter_strength, int filter_weight,
                      Buffer<unsigned int> *accumulator,
                      Buffer<uint16_t> *count) {
  Buffer<int> diff_sq = Buffer<int>(w, h, 0);
  ASSERT_TRUE(diff_sq.Init());
  diff_sq.Set(0);

  int rounding = 0;
  if (filter_strength > 0) {
    rounding = 1 << (filter_strength - 1);
  }

  if (a.TopLeftPixel() == NULL || b.TopLeftPixel() == NULL ||
      diff_sq.TopLeftPixel() == NULL) {
    assert(0);
    return;
  }
  // Calculate all the differences. Avoids re-calculating a bunch of extra
  // values.
  for (int height = 0; height < h; ++height) {
    for (int width = 0; width < w; ++width) {
      int diff = a.TopLeftPixel()[height * a.stride() + width] -
                 b.TopLeftPixel()[height * b.stride() + width];
      diff_sq.TopLeftPixel()[height * diff_sq.stride() + width] = diff * diff;
    }
  }

  // For any given point, sum the neighboring values and calculate the
  // modifier.
  for (int height = 0; height < h; ++height) {
    for (int width = 0; width < w; ++width) {
      // Determine how many values are being summed.
      int summed_values = 9;

      if (height == 0 || height == (h - 1)) {
        summed_values -= 3;
      }

      if (width == 0 || width == (w - 1)) {
        if (summed_values == 6) {  // corner
          summed_values -= 2;
        } else {
          summed_values -= 3;
        }
      }

      // Sum the diff_sq of the surrounding values.
      int sum = 0;
      for (int idy = -1; idy <= 1; ++idy) {
        for (int idx = -1; idx <= 1; ++idx) {
          const int y = height + idy;
          const int x = width + idx;

          // If inside the border.
          if (y >= 0 && y < h && x >= 0 && x < w) {
            sum += diff_sq.TopLeftPixel()[y * diff_sq.stride() + x];
          }
        }
      }

      sum *= 3;
      sum /= summed_values;
      sum += rounding;
      sum >>= filter_strength;

      // Clamp the value and invert it.
      if (sum > 16) sum = 16;
      sum = 16 - sum;

      sum *= filter_weight;

      count->TopLeftPixel()[height * count->stride() + width] += sum;
      accumulator->TopLeftPixel()[height * accumulator->stride() + width] +=
          sum * b.TopLeftPixel()[height * b.stride() + width];
    }
  }
}

class TemporalFilterTest : public ::testing::TestWithParam<TemporalFilterFunc> {
 public:
  virtual void SetUp() {
    filter_func_ = GetParam();
    rnd_.Reset(ACMRandom::DeterministicSeed());
  }

 protected:
  TemporalFilterFunc filter_func_;
  ACMRandom rnd_;
};

TEST_P(TemporalFilterTest, SizeCombinations) {
  // Depending on subsampling this function may be called with values of 8 or 16
  // for width and height, in any combination.
  Buffer<uint8_t> a = Buffer<uint8_t>(16, 16, 8);
  ASSERT_TRUE(a.Init());

  const int filter_weight = 2;
  const int filter_strength = 6;

  for (int width = 8; width <= 16; width += 8) {
    for (int height = 8; height <= 16; height += 8) {
      // The second buffer must not have any border.
      Buffer<uint8_t> b = Buffer<uint8_t>(width, height, 0);
      ASSERT_TRUE(b.Init());
      Buffer<unsigned int> accum_ref = Buffer<unsigned int>(width, height, 0);
      ASSERT_TRUE(accum_ref.Init());
      Buffer<unsigned int> accum_chk = Buffer<unsigned int>(width, height, 0);
      ASSERT_TRUE(accum_chk.Init());
      Buffer<uint16_t> count_ref = Buffer<uint16_t>(width, height, 0);
      ASSERT_TRUE(count_ref.Init());
      Buffer<uint16_t> count_chk = Buffer<uint16_t>(width, height, 0);
      ASSERT_TRUE(count_chk.Init());

      // The difference between the buffers must be small to pass the threshold
      // to apply the filter.
      a.Set(&rnd_, 0, 7);
      b.Set(&rnd_, 0, 7);

      accum_ref.Set(rnd_.Rand8());
      accum_chk.CopyFrom(accum_ref);
      count_ref.Set(rnd_.Rand8());
      count_chk.CopyFrom(count_ref);
      reference_filter(a, b, width, height, filter_strength, filter_weight,
                       &accum_ref, &count_ref);
      ASM_REGISTER_STATE_CHECK(
          filter_func_(a.TopLeftPixel(), a.stride(), b.TopLeftPixel(), width,
                       height, filter_strength, filter_weight,
                       accum_chk.TopLeftPixel(), count_chk.TopLeftPixel()));
      EXPECT_TRUE(accum_chk.CheckValues(accum_ref));
      EXPECT_TRUE(count_chk.CheckValues(count_ref));
      if (HasFailure()) {
        printf("Width: %d Height: %d\n", width, height);
        count_chk.PrintDifference(count_ref);
        accum_chk.PrintDifference(accum_ref);
        return;
      }
    }
  }
}

TEST_P(TemporalFilterTest, CompareReferenceRandom) {
  for (int width = 8; width <= 16; width += 8) {
    for (int height = 8; height <= 16; height += 8) {
      Buffer<uint8_t> a = Buffer<uint8_t>(width, height, 8);
      ASSERT_TRUE(a.Init());
      // The second buffer must not have any border.
      Buffer<uint8_t> b = Buffer<uint8_t>(width, height, 0);
      ASSERT_TRUE(b.Init());
      Buffer<unsigned int> accum_ref = Buffer<unsigned int>(width, height, 0);
      ASSERT_TRUE(accum_ref.Init());
      Buffer<unsigned int> accum_chk = Buffer<unsigned int>(width, height, 0);
      ASSERT_TRUE(accum_chk.Init());
      Buffer<uint16_t> count_ref = Buffer<uint16_t>(width, height, 0);
      ASSERT_TRUE(count_ref.Init());
      Buffer<uint16_t> count_chk = Buffer<uint16_t>(width, height, 0);
      ASSERT_TRUE(count_chk.Init());

      for (int filter_strength = 0; filter_strength <= 6; ++filter_strength) {
        for (int filter_weight = 0; filter_weight <= 2; ++filter_weight) {
          for (int repeat = 0; repeat < 100; ++repeat) {
            if (repeat < 50) {
              a.Set(&rnd_, 0, 7);
              b.Set(&rnd_, 0, 7);
            } else {
              // Check large (but close) values as well.
              a.Set(&rnd_, std::numeric_limits<uint8_t>::max() - 7,
                    std::numeric_limits<uint8_t>::max());
              b.Set(&rnd_, std::numeric_limits<uint8_t>::max() - 7,
                    std::numeric_limits<uint8_t>::max());
            }

            accum_ref.Set(rnd_.Rand8());
            accum_chk.CopyFrom(accum_ref);
            count_ref.Set(rnd_.Rand8());
            count_chk.CopyFrom(count_ref);
            reference_filter(a, b, width, height, filter_strength,
                             filter_weight, &accum_ref, &count_ref);
            ASM_REGISTER_STATE_CHECK(filter_func_(
                a.TopLeftPixel(), a.stride(), b.TopLeftPixel(), width, height,
                filter_strength, filter_weight, accum_chk.TopLeftPixel(),
                count_chk.TopLeftPixel()));
            EXPECT_TRUE(accum_chk.CheckValues(accum_ref));
            EXPECT_TRUE(count_chk.CheckValues(count_ref));
            if (HasFailure()) {
              printf("Weight: %d Strength: %d\n", filter_weight,
                     filter_strength);
              count_chk.PrintDifference(count_ref);
              accum_chk.PrintDifference(accum_ref);
              return;
            }
          }
        }
      }
    }
  }
}

TEST_P(TemporalFilterTest, DISABLED_Speed) {
  Buffer<uint8_t> a = Buffer<uint8_t>(16, 16, 8);
  ASSERT_TRUE(a.Init());

  const int filter_weight = 2;
  const int filter_strength = 6;

  for (int width = 8; width <= 16; width += 8) {
    for (int height = 8; height <= 16; height += 8) {
      // The second buffer must not have any border.
      Buffer<uint8_t> b = Buffer<uint8_t>(width, height, 0);
      ASSERT_TRUE(b.Init());
      Buffer<unsigned int> accum_ref = Buffer<unsigned int>(width, height, 0);
      ASSERT_TRUE(accum_ref.Init());
      Buffer<unsigned int> accum_chk = Buffer<unsigned int>(width, height, 0);
      ASSERT_TRUE(accum_chk.Init());
      Buffer<uint16_t> count_ref = Buffer<uint16_t>(width, height, 0);
      ASSERT_TRUE(count_ref.Init());
      Buffer<uint16_t> count_chk = Buffer<uint16_t>(width, height, 0);
      ASSERT_TRUE(count_chk.Init());

      a.Set(&rnd_, 0, 7);
      b.Set(&rnd_, 0, 7);

      accum_chk.Set(0);
      count_chk.Set(0);

      vpx_usec_timer timer;
      vpx_usec_timer_start(&timer);
      for (int i = 0; i < 10000; ++i) {
        filter_func_(a.TopLeftPixel(), a.stride(), b.TopLeftPixel(), width,
                     height, filter_strength, filter_weight,
                     accum_chk.TopLeftPixel(), count_chk.TopLeftPixel());
      }
      vpx_usec_timer_mark(&timer);
      const int elapsed_time = static_cast<int>(vpx_usec_timer_elapsed(&timer));
      printf("Temporal filter %dx%d time: %5d us\n", width, height,
             elapsed_time);
    }
  }
}

INSTANTIATE_TEST_CASE_P(C, TemporalFilterTest,
                        ::testing::Values(&vp9_temporal_filter_apply_c));

#if HAVE_SSE4_1
INSTANTIATE_TEST_CASE_P(SSE4_1, TemporalFilterTest,
                        ::testing::Values(&vp9_temporal_filter_apply_sse4_1));
#endif  // HAVE_SSE4_1
}  // namespace
<|endoftext|>


<commit_before>// $flisboac 2017-08-13
#include "adl_catch.hpp"
#include "adl/timer.hpp"

#include <cstdlib>
#include <chrono>

template <typename TimerHandleType>
static void payload(std::size_t passes_count, TimerHandleType && timer_handle) {
    for (std::size_t idx = 0; idx < passes_count; ++idx) {
        int i = std::rand() % 100;
        i = (i * 8) + 1337;
        i = (i / 2) - 3;
        i = (i * 8) + 32417;
        i = (i / 2) - 5;
        i = (i * 8) + 74348029;
        i = (i / 2) - 7;
    }
}

template <typename DurationType>
static double ms(DurationType duration) {
    return std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
}

static void execute() {
    constexpr const int global_passes = 1000;
    constexpr const int function_passes = 100000;

    adl::average_timer handler_timer;
    for (int i = 0; i < global_passes; ++i) {
        payload(function_passes, handler_timer.run());
    }
    WARN("Moving handler - Passes: " << handler_timer.run_count() << ", average time: " << ms(handler_timer.average()));

    adl::average_timer exec_timer;
    for (int i = 0; i < global_passes; ++i) {
        exec_timer.run([=] { payload(function_passes, 0); });
    }
    WARN("Lambda - Passes: " << exec_timer.run_count() << ", average time: " << ms(exec_timer.average()));

    adl::average_timer local_timer;
    for (int i = 0; i < global_passes; ++i) {
        auto local_timer_handle = local_timer.run();
        payload(function_passes, 0);
    }
    WARN("Local handle - Passes: " << local_timer.run_count() << ", average time: " << ms(local_timer.average()));

    adl::average_timer all_timer;
    auto all_timer_handle = all_timer.run();
    for (int i = 0; i < global_passes; ++i) {
        payload(function_passes, 0);
    }
    all_timer_handle.stop();
    WARN("Outside - average time: " << ms(all_timer_handle.duration() / global_passes));

    using namespace adl;
    adl::static_mark_timer<4> mark_timer;
    for (std::size_t i = mark_timer.size(); i < mark_timer.max_size() - 1; ++i) {
        mark_timer.mark();
        for (int i = 0; i < global_passes; ++i) {
            payload(function_passes, 0);
        }
    }
    mark_timer.mark();
    WARN("Mark - timings: " << ms(mark_timer.time(0)) << ", " << ms(mark_timer.time(1)) << ", " << ms(mark_timer.time(2)));
}

TEST_CASE("unit:adl/timer", "[adl][unit]") {
    //execute();
}
<commit_msg>Removed <cstdlib> usage<commit_after>// $flisboac 2017-08-13
#include "adl_catch.hpp"
#include "adl/timer.hpp"

#include <random>
#include <chrono>

static int random_num() {
    std::random_device rd;
    std::mt19937 g{ rd() };
    std::uniform_int_distribution<int> gen{ 0, 65575 };
    return gen(g);
}

template <typename TimerHandleType>
static void payload(std::size_t passes_count, TimerHandleType && timer_handle) {
    for (std::size_t idx = 0; idx < passes_count; ++idx) {
        int i = random_num() % 100;
        i = (i * 8) + 1337;
        i = (i / 2) - 3;
        i = (i * 8) + 32417;
        i = (i / 2) - 5;
        i = (i * 8) + 74348029;
        i = (i / 2) - 7;
    }
}

template <typename DurationType>
static double ms(DurationType duration) {
    return std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
}

static void execute() {
    constexpr const int global_passes = 1000;
    constexpr const int function_passes = 100000;

    adl::average_timer handler_timer;
    for (int i = 0; i < global_passes; ++i) {
        payload(function_passes, handler_timer.run());
    }
    WARN("Moving handler - Passes: " << handler_timer.run_count() << ", average time: " << ms(handler_timer.average()));

    adl::average_timer exec_timer;
    for (int i = 0; i < global_passes; ++i) {
        exec_timer.run([=] { payload(function_passes, 0); });
    }
    WARN("Lambda - Passes: " << exec_timer.run_count() << ", average time: " << ms(exec_timer.average()));

    adl::average_timer local_timer;
    for (int i = 0; i < global_passes; ++i) {
        auto local_timer_handle = local_timer.run();
        payload(function_passes, 0);
    }
    WARN("Local handle - Passes: " << local_timer.run_count() << ", average time: " << ms(local_timer.average()));

    adl::average_timer all_timer;
    auto all_timer_handle = all_timer.run();
    for (int i = 0; i < global_passes; ++i) {
        payload(function_passes, 0);
    }
    all_timer_handle.stop();
    WARN("Outside - average time: " << ms(all_timer_handle.duration() / global_passes));

    using namespace adl;
    adl::static_mark_timer<4> mark_timer;
    for (std::size_t i = mark_timer.size(); i < mark_timer.max_size() - 1; ++i) {
        mark_timer.mark();
        for (int i = 0; i < global_passes; ++i) {
            payload(function_passes, 0);
        }
    }
    mark_timer.mark();
    WARN("Mark - timings: " << ms(mark_timer.time(0)) << ", " << ms(mark_timer.time(1)) << ", " << ms(mark_timer.time(2)));
}

TEST_CASE("unit:adl/timer", "[adl][unit]") {
    //execute();
}
<|endoftext|>