<commit_before>#include "trippath.h"
#include <math.h>

#if 0
#define LOG(...) fprintf(stderr, __VA_ARGS__)
#else
#define LOG(...)
#endif

using namespace std;
using namespace tr1;
using namespace boost;

static inline double radians(double degrees)
{
    return degrees/180.0f*M_PI;
}

static inline double degrees(double radians)
{
    return radians*180.0f/M_PI;
}

static double distance(double src_lat, double src_lng, double dest_lat, double dest_lng)
{
    if (src_lat == dest_lat && src_lng == dest_lng)
        return 0.0f;

    double theta = src_lng - dest_lng;
    double src_lat_radians = radians(src_lat);
    double dest_lat_radians = radians(dest_lat);
    double dist = sin(src_lat_radians) * sin(dest_lat_radians) +
                 cos(src_lat_radians) * cos(dest_lat_radians) *
                 cos(radians(theta));
    dist = acos(dist);
    dist = degrees(dist);
    dist *= (60.0f * 1.1515 * 1.609344 * 1000.0f);
    return dist;
}

TripAction::TripAction(const char *_src_id, const char *_dest_id,
                       int _route_id, double _start_time, double _end_time) :
    src_id(_src_id),
    dest_id(_dest_id),
    route_id(_route_id),
    start_time(_start_time),
    end_time(_end_time),
    parent()
{
}

TripAction::TripAction(const TripAction &other):
    src_id(other.src_id),
    dest_id(other.dest_id),
    route_id(other.route_id),
    start_time(other.start_time),
    end_time(other.end_time),
    parent(other.parent)
{
}

TripAction& TripAction::operator=(const TripAction &other)
{
    src_id = other.src_id;
    dest_id = other.dest_id;
    route_id = other.route_id;
    start_time = other.start_time;
    end_time = other.end_time;
    parent = other.parent;
}

TripPath::TripPath(double _time, double _fastest_speed,
                   shared_ptr<TripStop> &_dest_stop,
                   shared_ptr<TripStop> &_last_stop)
{
    fastest_speed = _fastest_speed;
    dest_stop = _dest_stop;
    last_stop = _last_stop;
    time = _time;

    walking_time = 0.0f;
    weight = _time;
    traversed_route_ids = 0;
    last_route_id = -1;
    route_time = 0.0f;
    _get_heuristic_weight();
}

#if 0
python::object TripPath::get_last_action()
{
    if (last_action)
        return python::object(*last_action);

    return python::object();
}
#endif

void TripPath::_get_heuristic_weight()
{
    // start off with heuristic weight being equivalent to its real weight
    heuristic_weight = weight;

    // then, calculate the time remaining based on going directly
    // from the last vertex to the destination vertex at the fastest
    // possible speed in the graph
    double remaining_distance = distance(last_stop->lat, last_stop->lng,
                                        dest_stop->lat, dest_stop->lng);
    heuristic_weight += remaining_distance / 5; //(fastest_speed / 3);

    // now, add 5 minutes per each transfer, multiplied to the power of 2
    // (to make transfers exponentially more painful)
    if (traversed_route_ids > 1)
        heuristic_weight += (pow(2.0f, (int)(traversed_route_ids-2)) * 5.0f * 60.0f);

    // double the cost of walking after 5 mins, quadruple after 10 mins,
    // octuple after 15, etc.
    double excess_walking_time = walking_time - 300.0f;
    int iter = 0;
    while (excess_walking_time > 0)
    {
        double iter_walking_time = 0;
        if (excess_walking_time > 300.0f)
            iter_walking_time = 300.0f;
        else
            iter_walking_time = excess_walking_time;
        heuristic_weight += (iter_walking_time * pow(2.0f, iter));
        excess_walking_time -= 300.0f;
        iter++;
    }

    // add 5 mins to our weight if we were walking and remaining distance
    // >1000m, to account for the fact that we're probably going to
    // want to wait for another bus. this prevents us from repeatedly
    // getting out of the bus and walking around
    if (last_route_id == -1 && remaining_distance > 1000)
        heuristic_weight += (5*60);
}

static void _add_actions_to_list(list<TripAction> &l,
                                 shared_ptr<TripAction> &action)
{
    if (action)
    {
        if (action->parent)
            _add_actions_to_list(l, action->parent);
        l.push_back(TripAction(*action));
    }
}

list<TripAction> TripPath::get_actions()
{
    list<TripAction> l;

    // recursively add actions to list, so we get them back in the
    // correct order
    _add_actions_to_list(l, last_action);

    return l;
}

shared_ptr<TripPath> TripPath::add_action(shared_ptr<TripAction> &action,
                            unordered_set<int> &_possible_route_ids,
                            shared_ptr<TripStop> &_last_stop)
{
    shared_ptr<TripPath> new_trippath(new TripPath(*this));

    float departure_delay = 0.0f;

    if (action->route_id == -1)
    {
        new_trippath->walking_time += (action->end_time - action->start_time);
        new_trippath->route_time = 0;
    }
    else if (new_trippath->last_action)
    {
        // Starting first bus route, adjust the start time to match.
        if (new_trippath->traversed_route_ids == 0)
        {
            departure_delay =
                action->start_time - new_trippath->last_action->end_time;
            // Aim to be at the bus stop 3 minutes early.
            departure_delay -= 3*60;
        }

        if (action->route_id != new_trippath->last_action->route_id)
        {
            new_trippath->traversed_route_ids++;
            new_trippath->route_time = 0;
        }
    }

    for (unordered_set<int>::iterator i = _possible_route_ids.begin();
         i != _possible_route_ids.end(); i++)
    {
        new_trippath->possible_route_ids.insert(*i);
    }

    new_trippath->route_time += (action->end_time - action->start_time);
    new_trippath->weight += (action->end_time - action->start_time);
    new_trippath->weight += (action->start_time - new_trippath->time);

    if (new_trippath->last_action)
        action->parent = new_trippath->last_action;
    new_trippath->last_action = shared_ptr<TripAction>(new TripAction(*action));
    new_trippath->last_stop = _last_stop;
    new_trippath->last_route_id = action->route_id;
    new_trippath->_get_heuristic_weight();
    new_trippath->time = action->end_time;

    if (departure_delay > 0.0f)
    {
        LOG("Delaying start by %f seconds\n", departure_delay);
        new_trippath->delay_walk(new_trippath->last_action, departure_delay);
    }

    return new_trippath;
}

void TripPath::delay_walk(boost::shared_ptr<TripAction> walk, float secs)
{
    if (!walk)
        return;

    // Don't delay partial walks; we need to be given the element *after*
    // the final walk.
    if (walk->route_id == -1)
        return;

    // Only delay actual walks.
    if (!walk->parent || walk->parent->route_id != -1)
        return;

    boost::shared_ptr<TripAction> w(walk);
    while (w && w->parent && w->parent->route_id == -1)
    {
        // We need to clone the actions, as they're no longer safe to share
        // (for instance, they could be shared by another bus trip that leaves
        // earlier).
        w->parent = boost::shared_ptr<TripAction>(new TripAction(*(w->parent)));
        w = w->parent;

        w->start_time += secs;
        w->end_time += secs;
    }

    // If we delayed the initial walk, then we've reduced the total trip time.
    if (!w)
    {
        weight -= secs;
        _get_heuristic_weight();
    }
}

<commit_msg>Get rid of some extraneous boost:: prefixes.<commit_after>#include "trippath.h"
#include <math.h>

#if 0
#define LOG(...) fprintf(stderr, __VA_ARGS__)
#else
#define LOG(...)
#endif

using namespace std;
using namespace tr1;
using namespace boost;

static inline double radians(double degrees)
{
    return degrees/180.0f*M_PI;
}

static inline double degrees(double radians)
{
    return radians*180.0f/M_PI;
}

static double distance(double src_lat, double src_lng, double dest_lat, double dest_lng)
{
    if (src_lat == dest_lat && src_lng == dest_lng)
        return 0.0f;

    double theta = src_lng - dest_lng;
    double src_lat_radians = radians(src_lat);
    double dest_lat_radians = radians(dest_lat);
    double dist = sin(src_lat_radians) * sin(dest_lat_radians) +
                 cos(src_lat_radians) * cos(dest_lat_radians) *
                 cos(radians(theta));
    dist = acos(dist);
    dist = degrees(dist);
    dist *= (60.0f * 1.1515 * 1.609344 * 1000.0f);
    return dist;
}

TripAction::TripAction(const char *_src_id, const char *_dest_id,
                       int _route_id, double _start_time, double _end_time) :
    src_id(_src_id),
    dest_id(_dest_id),
    route_id(_route_id),
    start_time(_start_time),
    end_time(_end_time),
    parent()
{
}

TripAction::TripAction(const TripAction &other):
    src_id(other.src_id),
    dest_id(other.dest_id),
    route_id(other.route_id),
    start_time(other.start_time),
    end_time(other.end_time),
    parent(other.parent)
{
}

TripAction& TripAction::operator=(const TripAction &other)
{
    src_id = other.src_id;
    dest_id = other.dest_id;
    route_id = other.route_id;
    start_time = other.start_time;
    end_time = other.end_time;
    parent = other.parent;
}

TripPath::TripPath(double _time, double _fastest_speed,
                   shared_ptr<TripStop> &_dest_stop,
                   shared_ptr<TripStop> &_last_stop)
{
    fastest_speed = _fastest_speed;
    dest_stop = _dest_stop;
    last_stop = _last_stop;
    time = _time;

    walking_time = 0.0f;
    weight = _time;
    traversed_route_ids = 0;
    last_route_id = -1;
    route_time = 0.0f;
    _get_heuristic_weight();
}

#if 0
python::object TripPath::get_last_action()
{
    if (last_action)
        return python::object(*last_action);

    return python::object();
}
#endif

void TripPath::_get_heuristic_weight()
{
    // start off with heuristic weight being equivalent to its real weight
    heuristic_weight = weight;

    // then, calculate the time remaining based on going directly
    // from the last vertex to the destination vertex at the fastest
    // possible speed in the graph
    double remaining_distance = distance(last_stop->lat, last_stop->lng,
                                        dest_stop->lat, dest_stop->lng);
    heuristic_weight += remaining_distance / 5; //(fastest_speed / 3);

    // now, add 5 minutes per each transfer, multiplied to the power of 2
    // (to make transfers exponentially more painful)
    if (traversed_route_ids > 1)
        heuristic_weight += (pow(2.0f, (int)(traversed_route_ids-2)) * 5.0f * 60.0f);

    // double the cost of walking after 5 mins, quadruple after 10 mins,
    // octuple after 15, etc.
    double excess_walking_time = walking_time - 300.0f;
    int iter = 0;
    while (excess_walking_time > 0)
    {
        double iter_walking_time = 0;
        if (excess_walking_time > 300.0f)
            iter_walking_time = 300.0f;
        else
            iter_walking_time = excess_walking_time;
        heuristic_weight += (iter_walking_time * pow(2.0f, iter));
        excess_walking_time -= 300.0f;
        iter++;
    }

    // add 5 mins to our weight if we were walking and remaining distance
    // >1000m, to account for the fact that we're probably going to
    // want to wait for another bus. this prevents us from repeatedly
    // getting out of the bus and walking around
    if (last_route_id == -1 && remaining_distance > 1000)
        heuristic_weight += (5*60);
}

static void _add_actions_to_list(list<TripAction> &l,
                                 shared_ptr<TripAction> &action)
{
    if (action)
    {
        if (action->parent)
            _add_actions_to_list(l, action->parent);
        l.push_back(TripAction(*action));
    }
}

