// -*- LSST-C++ -*-


/*
 * this is a place for common math functions and handy declarations
 * used by the KDTree class. */

#ifndef LSST_KDTREE_COMMON_H
#define LSST_KDTREE_COMMON_H



#include <vector>
#include <cmath>

namespace KDTree {
    namespace Common {
        
        enum GeometryType {
            EUCLIDEAN,
            CIRCULAR_DEGREES,
            CIRCULAR_RADIANS
        };

        class Constants {
        public:
            double epsilon() { return 1.e-10; }; 
            double rad_to_deg()  { return 180./M_PI; };
            double deg_to_rad()  { return M_PI / 180.; };

        };

        /* O(n)-time implementation returns median value of fv */
        double fastMedian(std::vector<double> fv);

        void printDoubleVec(std::vector<double> fv);

        /* returns whether a, b are within epsilon of each other */
        bool areEqual(double a, double b);
        
        /* returns distance from p1 to p2, ASSUMES that p1 and p2 have
           size==dimensions*/
        double euclideanDistance(std::vector<double> p1, std::vector<double> p2, 
                                unsigned int dimensions);

        double distance1D(double a, double b, GeometryType geo);

        /* return the length of the shortest path from a to b, where a, b 
           are angles.*/
        double circularShortestPathLen_Deg(double a, double b);
        
        double circularShortestPathLen_Rad(double a, double b);

       /*
         * returns true iff the line segments aLo aHi and b1b2 overlap on the 1D
         * space of type GeometryType. 
         * 
         * for a circular space, we ASSUME that aLo is less than aHi, and aLo,
         * aHi may span up to 360 degrees (i.e., we always assume that aLo, aHi
         * does *not* cross 0).
         *
         * b1b2 is understood to be the shortest path * between b1 and b2.
         * E.g.:
         *
         * if aLo = 10, aHi = 310, then the length of aLo-aHi is 300.
         * if b1 = 10, b2 = 310, then the length of b1 to b2 is 60.
         *
         * This is useful for KDTreeNode hyperRectangle search; we have the data
         * partitioned by its numerical size as though euclidean; the searches
         * must be searching regions less than 180 degrees.
         */
        bool regionsOverlap1D(double aLo, double aHi, double b1, double b2, 
                              GeometryType type);
        
        /* for deg is any double value, return a value along [0, 369) */
        double convertToStandardDegrees(double deg);
        
        double minOfTwo(double a, double b);

        double maxOfTwo(double a, double b);
        
    }
}



#endif
