<commit_before>#ifndef RECTANGLE_HPP
#define RECTANGLE_HPP

#include "util/coordinate_calculation.hpp"

#include <boost/assert.hpp>

#include "osrm/coordinate.hpp"

#include <algorithm>
#include <iomanip>
#include <limits>
#include <utility>

#include <cstdint>

namespace osrm
{
namespace util
{

// TODO: Make template type, add tests
struct RectangleInt2D
{
    RectangleInt2D()
        : min_lon{std::numeric_limits<std::int32_t>::max()},
          max_lon{std::numeric_limits<std::int32_t>::min()},
          min_lat{std::numeric_limits<std::int32_t>::max()},
          max_lat{std::numeric_limits<std::int32_t>::min()}
    {
    }

    RectangleInt2D(FixedLongitude min_lon_,
                   FixedLongitude max_lon_,
                   FixedLatitude min_lat_,
                   FixedLatitude max_lat_)
        : min_lon(min_lon_), max_lon(max_lon_), min_lat(min_lat_), max_lat(max_lat_)
    {
    }

    RectangleInt2D(FloatLongitude min_lon_,
                   FloatLongitude max_lon_,
                   FloatLatitude min_lat_,
                   FloatLatitude max_lat_)
        : min_lon(toFixed(min_lon_)), max_lon(toFixed(max_lon_)), min_lat(toFixed(min_lat_)),
          max_lat(toFixed(max_lat_))
    {
    }

    FixedLongitude min_lon, max_lon;
    FixedLatitude min_lat, max_lat;

    void MergeBoundingBoxes(const RectangleInt2D &other)
    {
        min_lon = std::min(min_lon, other.min_lon);
        max_lon = std::max(max_lon, other.max_lon);
        min_lat = std::min(min_lat, other.min_lat);
        max_lat = std::max(max_lat, other.max_lat);
        BOOST_ASSERT(min_lon != FixedLongitude{std::numeric_limits<std::int32_t>::min()});
        BOOST_ASSERT(min_lat != FixedLatitude{std::numeric_limits<std::int32_t>::min()});
        BOOST_ASSERT(max_lon != FixedLongitude{std::numeric_limits<std::int32_t>::min()});
        BOOST_ASSERT(max_lat != FixedLatitude{std::numeric_limits<std::int32_t>::min()});
    }

    Coordinate Centroid() const
    {
        Coordinate centroid;
        // The coordinates of the midpoints are given by:
        // x = (x1 + x2) /2 and y = (y1 + y2) /2.
        centroid.lon = (min_lon + max_lon) / FixedLongitude{2};
        centroid.lat = (min_lat + max_lat) / FixedLatitude{2};
        return centroid;
    }

    bool Intersects(const RectangleInt2D &other) const
    {
        // Standard box intersection test - check if boxes *don't* overlap,
        // and return the negative of that
        return !(max_lon < other.min_lon || min_lon > other.max_lon || max_lat < other.min_lat ||
                 min_lat > other.max_lat);
    }

    // This code assumes that we are operating in euclidean space!
    // That means if you just put unprojected lat/lon in here you will
    // get invalid results.
    std::uint64_t GetMinSquaredDist(const Coordinate location) const
    {
        const bool is_contained = Contains(location);
        if (is_contained)
        {
            return 0.0f;
        }

        enum Direction
        {
            INVALID = 0,
            NORTH = 1,
            SOUTH = 2,
            EAST = 4,
            NORTH_EAST = 5,
            SOUTH_EAST = 6,
            WEST = 8,
            NORTH_WEST = 9,
            SOUTH_WEST = 10
        };

        Direction d = INVALID;
        if (location.lat > max_lat)
            d = (Direction)(d | NORTH);
        else if (location.lat < min_lat)
            d = (Direction)(d | SOUTH);
        if (location.lon > max_lon)
            d = (Direction)(d | EAST);
        else if (location.lon < min_lon)
            d = (Direction)(d | WEST);

        BOOST_ASSERT(d != INVALID);

        std::uint64_t min_dist = std::numeric_limits<std::uint64_t>::max();
        switch (d)
        {
        case NORTH:
            min_dist = coordinate_calculation::squaredEuclideanDistance(
                location, Coordinate(location.lon, max_lat));
            break;
        case SOUTH:
            min_dist = coordinate_calculation::squaredEuclideanDistance(
                location, Coordinate(location.lon, min_lat));
            break;
        case WEST:
            min_dist = coordinate_calculation::squaredEuclideanDistance(
                location, Coordinate(min_lon, location.lat));
            break;
        case EAST:
            min_dist = coordinate_calculation::squaredEuclideanDistance(
                location, Coordinate(max_lon, location.lat));
            break;
        case NORTH_EAST:
            min_dist = coordinate_calculation::squaredEuclideanDistance(
                location, Coordinate(max_lon, max_lat));
            break;
        case NORTH_WEST:
            min_dist = coordinate_calculation::squaredEuclideanDistance(
                location, Coordinate(min_lon, max_lat));
            break;
        case SOUTH_EAST:
            min_dist = coordinate_calculation::squaredEuclideanDistance(
                location, Coordinate(max_lon, min_lat));
            break;
        case SOUTH_WEST:
            min_dist = coordinate_calculation::squaredEuclideanDistance(
                location, Coordinate(min_lon, min_lat));
            break;
        default:
            break;
        }

        BOOST_ASSERT(min_dist < std::numeric_limits<std::uint64_t>::max());

        return min_dist;
    }

    bool Contains(const Coordinate location) const
    {
        const bool lons_contained = (location.lon >= min_lon) && (location.lon <= max_lon);
        const bool lats_contained = (location.lat >= min_lat) && (location.lat <= max_lat);
        return lons_contained && lats_contained;
    }

    bool IsValid() const
    {
        return min_lon != FixedLongitude{std::numeric_limits<std::int32_t>::max()} &&
               max_lon != FixedLongitude{std::numeric_limits<std::int32_t>::min()} &&
               min_lat != FixedLatitude{std::numeric_limits<std::int32_t>::max()} &&
               max_lat != FixedLatitude{std::numeric_limits<std::int32_t>::min()};
    }

    friend std::ostream &operator<<(std::ostream &out, const RectangleInt2D &rect);
};
inline std::ostream &operator<<(std::ostream &out, const RectangleInt2D &rect)
{
    out << std::setprecision(12) << "{\"type\":\"Polygon\",\"coordinates\": [["
        << toFloating(rect.min_lon) << "," << toFloating(rect.min_lat) << "],["
        << toFloating(rect.min_lon) << "," << toFloating(rect.max_lat) << "],["
        << toFloating(rect.max_lon) << "," << toFloating(rect.max_lat) << "],["
        << toFloating(rect.max_lon) << "," << toFloating(rect.min_lat) << "],["
        << toFloating(rect.min_lon) << "," << toFloating(rect.min_lat) << "]] }";
    return out;
}
}
}

#endif
<commit_msg>Remove debug printing code from Rectangle<commit_after>#ifndef OSRM_UTIL_RECTANGLE_HPP
#define OSRM_UTIL_RECTANGLE_HPP

#include "util/coordinate_calculation.hpp"
#include "util/coordinate.hpp"

#include <boost/assert.hpp>

#include <limits>
#include <utility>

#include <cstdint>

namespace osrm
{
namespace util
{

struct RectangleInt2D
{
    RectangleInt2D()
        : min_lon{std::numeric_limits<std::int32_t>::max()},
          max_lon{std::numeric_limits<std::int32_t>::min()},
          min_lat{std::numeric_limits<std::int32_t>::max()},
          max_lat{std::numeric_limits<std::int32_t>::min()}
    {
    }

    RectangleInt2D(FixedLongitude min_lon_,
                   FixedLongitude max_lon_,
                   FixedLatitude min_lat_,
                   FixedLatitude max_lat_)
        : min_lon(min_lon_), max_lon(max_lon_), min_lat(min_lat_), max_lat(max_lat_)
    {
    }

    RectangleInt2D(FloatLongitude min_lon_,
                   FloatLongitude max_lon_,
                   FloatLatitude min_lat_,
                   FloatLatitude max_lat_)
        : min_lon(toFixed(min_lon_)), max_lon(toFixed(max_lon_)), min_lat(toFixed(min_lat_)),
          max_lat(toFixed(max_lat_))
    {
    }

    FixedLongitude min_lon, max_lon;
    FixedLatitude min_lat, max_lat;

    void MergeBoundingBoxes(const RectangleInt2D &other)
    {
        min_lon = std::min(min_lon, other.min_lon);
        max_lon = std::max(max_lon, other.max_lon);
        min_lat = std::min(min_lat, other.min_lat);
        max_lat = std::max(max_lat, other.max_lat);
        BOOST_ASSERT(min_lon != FixedLongitude{std::numeric_limits<std::int32_t>::min()});
        BOOST_ASSERT(min_lat != FixedLatitude{std::numeric_limits<std::int32_t>::min()});
        BOOST_ASSERT(max_lon != FixedLongitude{std::numeric_limits<std::int32_t>::min()});
        BOOST_ASSERT(max_lat != FixedLatitude{std::numeric_limits<std::int32_t>::min()});
    }

    Coordinate Centroid() const
    {
        Coordinate centroid;
        // The coordinates of the midpoints are given by:
        // x = (x1 + x2) /2 and y = (y1 + y2) /2.
        centroid.lon = (min_lon + max_lon) / FixedLongitude{2};
        centroid.lat = (min_lat + max_lat) / FixedLatitude{2};
        return centroid;
    }

    bool Intersects(const RectangleInt2D &other) const
    {
        // Standard box intersection test - check if boxes *don't* overlap,
        // and return the negative of that
        return !(max_lon < other.min_lon || min_lon > other.max_lon || max_lat < other.min_lat ||
                 min_lat > other.max_lat);
    }

    // This code assumes that we are operating in euclidean space!
    // That means if you just put unprojected lat/lon in here you will
    // get invalid results.
    std::uint64_t GetMinSquaredDist(const Coordinate location) const
    {
        const bool is_contained = Contains(location);
        if (is_contained)
        {
            return 0.0f;
        }

        enum Direction
        {
            INVALID = 0,
            NORTH = 1,
            SOUTH = 2,
            EAST = 4,
            NORTH_EAST = 5,
            SOUTH_EAST = 6,
            WEST = 8,
            NORTH_WEST = 9,
            SOUTH_WEST = 10
        };

        Direction d = INVALID;
        if (location.lat > max_lat)
            d = (Direction)(d | NORTH);
        else if (location.lat < min_lat)
            d = (Direction)(d | SOUTH);
        if (location.lon > max_lon)
            d = (Direction)(d | EAST);
        else if (location.lon < min_lon)
            d = (Direction)(d | WEST);

        BOOST_ASSERT(d != INVALID);

        std::uint64_t min_dist = std::numeric_limits<std::uint64_t>::max();
        switch (d)
        {
        case NORTH:
            min_dist = coordinate_calculation::squaredEuclideanDistance(
                location, Coordinate(location.lon, max_lat));
            break;
        case SOUTH:
            min_dist = coordinate_calculation::squaredEuclideanDistance(
                location, Coordinate(location.lon, min_lat));
            break;
        case WEST:
            min_dist = coordinate_calculation::squaredEuclideanDistance(
                location, Coordinate(min_lon, location.lat));
            break;
        case EAST:
            min_dist = coordinate_calculation::squaredEuclideanDistance(
                location, Coordinate(max_lon, location.lat));
            break;
        case NORTH_EAST:
            min_dist = coordinate_calculation::squaredEuclideanDistance(
                location, Coordinate(max_lon, max_lat));
            break;
        case NORTH_WEST:
            min_dist = coordinate_calculation::squaredEuclideanDistance(
                location, Coordinate(min_lon, max_lat));
            break;
        case SOUTH_EAST:
            min_dist = coordinate_calculation::squaredEuclideanDistance(
                location, Coordinate(max_lon, min_lat));
            break;
        case SOUTH_WEST:
            min_dist = coordinate_calculation::squaredEuclideanDistance(
                location, Coordinate(min_lon, min_lat));
            break;
        default:
            break;
        }

        BOOST_ASSERT(min_dist < std::numeric_limits<std::uint64_t>::max());

        return min_dist;
    }