list<TripAction> TripPath::get_actions()
{
    list<TripAction> l;

    // recursively add actions to list, so we get them back in the
    // correct order
    _add_actions_to_list(l, last_action);

    return l;
}

shared_ptr<TripPath> TripPath::add_action(shared_ptr<TripAction> &action,
                            unordered_set<int> &_possible_route_ids,
                            shared_ptr<TripStop> &_last_stop)
{
    shared_ptr<TripPath> new_trippath(new TripPath(*this));

    float departure_delay = 0.0f;

    if (action->route_id == -1)
    {
        new_trippath->walking_time += (action->end_time - action->start_time);
        new_trippath->route_time = 0;
    }
    else if (new_trippath->last_action)
    {
        // Starting first bus route, adjust the start time to match.
        if (new_trippath->traversed_route_ids == 0)
        {
            departure_delay =
                action->start_time - new_trippath->last_action->end_time;
            // Aim to be at the bus stop 3 minutes early.
            departure_delay -= 3*60;
        }

        if (action->route_id != new_trippath->last_action->route_id)
        {
            new_trippath->traversed_route_ids++;
            new_trippath->route_time = 0;
        }
    }

    for (unordered_set<int>::iterator i = _possible_route_ids.begin();
         i != _possible_route_ids.end(); i++)
    {
        new_trippath->possible_route_ids.insert(*i);
    }

    new_trippath->route_time += (action->end_time - action->start_time);
    new_trippath->weight += (action->end_time - action->start_time);
    new_trippath->weight += (action->start_time - new_trippath->time);

    if (new_trippath->last_action)
        action->parent = new_trippath->last_action;
    new_trippath->last_action = shared_ptr<TripAction>(new TripAction(*action));
    new_trippath->last_stop = _last_stop;
    new_trippath->last_route_id = action->route_id;
    new_trippath->_get_heuristic_weight();
    new_trippath->time = action->end_time;

    if (departure_delay > 0.0f)
    {
        LOG("Delaying start by %f seconds\n", departure_delay);
        new_trippath->delay_walk(new_trippath->last_action, departure_delay);
    }

    return new_trippath;
}

void TripPath::delay_walk(shared_ptr<TripAction> walk, float secs)
{
    if (!walk)
        return;

    // Don't delay partial walks; we need to be given the element *after*
    // the final walk.
    if (walk->route_id == -1)
        return;

    // Only delay actual walks.
    if (!walk->parent || walk->parent->route_id != -1)
        return;

    shared_ptr<TripAction> w(walk);
    while (w && w->parent && w->parent->route_id == -1)
    {
        // We need to clone the actions, as they're no longer safe to share
        // (for instance, they could be shared by another bus trip that leaves
        // earlier).
        w->parent = shared_ptr<TripAction>(new TripAction(*(w->parent)));
        w = w->parent;

        w->start_time += secs;
        w->end_time += secs;
    }

    // If we delayed the initial walk, then we've reduced the total trip time.
    if (!w)
    {
        weight -= secs;
        _get_heuristic_weight();
    }
}

<|endoftext|>


<commit_before>#include <vector>
#include <map>
#include <cstring>
#include <algorithm>
#include <iostream>

#include "alloc.hpp"
#include "safemacros.h"

#include <sys/mman.h>
#include <fcntl.h>
#include <errno.h>

namespace aL4nin
{
    template <>
    struct meta<int>
    {
        int* allocate(std::size_t elems)
        {
            return new int[elems];
        }
    };

    template <>
    meta<int>& get_meta<int>(std::size_t)
    {
        static meta<int> m;
        return m;
    }
}

// metadata entry defines the
// marking method:
// a) bitpattern (up to 31 bits representing pointers to follow)
// b) freestyle procedural marker
//     - uncommitted arrays must zero out object data before setting marker
//     - concurrency in data <--> metadata access???

// let's fix some hard conventions
// - T* is non-null collectable pointer that is to be followed
// - nullable<T> is a possibly NULL pointer that should be followed
// - T& is a non-assignable, non-null reference that is to be followed
// - const T is a non-assignable non-null reference that is to be followed
// - const nullable<T> is a non-assignable, possibly NULL pointer that should be followed
// - references to builtin basic types are not followed
// - non<T> is a pointer that will not be followed
// - const non<T> is a non-assignable pointer that will not be followed
// - thresholded<T, N> is like nullable but does not follow <= N

#define WRAP(TYPE, MODIFIER) \
    MODIFIER ## _WRAPPER(TYPE)

#define BARE_WRAPPER(TYPE) TYPE
#define _WRAPPER(TYPE) BARE_WRAPPER(TYPE)
#define NULLABLE_WRAPPER(TYPE) nullable<TYPE>
#define NON_WRAPPER(TYPE) non<TYPE>
#define NULLABLE_WRAPPER(TYPE) nullable<TYPE>

template <typename T>
struct nullable
{
    T* real;
    nullable(T* real)
        : real(real)
        {}
};

template <typename T>
struct non
{
    T real;
    non(const T& real)
        : real(real)
        {}
};

WRAP(int, NON) hh(42);
WRAP(int, /*BARE*/) hh1;
WRAP(int, NULLABLE) hh2(0);

struct foo
{
    foo& f;
    foo() : f(*this)
        {}
    void bar()
        {
///            int i(&foo::f);
        }

};

template <unsigned long PAGE, unsigned long CLUSTER, unsigned long SCALE>
inline void* Obj2Meta(void* obj)
{
    typedef unsigned long sptr_t;
    register sptr_t o(reinterpret_cast<sptr_t>(obj));
    enum
        {
            pat = (1 << PAGE + CLUSTER) - 1
        };

    register sptr_t b(o & ~static_cast<sptr_t>(pat));
    register sptr_t d(o & static_cast<sptr_t>(pat));
    return reinterpret_cast<void*>(b + (d >> SCALE));
}

#include "alloc.cpp"

using namespace std;
using namespace aL4nin;

namespace aL4nin
{
    template <>
    meta<void>* object_meta<void>(void* p)
    {
        if (!p)
            return 0;

        static meta<void> me;
        return &me;
    }

    template <>
    struct meta<std::_Rb_tree_node<std::pair<const int, int> > >
    {
        typedef std::_Rb_tree_node<std::pair<const int, int> > payload;

        payload* allocate(std::size_t elems)
        {
            return new payload[elems];
        }
    };

    template <>
    meta<std::_Rb_tree_node<std::pair<const int, int> > >& get_meta<std::_Rb_tree_node<std::pair<const int, int> > >(std::size_t)
    {
        static meta<std::_Rb_tree_node<std::pair<const int, int> > > m;
        return m;
    }

    struct cons : pair<void*, void*>
    {};

    template <>
    struct meta<cons>
    {
        enum { bits = 32 };

        cons* objects;
        bool bitmap[bits];
        bool marks[bits];

        meta(void)
            {
                memset(this, 0, sizeof *this);
            }

        cons* allocate(std::size_t)
            {
                if (!objects)
                {
                    objects = new cons[bits];
                    *bitmap = true;
                    return objects;
                }

                bool* end(bitmap + meta<cons>::bits);
                bool* freebit(find(bitmap, end, 0));
                if (freebit == end)
                    return 0;

                *freebit = true;

                return objects + (freebit - bitmap);
            }

        void mark(const cons* p PLUS_VERBOSITY_ARG())
            {
                // simple minded!
                int i(bits - 1);
                for (const cons* my(objects + i);
                     i >= 0;
                     --my, --i)
                {
                    if (bitmap[i] && p == my)
                    {
                        VERBOSE("identified as cons");
                        if (marks[i])
                        {
                            VERBOSE("already marked");
                            return /*true*/;
                        }

                        marks[i] = true;
                        if (object_meta(p->first))
                        {
                            object_meta(p->first)->mark(p->first PASS_VERBOSE);
                        }

                        if (object_meta(p->second))
                        {
                            object_meta(p->second)->mark(p->second PASS_VERBOSE);
                        }

                        return /*true*/;
                    }
                }

                VERBOSE_ABORT("not a cons");
            }
    };

    template <>
    meta<cons>& get_meta<cons>(std::size_t)
    {
        static meta<cons> m;

        if (find(m.bitmap, m.bitmap + meta<cons>::bits, 0))
            return m;

        abort();
    }

    void* rooty(0);

    void collect(VERBOSITY_ARG())
    {
        VERBOSE("starting");

        // do we need meta<void>
        // or can we safely assume
        // to know the exact meta type?
        // probably not: if a slot is just declared
        // <object> we never know the metadata
        meta<void>* m(object_meta(rooty));
        if (m)
            m->mark(rooty PASS_VERBOSE);
        /// if (m.trymark(rooty.first)) ...;

        VERBOSE("done");
    }

    void meta<void>::mark(void* p PLUS_VERBOSITY_ARG())
    {
        // look whether it is a cons
        VERBOSE("trying to mark: " << p);
        // hack!
        meta<cons>& m(get_meta<cons>(1));
        m.mark(static_cast<cons*>(p) PASS_VERBOSE);
    }
}

int main(void)
{
    vector<int, alloc<int> > v(3);
    map<int, int, less<int>, alloc<int> > m;
    m.insert(make_pair(1, 42));

    cons* c(alloc<cons>().allocate(1));
    c->first = c;
    c->second = 0;
    rooty = c;

    collect(true);

    int hdl(shm_open("/blubber",
                     O_RDWR | O_CREAT,
                     S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP));

    perror("shm_open");

    const int lenn(100000000);

    int tr(ftruncate(hdl, lenn));
    if (tr == -1)
        perror("ftruncate");

    void* area(mmap(reinterpret_cast<void*>(0xF0000000UL),
                    lenn,
                    PROT_READ | PROT_WRITE,
                    MAP_SHARED,
                    hdl,
                    0));
    if (MAP_FAILED == area)
        perror("mmap");
    else
    {

        for (int i(0); i < 100; ++i)
        {
            char* p((char*)area + i);
            printf("i: %d, o: %p, m: %p\n", i, p, Obj2Meta<12, 4, 3>(p));
        }

        for (int i(10000); i < 10100; ++i)
        {
            char* p((char*)area + i);
            printf("i: %d, o: %p, m: %p\n", i, p, Obj2Meta<12, 4, 3>(p));
        }

        sleep(3);
        int um(munmap(area, lenn));
        if (um == -1)
            perror("munmap");
    }

    int ul(shm_unlink("/blubber"));
    if (ul == -1)
        perror("shm_unlink");

}
<commit_msg>use RawObjMeta<commit_after>#include <vector>
#include <map>
#include <cstring>
#include <algorithm>
#include <iostream>

#include "alloc.hpp"
#include "safemacros.h"

#include <sys/mman.h>
#include <fcntl.h>
#include <errno.h>

namespace aL4nin
{
    template <>
    struct meta<int>
    {
        int* allocate(std::size_t elems)
        {
            return new int[elems];
        }
    };

    template <>
    meta<int>& get_meta<int>(std::size_t)
    {
        static meta<int> m;
        return m;
    }
}

// metadata entry defines the
// marking method:
// a) bitpattern (up to 31 bits representing pointers to follow)
// b) freestyle procedural marker
//     - uncommitted arrays must zero out object data before setting marker
//     - concurrency in data <--> metadata access???

// let's fix some hard conventions
// - T* is non-null collectable pointer that is to be followed
// - nullable<T> is a possibly NULL pointer that should be followed
// - T& is a non-assignable, non-null reference that is to be followed
// - const T is a non-assignable non-null reference that is to be followed
// - const nullable<T> is a non-assignable, possibly NULL pointer that should be followed
// - references to builtin basic types are not followed
// - non<T> is a pointer that will not be followed
// - const non<T> is a non-assignable pointer that will not be followed
// - thresholded<T, N> is like nullable but does not follow <= N

