<commit_before>/**
 * Copyright © 2016 IBM Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "../manager.hpp"
#include "../config.h"
#include <cassert>
#include <iostream>
#include <algorithm>
#include <thread>

constexpr auto SERVICE = "phosphor.inventory.test";
constexpr auto INTERFACE = IFACE;
constexpr auto ROOT = "/testing/inventory";

/** @class SignalQueue
 *  @brief Store DBus signals in a queue.
 */
class SignalQueue
{
    public:
        ~SignalQueue() = default;
        SignalQueue() = delete;
        SignalQueue(const SignalQueue&) = delete;
        SignalQueue(SignalQueue&&) = default;
        SignalQueue& operator=(const SignalQueue&) = delete;
        SignalQueue& operator=(SignalQueue&&) = default;
        explicit SignalQueue(const std::string& match) :
            _bus(sdbusplus::bus::new_default()),
            _match(_bus, match.c_str(), &callback, this),
            _next(nullptr)
        {
        }

        auto&& pop(unsigned timeout = 1000000)
        {
            while (timeout > 0 && !_next)
            {
                _bus.process_discard();
                _bus.wait(50000);
                timeout -= 50000;
            }
            return std::move(_next);
        }

    private:
        static int callback(sd_bus_message* m, void* context, sd_bus_error*)
        {
            auto* me = static_cast<SignalQueue*>(context);
            sd_bus_message_ref(m);
            sdbusplus::message::message msg{m};
            me->_next = std::move(msg);
            return 0;
        }

        sdbusplus::bus::bus _bus;
        sdbusplus::server::match::match _match;
        sdbusplus::message::message _next;
};

template <typename ...T>
using Object = std::map <
               std::string,
               std::map <
               std::string,
               sdbusplus::message::variant<T... >>>;

/**@brief Find a subset of interfaces and properties in an object. */
template <typename ...T>
auto hasProperties(const Object<T...>& l, const Object<T...>& r)
{
    Object<T...> result;
    std::set_difference(
        r.cbegin(),
        r.cend(),
        l.cbegin(),
        l.cend(),
        std::inserter(result, result.end()));
    return result.empty();
}

/**@brief Check an object for one or more interfaces. */
template <typename ...T>
auto hasInterfaces(const std::vector<std::string>& l, const Object<T...>& r)
{
    std::vector<std::string> stripped, interfaces;
    std::transform(
        r.cbegin(),
        r.cend(),
        std::back_inserter(stripped),
        [](auto & p)
    {
        return p.first;
    });
    std::set_difference(
        stripped.cbegin(),
        stripped.cend(),
        l.cbegin(),
        l.cend(),
        std::back_inserter(interfaces));
    return interfaces.empty();
}

void runTests(phosphor::inventory::manager::Manager& mgr)
{
    const std::string root{ROOT};
    auto b = sdbusplus::bus::new_default();
    auto notify = [&]()
    {
        return b.new_method_call(
                   SERVICE,
                   ROOT,
                   INTERFACE,
                   "Notify");
    };
    auto set = [&](const std::string & path)
    {
        return b.new_method_call(
                   SERVICE,
                   path.c_str(),
                   "org.freedesktop.DBus.Properties",
                   "Set");
    };

    Object<std::string> obj
    {
        {
            "xyz.openbmc_project.Example.Iface1",
            {{"ExampleProperty1", "test1"}}
        },
        {
            "xyz.openbmc_project.Example.Iface2",
            {{"ExampleProperty2", "test2"}}
        },
    };

    // Make sure the notify method works.
    {
        sdbusplus::message::object_path relPath{"/foo"};
        std::string path(root + relPath.str);

        SignalQueue queue(
            "path='" + root + "',member='InterfacesAdded'");

        auto m = notify();
        m.append(relPath);
        m.append(obj);
        b.call(m);

        auto sig{queue.pop()};
        assert(sig);
        sdbusplus::message::object_path signalPath;
        Object<std::string> signalObject;
        sig.read(signalPath);
        assert(path == signalPath);
        sig.read(signalObject);
        assert(hasProperties(signalObject, obj));
        auto moreSignals{queue.pop()};
        assert(!moreSignals);
    }

    // Make sure DBus signals are handled.
    {
        sdbusplus::message::object_path relDeleteMeOne{"/deleteme1"};
        sdbusplus::message::object_path relDeleteMeTwo{"/deleteme2"};
        sdbusplus::message::object_path relTriggerOne{"/trigger1"};
        std::string deleteMeOne{root + relDeleteMeOne.str};
        std::string deleteMeTwo{root + relDeleteMeTwo.str};
        std::string triggerOne{root + relTriggerOne.str};

        // Create some objects to be deleted by an action.
        {
            auto m = notify();
            m.append(relDeleteMeOne);
            m.append(obj);
            b.call(m);
        }
        {
            auto m = notify();
            m.append(relDeleteMeTwo);
            m.append(obj);
            b.call(m);
        }

        // Create the triggering object.
        {
            auto m = notify();
            m.append(relTriggerOne);
            m.append(obj);
            b.call(m);
        }

        // Set a property that should not trigger due to a filter.
        {
            SignalQueue queue(
                "path='" + root + "',member='InterfacesRemoved'");
            auto m = set(triggerOne);
            m.append("xyz.openbmc_project.Example.Iface2");
            m.append("ExampleProperty2");
            m.append(sdbusplus::message::variant<std::string>("abc123"));
            b.call(m);
            auto sig{queue.pop()};
            assert(!sig);
        }

        // Set a property that should trigger.
        {
            SignalQueue queue(
                "path='" + root + "',member='InterfacesRemoved'");

            auto m = set(triggerOne);
            m.append("xyz.openbmc_project.Example.Iface2");
            m.append("ExampleProperty2");
            m.append(sdbusplus::message::variant<std::string>("xxxyyy"));
            b.call(m);

            sdbusplus::message::object_path sigpath;
            std::vector<std::string> interfaces;
            {
                std::vector<std::string> interfaces;
                auto sig{queue.pop()};
                assert(sig);
                sig.read(sigpath);
                assert(sigpath == deleteMeOne);
                sig.read(interfaces);
                std::sort(interfaces.begin(), interfaces.end());
                assert(hasInterfaces(interfaces, obj));
            }
            {
                std::vector<std::string> interfaces;
                auto sig{queue.pop()};
                assert(sig);
                sig.read(sigpath);
                assert(sigpath == deleteMeTwo);
                sig.read(interfaces);
                std::sort(interfaces.begin(), interfaces.end());
                assert(hasInterfaces(interfaces, obj));
            }
            {
                // Make sure there were only two signals.
                auto sig{queue.pop()};
                assert(!sig);
            }
        }
    }

    // Validate the set property action.
    {
        sdbusplus::message::object_path relChangeMe{"/changeme"};
        sdbusplus::message::object_path relTriggerTwo{"/trigger2"};
        std::string changeMe{root + relChangeMe.str};
        std::string triggerTwo{root + relTriggerTwo.str};

        // Create an object to be updated by the set property action.
        {
            auto m = notify();
            m.append(relChangeMe);
            m.append(obj);
            b.call(m);
        }

        // Create the triggering object.
        {
            auto m = notify();
            m.append(relTriggerTwo);
            m.append(obj);
            b.call(m);
        }

        // Trigger and validate the change.
        {
            SignalQueue queue(
                "path='" + changeMe + "',member='PropertiesChanged'");
            auto m = set(triggerTwo);
            m.append("xyz.openbmc_project.Example.Iface2");
            m.append("ExampleProperty2");
            m.append(sdbusplus::message::variant<std::string>("yyyxxx"));
            b.call(m);

            std::string sigInterface;
            std::map <
            std::string,
                sdbusplus::message::variant<std::string >> sigProperties;
            {
                std::vector<std::string> interfaces;
                auto sig{queue.pop()};
                sig.read(sigInterface);
                assert(sigInterface == "xyz.openbmc_project.Example.Iface1");
                sig.read(sigProperties);
                assert(sigProperties["ExampleProperty1"] == "changed");
            }
        }
    }

    mgr.shutdown();
    std::cout << "Success!" << std::endl;
}

int main()
{
    phosphor::inventory::manager::Manager mgr(
        sdbusplus::bus::new_default(),
        SERVICE, ROOT, INTERFACE);

    auto f = [](auto mgr)
    {
        mgr->run();
    };
    auto t = std::thread(f, &mgr);
    runTests(mgr);

    // Wait for server thread to exit.
    t.join();

    return 0;
}

// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
<commit_msg>Fix build failure<commit_after>/**
 * Copyright © 2016 IBM Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "../manager.hpp"
#include "../config.h"
#include <cassert>
#include <iostream>
#include <algorithm>
#include <thread>

constexpr auto SERVICE = "phosphor.inventory.test";
constexpr auto INTERFACE = IFACE;
constexpr auto ROOT = "/testing/inventory";

/** @class SignalQueue
 *  @brief Store DBus signals in a queue.
 */
class SignalQueue
{
    public:
        ~SignalQueue() = default;
        SignalQueue() = delete;
        SignalQueue(const SignalQueue&) = delete;
        SignalQueue(SignalQueue&&) = default;
        SignalQueue& operator=(const SignalQueue&) = delete;
        SignalQueue& operator=(SignalQueue&&) = default;
        explicit SignalQueue(const std::string& match) :
            _bus(sdbusplus::bus::new_default()),
            _match(_bus, match.c_str(), &callback, this),
            _next(nullptr)
        {
        }

        auto&& pop(unsigned timeout = 1000000)
        {
            while (timeout > 0 && !_next)
            {
                _bus.process_discard();
                _bus.wait(50000);
                timeout -= 50000;
            }
            return std::move(_next);
        }

    private:
        static int callback(sd_bus_message* m, void* context, sd_bus_error*)
        {
            auto* me = static_cast<SignalQueue*>(context);
            sd_bus_message_ref(m);
            sdbusplus::message::message msg{m};
            me->_next = std::move(msg);
            return 0;
        }

        sdbusplus::bus::bus _bus;
        sdbusplus::server::match::match _match;
        sdbusplus::message::message _next;
};

template <typename ...T>
using Object = std::map <
               std::string,
               std::map <
               std::string,
               sdbusplus::message::variant<T... >>>;

/**@brief Find a subset of interfaces and properties in an object. */
template <typename ...T>
auto hasProperties(const Object<T...>& l, const Object<T...>& r)
{
    Object<T...> result;
    std::set_difference(
        r.cbegin(),
        r.cend(),
        l.cbegin(),
        l.cend(),
        std::inserter(result, result.end()));
    return result.empty();
}

/**@brief Check an object for one or more interfaces. */
template <typename ...T>
auto hasInterfaces(const std::vector<std::string>& l, const Object<T...>& r)
{
    std::vector<std::string> stripped, interfaces;
    std::transform(
        r.cbegin(),
        r.cend(),
        std::back_inserter(stripped),
        [](auto & p)
    {
        return p.first;
    });
    std::set_difference(
        stripped.cbegin(),
        stripped.cend(),
        l.cbegin(),
        l.cend(),
        std::back_inserter(interfaces));
    return interfaces.empty();
}

