<commit_before>#include "base/str.h"
#include "base/cc.h"
#include "base/filesystem.h"

#include "api/app.h"
#include "api/rencache.h"
#include "api/image.h"
#include "api/font.h"

#include "ride/document.h"

#include "logo_256text_png.h"

struct Theme
{
    pix line_spacing = pix{3};
    pix gutter_spacing_left = pix{3};
    pix gutter_spacing_right = pix{3};
    pix text_spacing = pix{3};

    pix horizontal_scroll = 21_px;
    pix vertical_scroll = 41_px;

    pix scrollbar_width = pix{12};

    Color window_background_color = {255, 255, 255, 255};
    Color logo_color = {200, 200, 200, 255};
    Color gutter_color = {0, 0, 0, 255};
    Color plain_text_color = {0, 0, 0, 255};

    Color gutter_background = {150, 150, 150, 255};
    Color edit_background = {230, 230, 230, 190};

    Color scroll_through_color = {100, 100, 100, 255};
    Color scroll_thumb_color = {200, 200, 200, 255};
    Color scroll_button_color = {150, 150, 150, 255};
};

struct scroll_size
{
    std::optional<pix> width;
    std::optional<pix> height;
};

struct View
{
    App* app;
    Theme* theme;

    vec2<pix> position =
    {
        pix{0},
        pix{0}
    };

    size<pix> size =
    {
        pix{0},
        pix{0}
    };

    vec2<pix> scroll =
    {
        pix{0},
        pix{0}
    };

    void set_rect(const rect<pix>& r)
    {
        position = {r.x, r.y};
        size = {r.width, r.height};
    }

    void draw_scrollbar
    (
        rect<pix>* view_rect, RenCache* cache,
        pix document_height, pix scroll,
        bool is_vertical, Side through_side, Side top_side, Side bottom_side
    )
    {
        const auto view_rect_width = view_rect->width;
        const auto view_rect_height = view_rect->height;

        const auto size = theme->scrollbar_width;

        const auto through_rect = view_rect->cut(through_side, size);

        auto track_rect = through_rect;
        const auto top_button_rect = track_rect.cut(top_side, size);
        const auto bottom_button_rect = track_rect.cut(bottom_side, size);

        const auto fraction = (is_vertical ? view_rect_height : view_rect_width) / document_height;

        const auto scroll_fraction = scroll / document_height;

        const auto size_prop = is_vertical ? track_rect.height : track_rect.width;
        const auto thumb_size = size_prop * fraction;
        const auto available_size = size_prop - thumb_size;
        const auto thumb_offset = available_size * scroll_fraction;
        const auto thumb_rect = is_vertical
            ? rect<pix>{track_rect.x               , track_rect.y + thumb_offset, track_rect.width, thumb_size       }
            : rect<pix>{track_rect.x + thumb_offset, track_rect.y               , thumb_size      , track_rect.height}
            ;

        Color scroll_through_color = {100, 100, 100, 255};
        Color scroll_thumb_color = {200, 200, 200, 255};
        Color scroll_button_color = {150, 150, 150, 255};

        const auto clip_scope = ClipScope{cache, app->to_dip(through_rect)};
        cache->draw_rect(app->to_dip(through_rect), theme->scroll_through_color);
        cache->draw_rect(app->to_dip(thumb_rect), theme->scroll_thumb_color);
        cache->draw_rect(app->to_dip(top_button_rect), theme->scroll_button_color);
        cache->draw_rect(app->to_dip(bottom_button_rect), theme->scroll_button_color);
    }

    virtual void draw_body(const rect<pix>& main_view_rect, RenCache* cache) = 0;

    virtual scroll_size calculate_scroll_size() = 0;

    void draw(RenCache* cache)
    {
        auto main_view_rect = rect<pix>{position, size};

        const auto scroll_size = calculate_scroll_size();

        if(scroll_size.height)
        {
            draw_scrollbar
            (
                &main_view_rect, cache,
                *scroll_size.height, scroll.y,
                true, Side::right, Side::top, Side::bottom
            );
        }

        if(scroll_size.width)
        {
            draw_scrollbar
            (
                &main_view_rect, cache,
                *scroll_size.width, scroll.x,
                false, Side::bottom, Side::left, Side::right
            );
        }

        draw_body(main_view_rect, cache);
    }

    void on_mouse_wheel(int dx, int dy)
    {
        const auto scroll_size = calculate_scroll_size();

        if(scroll_size.width && dx != 0)
        {
            scroll.x = keep_within
            (
                pix{0},
                scroll.x + static_cast<double>(dx) * theme->horizontal_scroll,
                *scroll_size.width
            );
        }

        if(dy != 0 && scroll_size.height)
        {
            scroll.y = keep_within
            (
                pix{0},
                scroll.y - static_cast<double>(dy) * theme->vertical_scroll,
                *scroll_size.height
            );
        }
    }
};

struct ViewDoc : View
{
    Document doc;
    std::shared_ptr<Font> font;

    pix calculate_line_height()
    {
        return  app->to_pix(font->get_height()) + theme->line_spacing;
    }

    pix get_document_height()
    {
        const auto lines = doc.GetNumberOfLines();
        const auto spacing = calculate_line_height();

        // todo(Gustav): fix cast here
        return spacing * static_cast<double>(lines);
    }

    pix get_document_width()
    {
        const auto longest_line = std::max_element
        (
            doc.lines.begin(), doc.lines.end(),
            [](const std::string& lhs, const std::string& rhs) -> bool
            {
                return lhs.length() < rhs.length();
            }
        );

        if(longest_line == doc.lines.end())
        {
            return 0_px;
        }

        return app->to_pix(font->get_width(*longest_line));
    }

    scroll_size calculate_scroll_size() override
    {
        const auto line_height = calculate_line_height();

        const auto w = get_document_width();
        const auto h = get_document_height() - line_height;

        return {w, h};
    }

    void draw_body(const rect<pix>& main_view_rect, RenCache* cache) override
    {
        const auto clip_scope = ClipScope{cache, app->to_dip(main_view_rect)};

        const auto lines = doc.GetNumberOfLines();

        const auto min_gutter_width = app->to_pix(font->get_width( (Str{} << (lines+1)).ToString().c_str() ));
        const auto gutter_width = min_gutter_width + theme->gutter_spacing_left + theme->gutter_spacing_right;

        auto view_rect = main_view_rect;
        const auto gutter_rect = view_rect.cut_left(gutter_width);

        const auto spacing = calculate_line_height();

        cache->draw_rect(app->to_dip(main_view_rect), theme->edit_background);
        cache->draw_rect(app->to_dip(gutter_rect), theme->gutter_background);

        for(int line_index=0; line_index<lines; line_index += 1)
        {
            const auto y = static_cast<double>(line_index) * spacing - scroll.y;

            cache->draw_text
            (
                font,
                (Str{} << line_index+1).ToString(),
                app->to_dip(main_view_rect.x + theme->gutter_spacing_left),
                app->to_dip(main_view_rect.y + y),
                theme->gutter_color
            );

            {
                const auto text_scope = ClipScope(cache, app->to_dip(view_rect));
                cache->draw_text
                (
                    font,
                    doc.GetLineAt(line_index),
                    app->to_dip(main_view_rect.x + gutter_width + theme->text_spacing - scroll.x),
                    app->to_dip(main_view_rect.y + y),
                    theme->plain_text_color
                );
            }
        }
    }
};

struct RideApp : App
{
    vec2<pix> mouse = {pix{0}, pix{0}};

    std::shared_ptr<Image> logo;
    std::shared_ptr<Font> font;
    std::unique_ptr<filesystem> fs;

    ViewDoc root;
    Theme theme;

    void setup_view(View* view)
    {
        view->theme = &theme;
        view->app = this;
    }

    RideApp()
        : logo(load_shared(LOGO_256TEXT_PNG))
        , font(load_font(Font::default_font, pix{12}))
        , fs(create_local_filesystem())
    {
        setup_view(&root);
        root.font = font;
        root.doc.LoadFile(fs.get(), __FILE__);

        root.position = {pix{50}, pix{50}};
        root.size = {pix{300}, pix{300}};
    }

    void on_mouse_moved(const vec2<pix>& new_mouse, pix xrel, pix yrel) override
    {
        mouse = new_mouse;
    }

    void draw(RenCache* cache) override
    {
        const auto rect = ::rect<pix>::from_size(client_size);
        cache->draw_rect(to_dip(rect), theme.window_background_color);

        cache->draw_image(logo, to_dip(pix{10}), to_dip(pix{10}), theme.logo_color);

        root.set_rect(rect.Inset(pix{20}));

        root.draw(cache);

        cache->draw_rect
        (
            to_dip
            (
                ::rect<pix>
                {
                    mouse,
                    ::size<pix>
                    {
                        pix{10},
                        pix{10}
                    }
                }
            ),
            Color::rgb(0, 0, 255, 255)
        );
    }

    void on_mouse_wheel(int dx, int dy) override
    {
        root.on_mouse_wheel(dx, dy);
    }
};

int main(int argc, char** argv)
{
    return run_main(argc, argv, [](const StartupArguments&) -> std::unique_ptr<App> { return std::make_unique<RideApp>();});
}

<commit_msg>feat: don't display scrollbar when not needed<commit_after>#include "base/str.h"
#include "base/cc.h"
#include "base/filesystem.h"

#include "api/app.h"
#include "api/rencache.h"
#include "api/image.h"
#include "api/font.h"

#include "ride/document.h"

#include "logo_256text_png.h"

struct Theme
{
    pix line_spacing = pix{3};
    pix gutter_spacing_left = pix{3};
    pix gutter_spacing_right = pix{3};
    pix text_spacing = pix{3};

    pix horizontal_scroll = 21_px;
    pix vertical_scroll = 41_px;

    pix scrollbar_width = pix{12};

    Color window_background_color = {255, 255, 255, 255};
    Color logo_color = {200, 200, 200, 255};
    Color gutter_color = {0, 0, 0, 255};
    Color plain_text_color = {0, 0, 0, 255};

    Color gutter_background = {150, 150, 150, 255};
    Color edit_background = {230, 230, 230, 190};

    Color scroll_through_color = {100, 100, 100, 255};
    Color scroll_thumb_color = {200, 200, 200, 255};
    Color scroll_button_color = {150, 150, 150, 255};
};

struct scroll_size
{
    std::optional<pix> width;
    std::optional<pix> height;
};

struct View
{
    App* app;
    Theme* theme;

    vec2<pix> position =
    {
        pix{0},
        pix{0}
    };

    size<pix> size =
    {
        pix{0},
        pix{0}
    };

    vec2<pix> scroll =
    {
        pix{0},
        pix{0}
    };

    void set_rect(const rect<pix>& r)
    {
        position = {r.x, r.y};
        size = {r.width, r.height};
    }

    void draw_scrollbar
    (
        rect<pix>* view_rect, RenCache* cache,
        pix document_height, pix scroll,
        bool is_vertical, Side through_side, Side top_side, Side bottom_side
    )
    {
        const auto view_rect_width = view_rect->width;
        const auto view_rect_height = view_rect->height;

        const auto size = theme->scrollbar_width;

        const auto view_prop = is_vertical ? view_rect_height : view_rect_width;

        if(view_prop >= document_height)
        {
            return;
        }

        const auto fraction = view_prop / document_height;

        const auto through_rect = view_rect->cut(through_side, size);

        auto track_rect = through_rect;
        const auto top_button_rect = track_rect.cut(top_side, size);
        const auto bottom_button_rect = track_rect.cut(bottom_side, size);

        const auto scroll_fraction = scroll / document_height;

        const auto size_prop = is_vertical ? track_rect.height : track_rect.width;
        const auto thumb_size = size_prop * fraction;
        const auto available_size = size_prop - thumb_size;
        const auto thumb_offset = available_size * scroll_fraction;
        const auto thumb_rect = is_vertical
            ? rect<pix>{track_rect.x               , track_rect.y + thumb_offset, track_rect.width, thumb_size       }
            : rect<pix>{track_rect.x + thumb_offset, track_rect.y               , thumb_size      , track_rect.height}
            ;

        Color scroll_through_color = {100, 100, 100, 255};
        Color scroll_thumb_color = {200, 200, 200, 255};
        Color scroll_button_color = {150, 150, 150, 255};

        const auto clip_scope = ClipScope{cache, app->to_dip(through_rect)};
        cache->draw_rect(app->to_dip(through_rect), theme->scroll_through_color);
        cache->draw_rect(app->to_dip(thumb_rect), theme->scroll_thumb_color);
        cache->draw_rect(app->to_dip(top_button_rect), theme->scroll_button_color);
        cache->draw_rect(app->to_dip(bottom_button_rect), theme->scroll_button_color);
    }