#define WRAP(TYPE, MODIFIER) \
    MODIFIER ## _WRAPPER(TYPE)

#define BARE_WRAPPER(TYPE) TYPE
#define _WRAPPER(TYPE) BARE_WRAPPER(TYPE)
#define NULLABLE_WRAPPER(TYPE) nullable<TYPE>
#define NON_WRAPPER(TYPE) non<TYPE>
#define NULLABLE_WRAPPER(TYPE) nullable<TYPE>

template <typename T>
struct nullable
{
    T* real;
    nullable(T* real)
        : real(real)
        {}
};

template <typename T>
struct non
{
    T real;
    non(const T& real)
        : real(real)
        {}
};

WRAP(int, NON) hh(42);
WRAP(int, /*BARE*/) hh1;
WRAP(int, NULLABLE) hh2(0);

struct foo
{
    foo& f;
    foo() : f(*this)
        {}
    void bar()
        {
///            int i(&foo::f);
        }

};

template <unsigned long PAGE, unsigned long CLUSTER, unsigned long SCALE>
void* RawObj2Meta(void* obj)
{
    typedef unsigned long sptr_t;
    register sptr_t o(reinterpret_cast<sptr_t>(obj));
    enum
        {
            pat = (1 << PAGE + CLUSTER) - 1
        };

    register sptr_t b(o & ~static_cast<sptr_t>(pat));
    register sptr_t d(o & static_cast<sptr_t>(pat));
    return reinterpret_cast<void*>(b + (d >> SCALE));
}

#include "alloc.cpp"

using namespace std;
using namespace aL4nin;

namespace aL4nin
{
    template <>
    meta<void>* object_meta<void>(void* p)
    {
        if (!p)
            return 0;

        static meta<void> me;
        return &me;
    }

    template <>
    struct meta<std::_Rb_tree_node<std::pair<const int, int> > >
    {
        typedef std::_Rb_tree_node<std::pair<const int, int> > payload;

        payload* allocate(std::size_t elems)
        {
            return new payload[elems];
        }
    };

    template <>
    meta<std::_Rb_tree_node<std::pair<const int, int> > >& get_meta<std::_Rb_tree_node<std::pair<const int, int> > >(std::size_t)
    {
        static meta<std::_Rb_tree_node<std::pair<const int, int> > > m;
        return m;
    }

    struct cons : pair<void*, void*>
    {};

    template <>
    struct meta<cons>
    {
        enum { bits = 32 };

        cons* objects;
        bool bitmap[bits];
        bool marks[bits];

        meta(void)
            {
                memset(this, 0, sizeof *this);
            }

        cons* allocate(std::size_t)
            {
                if (!objects)
                {
                    objects = new cons[bits];
                    *bitmap = true;
                    return objects;
                }

                bool* end(bitmap + meta<cons>::bits);
                bool* freebit(find(bitmap, end, 0));
                if (freebit == end)
                    return 0;

                *freebit = true;

                return objects + (freebit - bitmap);
            }

        void mark(const cons* p PLUS_VERBOSITY_ARG())
            {
                // simple minded!
                int i(bits - 1);
                for (const cons* my(objects + i);
                     i >= 0;
                     --my, --i)
                {
                    if (bitmap[i] && p == my)
                    {
                        VERBOSE("identified as cons");
                        if (marks[i])
                        {
                            VERBOSE("already marked");
                            return /*true*/;
                        }

                        marks[i] = true;
                        if (object_meta(p->first))
                        {
                            object_meta(p->first)->mark(p->first PASS_VERBOSE);
                        }

                        if (object_meta(p->second))
                        {
                            object_meta(p->second)->mark(p->second PASS_VERBOSE);
                        }

                        return /*true*/;
                    }
                }

                VERBOSE_ABORT("not a cons");
            }
    };

    template <>
    meta<cons>& get_meta<cons>(std::size_t)
    {
        static meta<cons> m;

        if (find(m.bitmap, m.bitmap + meta<cons>::bits, 0))
            return m;

        abort();
    }

    void* rooty(0);

    void collect(VERBOSITY_ARG())
    {
        VERBOSE("starting");

        // do we need meta<void>
        // or can we safely assume
        // to know the exact meta type?
        // probably not: if a slot is just declared
        // <object> we never know the metadata
        meta<void>* m(object_meta(rooty));
        if (m)
            m->mark(rooty PASS_VERBOSE);
        /// if (m.trymark(rooty.first)) ...;

        VERBOSE("done");
    }

    void meta<void>::mark(void* p PLUS_VERBOSITY_ARG())
    {
        // look whether it is a cons
        VERBOSE("trying to mark: " << p);
        // hack!
        meta<cons>& m(get_meta<cons>(1));
        m.mark(static_cast<cons*>(p) PASS_VERBOSE);
    }
}

int main(void)
{
    vector<int, alloc<int> > v(3);
    map<int, int, less<int>, alloc<int> > m;
    m.insert(make_pair(1, 42));

    cons* c(alloc<cons>().allocate(1));
    c->first = c;
    c->second = 0;
    rooty = c;

    collect(true);

    int hdl(shm_open("/blubber",
                     O_RDWR | O_CREAT,
                     S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP));

    perror("shm_open");

    const int lenn(100000000);

    int tr(ftruncate(hdl, lenn));
    if (tr == -1)
        perror("ftruncate");

    void* area(mmap(reinterpret_cast<void*>(0xF0000000UL),
                    lenn,
                    PROT_READ | PROT_WRITE,
                    MAP_SHARED,
                    hdl,
                    0));
    if (MAP_FAILED == area)
        perror("mmap");
    else
    {

        for (int i(0); i < 100; i += 4)
        {
            char* p((char*)area + i);
            printf("i: %d, o: %p, m: %p\n", i, p, RawObj2Meta<12, 4, 3>(p));
        }

        for (int i(10000); i < 10100; i += 4)
        {
            char* p((char*)area + i);
            printf("i: %d, o: %p, m: %p\n", i, p, RawObj2Meta<12, 4, 3>(p));
        }

        sleep(3);
        int um(munmap(area, lenn));
        if (um == -1)
            perror("munmap");
    }

    int ul(shm_unlink("/blubber"));
    if (ul == -1)
        perror("shm_unlink");

}
<|endoftext|>


<commit_before>#include <sdbusplus/timer.hpp>

#include <chrono>
#include <iostream>

#include <gtest/gtest.h>

using namespace phosphor;

class TimerTest : public ::testing::Test
{
  public:
    // systemd event handler
    sd_event* events;

    // Need this so that events can be initialized.
    int rc;

    // Source of event
    sd_event_source* eventSource = nullptr;

    // Add a Timer Object
    Timer timer;

    // Gets called as part of each TEST_F construction
    TimerTest() : rc(sd_event_default(&events)), timer(events)
    {
        // Check for successful creation of
        // event handler and timer object.
        EXPECT_GE(rc, 0);
    }

    // Gets called as part of each TEST_F destruction
    ~TimerTest()
    {
        events = sd_event_unref(events);
    }
};

class TimerTestCallBack : public ::testing::Test
{
  public:
    // systemd event handler
    sd_event* events;

    // Need this so that events can be initialized.
    int rc;

    // Source of event
    sd_event_source* eventSource = nullptr;

    // Add a Timer Object
    std::unique_ptr<Timer> timer = nullptr;

    // Indicates optional call back fun was called
    bool callBackDone = false;

    void callBack()
    {
        callBackDone = true;
    }

    // Gets called as part of each TEST_F construction
    TimerTestCallBack() : rc(sd_event_default(&events))

    {
        // Check for successful creation of
        // event handler and timer object.
        EXPECT_GE(rc, 0);

        std::function<void()> func(
            std::bind(&TimerTestCallBack::callBack, this));
        timer = std::make_unique<Timer>(events, func);
    }

    // Gets called as part of each TEST_F destruction
    ~TimerTestCallBack()
    {
        events = sd_event_unref(events);
    }
};

/** @brief Makes sure that timer is expired and the
 *  callback handler gets invoked post 2 seconds
 */
TEST_F(TimerTest, timerExpiresAfter2seconds)
{
    using namespace std::chrono;

    auto time = duration_cast<microseconds>(seconds(2));
    EXPECT_GE(timer.start(time), 0);

    // Waiting 2 seconds is enough here since we have
    // already spent some usec now
    int count = 0;
    while (count < 2 && !timer.isExpired())
    {
        // Returns -0- on timeout and positive number on dispatch
        auto sleepTime = duration_cast<microseconds>(seconds(1));
        if (!sd_event_run(events, sleepTime.count()))
        {
            count++;
        }
    }
    EXPECT_EQ(true, timer.isExpired());
    EXPECT_EQ(1, count);
}

/** @brief Makes sure that timer is not expired
 */
TEST_F(TimerTest, timerNotExpiredAfter2Seconds)
{
    using namespace std::chrono;

    auto time = duration_cast<microseconds>(seconds(2));
    EXPECT_GE(timer.start(time), 0);

    // Now turn off the timer post a 1 second sleep
    sleep(1);
    EXPECT_GE(timer.stop(), 0);

    // Wait 2 seconds and see that timer is not expired
    int count = 0;
    while (count < 2)
    {
        // Returns -0- on timeout
        auto sleepTime = duration_cast<microseconds>(seconds(1));
        if (!sd_event_run(events, sleepTime.count()))
        {
            count++;
        }
    }
    EXPECT_EQ(false, timer.isExpired());

    // 2 because of one more count that happens prior to exiting
    EXPECT_EQ(2, count);
}

/** @brief Makes sure that timer value is changed in between
 *  and that the new timer expires
 */
TEST_F(TimerTest, updateTimerAndExpectExpire)
{
    using namespace std::chrono;

    auto time = duration_cast<microseconds>(seconds(2));
    EXPECT_GE(timer.start(time), 0);

    // Now sleep for a second and then set the new timeout value
    sleep(1);

    // New timeout is 3 seconds from THIS point.
    time = duration_cast<microseconds>(seconds(3));
    EXPECT_GE(timer.start(time), 0);

    // Wait 3 seconds and see that timer is expired
    int count = 0;
    while (count < 3 && !timer.isExpired())
    {
        // Returns -0- on timeout
        auto sleepTime = duration_cast<microseconds>(seconds(1));
        if (!sd_event_run(events, sleepTime.count()))
        {
            count++;
        }
    }
    EXPECT_EQ(true, timer.isExpired());
    EXPECT_EQ(2, count);
}

/** @brief Makes sure that timer value is changed in between
 *  and turn off and make sure that timer does not expire
 */
TEST_F(TimerTest, updateTimerAndNeverExpire)
{
    using namespace std::chrono;

    auto time = duration_cast<microseconds>(seconds(2));
    EXPECT_GE(timer.start(time), 0);

    // Now sleep for a second and then set the new timeout value
    sleep(1);

    // New timeout is 2 seconds from THIS point.
    time = duration_cast<microseconds>(seconds(2));
    EXPECT_GE(timer.start(time), 0);

    // Now turn off the timer post a 1 second sleep
    sleep(1);
    EXPECT_GE(timer.stop(), 0);

    // Wait 2 seconds and see that timer is expired
    int count = 0;
    while (count < 2)
    {
        // Returns -0- on timeout
        auto sleepTime = duration_cast<microseconds>(seconds(1));
        if (!sd_event_run(events, sleepTime.count()))
        {
            count++;
        }
    }
    EXPECT_EQ(false, timer.isExpired());

    // 2 because of one more count that happens prior to exiting
    EXPECT_EQ(2, count);
}