    bool Contains(const Coordinate location) const
    {
        const bool lons_contained = (location.lon >= min_lon) && (location.lon <= max_lon);
        const bool lats_contained = (location.lat >= min_lat) && (location.lat <= max_lat);
        return lons_contained && lats_contained;
    }

    bool IsValid() const
    {
        return min_lon != FixedLongitude{std::numeric_limits<std::int32_t>::max()} &&
               max_lon != FixedLongitude{std::numeric_limits<std::int32_t>::min()} &&
               min_lat != FixedLatitude{std::numeric_limits<std::int32_t>::max()} &&
               max_lat != FixedLatitude{std::numeric_limits<std::int32_t>::min()};
    }
};
}
}

#endif
<|endoftext|>


<commit_before>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2014 Max-Planck-Institute for Intelligent Systems,
 *                     University of Southern California
 *    Jan Issac (jan.issac@gmail.com)
 *    Manuel Wuthrich (manuel.wuthrich@gmail.com)
 *
 *  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 Willow Garage, Inc. 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.
 *
 */

/**
 * @date 2014
 * @author Jan Issac (jan.issac@gmail.com)
 * @author Manuel Wuthrich (manuel.wuthrich@gmail.com)
 * Max-Planck-Institute for Intelligent Systems, University of Southern California
 */

#include <gtest/gtest.h>

#include <Eigen/Dense>

#include <cmath>
#include <iostream>

#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>

#include <fast_filtering/models/process_models/linear_process_model.hpp>
#include <fast_filtering/models/observation_models/linear_observation_model.hpp>
#include <fast_filtering/filters/deterministic/factorized_unscented_kalman_filter.hpp>

TEST(FUKFAndLinearModels, init_fixedsize_predict)
{
    typedef double Scalar;
    typedef Eigen::Matrix<Scalar, 10, 1> State_a;
    typedef Eigen::Matrix<Scalar, 1, 1> State_b;
    typedef Eigen::Matrix<Scalar, 20, 1> Observation;

    typedef ff::LinearGaussianProcessModel<State_a> ProcessModel_a;
    typedef ff::LinearGaussianProcessModel<State_b> ProcessModel_b;
    typedef ff::FactorizedLinearGaussianObservationModel<
                    Observation,
                    State_a,
                    State_b> ObservationModel;

    typedef ff::FactorizedUnscentedKalmanFilter<ProcessModel_a,
                                                ProcessModel_b,
                                                ObservationModel> Filter;

    ProcessModel_a::Operator Q_a = ProcessModel_a::Operator::Identity();
    ProcessModel_b::Operator Q_b = ProcessModel_b::Operator::Identity();
    ObservationModel::Operator R = ObservationModel::Operator::Identity();

    Filter::CohesiveStateProcessModelPtr process_model =
            boost::make_shared<ProcessModel_a>(Q_a);
    Filter::FactorizedStateProcessModelPtr process_model_b =
            boost::make_shared<ProcessModel_b>(Q_b);
    Filter::ObservationModelPtr observation_model =
            boost::make_shared<ObservationModel>(R);

    Filter filter(process_model, process_model_b, observation_model);

    Filter::StateDistribution state_dist;
    state_dist.initialize(State_a::Zero(),
                          1,
                          State_b::Zero(),
                          1.0,
                          1.0);

    EXPECT_TRUE(state_dist.mean_a.isZero());
    EXPECT_TRUE(state_dist.cov_aa.isIdentity());
    EXPECT_TRUE(state_dist.joint_partitions[0].mean_b.isZero());
    EXPECT_TRUE(state_dist.joint_partitions[0].cov_bb.isIdentity());
    filter.Predict(state_dist, 1.0, state_dist);
    EXPECT_TRUE(state_dist.mean_a.isZero());
    EXPECT_TRUE(state_dist.cov_aa.isApprox(2. * Q_a));
    EXPECT_TRUE(state_dist.joint_partitions[0].mean_b.isZero());
    EXPECT_TRUE(state_dist.joint_partitions[0].cov_bb.isApprox(2. * Q_b));
}

TEST(FUKFAndLinearModels, init_dynamicsize_predict)
{
    const size_t dim_state_a = 10;
    const size_t dim_state_b = 1;
    const size_t dim_observation = 20;

    typedef double Scalar;
    typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1> State_a;
    typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1> State_b;
    typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1> Observation;

    typedef ff::LinearGaussianProcessModel<State_a> ProcessModel_a;
    typedef ff::LinearGaussianProcessModel<State_b> ProcessModel_b;
    typedef ff::FactorizedLinearGaussianObservationModel<
                    Observation,
                    State_a,
                    State_b> ObservationModel;

    typedef ff::FactorizedUnscentedKalmanFilter<ProcessModel_a,
                                                ProcessModel_b,
                                                ObservationModel> Filter;

    ProcessModel_a::Operator Q_a =
            ProcessModel_a::Operator::Identity(dim_state_a,
                                               dim_state_a);
    ProcessModel_b::Operator Q_b =
            ProcessModel_b::Operator::Identity(dim_state_b,
                                               dim_state_b);
    ObservationModel::Operator R =
            ObservationModel::Operator::Identity(dim_observation,
                                                 dim_observation);

    Filter::CohesiveStateProcessModelPtr process_model_a =
            boost::make_shared<ProcessModel_a>(Q_a, dim_state_a);
    Filter::FactorizedStateProcessModelPtr process_model_b =
            boost::make_shared<ProcessModel_b>(Q_b, dim_state_b);
    Filter::ObservationModelPtr observation_model =
            boost::make_shared<ObservationModel>(R,
                                                 dim_observation,
                                                 dim_state_a,
                                                 dim_state_b);

    Filter filter(process_model_a, process_model_b, observation_model);

    Filter::StateDistribution state_dist;
    state_dist.initialize(State_a::Zero(dim_state_a, 1),
                          1,
                          State_b::Zero(dim_state_b, 1),
                          1.0,
                          1.0);

    EXPECT_TRUE(state_dist.mean_a.isZero());
    EXPECT_TRUE(state_dist.cov_aa.isIdentity());
    EXPECT_TRUE(state_dist.joint_partitions[0].mean_b.isZero());
    EXPECT_TRUE(state_dist.joint_partitions[0].cov_bb.isIdentity());
    filter.Predict(state_dist, 1.0, state_dist);
    EXPECT_TRUE(state_dist.mean_a.isZero());
    EXPECT_TRUE(state_dist.cov_aa.isApprox(2. * Q_a));
    EXPECT_TRUE(state_dist.joint_partitions[0].mean_b.isZero());
    EXPECT_TRUE(state_dist.joint_partitions[0].cov_bb.isApprox(2. * Q_b));
}

TEST(FUKFAndLinearModels, fixedsize_predict_update)
{
    typedef double Scalar;
    typedef Eigen::Matrix<Scalar, 10, 1> State_a;
    typedef Eigen::Matrix<Scalar, 1, 1> State_b;
    typedef Eigen::Matrix<Scalar, 20, 1> Observation;

    typedef ff::LinearGaussianProcessModel<State_a> ProcessModel_a;
    typedef ff::LinearGaussianProcessModel<State_b> ProcessModel_b;
    typedef ff::FactorizedLinearGaussianObservationModel<
                    Observation,
                    State_a,
                    State_b> ObservationModel;

    typedef ff::FactorizedUnscentedKalmanFilter<ProcessModel_a,
                                                ProcessModel_b,
                                                ObservationModel> Filter;

    ProcessModel_a::Operator Q_a =
            ProcessModel_a::Operator::Random()*1.5;
    ProcessModel_b::Operator Q_b =
            ProcessModel_b::Operator::Random()*1.5;

    ProcessModel_a::DynamicsMatrix A_a =
            ProcessModel_a::DynamicsMatrix::Random();
    ProcessModel_b::DynamicsMatrix A_b =
            ProcessModel_b::DynamicsMatrix::Random();

    ObservationModel::Operator R =
            ObservationModel::Operator::Random();

    ObservationModel::SensorMatrix_a H_a =
            ObservationModel::SensorMatrix_a::Random();
    ObservationModel::SensorMatrix_b H_b =
            ObservationModel::SensorMatrix_b::Random();

    Q_a *= Q_a.transpose();
    Q_b *= Q_b.transpose();
    R *= R.transpose();

    Filter::CohesiveStateProcessModelPtr process_model_a =
            boost::make_shared<ProcessModel_a>(Q_a);
    Filter::FactorizedStateProcessModelPtr process_model_b =
            boost::make_shared<ProcessModel_b>(Q_b);
    Filter::ObservationModelPtr observation_model =
            boost::make_shared<ObservationModel>(R);

    process_model_a->A(A_a);
    process_model_b->A(A_b);
    observation_model->H_a(H_a);
    observation_model->H_b(H_b);

    Filter filter(process_model_a, process_model_b, observation_model);

    Filter::StateDistribution state_dist;
    state_dist.initialize(State_a::Zero(),
                          1,
                          State_b::Zero(),
                          1.0,
                          1.0);

    EXPECT_TRUE(state_dist.cov_aa.ldlt().isPositive());
    EXPECT_TRUE(state_dist.joint_partitions[0].cov_bb.ldlt().isPositive());

    for (size_t i = 0; i < 20000; ++i)
    {
        filter.Predict(state_dist, 1.0, state_dist);

        EXPECT_TRUE(state_dist.cov_aa.ldlt().isPositive());
        EXPECT_TRUE(state_dist.joint_partitions[0].cov_bb.ldlt().isPositive());

        Observation y = Observation::Random();
        filter.Update(state_dist, y, state_dist);

        EXPECT_TRUE(state_dist.cov_aa.ldlt().isPositive());
        EXPECT_TRUE(state_dist.joint_partitions[0].cov_bb.ldlt().isPositive());
    }
}

