// $Id: range.h,v 1.50 2018/01/03 21:33:04 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 */


//------------------------------------------------------------------------------------
// General comments about the meanings of terms as they apply to the Biglink versus Littlelink implementations.
//------------------------------------------------------------------------------------
//
// Classes "Range" and "RecRange" implement an ordered set of half-open intervals of "Links".  Both obey the same
// convention of being half-open intervals (closed at the lower end and open at the upper end).  RecRange objects
// are meant to be embedded within branches which allow for the possibility of recombination events.  Range objects
// (the base class) handle non-recombination-only events.
//
// RecRanges track two different ranges, the active sites and the newly-active sites, plus derived quantities,
// the active Links and newly-active Links.
//
// These classes provide getter/setter pairs for all of their internal variables.
//
// Range provides IsSiteLive() which answers whether the passed site is active on the owning branch.
//
// Range and RecRange also provide a set of virtual functions (1 per force) for handling active
// and newly-active site management during rearrangement.  These functions are currently:
//    UpdateCRange(), UpdateOneLeggedCRange(), UpdateMRange(), UpdateRootRange(),
//    UpdateOneLeggedRootRange(), and UpdateRRange().
//
// In RecRange objects, a LINK represents generically an inter-site span of genomic information.
// Specifically, in the Littlelink implementation, a LINK is the span connecting ADJACENT SITES.
// In the Biglink implementation, a LINK is the span connecting adjacent VARIANT SITES, where "variant"
// also includes any site denoted as a "disease" site.
//
// When the Biglink optimization is enabled, recombination is modeled as happening in the middle of the Biglink
// (no matter where it "really" happens) as an approximation, since the available data suffice only to tell that
// it happened between two particular variant sites (that is, "somewhere inside" a given Biglink).  Transmitted
// sites are calculated based on splitting the possible sites by that "fictitious" midpoint.
//
// Note that the word "Link" in any context (by itself in a comment or as part of a function or variable name)
// always means "Biglink" (interval between variant sites) if the Biglink optimization is enabled or "Littlelink"
// (single link between adjacent sites) if the Biglink optimization is NOT enabled.  If the Biglink optimization
// IS enabled but the implementation is emulating Littlelinks, then the two meanings are synomomous (the native
// implementation is Biglinks, but each Biglink is modeling a single Littlelink via a degenerate Biglink Map).
//
// A RANGESET is an ordered set of PAIRs of LONG INTs.  In each pair, the first element is the start of a group
// of objects (Sites or Links), and the second element is one past the lower end of that group.  So for example,
// you could express the idea that sites 1 - 10 and 15 - 19 are active with a rangeset containing (1 - 11), (15 - 20).
//
// A LINKRANGESET is an ordered set of PAIRs of UNSIGNED LONG INTs.  Same as for a rangeset, except that
// this type is defined to work only with Links (rather than Sites).
//
// However, the meaning of those integer pairs is different in the Biglink versus Littlelink case.  For Littlelinks,
// they are Littlelink indices denoting the interval of Littlelinks (ie, index of the lowest included Littlelink
// at the low end and index of the first excluded Littlelink at the high end).  For Biglinks, they are Biglink Map
// indices, that is, indices into the Biglink Vector Map whose stored values at that entry represent the Littlelink
// indices (again, as a half-open interval).  Each entry in the Map represents a single Biglink, and therefore a
// RANGPAIR of Biglink indices represents a SET of Map entries and thus a SET of Biglinks (each one in turn
// representing an interval of Littlelinks).  Within a single LINKRANGEPAIR representing an interval of Biglinks,
// the Littlelinks encompassed by those Biglinks will be contiguous.
//
// So the generic term "LINK" always denotes an interval of genomic information, represented as a half-open interval
// of indices.  In the Littlelink model, LINK means Littlelink exactly (the prior meaning of the word throughout
// Lamarc).  In the Biglink model, it means a Biglink (a contiguous interval of Littlelinks bounded by variant or
// disease sites), and it represents a genomic region over which recombination is detectable in the data.
//
// A Biglink integer conveys the same information but via one level of indirection: it indicates an INDEX
// into the Biglink Vector Map, each of whose entries (valid while processing a single region but changed
// between processing of different regions) is an object of class BiglinkMapitem, which in turn contains
// three items of information:
//
//   1. The index of the LOWER-bound Littlelink INCLUDED in the represented Biglink.
//
//   2. The index of the UPPER-bound Littlelink (the first one EXCLUDED) at the upper end of the represented
//      Biglink.  Note that (by coincidence) this index is numerically equal to the index of the upper-bounding
//      SITE of the interval included in that Biglink.
//
//   3. The "weight" of the current Biglink, which currently is simply a double-float number whose value is
//      a count of the number of Littlelinks included in the current Biglink's span.  Later this simple count
//      of spanned Littlelinks will be generalized to weight each by a possibly non-uniform recombination
//      probability, allowing the Biglink system to represent recombination hotspots and other variations.
//
//   "m_curTargetLinks" is a LINKRANGESET of links currently targetable - Littlelinks in one implementation and
//   Biglinks (indices into the Biglink Vector Map) in the other, but in BOTH implementations this variable
//   denotes a LINKRANGESET of spans of the genome in which recombination can happen.
//
//   "GetAllLinks()" is a member function which returns a LINKRANGESET of Links, of either type as appropriate
//   for the particular implementation (ie, Littlelinks implementation: a LINKRANGESET of indices of Littlelinks;
//   Biglink implementation: a LINKRANGESET of indices of BiglinkMapitem class objects in the Biglink Vector Map).
//
//   "GetNewTargetLinks()" is a member function which returns a LINKRANGESET of Links, again, as appropriate
//   for the particular implementation.
//
//   "m_curTargetLinkweight" is a "Linkweight" of links currently targetable, where "Linkweight" is defined
//   via a typedef to be a long int (count of Littlelinks currently targetable) in one implementation and a
//   double-float (sum of all currently targetable Biglinks) in the other.
//
// RSGNOTE (not relevant to anything about BigLinks; just put here to avoid losing the idea): Perhaps precision
// with respect to time can be attained by changing some usages of TIME from FLOAT to LONG INT, whose values,
// unlike floats, are EXACT (as long as they remain in range).
//
//------------------------------------------------------------------------------------