/** @brief Makes sure that optional callback is called */
TEST_F(TimerTestCallBack, optionalFuncCallBackDone)
{
    using namespace std::chrono;

    auto time = duration_cast<microseconds>(seconds(2));
    EXPECT_GE(timer->start(time), 0);

    // Waiting 2 seconds is enough here since we have
    // already spent some usec now
    int count = 0;
    while (count < 2 && !timer->isExpired())
    {
        // Returns -0- on timeout and positive number on dispatch
        auto sleepTime = duration_cast<microseconds>(seconds(1));
        if (!sd_event_run(events, sleepTime.count()))
        {
            count++;
        }
    }
    EXPECT_EQ(true, timer->isExpired());
    EXPECT_EQ(true, callBackDone);
    EXPECT_EQ(1, count);
}

/** @brief Makes sure that timer is not expired
 */
TEST_F(TimerTestCallBack, timerNotExpiredAfter2SecondsNoOptionalCallBack)
{
    using namespace std::chrono;

    auto time = duration_cast<microseconds>(seconds(2));
    EXPECT_GE(timer->start(time), 0);

    // Now turn off the timer post a 1 second sleep
    sleep(1);
    EXPECT_GE(timer->stop(), 0);

    // Wait 2 seconds and see that timer is not expired
    int count = 0;
    while (count < 2)
    {
        // Returns -0- on timeout
        auto sleepTime = duration_cast<microseconds>(seconds(1));
        if (!sd_event_run(events, sleepTime.count()))
        {
            count++;
        }
    }
    EXPECT_EQ(false, timer->isExpired());
    EXPECT_EQ(false, callBackDone);

    // 2 because of one more count that happens prior to exiting
    EXPECT_EQ(2, count);
}
<commit_msg>test: timer: fix warning under clang<commit_after>#include <sdbusplus/timer.hpp>

#include <chrono>
#include <iostream>

#include <gtest/gtest.h>

using namespace phosphor;

class TimerTest : public ::testing::Test
{
  public:
    // systemd event handler
    sd_event* events = nullptr;

    // Need this so that events can be initialized.
    int rc;

    // Source of event
    sd_event_source* eventSource = nullptr;

    // Add a Timer Object
    Timer timer;

    // Gets called as part of each TEST_F construction
    TimerTest() : rc(sd_event_default(&events)), timer(events)
    {
        // Check for successful creation of
        // event handler and timer object.
        EXPECT_GE(rc, 0);
    }

    // Gets called as part of each TEST_F destruction
    ~TimerTest()
    {
        events = sd_event_unref(events);
    }
};

class TimerTestCallBack : public ::testing::Test
{
  public:
    // systemd event handler
    sd_event* events;

    // Need this so that events can be initialized.
    int rc;

    // Source of event
    sd_event_source* eventSource = nullptr;

    // Add a Timer Object
    std::unique_ptr<Timer> timer = nullptr;

    // Indicates optional call back fun was called
    bool callBackDone = false;

    void callBack()
    {
        callBackDone = true;
    }

    // Gets called as part of each TEST_F construction
    TimerTestCallBack() : rc(sd_event_default(&events))

    {
        // Check for successful creation of
        // event handler and timer object.
        EXPECT_GE(rc, 0);

        std::function<void()> func(
            std::bind(&TimerTestCallBack::callBack, this));
        timer = std::make_unique<Timer>(events, func);
    }

    // Gets called as part of each TEST_F destruction
    ~TimerTestCallBack()
    {
        events = sd_event_unref(events);
    }
};

/** @brief Makes sure that timer is expired and the
 *  callback handler gets invoked post 2 seconds
 */
TEST_F(TimerTest, timerExpiresAfter2seconds)
{
    using namespace std::chrono;

    auto time = duration_cast<microseconds>(seconds(2));
    EXPECT_GE(timer.start(time), 0);

    // Waiting 2 seconds is enough here since we have
    // already spent some usec now
    int count = 0;
    while (count < 2 && !timer.isExpired())
    {
        // Returns -0- on timeout and positive number on dispatch
        auto sleepTime = duration_cast<microseconds>(seconds(1));
        if (!sd_event_run(events, sleepTime.count()))
        {
            count++;
        }
    }
    EXPECT_EQ(true, timer.isExpired());
    EXPECT_EQ(1, count);
}

/** @brief Makes sure that timer is not expired
 */
TEST_F(TimerTest, timerNotExpiredAfter2Seconds)
{
    using namespace std::chrono;

    auto time = duration_cast<microseconds>(seconds(2));
    EXPECT_GE(timer.start(time), 0);

    // Now turn off the timer post a 1 second sleep
    sleep(1);
    EXPECT_GE(timer.stop(), 0);

    // Wait 2 seconds and see that timer is not expired
    int count = 0;
    while (count < 2)
    {
        // Returns -0- on timeout
        auto sleepTime = duration_cast<microseconds>(seconds(1));
        if (!sd_event_run(events, sleepTime.count()))
        {
            count++;
        }
    }
    EXPECT_EQ(false, timer.isExpired());

    // 2 because of one more count that happens prior to exiting
    EXPECT_EQ(2, count);
}

/** @brief Makes sure that timer value is changed in between
 *  and that the new timer expires
 */
TEST_F(TimerTest, updateTimerAndExpectExpire)
{
    using namespace std::chrono;

    auto time = duration_cast<microseconds>(seconds(2));
    EXPECT_GE(timer.start(time), 0);

    // Now sleep for a second and then set the new timeout value
    sleep(1);

    // New timeout is 3 seconds from THIS point.
    time = duration_cast<microseconds>(seconds(3));
    EXPECT_GE(timer.start(time), 0);

    // Wait 3 seconds and see that timer is expired
    int count = 0;
    while (count < 3 && !timer.isExpired())
    {
        // Returns -0- on timeout
        auto sleepTime = duration_cast<microseconds>(seconds(1));
        if (!sd_event_run(events, sleepTime.count()))
        {
            count++;
        }
    }
    EXPECT_EQ(true, timer.isExpired());
    EXPECT_EQ(2, count);
}

/** @brief Makes sure that timer value is changed in between
 *  and turn off and make sure that timer does not expire
 */
TEST_F(TimerTest, updateTimerAndNeverExpire)
{
    using namespace std::chrono;

    auto time = duration_cast<microseconds>(seconds(2));
    EXPECT_GE(timer.start(time), 0);

    // Now sleep for a second and then set the new timeout value
    sleep(1);

    // New timeout is 2 seconds from THIS point.
    time = duration_cast<microseconds>(seconds(2));
    EXPECT_GE(timer.start(time), 0);

    // Now turn off the timer post a 1 second sleep
    sleep(1);
    EXPECT_GE(timer.stop(), 0);

    // Wait 2 seconds and see that timer is expired
    int count = 0;
    while (count < 2)
    {
        // Returns -0- on timeout
        auto sleepTime = duration_cast<microseconds>(seconds(1));
        if (!sd_event_run(events, sleepTime.count()))
        {
            count++;
        }
    }
    EXPECT_EQ(false, timer.isExpired());

    // 2 because of one more count that happens prior to exiting
    EXPECT_EQ(2, count);
}

/** @brief Makes sure that optional callback is called */
TEST_F(TimerTestCallBack, optionalFuncCallBackDone)
{
    using namespace std::chrono;

    auto time = duration_cast<microseconds>(seconds(2));
    EXPECT_GE(timer->start(time), 0);

    // Waiting 2 seconds is enough here since we have
    // already spent some usec now
    int count = 0;
    while (count < 2 && !timer->isExpired())
    {
        // Returns -0- on timeout and positive number on dispatch
        auto sleepTime = duration_cast<microseconds>(seconds(1));
        if (!sd_event_run(events, sleepTime.count()))
        {
            count++;
        }
    }
    EXPECT_EQ(true, timer->isExpired());
    EXPECT_EQ(true, callBackDone);
    EXPECT_EQ(1, count);
}

/** @brief Makes sure that timer is not expired
 */
TEST_F(TimerTestCallBack, timerNotExpiredAfter2SecondsNoOptionalCallBack)
{
    using namespace std::chrono;

    auto time = duration_cast<microseconds>(seconds(2));
    EXPECT_GE(timer->start(time), 0);

    // Now turn off the timer post a 1 second sleep
    sleep(1);
    EXPECT_GE(timer->stop(), 0);

    // Wait 2 seconds and see that timer is not expired
    int count = 0;
    while (count < 2)
    {
        // Returns -0- on timeout
        auto sleepTime = duration_cast<microseconds>(seconds(1));
        if (!sd_event_run(events, sleepTime.count()))
        {
            count++;
        }
    }
    EXPECT_EQ(false, timer->isExpired());
    EXPECT_EQ(false, callBackDone);

    // 2 because of one more count that happens prior to exiting
    EXPECT_EQ(2, count);
}
<|endoftext|>


<commit_before>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2006 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//
//  Original author of this file is igor@c-base.org
//

#include "DeDistort.h"
#include <vector>
#include "../graphics/Rect.h"
#include "../graphics/Point.h"

#include <iostream>
#include <math.h>

#define sqrt3 sqrt(3.)