    virtual void draw_body(const rect<pix>& main_view_rect, RenCache* cache) = 0;

    virtual scroll_size calculate_scroll_size() = 0;

    void draw(RenCache* cache)
    {
        auto main_view_rect = rect<pix>{position, size};

        const auto scroll_size = calculate_scroll_size();

        if(scroll_size.height)
        {
            draw_scrollbar
            (
                &main_view_rect, cache,
                *scroll_size.height, scroll.y,
                true, Side::right, Side::top, Side::bottom
            );
        }

        if(scroll_size.width)
        {
            draw_scrollbar
            (
                &main_view_rect, cache,
                *scroll_size.width, scroll.x,
                false, Side::bottom, Side::left, Side::right
            );
        }

        draw_body(main_view_rect, cache);
    }

    void on_mouse_wheel(int dx, int dy)
    {
        const auto scroll_size = calculate_scroll_size();

        if(scroll_size.width && dx != 0)
        {
            scroll.x = keep_within
            (
                pix{0},
                scroll.x + static_cast<double>(dx) * theme->horizontal_scroll,
                *scroll_size.width
            );
        }

        if(dy != 0 && scroll_size.height)
        {
            scroll.y = keep_within
            (
                pix{0},
                scroll.y - static_cast<double>(dy) * theme->vertical_scroll,
                *scroll_size.height
            );
        }
    }
};

struct ViewDoc : View
{
    Document doc;
    std::shared_ptr<Font> font;

    pix calculate_line_height()
    {
        return  app->to_pix(font->get_height()) + theme->line_spacing;
    }

    pix get_document_height()
    {
        const auto lines = doc.GetNumberOfLines();
        const auto spacing = calculate_line_height();

        // todo(Gustav): fix cast here
        return spacing * static_cast<double>(lines);
    }

    pix get_document_width()
    {
        const auto longest_line = std::max_element
        (
            doc.lines.begin(), doc.lines.end(),
            [](const std::string& lhs, const std::string& rhs) -> bool
            {
                return lhs.length() < rhs.length();
            }
        );

        if(longest_line == doc.lines.end())
        {
            return 0_px;
        }

        return app->to_pix(font->get_width(*longest_line));
    }

    scroll_size calculate_scroll_size() override
    {
        const auto line_height = calculate_line_height();

        const auto w = get_document_width();
        const auto h = get_document_height() - line_height;

        return {w, h};
    }

    void draw_body(const rect<pix>& main_view_rect, RenCache* cache) override
    {
        const auto clip_scope = ClipScope{cache, app->to_dip(main_view_rect)};

        const auto lines = doc.GetNumberOfLines();

        const auto min_gutter_width = app->to_pix(font->get_width( (Str{} << (lines+1)).ToString().c_str() ));
        const auto gutter_width = min_gutter_width + theme->gutter_spacing_left + theme->gutter_spacing_right;

        auto view_rect = main_view_rect;
        const auto gutter_rect = view_rect.cut_left(gutter_width);

        const auto spacing = calculate_line_height();

        cache->draw_rect(app->to_dip(main_view_rect), theme->edit_background);
        cache->draw_rect(app->to_dip(gutter_rect), theme->gutter_background);

        for(int line_index=0; line_index<lines; line_index += 1)
        {
            const auto y = static_cast<double>(line_index) * spacing - scroll.y;

            cache->draw_text
            (
                font,
                (Str{} << line_index+1).ToString(),
                app->to_dip(main_view_rect.x + theme->gutter_spacing_left),
                app->to_dip(main_view_rect.y + y),
                theme->gutter_color
            );

            {
                const auto text_scope = ClipScope(cache, app->to_dip(view_rect));
                cache->draw_text
                (
                    font,
                    doc.GetLineAt(line_index),
                    app->to_dip(main_view_rect.x + gutter_width + theme->text_spacing - scroll.x),
                    app->to_dip(main_view_rect.y + y),
                    theme->plain_text_color
                );
            }
        }
    }
};

struct RideApp : App
{
    vec2<pix> mouse = {pix{0}, pix{0}};

    std::shared_ptr<Image> logo;
    std::shared_ptr<Font> font;
    std::unique_ptr<filesystem> fs;

    ViewDoc root;
    Theme theme;

    void setup_view(View* view)
    {
        view->theme = &theme;
        view->app = this;
    }

    RideApp()
        : logo(load_shared(LOGO_256TEXT_PNG))
        , font(load_font(Font::default_font, pix{12}))
        , fs(create_local_filesystem())
    {
        setup_view(&root);
        root.font = font;
        root.doc.LoadFile(fs.get(), __FILE__);

        root.position = {pix{50}, pix{50}};
        root.size = {pix{300}, pix{300}};
    }

    void on_mouse_moved(const vec2<pix>& new_mouse, pix xrel, pix yrel) override
    {
        mouse = new_mouse;
    }

    void draw(RenCache* cache) override
    {
        const auto rect = ::rect<pix>::from_size(client_size);
        cache->draw_rect(to_dip(rect), theme.window_background_color);

        cache->draw_image(logo, to_dip(pix{10}), to_dip(pix{10}), theme.logo_color);

        root.set_rect(rect.Inset(pix{20}));

        root.draw(cache);

        cache->draw_rect
        (
            to_dip
            (
                ::rect<pix>
                {
                    mouse,
                    ::size<pix>
                    {
                        pix{10},
                        pix{10}
                    }
                }
            ),
            Color::rgb(0, 0, 255, 255)
        );
    }

    void on_mouse_wheel(int dx, int dy) override
    {
        root.on_mouse_wheel(dx, dy);
    }
};

int main(int argc, char** argv)
{
    return run_main(argc, argv, [](const StartupArguments&) -> std::unique_ptr<App> { return std::make_unique<RideApp>();});
}

<|endoftext|>


<commit_before><commit_msg>coverity#1000506 Unchecked return value<commit_after><|endoftext|>


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

/*! \file scan.inl
 *  \brief Inline file for scan.h.
 */

#include <thrust/detail/device/cuda/dispatch/scan.h>

namespace thrust
{
namespace detail
{
namespace device
{
namespace cuda
{

template<typename InputIterator,
         typename OutputIterator,
         typename AssociativeOperator>
  OutputIterator inclusive_scan(InputIterator first,
                                InputIterator last,
                                OutputIterator result,
                                AssociativeOperator binary_op)
{
    typedef typename thrust::iterator_value<OutputIterator>::type OutputType;

    // whether to use fast_scan or safe_scan
    static const bool use_fast_scan = sizeof(OutputType) <= 16;  // TODO profile this threshold

    return thrust::detail::device::cuda::dispatch::inclusive_scan
        (first, last, result, binary_op,
         thrust::detail::integral_constant<bool, use_fast_scan>());
}

template<typename InputIterator,
         typename OutputIterator,
         typename T,
         typename AssociativeOperator>
  OutputIterator exclusive_scan(InputIterator first,
                                InputIterator last,
                                OutputIterator result,
                                T init,
                                AssociativeOperator binary_op)
{
    typedef typename thrust::iterator_value<OutputIterator>::type OutputType;

    // whether to use fast_scan or safe_scan
    static const bool use_fast_scan = sizeof(OutputType) <= 16;  // TODO profile this threshold

    return thrust::detail::device::cuda::dispatch::exclusive_scan
        (first, last, result, init, binary_op,
         thrust::detail::integral_constant<bool, use_fast_scan>());
}

} // end namespace cuda
} // end namespace device
} // end namespace detail
} // end namespace thrust

<commit_msg>dispatch fast scan only for POD types<commit_after>/*
 *  Copyright 2008-2009 NVIDIA Corporation
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

/*! \file scan.inl
 *  \brief Inline file for scan.h.
 */

#include <thrust/detail/device/cuda/dispatch/scan.h>

namespace thrust
{
namespace detail
{
namespace device
{
namespace cuda
{

template<typename InputIterator,
         typename OutputIterator,
         typename AssociativeOperator>
  OutputIterator inclusive_scan(InputIterator first,
                                InputIterator last,
                                OutputIterator result,
                                AssociativeOperator binary_op)
{
    typedef typename thrust::iterator_value<OutputIterator>::type OutputType;

    // whether to use fast_scan or safe_scan
    // TODO profile this threshold
    static const bool use_fast_scan = sizeof(OutputType) <= 16 && thrust::detail::is_pod<OutputType>::value;

    return thrust::detail::device::cuda::dispatch::inclusive_scan
        (first, last, result, binary_op,
         thrust::detail::integral_constant<bool, use_fast_scan>());
}

template<typename InputIterator,
         typename OutputIterator,
         typename T,
         typename AssociativeOperator>
  OutputIterator exclusive_scan(InputIterator first,
                                InputIterator last,
                                OutputIterator result,
                                T init,
                                AssociativeOperator binary_op)
{
    typedef typename thrust::iterator_value<OutputIterator>::type OutputType;

    // whether to use fast_scan or safe_scan
    // TODO profile this threshold
    static const bool use_fast_scan = sizeof(OutputType) <= 16 && thrust::detail::is_pod<OutputType>::value;

    return thrust::detail::device::cuda::dispatch::exclusive_scan
        (first, last, result, init, binary_op,
         thrust::detail::integral_constant<bool, use_fast_scan>());
}

} // end namespace cuda
} // end namespace device
} // end namespace detail
} // end namespace thrust

<|endoftext|>


<commit_before>/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/**
 * Copyright (C) 2013 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * See COPYING for copyright and distribution information.
 */

#include <stdexcept>
#include <ndn-cpp/common.hpp>
#include <ndn-cpp/interest.hpp>

#if __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreorder"
#pragma clang diagnostic ignored "-Wtautological-compare"
#pragma clang diagnostic ignored "-Wunused-variable"
#pragma clang diagnostic ignored "-Wunused-function"
#elif __GNUC__
#pragma GCC diagnostic ignored "-Wreorder"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#endif

#include <cryptopp/osrng.h>

using namespace std;