void runTests(phosphor::inventory::manager::Manager& mgr)
{
    const std::string root{ROOT};
    auto b = sdbusplus::bus::new_default();
    auto notify = [&]()
    {
        return b.new_method_call(
                   SERVICE,
                   ROOT,
                   INTERFACE,
                   "Notify");
    };
    auto set = [&](const std::string & path)
    {
        return b.new_method_call(
                   SERVICE,
                   path.c_str(),
                   "org.freedesktop.DBus.Properties",
                   "Set");
    };

    Object<std::string> obj
    {
        {
            "xyz.openbmc_project.Example.Iface1",
            {{"ExampleProperty1", "test1"}}
        },
        {
            "xyz.openbmc_project.Example.Iface2",
            {{"ExampleProperty2", "test2"}}
        },
    };

    // Make sure the notify method works.
    {
        sdbusplus::message::object_path relPath{"/foo"};
        std::string path(root + relPath.str);

        SignalQueue queue(
            "path='" + root + "',member='InterfacesAdded'");

        auto m = notify();
        m.append(relPath);
        m.append(obj);
        b.call(m);

        auto sig{queue.pop()};
        assert(sig);
        sdbusplus::message::object_path signalPath;
        Object<std::string> signalObject;
        sig.read(signalPath);
        assert(path == signalPath.str);
        sig.read(signalObject);
        assert(hasProperties(signalObject, obj));
        auto moreSignals{queue.pop()};
        assert(!moreSignals);
    }

    // Make sure DBus signals are handled.
    {
        sdbusplus::message::object_path relDeleteMeOne{"/deleteme1"};
        sdbusplus::message::object_path relDeleteMeTwo{"/deleteme2"};
        sdbusplus::message::object_path relTriggerOne{"/trigger1"};
        std::string deleteMeOne{root + relDeleteMeOne.str};
        std::string deleteMeTwo{root + relDeleteMeTwo.str};
        std::string triggerOne{root + relTriggerOne.str};

        // Create some objects to be deleted by an action.
        {
            auto m = notify();
            m.append(relDeleteMeOne);
            m.append(obj);
            b.call(m);
        }
        {
            auto m = notify();
            m.append(relDeleteMeTwo);
            m.append(obj);
            b.call(m);
        }

        // Create the triggering object.
        {
            auto m = notify();
            m.append(relTriggerOne);
            m.append(obj);
            b.call(m);
        }

        // Set a property that should not trigger due to a filter.
        {
            SignalQueue queue(
                "path='" + root + "',member='InterfacesRemoved'");
            auto m = set(triggerOne);
            m.append("xyz.openbmc_project.Example.Iface2");
            m.append("ExampleProperty2");
            m.append(sdbusplus::message::variant<std::string>("abc123"));
            b.call(m);
            auto sig{queue.pop()};
            assert(!sig);
        }

        // Set a property that should trigger.
        {
            SignalQueue queue(
                "path='" + root + "',member='InterfacesRemoved'");

            auto m = set(triggerOne);
            m.append("xyz.openbmc_project.Example.Iface2");
            m.append("ExampleProperty2");
            m.append(sdbusplus::message::variant<std::string>("xxxyyy"));
            b.call(m);

            sdbusplus::message::object_path sigpath;
            std::vector<std::string> interfaces;
            {
                std::vector<std::string> interfaces;
                auto sig{queue.pop()};
                assert(sig);
                sig.read(sigpath);
                assert(sigpath == deleteMeOne);
                sig.read(interfaces);
                std::sort(interfaces.begin(), interfaces.end());
                assert(hasInterfaces(interfaces, obj));
            }
            {
                std::vector<std::string> interfaces;
                auto sig{queue.pop()};
                assert(sig);
                sig.read(sigpath);
                assert(sigpath == deleteMeTwo);
                sig.read(interfaces);
                std::sort(interfaces.begin(), interfaces.end());
                assert(hasInterfaces(interfaces, obj));
            }
            {
                // Make sure there were only two signals.
                auto sig{queue.pop()};
                assert(!sig);
            }
        }
    }

    // Validate the set property action.
    {
        sdbusplus::message::object_path relChangeMe{"/changeme"};
        sdbusplus::message::object_path relTriggerTwo{"/trigger2"};
        std::string changeMe{root + relChangeMe.str};
        std::string triggerTwo{root + relTriggerTwo.str};

        // Create an object to be updated by the set property action.
        {
            auto m = notify();
            m.append(relChangeMe);
            m.append(obj);
            b.call(m);
        }

        // Create the triggering object.
        {
            auto m = notify();
            m.append(relTriggerTwo);
            m.append(obj);
            b.call(m);
        }

        // Trigger and validate the change.
        {
            SignalQueue queue(
                "path='" + changeMe + "',member='PropertiesChanged'");
            auto m = set(triggerTwo);
            m.append("xyz.openbmc_project.Example.Iface2");
            m.append("ExampleProperty2");
            m.append(sdbusplus::message::variant<std::string>("yyyxxx"));
            b.call(m);

            std::string sigInterface;
            std::map <
            std::string,
                sdbusplus::message::variant<std::string >> sigProperties;
            {
                std::vector<std::string> interfaces;
                auto sig{queue.pop()};
                sig.read(sigInterface);
                assert(sigInterface == "xyz.openbmc_project.Example.Iface1");
                sig.read(sigProperties);
                assert(sigProperties["ExampleProperty1"] == "changed");
            }
        }
    }

    mgr.shutdown();
    std::cout << "Success!" << std::endl;
}

int main()
{
    phosphor::inventory::manager::Manager mgr(
        sdbusplus::bus::new_default(),
        SERVICE, ROOT, INTERFACE);

    auto f = [](auto mgr)
    {
        mgr->run();
    };
    auto t = std::thread(f, &mgr);
    runTests(mgr);

    // Wait for server thread to exit.
    t.join();

    return 0;
}

// vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
<|endoftext|>


<commit_before>#define gtf_HEADER_ONLY
#include "../iutest/include/iutest.hpp"
#include "../src/system/task.h"

#include <vector>

using namespace gtf;

IUTEST_MAKE_PEEP(weak_ptr<TaskBase> (TaskManager::*)(unsigned int) const, TaskManager, FindTask);
IUTEST_MAKE_PEEP(weak_ptr<BackgroundTaskBase> (TaskManager::*)(unsigned int) const, TaskManager, FindBGTask);

static std::vector<int> veve;

template<typename T, class B>
class CTekitou : public B
{
public:
    CTekitou(T init) : hogehoge(init)
    {

    }
    ~CTekitou()
    {}

    T hogehoge;
    unsigned int GetID() const override { return hogehoge; }
    int GetDrawPriority() const override { return 1; }
    void Draw() override { veve.push_back(hogehoge); }
};

template<typename T, class B, typename... Arg>
class CTekitou2 : public B
{
public:
	CTekitou2(T init, Arg&&... args) : B(forward<Arg>(args)...), hogehoge(init)
	{

	}
	~CTekitou2()
	{}

	T hogehoge;

	bool Execute(double /* e */) override{ veve.push_back(hogehoge); return true; }
	unsigned int GetID()const override{ return hogehoge; }
};

template<typename T, typename... Arg>
class CExTaskSelfDestruct : public ExclusiveTaskBase
{
public:
	CExTaskSelfDestruct(T init, Arg&&... args) : ExclusiveTaskBase(forward<Arg>(args)...), hogehoge(init)
	{

	}
	~CExTaskSelfDestruct()
	{}

	T hogehoge;

	bool Execute(double /* e */) override{ veve.push_back(hogehoge); return false; }
	unsigned int GetID()const override{ return hogehoge; }
};

IUTEST(gtfTest, TestMethod1)
{
    TaskManager task;
    auto ptr = task.AddNewTask< CTekitou<int, TaskBase> >(1);
    IUTEST_ASSERT_EQ((void*)IUTEST_PEEP_GET(task, TaskManager, FindTask)(ptr->GetID()).lock().get(), (void*)ptr.get());
    IUTEST_ASSERT_EQ((void*)task.FindTask<TaskBase>(ptr->GetID()).get(), (void*)ptr.get());
}

IUTEST(gtfTest, TestMethod2)
{
    TaskManager task;
    auto ptr = task.AddNewTask< CTekitou2<int, BackgroundTaskBase> >(1);
    IUTEST_ASSERT_EQ((void*)(task.FindTask<BackgroundTaskBase>(ptr->GetID())).get(), (void*)ptr.get());
}
IUTEST(gtfTest, TestMethod3)
{
    TaskManager task;
    auto ptr = task.AddNewTask< CTekitou2<int, ExclusiveTaskBase> >(1);
    IUTEST_ASSERT_NE((void*)IUTEST_PEEP_GET(task, TaskManager, FindTask)(ptr->GetID()).lock().get(), (void*)ptr.get());
}
IUTEST(gtfTest, RunOrder1)
{
    TaskManager task;
    veve.clear();
    auto ptr = task.AddNewTask< CTekitou2<int, ExclusiveTaskBase> >(1);
    auto ptr2 = task.AddNewTask< CTekitou2<int, TaskBase> >(2);
    //modify veve
    task.Execute(0);
    task.Execute(1);
    IUTEST_ASSERT_EQ(1, veve[0]);
    IUTEST_ASSERT_EQ(1, veve[1]);
}
IUTEST(gtfTest, RunOrder2)
{
    static TaskManager task;
    class ct : public CTekitou2 < int, ExclusiveTaskBase >
    {
    public:
        ct(int init) : CTekitou2 < int, ExclusiveTaskBase >(init) {}
        void Initialize()
        {
            task.AddNewTask< CTekitou2<int, TaskBase> >(2);
        }
    };

    veve.clear();
    auto ptr = task.AddNewTask<ct>(1);
    task.Execute(0);
    task.Execute(1);
    IUTEST_ASSERT_EQ(1, veve[0]);
    IUTEST_ASSERT_EQ(2, veve[1]);
}

IUTEST(gtfTest, Draw1)
{
    static TaskManager task;
    class ct2 : public CTekitou2 < int, ExclusiveTaskBase >
    {
    public:
        ct2(int init) : CTekitou2 < int, ExclusiveTaskBase >(init)
        {

        }
        void Initialize()
        {
            task.AddNewTask< CTekitou<int, TaskBase> >(hogehoge + 1);
        }
    };

    for (int i = 1; i < 257; i++)
    {
        task.AddNewTask<ct2>(i * 2);
        task.Execute(0);
    }
    veve.clear();
    task.RemoveTaskByID(1);
    for (int i = 0; i < 4; i++)
        task.Draw();

    IUTEST_ASSERT_EQ(513, veve[0]);
}
IUTEST(gtfTest, Draw2)
{
    static TaskManager task;
    class ct2 : public CTekitou2 < int, ExclusiveTaskBase >
    {
    public:
        ct2(int init) : CTekitou2 < int, ExclusiveTaskBase >(init)
        {

        }
        void Initialize()
        {
            task.AddNewTask< CTekitou<int, BackgroundTaskBase> >(hogehoge + 1);
        }
    };

    for (int i = 1; i < 5; i++)
    {
        task.AddNewTask<ct2>(i * 2);
        task.Execute(0);
    }
    veve.clear();
    task.RemoveTaskByID(1);
    for (int i = 0; i < 4; i++)
        task.Draw();

    IUTEST_ASSERT_EQ(3, veve[0]);
}
IUTEST(gtfTest, DrawFallthrough)
{
    static TaskManager task;
    class ct2 : public CTekitou2 < int, ExclusiveTaskBase, bool >
    {
    public:
        ct2(int init) : CTekitou2 < int, ExclusiveTaskBase, bool >(init, true)
        {

        }
        void Initialize()
        {
            task.AddNewTask< CTekitou<int, TaskBase> >(hogehoge + 1);
        }
    };

    for (int i = 1; i < 5; i++)
    {
        task.AddNewTask<ct2>(i * 2);
        task.Execute(0);
    }
    veve.clear();
    task.RemoveTaskByID(1);
    for (int i = 0; i < 4; i++)
        task.Draw();

    IUTEST_ASSERT_EQ(3, veve[0]);
}

IUTEST(gtfTest, TaskDependency)
{
    static TaskManager task;
    class ct : public CTekitou2 < int, ExclusiveTaskBase >
    {
    public:
        ct(int init) : CTekitou2 < int, ExclusiveTaskBase >(init)
        {

        }
        void Initialize()
        {
            task.AddNewTask< CTekitou2<int, TaskBase> >(hogehoge + 20);
        }
        virtual bool Inactivate(unsigned int /* nextTaskID */){ return true; }//!< 他の排他タスクが開始したときに呼ばれる
    };

    veve.clear();
    auto ptr = task.AddNewTask<ct>(1);
    task.Execute(0);
    auto ptr2 = task.AddNewTask<ct>(3);
    task.Execute(1);
    IUTEST_ASSERT_EQ(1, veve[0]);
    IUTEST_ASSERT_EQ(1 + 20, veve[1]);
    IUTEST_ASSERT_EQ(3, veve[2]);
    IUTEST_ASSERT_EQ(3 + 20, veve[3]);
    task.RevertExclusiveTaskByID(1);
    task.Execute(3);
    IUTEST_ASSERT_EQ(1, veve[4]);
    IUTEST_ASSERT_EQ(1 + 20, veve[5]);
    ptr2 = task.AddNewTask<ct>(4);
    task.Execute(4);
    task.RemoveTaskByID(21);
    task.Execute(5);
    IUTEST_ASSERT_EQ(4, veve[8]);
    IUTEST_ASSERT_EQ(4 + 20, veve[9]);
}
IUTEST(gtfTest, ReuseContainer)
{
    TaskManager task;
    auto ptr = task.AddNewTask< CTekitou2<int, ExclusiveTaskBase> >(1);
    IUTEST_ASSERT_NE((void*)IUTEST_PEEP_GET(task, TaskManager, FindTask)(ptr->GetID()).lock().get(), (void*)ptr.get());

    task.Destroy();
    task.Execute(0);
    IUTEST_ASSERT_EQ((void*)task.GetTopExclusiveTask().lock().get(), (void*)nullptr);

    auto ptr3 = task.AddNewTask< CTekitou2<int, ExclusiveTaskBase> >(1);
    task.Execute(0);
    IUTEST_ASSERT_NE((void*)IUTEST_PEEP_GET(task, TaskManager, FindTask)(ptr3->GetID()).lock().get(), (void*)ptr3.get());
}
IUTEST(gtfTest, ExTaskSelfDeestruct)
{
    TaskManager task;
    veve.clear();
    auto ptr = task.AddNewTask< CTekitou2<int, ExclusiveTaskBase> >(1);
    task.Execute(0);
    auto ptr2 = task.AddNewTask< CExTaskSelfDestruct<int> >(2);
    task.Execute(0);
    task.Execute(0);
    IUTEST_ASSERT_EQ(1, veve[0]);
    IUTEST_ASSERT_EQ(2, veve[1]);
    IUTEST_ASSERT_EQ(1, veve[2]);
}
int main(int argc, char** argv)
{
    IUTEST_INIT(&argc, argv);
    return IUTEST_RUN_ALL_TESTS();
}
<commit_msg>fix(test): fixed overload<commit_after>#define gtf_HEADER_ONLY
#include "../iutest/include/iutest.hpp"
#include "../src/system/task.h"