namespace avg{

// This transformation is based on the undistort code found at
// http://www.math.rutgers.edu/~ojanen/undistort/index.html.
//   a lot of parameters enter here, some of which can be calculated/set manually,
//   some of which need to be determined via an optimization procedure
//
//   * m_FilmDisplacement moves the optical axis back to the center of the image:
//   * m_FilmScale scales the ROI to standard coords
//   * m_pDistortionParams OPT see paper
//   * m_P m_N OPT see paper
//   * m_Angle corrects rotation of camera OPT
//   * m_DisplayScale convert back from standard coords to display
//   * m_DisplayDisplacement correct the offset of the display from the center of the table
//
DPoint inv_distort_map(std::vector<double> &params, double r);
double distort_map(std::vector<double> &params, double r);

DeDistort::DeDistort(const DPoint &FilmDisplacement, const DPoint &FilmScale,
        const std::vector<double>& DistortionParams,
        DPoint3& P, DPoint3& N, double Angle,
        const DPoint& DisplayDisplacement, const DPoint& DisplayScale )
    : m_FilmDisplacement(FilmDisplacement),
      m_FilmScale(FilmScale),
      m_Angle(Angle),
      m_P(P),
      m_N(N),
      m_DistortionParams(DistortionParams),
      m_DisplayDisplacement(DisplayDisplacement),
      m_DisplayScale(DisplayScale)
{

}

DeDistort::~DeDistort()
{
}

DPoint DeDistort::inverse_transform_point(const DPoint &pt)
{
//FIXME
}

DPoint DeDistort::transform_point(const DPoint &pt)
{
    return translate(m_DisplayDisplacement, //translate 0,0 to center of display
        scale(m_DisplayScale,  //scale back to real display resolution
            rotate(m_Angle, //rotate
                pinhole(m_P, m_N, //apply pinhole
                    undistort(m_DistortionParams, //undistort;
                        scale(m_FilmScale,  //scale to -1,-1,1,1
                            translate(m_FilmDisplacement, //move optical axis to center of image
                                pt
                            )
                        )
                    )
                )
            )
        )
    );
}

//scale a point around the origin
DPoint DeDistort::scale(const DPoint &scales, const DPoint &pt){
    return DPoint(pt.x*scales.x, pt.y*scales.y);
}

//translate a point pt by the distance displacement
DPoint DeDistort::translate(const DPoint &displacement, const DPoint &pt){
    return pt + displacement;
}
//rotate a point counter-clockwise around the origin
DPoint DeDistort::rotate(double angle, const DPoint &pt){
    return DPoint(
            sin(angle) * pt.x + cos(angle) * pt.y,
            cos(angle) * pt.x + sin(angle) * pt.y
            );
}

//FIXME
double inv_distort_map(std::vector<double> &params, double r){
  double r1,r2,r3,f1,f2;
  r1 = r;
  r2 = r+.001;
  f1 = distort_map(params, r1)-r;
  f2 = distort_map(params, r2)-r;
  while (fabs(f2) > 0.0001) {
    r3 = (r1*f2-r2*f1)/(f2-f1);
    r1 = r2;
    r2 = r3;
    f1 = f2;
    f2 = distort_map(params, r2)-r;
  }
  return r2;

}

double distort_map(std::vector<double> &params, double r) {
    double S = 1;
    for(int counter=2;v!=params.end();++v, ++counter){
        S += (*v) * power(r, counter)
    }
    return S;
}

DPoint DeDistort::undistort(std::vector<double> &params, DPoint &pt) {

    std::vector<double>::iterator v = params.begin();
    if ( v == params.end() ) {
        return pt;
    }
    double r_d = sqrt(pt_norm.x*pt_norm.x + pt_norm.y*pt_norm.y);
    double S = inv_distort_map(params, r_d);
    DPoint pt_norm = pt; //no need to scale anymore?

    return S*pt_norm;
}
DPoint DeDistort::undistort(std::vector<double> &params, DPoint &pt) {

    std::vector<double>::iterator v = params.begin();
    if ( v == params.end() ) {
        return pt;
    }
    double r_d = sqrt(pt_norm.x*pt_norm.x + pt_norm.y*pt_norm.y);
    double S = distort_map(params, r_d);
    DPoint pt_norm = pt; //no need to scale anymore?

    return S*pt_norm;
}
//apply a pinhole transformation to the point pt.

DPoint DeDistort::pinhole(const DPoint3& P, const DPoint3& N, DPoint &pt)
{
    double n1=N.x;
    double n2=N.y;
    double n3=N.z;
    double P1=P.x;
    double P2=P.y;
    double P3=P.z;
    double a=pt.x;
    double b=pt.y;

    double x=1./(-a*n1 + -b*n2 + -n3*n3 + a*n1*P1 + b*n1*P1 + a*n2*P2 + b*n2*P2) *
        (
         n3*n3*(-a + ((-1) + a + b)*P1) +
         (n1+P1) * (
             n1*(-a + a*P1 + b*P1) +
             n2*( -b + a*P2 + b*P2)
         ) +
         n3*(-a + n1 + a*P1 + b*P1)*P3
         );
    double y=1./(-a*n1 + -b*n2 + -1*n3*n3 + a*n1*P1 + b*n1*P1 + a*n2*P2 + b*n2.*P2) *
         (
          n3*n3*(-b + ((-1)+a+b)*P2) +
          (n2+P2)* (
              n1*(-a+ a*P1 + b*P1) +
              n2*(-b + a*P2 + b*P2)
          ) +
          n3*(-b + n2 + a*P2 + b*P2)*P3
          );

    return DPoint(x,y);
}

double DeDistort::getPixelSize(const DPoint &pt)
{
    //volume dxdy transforms as |D|dx'dy' where |D| is the functional determinant
    //det { { dx'/dx, dx'/dy}, {dy'/dx,dy'/dy}}
    //|D| = dx'/dx * dy'/dy - dx'/dy * dy'/dx
    //
    //with x'=x'(x,y) are the new coordinates in terms of the old ones
    //in our case.
    //trapezoid:
    //x' = m0 + (x-m0)*(1+m_TrapezoidFactor*yn)
    //y' = y
    //|D| = (1+m_TrapezoidFactor*yn)|(x,y)
    //
    //distortion:
    //x' = S*(x-x0) + x0
    //y' = S*(y-y0) + y0
    //oBdA x0=y0=0 (volume invariant under translation)
    //S = (1+m_K1*|(x,y)|^2/m_Scale)
    //dx'/dx = S+x*dS/dx
    //dx'/dy = x*dS/dy
    //dy'/dx = y*dS/dx
    //dy'/dy = S+y*dS/dx
    //maxima:
    //S(x,y):= (1+K1 *(x**2+y**2));
    //dS/dx = 2xK1
    //dS/dy = 2yK1
    //xd(x,y):=S(x,y)*x;
    //yd(x,y):=S(x,y)*y;
    //
    //diff(xd(x,y),x)*diff(yd(x,y),y)-diff(xd(x,y),y)*diff(yd(x,y),x);
    //|D| = S^2 + 2*x*y*dS/dx*dS/dy = S^2 + 16 x^2*y^2 K1^2
    //|D| = (...)|(xt,yt) where xt,yt are the coords after trapezoid trafo
    double yn = (pt.y - m_Center.y)/m_Scale;
    DPoint pt2 = trapezoid(pt);
    return (1+m_TrapezoidFactor*yn); // FIXME
}

}
<commit_msg>fixed foobar ;-)<commit_after>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2006 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//
//  Original author of this file is igor@c-base.org
//

#include "DeDistort.h"
#include <vector>
#include "../graphics/Rect.h"
#include "../graphics/Point.h"

#include <iostream>
#include <math.h>

#define sqrt3 sqrt(3.)

namespace avg{

// This transformation is based on the undistort code found at
// http://www.math.rutgers.edu/~ojanen/undistort/index.html.
//   a lot of parameters enter here, some of which can be calculated/set manually,
//   some of which need to be determined via an optimization procedure
//
//   * m_FilmDisplacement moves the optical axis back to the center of the image:
//   * m_FilmScale scales the ROI to standard coords
//   * m_pDistortionParams OPT see paper
//   * m_P m_N OPT see paper
//   * m_Angle corrects rotation of camera OPT
//   * m_DisplayScale convert back from standard coords to display
//   * m_DisplayDisplacement correct the offset of the display from the center of the table
//
DPoint inv_distort_map(std::vector<double> &params, double r);
double distort_map(std::vector<double> &params, double r);

DeDistort::DeDistort(const DPoint &FilmDisplacement, const DPoint &FilmScale,
        const std::vector<double>& DistortionParams,
        DPoint3& P, DPoint3& N, double Angle,
        const DPoint& DisplayDisplacement, const DPoint& DisplayScale )
    : m_FilmDisplacement(FilmDisplacement),
      m_FilmScale(FilmScale),
      m_Angle(Angle),
      m_P(P),
      m_N(N),
      m_DistortionParams(DistortionParams),
      m_DisplayDisplacement(DisplayDisplacement),
      m_DisplayScale(DisplayScale)
{

}

DeDistort::~DeDistort()
{
}

DPoint DeDistort::inverse_transform_point(const DPoint &pt)
{
//FIXME
}

DPoint DeDistort::transform_point(const DPoint &pt)
{
    return translate(m_DisplayDisplacement, //translate 0,0 to center of display
        scale(m_DisplayScale,  //scale back to real display resolution
            rotate(m_Angle, //rotate
                pinhole(m_P, m_N, //apply pinhole
                    undistort(m_DistortionParams, //undistort;
                        scale(m_FilmScale,  //scale to -1,-1,1,1
                            translate(m_FilmDisplacement, //move optical axis to center of image
                                pt
                            )
                        )
                    )
                )
            )
        )
    );
}

//scale a point around the origin
DPoint DeDistort::scale(const DPoint &scales, const DPoint &pt){
    return DPoint(pt.x*scales.x, pt.y*scales.y);
}

//translate a point pt by the distance displacement
DPoint DeDistort::translate(const DPoint &displacement, const DPoint &pt){
    return pt + displacement;
}
//rotate a point counter-clockwise around the origin
DPoint DeDistort::rotate(double angle, const DPoint &pt){
    return DPoint(
            sin(angle) * pt.x + cos(angle) * pt.y,
            cos(angle) * pt.x + sin(angle) * pt.y
            );
}

//FIXME
double inv_distort_map(std::vector<double> &params, double r){
  double r1,r2,r3,f1,f2;
  r1 = r;
  r2 = r+.001;
  f1 = distort_map(params, r1)-r;
  f2 = distort_map(params, r2)-r;
  while (fabs(f2) > 0.0001) {
    r3 = (r1*f2-r2*f1)/(f2-f1);
    r1 = r2;
    r2 = r3;
    f1 = f2;
    f2 = distort_map(params, r2)-r;
  }
  return r2;

}

double distort_map(std::vector<double> &params, double r) {
    double S = 1;
    for(std::vector<double>::iterator v=params.begin(), int counter=2;v!=params.end();++v, ++counter){
        S += (*v) * power(r, counter)
    }
    return S;
}

DPoint DeDistort::undistort(std::vector<double> &params, DPoint &pt) {

    if ( params.empty() ) {
        return pt;
    }
    double r_d = sqrt(pt_norm.x*pt_norm.x + pt_norm.y*pt_norm.y);
    double S = inv_distort_map(params, r_d);
    DPoint pt_norm = pt; //no need to scale anymore?

    return S*pt_norm;
}
DPoint DeDistort::undistort(std::vector<double> &params, DPoint &pt) {

    std::vector<double>::iterator v = params.begin();
    if ( v == params.end() ) {
        return pt;
    }
    double r_d = sqrt(pt_norm.x*pt_norm.x + pt_norm.y*pt_norm.y);
    double S = distort_map(params, r_d);
    DPoint pt_norm = pt; //no need to scale anymore?

    return S*pt_norm;
}
//apply a pinhole transformation to the point pt.

DPoint DeDistort::pinhole(const DPoint3& P, const DPoint3& N, DPoint &pt)
{
    double n1=N.x;
    double n2=N.y;
    double n3=N.z;
    double P1=P.x;
    double P2=P.y;
    double P3=P.z;
    double a=pt.x;
    double b=pt.y;

    double x=1./(-a*n1 + -b*n2 + -n3*n3 + a*n1*P1 + b*n1*P1 + a*n2*P2 + b*n2*P2) *
        (
         n3*n3*(-a + ((-1) + a + b)*P1) +
         (n1+P1) * (
             n1*(-a + a*P1 + b*P1) +
             n2*( -b + a*P2 + b*P2)
         ) +
         n3*(-a + n1 + a*P1 + b*P1)*P3
         );
    double y=1./(-a*n1 + -b*n2 + -1*n3*n3 + a*n1*P1 + b*n1*P1 + a*n2*P2 + b*n2.*P2) *
         (
          n3*n3*(-b + ((-1)+a+b)*P2) +
          (n2+P2)* (
              n1*(-a+ a*P1 + b*P1) +
              n2*(-b + a*P2 + b*P2)
          ) +
          n3*(-b + n2 + a*P2 + b*P2)*P3
          );

    return DPoint(x,y);
}

double DeDistort::getPixelSize(const DPoint &pt)
{
    //volume dxdy transforms as |D|dx'dy' where |D| is the functional determinant
    //det { { dx'/dx, dx'/dy}, {dy'/dx,dy'/dy}}
    //|D| = dx'/dx * dy'/dy - dx'/dy * dy'/dx
    //
    //with x'=x'(x,y) are the new coordinates in terms of the old ones
    //in our case.
    //trapezoid:
    //x' = m0 + (x-m0)*(1+m_TrapezoidFactor*yn)
    //y' = y
    //|D| = (1+m_TrapezoidFactor*yn)|(x,y)
    //
    //distortion:
    //x' = S*(x-x0) + x0
    //y' = S*(y-y0) + y0
    //oBdA x0=y0=0 (volume invariant under translation)
    //S = (1+m_K1*|(x,y)|^2/m_Scale)
    //dx'/dx = S+x*dS/dx
    //dx'/dy = x*dS/dy
    //dy'/dx = y*dS/dx
    //dy'/dy = S+y*dS/dx
    //maxima:
    //S(x,y):= (1+K1 *(x**2+y**2));
    //dS/dx = 2xK1
    //dS/dy = 2yK1
    //xd(x,y):=S(x,y)*x;
    //yd(x,y):=S(x,y)*y;
    //
    //diff(xd(x,y),x)*diff(yd(x,y),y)-diff(xd(x,y),y)*diff(yd(x,y),x);
    //|D| = S^2 + 2*x*y*dS/dx*dS/dy = S^2 + 16 x^2*y^2 K1^2
    //|D| = (...)|(xt,yt) where xt,yt are the coords after trapezoid trafo
    double yn = (pt.y - m_Center.y)/m_Scale;
    DPoint pt2 = trapezoid(pt);
    return (1+m_TrapezoidFactor*yn); // FIXME
}

}
<|endoftext|>