#ifndef RANGE_H
#define RANGE_H

#include <algorithm>
#include <cassert>
#include <iostream>
#include <cstdlib>

#include "local_build.h"

#include "constants.h"
#include "rangex.h"

class Region;

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

#ifdef RUN_BIGLINKS

// Used to indicate zero Biglink weight in Biglink system.
#define ZERO 0.0
#define FLAGFAULTY FLAGDOUBLE

#include <set>

class BiglinkMapitem;

// Typedef for the Biglink Associative Set object (temporary object used to build the Biglink Vector Map).
typedef   std::set < long int, std::less < long int > >   BiglinkAssocSet;

// Typedef for the Biglink Vector Map object (held by static member variable in class RecRange).
typedef   std::vector < BiglinkMapitem >   BiglinkVectormap;

// Type for recombination weights in Biglink system.
typedef   double   Linkweight;


//------------------------------------------------------------------------------------
// Class BiglinkMapitem.
//------------------------------------------------------------------------------------
// Class used to represent objects describing spans of Littlelinks in the Biglink Vector Map.
// This class contains, and its accessor functions return, Littlelinks, which are declared
// as type LONG INT.  We reserve UNSIGNED LONG INT for Biglink object indicators, ie, indices
// into the BiglinkVectormap.

class BiglinkMapitem
{
  private:

    BiglinkMapitem();                           // Default constructor is undefined.

    // SITE just below lowermost Littlelink included at lower end of the interval.
    // Equivalently, lowermost Littlelink included at lower end of the interval.
    long int m_lower_littlelink;

