// $Id: rangex.h,v 1.24 2018/01/03 21:33:02 mkkuhner Exp $

/*
Copyright 2002-2005 Mary K. Kuhner, Peter Beerli, and Joseph Felsenstein

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

*/

/* Authors: Peter Beerli, Mary Kuhner, Jon Yamato and Joseph Felsenstein */


#ifndef RANGEX_H
#define RANGEX_H

#include <set>
#include <string>
#include <vector>

#include "local_build.h"

//------------------------------------------------------------------------------------

struct rangecmp
{
    bool operator()(const std::pair<long int, long int> & p1, const std::pair<long int, long int> & p2)
    {
        if (p1.first == p2.first)
        {
            return (p1.second < p2.second);
        }
        return (p1.first < p2.first);
    }
};

//-----------------------------------------

struct linkrangecmp
{
    bool operator()(const std::pair<unsigned long int, unsigned long int> & p1, const std::pair<unsigned long int, unsigned long int> & p2)
    {
        if (p1.first == p2.first)
        {
            return (p1.second < p2.second);
        }
        return (p1.first < p2.first);
    }
};

//------------------------------------------------------------------------------------

typedef std::pair<long int, long int>                         rangepair;
typedef std::vector<rangepair>                                rangevector;
typedef std::set<rangepair, rangecmp>                         rangeset;
typedef std::set<rangepair, rangecmp>::iterator               rangesetiter;
typedef std::set<rangepair, rangecmp>::const_iterator         rangesetconstiter;

typedef std::pair<unsigned long int, unsigned long int>       linkrangepair;
typedef std::vector<linkrangepair>                            linkrangevector;
typedef std::set<linkrangepair, linkrangecmp>                 linkrangeset;
typedef std::set<linkrangepair, linkrangecmp>::iterator       linkrangesetiter;
typedef std::set<linkrangepair, linkrangecmp>::const_iterator linkrangesetconstiter;

//------------------------------------------------------------------------------------

std::string ToString(rangepair rpair);
std::string ToString(rangeset rset);

std::string ToGraphMLString(rangepair rpair);
std::string ToGraphMLString(rangeset rset);

#ifndef RUN_BIGLINKS
std::string ToString(linkrangeset rset);
#endif // RUN_BIGLINKS

std::string ToStringUserUnits(rangepair rpair);
std::string ToStringUserUnits(rangeset rset);

//------------------------------------------------------------------------------------

rangepair     ToRangePair(std::string & instr);
rangeset      ToRangeSet(std::string & instr);

rangeset      MakeRangeset(signed long int low, signed long int high);
linkrangeset  MakeRangeset(unsigned long int low, unsigned long int high);

rangeset      AddPairToRange(const rangepair & addpart, const rangeset & rset);
linkrangeset  AddPairToRange(const linkrangepair & addpart, const linkrangeset & rset);

rangeset      RemovePairFromRange(const rangepair & removepart, const rangeset & rset);
linkrangeset  RemovePairFromRange(const linkrangepair & removepart, const linkrangeset & rset);

rangeset      RemoveRangeFromRange(const rangeset & removerange, const rangeset & rset);
linkrangeset  RemoveRangeFromRange(const linkrangeset & removerange, const linkrangeset & rset);

rangeset      Union(const rangeset & set1, const rangeset & set2);
void          ORAppend(rangepair newrange, rangeset & oldranges);

rangeset      Intersection(const rangeset & set1, const rangeset & set2);
long int      CountSites(const rangeset & rset);

#if 0 // Apparently unused.
rangeset      SubtractFromRangeset(const rangeset & rset, long int offset);
rangeset      AddToRangeset(const rangeset & rset, long int offset);
#endif

//------------------------------------------------------------------------------------

bool      IsInRangeset(const rangeset & targetrange, long int target);

#ifndef RUN_BIGLINKS
#if 0 // RSGDEBUG: Enabled for debugging but called (only on RecRange objects) in commented-out section of debugging function.
bool      IsInRangeset(const linkrangeset & targetrange, long int target);
#endif // RSGDEBUG
#endif // RUN_BIGLINKS

long int  ToSequentialIfNeeded(long int input);
long int  ToNoZeroesIfNeeded(long int input);
rangepair ToSequentialIfNeeded(rangepair input);
rangepair ToNoZeroesIfNeeded(rangepair input);

//------------------------------------------------------------------------------------

#endif // RANGEX_H

//____________________________________________________________________________________