#include <vector>

using namespace gtf;

IUTEST_MAKE_PEEP(weak_ptr<BackgroundTaskBase> (TaskManager::*)(unsigned int) const, TaskManager, FindBGTask);

static std::vector<int> veve;

template<typename T, class B>
class CTekitou : public B
{
public:
    CTekitou(T init) : hogehoge(init)
    {

    }
    ~CTekitou()
    {}

    T hogehoge;
    unsigned int GetID() const override { return hogehoge; }
    int GetDrawPriority() const override { return 1; }
    void Draw() override { veve.push_back(hogehoge); }
};

template<typename T, class B, typename... Arg>
class CTekitou2 : public B
{
public:
	CTekitou2(T init, Arg&&... args) : B(forward<Arg>(args)...), hogehoge(init)
	{

	}
	~CTekitou2()
	{}

	T hogehoge;

	bool Execute(double /* e */) override{ veve.push_back(hogehoge); return true; }
	unsigned int GetID()const override{ return hogehoge; }
};

template<typename T, typename... Arg>
class CExTaskSelfDestruct : public ExclusiveTaskBase
{
public:
	CExTaskSelfDestruct(T init, Arg&&... args) : ExclusiveTaskBase(forward<Arg>(args)...), hogehoge(init)
	{

	}
	~CExTaskSelfDestruct()
	{}

	T hogehoge;

	bool Execute(double /* e */) override{ veve.push_back(hogehoge); return false; }
	unsigned int GetID()const override{ return hogehoge; }
};

IUTEST(gtfTest, TestMethod1)
{
    TaskManager task;
    auto ptr = task.AddNewTask< CTekitou<int, TaskBase> >(1);
    IUTEST_ASSERT_EQ((void*)task.FindTask<TaskBase>(ptr->GetID()).get(), (void*)ptr.get());
}

IUTEST(gtfTest, TestMethod2)
{
    TaskManager task;
    auto ptr = task.AddNewTask< CTekitou2<int, BackgroundTaskBase> >(1);
    IUTEST_ASSERT_EQ((void*)(task.FindTask<BackgroundTaskBase>(ptr->GetID())).get(), (void*)ptr.get());
}
IUTEST(gtfTest, TestMethod3)
{
    TaskManager task;
    auto ptr = task.AddNewTask< CTekitou2<int, ExclusiveTaskBase> >(1);
    IUTEST_ASSERT_NE((void*)task.FindTask<TaskBase>(ptr->GetID()).get(), (void*)ptr.get());
}
IUTEST(gtfTest, RunOrder1)
{
    TaskManager task;
    veve.clear();
    auto ptr = task.AddNewTask< CTekitou2<int, ExclusiveTaskBase> >(1);
    auto ptr2 = task.AddNewTask< CTekitou2<int, TaskBase> >(2);
    //modify veve
    task.Execute(0);
    task.Execute(1);
    IUTEST_ASSERT_EQ(1, veve[0]);
    IUTEST_ASSERT_EQ(1, veve[1]);
}
IUTEST(gtfTest, RunOrder2)
{
    static TaskManager task;
    class ct : public CTekitou2 < int, ExclusiveTaskBase >
    {
    public:
        ct(int init) : CTekitou2 < int, ExclusiveTaskBase >(init) {}
        void Initialize()
        {
            task.AddNewTask< CTekitou2<int, TaskBase> >(2);
        }
    };

    veve.clear();
    auto ptr = task.AddNewTask<ct>(1);
    task.Execute(0);
    task.Execute(1);
    IUTEST_ASSERT_EQ(1, veve[0]);
    IUTEST_ASSERT_EQ(2, veve[1]);
}

IUTEST(gtfTest, Draw1)
{
    static TaskManager task;
    class ct2 : public CTekitou2 < int, ExclusiveTaskBase >
    {
    public:
        ct2(int init) : CTekitou2 < int, ExclusiveTaskBase >(init)
        {

        }
        void Initialize()
        {
            task.AddNewTask< CTekitou<int, TaskBase> >(hogehoge + 1);
        }
    };

    for (int i = 1; i < 257; i++)
    {
        task.AddNewTask<ct2>(i * 2);
        task.Execute(0);
    }
    veve.clear();
    task.RemoveTaskByID(1);
    for (int i = 0; i < 4; i++)
        task.Draw();

    IUTEST_ASSERT_EQ(513, veve[0]);
}
IUTEST(gtfTest, Draw2)
{
    static TaskManager task;
    class ct2 : public CTekitou2 < int, ExclusiveTaskBase >
    {
    public:
        ct2(int init) : CTekitou2 < int, ExclusiveTaskBase >(init)
        {

        }
        void Initialize()
        {
            task.AddNewTask< CTekitou<int, BackgroundTaskBase> >(hogehoge + 1);
        }
    };

    for (int i = 1; i < 5; i++)
    {
        task.AddNewTask<ct2>(i * 2);
        task.Execute(0);
    }
    veve.clear();
    task.RemoveTaskByID(1);
    for (int i = 0; i < 4; i++)
        task.Draw();

    IUTEST_ASSERT_EQ(3, veve[0]);
}
IUTEST(gtfTest, DrawFallthrough)
{
    static TaskManager task;
    class ct2 : public CTekitou2 < int, ExclusiveTaskBase, bool >
    {
    public:
        ct2(int init) : CTekitou2 < int, ExclusiveTaskBase, bool >(init, true)
        {

        }
        void Initialize()
        {
            task.AddNewTask< CTekitou<int, TaskBase> >(hogehoge + 1);
        }
    };

    for (int i = 1; i < 5; i++)
    {
        task.AddNewTask<ct2>(i * 2);
        task.Execute(0);
    }
    veve.clear();
    task.RemoveTaskByID(1);
    for (int i = 0; i < 4; i++)
        task.Draw();

    IUTEST_ASSERT_EQ(3, veve[0]);
}

IUTEST(gtfTest, TaskDependency)
{
    static TaskManager task;
    class ct : public CTekitou2 < int, ExclusiveTaskBase >
    {
    public:
        ct(int init) : CTekitou2 < int, ExclusiveTaskBase >(init)
        {

        }
        void Initialize()
        {
            task.AddNewTask< CTekitou2<int, TaskBase> >(hogehoge + 20);
        }
        virtual bool Inactivate(unsigned int /* nextTaskID */){ return true; }//!< 他の排他タスクが開始したときに呼ばれる
    };

    veve.clear();
    auto ptr = task.AddNewTask<ct>(1);
    task.Execute(0);
    auto ptr2 = task.AddNewTask<ct>(3);
    task.Execute(1);
    IUTEST_ASSERT_EQ(1, veve[0]);
    IUTEST_ASSERT_EQ(1 + 20, veve[1]);
    IUTEST_ASSERT_EQ(3, veve[2]);
    IUTEST_ASSERT_EQ(3 + 20, veve[3]);
    task.RevertExclusiveTaskByID(1);
    task.Execute(3);
    IUTEST_ASSERT_EQ(1, veve[4]);
    IUTEST_ASSERT_EQ(1 + 20, veve[5]);
    ptr2 = task.AddNewTask<ct>(4);
    task.Execute(4);
    task.RemoveTaskByID(21);
    task.Execute(5);
    IUTEST_ASSERT_EQ(4, veve[8]);
    IUTEST_ASSERT_EQ(4 + 20, veve[9]);
}
IUTEST(gtfTest, ReuseContainer)
{
    TaskManager task;
    auto ptr = task.AddNewTask< CTekitou2<int, ExclusiveTaskBase> >(1);
    IUTEST_ASSERT_NE((void*)task.FindTask<TaskBase>(ptr->GetID()).get(), (void*)ptr.get());

    task.Destroy();
    task.Execute(0);
    IUTEST_ASSERT_EQ((void*)task.GetTopExclusiveTask().lock().get(), (void*)nullptr);

    auto ptr3 = task.AddNewTask< CTekitou2<int, ExclusiveTaskBase> >(1);
    task.Execute(0);
    IUTEST_ASSERT_NE((void*)task.FindTask<TaskBase>(ptr3->GetID()).get(), (void*)ptr3.get());
}
IUTEST(gtfTest, ExTaskSelfDeestruct)
{
    TaskManager task;
    veve.clear();
    auto ptr = task.AddNewTask< CTekitou2<int, ExclusiveTaskBase> >(1);
    task.Execute(0);
    auto ptr2 = task.AddNewTask< CExTaskSelfDestruct<int> >(2);
    task.Execute(0);
    task.Execute(0);
    IUTEST_ASSERT_EQ(1, veve[0]);
    IUTEST_ASSERT_EQ(2, veve[1]);
    IUTEST_ASSERT_EQ(1, veve[2]);
}
int main(int argc, char** argv)
{
    IUTEST_INIT(&argc, argv);
    return IUTEST_RUN_ALL_TESTS();
}
<|endoftext|>


<commit_before>#include "tmath.hpp"

/* ================================ SINE ======================================== */
TMath::DOUBLE TMath::sin(DOUBLE x)
{
	x = mod(x + PI, 2 * PI) - PI;
	DOUBLE r = 0;
	for (LONG n = 0; n <= 8L; n++) {
		r += pow(DOUBLE(-1), n) * pow(x, 2 * n + 1) / fac(2 * n + 1);
	}
	return r;
}
TMath::DOUBLE TMath::asin(DOUBLE x)
{
	DOUBLE r = 0;
	DOUBLE delta = 1;
	for (LONG n = 1; delta > 1e-6; n++)
	{
		LONG odd = 2 * n - 1;
		DOUBLE oddf = oddfacd(odd - 2);
		DOUBLE f = facd(odd);
		DOUBLE p = pow(x, odd);
		DOUBLE d = p / f * oddf * oddf;
		delta = abs(d);
		r += p / f * oddf * oddf;
	}
	return r;
}
TMath::DOUBLE TMath::sinh(DOUBLE x)
{
	return 0.5 * (exp(x) - exp(-x));
}
/* ================================ COSINE ======================================== */
TMath::DOUBLE TMath::cos(DOUBLE x)
{
	x = mod(x + PI, 2 * PI) - PI;
	DOUBLE r = 0;
	for (LONG n = 0; n <= 8L; n++) {
		r += pow(DOUBLE(-1.0), n) * pow(x, 2 * n) / fac(2 * n);
	}
	return r;
}
TMath::DOUBLE TMath::acos(DOUBLE x)
{
	return PI / 2 - asin(x);
}
TMath::DOUBLE TMath::cosh(DOUBLE x)
{
	return 0.5 * (exp(x) + exp(-x));
}
/* ================================ TANGENT ======================================== */
TMath::DOUBLE TMath::tan(DOUBLE x)
{
	return sin(x) / cos(x);
}
TMath::DOUBLE TMath::atan(DOUBLE x)
{
	DOUBLE r = 0;
	DOUBLE delta = 1;
	for (LONG n = 0; delta > 1e-4; n++)
	{
		LONG odd = 2 * n + 1;
		DOUBLE d = DOUBLE(pow(-1LL, n)) * pow(x, odd) / DOUBLE(odd);
		delta = abs(d);
		r += d;
	}
	return r;
}
TMath::DOUBLE TMath::tanh(DOUBLE x)
{
	return sinh(x) / cosh(x);
}
/* ================================ COTANGENT ======================================== */
TMath::DOUBLE TMath::cot(DOUBLE x)
{
	return cos(x) / sin(x);
}
TMath::DOUBLE TMath::acot(DOUBLE x)
{
	return PI / 2 - atan(x);
}
TMath::DOUBLE TMath::coth(DOUBLE x)
{
	return cosh(x) / sinh(x);
}
/* ================================ SECANT ======================================== */
TMath::DOUBLE TMath::sec(DOUBLE x)
{
	return 1 / cos(x);
}
TMath::DOUBLE TMath::asec(DOUBLE x)
{
	return acos(1 / x);
}
TMath::DOUBLE TMath::sech(DOUBLE x)
{
	return 1 / cosh(x);
}
/* ================================ COSECANT ======================================== */
TMath::DOUBLE TMath::cosec(DOUBLE x)
{
	return 1 / sin(x);
}
TMath::DOUBLE TMath::acsc(DOUBLE x)
{
	return asin(1 / x);
}
TMath::DOUBLE TMath::csch(DOUBLE x)
{
	return 1 / sinh(x);
}
/* ================================= FLOOR, CEIL AND MODULO ======================================== */
TMath::LONG TMath::floor(DOUBLE x)
{
	LONG truncated = LONG(x);
	if (x < 0) {
		if (truncated > x) {
			return truncated - 1;
		} else {
			return truncated;
		}
	}
	else {
		return truncated;
	}
}
TMath::LONG TMath::ceil(DOUBLE x)
{
	LONG truncated = LONG(x);
	if (x < 0) {
		return truncated;
	} else {
		return truncated + 1;
	}
}
TMath::DOUBLE TMath::mod(DOUBLE x, DOUBLE y)
{
	return y * ((x / y) - floor(x / y));
}
/* =============================== EXPONENTIAL FUNCTION, SQRT, LOGARITHM ======================= */
TMath::DOUBLE TMath::exp(DOUBLE x)
{
	DOUBLE r = 0;
	for (LONG n = 0; n <= 15L; n++)
	{
		r += pow(x, n) / fac(n);
	}
	return r;
}
TMath::DOUBLE TMath::sqrt(DOUBLE x)
{
	return root(x, 2);
}
TMath::DOUBLE TMath::root(DOUBLE x, DOUBLE n)
{
	return pow(x, 1 / n);
}
TMath::DOUBLE TMath::ln(DOUBLE x)
{
	x = (x - 1) / (x + 1);
	DOUBLE r = 0;
	for (LONG n = 0; n <= 100L; n++)
	{
		r += 2 * pow(x, 2 * n + 1) / (2 * n + 1);
	}
	return r;
}
TMath::DOUBLE TMath::lg(DOUBLE x)
{
	return ln(x) / ln(10);
}
TMath::DOUBLE TMath::lb(DOUBLE x)
{
	return ln(x) / ln(2);
}
TMath::DOUBLE TMath::log(DOUBLE x, DOUBLE n)
{
	return ln(x) / ln(n);
}
/* =================================== POWER FUNCTIONS =====================================================*/
TMath::DOUBLE TMath::pow(DOUBLE x, LONG n)
{
	if (n < 0) {
		return 1 / pow(x, -n);
	}

	DOUBLE r = 1;
	for (LONG i = 1; i <= n; i++)
	{
		r *= x;
	}
	return r;
}