namespace ndn {

const uint32_t&
Interest::getNonce() const
{
  static CryptoPP::AutoSeededRandomPool rng;

  if (nonce_ == 0)
    nonce_ = rng.GenerateWord32();

  return nonce_;
}

bool
Interest::matchesName(const Name &name) const
{
  if (!name_.isPrefixOf(name))
    return false;

  if (minSuffixComponents_ >= 0 &&
    // Add 1 for the implicit digest.
      !(name.size() + 1 - name_.size() >= minSuffixComponents_))
    return false;

  if (maxSuffixComponents_ >= 0 &&
    // Add 1 for the implicit digest.
    !(name.size() + 1 - name_.size() <= maxSuffixComponents_))
    return false;

  if (!exclude_.empty() && name.size() > name_.size() &&
      exclude_.isExcluded(name[name_.size()]))
    return false;

  return true;
}

std::ostream &
operator << (std::ostream &os, const Interest &interest)
{
  os << interest.getName();

  char delim = '?';

  if (interest.getMinSuffixComponents() >= 0) {
    os << delim << "ndn.MinSuffixComponents=" << interest.getMinSuffixComponents();
    delim = '&';
  }
  if (interest.getMaxSuffixComponents() >= 0) {
    os << delim << "ndn.MaxSuffixComponents=" << interest.getMaxSuffixComponents();
    delim = '&';
  }
  if (interest.getChildSelector() >= 0) {
    os << delim << "ndn.ChildSelector=" << interest.getChildSelector();
    delim = '&';
  }
  if (interest.getMustBeFresh()) {
    os << delim << "ndn.MustBeFresh=" << interest.getMustBeFresh();
    delim = '&';
  }
  if (interest.getScope() >= 0) {
    os << delim << "ndn.Scope=" << interest.getScope();
    delim = '&';
  }
  if (interest.getInterestLifetime() >= 0) {
    os << delim << "ndn.InterestLifetime=" << interest.getInterestLifetime();
    delim = '&';
  }

  if (interest.getNonce() > 0) {
    os << delim << "ndn.Nonce=" << interest.getNonce();
    delim = '&';
  }
  if (!interest.getExclude().empty()) {
    os << delim << "ndn.Exclude=" << interest.getExclude();
    delim = '&';
  }

  return os;
}

const Block&
Interest::wireEncode() const
{
  if (wire_.hasWire())
    return wire_;

  // Interest ::= INTEREST-TYPE TLV-LENGTH
  //                Name
  //                Selectors?
  //                Nonce
  //                Scope?
  //                InterestLifetime?

  wire_ = Block(Tlv::Interest);
  wire_.push_back(getName().wireEncode());

  // selectors
  {
    Block selectors(Tlv::Selectors);

    if (getMinSuffixComponents() >= 0) {
      selectors.push_back
        (nonNegativeIntegerBlock(Tlv::MinSuffixComponents, getMinSuffixComponents()));
    }
    if (getMaxSuffixComponents() >= 0) {
      selectors.push_back
        (nonNegativeIntegerBlock(Tlv::MaxSuffixComponents, getMaxSuffixComponents()));
    }
    if (!getExclude().empty()) {
      selectors.push_back
        (getExclude().wireEncode());
    }
    if (getChildSelector() >= 0) {
      selectors.push_back
        (nonNegativeIntegerBlock(Tlv::ChildSelector, getChildSelector()));
    }
    if (getMustBeFresh()) {
      selectors.push_back
        (booleanBlock(Tlv::MustBeFresh));
    }

    if (!selectors.getAll().empty())
      {
        selectors.encode();
        wire_.push_back(selectors);
      }
  }

  // Nonce
  {
    wire_.push_back
      (nonNegativeIntegerBlock(Tlv::Nonce, getNonce()));
  }

  if (getScope() >= 0) {
    wire_.push_back
      (nonNegativeIntegerBlock(Tlv::Scope, getScope()));
  }
  if (getInterestLifetime() >= 0) {
    wire_.push_back
      (nonNegativeIntegerBlock(Tlv::InterestLifetime, getInterestLifetime()));
  }

  wire_.encode();
  return wire_;
}

void
Interest::wireDecode(const Block &wire)
{
  wire_ = wire;
  wire_.parse();

  // Interest ::= INTEREST-TYPE TLV-LENGTH
  //                Name
  //                Selectors?
  //                Nonce
  //                Scope?
  //                InterestLifetime?

  // Name
  name_.wireDecode(wire_.get(Tlv::Name));

  // Selectors
  Block::element_iterator selectors = wire_.find(Tlv::Selectors);
  if (selectors != wire_.getAll().end())
    {
      selectors->parse();

      // MinSuffixComponents
      Block::element_iterator val = selectors->find(Tlv::MinSuffixComponents);
      if (val != selectors->getAll().end())
        {
          minSuffixComponents_ = readNonNegativeInteger(*val);
        }

      // MaxSuffixComponents
      val = selectors->find(Tlv::MaxSuffixComponents);
      if (val != selectors->getAll().end())
        {
          maxSuffixComponents_ = readNonNegativeInteger(*val);
        }

      // Exclude
      val = selectors->find(Tlv::Exclude);
      if (val != selectors->getAll().end())
        {
          exclude_.wireDecode(*val);
        }

      // ChildSelector
      val = selectors->find(Tlv::ChildSelector);
      if (val != selectors->getAll().end())
        {
          childSelector_ = readNonNegativeInteger(*val);
        }

      //MustBeFresh aka AnswerOriginKind
      val = selectors->find(Tlv::MustBeFresh);
      if (val != selectors->getAll().end())
        {
          mustBeFresh_ = true;
        }
    }

  // Nonce
  Block::element_iterator val = wire_.find(Tlv::Nonce);
  if (val != wire_.getAll().end())
    {
      nonce_ = readNonNegativeInteger(*val);
    }

  // Scope
  val = wire_.find(Tlv::Scope);
  if (val != wire_.getAll().end())
    {
      scope_ = readNonNegativeInteger(*val);
    }

  // InterestLifetime
  val = wire_.find(Tlv::InterestLifetime);
  if (val != wire_.getAll().end())
    {
      interestLifetime_ = readNonNegativeInteger(*val);
    }
}

}
<commit_msg>interest/tlv: Do not encode InterestLifetime if it has default value (4sec)<commit_after>/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
/**
 * Copyright (C) 2013 Regents of the University of California.
 * @author: Jeff Thompson <jefft0@remap.ucla.edu>
 * See COPYING for copyright and distribution information.
 */

#include <stdexcept>
#include <ndn-cpp/common.hpp>
#include <ndn-cpp/interest.hpp>

#if __clang__
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wreorder"
#pragma clang diagnostic ignored "-Wtautological-compare"
#pragma clang diagnostic ignored "-Wunused-variable"
#pragma clang diagnostic ignored "-Wunused-function"
#elif __GNUC__
#pragma GCC diagnostic ignored "-Wreorder"
#pragma GCC diagnostic ignored "-Wunused-variable"
#pragma GCC diagnostic ignored "-Wunused-function"
#endif

#include <cryptopp/osrng.h>

using namespace std;

namespace ndn {

const Milliseconds DEFAULT_INTEREST_LIFETIME = 4000;

const uint32_t&
Interest::getNonce() const
{
  static CryptoPP::AutoSeededRandomPool rng;

  if (nonce_ == 0)
    nonce_ = rng.GenerateWord32();

  return nonce_;
}

bool
Interest::matchesName(const Name &name) const
{
  if (!name_.isPrefixOf(name))
    return false;

  if (minSuffixComponents_ >= 0 &&
    // Add 1 for the implicit digest.
      !(name.size() + 1 - name_.size() >= minSuffixComponents_))
    return false;

  if (maxSuffixComponents_ >= 0 &&
    // Add 1 for the implicit digest.
    !(name.size() + 1 - name_.size() <= maxSuffixComponents_))
    return false;

  if (!exclude_.empty() && name.size() > name_.size() &&
      exclude_.isExcluded(name[name_.size()]))
    return false;

  return true;
}

std::ostream &
operator << (std::ostream &os, const Interest &interest)
{
  os << interest.getName();

  char delim = '?';

  if (interest.getMinSuffixComponents() >= 0) {
    os << delim << "ndn.MinSuffixComponents=" << interest.getMinSuffixComponents();
    delim = '&';
  }
  if (interest.getMaxSuffixComponents() >= 0) {
    os << delim << "ndn.MaxSuffixComponents=" << interest.getMaxSuffixComponents();
    delim = '&';
  }
  if (interest.getChildSelector() >= 0) {
    os << delim << "ndn.ChildSelector=" << interest.getChildSelector();
    delim = '&';
  }
  if (interest.getMustBeFresh()) {
    os << delim << "ndn.MustBeFresh=" << interest.getMustBeFresh();
    delim = '&';
  }
  if (interest.getScope() >= 0) {
    os << delim << "ndn.Scope=" << interest.getScope();
    delim = '&';
  }
  if (interest.getInterestLifetime() >= 0 && interest.getInterestLifetime() != DEFAULT_INTEREST_LIFETIME) {
    os << delim << "ndn.InterestLifetime=" << interest.getInterestLifetime();
    delim = '&';
  }

  if (interest.getNonce() > 0) {
    os << delim << "ndn.Nonce=" << interest.getNonce();
    delim = '&';
  }
  if (!interest.getExclude().empty()) {
    os << delim << "ndn.Exclude=" << interest.getExclude();
    delim = '&';
  }

  return os;
}

const Block&
Interest::wireEncode() const
{
  if (wire_.hasWire())
    return wire_;

  // Interest ::= INTEREST-TYPE TLV-LENGTH
  //                Name
  //                Selectors?
  //                Nonce
  //                Scope?
  //                InterestLifetime?

  wire_ = Block(Tlv::Interest);
  wire_.push_back(getName().wireEncode());

  // selectors
  {
    Block selectors(Tlv::Selectors);

    if (getMinSuffixComponents() >= 0) {
      selectors.push_back
        (nonNegativeIntegerBlock(Tlv::MinSuffixComponents, getMinSuffixComponents()));
    }
    if (getMaxSuffixComponents() >= 0) {
      selectors.push_back
        (nonNegativeIntegerBlock(Tlv::MaxSuffixComponents, getMaxSuffixComponents()));
    }
    if (!getExclude().empty()) {
      selectors.push_back
        (getExclude().wireEncode());
    }
    if (getChildSelector() >= 0) {
      selectors.push_back
        (nonNegativeIntegerBlock(Tlv::ChildSelector, getChildSelector()));
    }
    if (getMustBeFresh()) {
      selectors.push_back
        (booleanBlock(Tlv::MustBeFresh));
    }

    if (!selectors.getAll().empty())
      {
        selectors.encode();
        wire_.push_back(selectors);
      }
  }

  // Nonce
  {
    wire_.push_back
      (nonNegativeIntegerBlock(Tlv::Nonce, getNonce()));
  }

  // Scope
  if (getScope() >= 0) {
    wire_.push_back
      (nonNegativeIntegerBlock(Tlv::Scope, getScope()));
  }

  // InterestLifetime
  if (getInterestLifetime() >= 0 && getInterestLifetime() != DEFAULT_INTEREST_LIFETIME) {
    wire_.push_back
      (nonNegativeIntegerBlock(Tlv::InterestLifetime, getInterestLifetime()));
  }

  wire_.encode();
  return wire_;
}

void
Interest::wireDecode(const Block &wire)
{
  wire_ = wire;
  wire_.parse();

  // Interest ::= INTEREST-TYPE TLV-LENGTH
  //                Name
  //                Selectors?
  //                Nonce
  //                Scope?
  //                InterestLifetime?

  // Name
  name_.wireDecode(wire_.get(Tlv::Name));

  // Selectors
  Block::element_iterator selectors = wire_.find(Tlv::Selectors);
  if (selectors != wire_.getAll().end())
    {
      selectors->parse();

      // MinSuffixComponents
      Block::element_iterator val = selectors->find(Tlv::MinSuffixComponents);
      if (val != selectors->getAll().end())
        {
          minSuffixComponents_ = readNonNegativeInteger(*val);
        }

      // MaxSuffixComponents
      val = selectors->find(Tlv::MaxSuffixComponents);
      if (val != selectors->getAll().end())
        {
          maxSuffixComponents_ = readNonNegativeInteger(*val);
        }

      // Exclude
      val = selectors->find(Tlv::Exclude);
      if (val != selectors->getAll().end())
        {
          exclude_.wireDecode(*val);
        }

      // ChildSelector
      val = selectors->find(Tlv::ChildSelector);
      if (val != selectors->getAll().end())
        {
          childSelector_ = readNonNegativeInteger(*val);
        }

      //MustBeFresh aka AnswerOriginKind
      val = selectors->find(Tlv::MustBeFresh);
      if (val != selectors->getAll().end())
        {
          mustBeFresh_ = true;
        }
    }

  // Nonce
  Block::element_iterator val = wire_.find(Tlv::Nonce);
  if (val != wire_.getAll().end())
    {
      nonce_ = readNonNegativeInteger(*val);
    }

  // Scope
  val = wire_.find(Tlv::Scope);
  if (val != wire_.getAll().end())
    {
      scope_ = readNonNegativeInteger(*val);
    }

  // InterestLifetime
  val = wire_.find(Tlv::InterestLifetime);
  if (val != wire_.getAll().end())
    {
      interestLifetime_ = readNonNegativeInteger(*val);
    }
  else
    {
      interestLifetime_ = DEFAULT_INTEREST_LIFETIME;
    }
}

}
<|endoftext|>