    // SITE just above uppermost Littlelink INCLUDED at higher end of the interval.
    // Equivalently, lowermost Littlelink EXCLUDED at higher end of the interval.
    long int m_upper_littlelink;

    // Recombination probability (if it varies, else 1.0) over interval represented by this Biglink.
    double m_linkweight;

  public:

    // We accept the default (compiler-generated) COPY CONSTRUCTOR, ASSIGNMENT OPERATOR, and DESTRUCTOR.

    // The "real" constructor for class BiglinkMapitem.
    // Link arguments (first, second) refer to Littlelinks, and hence their type is SIGNED LONG INT.
    // We reserve UNSIGNED LONG INTs to refer to Biglink indices.
    BiglinkMapitem(long int lowerlink, long int upperlink, double linkweight);

    // Accessors.
    long int GetBiglinkLowerLittlelink() const { return m_lower_littlelink; };
    long int GetBiglinkUpperLittlelink() const { return m_upper_littlelink; };
    double   GetBiglinkWeight() const { return m_linkweight; };
};

#else // RUN_BIGLINKS

// Used to indicate zero Littlelink count or weight in Littlelink system.
#define ZERO 0L
#define FLAGFAULTY FLAGLONG

// Type for recombination weights (Littlelink counts) in Littlelink system.
typedef   long int   Linkweight;

#endif // RUN_BIGLINKS


//------------------------------------------------------------------------------------
// Class Range.
//------------------------------------------------------------------------------------
// Base class used to represent non-recombinant Ranges and as superclass for RecRange class.

class Range
{
  private:

    Range();                              // Default constructor is undefined.
    Range & operator=(const Range & src); // Assignment operator is undefined.

    // No processing is done by Range except to present total number of sites.
    // This is used when there is no recombination.

  protected:

    // Information about permanent state (they are data-dependent and never change).
    // In a non-recombinant Range, ALL sites are LIVE sites; they pass through every node and reach every tip.
    // Value of this variable is fixed for all Ranges (and RecRanges) within a Region, and Range objects
    // are valid only within a single Region at a time anyway.  This variable is initialized to FLAGLONG
    // at program startup and then reset to the correct value for each Region when process enters a new
    // Region (same time that the Biglink Map is built for a new Region, if Biglinks are enabled).
    // Note that this number includes sites within all Loci in the region plus sites in all inter-locus
    // areas, for which recombination must be modeled even though we have no data for these sites.
    static long int s_numRegionSites;

    Range(const Range & src);           // Copy constructor is callable only by Range::Clone and RecRange copy CTORs.

    rangeset GetAllSites() const { assert(s_numRegionSites > 0L); return MakeRangeset(0L, s_numRegionSites); };

  public:

    // Setter, for resetting this protected static variable when starting processing of a new region.
    // Static: Sets static variable but may be called before any Range objects are created.
    // This is declaration only; definition is in "range.cpp" because it needs "region.h", but
    // including that here would cause a circular dependency.
    static void SetNumRegionSites(const Region & curregion);

    // Setter, for setting this protected static variable when reading in an ARG tree.
    // This is used ONLY when reading in an ARG tree.  Use ANYWHERE ELSE is likely DISASTROUS.
    // This would not need to be STATIC were it not merely an overloaded definition of STATIC function above.
    // RSGNOTE: Commented out by JMcGill - test whether still called.
#if 0
    static void SetNumRegionSites(long int totalsites)  {s_numRegionSites = totalsites; };
#endif

    // "explicit" to prevent accidental type conversion via assignment.
    //
    // RSGNOTE:  The argument "nsites" is not really needed, because its value can only be "s_numRegionSites".
    // I've left it unchanged to minimize upsetting the interface when going from Littlelink to Biglink
    // version.  A later optimization could remove this argument.
    explicit Range(long int nsites);    // The "real" constructor.