TMath::LONG TMath::pow(LONG x, LONG n)
{
	if (n < 0) {
		return 1 / pow(x, -n);
	}

	LONG r = 1;
	for (LONG i = 1; i <= n; i++)
	{
		r *= x;
	}
	return r;
}
TMath::DOUBLE TMath::pow(DOUBLE x, DOUBLE n)
{
	return exp(n * ln(x));
}
/* ========================================== FACULTY ============================================*/
TMath::LONG TMath::fac(LONG n) {
	LONG r = 1;
	for (LONG i = 2; i <= n; i++)
	{
		r *= i;
	}
	return r;
}
TMath::DOUBLE TMath::facd(LONG n) {
	DOUBLE r = 1;
	for (LONG i = 2; i <= n; i++) {
		r *= DOUBLE(i);
	}
	return r;
}
TMath::LONG TMath::oddfac(LONG n) {
	LONG r = 1;
	for (LONG i = 3; i <= n; i++) {
		r *= i;
	}
	return r;
}
TMath::DOUBLE TMath::oddfacd(LONG n) {
	DOUBLE r = 1;
	for (LONG i = 3; i <= n; i += 2) {
		r *= DOUBLE(i);
	}
	return r;
}
TMath::DOUBLE TMath::abs(DOUBLE x) {
	if (x < 0) return -x;
	else return x;
}
/* ========================================== DEGREE / RADIANT CONVERSION ================================*/
TMath::DOUBLE TMath::rad(DOUBLE deg)
{
	return PI / 180 * deg;
}
TMath::DOUBLE TMath::deg(DOUBLE rad)
{
	return 180 / PI * rad;
}
<commit_msg>fix: error in oddfac<commit_after>#include "tmath.hpp"

/* ================================ SINE ======================================== */
TMath::DOUBLE TMath::sin(DOUBLE x)
{
	x = mod(x + PI, 2 * PI) - PI;
	DOUBLE r = 0;
	for (LONG n = 0; n <= 8L; n++) {
		r += pow(DOUBLE(-1), n) * pow(x, 2 * n + 1) / fac(2 * n + 1);
	}
	return r;
}
TMath::DOUBLE TMath::asin(DOUBLE x)
{
	DOUBLE r = 0;
	DOUBLE delta = 1;
	for (LONG n = 1; delta > 1e-6; n++)
	{
		LONG odd = 2 * n - 1;
		DOUBLE oddf = oddfacd(odd - 2);
		DOUBLE f = facd(odd);
		DOUBLE p = pow(x, odd);
		DOUBLE d = p / f * oddf * oddf;
		delta = abs(d);
		r += p / f * oddf * oddf;
	}
	return r;
}
TMath::DOUBLE TMath::sinh(DOUBLE x)
{
	return 0.5 * (exp(x) - exp(-x));
}
/* ================================ COSINE ======================================== */
TMath::DOUBLE TMath::cos(DOUBLE x)
{
	x = mod(x + PI, 2 * PI) - PI;
	DOUBLE r = 0;
	for (LONG n = 0; n <= 8L; n++) {
		r += pow(DOUBLE(-1.0), n) * pow(x, 2 * n) / fac(2 * n);
	}
	return r;
}
TMath::DOUBLE TMath::acos(DOUBLE x)
{
	return PI / 2 - asin(x);
}
TMath::DOUBLE TMath::cosh(DOUBLE x)
{
	return 0.5 * (exp(x) + exp(-x));
}
/* ================================ TANGENT ======================================== */
TMath::DOUBLE TMath::tan(DOUBLE x)
{
	return sin(x) / cos(x);
}
TMath::DOUBLE TMath::atan(DOUBLE x)
{
	DOUBLE r = 0;
	DOUBLE delta = 1;
	for (LONG n = 0; delta > 1e-4; n++)
	{
		LONG odd = 2 * n + 1;
		DOUBLE d = DOUBLE(pow(-1LL, n)) * pow(x, odd) / DOUBLE(odd);
		delta = abs(d);
		r += d;
	}
	return r;
}
TMath::DOUBLE TMath::tanh(DOUBLE x)
{
	return sinh(x) / cosh(x);
}
/* ================================ COTANGENT ======================================== */
TMath::DOUBLE TMath::cot(DOUBLE x)
{
	return cos(x) / sin(x);
}
TMath::DOUBLE TMath::acot(DOUBLE x)
{
	return PI / 2 - atan(x);
}
TMath::DOUBLE TMath::coth(DOUBLE x)
{
	return cosh(x) / sinh(x);
}
/* ================================ SECANT ======================================== */
TMath::DOUBLE TMath::sec(DOUBLE x)
{
	return 1 / cos(x);
}
TMath::DOUBLE TMath::asec(DOUBLE x)
{
	return acos(1 / x);
}
TMath::DOUBLE TMath::sech(DOUBLE x)
{
	return 1 / cosh(x);
}
/* ================================ COSECANT ======================================== */
TMath::DOUBLE TMath::cosec(DOUBLE x)
{
	return 1 / sin(x);
}
TMath::DOUBLE TMath::acsc(DOUBLE x)
{
	return asin(1 / x);
}
TMath::DOUBLE TMath::csch(DOUBLE x)
{
	return 1 / sinh(x);
}
/* ================================= FLOOR, CEIL AND MODULO ======================================== */
TMath::LONG TMath::floor(DOUBLE x)
{
	LONG truncated = LONG(x);
	if (x < 0) {
		if (truncated > x) {
			return truncated - 1;
		} else {
			return truncated;
		}
	}
	else {
		return truncated;
	}
}
TMath::LONG TMath::ceil(DOUBLE x)
{
	LONG truncated = LONG(x);
	if (x < 0) {
		return truncated;
	} else {
		return truncated + 1;
	}
}
TMath::DOUBLE TMath::mod(DOUBLE x, DOUBLE y)
{
	return y * ((x / y) - floor(x / y));
}
/* =============================== EXPONENTIAL FUNCTION, SQRT, LOGARITHM ======================= */
TMath::DOUBLE TMath::exp(DOUBLE x)
{
	DOUBLE r = 0;
	for (LONG n = 0; n <= 15L; n++)
	{
		r += pow(x, n) / fac(n);
	}
	return r;
}
TMath::DOUBLE TMath::sqrt(DOUBLE x)
{
	return root(x, 2);
}
TMath::DOUBLE TMath::root(DOUBLE x, DOUBLE n)
{
	return pow(x, 1 / n);
}
TMath::DOUBLE TMath::ln(DOUBLE x)
{
	x = (x - 1) / (x + 1);
	DOUBLE r = 0;
	for (LONG n = 0; n <= 100L; n++)
	{
		r += 2 * pow(x, 2 * n + 1) / (2 * n + 1);
	}
	return r;
}
TMath::DOUBLE TMath::lg(DOUBLE x)
{
	return ln(x) / ln(10);
}
TMath::DOUBLE TMath::lb(DOUBLE x)
{
	return ln(x) / ln(2);
}
TMath::DOUBLE TMath::log(DOUBLE x, DOUBLE n)
{
	return ln(x) / ln(n);
}
/* =================================== POWER FUNCTIONS =====================================================*/
TMath::DOUBLE TMath::pow(DOUBLE x, LONG n)
{
	if (n < 0) {
		return 1 / pow(x, -n);
	}

	DOUBLE r = 1;
	for (LONG i = 1; i <= n; i++)
	{
		r *= x;
	}
	return r;
}

TMath::LONG TMath::pow(LONG x, LONG n)
{
	if (n < 0) {
		return 1 / pow(x, -n);
	}

	LONG r = 1;
	for (LONG i = 1; i <= n; i++)
	{
		r *= x;
	}
	return r;
}
TMath::DOUBLE TMath::pow(DOUBLE x, DOUBLE n)
{
	return exp(n * ln(x));
}
/* ========================================== FACULTY ============================================*/
TMath::LONG TMath::fac(LONG n) {
	LONG r = 1;
	for (LONG i = 2; i <= n; i++)
	{
		r *= i;
	}
	return r;
}
TMath::DOUBLE TMath::facd(LONG n) {
	DOUBLE r = 1;
	for (LONG i = 2; i <= n; i++) {
		r *= DOUBLE(i);
	}
	return r;
}
TMath::LONG TMath::oddfac(LONG n) {
	LONG r = 1;
	for (LONG i = 3; i <= n; i += 2) {
		r *= i;
	}
	return r;
}
TMath::DOUBLE TMath::oddfacd(LONG n) {
	DOUBLE r = 1;
	for (LONG i = 3; i <= n; i += 2) {
		r *= DOUBLE(i);
	}
	return r;
}
TMath::DOUBLE TMath::abs(DOUBLE x) {
	if (x < 0) return -x;
	else return x;
}
/* ========================================== DEGREE / RADIANT CONVERSION ================================*/
TMath::DOUBLE TMath::rad(DOUBLE deg)
{
	return PI / 180 * deg;
}
TMath::DOUBLE TMath::deg(DOUBLE rad)
{
	return 180 / PI * rad;
}
<|endoftext|>


<commit_before>/*
*******************************************************************************
\file test.cpp
\brief Tests
\project GF2 [GF(2) algebra library]
\author () Sergey Agievich [agievich@{bsu.by|gmail.com}]
\created 2016.07.06
\version 2016.07.22
\license This program is released under the MIT License. See Copyright Notices
in GF2/info.h.
*******************************************************************************
*/

#include "gf2/buchb.h"
#include "gf2/func.h"
#include "gf2/ideal.h"
#include <sstream>

using namespace GF2;
using namespace std;

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

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

template class Word<127>;
	template class Monom<129>;
	template class ZZ<130>;

template struct OrderGr<OrderLR<OrderLex<65>, OrderGrlex<66> > >;
template struct OrderRL<OrderRev<OrderGrevlex<68> >, OrderLex<67> >;

template class MPoly<135, OrderLex<135> >;
template class Ideal<136, OrderGrevlex<136> >;
template class Buchb<137, OrderGrlex<137> >;

template class Func<5, int>;
	template class BFunc<6>;
	template class VFunc<7, 8>;
		template class VSubst<8>;
/*
*******************************************************************************

#	orderTest:   OrderGrlex<6>  OrderGr<OrderLex<6> >;
#	bentTest:    -;
#	sboxTest:    4- S-
	(by.gost28147.params.1);
#	bashTest:   ,  S- Bash;
#	commuteTest:      2.
*******************************************************************************
*/

bool orderTest()
{
	OrderGrlex<6> o1;
	OrderGr<OrderLex<6> > o2;
	Monom<6> m1;
	do
	{
		Monom<6> m2;
		do
		{
			if (o1.Compare(m1, m2) != o2.Compare(m1, m2))
				return false;
		}
		while (m2.Next());
	}
	while (m1.Next());
	return true;
}

bool bentTest()
{
	typedef Monom<12> X;
	MPoly<12> p;
	BFunc<12> bf;
	//
	p = X(0,6) + X(1, 7) + X(2, 8) + X(3, 9);
	p += X(4, 10) + X(5, 11);
	//
	bf.From(p);
	return bf.IsBent();
}

bool sboxTest()
{
	static const word s_table[16] = {2,6,3,14,12,15,7,5,11,13,8,9,10,0,4,1};
	VSubst<4> s(s_table);
	//
	return s.Nl() == 4 &&
		s.Deg() == 3 && s.DegSpan() == 3 &&
		s.Dc(0) == 4 && s.Dc(1) == 4 && s.Dc(2) == 4 && s.Dc(3) == 3;
}

