Program Listing for File CRSDistance.h

Return to documentation for file (include/gwmodelpp/spatialweight/CRSDistance.h)

#ifndef CRSDISTANCE_H
#define CRSDISTANCE_H

#include "Distance.h"

#ifdef ENABLE_CUDA
#include "gwmodelpp/utils/cumat.hpp"
#include "gwmodelpp/spatialweight/cuda/CRSDistanceKernel.h"
#include "gwmodelpp/spatialweight/cuda/ISpatialCudaEnabled.h"
#endif // ENABLE_CUDA

namespace gwm
{

class CRSDistance : public Distance
{
public:

    struct Parameter : public Distance::Parameter
    {
        arma::mat focusPoints;

        arma::mat dataPoints;

        Parameter(const arma::mat& fp, const arma::mat& dp) : Distance::Parameter()
            , focusPoints(fp)
            , dataPoints(dp)
        {
            total = fp.n_rows;
        }
    };

public:

    static arma::vec SpatialDistance(const arma::rowvec& out_loc, const arma::mat& in_locs);

    static arma::vec EuclideanDistance(const arma::rowvec& out_loc, const arma::mat& in_locs)
    {
        arma::mat diff = (in_locs.each_row() - out_loc);
        return sqrt(sum(diff % diff, 1));
    }

    static double SpGcdist(double lon1, double lon2, double lat1, double lat2);

private:
    typedef arma::vec (*CalculatorType)(const arma::rowvec&, const arma::mat&);
#ifdef ENABLE_CUDA
    typedef cudaError_t (*CalculatorCudaType)(const double*, const double*, size_t, size_t, double*);
#endif

public:

    CRSDistance() : mGeographic(false), mParameter(nullptr) {}

    explicit CRSDistance(bool isGeographic): mGeographic(isGeographic), mParameter(nullptr)
    {
        mCalculator = mGeographic ? &SpatialDistance : &EuclideanDistance;
#ifdef ENABLE_CUDA
        mCalculatorCuda = mGeographic ? &sp_dist_cuda : eu_dist_cuda;
#endif
    }

    CRSDistance(const CRSDistance& distance);

    virtual ~CRSDistance()
    {
    }

    virtual Distance * clone() const override
    {
        return new CRSDistance(*this);
    }

    DistanceType type() override { return DistanceType::CRSDistance; }

    bool geographic() const
    {
        return mGeographic;
    }

    void setGeographic(bool geographic)
    {
        mGeographic = geographic;
        mCalculator = mGeographic ? &SpatialDistance : &EuclideanDistance;
#ifdef ENABLE_CUDA
        mCalculatorCuda = mGeographic ? &sp_dist_cuda : eu_dist_cuda;
#endif
    }

public:

    virtual void makeParameter(std::initializer_list<DistParamVariant> plist) override;

    virtual arma::vec distance(arma::uword focus) override;
    virtual double maxDistance() override;
    virtual double minDistance() override;

#ifdef ENABLE_CUDA
    virtual cudaError_t prepareCuda(size_t gpuId) override;

    virtual cudaError_t distance(arma::uword focus, double* d_dists, size_t* elems) override;
#endif

protected:
    bool mGeographic;
    std::unique_ptr<Parameter> mParameter;

private:
    CalculatorType mCalculator = &EuclideanDistance;

#ifdef ENABLE_CUDA
    cumat mCudaDp;
    cumat mCudaFp;
    CalculatorCudaType mCalculatorCuda = &eu_dist_cuda;
#endif

};

}

#endif // CRSDISTANCE_H