    // Destructor.
    //
    // We accept an empty destructor, which does nothing other than to call the destructor for each
    // element (STL object) needing deallocation.  Even though it is empty, we need to declare it
    // and define it so we can make it VIRTUAL (the compiler default destructor is NON-virtual).
    virtual ~Range() {};

    // Clone serves as a polymorphic copy constructor (handles memory allocation and returns a pointer).
    virtual Range * Clone() const;

    // Getter, inherited and used by both Range and RecRange (only such function).
    long int GetNumRegionSites() const { assert(s_numRegionSites > 0L); return s_numRegionSites; };

    // Tests.
    virtual bool operator==(const Range & other)     const;
    virtual bool SameLiveSites(const rangeset &)     const { return true; };
    virtual bool LiveSitesOnly()                     const { return true; };
    virtual bool IsSiteLive(long int)                const { return true; };

    // Getters.
    // Functions which ASSERT here are defined to return a RANGESET (or LINKRANGESET) simply to satisfy the compiler
    // on return type.  They should never be called; hence we don't care what the rangeset they "return" contains.
    virtual rangeset     GetLiveSites()            const { return GetAllSites(); };
    virtual rangeset     GetDiseaseSites()         const { assert(false); return rangeset(); };
    virtual linkrangeset GetCurTargetLinks()       const { assert(false); return linkrangeset(); };
    virtual linkrangeset GetNewTargetLinks()       const { assert(false); return linkrangeset(); };
    virtual linkrangeset GetOldTargetLinks()       const { assert(false); return linkrangeset(); };
    virtual Linkweight   GetCurTargetLinkweight()  const { assert(false); return FLAGFAULTY; };
    virtual Linkweight   GetNewTargetLinkweight()  const { assert(false); return FLAGFAULTY; };
    virtual rangeset     GetOldTargetSites()       const { assert(false); return rangeset(); };
    virtual rangeset     GetOldLiveSites()         const { assert(false); return rangeset(); };
    virtual rangeset     GetTransmittedSites()     const { assert(false); return rangeset(); };
    virtual long int     GetRecpoint()             const { assert(false); return FLAGLONG; };

    // Updaters.
    // The following six functions all are NO-OPs on Range objects.
    // They change member variables only on RecRange objects.
    virtual void UpdateCRange(const Range * const child1rangeptr, const Range * const child2rangeptr,
                              const rangeset & fcsites, bool dofc);
    virtual void UpdateRootRange(const Range * const child1rangeptr, const Range * const child2rangeptr,
                                 const rangeset & fcsites, bool dofc);
    virtual void UpdateOneLeggedCRange(const Range * const childrangeptr);
    virtual void UpdateOneLeggedRootRange(const Range * const childrangeptr);
    virtual void UpdateMRange(const Range * const childrangeptr);
    virtual void UpdateRRange(const Range * const childrangeptr, const rangeset & fcsites, bool dofc);

    virtual bool AreLowSitesOnInactiveBranch(long int) const
    { assert(false); return false; };

    virtual bool AreDiseaseSitesTransmitted() const { return true; };

    // Used by RecTree::Prune and Branch::ResetBuffersForNextRearrangement.
    virtual void ClearNewTargetLinks();
    virtual void SetOldInfoToCurrent();
    virtual void ResetOldTargetSites(const rangeset & fcsites);

    // Used by RBranch::IsRemovableRecombinationLeg (ASSERTs on Range object).
    virtual bool AreChildTargetSitesTransmitted(const Range * const childrangeptr, const rangeset & fcsites) const;

    // Used in revalidation to compare a branch to its child.
    virtual bool SameAsChild(const Range * const childrangeptr) const;

    // Debugging functions for Range and RecRange (virtual).
    virtual void PrintLive() const;
    virtual void PrintInfo() const;
    virtual void PrintNewTargetLinks() const;
    virtual bool NoLiveAndNoTransmittedDiseaseSites() const { return false; };
    virtual bool DifferentCurTargetLinks(const linkrangeset &) const { return false; };
    virtual bool DifferentNewTargetLinks(const linkrangeset &) const { return false; };

};