<commit_before>#include <cstring>

/*
 * Member function definitions of IQHandler template class.
 * See iqhandler.h for template class declaration.
 */
template <typename T, size_t M, size_t N>
IQHandler<T, M, N>::IQHandler(iqcond_t cond_func) :
m_cond(cond_func) {
    static_assert(M < N, "Input queue must be smaller than circular buffer.");

    chSysLock();
    m_thread = chThdCreateI(m_wa_iqueue_handler_thread,
            sizeof(m_wa_iqueue_handler_thread), NORMALPRIO + 1,
            iqueue_handler, this);
    chSysUnlock();
    ibqObjectInit(&m_iqueue, false, m_iqueue_buffer, sizeof(T), M, nullptr, nullptr);
    chBSemObjectInit(&m_sem, false); /* set to not taken */
}

template <typename T, size_t M, size_t N>
void IQHandler<T, M, N>::start() {
    chSysLock();
    ibqResetI(&m_iqueue);
    chBSemResetI(&m_sem, false); /* set to not taken*/
    chThdStartI(m_thread);
    chSchRescheduleS();
    chSysUnlock();
}

template <typename T, size_t M, size_t N>
void IQHandler<T, M, N>::stop() {
    chThdTerminate(m_thread);

    chSysLock();
    ibqResetI(&m_iqueue);
    chBSemResetI(&m_sem, true); /* set to taken */
    chSysUnlock();

    chThdWait(m_thread);
}

template <typename T, size_t M, size_t N>
void IQHandler<T, M, N>::wait() {
    chBSemWait(&m_sem);
}

template <typename T, size_t M, size_t N>
void IQHandler<T, M, N>::signal() {
    chBSemSignal(&m_sem);
}

template <typename T, size_t M, size_t N>
void IQHandler<T, M, N>::insertI(T* element) {
    chDbgCheckClassI();

    uint8_t* buf = ibqGetEmptyBufferI(&m_iqueue);
    if (buf == nullptr) {
        /* queue elements not consumed quickly enough */
        chSysHalt("input queue full");
        // TODO: handle this case
    }
    std::memcpy(buf, element, sizeof(T));
    ibqPostFullBufferI(&m_iqueue, sizeof(T));
}

template <typename T, size_t M, size_t N>
const std::array<T, N>& IQHandler<T, M, N>::circular_buffer() const {
    return m_circular_buffer;
}

template <typename T, size_t M, size_t N>
size_t IQHandler<T, M, N>::index() const {
    return m_buffer_index;
}

template <typename T, size_t M, size_t N>
void IQHandler<T, M, N>::iqueue_handler(void* p) {
    auto obj = static_cast<IQHandler<T, M, N>*>(p);
    while (!chThdShouldTerminateX()) {
        if (ibqGetFullBufferTimeout(&obj->m_iqueue, TIME_INFINITE) == MSG_OK) {
            iqcond_t condition = obj->m_cond; /* get condition to check if element should be inserted */
            if ((condition == nullptr) || (condition(p))) {
                if (chBSemWait(&obj->m_sem) == MSG_RESET) { /* wait for algorithm calculation to finish */
                    /* Sem reset due to start/stop */
                    ibqReleaseEmptyBuffer(&obj->m_iqueue);
                    chThdYield();
                    continue;
                }
                obj->insert_circular_buffer(reinterpret_cast<T*>(obj->m_iqueue.ptr));
                chBSemSignal(&obj->m_sem);
            }
            ibqReleaseEmptyBuffer(&obj->m_iqueue);
        }
        chThdYield();
    }
}

template <typename T, size_t M, size_t N>
void IQHandler<T, M, N>::insert_circular_buffer(T* element) {
    std::memcpy(&m_circular_buffer[m_buffer_index++], element, sizeof(T));
    if (m_buffer_index == N) {
        m_buffer_index = 0;
    }
}
<commit_msg>Set IQHandler thread name<commit_after>#include <cstring>

/*
 * Member function definitions of IQHandler template class.
 * See iqhandler.h for template class declaration.
 */
template <typename T, size_t M, size_t N>
IQHandler<T, M, N>::IQHandler(iqcond_t cond_func) :
m_cond(cond_func) {
    static_assert(M < N, "Input queue must be smaller than circular buffer.");

    chSysLock();
    m_thread = chThdCreateI(m_wa_iqueue_handler_thread,
            sizeof(m_wa_iqueue_handler_thread), NORMALPRIO + 1,
            iqueue_handler, this);
    chSysUnlock();
    ibqObjectInit(&m_iqueue, false, m_iqueue_buffer, sizeof(T), M, nullptr, nullptr);
    chBSemObjectInit(&m_sem, false); /* set to not taken */
}

template <typename T, size_t M, size_t N>
void IQHandler<T, M, N>::start() {
    chSysLock();
    ibqResetI(&m_iqueue);
    chBSemResetI(&m_sem, false); /* set to not taken*/
    chThdStartI(m_thread);
    chSchRescheduleS();
    chSysUnlock();
}

template <typename T, size_t M, size_t N>
void IQHandler<T, M, N>::stop() {
    chThdTerminate(m_thread);

    chSysLock();
    ibqResetI(&m_iqueue);
    chBSemResetI(&m_sem, true); /* set to taken */
    chSysUnlock();

    chThdWait(m_thread);
}

template <typename T, size_t M, size_t N>
void IQHandler<T, M, N>::wait() {
    chBSemWait(&m_sem);
}

template <typename T, size_t M, size_t N>
void IQHandler<T, M, N>::signal() {
    chBSemSignal(&m_sem);
}

template <typename T, size_t M, size_t N>
void IQHandler<T, M, N>::insertI(T* element) {
    chDbgCheckClassI();

    uint8_t* buf = ibqGetEmptyBufferI(&m_iqueue);
    if (buf == nullptr) {
        /* queue elements not consumed quickly enough */
        chSysHalt("input queue full");
        // TODO: handle this case
    }
    std::memcpy(buf, element, sizeof(T));
    ibqPostFullBufferI(&m_iqueue, sizeof(T));
}

template <typename T, size_t M, size_t N>
const std::array<T, N>& IQHandler<T, M, N>::circular_buffer() const {
    return m_circular_buffer;
}

template <typename T, size_t M, size_t N>
size_t IQHandler<T, M, N>::index() const {
    return m_buffer_index;
}

template <typename T, size_t M, size_t N>
void IQHandler<T, M, N>::iqueue_handler(void* p) {
    auto obj = static_cast<IQHandler<T, M, N>*>(p);
    chRegSetThreadName("iqhandler");

    while (!chThdShouldTerminateX()) {
        if (ibqGetFullBufferTimeout(&obj->m_iqueue, TIME_INFINITE) == MSG_OK) {
            iqcond_t condition = obj->m_cond; /* get condition to check if element should be inserted */
            if ((condition == nullptr) || (condition(p))) {
                if (chBSemWait(&obj->m_sem) == MSG_RESET) { /* wait for algorithm calculation to finish */
                    /* Sem reset due to start/stop */
                    ibqReleaseEmptyBuffer(&obj->m_iqueue);
                    chThdYield();
                    continue;
                }
                obj->insert_circular_buffer(reinterpret_cast<T*>(obj->m_iqueue.ptr));
                chBSemSignal(&obj->m_sem);
            }
            ibqReleaseEmptyBuffer(&obj->m_iqueue);
        }
        chThdYield();
    }
}

template <typename T, size_t M, size_t N>
void IQHandler<T, M, N>::insert_circular_buffer(T* element) {
    std::memcpy(&m_circular_buffer[m_buffer_index++], element, sizeof(T));
    if (m_buffer_index == N) {
        m_buffer_index = 0;
    }
}
<|endoftext|>


<commit_before>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- vim:set ts=4 sw=4 sts=4 noet: */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "job.hh"

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <map>
#include <string>

#include <boost/ptr_container/ptr_map.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/scoped_array.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/uuid/string_generator.hpp>
#include <boost/uuid/uuid_io.hpp>

#include "lo.pb.h"

#include "bc/index.h"
#include "db/statement-driver.h"
#include "lo/layout_loader.h"

using std::cerr;
using std::endl;
using std::fclose;
using std::fopen;
using std::fread;
using std::fseek;
using std::make_pair;
using std::perror;
using std::printf;
using std::sscanf;
using std::string;
using std::strlen;

namespace job {

namespace {

class FormatLoader : db::StatementDriver {
public:
	// Note that db is for read only.
	explicit FormatLoader(sqlite3 *db)
		: db::StatementDriver(db, "SELECT format FROM model")
	{}

	// the return value should be freed by caller.
	char *Load()
	{
		int e;
		e = sqlite3_step(stmt());
		if (e != SQLITE_ROW) {
			cerr << "failed to step statement: " << e << endl;
			return NULL;
		}
		const char *f = (const char *)sqlite3_column_text(stmt(), 0);
		size_t len = strlen(f);
		char *format = new char[len+1];
		strcpy(format, f);
		return format;
	}
};

typedef std::map<int, int> TargetMap;

class SourceLayout : boost::noncopyable {
public:
	void AddTrack(lo::Track *track) {
		tv_.push_back(track);
	}

	void AddSector(lo::Sector *sector) {
		(void)sector; // nothing to do
	}

	void AddData(lo::Data *data) {
		dv_.push_back(data);
	}

	int CollectTargets(TargetMap *tm) const {
		int si = 0;
		int di = 0;
		int pos = kOffsetBase;
		for (TrackVector::const_iterator it=tv_.begin();it!=tv_.end();++it) {
			int nos = it->nos();
			int nod = it->nod();
			int sie = si + nos;
			int dib = di;
			int die = di + nod;

			while (si++ < sie) {
				di = dib;
				while (di < die) {
					const lo::Data &d = dv_.at(di++);
					switch (d.type()) {
					case lo::S:
						if (std::strncmp(d.name().c_str(), "phsp:target", 11) == 0) {
							const char *nstr = d.name().c_str();
							int target_id = std::atoi(&nstr[11]);
							tm->insert(make_pair(target_id, pos));
						}
						break;
					default:
						cerr << "unexpected data type: " << d.type() << endl;
						return -1;
					}
					pos += d.size();
				}
			}
		}
		return pos;
	}

private:
	typedef boost::ptr_vector<lo::Track> TrackVector;
	typedef boost::ptr_vector<lo::Data> DataVector;

	TrackVector tv_;
	DataVector dv_;
};

typedef boost::ptr_map<string, std::map<string, double> > TargetValueMap;

class TargetLoader : db::StatementDriver {
public:
	// Note that db is for read only.
	explicit TargetLoader(sqlite3 *db)
		: db::StatementDriver(db, "SELECT uuid, id FROM phsp_targets WHERE rowid = ?")
	{}

	bool Load(const TargetMap &tm, const double *data, TargetValueMap *tvm) {
		boost::uuids::uuid u;
		boost::uuids::string_generator gen;
		for (TargetMap::const_iterator it=tm.begin();it!=tm.end();++it) {
			int e = sqlite3_bind_int(stmt(), 1, it->first);
			if (e != SQLITE_OK) {
				cerr << "failed to bind rowid: " << e << endl;
				return false;
			}
			e = sqlite3_step(stmt());
			if (e != SQLITE_ROW) {
				cerr << "missing row with rowid " << it->first << " in phsp_targets" << endl;
				return false;
			}
			u = gen((const char *)sqlite3_column_text(stmt(), 0));
			(*tvm)[string((const char *)u.data, 16)].insert(make_pair((const char *)sqlite3_column_text(stmt(), 1), data[it->second]));
			sqlite3_reset(stmt());
		}
		return true;
	}
};

class TargetLayout : boost::noncopyable {
public:
	void AddTrack(lo::Track *track) {
		tv_.push_back(track);
	}

	void AddSector(lo::Sector *sector) {
		sv_.push_back(sector);
	}

	void AddData(lo::Data *data) {
		dv_.push_back(data);
	}