TEST(FUKFAndLinearModels, dynamicsize_predict_update)
{
    const size_t dim_state_a = 10;
    const size_t dim_state_b = 1;
    const size_t dim_observation = 20;

    typedef double Scalar;
    typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1> State_a;
    typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1> State_b;
    typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1> Observation;

    typedef ff::LinearGaussianProcessModel<State_a> ProcessModel_a;
    typedef ff::LinearGaussianProcessModel<State_b> ProcessModel_b;
    typedef ff::FactorizedLinearGaussianObservationModel<
                    Observation,
                    State_a,
                    State_b> ObservationModel;

    typedef ff::FactorizedUnscentedKalmanFilter<ProcessModel_a,
                                                ProcessModel_b,
                                                ObservationModel> Filter;

    ProcessModel_a::Operator Q_a =
            ProcessModel_a::Operator::Random(dim_state_a, dim_state_a) * 1.5;
    ProcessModel_b::Operator Q_b =
            ProcessModel_b::Operator::Random(dim_state_b, dim_state_b) * 1.5;

    ProcessModel_a::DynamicsMatrix A_a =
            ProcessModel_a::DynamicsMatrix::Random(dim_state_a,
                                                   dim_state_a);
    ProcessModel_b::DynamicsMatrix A_b =
            ProcessModel_b::DynamicsMatrix::Random(dim_state_b,
                                                   dim_state_b);

    ObservationModel::Operator R =
            ObservationModel::Operator::Random(dim_observation,
                                               dim_observation);

    ObservationModel::SensorMatrix_a H_a =
            ObservationModel::SensorMatrix_a::Random(dim_observation,
                                                     dim_state_a);
    ObservationModel::SensorMatrix_b H_b =
            ObservationModel::SensorMatrix_b::Random(dim_observation,
                                                     dim_state_b);

    Filter::CohesiveStateProcessModelPtr process_model_a =
            boost::make_shared<ProcessModel_a>(Q_a, dim_state_a);
    Filter::FactorizedStateProcessModelPtr process_model_b =
            boost::make_shared<ProcessModel_b>(Q_b, dim_state_b);
    Filter::ObservationModelPtr observation_model =
            boost::make_shared<ObservationModel>(R,
                                                 dim_observation,
                                                 dim_state_a,
                                                 dim_state_b);
    Q_a *= Q_a.transpose();
    Q_b *= Q_b.transpose();
    R *= R.transpose();

    process_model_a->A(A_a);
    process_model_b->A(A_b);
    observation_model->H_a(H_a);
    observation_model->H_b(H_b);

    Filter filter(process_model_a, process_model_b, observation_model);

    Filter::StateDistribution state_dist;
    state_dist.initialize(State_a::Zero(dim_state_a, 1),
                          1,
                          State_b::Zero(dim_state_b, 1),
                          1.0,
                          1.0);

    EXPECT_TRUE(state_dist.cov_aa.ldlt().isPositive());
    EXPECT_TRUE(state_dist.joint_partitions[0].cov_bb.ldlt().isPositive());

    for (size_t i = 0; i < 20000; ++i)
    {
        filter.Predict(state_dist, 1.0, state_dist);

        EXPECT_TRUE(state_dist.cov_aa.ldlt().isPositive());
        EXPECT_TRUE(state_dist.joint_partitions[0].cov_bb.ldlt().isPositive());

        Observation y = Observation::Random(dim_observation, 1);
        filter.Update(state_dist, y, state_dist);

        EXPECT_TRUE(state_dist.cov_aa.ldlt().isPositive());
        EXPECT_TRUE(state_dist.joint_partitions[0].cov_bb.ldlt().isPositive());
    }
}

<commit_msg>Updated tests on FUKF with linear models<commit_after>/*
 * Software License Agreement (BSD License)
 *
 *  Copyright (c) 2014 Max-Planck-Institute for Intelligent Systems,
 *                     University of Southern California
 *    Jan Issac (jan.issac@gmail.com)
 *    Manuel Wuthrich (manuel.wuthrich@gmail.com)
 *
 *  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 Willow Garage, Inc. 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.
 *
 */

/**
 * @date 2014
 * @author Jan Issac (jan.issac@gmail.com)
 * @author Manuel Wuthrich (manuel.wuthrich@gmail.com)
 * Max-Planck-Institute for Intelligent Systems, University of Southern California
 */

#include <gtest/gtest.h>

#include <Eigen/Dense>

#include <cmath>
#include <iostream>

#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>

#include <fast_filtering/models/process_models/linear_process_model.hpp>
#include <fast_filtering/models/observation_models/linear_observation_model.hpp>
#include <fast_filtering/filters/deterministic/factorized_unscented_kalman_filter.hpp>

TEST(FUKFAndLinearModels, init_fixedsize_predict)
{
    typedef double Scalar;
    typedef Eigen::Matrix<Scalar, 10, 1> State_a;
    typedef Eigen::Matrix<Scalar, 1, 1> State_b;
    typedef Eigen::Matrix<Scalar, 20, 1> Observation;

    typedef ff::LinearGaussianProcessModel<State_a> ProcessModel_a;
    typedef ff::LinearGaussianProcessModel<State_b> ProcessModel_b;
    typedef ff::FactorizedLinearGaussianObservationModel<
                    Observation,
                    State_a,
                    State_b> ObservationModel;

    typedef ff::FactorizedUnscentedKalmanFilter<ProcessModel_a,
                                                ProcessModel_b,
                                                ObservationModel> Filter;

    ProcessModel_a::Operator Q_a = ProcessModel_a::Operator::Identity();
    ProcessModel_b::Operator Q_b = ProcessModel_b::Operator::Identity();
    ObservationModel::Operator R = ObservationModel::Operator::Identity();

    Filter::CohesiveStateProcessModelPtr process_model =
            boost::make_shared<ProcessModel_a>(Q_a);
    Filter::FactorizedStateProcessModelPtr process_model_b =
            boost::make_shared<ProcessModel_b>(Q_b);
    Filter::ObservationModelPtr observation_model =
            boost::make_shared<ObservationModel>(R);

    Filter filter(process_model, process_model_b, observation_model);

    Filter::StateDistribution state_dist;
    state_dist.initialize(State_a::Zero(),
                          1,
                          State_b::Zero(),
                          1.0,
                          1.0);

    EXPECT_TRUE(state_dist.mean_a.isZero());
    EXPECT_TRUE(state_dist.cov_aa.isIdentity());
    EXPECT_TRUE(state_dist.joint_partitions[0].mean_b.isZero());
    EXPECT_TRUE(state_dist.joint_partitions[0].cov_bb.isIdentity());
    filter.Predict(state_dist, 1.0, state_dist);
    EXPECT_TRUE(state_dist.mean_a.isZero());
    EXPECT_TRUE(state_dist.cov_aa.isApprox(2. * Q_a));
    EXPECT_TRUE(state_dist.joint_partitions[0].mean_b.isZero());
    EXPECT_TRUE(state_dist.joint_partitions[0].cov_bb.isApprox(2. * Q_b));
}

TEST(FUKFAndLinearModels, init_dynamicsize_predict)
{
    const size_t dim_state_a = 10;
    const size_t dim_state_b = 1;
    const size_t dim_observation = 20;

    typedef double Scalar;
    typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1> State_a;
    typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1> State_b;
    typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1> Observation;

    typedef ff::LinearGaussianProcessModel<State_a> ProcessModel_a;
    typedef ff::LinearGaussianProcessModel<State_b> ProcessModel_b;
    typedef ff::FactorizedLinearGaussianObservationModel<
                    Observation,
                    State_a,
                    State_b> ObservationModel;

    typedef ff::FactorizedUnscentedKalmanFilter<ProcessModel_a,
                                                ProcessModel_b,
                                                ObservationModel> Filter;

    ProcessModel_a::Operator Q_a =
            ProcessModel_a::Operator::Identity(dim_state_a,
                                               dim_state_a);
    ProcessModel_b::Operator Q_b =
            ProcessModel_b::Operator::Identity(dim_state_b,
                                               dim_state_b);
    ObservationModel::Operator R =
            ObservationModel::Operator::Identity(dim_observation,
                                                 dim_observation);

    Filter::CohesiveStateProcessModelPtr process_model_a =
            boost::make_shared<ProcessModel_a>(Q_a, dim_state_a);
    Filter::FactorizedStateProcessModelPtr process_model_b =
            boost::make_shared<ProcessModel_b>(Q_b, dim_state_b);
    Filter::ObservationModelPtr observation_model =
            boost::make_shared<ObservationModel>(R,
                                                 dim_observation,
                                                 dim_state_a,
                                                 dim_state_b);

    Filter filter(process_model_a, process_model_b, observation_model);

    Filter::StateDistribution state_dist;
    state_dist.initialize(State_a::Zero(dim_state_a, 1),
                          1,
                          State_b::Zero(dim_state_b, 1),
                          1.0,
                          1.0);

    EXPECT_TRUE(state_dist.mean_a.isZero());
    EXPECT_TRUE(state_dist.cov_aa.isIdentity());
    EXPECT_TRUE(state_dist.joint_partitions[0].mean_b.isZero());
    EXPECT_TRUE(state_dist.joint_partitions[0].cov_bb.isIdentity());
    filter.Predict(state_dist, 1.0, state_dist);
    EXPECT_TRUE(state_dist.mean_a.isZero());
    EXPECT_TRUE(state_dist.cov_aa.isApprox(2. * Q_a));
    EXPECT_TRUE(state_dist.joint_partitions[0].mean_b.isZero());
    EXPECT_TRUE(state_dist.joint_partitions[0].cov_bb.isApprox(2. * Q_b));
}