<commit_before>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// btree_index.cpp
//
// Identification: src/index/btree_index.cpp
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "index/btree_index.h"
#include "index/index_key.h"
#include "index/index_util.h"
#include "common/logger.h"
#include "storage/tuple.h"

namespace peloton {
namespace index {

template <typename KeyType, typename ValueType, class KeyComparator,
          class KeyEqualityChecker>
BTreeIndex<KeyType, ValueType, KeyComparator, KeyEqualityChecker>::BTreeIndex(
    IndexMetadata *metadata)
    : Index(metadata),
      container(KeyComparator()),
      equals(),
      comparator() {}

template <typename KeyType, typename ValueType, class KeyComparator,
          class KeyEqualityChecker>
BTreeIndex<KeyType, ValueType, KeyComparator,
           KeyEqualityChecker>::~BTreeIndex() {
  // we should not rely on shared_ptr to reclaim memory.
  // this is because the underlying index can split or merge leaf nodes,
  // which invokes data data copy and deletes.
  // as the underlying index is unaware of shared_ptr,
  // memory allocated should be managed carefully by programmers.
  for (auto entry = container.begin(); entry != container.end(); ++entry) {
    delete entry->second;
    entry->second = nullptr;
  }
}

template <typename KeyType, typename ValueType, class KeyComparator,
          class KeyEqualityChecker>
bool BTreeIndex<KeyType, ValueType, KeyComparator,
                KeyEqualityChecker>::InsertEntry(const storage::Tuple *key,
                                                 const ItemPointer &location) {
  KeyType index_key;

  index_key.SetFromKey(key);
  std::pair<KeyType, ValueType> entry(index_key, new ItemPointer(location));

  {
    index_lock.WriteLock();

    // Insert the key, val pair
    container.insert(entry);

    index_lock.Unlock();
  }

  return true;
}

template <typename KeyType, typename ValueType, class KeyComparator,
          class KeyEqualityChecker>
bool BTreeIndex<KeyType, ValueType, KeyComparator,
                KeyEqualityChecker>::DeleteEntry(const storage::Tuple *key,
                                                 const ItemPointer &location) {
  KeyType index_key;
  index_key.SetFromKey(key);

  {
    index_lock.WriteLock();

    // Delete the < key, location > pair
    bool try_again = true;
    while (try_again == true) {
      // Unset try again
      try_again = false;

      // Lookup matching entries
      auto entries = container.equal_range(index_key);
      for (auto iterator = entries.first; iterator != entries.second;
           iterator++) {
        ItemPointer value = *(iterator->second);

        if ((value.block == location.block) &&
            (value.offset == location.offset)) {
          delete iterator->second;
          iterator->second = nullptr;
          container.erase(iterator);
          // Set try again
          // We could not proceed here since erase() may invalidate
          // iterators by one or more node merge
          try_again = true;

          break;
        }
      }
    }

    index_lock.Unlock();
  }

  return true;
}

template <typename KeyType, typename ValueType, class KeyComparator,
          class KeyEqualityChecker>
bool BTreeIndex<KeyType, ValueType, KeyComparator, KeyEqualityChecker>::
    CondInsertEntry(const storage::Tuple *key, const ItemPointer &location,
                    std::function<bool(const ItemPointer &)> predicate) {
  KeyType index_key;
  index_key.SetFromKey(key);

  {
    index_lock.WriteLock();

    // find the <key, location> pair
    auto entries = container.equal_range(index_key);
    for (auto entry = entries.first; entry != entries.second; ++entry) {
      ItemPointer item_pointer = *(entry->second);

      if (predicate(item_pointer)) {
        // this key is already visible or dirty in the index
        index_lock.Unlock();
        return false;
      }
    }

    // Insert the key, val pair
    container.insert(
        std::pair<KeyType, ValueType>(index_key, new ItemPointer(location)));

    index_lock.Unlock();
  }

  return true;
}

///////////////////////////////////////////////////////////////////////

template <typename KeyType, typename ValueType, class KeyComparator,
          class KeyEqualityChecker>
void BTreeIndex<KeyType, ValueType, KeyComparator, KeyEqualityChecker>::Scan(
    const std::vector<Value> &values,
    const std::vector<oid_t> &key_column_ids,
    const std::vector<ExpressionType> &expr_types,
    const ScanDirectionType &scan_direction,
    std::vector<ItemPointer *> &result) {

  // Check if we have leading (leftmost) column equality
  // refer : http://www.postgresql.org/docs/8.2/static/indexes-multicolumn.html
  //  oid_t leading_column_id = 0;
  //  auto key_column_ids_itr = std::find(key_column_ids.begin(),
  //                                      key_column_ids.end(),
  //                                      leading_column_id);

  // SPECIAL CASE : leading column id is one of the key column ids
  // and is involved in a equality constraint
  // Currently special case only includes EXPRESSION_TYPE_COMPARE_EQUAL
  // There are two more types, one is aligned, another is not aligned.
  // Aligned example: A > 0, B >= 15, c > 4
  // Not Aligned example: A >= 15, B < 30

  bool special_case = true;
  for (auto key_column_ids_itr = key_column_ids.begin();
       key_column_ids_itr != key_column_ids.end(); key_column_ids_itr++) {
    auto offset = std::distance(key_column_ids.begin(), key_column_ids_itr);

    if (expr_types[offset] == EXPRESSION_TYPE_COMPARE_NOTEQUAL ||
        expr_types[offset] == EXPRESSION_TYPE_COMPARE_IN ||
        expr_types[offset] == EXPRESSION_TYPE_COMPARE_LIKE ||
        expr_types[offset] == EXPRESSION_TYPE_COMPARE_NOTLIKE) {
      special_case = false;
      break;
    }
  }

  LOG_TRACE("Special case : %d ", special_case);

  {
    index_lock.ReadLock();

    // If it is a special case, we can figure out the range to scan in the index
    if (special_case == true) {
      // Assumption: must have leading column, assume it's first one in
      // key_column_ids.
      assert(key_column_ids.size() > 0);
      oid_t leading_column_offset = 0;
      oid_t leading_column_id = key_column_ids[leading_column_offset];

      std::vector<std::pair<Value, Value>> intervals;

      ConstructIntervals(leading_column_id, values, key_column_ids, expr_types,
                         intervals);

      // For non-leading columns, find the max and min
      std::map<oid_t, std::pair<Value, Value>> non_leading_columns;
      FindMaxMinInColumns(leading_column_id, values, key_column_ids, expr_types,
                          non_leading_columns);

      auto indexed_columns = metadata->GetKeySchema()->GetIndexedColumns();
      for (auto key_column_id : indexed_columns) {
        if (key_column_id == leading_column_id) {
          LOG_TRACE("Leading column : %u", key_column_id);
          continue;
        }

        if (non_leading_columns.find(key_column_id) == non_leading_columns.end()) {
          auto type =
              metadata->GetKeySchema()->GetColumn(key_column_id).column_type;
          std::pair<Value, Value> range(Value::GetMinValue(type),
                                        Value::GetMaxValue(type));
          std::pair<oid_t, std::pair<Value, Value>> key_value(key_column_id,
                                                              range);
          non_leading_columns.insert(key_value);
        }
      }

      assert(intervals.size() != 0);
      // Search each interval of leading_column.
      for (const auto &interval : intervals) {
        auto scan_begin_itr = container.begin();
        auto scan_end_itr = container.end();
        std::unique_ptr<storage::Tuple> start_key;
        std::unique_ptr<storage::Tuple> end_key;
        start_key.reset(new storage::Tuple(metadata->GetKeySchema(), true));
        end_key.reset(new storage::Tuple(metadata->GetKeySchema(), true));

        LOG_TRACE("%s", "Constructing start/end keys\n");

        LOG_TRACE("left bound %s\t\t right bound %s\n",
                  interval.first.GetInfo().c_str(),
                  interval.second.GetInfo().c_str());

        start_key->SetValue(leading_column_offset, interval.first, GetPool());
        end_key->SetValue(leading_column_offset, interval.second, GetPool());

        for (const auto &k_v : non_leading_columns) {
          start_key->SetValue(k_v.first, k_v.second.first, GetPool());
          end_key->SetValue(k_v.first, k_v.second.second, GetPool());
          LOG_TRACE("left bound %s\t\t right bound %s\n",
                    k_v.second.first.GetInfo().c_str(),
                    k_v.second.second.GetInfo().c_str());
        }

        KeyType start_index_key;
        KeyType end_index_key;
        start_index_key.SetFromKey(start_key.get());
        end_index_key.SetFromKey(end_key.get());

        scan_begin_itr = container.equal_range(start_index_key).first;
        scan_end_itr = container.equal_range(end_index_key).second;

        switch (scan_direction) {
          case SCAN_DIRECTION_TYPE_FORWARD:
          case SCAN_DIRECTION_TYPE_BACKWARD: {
            // Scan the index entries in forward direction
            for (auto scan_itr = scan_begin_itr; scan_itr != scan_end_itr;
                 scan_itr++) {
              auto scan_current_key = scan_itr->first;
              auto tuple = scan_current_key.GetTupleForComparison(
                  metadata->GetKeySchema());

              // Compare the current key in the scan with "values" based on
              // "expression types"
              // For instance, "5" EXPR_GREATER_THAN "2" is true
              if (Compare(tuple, key_column_ids, expr_types, values) == true) {
                ItemPointer *location_header = scan_itr->second;
                result.push_back(location_header);
              }
            }
          } break;

          case SCAN_DIRECTION_TYPE_INVALID:
          default:
            throw Exception("Invalid scan direction \n");
            break;
        }
      }

    } else {
      auto scan_begin_itr = container.begin();

      switch (scan_direction) {
        case SCAN_DIRECTION_TYPE_FORWARD:
        case SCAN_DIRECTION_TYPE_BACKWARD: {
          // Scan the index entries in forward direction
          for (auto scan_itr = scan_begin_itr; scan_itr != container.end();
               scan_itr++) {
            auto scan_current_key = scan_itr->first;
            auto tuple = scan_current_key.GetTupleForComparison(
                metadata->GetKeySchema());

            // Compare the current key in the scan with "values" based on
            // "expression types"
            // For instance, "5" EXPR_GREATER_THAN "2" is true
            if (Compare(tuple, key_column_ids, expr_types, values) == true) {
              ItemPointer *location_header = scan_itr->second;
              result.push_back(location_header);
            }
          }
        } break;

        case SCAN_DIRECTION_TYPE_INVALID:
        default:
          throw Exception("Invalid scan direction \n");
          break;
      }
    }

    index_lock.Unlock();
  }
}

template <typename KeyType, typename ValueType, class KeyComparator,
          class KeyEqualityChecker>
void BTreeIndex<KeyType, ValueType, KeyComparator,
                KeyEqualityChecker>::ScanAllKeys(std::vector<ItemPointer *> &
                                                     result) {
  {
    index_lock.ReadLock();

    auto itr = container.begin();

    // scan all entries
    while (itr != container.end()) {
      ItemPointer *location = itr->second;
      result.push_back(location);
      itr++;
    }

    index_lock.Unlock();
  }
}

/**
 * @brief Return all locations related to this key.
 */
template <typename KeyType, typename ValueType, class KeyComparator,
          class KeyEqualityChecker>
void BTreeIndex<KeyType, ValueType, KeyComparator, KeyEqualityChecker>::ScanKey(
    const storage::Tuple *key, std::vector<ItemPointer *> &result) {
  KeyType index_key;
  index_key.SetFromKey(key);

  {
    index_lock.ReadLock();

    // find the <key, location> pair
    auto entries = container.equal_range(index_key);
    for (auto entry = entries.first; entry != entries.second; ++entry) {
      result.push_back(entry->second);
    }

    index_lock.Unlock();
  }
}

///////////////////////////////////////////////////////////////////////////////////////////

template <typename KeyType, typename ValueType, class KeyComparator,
          class KeyEqualityChecker>
std::string BTreeIndex<KeyType, ValueType, KeyComparator,
                       KeyEqualityChecker>::GetTypeName() const {
  return "Btree";
}

// Explicit template instantiation

template class BTreeIndex<GenericKey<4>, ItemPointer *, GenericComparator<4>,
                          GenericEqualityChecker<4>>;
template class BTreeIndex<GenericKey<8>, ItemPointer *, GenericComparator<8>,
                          GenericEqualityChecker<8>>;
template class BTreeIndex<GenericKey<16>, ItemPointer *, GenericComparator<16>,
                          GenericEqualityChecker<16>>;
template class BTreeIndex<GenericKey<64>, ItemPointer *, GenericComparator<64>,
                          GenericEqualityChecker<64>>;
template class BTreeIndex<GenericKey<256>, ItemPointer *,
                          GenericComparator<256>, GenericEqualityChecker<256>>;

template class BTreeIndex<TupleKey, ItemPointer *, TupleKeyComparator,
                          TupleKeyEqualityChecker>;

}  // End index namespace
}  // End peloton namespace
<commit_msg>Reformat the fking btree index source to make it easier to navigate through<commit_after>//===----------------------------------------------------------------------===//
//
//                         Peloton
//
// btree_index.cpp
//
// Identification: src/index/btree_index.cpp
//
// Copyright (c) 2015-16, Carnegie Mellon University Database Group
//
//===----------------------------------------------------------------------===//