	bool Rewrite(const char *format, const TargetValueMap &tvm, FILE *fp) const {
		boost::scoped_array<char> buf(new char[32]); // FIXME
		int si = 0;
		int di = 0;
		if (fseek(fp, kOffsetBase*sizeof(double), SEEK_SET) != 0) {
			return false;
		}
		for (TrackVector::const_iterator it=tv_.begin();it!=tv_.end();++it) {
			int nos = it->nos();
			int nod = it->nod();
			int sie = si + nos;
			int dib = di;
			int die = di + nod;

			while (si < sie) {
				const lo::Sector &s = sv_.at(si++);
				di = dib;
				while (di < die) {
					const lo::Data &d = dv_.at(di++);
					switch (d.type()) {
					case lo::S:
					case lo::X:
						{
							TargetValueMap::const_iterator it = tvm.find(s.id());
							if (it == tvm.end()) {
								if (fseek(fp, d.size()*sizeof(double), SEEK_CUR) != 0) {
									return false;
								}
							} else {
								std::map<string, double>::const_iterator mit;
								if (strcmp("phml", format) == 0) {
									sprintf(buf.get(), "%d", d.id());
									mit = it->second->find(buf.get());
								} else {
									mit = it->second->find(d.name());
								}
								if (mit == it->second->end()) {
									if (fseek(fp, d.size()*sizeof(double), SEEK_CUR) != 0) {
										return false;
									}
								} else {
									double value = mit->second;
									if (std::fwrite(&value, sizeof(double), d.size(), fp) != static_cast<size_t>(d.size())) {
										// TODO
										return false;
									}
								}
							}
						}
						break;
					default:
						if (fseek(fp, d.size()*sizeof(double), SEEK_CUR) != 0) {
							return false;
						}
						break;
					}
				}
			}
		}
		return true;
	}

private:
	typedef boost::ptr_vector<lo::Track> TrackVector;
	typedef boost::ptr_vector<lo::Sector> SectorVector;
	typedef boost::ptr_vector<lo::Data> DataVector;

	TrackVector tv_;
	SectorVector sv_;
	DataVector dv_;
};

}

bool Store(sqlite3 *db,
		   const char *source_layout_file, const char *source_data_file,
		   const char *target_layout_file, const char *target_data_file)
{
	SourceLayout source_layout;
	{
		boost::scoped_ptr<LayoutLoader> loader(new LayoutLoader(source_layout_file));
		if (!loader->Load(&source_layout)) return false;
	}
	TargetMap tm;
	int source_layer_size = source_layout.CollectTargets(&tm);
	if (source_layer_size <= 0) {
		return false;
	}

	boost::scoped_array<double> data(new double[source_layer_size]);
	FILE *fp = fopen(source_data_file, "rb");
	if (!fp) {
		perror(source_data_file);
		return false;
	}
	if (fread(data.get(), sizeof(double), source_layer_size, fp) != static_cast<size_t>(source_layer_size)) {
		cerr << "could not read data with size: " << source_layer_size << endl;
		fclose(fp);
		return false;
	}
	fclose(fp);

	boost::scoped_array<char> format;
	TargetValueMap tvm;
	{
		// check model's format
		{
			FormatLoader loader(db);
			format.reset(loader.Load());
			if (!format) return false;
		}
		{
			TargetLoader loader(db);
			if (!loader.Load(tm, data.get(), &tvm))
				return false;
		}
	}

	fp = fopen(target_data_file, "r+b");
	if (!fp) {
		perror(target_data_file);
		return false;
	}
	TargetLayout target_layout;
	{
		boost::scoped_ptr<LayoutLoader> loader(new LayoutLoader(target_layout_file));
		if (!loader->Load(&target_layout)) return false;
	}
	if (!target_layout.Rewrite(format.get(), tvm, fp)) {
		fclose(fp);
		return false;
	}
	fclose(fp);

	return true;
}

}
<commit_msg>fix a resource leak<commit_after>/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- vim:set ts=4 sw=4 sts=4 noet: */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "job.hh"

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <iostream>
#include <map>
#include <string>

#include <boost/ptr_container/ptr_map.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/scoped_array.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/uuid/string_generator.hpp>
#include <boost/uuid/uuid_io.hpp>

#include "lo.pb.h"

#include "bc/index.h"
#include "db/statement-driver.h"
#include "lo/layout_loader.h"

using std::cerr;
using std::endl;
using std::fclose;
using std::fopen;
using std::fread;
using std::fseek;
using std::make_pair;
using std::perror;
using std::printf;
using std::sscanf;
using std::string;
using std::strlen;

namespace job {

namespace {

class FormatLoader : db::StatementDriver {
public:
	// Note that db is for read only.
	explicit FormatLoader(sqlite3 *db)
		: db::StatementDriver(db, "SELECT format FROM model")
	{}

	// the return value should be freed by caller.
	char *Load()
	{
		int e;
		e = sqlite3_step(stmt());
		if (e != SQLITE_ROW) {
			cerr << "failed to step statement: " << e << endl;
			return NULL;
		}
		const char *f = (const char *)sqlite3_column_text(stmt(), 0);
		size_t len = strlen(f);
		char *format = new char[len+1];
		strcpy(format, f);
		return format;
	}
};

typedef std::map<int, int> TargetMap;

class SourceLayout : boost::noncopyable {
public:
	void AddTrack(lo::Track *track) {
		tv_.push_back(track);
	}

	void AddSector(lo::Sector *sector) {
		(void)sector; // nothing to do
	}

	void AddData(lo::Data *data) {
		dv_.push_back(data);
	}

	int CollectTargets(TargetMap *tm) const {
		int si = 0;
		int di = 0;
		int pos = kOffsetBase;
		for (TrackVector::const_iterator it=tv_.begin();it!=tv_.end();++it) {
			int nos = it->nos();
			int nod = it->nod();
			int sie = si + nos;
			int dib = di;
			int die = di + nod;

			while (si++ < sie) {
				di = dib;
				while (di < die) {
					const lo::Data &d = dv_.at(di++);
					switch (d.type()) {
					case lo::S:
						if (std::strncmp(d.name().c_str(), "phsp:target", 11) == 0) {
							const char *nstr = d.name().c_str();
							int target_id = std::atoi(&nstr[11]);
							tm->insert(make_pair(target_id, pos));
						}
						break;
					default:
						cerr << "unexpected data type: " << d.type() << endl;
						return -1;
					}
					pos += d.size();
				}
			}
		}
		return pos;
	}

private:
	typedef boost::ptr_vector<lo::Track> TrackVector;
	typedef boost::ptr_vector<lo::Data> DataVector;

	TrackVector tv_;
	DataVector dv_;
};

typedef boost::ptr_map<string, std::map<string, double> > TargetValueMap;

class TargetLoader : db::StatementDriver {
public:
	// Note that db is for read only.
	explicit TargetLoader(sqlite3 *db)
		: db::StatementDriver(db, "SELECT uuid, id FROM phsp_targets WHERE rowid = ?")
	{}

	bool Load(const TargetMap &tm, const double *data, TargetValueMap *tvm) {
		boost::uuids::uuid u;
		boost::uuids::string_generator gen;
		for (TargetMap::const_iterator it=tm.begin();it!=tm.end();++it) {
			int e = sqlite3_bind_int(stmt(), 1, it->first);
			if (e != SQLITE_OK) {
				cerr << "failed to bind rowid: " << e << endl;
				return false;
			}
			e = sqlite3_step(stmt());
			if (e != SQLITE_ROW) {
				cerr << "missing row with rowid " << it->first << " in phsp_targets" << endl;
				return false;
			}
			u = gen((const char *)sqlite3_column_text(stmt(), 0));
			(*tvm)[string((const char *)u.data, 16)].insert(make_pair((const char *)sqlite3_column_text(stmt(), 1), data[it->second]));
			sqlite3_reset(stmt());
		}
		return true;
	}
};

class TargetLayout : boost::noncopyable {
public:
	void AddTrack(lo::Track *track) {
		tv_.push_back(track);
	}

	void AddSector(lo::Sector *sector) {
		sv_.push_back(sector);
	}

	void AddData(lo::Data *data) {
		dv_.push_back(data);
	}

	bool Rewrite(const char *format, const TargetValueMap &tvm, FILE *fp) const {
		boost::scoped_array<char> buf(new char[32]); // FIXME
		int si = 0;
		int di = 0;
		if (fseek(fp, kOffsetBase*sizeof(double), SEEK_SET) != 0) {
			return false;
		}
		for (TrackVector::const_iterator it=tv_.begin();it!=tv_.end();++it) {
			int nos = it->nos();
			int nod = it->nod();
			int sie = si + nos;
			int dib = di;
			int die = di + nod;

			while (si < sie) {
				const lo::Sector &s = sv_.at(si++);
				di = dib;
				while (di < die) {
					const lo::Data &d = dv_.at(di++);
					switch (d.type()) {
					case lo::S:
					case lo::X:
						{
							TargetValueMap::const_iterator it = tvm.find(s.id());
							if (it == tvm.end()) {
								if (fseek(fp, d.size()*sizeof(double), SEEK_CUR) != 0) {
									return false;
								}
							} else {
								std::map<string, double>::const_iterator mit;
								if (strcmp("phml", format) == 0) {
									sprintf(buf.get(), "%d", d.id());
									mit = it->second->find(buf.get());
								} else {
									mit = it->second->find(d.name());
								}
								if (mit == it->second->end()) {
									if (fseek(fp, d.size()*sizeof(double), SEEK_CUR) != 0) {
										return false;
									}
								} else {
									double value = mit->second;
									if (std::fwrite(&value, sizeof(double), d.size(), fp) != static_cast<size_t>(d.size())) {
										// TODO
										return false;
									}
								}
							}
						}
						break;
					default:
						if (fseek(fp, d.size()*sizeof(double), SEEK_CUR) != 0) {
							return false;
						}
						break;
					}
				}
			}
		}
		return true;
	}

private:
	typedef boost::ptr_vector<lo::Track> TrackVector;
	typedef boost::ptr_vector<lo::Sector> SectorVector;
	typedef boost::ptr_vector<lo::Data> DataVector;

	TrackVector tv_;
	SectorVector sv_;
	DataVector dv_;
};

}

bool Store(sqlite3 *db,
		   const char *source_layout_file, const char *source_data_file,
		   const char *target_layout_file, const char *target_data_file)
{
	SourceLayout source_layout;
	{
		boost::scoped_ptr<LayoutLoader> loader(new LayoutLoader(source_layout_file));
		if (!loader->Load(&source_layout)) return false;
	}
	TargetMap tm;
	int source_layer_size = source_layout.CollectTargets(&tm);
	if (source_layer_size <= 0) {
		return false;
	}

	boost::scoped_array<double> data(new double[source_layer_size]);
	FILE *fp = fopen(source_data_file, "rb");
	if (!fp) {
		perror(source_data_file);
		return false;
	}
	if (fread(data.get(), sizeof(double), source_layer_size, fp) != static_cast<size_t>(source_layer_size)) {
		cerr << "could not read data with size: " << source_layer_size << endl;
		fclose(fp);
		return false;
	}
	fclose(fp);

	boost::scoped_array<char> format;
	TargetValueMap tvm;
	{
		// check model's format
		{
			FormatLoader loader(db);
			format.reset(loader.Load());
			if (!format) return false;
		}
		{
			TargetLoader loader(db);
			if (!loader.Load(tm, data.get(), &tvm))
				return false;
		}
	}

	TargetLayout target_layout;
	{
		boost::scoped_ptr<LayoutLoader> loader(new LayoutLoader(target_layout_file));
		if (!loader->Load(&target_layout)) return false;
	}
	fp = fopen(target_data_file, "r+b");
	if (!fp) {
		perror(target_data_file);
		return false;
	}
	if (!target_layout.Rewrite(format.get(), tvm, fp)) {
		fclose(fp);
		return false;
	}
	fclose(fp);

	return true;
}

}
<|endoftext|>


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

#include <pcl/io/pcd_io.h>
#include <pcl/console/print.h>
#include <pcl/console/parse.h>
#include <pcl/console/time.h>

#include <pcl/segmentation/unary_classifier.h>