bool bashTest()
{
	typedef OrderGrevlex<6> O;
	typedef Monom<6> X;
	// S-
	word s_table[] = {1, 2, 3, 4, 6, 7, 5, 0};
	VSubst<3> s(s_table);
	Ideal<6, O> i;
	// i <- {x_{k + 3} - s_k(x_0, s_1, x_2): k = 0, 1, 2}
	MPoly<3, O> p;
	BFunc<3> bf;
	s.GetCoord(0, bf);
	bf.To(p);
	i.Insert(MPoly<6, O>(p) + X(3));
	s.GetCoord(1, bf);
	bf.To(p);
	i.Insert(MPoly<6, O>(p) + X(4));
	s.GetCoord(2, bf);
	bf.To(p);
	i.Insert(MPoly<6, O>(p) + X(5));
	//
	Buchb<6, O> bb;
	bb.Init();
	bb.Update(i);
	bb.Process();
	bb.Done(i);
	//
	Env::Trace("");
	return i.Size() == 14;
}

bool commuteTest()
{
	typedef OrderGrevlex<8> O;
	//
	stringstream ss;
	ss <<
		"{ x0 x3 + x1 x2 + 1,"				/*    */
		"  x1 x6 + x2 x5,"					/*  */
		"  x1 x7 + x3 x5 + x0 x5 + x1 x4,"	/*  */
		"  x2 x7 + x3 x6 + x0 x6 + x2 x4,"	/*  */
		"  x4 x7 + x5 x6 + 1}";				/*    */
	Ideal<8, O> i;
	ss >> i;
	//
	Buchb<8, O> bb;
	bb.Init();
	bb.Update(i);
	bb.Process();
	bb.Done(i);
	//  ?
	if (!i.IsGB())
		return false;
	//
	return i.QuotientBasisDim() == (word)18;
}

/*
*******************************************************************************
main
*******************************************************************************
*/

int main()
{
	bool code;
	int ret = 0;
	Env::Print("gf2/test [gf2 version %s]\n", Env::Version());
	Env::Print("orderTest: %s\n", (code = orderTest()) ? "OK" : "Err"),
		ret |= !code;
	Env::Print("bentTest: %s\n", (code = bentTest()) ? "OK" : "Err"),
		ret |= !code;
	Env::Print("sboxTest: %s\n", (code = sboxTest()) ? "OK" : "Err"),
		ret |= !code;
	Env::Print("bashTest: %s\n", (code = bashTest()) ? "OK" : "Err"),
		ret |= !code;
	Env::Print("commuteTest: %s\n", (code = commuteTest()) ? "OK" : "Err"),
		ret |= !code;
	return ret;
}
<commit_msg>+= beltTest<commit_after>/*
*******************************************************************************
\file test.cpp
\brief Tests
\project GF2 [GF(2) algebra library]
\author (С) Sergey Agievich [agievich@{bsu.by|gmail.com}]
\created 2016.07.06
\version 2017.06.02
\license This program is released under the MIT License. See Copyright Notices
in GF2/info.h.
*******************************************************************************
*/

#include "gf2/buchb.h"
#include "gf2/func.h"
#include "gf2/ideal.h"
#include <sstream>

using namespace GF2;
using namespace std;

/*
*******************************************************************************
Явное проверочное инстанциирование
*******************************************************************************
*/

template class Word<127>;
	template class Monom<129>;
	template class ZZ<130>;

template struct OrderGr<OrderLR<OrderLex<65>, OrderGrlex<66> > >;
template struct OrderRL<OrderRev<OrderGrevlex<68> >, OrderLex<67> >;

template class MPoly<135, OrderLex<135> >;
template class Ideal<136, OrderGrevlex<136> >;
template class Buchb<137, OrderGrlex<137> >;

template class Func<5, int>;
	template class BFunc<6>;
	template class VFunc<7, 8>;
		template class VSubst<8>;
/*
*******************************************************************************
Тесты

#	orderTest: проверка тождественности OrderGrlex<6> и OrderGr<OrderLex<6> >;
#	bentTest: проверка бентовости функции Майораны-МакФарланда;
#	sboxTest: проверка криптографических характеристик 4-битового S-блока
	(by.gost28147.params.1);
#	beltTest: проверка криптографических характеристик 8-битового S-блока belt
	(СТБ 34.101.31);
#	bashTest: базис Гребнера идеала, описывающего S-блок Bash;
#	commuteTest: коммутируемые обратимые двоичные матрицы порядка 2.
*******************************************************************************
*/

bool orderTest()
{
	OrderGrlex<6> o1;
	OrderGr<OrderLex<6> > o2;
	Monom<6> m1;
	do
	{
		Monom<6> m2;
		do
		{
			if (o1.Compare(m1, m2) != o2.Compare(m1, m2))
				return false;
		}
		while (m2.Next());
	}
	while (m1.Next());
	return true;
}

bool bentTest()
{
	typedef Monom<12> X;
	MPoly<12> p;
	BFunc<12> bf;
	// многочлен
	p = X(0,6) + X(1, 7) + X(2, 8) + X(3, 9);
	p += X(4, 10) + X(5, 11);
	// функция
	bf.From(p);
	return bf.IsBent();
}

bool sboxTest()
{
	static const word s_table[16] = {2,6,3,14,12,15,7,5,11,13,8,9,10,0,4,1};
	VSubst<4> s(s_table);
	// характеристики
	return s.Nl() == 4 &&
		s.Deg() == 3 && s.DegSpan() == 3 &&
		s.Dc(0) == 4 && s.Dc(1) == 4 && s.Dc(2) == 4 && s.Dc(3) == 3;
}

bool beltTest(bool verbose = false)
{
	static const word h_table[256] = {
		0xB1,0x94,0xBA,0xC8,0x0A,0x08,0xF5,0x3B,0x36,0x6D,0x00,0x8E,0x58,0x4A,0x5D,0xE4,
		0x85,0x04,0xFA,0x9D,0x1B,0xB6,0xC7,0xAC,0x25,0x2E,0x72,0xC2,0x02,0xFD,0xCE,0x0D,
		0x5B,0xE3,0xD6,0x12,0x17,0xB9,0x61,0x81,0xFE,0x67,0x86,0xAD,0x71,0x6B,0x89,0x0B,
		0x5C,0xB0,0xC0,0xFF,0x33,0xC3,0x56,0xB8,0x35,0xC4,0x05,0xAE,0xD8,0xE0,0x7F,0x99,
		0xE1,0x2B,0xDC,0x1A,0xE2,0x82,0x57,0xEC,0x70,0x3F,0xCC,0xF0,0x95,0xEE,0x8D,0xF1,
		0xC1,0xAB,0x76,0x38,0x9F,0xE6,0x78,0xCA,0xF7,0xC6,0xF8,0x60,0xD5,0xBB,0x9C,0x4F,
		0xF3,0x3C,0x65,0x7B,0x63,0x7C,0x30,0x6A,0xDD,0x4E,0xA7,0x79,0x9E,0xB2,0x3D,0x31,
		0x3E,0x98,0xB5,0x6E,0x27,0xD3,0xBC,0xCF,0x59,0x1E,0x18,0x1F,0x4C,0x5A,0xB7,0x93,
		0xE9,0xDE,0xE7,0x2C,0x8F,0x0C,0x0F,0xA6,0x2D,0xDB,0x49,0xF4,0x6F,0x73,0x96,0x47,
		0x06,0x07,0x53,0x16,0xED,0x24,0x7A,0x37,0x39,0xCB,0xA3,0x83,0x03,0xA9,0x8B,0xF6,
		0x92,0xBD,0x9B,0x1C,0xE5,0xD1,0x41,0x01,0x54,0x45,0xFB,0xC9,0x5E,0x4D,0x0E,0xF2,
		0x68,0x20,0x80,0xAA,0x22,0x7D,0x64,0x2F,0x26,0x87,0xF9,0x34,0x90,0x40,0x55,0x11,
		0xBE,0x32,0x97,0x13,0x43,0xFC,0x9A,0x48,0xA0,0x2A,0x88,0x5F,0x19,0x4B,0x09,0xA1,
		0x7E,0xCD,0xA4,0xD0,0x15,0x44,0xAF,0x8C,0xA5,0x84,0x50,0xBF,0x66,0xD2,0xE8,0x8A,
		0xA2,0xD7,0x46,0x52,0x42,0xA8,0xDF,0xB3,0x69,0x74,0xC5,0x51,0xEB,0x23,0x29,0x21,
		0xD4,0xEF,0xD9,0xB4,0x3A,0x62,0x28,0x75,0x91,0x14,0x10,0xEA,0x77,0x6C,0xDA,0x1D,
	};
	VSubst<8> s(h_table);
	word a, x;
	// характеристики s
	if (s.Nl() != 102 || s.Deg() != 7 || s.DegSpan() != 6 ||
		s.Dc(0) != 8 || s.Dc(1) != 6 || s.Dc(2) != 3 || s.Dc(3) != 7)
		return false;
	if (!verbose)
		return true;
	// характеристики add-семейства
	for (a = 1; a < 256; ++a)
	{
		VSubst<8> t;
		for (x = 0; x < 256; ++x)
			t[x] = s[(x + a) % 256];
		if (t.Nl() < 96 || t.Deg() != 7 || t.Dc(0) > 10 || t.Dc(1) > 8)
			return false;
	}
	return true;
}

bool bashTest()
{
	typedef OrderGrevlex<6> O;
	typedef Monom<6> X;
	// S-блок и его идеал
	word s_table[] = {1, 2, 3, 4, 6, 7, 5, 0};
	VSubst<3> s(s_table);
	Ideal<6, O> i;
	// i <- {x_{k + 3} - s_k(x_0, s_1, x_2): k = 0, 1, 2}
	MPoly<3, O> p;
	BFunc<3> bf;
	s.GetCoord(0, bf);
	bf.To(p);
	i.Insert(MPoly<6, O>(p) + X(3));
	s.GetCoord(1, bf);
	bf.To(p);
	i.Insert(MPoly<6, O>(p) + X(4));
	s.GetCoord(2, bf);
	bf.To(p);
	i.Insert(MPoly<6, O>(p) + X(5));
	// базис Гребнера
	Buchb<6, O> bb;
	bb.Init();
	bb.Update(i);
	bb.Process();
	bb.Done(i);
	// завершение
	Env::Trace("");
	return i.Size() == 14;
}

bool commuteTest()
{
	typedef OrderGrevlex<8> O;
	// система
	stringstream ss;
	ss <<
		"{ x0 x3 + x1 x2 + 1,"				/* обратимость первой матрицы */
		"  x1 x6 + x2 x5,"					/* коммутируемость */
		"  x1 x7 + x3 x5 + x0 x5 + x1 x4,"	/* коммутируемость */
		"  x2 x7 + x3 x6 + x0 x6 + x2 x4,"	/* коммутируемость */
		"  x4 x7 + x5 x6 + 1}";				/* обратимость второй матрицы */
	Ideal<8, O> i;
	ss >> i;
	// базис Гребнера
	Buchb<8, O> bb;
	bb.Init();
	bb.Update(i);
	bb.Process();
	bb.Done(i);
	// базис Гребнера?
	if (!i.IsGB())
		return false;
	// количество матриц
	return i.QuotientBasisDim() == (word)18;
}

/*
*******************************************************************************
main
*******************************************************************************
*/

int main()
{
	bool code;
	int ret = 0;
	Env::Print("gf2/test [gf2 version %s]\n", Env::Version());
	Env::Print("orderTest: %s\n", (code = orderTest()) ? "OK" : "Err"),
		ret |= !code;
	Env::Print("bentTest: %s\n", (code = bentTest()) ? "OK" : "Err"),
		ret |= !code;
	Env::Print("sboxTest: %s\n", (code = sboxTest()) ? "OK" : "Err"),
		ret |= !code;
	Env::Print("beltTest: %s\n", (code = beltTest()) ? "OK" : "Err"),
		ret |= !code;
	Env::Print("bashTest: %s\n", (code = bashTest()) ? "OK" : "Err"),
		ret |= !code;
	Env::Print("commuteTest: %s\n", (code = commuteTest()) ? "OK" : "Err"),
		ret |= !code;
	return ret;
}
<|endoftext|>


<commit_before>#include "token.hpp"

namespace laskin
{
    static inline bool isword(char);

    token::token(enum type type, const std::string& data)
        : m_type(type)
        , m_data(data) {}

    token::token(const token& that)
        : m_type(that.m_type)
        , m_data(that.m_data) {}