//------------------------------------------------------------------------------------
// Class RecRange
//------------------------------------------------------------------------------------
// Derived class used to represent recombinant Ranges.
// Full recombinant processing is done by RecRange.
//
// The member variable whose name starts with "s_..." is STATIC (value is a BiglinkVectormap object).
//
// Member variables whose names end with "...Linkweight" have Linkweight numbers as their values (double for Biglink,
// long int for Littlelink); the value is the accumulated weight (count for Littlelinks) summed over all Links.
//
// In the future (in Biglink implementation), a location-dependent recombination probability will weight
// the Littlelinks in this summation.  Currently, that probability is flat with a unity weighting.  Thus
// double-float weight sums (for Biglink system) and long int Littlelink counts (for Littlelink system)
// are equivalent numerically (aside from double-vs-int datatypes).
//
// The rest of the member variables have values which are a RANGESET (a set of PAIRs of LONG INTs representing SITEs)
// or a LINKRANGESET (a set of PAIRs of UNSIGNED LONG INTs representing Links - either Biglinks or Littlelinks,
// depending on the system enabled) where the integer values denote a half-open (inclusive start, exclusive end)
// interval of Link indices.  For the Biglink system, these are BiglinkMapitem indices; for the Littlelink system,
// they are Littlelink indices.

class RecRange : public Range
{
  private:

    RecRange();                         // Default constructor is undefined.
    RecRange(const RecRange & src);     // Copy constructor is callable only by RecRange::Clone.
    RecRange & operator=(const RecRange & src); // Assignment operator is undefined.

#ifdef RUN_BIGLINKS
    static BiglinkVectormap s_biglink_vectormap;
#endif

    // LIVE sites pass through the branch holding this RecRange and reach one or more tips.
    rangeset m_liveSites;               // Sites currently live (transmitted from here to at least one tip).

    rangeset m_diseaseSites;            // Locations (SITEs) of all disease traits.
    rangeset m_transmittedSites;        // Sites transmitted through this branch.

    // "m_curTargetLinks" are legal targets (Links) for recombination (variable during life of a RecRange object).
    // Remember that in Biglink system, "Links" means "Biglinks"; in Littlelink system, "Links" means "Littlelinks".
    linkrangeset m_curTargetLinks;      // Links currently targetable.
    Linkweight m_curTargetLinkweight;   // Weight of Links currently targetable.

    // Stored so that recombinations that result from "m_newTargetLinks" can be handled reversibly.
    // Modified by recombinations in RecRange.
    rangeset m_oldTargetSites;          // Sites that framed targetable Links when tree last created/modified.
    rangeset m_oldLiveSites;            // Sites that were live when this tree was last created/modified.

    // "m_oldTargetLinks" were targetable before rearrangement began.
    // Modified in by recombinations in RecRange.
    linkrangeset m_oldTargetLinks;      // Links previously targetable.

    // "m_newTargetLinks" were not legal targets before rearrangement began, but have become legal.
    linkrangeset m_newTargetLinks;      // Links newly targetable; m_curTargetLinks - m_oldTargetLinks.
    Linkweight m_newTargetLinkweight;   // Weight of Links newly targetable.

  public:

#ifdef RUN_BIGLINKS
    // Builds map from inter-site Littlelinks to recombination-visible Biglinks.
    // Static member function (RecRange-only, but may be called before first object is created).
    static void BuildBiglinkMap(const Region & curregion);
    //
    // Static member function (gives access to Biglink Map from outside class; independent of RecRange objects).
    static BiglinkVectormap GetBiglinkVectormap() { return s_biglink_vectormap; };
#endif