using namespace pcl;
using namespace pcl::io;
using namespace pcl::console;

double default_feature_threshold = 5.0;
double default_normal_radius_search = 0.01;
double default_fpfh_radius_search = 0.05;

typedef PointXYZRGBA PointT;
typedef PointCloud<PointT> CloudT;
typedef PointCloud<PointXYZRGBL> CloudLT;
typedef PointCloud<FPFHSignature33> FeatureT;

void
printHelp (int, char **argv)
{
  print_error ("Syntax is: %s input.pcd output.pcd <options>\n", argv[0]);
  print_info ("  where options are:\n");
  print_info ("                     -d = trained features directory \n");
  print_info ("                     -threshold X = feature threshold (default: ");
  print_value ("%f", default_feature_threshold); print_info (")\n");
  print_info ("                     -normal-search X = Normal radius search (default: ");
  print_value ("%f", default_normal_radius_search); print_info (")\n");
  print_info ("                     -fpfh-search X = FPFH radius search (default: ");
  print_value ("%f", default_fpfh_radius_search); print_info (")\n");
}

bool
loadTrainedFeatures (std::vector<FeatureT::Ptr> &out,
                     const boost::filesystem::path &base_dir)
{
  if (!boost::filesystem::exists (base_dir) && !boost::filesystem::is_directory (base_dir))
    return false;

  for (boost::filesystem::directory_iterator it (base_dir); it != boost::filesystem::directory_iterator (); ++it)
  {
    if (!boost::filesystem::is_directory (it->status ()) &&
        boost::filesystem::extension (it->path ()) == ".pcd")
    {
      std::stringstream ss;
      ss << it->path ().filename ();

      print_highlight ("Loading %s \n", ss.str ().c_str ());

      FeatureT::Ptr features (new FeatureT);
      loadPCDFile (it->path ().filename (), *features);

      out.push_back (features);
    }
  }
  return true;
}

bool
loadCloud (const std::string &filename, CloudT::Ptr &cloud)
{
  TicToc tt;
  print_highlight ("Loading "); print_value ("%s ", filename.c_str ());

  tt.tic ();
  if (loadPCDFile (filename, *cloud) < 0)
    return (false);
  print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%d", cloud->width * cloud->height); print_info (" points]\n");

  return (true);
}

void
compute (const CloudT::Ptr &input, std::vector<FeatureT::Ptr> &trained_features,
         CloudLT::Ptr &out,
         float normal_radius_search,
         float fpfh_radius_search,
         float feature_threshold)
{
  TicToc tt;
  tt.tic ();

  print_highlight ("Computing ");

  UnaryClassifier<PointT> classifier;
  classifier.setInputCloud (input);
  classifier.setTrainedFeatures (trained_features);
  classifier.setNormalRadiusSearch (normal_radius_search);
  classifier.setFPFHRadiusSearch (fpfh_radius_search);
  classifier.setFeatureThreshold (feature_threshold);

  classifier.segment (out);

  print_info ("[done, ");
  print_value ("%g", tt.toc ());
  print_info (" ms : "); print_value ("%d", out->width * out->height);
  print_info (" points]\n");

}

void
saveCloud (const std::string &filename, CloudLT::Ptr &output)
{
  TicToc tt;
  tt.tic ();

  print_highlight ("Saving "); print_value ("%s ", filename.c_str ());

  PCDWriter w;
  w.write (filename, *output);

  print_info ("[done, ");
  print_value ("%g", tt.toc ()); print_info (" ms : ");
  print_value ("%d", output->width * output->height); print_info (" points]\n");
}

/* ---[ */
int
main (int argc, char** argv)
{
  print_info ("Train unary classifier using FPFH. For more information, use: %s -h\n", argv[0]);

  if (argc < 4)
  {
    printHelp (argc, argv);
    return (-1);
  }

  // Parse the command line arguments for .pcd files
  std::vector<int> p_file_indices;
  p_file_indices = parse_file_extension_argument (argc, argv, ".pcd");
  if (p_file_indices.size () != 2)
  {
    print_error ("Need one input PCD file and one output PCD file to continue.\n");
    return (-1);
  }

  // Load the input file
  CloudT::Ptr cloud (new CloudT);
  if (!loadCloud (argv[p_file_indices[0]], cloud))
    return (-1);

  // TODO:: make this as an optional argument ??
  std::vector<int> tmp_indices;
  pcl::removeNaNFromPointCloud (*cloud, *cloud, tmp_indices);

  // parse optional input arguments from the command line
  float normal_radius_search = static_cast<float> (default_normal_radius_search);
  float fpfh_radius_search = static_cast<float> (default_fpfh_radius_search);
  float feature_threshold = static_cast<float> (default_feature_threshold);
  std::string dir_name;

  parse_argument (argc, argv, "-d", dir_name);
  parse_argument (argc, argv, "-threshold", feature_threshold);
  parse_argument (argc, argv, "-normal-radius-search", normal_radius_search);
  parse_argument (argc, argv, "-fpfh-radius-search", fpfh_radius_search);

  print_info ("trained feature directory: %s \n", dir_name.c_str ());

  // load the trained features
  std::vector<FeatureT::Ptr> trained_features;
  loadTrainedFeatures (trained_features, dir_name.c_str ());

  print_info ("feature_threshold: %f \n", feature_threshold);
  print_info ("normal-radius-search: %f \n", normal_radius_search);
  print_info ("fpfh-radius-search: %f \n\n", fpfh_radius_search);

  CloudLT::Ptr out (new CloudLT);
  compute (cloud, trained_features, out, normal_radius_search, fpfh_radius_search, feature_threshold);

  saveCloud (argv[p_file_indices[1]], out);
}

<commit_msg>Follow-up fix to r7110, hopefully this is portable across different OS and Boost versions.<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Point Cloud Library (PCL) - www.pointclouds.org
 *  Copyright (c) 2011-2012, Willow Garage, Inc.
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions
 *  are met:
 *
 *   * Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *   * Redistributions in binary form must reproduce the above
 *     copyright notice, this list of conditions and the following
 *     disclaimer in the documentation and/or other materials provided
 *     with the distribution.
 *   * Neither the name of the copyright holder(s) nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 * Author : Christian Potthast
 * Email  : potthast@usc.edu
 *
 */

#include <pcl/io/pcd_io.h>
#include <pcl/console/print.h>
#include <pcl/console/parse.h>
#include <pcl/console/time.h>

#include <pcl/segmentation/unary_classifier.h>

using namespace pcl;
using namespace pcl::io;
using namespace pcl::console;

double default_feature_threshold = 5.0;
double default_normal_radius_search = 0.01;
double default_fpfh_radius_search = 0.05;

typedef PointXYZRGBA PointT;
typedef PointCloud<PointT> CloudT;
typedef PointCloud<PointXYZRGBL> CloudLT;
typedef PointCloud<FPFHSignature33> FeatureT;

void
printHelp (int, char **argv)
{
  print_error ("Syntax is: %s input.pcd output.pcd <options>\n", argv[0]);
  print_info ("  where options are:\n");
  print_info ("                     -d = trained features directory \n");
  print_info ("                     -threshold X = feature threshold (default: ");
  print_value ("%f", default_feature_threshold); print_info (")\n");
  print_info ("                     -normal-search X = Normal radius search (default: ");
  print_value ("%f", default_normal_radius_search); print_info (")\n");
  print_info ("                     -fpfh-search X = FPFH radius search (default: ");
  print_value ("%f", default_fpfh_radius_search); print_info (")\n");
}

bool
loadTrainedFeatures (std::vector<FeatureT::Ptr> &out,
                     const boost::filesystem::path &base_dir)
{
  if (!boost::filesystem::exists (base_dir) && !boost::filesystem::is_directory (base_dir))
    return false;

  for (boost::filesystem::directory_iterator it (base_dir); it != boost::filesystem::directory_iterator (); ++it)
  {
    if (!boost::filesystem::is_directory (it->status ()) &&
        boost::filesystem::extension (it->path ()) == ".pcd")
    {
      std::stringstream ss;
      ss << it->path ().filename ();

      print_highlight ("Loading %s \n", ss.str ().c_str ());

      FeatureT::Ptr features (new FeatureT);
      loadPCDFile (ss.str (), *features);

      out.push_back (features);
    }
  }
  return true;
}

bool
loadCloud (const std::string &filename, CloudT::Ptr &cloud)
{
  TicToc tt;
  print_highlight ("Loading "); print_value ("%s ", filename.c_str ());

  tt.tic ();
  if (loadPCDFile (filename, *cloud) < 0)
    return (false);
  print_info ("[done, "); print_value ("%g", tt.toc ()); print_info (" ms : "); print_value ("%d", cloud->width * cloud->height); print_info (" points]\n");

  return (true);
}

void
compute (const CloudT::Ptr &input, std::vector<FeatureT::Ptr> &trained_features,
         CloudLT::Ptr &out,
         float normal_radius_search,
         float fpfh_radius_search,
         float feature_threshold)
{
  TicToc tt;
  tt.tic ();

  print_highlight ("Computing ");

  UnaryClassifier<PointT> classifier;
  classifier.setInputCloud (input);
  classifier.setTrainedFeatures (trained_features);
  classifier.setNormalRadiusSearch (normal_radius_search);
  classifier.setFPFHRadiusSearch (fpfh_radius_search);
  classifier.setFeatureThreshold (feature_threshold);

  classifier.segment (out);

  print_info ("[done, ");
  print_value ("%g", tt.toc ());
  print_info (" ms : "); print_value ("%d", out->width * out->height);
  print_info (" points]\n");

}

void
saveCloud (const std::string &filename, CloudLT::Ptr &output)
{
  TicToc tt;
  tt.tic ();

  print_highlight ("Saving "); print_value ("%s ", filename.c_str ());

  PCDWriter w;
  w.write (filename, *output);

  print_info ("[done, ");
  print_value ("%g", tt.toc ()); print_info (" ms : ");
  print_value ("%d", output->width * output->height); print_info (" points]\n");
}

/* ---[ */
int
main (int argc, char** argv)
{
  print_info ("Train unary classifier using FPFH. For more information, use: %s -h\n", argv[0]);

  if (argc < 4)
  {
    printHelp (argc, argv);
    return (-1);
  }

  // Parse the command line arguments for .pcd files
  std::vector<int> p_file_indices;
  p_file_indices = parse_file_extension_argument (argc, argv, ".pcd");
  if (p_file_indices.size () != 2)
  {
    print_error ("Need one input PCD file and one output PCD file to continue.\n");
    return (-1);
  }

  // Load the input file
  CloudT::Ptr cloud (new CloudT);
  if (!loadCloud (argv[p_file_indices[0]], cloud))
    return (-1);

  // TODO:: make this as an optional argument ??
  std::vector<int> tmp_indices;
  pcl::removeNaNFromPointCloud (*cloud, *cloud, tmp_indices);

  // parse optional input arguments from the command line
  float normal_radius_search = static_cast<float> (default_normal_radius_search);
  float fpfh_radius_search = static_cast<float> (default_fpfh_radius_search);
  float feature_threshold = static_cast<float> (default_feature_threshold);
  std::string dir_name;

  parse_argument (argc, argv, "-d", dir_name);
  parse_argument (argc, argv, "-threshold", feature_threshold);
  parse_argument (argc, argv, "-normal-radius-search", normal_radius_search);
  parse_argument (argc, argv, "-fpfh-radius-search", fpfh_radius_search);

  print_info ("trained feature directory: %s \n", dir_name.c_str ());

  // load the trained features
  std::vector<FeatureT::Ptr> trained_features;
  loadTrainedFeatures (trained_features, dir_name.c_str ());

  print_info ("feature_threshold: %f \n", feature_threshold);
  print_info ("normal-radius-search: %f \n", normal_radius_search);
  print_info ("fpfh-radius-search: %f \n\n", fpfh_radius_search);

  CloudLT::Ptr out (new CloudLT);
  compute (cloud, trained_features, out, normal_radius_search, fpfh_radius_search, feature_threshold);

  saveCloud (argv[p_file_indices[1]], out);
}