    std::vector<token> token::scan(std::istream& is)
        throw(syntax_error)
    {
        std::vector<token> tokens;
        std::string buffer;

        for (std::istreambuf_iterator<char> current(is), end; current != end;)
        {
            char c = *current++;

            switch (c)
            {
                // Skip comments.
                case '#':
                    while (current != end)
                    {
                        if (*current++ == '\n')
                        {
                            break;
                        }
                    }
                    break;

                // Skip whitespace.
                case ' ':
                case '\t':
                case '\r':
                case '\n':
                    break;

                // Various separators.
                case '(': case ')':
                case '[': case ']':
                case '{': case '}':
                case ':':
                    tokens.push_back(token(
                                c == '(' ? type_lparen :
                                c == ')' ? type_rparen :
                                c == '[' ? type_lbrack :
                                c == ']' ? type_rbrack :
                                c == '{' ? type_lbrace :
                                c == '}' ? type_rbrace :
                                type_colon
                    ));
                    break;

                // Parse numbers from zero.
                case '0':
                    buffer.assign(1, '0');
                    if (current != end)
                    {
SCAN_NUMBER_FROM_ZERO:
                        switch (c = *current++)
                        {
                            case 'b': case 'B':
                                buffer.append(1, c);
                                while (current != end && std::isdigit(*current))
                                {
                                    if ((c = *current++) != '0' && c != '1')
                                    {
                                        throw syntax_error(
                                                "invalid binary digit"
                                        );
                                    }
                                    buffer.append(1, c);
                                }
                                break;

                            case 'x': case 'X':
                                buffer.append(1, 'x');
                                while (current != end && std::isxdigit(*current))
                                {
                                    buffer.append(1, *current++);
                                }
                                break;

                            case 'o': case 'O':
                            case '0': case '1':
                            case '2': case '3':
                            case '4': case '5':
                            case '6': case '7':
                                buffer.append(1, c);
                                while (current != end && std::isdigit(*current))
                                {
                                    if ((c = *current++) > '7')
                                    {
                                        throw syntax_error(
                                                "invalid octal digit"
                                        );
                                    }
                                    buffer.append(1, c);
                                }
                                break;

                            case '8': case '9':
                                throw syntax_error("invalid octal digit");

                            case 'e': case 'E':
                                goto SCAN_EXPONENT;

                            case '.':
                                goto SCAN_REAL;
                        }
                    }
                    tokens.push_back(token(type_integer, buffer));
                    break;

                // Parse numbers.
                case '1': case '2': case '3':
                case '4': case '5': case '6':
                case '7': case '8': case '9':
                    buffer.assign(1, c);
SCAN_NUMBER:
                    while (current != end && std::isdigit(*current))
                    {
                        buffer.append(1, *current++);
                    }
                    if (current != end && *current == '.')
                    {
                        ++current;
SCAN_REAL:
                        buffer.append(1, '.');
                        if (current == end || !std::isdigit(*current))
                        {
                            throw syntax_error("missing digits after `.'");
                        }
                        do
                        {
                            buffer.append(1, *current++);
                        }
                        while (current != end && std::isdigit(*current));
                        if (current != end && (*current == 'e' || *current == 'E'))
                        {
SCAN_EXPONENT:
                            buffer.append(1, 'e');
                            ++current;
                            if (current != end && (*current == '+' || *current == '-'))
                            {
                                buffer.append(1, *current++);
                            }
                            if (current == end || !std::isdigit(*current))
                            {
                                throw syntax_error("missing exponent");
                            }
                            do
                            {
                                buffer.append(1, *current++);
                            }
                            while (current != end && std::isdigit(*current));
                        }
                        tokens.push_back(token(type_real, buffer));
                    } else {
                        tokens.push_back(token(type_integer, buffer));
                    }
                    break;

                // Parse string literals.
                case '"':
                case '\'':
                {
                    buffer.clear();
                    while (current != end && *current != c)
                    {
                        if (*current == '\\')
                        {
                            // TODO: process escape sequence
                        } else {
                            buffer.append(1, *current++);
                        }
                    }
                    if (current == end)
                    {
                        throw syntax_error("unterminated string literal");
                    }
                    tokens.push_back(token(type_string, buffer));
                    ++current;
                    break;
                }

                case '-':
                case '+':
                    buffer.assign(1, c);
                    if (current != end)
                    {
                        if (*current == '0')
                        {
                            goto SCAN_NUMBER_FROM_ZERO;
                        }
                        else if (std::isdigit(*current))
                        {
                            goto SCAN_NUMBER;
                        }
                    }
                    goto SCAN_WORD;

                default:
                    if (isword(c))
                    {
                        buffer.assign(1, c);
SCAN_WORD:
                        while (current != end && isword(*current))
                        {
                            buffer.append(1, *current++);
                        }
                        tokens.push_back(token(type_word, buffer));
                    } else {
                        throw syntax_error("unexpected input");
                    }
            }
        }

        return tokens;
    }

    token& token::assign(const token& that)
    {
        m_type = that.m_type;
        m_data = that.m_data;

        return *this;
    }

    std::ostream& operator<<(std::ostream& os, const class token& token)
    {
        switch (token.type())
        {
            case token::type_lparen:
                os << "`('";
                break;

            case token::type_rparen:
                os << "`)'";
                break;

            case token::type_lbrack:
                os << "`['";
                break;

            case token::type_rbrack:
                os << "`]'";
                break;

            case token::type_lbrace:
                os << "`{'";
                break;

            case token::type_rbrace:
                os << "`}'";
                break;

            case token::type_colon:
                os << "`:'";
                break;

            case token::type_integer:
            case token::type_real:
                os << token.data();
                break;

            case token::type_string:
                os << "string literal";
                break;

            case token::type_word:
                os << "`" << token.data() << "'";
        }

        return os;
    }

    std::ostream& operator<<(std::ostream& os, enum token::type type)
    {
        switch (type)
        {
            case token::type_lparen:
                os << "`('";
                break;

            case token::type_rparen:
                os << "`)'";
                break;

            case token::type_lbrack:
                os << "`['";
                break;

            case token::type_rbrack:
                os << "`]'";
                break;

            case token::type_lbrace:
                os << "`{'";
                break;

            case token::type_rbrace:
                os << "`}'";
                break;

            case token::type_colon:
                os << "`:'";
                break;

            case token::type_integer:
            case token::type_real:
                os << "number literal";
                break;

            case token::type_string:
                os << "string literal";
                break;

            case token::type_word:
                os << "word";
        }

        return os;
    }

    static inline bool isword(char c)
    {
        return (c >= '0' && c <= '9')
            || (c >= 'a' && c <= 'z')
            || (c >= 'A' && c <= 'Z')
            || c == '!'
            || c == '$'
            || c == '%'
            || c == '&'
            || c == '\''
            || c == '*'
            || c == '+'
            || c == ','
            || c == '-'
            || c == '.'
            || c == '/'
            || c == ';'
            || c == '<'
            || c == '>'
            || c == '='
            || c == '?'
            || c == '@'
            || c == '^'
            || c == '_'
            || c == '`'
            || c == '|'
            || c == '~';
    }
}
<commit_msg>fix number scaning routine<commit_after>#include "token.hpp"

namespace laskin
{
    static inline bool isword(char);

    token::token(enum type type, const std::string& data)
        : m_type(type)
        , m_data(data) {}

    token::token(const token& that)
        : m_type(that.m_type)
        , m_data(that.m_data) {}

    std::vector<token> token::scan(std::istream& is)
        throw(syntax_error)
    {
        std::vector<token> tokens;
        std::string buffer;

        for (std::istreambuf_iterator<char> current(is), end; current != end;)
        {
            char c = *current++;

            switch (c)
            {
                // Skip comments.
                case '#':
                    while (current != end)
                    {
                        if (*current++ == '\n')
                        {
                            break;
                        }
                    }
                    break;

                // Skip whitespace.
                case ' ':
                case '\t':
                case '\r':
                case '\n':
                    break;

                // Various separators.
                case '(': case ')':
                case '[': case ']':
                case '{': case '}':
                case ':':
                    tokens.push_back(token(
                                c == '(' ? type_lparen :
                                c == ')' ? type_rparen :
                                c == '[' ? type_lbrack :
                                c == ']' ? type_rbrack :
                                c == '{' ? type_lbrace :
                                c == '}' ? type_rbrace :
                                type_colon
                    ));
                    break;

                // Parse numbers from zero.
                case '0':
                    buffer.assign(1, '0');
                    if (current != end)
                    {
SCAN_NUMBER_FROM_ZERO:
                        switch (c = *current++)
                        {
                            case 'b': case 'B':
                                buffer.append(1, c);
                                while (current != end && std::isdigit(*current))
                                {
                                    if ((c = *current++) != '0' && c != '1')
                                    {
                                        throw syntax_error(
                                                "invalid binary digit"
                                        );
                                    }
                                    buffer.append(1, c);
                                }
                                break;

                            case 'x': case 'X':
                                buffer.append(1, 'x');
                                while (current != end && std::isxdigit(*current))
                                {
                                    buffer.append(1, *current++);
                                }
                                break;

                            case 'o': case 'O':
                            case '0': case '1':
                            case '2': case '3':
                            case '4': case '5':
                            case '6': case '7':
                                buffer.append(1, c);
                                while (current != end && std::isdigit(*current))
                                {
                                    if ((c = *current++) > '7')
                                    {
                                        throw syntax_error(
                                                "invalid octal digit"
                                        );
                                    }
                                    buffer.append(1, c);
                                }
                                break;

                            case '8': case '9':
                                throw syntax_error("invalid octal digit");

                            case 'e': case 'E':
                                goto SCAN_EXPONENT;

                            case '.':
                                goto SCAN_REAL;
                        }
                    }
                    tokens.push_back(token(type_integer, buffer));
                    break;

                // Parse numbers.
                case '1': case '2': case '3':
                case '4': case '5': case '6':
                case '7': case '8': case '9':
                    buffer.assign(1, c);
SCAN_NUMBER:
                    while (current != end && std::isdigit(*current))
                    {
                        buffer.append(1, *current++);
                    }
                    if (current != end && *current == '.')
                    {
                        ++current;
SCAN_REAL:
                        buffer.append(1, '.');
                        if (current == end || !std::isdigit(*current))
                        {
                            throw syntax_error("missing digits after `.'");
                        }
                        do
                        {
                            buffer.append(1, *current++);
                        }
                        while (current != end && std::isdigit(*current));
                        if (current != end && (*current == 'e' || *current == 'E'))
                        {
SCAN_EXPONENT:
                            buffer.append(1, 'e');
                            ++current;
                            if (current != end && (*current == '+' || *current == '-'))
                            {
                                buffer.append(1, *current++);
                            }
                            if (current == end || !std::isdigit(*current))
                            {
                                throw syntax_error("missing exponent");
                            }
                            do
                            {
                                buffer.append(1, *current++);
                            }
                            while (current != end && std::isdigit(*current));
                        }
                        tokens.push_back(token(type_real, buffer));
                    } else {
                        tokens.push_back(token(type_integer, buffer));
                    }
                    break;

                // Parse string literals.
                case '"':
                case '\'':
                {
                    buffer.clear();
                    while (current != end && *current != c)
                    {
                        if (*current == '\\')
                        {
                            // TODO: process escape sequence
                        } else {
                            buffer.append(1, *current++);
                        }
                    }
                    if (current == end)
                    {
                        throw syntax_error("unterminated string literal");
                    }
                    tokens.push_back(token(type_string, buffer));
                    ++current;
                    break;
                }

                case '-':
                case '+':
                    buffer.assign(1, c);
                    if (current != end)
                    {
                        if (*current == '0')
                        {
                            buffer.append(1, *current++);
                            goto SCAN_NUMBER_FROM_ZERO;
                        }
                        else if (std::isdigit(*current))
                        {
                            buffer.append(1, *current++);
                            goto SCAN_NUMBER;
                        }
                    }
                    goto SCAN_WORD;

                default:
                    if (isword(c))
                    {
                        buffer.assign(1, c);
SCAN_WORD:
                        while (current != end && isword(*current))
                        {
                            buffer.append(1, *current++);
                        }
                        tokens.push_back(token(type_word, buffer));
                    } else {
                        throw syntax_error("unexpected input");
                    }
            }
        }

        return tokens;
    }

    token& token::assign(const token& that)
    {
        m_type = that.m_type;
        m_data = that.m_data;

        return *this;
    }

    std::ostream& operator<<(std::ostream& os, const class token& token)
    {
        switch (token.type())
        {
            case token::type_lparen:
                os << "`('";
                break;

            case token::type_rparen:
                os << "`)'";
                break;

            case token::type_lbrack:
                os << "`['";
                break;

            case token::type_rbrack:
                os << "`]'";
                break;

            case token::type_lbrace:
                os << "`{'";
                break;

            case token::type_rbrace:
                os << "`}'";
                break;

            case token::type_colon:
                os << "`:'";
                break;

            case token::type_integer:
            case token::type_real:
                os << token.data();
                break;

            case token::type_string:
                os << "string literal";
                break;

            case token::type_word:
                os << "`" << token.data() << "'";
        }

        return os;
    }

    std::ostream& operator<<(std::ostream& os, enum token::type type)
    {
        switch (type)
        {
            case token::type_lparen:
                os << "`('";
                break;

            case token::type_rparen:
                os << "`)'";
                break;

            case token::type_lbrack:
                os << "`['";
                break;

            case token::type_rbrack:
                os << "`]'";
                break;

            case token::type_lbrace:
                os << "`{'";
                break;

            case token::type_rbrace:
                os << "`}'";
                break;

            case token::type_colon:
                os << "`:'";
                break;

            case token::type_integer:
            case token::type_real:
                os << "number literal";
                break;

            case token::type_string:
                os << "string literal";
                break;

            case token::type_word:
                os << "word";
        }

        return os;
    }