#include "index/btree_index.h"
#include "index/index_key.h"
#include "index/index_util.h"
#include "common/logger.h"
#include "storage/tuple.h"

namespace peloton {
namespace index {

#define BTREE_TEMPLATE_ARGUMENT template <typename KeyType, \
                                          typename ValueType, \
                                          typename KeyComparator, \
                                          typename KeyEqualityChecker>

#define BTREE_TEMPLATE_TYPE BTreeIndex<KeyType, \
                                       ValueType, \
                                       KeyComparator, \
                                       KeyEqualityChecker>

BTREE_TEMPLATE_ARGUMENT
BTreeIndex<KeyType, ValueType, KeyComparator, KeyEqualityChecker>::BTreeIndex(
    IndexMetadata *metadata)
    : Index(metadata),
      container(KeyComparator()),
      equals(),
      comparator() {}

BTREE_TEMPLATE_ARGUMENT
BTreeIndex<KeyType, ValueType, KeyComparator,
           KeyEqualityChecker>::~BTreeIndex() {
  // we should not rely on shared_ptr to reclaim memory.
  // this is because the underlying index can split or merge leaf nodes,
  // which invokes data data copy and deletes.
  // as the underlying index is unaware of shared_ptr,
  // memory allocated should be managed carefully by programmers.
  for (auto entry = container.begin(); entry != container.end(); ++entry) {
    delete entry->second;
    entry->second = nullptr;
  }
}

BTREE_TEMPLATE_ARGUMENT
bool BTREE_TEMPLATE_TYPE::InsertEntry(const storage::Tuple *key,
                                                 const ItemPointer &location) {
  KeyType index_key;

  index_key.SetFromKey(key);
  std::pair<KeyType, ValueType> entry(index_key, new ItemPointer(location));

  {
    index_lock.WriteLock();

    // Insert the key, val pair
    container.insert(entry);

    index_lock.Unlock();
  }

  return true;
}

BTREE_TEMPLATE_ARGUMENT
bool BTREE_TEMPLATE_TYPE::DeleteEntry(const storage::Tuple *key,
                                                 const ItemPointer &location) {
  KeyType index_key;
  index_key.SetFromKey(key);

  {
    index_lock.WriteLock();

    // Delete the < key, location > pair
    bool try_again = true;
    while (try_again == true) {
      // Unset try again
      try_again = false;

      // Lookup matching entries
      auto entries = container.equal_range(index_key);
      for (auto iterator = entries.first; iterator != entries.second;
           iterator++) {
        ItemPointer value = *(iterator->second);

        if ((value.block == location.block) &&
            (value.offset == location.offset)) {
          delete iterator->second;
          iterator->second = nullptr;
          container.erase(iterator);
          // Set try again
          // We could not proceed here since erase() may invalidate
          // iterators by one or more node merge
          try_again = true;

          break;
        }
      }
    }

    index_lock.Unlock();
  }

  return true;
}

BTREE_TEMPLATE_ARGUMENT
bool BTREE_TEMPLATE_TYPE::CondInsertEntry(const storage::Tuple *key,
                                          const ItemPointer &location,
                                          std::function<bool(const ItemPointer &)> predicate) {
  KeyType index_key;
  index_key.SetFromKey(key);

  {
    index_lock.WriteLock();

    // find the <key, location> pair
    auto entries = container.equal_range(index_key);
    for (auto entry = entries.first; entry != entries.second; ++entry) {
      ItemPointer item_pointer = *(entry->second);

      if (predicate(item_pointer)) {
        // this key is already visible or dirty in the index
        index_lock.Unlock();
        return false;
      }
    }

    // Insert the key, val pair
    container.insert(
        std::pair<KeyType, ValueType>(index_key, new ItemPointer(location)));

    index_lock.Unlock();
  }

  return true;
}

///////////////////////////////////////////////////////////////////////

BTREE_TEMPLATE_ARGUMENT
void BTREE_TEMPLATE_TYPE::Scan(const std::vector<Value> &values,
                               const std::vector<oid_t> &key_column_ids,
                               const std::vector<ExpressionType> &expr_types,
                               const ScanDirectionType &scan_direction,
                               std::vector<ItemPointer *> &result) {

  // Check if we have leading (leftmost) column equality
  // refer : http://www.postgresql.org/docs/8.2/static/indexes-multicolumn.html
  //  oid_t leading_column_id = 0;
  //  auto key_column_ids_itr = std::find(key_column_ids.begin(),
  //                                      key_column_ids.end(),
  //                                      leading_column_id);

  // SPECIAL CASE : leading column id is one of the key column ids
  // and is involved in a equality constraint
  // Currently special case only includes EXPRESSION_TYPE_COMPARE_EQUAL
  // There are two more types, one is aligned, another is not aligned.
  // Aligned example: A > 0, B >= 15, c > 4
  // Not Aligned example: A >= 15, B < 30

  bool special_case = true;
  for (auto key_column_ids_itr = key_column_ids.begin();
       key_column_ids_itr != key_column_ids.end(); key_column_ids_itr++) {
    auto offset = std::distance(key_column_ids.begin(), key_column_ids_itr);

    if (expr_types[offset] == EXPRESSION_TYPE_COMPARE_NOTEQUAL ||
        expr_types[offset] == EXPRESSION_TYPE_COMPARE_IN ||
        expr_types[offset] == EXPRESSION_TYPE_COMPARE_LIKE ||
        expr_types[offset] == EXPRESSION_TYPE_COMPARE_NOTLIKE) {
      special_case = false;
      break;
    }
  }

  LOG_TRACE("Special case : %d ", special_case);

  {
    index_lock.ReadLock();

    // If it is a special case, we can figure out the range to scan in the index
    if (special_case == true) {
      // Assumption: must have leading column, assume it's first one in
      // key_column_ids.
      assert(key_column_ids.size() > 0);
      oid_t leading_column_offset = 0;
      oid_t leading_column_id = key_column_ids[leading_column_offset];

      std::vector<std::pair<Value, Value>> intervals;

      ConstructIntervals(leading_column_id, values, key_column_ids, expr_types,
                         intervals);

      // For non-leading columns, find the max and min
      std::map<oid_t, std::pair<Value, Value>> non_leading_columns;
      FindMaxMinInColumns(leading_column_id, values, key_column_ids, expr_types,
                          non_leading_columns);

      auto indexed_columns = metadata->GetKeySchema()->GetIndexedColumns();
      for (auto key_column_id : indexed_columns) {
        if (key_column_id == leading_column_id) {
          LOG_TRACE("Leading column : %u", key_column_id);
          continue;
        }

        if (non_leading_columns.find(key_column_id) == non_leading_columns.end()) {
          auto type =
              metadata->GetKeySchema()->GetColumn(key_column_id).column_type;
          std::pair<Value, Value> range(Value::GetMinValue(type),
                                        Value::GetMaxValue(type));
          std::pair<oid_t, std::pair<Value, Value>> key_value(key_column_id,
                                                              range);
          non_leading_columns.insert(key_value);
        }
      }

      assert(intervals.size() != 0);
      // Search each interval of leading_column.
      for (const auto &interval : intervals) {
        auto scan_begin_itr = container.begin();
        auto scan_end_itr = container.end();
        std::unique_ptr<storage::Tuple> start_key;
        std::unique_ptr<storage::Tuple> end_key;
        start_key.reset(new storage::Tuple(metadata->GetKeySchema(), true));
        end_key.reset(new storage::Tuple(metadata->GetKeySchema(), true));

        LOG_TRACE("%s", "Constructing start/end keys\n");

        LOG_TRACE("left bound %s\t\t right bound %s\n",
                  interval.first.GetInfo().c_str(),
                  interval.second.GetInfo().c_str());

        start_key->SetValue(leading_column_offset, interval.first, GetPool());
        end_key->SetValue(leading_column_offset, interval.second, GetPool());

        for (const auto &k_v : non_leading_columns) {
          start_key->SetValue(k_v.first, k_v.second.first, GetPool());
          end_key->SetValue(k_v.first, k_v.second.second, GetPool());
          LOG_TRACE("left bound %s\t\t right bound %s\n",
                    k_v.second.first.GetInfo().c_str(),
                    k_v.second.second.GetInfo().c_str());
        }

        KeyType start_index_key;
        KeyType end_index_key;
        start_index_key.SetFromKey(start_key.get());
        end_index_key.SetFromKey(end_key.get());

        scan_begin_itr = container.equal_range(start_index_key).first;
        scan_end_itr = container.equal_range(end_index_key).second;

        switch (scan_direction) {
          case SCAN_DIRECTION_TYPE_FORWARD:
          case SCAN_DIRECTION_TYPE_BACKWARD: {
            // Scan the index entries in forward direction
            for (auto scan_itr = scan_begin_itr; scan_itr != scan_end_itr;
                 scan_itr++) {
              auto scan_current_key = scan_itr->first;
              auto tuple = scan_current_key.GetTupleForComparison(
                  metadata->GetKeySchema());

              // Compare the current key in the scan with "values" based on
              // "expression types"
              // For instance, "5" EXPR_GREATER_THAN "2" is true
              if (Compare(tuple, key_column_ids, expr_types, values) == true) {
                ItemPointer *location_header = scan_itr->second;
                result.push_back(location_header);
              }
            }
          } break;

          case SCAN_DIRECTION_TYPE_INVALID:
          default:
            throw Exception("Invalid scan direction \n");
            break;
        }
      }

    } else {
      auto scan_begin_itr = container.begin();

      switch (scan_direction) {
        case SCAN_DIRECTION_TYPE_FORWARD:
        case SCAN_DIRECTION_TYPE_BACKWARD: {
          // Scan the index entries in forward direction
          for (auto scan_itr = scan_begin_itr; scan_itr != container.end();
               scan_itr++) {
            auto scan_current_key = scan_itr->first;
            auto tuple = scan_current_key.GetTupleForComparison(
                metadata->GetKeySchema());

            // Compare the current key in the scan with "values" based on
            // "expression types"
            // For instance, "5" EXPR_GREATER_THAN "2" is true
            if (Compare(tuple, key_column_ids, expr_types, values) == true) {
              ItemPointer *location_header = scan_itr->second;
              result.push_back(location_header);
            }
          }
        } break;

        case SCAN_DIRECTION_TYPE_INVALID:
        default:
          throw Exception("Invalid scan direction \n");
          break;
      }
    }

    index_lock.Unlock();
  }
}

BTREE_TEMPLATE_ARGUMENT
void BTREE_TEMPLATE_TYPE::ScanAllKeys(std::vector<ItemPointer *> &result) {
  {
    index_lock.ReadLock();

    auto itr = container.begin();

    // scan all entries
    while (itr != container.end()) {
      ItemPointer *location = itr->second;
      result.push_back(location);
      itr++;
    }

    index_lock.Unlock();
  }
}

/**
 * @brief Return all locations related to this key.
 */
BTREE_TEMPLATE_ARGUMENT
void BTREE_TEMPLATE_TYPE::ScanKey(const storage::Tuple *key,
                                  std::vector<ItemPointer *> &result) {
  KeyType index_key;
  index_key.SetFromKey(key);

  {
    index_lock.ReadLock();

    // find the <key, location> pair
    auto entries = container.equal_range(index_key);
    for (auto entry = entries.first; entry != entries.second; ++entry) {
      result.push_back(entry->second);
    }

    index_lock.Unlock();
  }
}

///////////////////////////////////////////////////////////////////////////////////////////

BTREE_TEMPLATE_ARGUMENT
std::string BTREE_TEMPLATE_TYPE::GetTypeName() const {
  return "Btree";
}

// Explicit template instantiation

template class BTreeIndex<GenericKey<4>, ItemPointer *, GenericComparator<4>,
                          GenericEqualityChecker<4>>;
template class BTreeIndex<GenericKey<8>, ItemPointer *, GenericComparator<8>,
                          GenericEqualityChecker<8>>;
template class BTreeIndex<GenericKey<16>, ItemPointer *, GenericComparator<16>,
                          GenericEqualityChecker<16>>;
template class BTreeIndex<GenericKey<64>, ItemPointer *, GenericComparator<64>,
                          GenericEqualityChecker<64>>;
template class BTreeIndex<GenericKey<256>, ItemPointer *,
                          GenericComparator<256>, GenericEqualityChecker<256>>;

template class BTreeIndex<TupleKey, ItemPointer *, TupleKeyComparator,
                          TupleKeyEqualityChecker>;

}  // End index namespace
}  // End peloton namespace
<|endoftext|>