<|endoftext|>


<commit_before>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2013 Preferred Infrastructure and Nippon Telegraph and Telephone Corporation.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License version 2.1 as published by the Free Software Foundation.
//
// 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#include "save_load.hpp"

#include <ctime>
#include <fstream>
#include <string>
#include <vector>
#include <glog/logging.h>
#include "jubatus/util/lang/cast.h"

#include "jubatus/core/common/exception.hpp"
#include "jubatus/core/common/big_endian.hpp"
#include "jubatus/core/common/crc32.hpp"
#include "jubatus/core/framework/mixable.hpp"
#include "jubatus/core/framework/stream_writer.hpp"

using jubatus::core::common::write_big_endian;
using jubatus::core::common::read_big_endian;
using std::string;
using jubatus::util::lang::lexical_cast;

namespace jubatus {
namespace server {
namespace framework {

namespace {

const char magic_number[8] = "jubatus";
const uint64_t format_version = 1;

uint32_t jubatus_version_major = -1;
uint32_t jubatus_version_minor = -1;
uint32_t jubatus_version_maintenance = -1;

// TODO(gintenlabo): remove sscanf
void init_versions() {
  if (jubatus_version_major == static_cast<uint32_t>(-1)) {
    int major, minor, maintenance;
    std::sscanf(JUBATUS_VERSION, "%d.%d.%d", &major, &minor, &maintenance);  // NOLINT
    jubatus_version_major = major;
    jubatus_version_minor = minor;
    jubatus_version_maintenance = maintenance;
  }
}

const uint64_t system_data_container_version = 1;

struct system_data_container {
  uint64_t version;
  time_t timestamp;
  std::string type;
  std::string id;
  std::string config;

  system_data_container()
      : version(), timestamp(), type(), id(), config() {
  }

  system_data_container(const server_base& server, const std::string& id_)
      : version(system_data_container_version),
        timestamp(std::time(NULL)),
        type(server.argv().type), id(id_),
        config(server.get_config()) {
  }

  MSGPACK_DEFINE(version, timestamp, type, id, config);
};

uint32_t calc_crc32(const char* header,  // header size is 28 (fixed)
    const char* system_data, uint64_t system_data_size,
    const char* user_data, uint64_t user_data_size) {
  uint32_t crc32 = core::common::calc_crc32(header, 28);
  crc32 = core::common::calc_crc32(&header[32], 16, crc32);
  crc32 = core::common::calc_crc32(system_data, system_data_size, crc32);
  crc32 = core::common::calc_crc32(user_data, user_data_size, crc32);
  return crc32;
}

}  // namespace

void save_server(std::ostream& os,
    const server_base& server, const std::string& id) {
  if (id == "") {
    throw JUBATUS_EXCEPTION(
        core::common::exception::runtime_error("empty id is not allowed"));
  }

  init_versions();

  msgpack::sbuffer system_data_buf;
  msgpack::pack(&system_data_buf, system_data_container(server, id));

  msgpack::sbuffer user_data_buf;
  {
    core::framework::stream_writer<msgpack::sbuffer> st(user_data_buf);
    core::framework::jubatus_packer jp(st);
    core::framework::packer packer(jp);
    packer.pack_array(2);

    uint64_t user_data_version = server.user_data_version();
    packer.pack(user_data_version);
    server.get_driver()->pack(packer);
  }

  char header_buf[48];
  std::memcpy(header_buf, magic_number, 8);
  write_big_endian(format_version, &header_buf[8]);
  write_big_endian(jubatus_version_major, &header_buf[16]);
  write_big_endian(jubatus_version_minor, &header_buf[20]);
  write_big_endian(jubatus_version_maintenance, &header_buf[24]);
  // write_big_endian(crc32, &header_buf[28]);  // skipped
  write_big_endian(static_cast<uint64_t>(system_data_buf.size()),
                   &header_buf[32]);
  write_big_endian(static_cast<uint64_t>(user_data_buf.size()),
                   &header_buf[40]);

  uint32_t crc32 = calc_crc32(header_buf,
      system_data_buf.data(), system_data_buf.size(),
      user_data_buf.data(), user_data_buf.size());
  write_big_endian(crc32, &header_buf[28]);

  os.write(header_buf, 48);
  os.write(system_data_buf.data(), system_data_buf.size());
  os.write(user_data_buf.data(), user_data_buf.size());
}

void load_server(std::istream& is,
    server_base& server, const std::string& id) {
  init_versions();

  char header_buf[48];
  is.read(header_buf, 48);
  if (std::memcmp(header_buf, magic_number, 8) != 0) {
    throw JUBATUS_EXCEPTION(
        core::common::exception::runtime_error("invalid file format"));
  }
  uint64_t format_version_read = read_big_endian<uint64_t>(&header_buf[8]);
  if (format_version_read != format_version) {
    throw JUBATUS_EXCEPTION(
        core::common::exception::runtime_error(
          "invalid format version: " +
          lexical_cast<string>(format_version_read) +
          ", expected " +
          lexical_cast<string>(format_version)));
  }
  uint32_t jubatus_major_read = read_big_endian<uint32_t>(&header_buf[16]);
  uint32_t jubatus_minor_read = read_big_endian<uint32_t>(&header_buf[20]);
  uint32_t jubatus_maintenance_read =
      read_big_endian<uint32_t>(&header_buf[24]);
  if (jubatus_major_read != jubatus_version_major ||
      jubatus_minor_read != jubatus_version_minor ||
      jubatus_maintenance_read != jubatus_version_maintenance) {
    throw JUBATUS_EXCEPTION(
        core::common::exception::runtime_error(
          "jubatus version mismatched: current version: " JUBATUS_VERSION
          ", saved version: " +
          lexical_cast<std::string>(jubatus_major_read) + "." +
          lexical_cast<std::string>(jubatus_minor_read) + "." +
          lexical_cast<std::string>(jubatus_maintenance_read)));
  }
  uint32_t crc32_expected = read_big_endian<uint32_t>(&header_buf[28]);
  uint64_t system_data_size = read_big_endian<uint64_t>(&header_buf[32]);
  uint64_t user_data_size = read_big_endian<uint64_t>(&header_buf[40]);

  std::vector<char> system_data_buf(system_data_size);
  is.read(&system_data_buf[0], system_data_size);

  std::vector<char> user_data_buf(user_data_size);
  is.read(&user_data_buf[0], user_data_size);

  uint32_t crc32_actual = calc_crc32(header_buf,
      &system_data_buf[0], system_data_size,
      &user_data_buf[0], user_data_size);
  if (crc32_actual != crc32_expected) {
    std::ostringstream ss;
    ss << "invalid crc32 checksum: " << std::hex << crc32_actual;
    ss << ", read " << crc32_expected;
    throw JUBATUS_EXCEPTION(
        core::common::exception::runtime_error(ss.str()));
  }

  system_data_container system_data_actual;
  try {
    msgpack::unpacked unpacked;
    msgpack::unpack(&unpacked, &system_data_buf[0], system_data_size);
    unpacked.get().convert(&system_data_actual);
  } catch (msgpack::type_error) {
    throw JUBATUS_EXCEPTION(
        core::common::exception::runtime_error(
          "system data is broken"));
  }
  system_data_container system_data_expected(server, id);
  if (system_data_actual.version != system_data_expected.version) {
    throw JUBATUS_EXCEPTION(
        core::common::exception::runtime_error(
          "invalid system data version: saved version: " +
          lexical_cast<string>(system_data_actual.version) +
          ", expected " +
          lexical_cast<string>(system_data_expected.version)));
  }
  if (system_data_actual.type != system_data_expected.type) {
    throw JUBATUS_EXCEPTION(
        core::common::exception::runtime_error(
          "server type mismatched: " + system_data_actual.type +
          ", expected " + system_data_expected.type));
  }
  if (system_data_actual.config != system_data_expected.config) {
    throw JUBATUS_EXCEPTION(
        core::common::exception::runtime_error(
          "server config mismatched" + system_data_actual.config +
          ", expected " + system_data_expected.config));
  }

  try {
    msgpack::unpacked unpacked;
    msgpack::unpack(&unpacked, &user_data_buf[0], user_data_size);

    std::vector<msgpack::object> objs;
    unpacked.get().convert(&objs);
    if (objs.size() != 2) {
      throw JUBATUS_EXCEPTION(
          core::common::exception::runtime_error("invalid user container"));
    }

    uint64_t user_data_version_expected = server.user_data_version();
    uint64_t user_data_version_actual;
    objs[0].convert(&user_data_version_actual);
    if (user_data_version_actual != user_data_version_expected) {
      throw JUBATUS_EXCEPTION(
          core::common::exception::runtime_error(
            "user data version mismatched: " +
            lexical_cast<string>(user_data_version_actual) +
            ", expected " +
            lexical_cast<string>(user_data_version_expected)));
    }

    server.get_driver()->unpack(objs[1]);
  } catch (msgpack::type_error) {
    throw JUBATUS_EXCEPTION(
        core::common::exception::runtime_error(
          "user data is broken"));
  }
}

}  // namespace framework
}  // namespace server
}  // namespace jubatus
<commit_msg>Add const reference<commit_after>// Jubatus: Online machine learning framework for distributed environment
// Copyright (C) 2013 Preferred Infrastructure and Nippon Telegraph and Telephone Corporation.
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License version 2.1 as published by the Free Software Foundation.
//
// 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., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA

#include "save_load.hpp"

#include <ctime>
#include <fstream>
#include <string>
#include <vector>
#include <glog/logging.h>
#include "jubatus/util/lang/cast.h"

#include "jubatus/core/common/exception.hpp"
#include "jubatus/core/common/big_endian.hpp"
#include "jubatus/core/common/crc32.hpp"
#include "jubatus/core/framework/mixable.hpp"
#include "jubatus/core/framework/stream_writer.hpp"

using jubatus::core::common::write_big_endian;
using jubatus::core::common::read_big_endian;
using std::string;
using jubatus::util::lang::lexical_cast;

namespace jubatus {
namespace server {
namespace framework {

namespace {

const char magic_number[8] = "jubatus";
const uint64_t format_version = 1;

uint32_t jubatus_version_major = -1;
uint32_t jubatus_version_minor = -1;
uint32_t jubatus_version_maintenance = -1;

// TODO(gintenlabo): remove sscanf
void init_versions() {
  if (jubatus_version_major == static_cast<uint32_t>(-1)) {
    int major, minor, maintenance;
    std::sscanf(JUBATUS_VERSION, "%d.%d.%d", &major, &minor, &maintenance);  // NOLINT
    jubatus_version_major = major;
    jubatus_version_minor = minor;
    jubatus_version_maintenance = maintenance;
  }
}

const uint64_t system_data_container_version = 1;

struct system_data_container {
  uint64_t version;
  time_t timestamp;
  std::string type;
  std::string id;
  std::string config;

  system_data_container()
      : version(), timestamp(), type(), id(), config() {
  }

  system_data_container(const server_base& server, const std::string& id_)
      : version(system_data_container_version),
        timestamp(std::time(NULL)),
        type(server.argv().type), id(id_),
        config(server.get_config()) {
  }