    static inline bool isword(char c)
    {
        return (c >= '0' && c <= '9')
            || (c >= 'a' && c <= 'z')
            || (c >= 'A' && c <= 'Z')
            || c == '!'
            || c == '$'
            || c == '%'
            || c == '&'
            || c == '\''
            || c == '*'
            || c == '+'
            || c == ','
            || c == '-'
            || c == '.'
            || c == '/'
            || c == ';'
            || c == '<'
            || c == '>'
            || c == '='
            || c == '?'
            || c == '@'
            || c == '^'
            || c == '_'
            || c == '`'
            || c == '|'
            || c == '~';
    }
}
<|endoftext|>


<commit_before>#include <gtest/gtest.h>

#include "gridpoint.hpp"

TEST(Point, gribpoint_check) {
    GridPoint p1(2,2);
    GridPoint p2(3,3);
    GridPoint p3(5,5);

    GridPoint a = p1+p2;
    GridPoint b = p3-p1;

    ASSERT_TRUE(p3==a);
    ASSERT_TRUE(p2==b);

    p1.calH(p3);
    p1.calG(p2);
    p1.calF();

    ASSERT_GE(p1.getG(), 10);
    ASSERT_GT(p1.getH(), 0);
    ASSERT_GT(p1.getF(), 0);
}
<commit_msg>Added Test<commit_after>#include <gtest/gtest.h>

#include "gridpoint.hpp"

TEST(Point, gribpoint_check) {
    GridPoint p1(2,2);
    GridPoint p2(3,3);
    GridPoint p3(5,5);

    GridPoint a = p1+p2;
    GridPoint b = p3-p1;

    ASSERT_TRUE(p3==a);
    ASSERT_TRUE(p2==b);

    p1.calH(p3);
    p1.calG(p2);
    p1.calF();

    ASSERT_GE(p1.getG(), 10);
    ASSERT_GT(p1.getH(), 0);
    ASSERT_GT(p1.getF(), 0);

    p1.setStatus(PATH);

    ASSERT_EQ(p1.getStatus(), 3);
}
<|endoftext|>


<commit_before>#include <iostream>
#include "tools.h"

using Eigen::VectorXd;
using Eigen::MatrixXd;
using std::vector;

Tools::Tools() {}

Tools::~Tools() {}

VectorXd Tools::CalculateRMSE(const vector<VectorXd> &estimations,
                              const vector<VectorXd> &ground_truth) {
    // Calculate the RMSE.
    VectorXd rmse(4);
    rmse << 0, 0, 0, 0;

	// check the validity of the following inputs:
	//  * the estimation vector size should not be zero
	//  * the estimation vector size should equal ground truth vector size
	if (estimations.size() != ground_truth.size()
			|| estimations.size() == 0){
		cout << "Invalid estimation or ground_truth data" << endl;
		return rmse;
	}

	// Accumulate squared residuals
	for(unsigned int i = 0; i < estimations.size(); ++i) {
		VectorXd residual = estimations[i] - ground_truth[i];
		// Coefficient-wise multiplication
		residual = residual.array() * residual.array();
		rmse += residual;
	}

	// Calculate the mean
	rmse = rmse / estimations.size();

	// Calculate the squared root
	rmse = rmse.array().sqrt();

	// Return the result
	return rmse;
}

MatrixXd Tools::CalculateJacobian(const VectorXd& x_state) {
	// Calculate a Jacobian.
	MatrixXd Hj(3, 4);

	// Recover state parameters
	float px = x_state(0);
	float py = x_state(1);
	float vx = x_state(2);
	float vy = x_state(3);

	// Pre-compute a set of terms to avoid repeated calculation
	float c1 = px*px + py*py;
	float c2 = sqrt(c1);
	float c3 = (c1*c2);

	// Check division by zero
	if (fabs(c1) < 0.0001) {
		cout << "CalculateJacobian () - Error - Division by Zero" << endl;
		return Hj;
	}

	// Compute the Jacobian matrix
	Hj << (px/c2), (py/c2), 0, 0,
            -(py/c1), (px/c1), 0, 0,
            py*(vx*py - vy*px)/c3, px*(px*vy - py*vx)/c3, px/c2, py/c2;

	return Hj;
}
<commit_msg>Minor fixes<commit_after>#include <iostream>
#include "tools.h"

using Eigen::VectorXd;
using Eigen::MatrixXd;
using std::vector;

Tools::Tools() {}

Tools::~Tools() {}

VectorXd Tools::CalculateRMSE(const vector<VectorXd> &estimations,
                              const vector<VectorXd> &ground_truth) {
    // Calculate the RMSE.
    VectorXd rmse(4);
    rmse << 0, 0, 0, 0;

    // check the validity of the following inputs:
    //  * the estimation vector size should not be zero
    //  * the estimation vector size should equal ground truth vector size
    if (estimations.size() != ground_truth.size()
        || estimations.size() == 0){
        cout << "Invalid estimation or ground_truth data" << endl;
        return rmse;
    }

    // Accumulate squared residuals
    for(unsigned int i = 0; i < estimations.size(); ++i) {
        VectorXd residual = estimations[i] - ground_truth[i];
        // Coefficient-wise multiplication
        residual = residual.array() * residual.array();
        rmse += residual;
    }

    // Calculate the mean
    rmse = rmse / estimations.size();

    // Calculate the squared root
    rmse = rmse.array().sqrt();

    // Return the result
    return rmse;
}

MatrixXd Tools::CalculateJacobian(const VectorXd& x_state) {
    // Calculate a Jacobian.
    MatrixXd Hj(3, 4);

    // Recover state parameters
    float px = x_state(0);
    float py = x_state(1);
    float vx = x_state(2);
    float vy = x_state(3);

    // Pre-compute a set of terms to avoid repeated calculation
    float c1 = px*px + py*py;
    float c2 = sqrt(c1);
    float c3 = (c1*c2);

    // Check division by zero
    if (fabs(c1) < 0.0001) {
        cout << "CalculateJacobian () - Error - Division by Zero" << endl;
        return Hj;
    }

    // Compute the Jacobian matrix
    Hj << (px/c2), (py/c2), 0, 0,
    -(py/c1), (px/c1), 0, 0,
    py*(vx*py - vy*px)/c3, px*(px*vy - py*vx)/c3, px/c2, py/c2;

    return Hj;
}
<|endoftext|>


<commit_before>#define CATCH_CONFIG_MAIN
#include <catch.hpp>

#include "../picojson_serializer.h"
#include "test_helpers.h"

namespace {
    struct Point {
        double x, y, z;

        friend class picojson::convert::access;
        template<class Archive>
        void json(Archive & ar) const
        {
            ar & picojson::convert::member("x", x);
            ar & picojson::convert::member("y", y);
            ar & picojson::convert::member("z", z);
        }
        template<class Archive>
        void json(Archive & ar)
        {
            ar & picojson::convert::member("x", x);
            ar & picojson::convert::member("y", y);
            ar & picojson::convert::member("z", z);
        }
    };

    struct NamedPoint {
        std::string name;
        Point point;

        friend class picojson::convert::access;
        template<class Archive>
        void json(Archive & ar) const
        {
            ar & picojson::convert::member("name", name);
            ar & picojson::convert::member("point", point);
        }
        template<class Archive>
        void json(Archive & ar)
        {
            ar & picojson::convert::member("name", name);
            ar & picojson::convert::member("point", point);
        }
    };
}

TEST_CASE() {

    SECTION("serialization") {

        Point p = { 1, 2, 3 };
        picojson::value pv = picojson::convert::to_value(p);
        CHECK(has<double>(pv, "x", 1));
        CHECK(has<double>(pv, "y", 2));
        CHECK(has<double>(pv, "z", 3));

        std::string test_point_name("test point");
        NamedPoint np = { test_point_name , p };

        picojson::value npv = picojson::convert::to_value(np);
        CHECK(has<std::string>(npv, "name", test_point_name));
        CHECK(has<picojson::object>(npv, "point"));

        SECTION("deserialization from value") {
            Point np_ = { 0, 0, 0 };
            picojson::convert::from_value(pv, np_);
            CHECK(np_.x == 1);
            CHECK(np_.y == 2);
            CHECK(np_.z == 3);

            NamedPoint nnp = { "", { 0, 0, 0 } };
            picojson::convert::from_value(npv, nnp);
            CHECK(nnp.name == test_point_name);
            CHECK(nnp.point.x == 1);
            CHECK(nnp.point.y == 2);
            CHECK(nnp.point.z == 3);

            SECTION("deserialization from string") {
                std::string ps = picojson::convert::to_string(p);
                Point pss = { 0, 0, 0 };
                picojson::convert::from_string(ps, pss);
                CHECK(pss.x == 1);
                CHECK(pss.y == 2);
                CHECK(pss.z == 3);

                std::string nps = picojson::convert::to_string(np);
                NamedPoint npss = { "", { 0, 0, 0 } };
                picojson::convert::from_string(nps, npss);
                CHECK(npss.name == test_point_name);
                CHECK(npss.point.x == 1);
                CHECK(npss.point.y == 2);
                CHECK(npss.point.z == 3);
            }
        }

        SECTION("const data") {
            Point const pc = { 1, 2, 3 };
            pv = picojson::convert::to_value(pc);
            CHECK(has<double>(pv, "x", 1));
            CHECK(has<double>(pv, "y", 2));
            CHECK(has<double>(pv, "z", 3));

            NamedPoint const npc = { test_point_name , p };

            npv = picojson::convert::to_value(npc);
            CHECK(has<std::string>(npv, "name", test_point_name));
            CHECK(has<picojson::object>(npv, "point"));
        }
    }

    SECTION("boundary cases") {
        const Point p1 = { 1, 2, 3 };

        SECTION("cannot deserialize an object from an array") {
            picojson::array a;
            a.emplace_back(picojson::convert::to_value(p1));

            Point p2 = { 0, 0, 0 };
            picojson::convert::from_string(picojson::value(a).serialize(), p2);

            CHECK(p2.x == 0);
            CHECK(p2.y == 0);
            CHECK(p2.z == 0);
        }

        SECTION("missing fields are ignored") {
            picojson::value p1v(picojson::convert::to_value(p1));
            REQUIRE(p1v.is<picojson::object>());
            p1v.get<picojson::object>()["z"] = picojson::value();

            Point p2 = { 42, 42, 42 };
            picojson::convert::from_value(p1v, p2);

            CHECK(p2.x == 1);
            CHECK(p2.y == 2);
            CHECK(p2.z == 42);
        }
    }
}
<commit_msg>test is c++03<commit_after>#define CATCH_CONFIG_MAIN
#include <catch.hpp>

#include "../picojson_serializer.h"
#include "test_helpers.h"

namespace {
    struct Point {
        double x, y, z;

        friend class picojson::convert::access;
        template<class Archive>
        void json(Archive & ar) const
        {
            ar & picojson::convert::member("x", x);
            ar & picojson::convert::member("y", y);
            ar & picojson::convert::member("z", z);
        }
        template<class Archive>
        void json(Archive & ar)
        {
            ar & picojson::convert::member("x", x);
            ar & picojson::convert::member("y", y);
            ar & picojson::convert::member("z", z);
        }
    };

    struct NamedPoint {
        std::string name;
        Point point;

        friend class picojson::convert::access;
        template<class Archive>
        void json(Archive & ar) const
        {
            ar & picojson::convert::member("name", name);
            ar & picojson::convert::member("point", point);
        }
        template<class Archive>
        void json(Archive & ar)
        {
            ar & picojson::convert::member("name", name);
            ar & picojson::convert::member("point", point);
        }
    };
}

TEST_CASE() {

    SECTION("serialization") {

        Point p = { 1, 2, 3 };
        picojson::value pv = picojson::convert::to_value(p);
        CHECK(has<double>(pv, "x", 1));
        CHECK(has<double>(pv, "y", 2));
        CHECK(has<double>(pv, "z", 3));

        std::string test_point_name("test point");
        NamedPoint np = { test_point_name , p };

        picojson::value npv = picojson::convert::to_value(np);
        CHECK(has<std::string>(npv, "name", test_point_name));
        CHECK(has<picojson::object>(npv, "point"));

        SECTION("deserialization from value") {
            Point np_ = { 0, 0, 0 };
            picojson::convert::from_value(pv, np_);
            CHECK(np_.x == 1);
            CHECK(np_.y == 2);
            CHECK(np_.z == 3);

            NamedPoint nnp = { "", { 0, 0, 0 } };
            picojson::convert::from_value(npv, nnp);
            CHECK(nnp.name == test_point_name);
            CHECK(nnp.point.x == 1);
            CHECK(nnp.point.y == 2);
            CHECK(nnp.point.z == 3);

            SECTION("deserialization from string") {
                std::string ps = picojson::convert::to_string(p);
                Point pss = { 0, 0, 0 };
                picojson::convert::from_string(ps, pss);
                CHECK(pss.x == 1);
                CHECK(pss.y == 2);
                CHECK(pss.z == 3);

                std::string nps = picojson::convert::to_string(np);
                NamedPoint npss = { "", { 0, 0, 0 } };
                picojson::convert::from_string(nps, npss);
                CHECK(npss.name == test_point_name);
                CHECK(npss.point.x == 1);
                CHECK(npss.point.y == 2);
                CHECK(npss.point.z == 3);
            }
        }

        SECTION("const data") {
            Point const pc = { 1, 2, 3 };
            pv = picojson::convert::to_value(pc);
            CHECK(has<double>(pv, "x", 1));
            CHECK(has<double>(pv, "y", 2));
            CHECK(has<double>(pv, "z", 3));

            NamedPoint const npc = { test_point_name , p };

            npv = picojson::convert::to_value(npc);
            CHECK(has<std::string>(npv, "name", test_point_name));
            CHECK(has<picojson::object>(npv, "point"));
        }
    }

    SECTION("boundary cases") {
        const Point p1 = { 1, 2, 3 };

        SECTION("cannot deserialize an object from an array") {
            picojson::array a;
            a.push_back(picojson::convert::to_value(p1));

            Point p2 = { 0, 0, 0 };
            picojson::convert::from_string(picojson::value(a).serialize(), p2);

            CHECK(p2.x == 0);
            CHECK(p2.y == 0);
            CHECK(p2.z == 0);
        }

        SECTION("missing fields are ignored") {
            picojson::value p1v(picojson::convert::to_value(p1));
            REQUIRE(p1v.is<picojson::object>());
            p1v.get<picojson::object>()["z"] = picojson::value();

            Point p2 = { 42, 42, 42 };
            picojson::convert::from_value(p1v, p2);

            CHECK(p2.x == 1);
            CHECK(p2.y == 2);
            CHECK(p2.z == 42);
        }
    }
}
<|endoftext|>