TEST(FUKFAndLinearModels, fixedsize_predict_update)
{
    typedef double Scalar;
    typedef Eigen::Matrix<Scalar, 10, 1> State_a;
    typedef Eigen::Matrix<Scalar, 1, 1> State_b;
    typedef Eigen::Matrix<Scalar, 100, 1> Observation;

    typedef ff::LinearGaussianProcessModel<State_a> ProcessModel_a;
    typedef ff::LinearGaussianProcessModel<State_b> ProcessModel_b;
    typedef ff::FactorizedLinearGaussianObservationModel<
                    Observation,
                    State_a,
                    State_b> ObservationModel;

    typedef ff::FactorizedUnscentedKalmanFilter<ProcessModel_a,
                                                ProcessModel_b,
                                                ObservationModel> Filter;

    ProcessModel_a::Operator Q_a =
            ProcessModel_a::Operator::Identity();
    ProcessModel_b::Operator Q_b =
            ProcessModel_b::Operator::Identity();

    ProcessModel_a::DynamicsMatrix A_a =
            ProcessModel_a::DynamicsMatrix::Identity();
    ProcessModel_b::DynamicsMatrix A_b =
            ProcessModel_b::DynamicsMatrix::Identity();

    ObservationModel::Operator R =
            ObservationModel::Operator::Identity();

    ObservationModel::SensorMatrix_a H_a =
            ObservationModel::SensorMatrix_a::Random();
    ObservationModel::SensorMatrix_b H_b =
            ObservationModel::SensorMatrix_b::Random();

    Q_a *= Q_a.transpose() * 0.05;
    Q_b *= Q_b.transpose() * 0.055;
    R *= 0.0005;
//    A_a *= 0.05;
//    A_b *= 0.05;

    Filter::CohesiveStateProcessModelPtr process_model_a =
            boost::make_shared<ProcessModel_a>(Q_a);
    Filter::FactorizedStateProcessModelPtr process_model_b =
            boost::make_shared<ProcessModel_b>(Q_b);
    Filter::ObservationModelPtr observation_model =
            boost::make_shared<ObservationModel>(R);

    process_model_a->A(A_a);
    process_model_b->A(A_b);
    observation_model->H_a(H_a);
    observation_model->H_b(H_b);

    Filter filter(process_model_a, process_model_b, observation_model);

    Filter::StateDistribution state_dist;
    state_dist.initialize(State_a::Zero(),
                          1,
                          State_b::Zero(),
                          1.0,
                          1.0);

    EXPECT_TRUE(state_dist.cov_aa.ldlt().isPositive());
    EXPECT_TRUE(state_dist.joint_partitions[0].cov_bb.ldlt().isPositive());

    for (size_t i = 0; i < 20000; ++i)
    {
        filter.Predict(state_dist, 1.0, state_dist);

        std::cout << "predict \n" <<  state_dist.cov_aa << std::endl;
        std::cout << "predict \n" <<  state_dist.joint_partitions[0].cov_bb << std::endl;

        EXPECT_TRUE(state_dist.cov_aa.ldlt().isPositive());
        EXPECT_TRUE(state_dist.joint_partitions[0].cov_bb.ldlt().isPositive());

        Observation y = Observation::Random();
        filter.Update(state_dist, y, state_dist);

        std::cout << "update \n" << state_dist.cov_aa << std::endl;
        std::cout << "update \n" << state_dist.joint_partitions[0].cov_bb << std::endl;

        EXPECT_TRUE(state_dist.cov_aa.ldlt().isPositive());
        EXPECT_TRUE(state_dist.joint_partitions[0].cov_bb.ldlt().isPositive());

        if (!state_dist.cov_aa.ldlt().isPositive())
        {
            ADD_FAILURE();
            break;
        }
    }
}

TEST(FUKFAndLinearModels, dynamicsize_predict_update)
{
    const size_t dim_state_a = 10;
    const size_t dim_state_b = 1;
    const size_t dim_observation = 1;

    typedef double Scalar;
    typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1> State_a;
    typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1> State_b;
    typedef Eigen::Matrix<Scalar, Eigen::Dynamic, 1> Observation;

    typedef ff::LinearGaussianProcessModel<State_a> ProcessModel_a;
    typedef ff::LinearGaussianProcessModel<State_b> ProcessModel_b;
    typedef ff::FactorizedLinearGaussianObservationModel<
                    Observation,
                    State_a,
                    State_b> ObservationModel;

    typedef ff::FactorizedUnscentedKalmanFilter<ProcessModel_a,
                                                ProcessModel_b,
                                                ObservationModel> Filter;

    ProcessModel_a::Operator Q_a =
            ProcessModel_a::Operator::Random(dim_state_a, dim_state_a);
    ProcessModel_b::Operator Q_b =
            ProcessModel_b::Operator::Random(dim_state_b, dim_state_b);

    ProcessModel_a::DynamicsMatrix A_a =
            ProcessModel_a::DynamicsMatrix::Random(dim_state_a,
                                                   dim_state_a);
    ProcessModel_b::DynamicsMatrix A_b =
            ProcessModel_b::DynamicsMatrix::Random(dim_state_b,
                                                   dim_state_b);

    ObservationModel::Operator R =
            ObservationModel::Operator::Identity(dim_observation,
                                                 dim_observation);

    ObservationModel::SensorMatrix_a H_a =
            ObservationModel::SensorMatrix_a::Random(dim_observation,
                                                     dim_state_a);
    ObservationModel::SensorMatrix_b H_b =
            ObservationModel::SensorMatrix_b::Random(dim_observation,
                                                     dim_state_b);

    Q_a *= Q_a.transpose() * 0.05;
    Q_b *= Q_b.transpose() * 0.055;
    R *= 0.0005;
    A_a *= 0.05;
    A_b *= 0.05;

    Filter::CohesiveStateProcessModelPtr process_model_a =
            boost::make_shared<ProcessModel_a>(Q_a, dim_state_a);
    Filter::FactorizedStateProcessModelPtr process_model_b =
            boost::make_shared<ProcessModel_b>(Q_b, dim_state_b);
    Filter::ObservationModelPtr observation_model =
            boost::make_shared<ObservationModel>(R,
                                                 dim_observation,
                                                 dim_state_a,
                                                 dim_state_b);

    process_model_a->A(A_a);
    process_model_b->A(A_b);
    observation_model->H_a(H_a);
    observation_model->H_b(H_b);

    Filter filter(process_model_a, process_model_b, observation_model);

    Filter::StateDistribution state_dist;
    state_dist.initialize(State_a::Zero(dim_state_a, 1),
                          10,
                          State_b::Zero(dim_state_b, 1),
                          1.0,
                          1.0);

    EXPECT_TRUE(state_dist.cov_aa.ldlt().isPositive());
    EXPECT_TRUE(state_dist.joint_partitions[0].cov_bb.ldlt().isPositive());

    for (size_t i = 0; i < 1000; ++i)
    {
        filter.Predict(state_dist, 1.0, state_dist);

        EXPECT_TRUE(state_dist.cov_aa.ldlt().isPositive());
        EXPECT_TRUE(state_dist.joint_partitions[0].cov_bb.ldlt().isPositive());

        Observation y = Observation::Random(dim_observation, 1);
        filter.Update(state_dist, y, state_dist);

        EXPECT_TRUE(state_dist.cov_aa.ldlt().isPositive());
        EXPECT_TRUE(state_dist.joint_partitions[0].cov_bb.ldlt().isPositive());
    }
}

<|endoftext|>


<commit_before>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string>

#include "app/l10n_util.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"

namespace {

// Given a page title, returns the expected window caption string.
std::wstring WindowCaptionFromPageTitle(std::wstring page_title) {
#if defined(OS_WIN) || defined(OS_LINUX)
  if (page_title.empty())
    return l10n_util::GetString(IDS_PRODUCT_NAME);

  return l10n_util::GetStringF(IDS_BROWSER_WINDOW_TITLE_FORMAT, page_title);
#elif defined(OS_MACOSX)
  // On Mac, we don't want to suffix the page title with the application name.
  if (page_title.empty())
    return l10n_util::GetString(IDS_BROWSER_WINDOW_MAC_TAB_UNTITLED);
  return page_title;
#endif
}

}  // namespace

class BrowserTest : public InProcessBrowserTest {
 protected:
  // In RTL locales wrap the page title with RTL embedding characters so that it
  // matches the value returned by GetWindowTitle().
  std::wstring LocaleWindowCaptionFromPageTitle(
      const std::wstring& expected_title) {
    std::wstring page_title = WindowCaptionFromPageTitle(expected_title);
#if defined(OS_WIN)
    std::string locale = g_browser_process->GetApplicationLocale();
    if (l10n_util::GetTextDirectionForLocale(locale.c_str()) ==
        l10n_util::RIGHT_TO_LEFT) {
      l10n_util::WrapStringWithLTRFormatting(&page_title);
    }

    return page_title;
#else
    // Do we need to use the above code on POSIX as well?
    return page_title;
#endif
  }
};

// Launch the app on a page with no title, check that the app title was set
// correctly.
IN_PROC_BROWSER_TEST_F(BrowserTest, NoTitle) {
  ui_test_utils::NavigateToURL(browser(),
                               ui_test_utils::GetTestUrl(L".", L"title1.html"));
  EXPECT_EQ(LocaleWindowCaptionFromPageTitle(L"title1.html"),
            UTF16ToWideHack(browser()->GetCurrentPageTitle()));
  string16 tab_title;
  ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(), &tab_title));
  EXPECT_EQ(ASCIIToUTF16("title1.html"), tab_title);
}

// Launch the app, navigate to a page with a title, check that the app title
// was set correctly.
IN_PROC_BROWSER_TEST_F(BrowserTest, Title) {
  ui_test_utils::NavigateToURL(browser(),
                               ui_test_utils::GetTestUrl(L".", L"title2.html"));
  const std::wstring test_title(L"Title Of Awesomeness");
  EXPECT_EQ(LocaleWindowCaptionFromPageTitle(test_title),
            browser()->GetCurrentPageTitle());
  string16 tab_title;
  ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(), &tab_title));
  EXPECT_EQ(WideToUTF16(test_title), tab_title);
}
<commit_msg>Fix another string conversion with UTF16ToWideHack<commit_after>// Copyright (c) 2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <string>

#include "app/l10n_util.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/test/in_process_browser_test.h"
#include "chrome/test/ui_test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"

namespace {

// Given a page title, returns the expected window caption string.
std::wstring WindowCaptionFromPageTitle(std::wstring page_title) {
#if defined(OS_WIN) || defined(OS_LINUX)
  if (page_title.empty())
    return l10n_util::GetString(IDS_PRODUCT_NAME);

  return l10n_util::GetStringF(IDS_BROWSER_WINDOW_TITLE_FORMAT, page_title);
#elif defined(OS_MACOSX)
  // On Mac, we don't want to suffix the page title with the application name.
  if (page_title.empty())
    return l10n_util::GetString(IDS_BROWSER_WINDOW_MAC_TAB_UNTITLED);
  return page_title;
#endif
}

}  // namespace

class BrowserTest : public InProcessBrowserTest {
 protected:
  // In RTL locales wrap the page title with RTL embedding characters so that it
  // matches the value returned by GetWindowTitle().
  std::wstring LocaleWindowCaptionFromPageTitle(
      const std::wstring& expected_title) {
    std::wstring page_title = WindowCaptionFromPageTitle(expected_title);
#if defined(OS_WIN)
    std::string locale = g_browser_process->GetApplicationLocale();
    if (l10n_util::GetTextDirectionForLocale(locale.c_str()) ==
        l10n_util::RIGHT_TO_LEFT) {
      l10n_util::WrapStringWithLTRFormatting(&page_title);
    }

    return page_title;
#else
    // Do we need to use the above code on POSIX as well?
    return page_title;
#endif
  }
};

// Launch the app on a page with no title, check that the app title was set
// correctly.
IN_PROC_BROWSER_TEST_F(BrowserTest, NoTitle) {
  ui_test_utils::NavigateToURL(browser(),
                               ui_test_utils::GetTestUrl(L".", L"title1.html"));
  EXPECT_EQ(LocaleWindowCaptionFromPageTitle(L"title1.html"),
            UTF16ToWideHack(browser()->GetCurrentPageTitle()));
  string16 tab_title;
  ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(), &tab_title));
  EXPECT_EQ(ASCIIToUTF16("title1.html"), tab_title);
}