<commit_before>//
//  StoreSubscriptionManager.cpp
//  Pods
//
//  Created by eps on 7/3/20.
//

#include "ee/store/private/StoreSubscriptionManager.hpp"

#include <ee/nlohmann/json.hpp>

#include "ee/store/StoreProduct.hpp"
#include "ee/store/StoreProductDefinition.hpp"
#include "ee/store/StoreSubscriptionInfo.hpp"
#include "ee/store/private/StoreAppleInAppPurchaseReceipt.hpp"
#include "ee/store/private/StoreAppleReceipt.hpp"
#include "ee/store/private/StoreAppleReceiptParser.hpp"

namespace ee {
namespace store {
using Self = SubscriptionManager;

Self::SubscriptionManager(const std::shared_ptr<Product>& product,
                          const std::string& introJson)
    : Self(product->receipt(), product->definition()->storeSpecificId(),
           introJson) {}

Self::SubscriptionManager(const std::string& receipt, const std::string& id,
                          const std::string& introJson)
    : receipt_(receipt)
    , productId_(id)
    , introJson_(introJson) {}

std::shared_ptr<SubscriptionInfo> Self::getSubscriptionInfo() {
    if (receipt_.empty()) {
        assert(false);
        return nullptr;
    }
    auto&& dictionary = nlohmann::json::parse(receipt_);
    auto&& store = dictionary["Store"].get<std::string>();
    auto&& payload = dictionary["Payload"].get<std::string>();
    if (store == "GooglePlay") {
        return getGooglePlayStoreSubInfo(payload);
    }
    if (productId_.empty()) {
        assert(false);
        return nullptr;
    }
    return getAppleAppStoreSubInfo(payload, productId_);
}

std::shared_ptr<SubscriptionInfo>
Self::getAppleAppStoreSubInfo(const std::string& payload,
                              const std::string& productId) {
    auto receipt = AppleReceiptParser().parse(payload);
    if (receipt == nullptr) {
        return nullptr;
    }
    std::vector<std::shared_ptr<AppleInAppPurchaseReceipt>> all;
    for (auto&& r : receipt->inAppPurchaseReceipts()) {
        if (r->productId() == productId) {
            all.push_back(r);
        }
    }
    if (all.empty()) {
        return nullptr;
    }
    std::stable_sort(all.begin(), all.end(),
                     [](const std::shared_ptr<AppleInAppPurchaseReceipt>& b,
                        const std::shared_ptr<AppleInAppPurchaseReceipt>& a) {
                         return a->purchaseDate() < b->purchaseDate();
                     });
    return std::make_shared<SubscriptionInfo>(all[0], introJson_);
}

std::shared_ptr<SubscriptionInfo>
Self::getGooglePlayStoreSubInfo(const std::string& payload) {
    auto&& dictionary1 = nlohmann::json::parse(payload);
    auto&& skuDetails = dictionary1["skuDetails"].get<std::string>();
    auto&& purchaseHistorySupported =
        dictionary1["isPurchaseHistorySupported"].get<bool>();
    auto&& dictionary2 = dictionary1["json"];
    auto&& isAutoRenewing = dictionary2["autoReviewing"].get<bool>();
    auto&& purchaseDate = dictionary2["purchaseTime"].get<int>();
    auto&& dictionary3 = dictionary2["developerPayload"];
    auto&& isFreeTrial = dictionary3["is_free_trial"].get<bool>();
    auto&& hasIntroductoryPriceTrial =
        dictionary3["has_introductory_price_trial"].get<bool>();
    std::string updateMetadata;
    if (dictionary3["is_updated"].get<bool>()) {
        updateMetadata = dictionary3["update_subscription_metadata"];
    }
    return std::make_shared<SubscriptionInfo>(
        skuDetails, isAutoRenewing, purchaseDate, isFreeTrial,
        hasIntroductoryPriceTrial, purchaseHistorySupported, updateMetadata);
}
} // namespace store
} // namespace ee
<commit_msg>Fix parsing subscription info.<commit_after>//
//  StoreSubscriptionManager.cpp
//  Pods
//
//  Created by eps on 7/3/20.
//

#include "ee/store/private/StoreSubscriptionManager.hpp"

#include <ee/nlohmann/json.hpp>

#include "ee/store/StoreProduct.hpp"
#include "ee/store/StoreProductDefinition.hpp"
#include "ee/store/StoreSubscriptionInfo.hpp"
#include "ee/store/private/StoreAppleInAppPurchaseReceipt.hpp"
#include "ee/store/private/StoreAppleReceipt.hpp"
#include "ee/store/private/StoreAppleReceiptParser.hpp"

namespace ee {
namespace store {
using Self = SubscriptionManager;

Self::SubscriptionManager(const std::shared_ptr<Product>& product,
                          const std::string& introJson)
    : Self(product->receipt(), product->definition()->storeSpecificId(),
           introJson) {}

Self::SubscriptionManager(const std::string& receipt, const std::string& id,
                          const std::string& introJson)
    : receipt_(receipt)
    , productId_(id)
    , introJson_(introJson) {}

std::shared_ptr<SubscriptionInfo> Self::getSubscriptionInfo() {
    if (receipt_.empty()) {
        assert(false);
        return nullptr;
    }
    auto&& dictionary = nlohmann::json::parse(receipt_);
    auto&& store = dictionary["Store"].get<std::string>();
    auto&& payload = dictionary["Payload"].get<std::string>();
    if (store == "GooglePlay") {
        return getGooglePlayStoreSubInfo(payload);
    }
    if (productId_.empty()) {
        assert(false);
        return nullptr;
    }
    return getAppleAppStoreSubInfo(payload, productId_);
}

std::shared_ptr<SubscriptionInfo>
Self::getAppleAppStoreSubInfo(const std::string& payload,
                              const std::string& productId) {
    auto receipt = AppleReceiptParser().parse(payload);
    if (receipt == nullptr) {
        return nullptr;
    }
    std::vector<std::shared_ptr<AppleInAppPurchaseReceipt>> all;
    for (auto&& r : receipt->inAppPurchaseReceipts()) {
        if (r->productId() == productId) {
            all.push_back(r);
        }
    }
    if (all.empty()) {
        return nullptr;
    }
    std::stable_sort(all.begin(), all.end(),
                     [](const std::shared_ptr<AppleInAppPurchaseReceipt>& b,
                        const std::shared_ptr<AppleInAppPurchaseReceipt>& a) {
                         return a->purchaseDate() < b->purchaseDate();
                     });
    return std::make_shared<SubscriptionInfo>(all[0], introJson_);
}

std::shared_ptr<SubscriptionInfo>
Self::getGooglePlayStoreSubInfo(const std::string& payload) {
    auto&& dictionary1 = nlohmann::json::parse(payload);
    auto&& skuDetails = dictionary1["skuDetails"].get<std::string>();
    auto&& purchaseHistorySupported =
        dictionary1["isPurchaseHistorySupported"].get<bool>();
    auto&& dictionary2 = nlohmann::json::parse(dictionary1["json"].get<std::string>());
    auto&& isAutoRenewing = dictionary2["autoRenewing"].get<bool>();
    auto&& purchaseDate = dictionary2["purchaseTime"].get<int>();

    // FIXME: developerPayload key not exist.
    // auto&& dictionary3 = nlohmann::json::parse(dictionary2["developerPayload"].get<std::string>());
    // auto&& isFreeTrial = dictionary3["is_free_trial"].get<bool>();
    // auto&& hasIntroductoryPriceTrial =
    //     dictionary3["has_introductory_price_trial"].get<bool>();
    // std::string updateMetadata;
    // if (dictionary3["is_updated"].get<bool>()) {
    //     updateMetadata = dictionary3["update_subscription_metadata"];
    // }
    const auto isFreeTrial = false;
    const auto hasIntroductoryPriceTrial = false;
    const auto updateMetadata = "";
    return std::make_shared<SubscriptionInfo>(
        skuDetails, isAutoRenewing, purchaseDate, isFreeTrial,
        hasIntroductoryPriceTrial, purchaseHistorySupported, updateMetadata);
}
} // namespace store
} // namespace ee
<|endoftext|>