    // NOTA BENE: The meaning of "GetAllLinks" is different for Littlelinks vs Biglinks.
    // For Littlelinks, the function returns the LINKRANGESET containing ALL links between the first and last site.
    // For Biglinks, it returns a LINKRANGESET denoting all the Biglinks between the first and last site, but such
    // Biglinks MIGHT NOT EXTEND down to the lowest and/or up to the highest site (and, in general, they WON'T,
    // unless both end sites happen to be either disease or variant sites).  In other words, for Biglinks,
    // it returns the set denoting all possible Biglinks, even though the Littlelinks directly spanned by that
    // set of Biglinks might not include all sites out to the very ends.
    //
    // Also, corresponding to the difference between Littlelinks and Biglinks, a Littlelink is denoted directly
    // by a SITE index (that of the site to its "left"), while a Biglink is denoted by the index in the
    // Biglink Vector Map of BiglinkMapitem object describing an interval of Littlelinks.
    //
#ifdef RUN_BIGLINKS
    // Returns a LINKRANGESET of all indices in the Biglink Vector Map.  This is a static member function;
    // it needs access to the Biglink Vector Map, but it is otherwise independent of RecRange objects.
    // Also, it could be called before the first RecRange object is created.
    // For each Region, this may be called only after BuildBiglinkMap() has built the map.
    // Second argument to MakeRangeset is EXCLUDED endpoint; size of Map is how many Biglinks are in the set.
    static linkrangeset GetAllLinks() { return MakeRangeset(0UL, s_biglink_vectormap.size()); };
#else
    // Simply returns a LINKRANGESET of all links (ie, those BETWEEN the first and last site,
    // NOT including the non-existent "link" after the last site).
    // Second argument to MakeRangeset is EXCLUDED endpoint; "s_numRegionSites - 1" is how many Littlelinks are in the set.
    static linkrangeset GetAllLinks() { assert(s_numRegionSites > 0L); return MakeRangeset(0UL, s_numRegionSites - 1UL); };
#endif

    // The "real" constructor.
    // Note that args 5 and 6 are "Link" linkrangesets (Biglink or Littlelink, depending on system).
    RecRange(long int nsites, const rangeset & diseasesites,
             const rangeset & transmittedsites, const rangeset & livesites,
             const linkrangeset & curtargetlinks, const linkrangeset & oldtargetlinks,
             const rangeset & oldtargetsites, const rangeset & oldlivesites);

    // Destructor
    // We accept an empty destructor, which does nothing other than to call the destructor for each
    // element (STL object) needing deallocation.  Even though it is empty, we need to declare it
    // and define it so we can make it VIRTUAL (the compiler default destructor is NON-virtual).
    virtual ~RecRange() {};

    // Clone serves as a polymorphic copy constructor (handles memory allocation and returns a pointer).
    virtual Range * Clone() const;

    // Tests.
    virtual bool operator==(const Range & other)     const;
    virtual bool SameLiveSites(const rangeset & src) const { return m_liveSites == src; };
    virtual bool LiveSitesOnly()                     const { return false; };
    virtual bool IsSiteLive(long int site)           const { return IsInRangeset(m_liveSites, site); };

    // Getters.
    virtual rangeset     GetLiveSites()            const { return m_liveSites; };
    virtual rangeset     GetDiseaseSites()         const { return m_diseaseSites; };
    virtual linkrangeset GetCurTargetLinks()       const { return m_curTargetLinks; };
    virtual linkrangeset GetNewTargetLinks()       const { return m_newTargetLinks; };
    virtual linkrangeset GetOldTargetLinks()       const { return m_oldTargetLinks; };
    virtual Linkweight   GetCurTargetLinkweight()  const { return m_curTargetLinkweight; };
    virtual Linkweight   GetNewTargetLinkweight()  const { return m_newTargetLinkweight; };
    virtual rangeset     GetOldTargetSites()       const { return m_oldTargetSites; };
    virtual rangeset     GetOldLiveSites()         const { return m_oldLiveSites; };
    virtual rangeset     GetTransmittedSites()     const { return m_transmittedSites; };
    virtual long int     GetRecpoint()             const;