// Launch the app, navigate to a page with a title, check that the app title
// was set correctly.
IN_PROC_BROWSER_TEST_F(BrowserTest, Title) {
  ui_test_utils::NavigateToURL(browser(),
                               ui_test_utils::GetTestUrl(L".", L"title2.html"));
  const std::wstring test_title(L"Title Of Awesomeness");
  EXPECT_EQ(LocaleWindowCaptionFromPageTitle(test_title),
            UTF16ToWideHack(browser()->GetCurrentPageTitle()));
  string16 tab_title;
  ASSERT_TRUE(ui_test_utils::GetCurrentTabTitle(browser(), &tab_title));
  EXPECT_EQ(WideToUTF16(test_title), tab_title);
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/common/notification_service.h"

#include "base/lazy_instance.h"
#include "base/threading/thread_local.h"
#include "chrome/common/notification_observer.h"

static base::LazyInstance<base::ThreadLocalPointer<NotificationService> >
    lazy_tls_ptr(base::LINKER_INITIALIZED);

// static
NotificationService* NotificationService::current() {
  return lazy_tls_ptr.Pointer()->Get();
}

// static
bool NotificationService::HasKey(const NotificationSourceMap& map,
                                 const NotificationSource& source) {
  return map.find(source.map_key()) != map.end();
}

NotificationService::NotificationService() {
  DCHECK(current() == NULL);
#ifndef NDEBUG
  memset(observer_counts_, 0, sizeof(observer_counts_));
#endif

  lazy_tls_ptr.Pointer()->Set(this);
}

void NotificationService::AddObserver(NotificationObserver* observer,
                                      NotificationType type,
                                      const NotificationSource& source) {
  DCHECK(type.value < NotificationType::NOTIFICATION_TYPE_COUNT);

  // We have gotten some crashes where the observer pointer is NULL. The problem
  // is that this happens when we actually execute a notification, so have no
  // way of knowing who the bad observer was. We want to know when this happens
  // in release mode so we know what code to blame the crash on (since this is
  // guaranteed to crash later).
  CHECK(observer);

  NotificationObserverList* observer_list;
  if (HasKey(observers_[type.value], source)) {
    observer_list = observers_[type.value][source.map_key()];
  } else {
    observer_list = new NotificationObserverList;
    observers_[type.value][source.map_key()] = observer_list;
  }

  observer_list->AddObserver(observer);
#ifndef NDEBUG
  ++observer_counts_[type.value];
#endif
}

void NotificationService::RemoveObserver(NotificationObserver* observer,
                                         NotificationType type,
                                         const NotificationSource& source) {
  DCHECK(type.value < NotificationType::NOTIFICATION_TYPE_COUNT);

  // This is a very serious bug.  An object is most likely being deleted on
  // the wrong thread, and as a result another thread's NotificationService
  // has its deleted pointer in its map.  A garbge object will be called in the
  // future.
  // NOTE: when this check shows crashes, use BrowserThread::DeleteOnIOThread or
  // other variants as the trait on the object.
  CHECK(HasKey(observers_[type.value], source));

  NotificationObserverList* observer_list =
      observers_[type.value][source.map_key()];
  if (observer_list) {
    observer_list->RemoveObserver(observer);
#ifndef NDEBUG
    --observer_counts_[type.value];
#endif
  }

  // TODO(jhughes): Remove observer list from map if empty?
}

void NotificationService::Notify(NotificationType type,
                                 const NotificationSource& source,
                                 const NotificationDetails& details) {
  DCHECK(type.value > NotificationType::ALL) <<
      "Allowed for observing, but not posting.";
  DCHECK(type.value < NotificationType::NOTIFICATION_TYPE_COUNT);

  // There's no particular reason for the order in which the different
  // classes of observers get notified here.

  // Notify observers of all types and all sources
  if (HasKey(observers_[NotificationType::ALL], AllSources()) &&
      source != AllSources()) {
    FOR_EACH_OBSERVER(NotificationObserver,
       *observers_[NotificationType::ALL][AllSources().map_key()],
       Observe(type, source, details));
  }

  // Notify observers of all types and the given source
  if (HasKey(observers_[NotificationType::ALL], source)) {
    FOR_EACH_OBSERVER(NotificationObserver,
        *observers_[NotificationType::ALL][source.map_key()],
        Observe(type, source, details));
  }

  // Notify observers of the given type and all sources
  if (HasKey(observers_[type.value], AllSources()) &&
      source != AllSources()) {
    FOR_EACH_OBSERVER(NotificationObserver,
                      *observers_[type.value][AllSources().map_key()],
                      Observe(type, source, details));
  }

  // Notify observers of the given type and the given source
  if (HasKey(observers_[type.value], source)) {
    FOR_EACH_OBSERVER(NotificationObserver,
                      *observers_[type.value][source.map_key()],
                      Observe(type, source, details));
  }
}

NotificationService::~NotificationService() {
  lazy_tls_ptr.Pointer()->Set(NULL);

#ifndef NDEBUG
  for (int i = 0; i < NotificationType::NOTIFICATION_TYPE_COUNT; i++) {
    if (observer_counts_[i] > 0) {
      // This may not be completely fixable -- see
      // http://code.google.com/p/chromium/issues/detail?id=11010 .
      VLOG(1) << observer_counts_[i] << " notification observer(s) leaked "
                 " of notification type " << i;
    }
  }
#endif

  for (int i = 0; i < NotificationType::NOTIFICATION_TYPE_COUNT; i++) {
    NotificationSourceMap omap = observers_[i];
    for (NotificationSourceMap::iterator it = omap.begin();
         it != omap.end(); ++it)
      delete it->second;
  }
}

NotificationObserver::NotificationObserver() {}

NotificationObserver::~NotificationObserver() {}
<commit_msg>Got rid of extra space in notification log<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/common/notification_service.h"

#include "base/lazy_instance.h"
#include "base/threading/thread_local.h"
#include "chrome/common/notification_observer.h"

static base::LazyInstance<base::ThreadLocalPointer<NotificationService> >
    lazy_tls_ptr(base::LINKER_INITIALIZED);

// static
NotificationService* NotificationService::current() {
  return lazy_tls_ptr.Pointer()->Get();
}

// static
bool NotificationService::HasKey(const NotificationSourceMap& map,
                                 const NotificationSource& source) {
  return map.find(source.map_key()) != map.end();
}

NotificationService::NotificationService() {
  DCHECK(current() == NULL);
#ifndef NDEBUG
  memset(observer_counts_, 0, sizeof(observer_counts_));
#endif

  lazy_tls_ptr.Pointer()->Set(this);
}

void NotificationService::AddObserver(NotificationObserver* observer,
                                      NotificationType type,
                                      const NotificationSource& source) {
  DCHECK(type.value < NotificationType::NOTIFICATION_TYPE_COUNT);

  // We have gotten some crashes where the observer pointer is NULL. The problem
  // is that this happens when we actually execute a notification, so have no
  // way of knowing who the bad observer was. We want to know when this happens
  // in release mode so we know what code to blame the crash on (since this is
  // guaranteed to crash later).
  CHECK(observer);

  NotificationObserverList* observer_list;
  if (HasKey(observers_[type.value], source)) {
    observer_list = observers_[type.value][source.map_key()];
  } else {
    observer_list = new NotificationObserverList;
    observers_[type.value][source.map_key()] = observer_list;
  }

  observer_list->AddObserver(observer);
#ifndef NDEBUG
  ++observer_counts_[type.value];
#endif
}

void NotificationService::RemoveObserver(NotificationObserver* observer,
                                         NotificationType type,
                                         const NotificationSource& source) {
  DCHECK(type.value < NotificationType::NOTIFICATION_TYPE_COUNT);

  // This is a very serious bug.  An object is most likely being deleted on
  // the wrong thread, and as a result another thread's NotificationService
  // has its deleted pointer in its map.  A garbge object will be called in the
  // future.
  // NOTE: when this check shows crashes, use BrowserThread::DeleteOnIOThread or
  // other variants as the trait on the object.
  CHECK(HasKey(observers_[type.value], source));

  NotificationObserverList* observer_list =
      observers_[type.value][source.map_key()];
  if (observer_list) {
    observer_list->RemoveObserver(observer);
#ifndef NDEBUG
    --observer_counts_[type.value];
#endif
  }

  // TODO(jhughes): Remove observer list from map if empty?
}

void NotificationService::Notify(NotificationType type,
                                 const NotificationSource& source,
                                 const NotificationDetails& details) {
  DCHECK(type.value > NotificationType::ALL) <<
      "Allowed for observing, but not posting.";
  DCHECK(type.value < NotificationType::NOTIFICATION_TYPE_COUNT);

  // There's no particular reason for the order in which the different
  // classes of observers get notified here.

  // Notify observers of all types and all sources
  if (HasKey(observers_[NotificationType::ALL], AllSources()) &&
      source != AllSources()) {
    FOR_EACH_OBSERVER(NotificationObserver,
       *observers_[NotificationType::ALL][AllSources().map_key()],
       Observe(type, source, details));
  }

  // Notify observers of all types and the given source
  if (HasKey(observers_[NotificationType::ALL], source)) {
    FOR_EACH_OBSERVER(NotificationObserver,
        *observers_[NotificationType::ALL][source.map_key()],
        Observe(type, source, details));
  }

  // Notify observers of the given type and all sources
  if (HasKey(observers_[type.value], AllSources()) &&
      source != AllSources()) {
    FOR_EACH_OBSERVER(NotificationObserver,
                      *observers_[type.value][AllSources().map_key()],
                      Observe(type, source, details));
  }

  // Notify observers of the given type and the given source
  if (HasKey(observers_[type.value], source)) {
    FOR_EACH_OBSERVER(NotificationObserver,
                      *observers_[type.value][source.map_key()],
                      Observe(type, source, details));
  }
}

NotificationService::~NotificationService() {
  lazy_tls_ptr.Pointer()->Set(NULL);

#ifndef NDEBUG
  for (int i = 0; i < NotificationType::NOTIFICATION_TYPE_COUNT; i++) {
    if (observer_counts_[i] > 0) {
      // This may not be completely fixable -- see
      // http://code.google.com/p/chromium/issues/detail?id=11010 .
      VLOG(1) << observer_counts_[i] << " notification observer(s) leaked "
                 "of notification type " << i;
    }
  }
#endif

  for (int i = 0; i < NotificationType::NOTIFICATION_TYPE_COUNT; i++) {
    NotificationSourceMap omap = observers_[i];
    for (NotificationSourceMap::iterator it = omap.begin();
         it != omap.end(); ++it)
      delete it->second;
  }
}

NotificationObserver::NotificationObserver() {}

NotificationObserver::~NotificationObserver() {}
<|endoftext|>


<commit_before>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkTimeStampTest.cxx
  Language:  C++

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif
#include <iostream>
#include "itkTimeStamp.h"
#include "itkMultiThreader.h"

typedef struct {
  itk::TimeStamp * m_TimeStamp;
  signed long counters[ITK_MAX_THREADS];
} TimeStampTestHelper;

ITK_THREAD_RETURN_TYPE modified_function( void *ptr )
{
  typedef itk::MultiThreader::ThreadInfoStruct  ThreadInfoType;

  ThreadInfoType * infoStruct = static_cast< ThreadInfoType * >( ptr );

  const unsigned int threadId = infoStruct->ThreadID;

  TimeStampTestHelper * helper =
    static_cast< TimeStampTestHelper * >( infoStruct->UserData );

  itk::TimeStamp *tsp = helper->m_TimeStamp;
  helper->counters[threadId]++;

  tsp->Modified();

  return ITK_THREAD_RETURN_VALUE;
}

// Fake the non-optimized timestamp by surrounding
// the call to TimeStamp::Modified with a mutex
static itk::SimpleFastMutexLock TimeStampTestMutex;

ITK_THREAD_RETURN_TYPE modified_function_base( void *ptr )
{
  typedef itk::MultiThreader::ThreadInfoStruct  ThreadInfoType;

  ThreadInfoType * infoStruct = static_cast< ThreadInfoType * >( ptr );

  const unsigned int threadId = infoStruct->ThreadID;

  TimeStampTestHelper * helper =
    static_cast< TimeStampTestHelper * >( infoStruct->UserData );

  itk::TimeStamp *tsp = helper->m_TimeStamp;
  helper->counters[threadId]++;

  TimeStampTestMutex.Lock();
  tsp->Modified();
  TimeStampTestMutex.Unlock();

  return ITK_THREAD_RETURN_VALUE;
}

bool TimeStampTest( itk::ThreadFunctionType modfunc, bool addmodifiedcall=false )
{
  bool success = true;

  TimeStampTestHelper helper;

  for(unsigned int k=0; k < ITK_MAX_THREADS; k++)
    {
    helper.counters[k] = 0;
    }

  try
    {
    itk::TimeStamp ts;

    itk::MultiThreader::Pointer multithreader = itk::MultiThreader::New();
    multithreader->SetNumberOfThreads(ITK_MAX_THREADS+10);// this will be clamped

    const signed long numberOfThreads =
      static_cast<signed long>( multithreader->GetNumberOfThreads() );

    if( numberOfThreads > ITK_MAX_THREADS )
      {
      std::cerr << "[PARTIAL TEST FAILED]" << std::endl;
      std::cerr << "numberOfThreads > ITK_MAX_THREADS" << std::endl;
      return false;
      }

    std::cout << "Global Maximum Number of Threads = " <<
      multithreader->GetGlobalMaximumNumberOfThreads() << std::endl;
    std::cout << "Global Default Number of Threads = " <<
      multithreader->GetGlobalDefaultNumberOfThreads() << std::endl;

    std::cout << "Number of Threads = " << numberOfThreads << std::endl;

    helper.m_TimeStamp = &ts;

    multithreader->SetSingleMethod( modfunc, &helper);

    // call modified once to make it up-to-date;
    ts.Modified();

    const signed long init_mtime = ts.GetMTime();
    std::cout << "init_mtime: " << init_mtime << std::endl;

    signed long prev_mtime = init_mtime;

    const signed int num_exp = 2000;

    for( signed int i = 0; i < num_exp; i++ )
      {
      multithreader->SingleMethodExecute();

      // This is to check whether if we update the modified
      // time in the main thread, we do get a good result or not
      if ( addmodifiedcall ) ts.Modified();

      signed long current_mtime = ts.GetMTime();

      // This is to use the same tests as the standard test
      if ( addmodifiedcall ) current_mtime-=1;

      for( signed int j = 0; j < numberOfThreads; j++ )
        {
        if( helper.counters[j] != i+1 )
          {
          std::cerr << "counter[" << j << "] = " << helper.counters[j];
          std::cerr << " at iteration " << i << std::endl;
          }
        }

      if( ( current_mtime - prev_mtime ) > numberOfThreads )
        {
        // This might be a normal case since the modified time of a time stamp
        // is global If a new itk object is created this will also increment
        // the time
        std::cout << "[Iteration " << i << "]" << std::endl;
        std::cout << "current_mtime   : " << current_mtime << std::endl;
        std::cout << "prev_mtime      : " << prev_mtime << std::endl;
        std::cout << "num_threads     : " << numberOfThreads << std::endl;
        std::cout << "cur - prev mtime: " << current_mtime - prev_mtime << std::endl;
        std::cout << std::endl;
        }
      else
        {
        if( ( current_mtime - prev_mtime ) < numberOfThreads )
          {
          // This is a failure
          std::cerr << "[Iteration " << i << " FAILED]" << std::endl;
          std::cerr << "current_mtime   : " << current_mtime << std::endl;
          std::cerr << "prev_mtime      : " << prev_mtime << std::endl;
          std::cerr << "num_threads     : " << numberOfThreads << std::endl;
          std::cerr << "cur - prev mtime: " << current_mtime - prev_mtime << std::endl;
          std::cerr << std::endl;
          success = false;
          }
        }

      prev_mtime = current_mtime;

      // This is to use the same tests as the standard test
      if ( addmodifiedcall ) prev_mtime+=1;
      }
    }
  catch (itk::ExceptionObject &e)
    {
    std::cerr << "[PARTIAL TEST FAILED]" << std::endl;
    std::cerr << "Exception caught: "<< e << std::endl;
    return false;
    }

  if (!success)
    {
    std::cerr << "[PARTIAL TEST FAILED]" << std::endl;
    return false;
    }

  std::cout << "[PARTIAL TEST PASSED]" << std::endl;
  return true;
}

int itkTimeStampTest(int, char*[])
{
   const bool baseres = TimeStampTest( modified_function_base );
  if ( !baseres )
    {
    std::cerr << "[BASE TEST FAILED]" << std::endl;
    }

  const bool optres  = TimeStampTest( modified_function );
  if ( !optres )
    {
    std::cerr << "[OPTIMIZED TEST FAILED]" << std::endl;
    }

  const bool baseresadd = TimeStampTest( modified_function_base, true );
  if ( !baseresadd )
    {
    std::cerr << "[BASE TEST 2 FAILED]" << std::endl;
    }

  const bool optresadd  = TimeStampTest( modified_function, true );
  if ( !optresadd )
    {
    std::cerr << "[OPTIMIZED TEST 2 FAILED]" << std::endl;
    }

  if ( !(baseres && optres && baseresadd && optresadd) )
    {
    std::cerr << "[TEST FAILED]" << std::endl;
    return EXIT_FAILURE;
    }

  std::cout << "[TEST PASSED]" << std::endl;
  return EXIT_SUCCESS;
}
<commit_msg>BUG: Fixed the TimeStamp test to use one timestamp per thread (it might not be safe to call Modified on the same object at the same time by different threads, see http://www.itk.org/mailman/private/insight-developers/2009-February/011732.html for more detail<commit_after>/*=========================================================================

  Program:   Insight Segmentation & Registration Toolkit
  Module:    itkTimeStampTest.cxx
  Language:  C++

  Copyright (c) Insight Software Consortium. All rights reserved.
  See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.

     This software is distributed WITHOUT ANY WARRANTY; without even
     the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
     PURPOSE.  See the above copyright notices for more information.

=========================================================================*/
#if defined(_MSC_VER)
#pragma warning ( disable : 4786 )
#endif
#include <iostream>
#include "itkTimeStamp.h"
#include "itkMultiThreader.h"

// A helper struct for the test, the idea is to have one timestamp per thread.
// To ease the writing of the test, we use  MultiThreader::SingleMethodExecute
// with an array of timestamps in the shared data
typedef struct {
  std::vector<itk::TimeStamp> timestamps;
  std::vector<long int> counters;
} TimeStampTestHelper;

ITK_THREAD_RETURN_TYPE modified_function( void *ptr )
{
  typedef itk::MultiThreader::ThreadInfoStruct  ThreadInfoType;

  ThreadInfoType * infoStruct = static_cast< ThreadInfoType * >( ptr );

  const unsigned int threadId = infoStruct->ThreadID;

  TimeStampTestHelper * helper =
    static_cast< TimeStampTestHelper * >( infoStruct->UserData );

  helper->timestamps[threadId].Modified();
  helper->counters[threadId]++;

  return ITK_THREAD_RETURN_VALUE;
}

int itkTimeStampTest(int, char*[])
{
  bool success = true;

  try
    {
    TimeStampTestHelper helper;

    // Set up the multithreader
    itk::MultiThreader::Pointer multithreader = itk::MultiThreader::New();
    multithreader->SetNumberOfThreads( ITK_MAX_THREADS+10 );// this will be clamped
    multithreader->SetSingleMethod( modified_function, &helper);

    // Test that the number of threads has actually been clamped
    const long int numberOfThreads =
      static_cast<long int>( multithreader->GetNumberOfThreads() );

    if( numberOfThreads > ITK_MAX_THREADS )
      {
      std::cerr << "[TEST FAILED]" << std::endl;
      std::cerr << "numberOfThreads > ITK_MAX_THREADS" << std::endl;
      return EXIT_FAILURE;
      }

    // Set up the helper class
    helper.counters.resize( numberOfThreads );
    helper.timestamps.resize( numberOfThreads );
    for(int k=0; k < numberOfThreads; k++)
    {
       helper.counters[k] = 0;
    }

    // Declare an array to test whether the all modified times have
    // been used
    std::vector<bool> istimestamped( numberOfThreads );

    // Call Modified once  on any object to make it up-to-date
    multithreader->Modified();

    const long int init_mtime = multithreader->GetMTime();
    std::cout << "init_mtime: " << init_mtime << std::endl;

    long int prev_mtime = init_mtime;

    const int num_exp = 500;

    for( int i = 0; i < num_exp; i++ )
      {
      multithreader->SingleMethodExecute();

      long int min_mtime = helper.timestamps[0].GetMTime();
      long int max_mtime = helper.timestamps[0].GetMTime();
      for(int k=0; k < numberOfThreads; k++)
        {
        const long int & mtime = helper.timestamps[k].GetMTime();
        if ( mtime > max_mtime )
          {
          max_mtime = mtime;
          }
        else if ( mtime < min_mtime )
          {
          min_mtime = mtime;
          }

        // initialiaze the array to false
        istimestamped[k]=false;
        }

      bool iter_success =
             ( ((max_mtime-prev_mtime )==numberOfThreads) &&
               (min_mtime==prev_mtime+1) );

      if ( iter_success )
        {
        for(int k=0; k < numberOfThreads; k++)
          {
          // Test whether the all modified times have
          // been used
          const long int index = helper.timestamps[k].GetMTime()-min_mtime;

          if ( istimestamped[index] == true )
            {
            iter_success = false;
            std::cerr<<helper.timestamps[k].GetMTime()<<" was used twice as a timestamp!"<<std::endl;
            }
          else
            {
            istimestamped[index] = true;
            }

          // Test the counters
          if( helper.counters[k] != i+1 )
            {
            iter_success = false;
            std::cerr << "counter[" << k << "] = " << helper.counters[k];
            std::cerr << " at iteration " << i << std::endl;
            }
          }
      }

      if( !iter_success )
        {
        std::cerr << "[Iteration " << i << " FAILED]" << std::endl;
        std::cerr << "max_mtime       : " << max_mtime << std::endl;
        std::cerr << "min_mtime       : " << min_mtime << std::endl;
        std::cerr << "prev_mtime      : " << prev_mtime << std::endl;
        std::cerr << "num_threads     : " << numberOfThreads << std::endl;
        std::cerr << "max - prev mtime: " << max_mtime - prev_mtime << std::endl;
        std::cerr << std::endl;
        success = false;

        // Note that in a more general setting,  (max_mtime-prev_mtime)>numberOfThreads
        // might be a normal case since the modified time of a time stamp
        // is global. If a new itk object is created this will also increment
        // the time. In our specific test, there's no reason for another ITK object to be
        // modified though
        }

      prev_mtime = max_mtime;
      }
    }
  catch (itk::ExceptionObject &e)
    {
    std::cerr << "[TEST FAILED]" << std::endl;
    std::cerr << "Exception caught: "<< e << std::endl;
    return EXIT_FAILURE;
    }

  if (!success)
    {
    std::cerr << "[TEST FAILED]" << std::endl;
    return EXIT_FAILURE;
    }

  std::cout << "[TEST PASSED]" << std::endl;
  return EXIT_SUCCESS;
}
<|endoftext|>


<commit_before>/*************************************************************************
 *
 *  $RCSfile: Ref.cxx,v $
 *
 *  $Revision: 1.6 $
 *
 *  last change: $Author: vg $ $Date: 2005-02-16 17:29:21 $
 *
 *  The Contents of this file are made available subject to the terms of
 *  either of the following licenses
 *
 *         - GNU Lesser General Public License Version 2.1
 *         - Sun Industry Standards Source License Version 1.1
 *
 *  Sun Microsystems Inc., October, 2000
 *
 *  GNU Lesser General Public License Version 2.1
 *  =============================================
 *  Copyright 2000 by Sun Microsystems, Inc.
 *  901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *  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., 59 Temple Place, Suite 330, Boston,
 *  MA  02111-1307  USA
 *
 *
 *  Sun Industry Standards Source License Version 1.1
 *  =================================================
 *  The contents of this file are subject to the Sun Industry Standards
 *  Source License Version 1.1 (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.openoffice.org/license.html.
 *
 *  Software provided under this License is provided on an "AS IS" basis,
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 *  See the License for the specific provisions governing your rights and
 *  obligations concerning the Software.
 *
 *  The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 *
 *  Copyright: 2000 by Sun Microsystems, Inc.
 *
 *  All Rights Reserved.
 *
 *  Contributor(s): _______________________________________
 *
 *
 ************************************************************************/

#ifndef _CONNECTIVITY_JAVA_SQL_REF_HXX_
#include "java/sql/Ref.hxx"
#endif
#ifndef _CONNECTIVITY_JAVA_TOOLS_HXX_
#include "java/tools.hxx"
#endif
using namespace connectivity;
//**************************************************************
//************ Class: java.sql.Ref
//**************************************************************

jclass java_sql_Ref::theClass = 0;
java_sql_Ref::java_sql_Ref( JNIEnv * pEnv, jobject myObj )
: java_lang_Object( pEnv, myObj )
{
    SDBThreadAttach::addRef();
}
java_sql_Ref::~java_sql_Ref()
{
    SDBThreadAttach::releaseRef();
}

jclass java_sql_Ref::getMyClass()
{
    // die Klasse muss nur einmal geholt werden, daher statisch
    if( !theClass ){
        SDBThreadAttach t;
        if( !t.pEnv ) return (jclass)NULL;
        jclass tempClass = t.pEnv->FindClass( "java/sql/Ref" );
        jclass globClass = (jclass)t.pEnv->NewGlobalRef( tempClass );
        t.pEnv->DeleteLocalRef( tempClass );
        saveClassRef( globClass );
    }
    return theClass;
}

void java_sql_Ref::saveClassRef( jclass pClass )
{
    if( pClass==NULL  )
        return;
    // der uebergebe Klassen-Handle ist schon global, daher einfach speichern
    theClass = pClass;
}

::rtl::OUString SAL_CALL java_sql_Ref::getBaseTypeName(  ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
{
    SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java Enviroment geloescht worden!");
    ::rtl::OUString aStr;
    if( t.pEnv ){
        // temporaere Variable initialisieren
        static char * cSignature = "()Ljava/lang/String;";
        static char * cMethodName = "getBaseTypeName";
        // Java-Call absetzen
        static jmethodID mID = NULL;
        if ( !mID  )
            mID  = t.pEnv->GetMethodID( getMyClass(), cMethodName, cSignature );OSL_ENSURE(mID,"Unknown method id!");
        if( mID ){
            jstring out = (jstring)t.pEnv->CallObjectMethod( object, mID);
            ThrowSQLException(t.pEnv,*this);
            aStr = JavaString2String(t.pEnv,out);
            // und aufraeumen
        } //mID
    } //t.pEnv
    // ACHTUNG: der Aufrufer wird Eigentuemer des zurueckgelieferten Zeigers !!!
    return  aStr;
}

<commit_msg>INTEGRATION: CWS ooo19126 (1.6.78); FILE MERGED 2005/09/05 17:24:14 rt 1.6.78.1: #i54170# Change license header: remove SISSL<commit_after>/*************************************************************************
 *
 *  OpenOffice.org - a multi-platform office productivity suite
 *
 *  $RCSfile: Ref.cxx,v $
 *
 *  $Revision: 1.7 $
 *
 *  last change: $Author: rt $ $Date: 2005-09-08 06:11:51 $
 *
 *  The Contents of this file are made available subject to
 *  the terms of GNU Lesser General Public License Version 2.1.
 *
 *
 *    GNU Lesser General Public License Version 2.1
 *    =============================================
 *    Copyright 2005 by Sun Microsystems, Inc.
 *    901 San Antonio Road, Palo Alto, CA 94303, USA
 *
 *    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., 59 Temple Place, Suite 330, Boston,
 *    MA  02111-1307  USA
 *
 ************************************************************************/

#ifndef _CONNECTIVITY_JAVA_SQL_REF_HXX_
#include "java/sql/Ref.hxx"
#endif
#ifndef _CONNECTIVITY_JAVA_TOOLS_HXX_
#include "java/tools.hxx"
#endif
using namespace connectivity;
//**************************************************************
//************ Class: java.sql.Ref
//**************************************************************

jclass java_sql_Ref::theClass = 0;
java_sql_Ref::java_sql_Ref( JNIEnv * pEnv, jobject myObj )
: java_lang_Object( pEnv, myObj )
{
    SDBThreadAttach::addRef();
}
java_sql_Ref::~java_sql_Ref()
{
    SDBThreadAttach::releaseRef();
}

jclass java_sql_Ref::getMyClass()
{
    // die Klasse muss nur einmal geholt werden, daher statisch
    if( !theClass ){
        SDBThreadAttach t;
        if( !t.pEnv ) return (jclass)NULL;
        jclass tempClass = t.pEnv->FindClass( "java/sql/Ref" );
        jclass globClass = (jclass)t.pEnv->NewGlobalRef( tempClass );
        t.pEnv->DeleteLocalRef( tempClass );
        saveClassRef( globClass );
    }
    return theClass;
}

void java_sql_Ref::saveClassRef( jclass pClass )
{
    if( pClass==NULL  )
        return;
    // der uebergebe Klassen-Handle ist schon global, daher einfach speichern
    theClass = pClass;
}

::rtl::OUString SAL_CALL java_sql_Ref::getBaseTypeName(  ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
{
    SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java Enviroment geloescht worden!");
    ::rtl::OUString aStr;
    if( t.pEnv ){
        // temporaere Variable initialisieren
        static char * cSignature = "()Ljava/lang/String;";
        static char * cMethodName = "getBaseTypeName";
        // Java-Call absetzen
        static jmethodID mID = NULL;
        if ( !mID  )
            mID  = t.pEnv->GetMethodID( getMyClass(), cMethodName, cSignature );OSL_ENSURE(mID,"Unknown method id!");
        if( mID ){
            jstring out = (jstring)t.pEnv->CallObjectMethod( object, mID);
            ThrowSQLException(t.pEnv,*this);
            aStr = JavaString2String(t.pEnv,out);
            // und aufraeumen
        } //mID
    } //t.pEnv
    // ACHTUNG: der Aufrufer wird Eigentuemer des zurueckgelieferten Zeigers !!!
    return  aStr;
}

<|endoftext|>


<commit_before>#include <map>
#include <iostream>

#include "globals.hh"
#include "fstate.hh"
#include "store.hh"
#include "shared.hh"

typedef ATerm Expr;

static Expr evalFile(string fileName);

static Expr substExpr(string x, Expr rep, Expr e)
{
    char * s;
    Expr e2;

    if (ATmatch(e, "Var(<str>)", &s))
        if (x == s)
            return rep;
        else
            return e;

    if (ATmatch(e, "Lam(<str>, <term>)", &s, &e2))
        if (x == s)
            return e;
    /* !!! unfair substitutions */

    /* Generically substitute in subterms. */

    if (ATgetType(e) == AT_APPL) {
        AFun fun = ATgetAFun(e);
        int arity = ATgetArity(fun);
        ATermList args = ATempty;

        for (int i = arity - 1; i >= 0; i--)
            args = ATinsert(args, substExpr(x, rep, ATgetArgument(e, i)));

        return (ATerm) ATmakeApplList(fun, args);
    }

    if (ATgetType(e) == AT_LIST) {
        ATermList in = (ATermList) e;
        ATermList out = ATempty;

        while (!ATisEmpty(in)) {
            out = ATinsert(out, substExpr(x, rep, ATgetFirst(in)));
            in = ATgetNext(in);
        }

        return (ATerm) ATreverse(out);
    }

    throw badTerm("do not know how to substitute", e);
}

static Expr substExprMany(ATermList formals, ATermList args, Expr body)
{
    char * s;
    Expr e;

    /* !!! check args against formals */

    while (!ATisEmpty(args)) {
        ATerm tup = ATgetFirst(args);
        if (!ATmatch(tup, "(<str>, <term>)", &s, &e))
            throw badTerm("expected an argument tuple", tup);

        body = substExpr(s, e, body);

        args = ATgetNext(args);
    }

    return body;
}

static Expr evalExpr(Expr e)
{
    char * s1;
    Expr e1, e2, e3, e4;
    ATermList bnds;

    /* Normal forms. */
    if (ATmatch(e, "<str>", &s1) ||
        ATmatch(e, "Function([<list>], <term>)", &e1, &e2))
        return e;

    if (fstatePath(e) != "") return e; /* !!! hack */

    /* Application. */
    if (ATmatch(e, "App(<term>, [<list>])", &e1, &e2)) {
        e1 = evalExpr(e1);
        if (!ATmatch(e1, "Function([<list>], <term>)", &e3, &e4))
            throw badTerm("expecting a function", e1);
        return evalExpr(substExprMany((ATermList) e3, (ATermList) e2, e4));
    }

    /* Fix inclusion. */
    if (ATmatch(e, "IncludeFix(<str>)", &s1)) {
        string fileName(s1);
        return evalFile(s1);
    }

    /* Relative files. */
    if (ATmatch(e, "Relative(<str>)", &s1)) {
        string srcPath = s1;
        string dstPath;
        Hash hash;
        addToStore(srcPath, dstPath, hash);
        return ATmake("Path(<str>, Hash(<str>), [])",
            dstPath.c_str(), ((string) hash).c_str());
    }

    /* Packages are transformed into Derive fstate expressions. */
    if (ATmatch(e, "Package([<list>])", &bnds)) {

        /* Evaluate the bindings and put them in a map. */
        map<string, ATerm> bndMap;
        bndMap["platform"] = ATmake("<str>", SYSTEM);
        while (!ATisEmpty(bnds)) {
            ATerm bnd = ATgetFirst(bnds);
            if (!ATmatch(bnd, "(<str>, <term>)", &s1, &e1))
                throw badTerm("binding expected", bnd);
            bndMap[s1] = evalExpr(e1);
            bnds = ATgetNext(bnds);
        }

        /* Gather information for building the Derive expression. */
        ATermList ins = ATempty, env = ATempty;
        string builder, name;
        bnds = ATempty;

        for (map<string, ATerm>::iterator it = bndMap.begin();
             it != bndMap.end(); it++)
        {
            string key = it->first;
            ATerm value = it->second;

            string path = fstatePath(value);
            if (path != "") {
                ins = ATinsert(ins, value);
                env = ATinsert(env, ATmake("(<str>, <str>)",
                    key.c_str(), path.c_str()));
                if (key == "build") builder = path;
            }
            else if (ATmatch(value, "<str>", &s1)) {
                if (key == "name") name = s1;
                env = ATinsert(env,
                    ATmake("(<str>, <str>)", key.c_str(), s1));
            }
            else throw badTerm("invalid package argument", value);

            bnds = ATinsert(bnds,
                ATmake("(<str>, <term>)", key.c_str(), value));
        }

        /* Hash the normal form to produce a unique but deterministic
           path name for this package. */
        ATerm nf = ATmake("Package(<term>)", ATreverse(bnds));
        Hash hash = hashTerm(nf);

        if (builder == "")
            throw badTerm("no builder specified", nf);

        if (name == "")
            throw badTerm("no package name specified", nf);

        string out =
            canonPath(nixStore + "/" + ((string) hash).c_str() + "-" + name);

        env = ATinsert(env, ATmake("(<str>, <str>)", "out", out.c_str()));

        /* Construct the result. */
        e = ATmake("Derive(<str>, <str>, <term>, <str>, <term>)",
            SYSTEM, builder.c_str(), ins, out.c_str(), env);

        /* Write the resulting term into the Nix store directory. */
        Hash eHash = writeTerm(e, "-d-" + name);

        return ATmake("Include(<str>)", ((string) eHash).c_str());
    }

    /* BaseName primitive function. */
    if (ATmatch(e, "BaseName(<term>)", &e1)) {
        e1 = evalExpr(e1);
        if (!ATmatch(e1, "<str>", &s1))
            throw badTerm("string expected", e1);
        return ATmake("<str>", baseNameOf(s1).c_str());
    }

    /* Barf. */
    throw badTerm("invalid expression", e);
}

static Strings searchPath;

static Expr evalFile(string fileName)
{
    Expr e = ATreadFromNamedFile(fileName.c_str());
    if (!e) throw Error(format("cannot read aterm `%1%'") % fileName);
    return evalExpr(e);
}

void run(Strings args)
{
    Strings files;

    searchPath.push_back(".");

    for (Strings::iterator it = args.begin();
         it != args.end(); )
    {
        string arg = *it++;

        if (arg == "--includedir" || arg == "-I") {
            if (it == args.end())
                throw UsageError(format("argument required in `%1%'") % arg);
            searchPath.push_back(*it++);
        }
        else if (arg[0] == '-')
            throw UsageError(format("unknown flag `%1%`") % arg);
        else
            files.push_back(arg);
    }

    if (files.empty()) throw UsageError("no files specified");

    for (Strings::iterator it = files.begin();
         it != files.end(); it++)
    {
        Expr e = evalFile(*it);
        char * s;
        if (ATmatch(e, "Include(<str>)", &s)) {
            cout << format("%1%\n") % s;
        }
        else throw badTerm("top level is not a package", e);
    }
}

string programId = "fix";
<commit_msg>* Actually go through the search directories when looking for files.<commit_after>#include <map>
#include <iostream>

#include "globals.hh"
#include "fstate.hh"
#include "store.hh"
#include "shared.hh"

typedef ATerm Expr;

static Strings searchDirs;

static string searchPath(string relPath)
{
    for (Strings::iterator i = searchDirs.begin();
         i != searchDirs.end(); i++)
    {
        string path = *i + "/" + relPath;
        if (pathExists(path)) return path;
    }

    throw Error(
        format("path `%1%' not found in any of the search directories")
        % relPath);
}

static Expr evalFile(string fileName);

static Expr substExpr(string x, Expr rep, Expr e)
{
    char * s;
    Expr e2;

    if (ATmatch(e, "Var(<str>)", &s))
        if (x == s)
            return rep;
        else
            return e;

    if (ATmatch(e, "Lam(<str>, <term>)", &s, &e2))
        if (x == s)
            return e;
    /* !!! unfair substitutions */

    /* Generically substitute in subterms. */

    if (ATgetType(e) == AT_APPL) {
        AFun fun = ATgetAFun(e);
        int arity = ATgetArity(fun);
        ATermList args = ATempty;

        for (int i = arity - 1; i >= 0; i--)
            args = ATinsert(args, substExpr(x, rep, ATgetArgument(e, i)));

        return (ATerm) ATmakeApplList(fun, args);
    }

    if (ATgetType(e) == AT_LIST) {
        ATermList in = (ATermList) e;
        ATermList out = ATempty;

        while (!ATisEmpty(in)) {
            out = ATinsert(out, substExpr(x, rep, ATgetFirst(in)));
            in = ATgetNext(in);
        }

        return (ATerm) ATreverse(out);
    }

    throw badTerm("do not know how to substitute", e);
}

static Expr substExprMany(ATermList formals, ATermList args, Expr body)
{
    char * s;
    Expr e;

    /* !!! check args against formals */

    while (!ATisEmpty(args)) {
        ATerm tup = ATgetFirst(args);
        if (!ATmatch(tup, "(<str>, <term>)", &s, &e))
            throw badTerm("expected an argument tuple", tup);

        body = substExpr(s, e, body);

        args = ATgetNext(args);
    }

    return body;
}

static Expr evalExpr(Expr e)
{
    char * s1;
    Expr e1, e2, e3, e4;
    ATermList bnds;

    /* Normal forms. */
    if (ATmatch(e, "<str>", &s1) ||
        ATmatch(e, "Function([<list>], <term>)", &e1, &e2))
        return e;

    if (fstatePath(e) != "") return e; /* !!! hack */

    /* Application. */
    if (ATmatch(e, "App(<term>, [<list>])", &e1, &e2)) {
        e1 = evalExpr(e1);
        if (!ATmatch(e1, "Function([<list>], <term>)", &e3, &e4))
            throw badTerm("expecting a function", e1);
        return evalExpr(substExprMany((ATermList) e3, (ATermList) e2, e4));
    }

    /* Fix inclusion. */
    if (ATmatch(e, "IncludeFix(<str>)", &s1)) {
        string fileName(s1);
        return evalFile(s1);
    }

    /* Relative files. */
    if (ATmatch(e, "Relative(<str>)", &s1)) {
        string srcPath = searchPath(s1);
        string dstPath;
        Hash hash;
        addToStore(srcPath, dstPath, hash);
        return ATmake("Path(<str>, Hash(<str>), [])",
            dstPath.c_str(), ((string) hash).c_str());
    }

    /* Packages are transformed into Derive fstate expressions. */
    if (ATmatch(e, "Package([<list>])", &bnds)) {

        /* Evaluate the bindings and put them in a map. */
        map<string, ATerm> bndMap;
        bndMap["platform"] = ATmake("<str>", SYSTEM);
        while (!ATisEmpty(bnds)) {
            ATerm bnd = ATgetFirst(bnds);
            if (!ATmatch(bnd, "(<str>, <term>)", &s1, &e1))
                throw badTerm("binding expected", bnd);
            bndMap[s1] = evalExpr(e1);
            bnds = ATgetNext(bnds);
        }

        /* Gather information for building the Derive expression. */
        ATermList ins = ATempty, env = ATempty;
        string builder, name;
        bnds = ATempty;

        for (map<string, ATerm>::iterator it = bndMap.begin();
             it != bndMap.end(); it++)
        {
            string key = it->first;
            ATerm value = it->second;

            string path = fstatePath(value);
            if (path != "") {
                ins = ATinsert(ins, value);
                env = ATinsert(env, ATmake("(<str>, <str>)",
                    key.c_str(), path.c_str()));
                if (key == "build") builder = path;
            }
            else if (ATmatch(value, "<str>", &s1)) {
                if (key == "name") name = s1;
                env = ATinsert(env,
                    ATmake("(<str>, <str>)", key.c_str(), s1));
            }
            else throw badTerm("invalid package argument", value);

            bnds = ATinsert(bnds,
                ATmake("(<str>, <term>)", key.c_str(), value));
        }

        /* Hash the normal form to produce a unique but deterministic
           path name for this package. */
        ATerm nf = ATmake("Package(<term>)", ATreverse(bnds));
        Hash hash = hashTerm(nf);

        if (builder == "")
            throw badTerm("no builder specified", nf);

        if (name == "")
            throw badTerm("no package name specified", nf);

        string out =
            canonPath(nixStore + "/" + ((string) hash).c_str() + "-" + name);

        env = ATinsert(env, ATmake("(<str>, <str>)", "out", out.c_str()));

        /* Construct the result. */
        e = ATmake("Derive(<str>, <str>, <term>, <str>, <term>)",
            SYSTEM, builder.c_str(), ins, out.c_str(), env);

        /* Write the resulting term into the Nix store directory. */
        Hash eHash = writeTerm(e, "-d-" + name);

        return ATmake("Include(<str>)", ((string) eHash).c_str());
    }

    /* BaseName primitive function. */
    if (ATmatch(e, "BaseName(<term>)", &e1)) {
        e1 = evalExpr(e1);
        if (!ATmatch(e1, "<str>", &s1))
            throw badTerm("string expected", e1);
        return ATmake("<str>", baseNameOf(s1).c_str());
    }

    /* Barf. */
    throw badTerm("invalid expression", e);
}

static Expr evalFile(string relPath)
{
    Expr e = ATreadFromNamedFile(searchPath(relPath).c_str());
    return evalExpr(e);
}

void run(Strings args)
{
    Strings files;

    searchDirs.push_back(".");

    for (Strings::iterator it = args.begin();
         it != args.end(); )
    {
        string arg = *it++;

        if (arg == "--includedir" || arg == "-I") {
            if (it == args.end())
                throw UsageError(format("argument required in `%1%'") % arg);
            searchDirs.push_back(*it++);
        }
        else if (arg[0] == '-')
            throw UsageError(format("unknown flag `%1%`") % arg);
        else
            files.push_back(arg);
    }

    if (files.empty()) throw UsageError("no files specified");

    for (Strings::iterator it = files.begin();
         it != files.end(); it++)
    {
        Expr e = evalFile(*it);
        char * s;
        if (ATmatch(e, "Include(<str>)", &s)) {
            cout << format("%1%\n") % s;
        }
        else throw badTerm("top level is not a package", e);
    }
}

string programId = "fix";
<|endoftext|>