  MSGPACK_DEFINE(version, timestamp, type, id, config);
};

uint32_t calc_crc32(const char* header,  // header size is 28 (fixed)
    const char* system_data, uint64_t system_data_size,
    const char* user_data, uint64_t user_data_size) {
  uint32_t crc32 = core::common::calc_crc32(header, 28);
  crc32 = core::common::calc_crc32(&header[32], 16, crc32);
  crc32 = core::common::calc_crc32(system_data, system_data_size, crc32);
  crc32 = core::common::calc_crc32(user_data, user_data_size, crc32);
  return crc32;
}

}  // namespace

void save_server(std::ostream& os,
    const server_base& server, const std::string& id) {
  if (id == "") {
    throw JUBATUS_EXCEPTION(
        core::common::exception::runtime_error("empty id is not allowed"));
  }

  init_versions();

  msgpack::sbuffer system_data_buf;
  msgpack::pack(&system_data_buf, system_data_container(server, id));

  msgpack::sbuffer user_data_buf;
  {
    core::framework::stream_writer<msgpack::sbuffer> st(user_data_buf);
    core::framework::jubatus_packer jp(st);
    core::framework::packer packer(jp);
    packer.pack_array(2);

    uint64_t user_data_version = server.user_data_version();
    packer.pack(user_data_version);
    server.get_driver()->pack(packer);
  }

  char header_buf[48];
  std::memcpy(header_buf, magic_number, 8);
  write_big_endian(format_version, &header_buf[8]);
  write_big_endian(jubatus_version_major, &header_buf[16]);
  write_big_endian(jubatus_version_minor, &header_buf[20]);
  write_big_endian(jubatus_version_maintenance, &header_buf[24]);
  // write_big_endian(crc32, &header_buf[28]);  // skipped
  write_big_endian(static_cast<uint64_t>(system_data_buf.size()),
                   &header_buf[32]);
  write_big_endian(static_cast<uint64_t>(user_data_buf.size()),
                   &header_buf[40]);

  uint32_t crc32 = calc_crc32(header_buf,
      system_data_buf.data(), system_data_buf.size(),
      user_data_buf.data(), user_data_buf.size());
  write_big_endian(crc32, &header_buf[28]);

  os.write(header_buf, 48);
  os.write(system_data_buf.data(), system_data_buf.size());
  os.write(user_data_buf.data(), user_data_buf.size());
}

void load_server(std::istream& is,
    server_base& server, const std::string& id) {
  init_versions();

  char header_buf[48];
  is.read(header_buf, 48);
  if (std::memcmp(header_buf, magic_number, 8) != 0) {
    throw JUBATUS_EXCEPTION(
        core::common::exception::runtime_error("invalid file format"));
  }
  uint64_t format_version_read = read_big_endian<uint64_t>(&header_buf[8]);
  if (format_version_read != format_version) {
    throw JUBATUS_EXCEPTION(
        core::common::exception::runtime_error(
          "invalid format version: " +
          lexical_cast<string>(format_version_read) +
          ", expected " +
          lexical_cast<string>(format_version)));
  }
  uint32_t jubatus_major_read = read_big_endian<uint32_t>(&header_buf[16]);
  uint32_t jubatus_minor_read = read_big_endian<uint32_t>(&header_buf[20]);
  uint32_t jubatus_maintenance_read =
      read_big_endian<uint32_t>(&header_buf[24]);
  if (jubatus_major_read != jubatus_version_major ||
      jubatus_minor_read != jubatus_version_minor ||
      jubatus_maintenance_read != jubatus_version_maintenance) {
    throw JUBATUS_EXCEPTION(
        core::common::exception::runtime_error(
          "jubatus version mismatched: current version: " JUBATUS_VERSION
          ", saved version: " +
          lexical_cast<std::string>(jubatus_major_read) + "." +
          lexical_cast<std::string>(jubatus_minor_read) + "." +
          lexical_cast<std::string>(jubatus_maintenance_read)));
  }
  uint32_t crc32_expected = read_big_endian<uint32_t>(&header_buf[28]);
  uint64_t system_data_size = read_big_endian<uint64_t>(&header_buf[32]);
  uint64_t user_data_size = read_big_endian<uint64_t>(&header_buf[40]);

  std::vector<char> system_data_buf(system_data_size);
  is.read(&system_data_buf[0], system_data_size);

  std::vector<char> user_data_buf(user_data_size);
  is.read(&user_data_buf[0], user_data_size);

  uint32_t crc32_actual = calc_crc32(header_buf,
      &system_data_buf[0], system_data_size,
      &user_data_buf[0], user_data_size);
  if (crc32_actual != crc32_expected) {
    std::ostringstream ss;
    ss << "invalid crc32 checksum: " << std::hex << crc32_actual;
    ss << ", read " << crc32_expected;
    throw JUBATUS_EXCEPTION(
        core::common::exception::runtime_error(ss.str()));
  }

  system_data_container system_data_actual;
  try {
    msgpack::unpacked unpacked;
    msgpack::unpack(&unpacked, &system_data_buf[0], system_data_size);
    unpacked.get().convert(&system_data_actual);
  } catch (const msgpack::type_error&) {
    throw JUBATUS_EXCEPTION(
        core::common::exception::runtime_error(
          "system data is broken"));
  }
  system_data_container system_data_expected(server, id);
  if (system_data_actual.version != system_data_expected.version) {
    throw JUBATUS_EXCEPTION(
        core::common::exception::runtime_error(
          "invalid system data version: saved version: " +
          lexical_cast<string>(system_data_actual.version) +
          ", expected " +
          lexical_cast<string>(system_data_expected.version)));
  }
  if (system_data_actual.type != system_data_expected.type) {
    throw JUBATUS_EXCEPTION(
        core::common::exception::runtime_error(
          "server type mismatched: " + system_data_actual.type +
          ", expected " + system_data_expected.type));
  }
  if (system_data_actual.config != system_data_expected.config) {
    throw JUBATUS_EXCEPTION(
        core::common::exception::runtime_error(
          "server config mismatched" + system_data_actual.config +
          ", expected " + system_data_expected.config));
  }

  try {
    msgpack::unpacked unpacked;
    msgpack::unpack(&unpacked, &user_data_buf[0], user_data_size);

    std::vector<msgpack::object> objs;
    unpacked.get().convert(&objs);
    if (objs.size() != 2) {
      throw JUBATUS_EXCEPTION(
          core::common::exception::runtime_error("invalid user container"));
    }

    uint64_t user_data_version_expected = server.user_data_version();
    uint64_t user_data_version_actual;
    objs[0].convert(&user_data_version_actual);
    if (user_data_version_actual != user_data_version_expected) {
      throw JUBATUS_EXCEPTION(
          core::common::exception::runtime_error(
            "user data version mismatched: " +
            lexical_cast<string>(user_data_version_actual) +
            ", expected " +
            lexical_cast<string>(user_data_version_expected)));
    }

    server.get_driver()->unpack(objs[1]);
  } catch (const msgpack::type_error&) {
    throw JUBATUS_EXCEPTION(
        core::common::exception::runtime_error(
          "user data is broken"));
  }
}

}  // namespace framework
}  // namespace server
}  // namespace jubatus
<|endoftext|>


<commit_before>/*
 * This is part of the FL library, a C++ Bayesian filtering library
 * (https://github.com/filtering-library)
 *
 * Copyright (c) 2014 Jan Issac (jan.issac@gmail.com)
 * Copyright (c) 2014 Manuel Wuthrich (manuel.wuthrich@gmail.com)
 *
 * Max-Planck Institute for Intelligent Systems, AMD Lab
 * University of Southern California, CLMC Lab
 *
 * This Source Code Form is subject to the terms of the MIT License (MIT).
 * A copy of the license can be found in the LICENSE file distributed with this
 * source code.
 */

/**
 * \file process_density.hpp
 * \date June 2015
 * \author Jan Issac (jan.issac@gmail.com)
 * \author Manuel Wuthrich (manuel.wuthrich@gmail.com)
 */

#ifndef FL__MODEL__PROCESS__STATE_TRANSITION_DENSITY_HPP
#define FL__MODEL__PROCESS__STATE_TRANSITION_DENSITY_HPP

#include <fl/util/types.hpp>
#include <fl/util/traits.hpp>

namespace fl
{

template <
    typename State,
    typename Input,
    int BatchSize = Eigen::Dynamic
>
class StateTransitionDensity
{
public:
    typedef Eigen::Array<State, BatchSize, 1 > StateArray;
    typedef Eigen::Array<Input, BatchSize, 1 > InputArray;
    typedef Eigen::Array<FloatingPoint, BatchSize, 1 > ValueArray;

public:
    /// \todo should add the unnormalized log probability interface

    virtual FloatingPoint log_probability(const State& state,
                                          const State& cond_state,
                                          const Input& cond_input,
                                          FloatingPoint dt) const = 0;

    /**
     * \return Dimension of the state variable $\f$x_t\f$
     */
    virtual int state_dimension() const = 0;

    /**
     * \return Dimension of the input \f$u_t\f$
     */
    virtual int input_dimension() const = 0;

    virtual FloatingPoint probability(const State& state,
                                      const State& cond_state,
                                      const Input& cond_input,
                                      FloatingPoint dt) const
    {
        return std::exp(log_probability(state, cond_state, cond_input, dt));
    }

    virtual ValueArray log_probabilities(const StateArray& states,
                                         const StateArray& cond_states,
                                         const InputArray& cond_inputs,
                                         FloatingPoint dt) const
    {
        assert(states.size() == cond_inputs.size());

        auto probs = ValueArray(states.size());

        for (int i = 0; i < states.size(); ++i)
        {
            probs[i] = log_probability(states[i],
                                       cond_states[i],
                                       cond_inputs[i],
                                       dt);
        }

        return probs;
    }

    virtual ValueArray probabilities(const StateArray& states,
                                     const StateArray& cond_states,
                                     const InputArray& cond_inputs,
                                     FloatingPoint dt)
    {
        return log_probabilities(states, cond_inputs, cond_inputs, dt).exp();
    }
};

}

#endif
<commit_msg>fixed log_probabilities<commit_after>/*
 * This is part of the FL library, a C++ Bayesian filtering library
 * (https://github.com/filtering-library)
 *
 * Copyright (c) 2014 Jan Issac (jan.issac@gmail.com)
 * Copyright (c) 2014 Manuel Wuthrich (manuel.wuthrich@gmail.com)
 *
 * Max-Planck Institute for Intelligent Systems, AMD Lab
 * University of Southern California, CLMC Lab
 *
 * This Source Code Form is subject to the terms of the MIT License (MIT).
 * A copy of the license can be found in the LICENSE file distributed with this
 * source code.
 */

/**
 * \file process_density.hpp
 * \date June 2015
 * \author Jan Issac (jan.issac@gmail.com)
 * \author Manuel Wuthrich (manuel.wuthrich@gmail.com)
 */

#ifndef FL__MODEL__PROCESS__STATE_TRANSITION_DENSITY_HPP
#define FL__MODEL__PROCESS__STATE_TRANSITION_DENSITY_HPP

#include <fl/util/types.hpp>
#include <fl/util/traits.hpp>

namespace fl
{

template <
    typename State,
    typename Input,
    int BatchSize = Eigen::Dynamic
>
class StateTransitionDensity
{
public:
    typedef Eigen::Array<State, BatchSize, 1 > StateArray;
    typedef Eigen::Array<Input, BatchSize, 1 > InputArray;
    typedef Eigen::Array<FloatingPoint, BatchSize, 1 > ValueArray;

public:
    /// \todo should add the unnormalized log probability interface

    virtual FloatingPoint log_probability(const State& state,
                                          const State& cond_state,
                                          const Input& cond_input,
                                          FloatingPoint dt) const = 0;

    /**
     * \return Dimension of the state variable $\f$x_t\f$
     */
    virtual int state_dimension() const = 0;

    /**
     * \return Dimension of the input \f$u_t\f$
     */
    virtual int input_dimension() const = 0;

    virtual FloatingPoint probability(const State& state,
                                      const State& cond_state,
                                      const Input& cond_input,
                                      FloatingPoint dt) const
    {
        return std::exp(log_probability(state, cond_state, cond_input, dt));
    }

    virtual ValueArray log_probabilities(const StateArray& states,
                                         const StateArray& cond_states,
                                         const InputArray& cond_inputs,
                                         FloatingPoint dt) const
    {
        assert(states.size() == cond_inputs.size());

        auto probs = ValueArray(states.size());

        for (int i = 0; i < states.size(); ++i)
        {
            probs[i] = log_probability(states[i],
                                       cond_states[i],
                                       cond_inputs[i],
                                       dt);
        }

        return probs;
    }

    virtual ValueArray probabilities(const StateArray& states,
                                     const StateArray& cond_states,
                                     const InputArray& cond_inputs,
                                     FloatingPoint dt)
    {
        return log_probabilities(states, cond_states, cond_inputs, dt).exp();
    }
};

}

#endif
<|endoftext|>