    // Setters
    // This is used ONLY when reading in an ARG tree.  Use ANYWHERE ELSE is likely DISASTROUS.
#if 0 // RSGNOTE:  Unused so far; reserved for future expansion in ARGtree hackery.
    virtual void SetLiveSites(rangeset livesites)  {m_liveSites = livesites; };
#endif

    // Updaters.
    // The following six functions modify a RecRange to reflect tipward changes during rearrangement,
    // including modifying m_liveSites, m_curTargetLinks, and m_newTargetLinks plus their respective counts.
    virtual void UpdateCRange(const Range * const child1rangeptr, const Range * const child2rangeptr,
                              const rangeset & fcsites, bool dofc);
    virtual void UpdateRootRange(const Range * const child1rangeptr, const Range * const child2rangeptr,
                                 const rangeset & fcsites, bool dofc);
    virtual void UpdateOneLeggedCRange(const Range * const childrangeptr);
    virtual void UpdateOneLeggedRootRange(const Range * const childrangeptr);
    virtual void UpdateMRange(const Range * const childrangeptr);
    virtual void UpdateRRange(const Range * const childrangeptr, const rangeset & fcsites, bool dofc);

    // When placing an inactive (hidden passages) recombination, should the branch that remains
    // in the residual tree carry the low-numbered sites (as opposed to the high-numbered sites)?
    virtual bool AreLowSitesOnInactiveBranch(long int recpoint) const;

    virtual bool AreDiseaseSitesTransmitted() const;

    // Used by RecTree::Prune and Branch::ResetBuffersForNextRearrangement.
    virtual void ClearNewTargetLinks();
    virtual void SetOldInfoToCurrent();
    virtual void ResetOldTargetSites(const rangeset & fcsites);

    // Used in RBranch::IsRemovableRecombinationLeg (recombinant case only).
    virtual bool AreChildTargetSitesTransmitted(const Range * const childrangeptr, const rangeset & fcsites) const;

    // Used in revalidation to compare a branch to its child; does not require m_transmittedSites to match.
    virtual bool SameAsChild(const Range * const childrangeptr) const;

    // Utility functions, RecRange only.

    // Static member function (Biglink version needs access to the Biglink Vector Map).
    static Linkweight AccumulatedLinkweight(const linkrangeset & setoflinks);

    // Biglink version returns a LINKRANGESET of Biglinks spanning lowest to highest target site (including Disease sites).
    // Static member function (needs access to the Biglink Vector Map).
    //
    // Littlelink version returns a LINKRANGESET of Littlelinks.
    // Needs no access to statics, but declared static for calling consistency with one just above.
    //
    // Both versions have same declaration, but function definitions have different semantics.
    static linkrangeset LinksSpanningSites(const rangeset & targetsites);

    virtual bool NoLiveAndNoTransmittedDiseaseSites() const
    { return (m_liveSites.empty() && !AreDiseaseSitesTransmitted()); };

    virtual bool DifferentCurTargetLinks(const linkrangeset & src) const { return m_curTargetLinks != src; };
    virtual bool DifferentNewTargetLinks(const linkrangeset & src) const { return m_newTargetLinks != src; };

    // Debugging functions for Range and RecRange (virtual).
    virtual void PrintLive() const;
    virtual void PrintInfo() const;
    virtual void PrintNewTargetLinks() const;

    // Utility function, RecRange only, used in above two functions.
    // Static member function; needs access to Biglink Vector Map but is otherwise independent of RecRange objects.
    static void PrintLinks(const linkrangeset & setoflinks);

    // Debugging functions for RecRange only.
    void PrintDiseaseSites() const;
    void PrintRightOrLeft()  const;
    void TestInvariants()    const;

};


//------------------------------------------------------------------------------------
// Helper debugging function at global scope.
//------------------------------------------------------------------------------------

#ifdef ENABLE_REGION_DUMP
void PrintRegionData(long int regionnum, const Region & curregion);
#endif // ENABLE_REGION_DUMP

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

#endif // RANGE_H

//____________________________________________________________________________________