<commit_before>/*
*/
#include"types.hpp"
#include"heaps.hpp"
#include"processes.hpp"
#include"errors.hpp"
#include"executors.hpp"
#include"phandles.hpp"

/*O(N), where N is the number of objects involved!*/
/*necessary for determining the size of the semispace
to be allocated when sending messages.
*/
size_t Generic::total_size(ToPointerLock& toptrs, std::stack<Generic**>& s){
	Generic** gpp;
	Generic* to;
	size_t rv = get_size();
	/*Use the to-pointers as expensive marks*/
	toptrs.pointto(this, this);
	get_refs(s);
	while(!s.empty()){
		gpp = s.top(); s.pop();
		to = toptrs.to(*gpp);
		if(to == NULL){
			toptrs.pointto(*gpp, *gpp);
			rv += (*gpp)->get_size();
			(*gpp)->get_refs(s);
		}
	}
	/*toptrs' dtor should clear the to-pointers of the objects*/
	return rv;
}

Generic* Generic::type(Process& proc) {
	return new(proc) Sym(type_atom());
}

Generic* Generic::car(void) {
	throw ArcError("apply",
		"'car expects an object of type 'cons");
}

Generic* Generic::cdr(void) {
	throw ArcError("apply",
		"'cdr expects an object of type 'cons");
}

Generic* Generic::sv_ref(void) {
	throw ArcError("container",
		"expected an object of type 'container");
}

Generic* Generic::make_sv(Process& proc) {
	SharedVar* sp = new(proc) SharedVar();
	sp->val = this;
	return sp;
}

Generic* Cons::car(void){
	return a;
}

Generic* Cons::cdr(void){
	return d;
}

Generic* SharedVar::sv_ref(void) {
	return val;
}

Generic* Sym::car(void){
	if(isnil())	return this;
	else		Generic::car();
}

Generic* Sym::cdr(void){
	if(isnil())	return this;
	else		Generic::cdr();
}

Closure::Closure(Executor* c, size_t s)
	: Generic(), cd(c), vars(s) {}

Closure::Closure(boost::shared_ptr<Executor> c, size_t s)
	: Generic(), cd(c), vars(s) {}

KClosure::KClosure(Executor* c, size_t s)
	: Closure(c, s), nonreusable(0) {}

KClosure::KClosure(boost::shared_ptr<Executor> c, size_t s)
	: Closure(c, s), nonreusable(0) {}

ArcBytecodeSequence::ArcBytecodeSequence()
	: Generic(), seq(new BytecodeSequence()) {}

void ArcBytecodeSequence::append(Bytecode* b){
	seq->append(b);
}

/*DEBUG CODE*/
#include<iostream>
#define INDENT(ind)	for(size_t i = 0; i < ind; ++i) std::cout << "\t"
void Cons::probe(size_t ind){
	INDENT(ind); std::cout << "CONS cell@" <<
			std::hex << ((size_t)(this)) << std::endl;
	a->probe(ind+1);
	d->probe(ind+1);
}

void MetadataCons::probe(size_t ind){
	Cons::probe(ind);
	INDENT(ind); std::cout << "(metadata)" << std::endl;
	line->probe(ind+1);
	file->probe(ind+1);
}
#include"atoms.hpp"

void Sym::probe(size_t ind){
	INDENT(ind); std::cout << "SYMBOL: ";
	GlobalAtom* gp = dynamic_cast<GlobalAtom*>(a.get());
	if(gp != NULL) {gp->emit(); std::cout << std::endl;}
	else	std::cout << "<uniq>" << std::endl;
}

void Closure::probe(size_t ind){
	INDENT(ind); std::cout <<  "CLOSURE: fn@" <<
			std::hex << ((size_t) cd.get()) << " {" << std::endl;
	for(size_t i = 0; i < vars.size(); ++i){
		vars[i]->probe(ind+1);
	}
	INDENT(ind); std::cout << "}" << std::endl;
}

void KClosure::probe(size_t ind){
	Closure::probe(ind);
	INDENT(ind); std::cout << "(" <<
			(nonreusable ? "" : "reusable ") <<
			"continuation)" << std::endl;
}

void Integer::probe(size_t ind){
	INDENT(ind); std::cout << "INTEGER: " << std::dec << val <<
			" @" << std::hex << ((size_t)(this)) << std::endl;
}

void ArcBytecodeSequence::probe(size_t ind){
	INDENT(ind); std::cout << "BYTECODE @" <<
			std::hex << ((size_t) seq.get()) << std::endl;
}

void Tagged::probe(size_t ind){
	INDENT(ind); std::cout << "TAGGED @" <<
			std::hex << ((size_t) this) << std::endl;
	INDENT(ind); std::cout << "type:" << std::endl;
	type_o->probe(ind+1);
	INDENT(ind); std::cout << "rep:" << std::endl;
	rep_o->probe(ind+1);
}

void SharedVar::probe(size_t ind){
	INDENT(ind); std::cout << "SHAREDVAR @" <<
			std::hex << ((size_t) this) << std::endl;
	val->probe(ind+1);
}

void Pid::probe(size_t ind){
	INDENT(ind); std::cout << "PID @" <<
			std::hex << ((size_t) this) <<
			" referring to: " << ((size_t) hproc->pproc.get()) <<
			std::endl;
}

void BinaryBlob::probe(size_t ind){
	INDENT(ind); std::cout << "BINARY @" << std::hex << ((size_t) this) <<
			" referring to:" << ((size_t) pdat.get()) <<
			std::endl;
	for(size_t i = 0; i < pdat->size; ++i){
		INDENT(ind+1); std::cout << (*pdat)[i] << std::endl;
	}
}

void SemispacePackage(size_t ind){
	INDENT(ind); std::cout << "PACKAGE @" << std::hex << ((size_t) this) <<
			std::endl;
	INDENT(ind); std::cout << "Semispace @" << ((size_t) ns.get()) <<
			std::endl;
	gp->probe(ind+1);
}

<commit_msg>types: fixed compilation errors<commit_after>/*
*/
#include"types.hpp"
#include"heaps.hpp"
#include"processes.hpp"
#include"errors.hpp"
#include"executors.hpp"
#include"phandles.hpp"

/*O(N), where N is the number of objects involved!*/
/*necessary for determining the size of the semispace
to be allocated when sending messages.
*/
size_t Generic::total_size(ToPointerLock& toptrs, std::stack<Generic**>& s){
	Generic** gpp;
	Generic* to;
	size_t rv = get_size();
	/*Use the to-pointers as expensive marks*/
	toptrs.pointto(this, this);
	get_refs(s);
	while(!s.empty()){
		gpp = s.top(); s.pop();
		to = toptrs.to(*gpp);
		if(to == NULL){
			toptrs.pointto(*gpp, *gpp);
			rv += (*gpp)->get_size();
			(*gpp)->get_refs(s);
		}
	}
	/*toptrs' dtor should clear the to-pointers of the objects*/
	return rv;
}

Generic* Generic::type(Process& proc) {
	return new(proc) Sym(type_atom());
}

Generic* Generic::car(void) {
	throw ArcError("apply",
		"'car expects an object of type 'cons");
}

Generic* Generic::cdr(void) {
	throw ArcError("apply",
		"'cdr expects an object of type 'cons");
}

Generic* Generic::sv_ref(void) {
	throw ArcError("container",
		"expected an object of type 'container");
}

Generic* Generic::make_sv(Process& proc) {
	SharedVar* sp = new(proc) SharedVar();
	sp->val = this;
	return sp;
}

Generic* Cons::car(void){
	return a;
}

Generic* Cons::cdr(void){
	return d;
}

Generic* SharedVar::sv_ref(void) {
	return val;
}

Generic* Sym::car(void){
	if(isnil())	return this;
	else		Generic::car();
}

Generic* Sym::cdr(void){
	if(isnil())	return this;
	else		Generic::cdr();
}

Closure::Closure(Executor* c, size_t s)
	: Generic(), cd(c), vars(s) {}

Closure::Closure(boost::shared_ptr<Executor> c, size_t s)
	: Generic(), cd(c), vars(s) {}

KClosure::KClosure(Executor* c, size_t s)
	: Closure(c, s), nonreusable(0) {}

KClosure::KClosure(boost::shared_ptr<Executor> c, size_t s)
	: Closure(c, s), nonreusable(0) {}

ArcBytecodeSequence::ArcBytecodeSequence()
	: Generic(), seq(new BytecodeSequence()) {}

void ArcBytecodeSequence::append(Bytecode* b){
	seq->append(b);
}

/*DEBUG CODE*/
#include<iostream>
#define INDENT(ind)	for(size_t __i = 0; __i < ind; ++__i) std::cout << "\t"
void Cons::probe(size_t ind){
	INDENT(ind); std::cout << "CONS cell@" <<
			std::hex << ((size_t)(this)) << std::endl;
	a->probe(ind+1);
	d->probe(ind+1);
}

void MetadataCons::probe(size_t ind){
	Cons::probe(ind);
	INDENT(ind); std::cout << "(metadata)" << std::endl;
	line->probe(ind+1);
	file->probe(ind+1);
}
#include"atoms.hpp"

void Sym::probe(size_t ind){
	INDENT(ind); std::cout << "SYMBOL: ";
	GlobalAtom* gp = dynamic_cast<GlobalAtom*>(a.get());
	if(gp != NULL) {gp->emit(); std::cout << std::endl;}
	else	std::cout << "<uniq>" << std::endl;
}

void Closure::probe(size_t ind){
	INDENT(ind); std::cout <<  "CLOSURE: fn@" <<
			std::hex << ((size_t) cd.get()) << " {" << std::endl;
	for(size_t i = 0; i < vars.size(); ++i){
		vars[i]->probe(ind+1);
	}
	INDENT(ind); std::cout << "}" << std::endl;
}

void KClosure::probe(size_t ind){
	Closure::probe(ind);
	INDENT(ind); std::cout << "(" <<
			(nonreusable ? "" : "reusable ") <<
			"continuation)" << std::endl;
}

void Integer::probe(size_t ind){
	INDENT(ind); std::cout << "INTEGER: " << std::dec << val <<
			" @" << std::hex << ((size_t)(this)) << std::endl;
}

void ArcBytecodeSequence::probe(size_t ind){
	INDENT(ind); std::cout << "BYTECODE @" <<
			std::hex << ((size_t) seq.get()) << std::endl;
}

void Tagged::probe(size_t ind){
	INDENT(ind); std::cout << "TAGGED @" <<
			std::hex << ((size_t) this) << std::endl;
	INDENT(ind); std::cout << "type:" << std::endl;
	type_o->probe(ind+1);
	INDENT(ind); std::cout << "rep:" << std::endl;
	rep_o->probe(ind+1);
}

void SharedVar::probe(size_t ind){
	INDENT(ind); std::cout << "SHAREDVAR @" <<
			std::hex << ((size_t) this) << std::endl;
	val->probe(ind+1);
}

void Pid::probe(size_t ind){
	INDENT(ind); std::cout << "PID @" <<
			std::hex << ((size_t) this) <<
			" referring to: " << ((size_t) hproc->pproc.get()) <<
			std::endl;
}

void BinaryBlob::probe(size_t ind){
	INDENT(ind); std::cout << "BINARY @" << std::hex << ((size_t) this) <<
			" referring to:" << ((size_t) pdat.get()) <<
			std::endl;
	for(size_t i = 0; i < pdat->size(); ++i){
		INDENT(ind+1); std::cout << (*pdat)[i] << std::endl;
	}
}

void SemispacePackage::probe(size_t ind){
	INDENT(ind); std::cout << "PACKAGE @" << std::hex << ((size_t) this) <<
			std::endl;
	INDENT(ind); std::cout << "Semispace @" << ((size_t) ns.get()) <<
			std::endl;
	gp->probe(ind+1);
}

<|endoftext|>