Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright (C) 2010 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  *
      8  * 1.  Redistributions of source code must retain the above copyright
      9  *     notice, this list of conditions and the following disclaimer.
     10  * 2.  Redistributions in binary form must reproduce the above copyright
     11  *     notice, this list of conditions and the following disclaimer in the
     12  *     documentation and/or other materials provided with the distribution.
     13  *
     14  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
     15  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     16  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     17  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     18  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     19  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     20  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
     21  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     24  */
     25 
     26 #ifndef PODIntervalTree_h
     27 #define PODIntervalTree_h
     28 
     29 #include "PODArena.h"
     30 #include "PODInterval.h"
     31 #include "PODRedBlackTree.h"
     32 #include <wtf/Assertions.h>
     33 #include <wtf/Noncopyable.h>
     34 #include <wtf/Vector.h>
     35 
     36 namespace WebCore {
     37 
     38 #ifndef NDEBUG
     39 template<class T>
     40 struct ValueToString;
     41 #endif
     42 
     43 // An interval tree, which is a form of augmented red-black tree. It
     44 // supports efficient (O(lg n)) insertion, removal and querying of
     45 // intervals in the tree.
     46 template<class T, class UserData = void*>
     47 class PODIntervalTree : public PODRedBlackTree<PODInterval<T, UserData> > {
     48     WTF_MAKE_NONCOPYABLE(PODIntervalTree);
     49 public:
     50     // Typedef to reduce typing when declaring intervals to be stored in
     51     // this tree.
     52     typedef PODInterval<T, UserData> IntervalType;
     53 
     54     PODIntervalTree()
     55         : PODRedBlackTree<IntervalType>()
     56     {
     57         init();
     58     }
     59 
     60     explicit PODIntervalTree(PassRefPtr<PODArena> arena)
     61         : PODRedBlackTree<IntervalType>(arena)
     62     {
     63         init();
     64     }
     65 
     66     // Returns all intervals in the tree which overlap the given query
     67     // interval. The returned intervals are sorted by increasing low
     68     // endpoint.
     69     Vector<IntervalType> allOverlaps(const IntervalType& interval) const
     70     {
     71         Vector<IntervalType> result;
     72         allOverlaps(interval, result);
     73         return result;
     74     }
     75 
     76     // Returns all intervals in the tree which overlap the given query
     77     // interval. The returned intervals are sorted by increasing low
     78     // endpoint.
     79     void allOverlaps(const IntervalType& interval, Vector<IntervalType>& result) const
     80     {
     81         // Explicit dereference of "this" required because of
     82         // inheritance rules in template classes.
     83         searchForOverlapsFrom(this->root(), interval, result);
     84     }
     85 
     86     // Helper to create interval objects.
     87     static IntervalType createInterval(const T& low, const T& high, const UserData data = 0)
     88     {
     89         return IntervalType(low, high, data);
     90     }
     91 
     92     virtual bool checkInvariants() const
     93     {
     94         if (!PODRedBlackTree<IntervalType>::checkInvariants())
     95             return false;
     96         if (!this->root())
     97             return true;
     98         return checkInvariantsFromNode(this->root(), 0);
     99     }
    100 
    101 private:
    102     typedef typename PODRedBlackTree<IntervalType>::Node IntervalNode;
    103 
    104     // Initializes the tree.
    105     void init()
    106     {
    107         // Explicit dereference of "this" required because of
    108         // inheritance rules in template classes.
    109         this->setNeedsFullOrderingComparisons(true);
    110     }
    111 
    112     // Starting from the given node, adds all overlaps with the given
    113     // interval to the result vector. The intervals are sorted by
    114     // increasing low endpoint.
    115     void searchForOverlapsFrom(IntervalNode* node, const IntervalType& interval, Vector<IntervalType>& res) const
    116     {
    117         if (!node)
    118             return;
    119 
    120         // Because the intervals are sorted by left endpoint, inorder
    121         // traversal produces results sorted as desired.
    122 
    123         // See whether we need to traverse the left subtree.
    124         IntervalNode* left = node->left();
    125         if (left
    126             // This is phrased this way to avoid the need for operator
    127             // <= on type T.
    128             && !(left->data().maxHigh() < interval.low()))
    129             searchForOverlapsFrom(left, interval, res);
    130 
    131         // Check for overlap with current node.
    132         if (node->data().overlaps(interval))
    133             res.append(node->data());
    134 
    135         // See whether we need to traverse the right subtree.
    136         // This is phrased this way to avoid the need for operator <=
    137         // on type T.
    138         if (!(interval.high() < node->data().low()))
    139             searchForOverlapsFrom(node->right(), interval, res);
    140     }
    141 
    142     virtual bool updateNode(IntervalNode* node)
    143     {
    144         // Would use const T&, but need to reassign this reference in this
    145         // function.
    146         const T* curMax = &node->data().high();
    147         IntervalNode* left = node->left();
    148         if (left) {
    149             if (*curMax < left->data().maxHigh())
    150                 curMax = &left->data().maxHigh();
    151         }
    152         IntervalNode* right = node->right();
    153         if (right) {
    154             if (*curMax < right->data().maxHigh())
    155                 curMax = &right->data().maxHigh();
    156         }
    157         // This is phrased like this to avoid needing operator!= on type T.
    158         if (!(*curMax == node->data().maxHigh())) {
    159             node->data().setMaxHigh(*curMax);
    160             return true;
    161         }
    162         return false;
    163     }
    164 
    165     bool checkInvariantsFromNode(IntervalNode* node, T* currentMaxValue) const
    166     {
    167         // These assignments are only done in order to avoid requiring
    168         // a default constructor on type T.
    169         T leftMaxValue(node->data().maxHigh());
    170         T rightMaxValue(node->data().maxHigh());
    171         IntervalNode* left = node->left();
    172         IntervalNode* right = node->right();
    173         if (left) {
    174             if (!checkInvariantsFromNode(left, &leftMaxValue))
    175                 return false;
    176         }
    177         if (right) {
    178             if (!checkInvariantsFromNode(right, &rightMaxValue))
    179                 return false;
    180         }
    181         if (!left && !right) {
    182             // Base case.
    183             if (currentMaxValue)
    184                 *currentMaxValue = node->data().high();
    185             return (node->data().high() == node->data().maxHigh());
    186         }
    187         T localMaxValue(node->data().maxHigh());
    188         if (!left || !right) {
    189             if (left)
    190                 localMaxValue = leftMaxValue;
    191             else
    192                 localMaxValue = rightMaxValue;
    193         } else
    194             localMaxValue = (leftMaxValue < rightMaxValue) ? rightMaxValue : leftMaxValue;
    195         if (localMaxValue < node->data().high())
    196             localMaxValue = node->data().high();
    197         if (!(localMaxValue == node->data().maxHigh())) {
    198 #ifndef NDEBUG
    199             String localMaxValueString = ValueToString<T>::string(localMaxValue);
    200             LOG_ERROR("PODIntervalTree verification failed at node 0x%p: localMaxValue=%s and data=%s",
    201                       node, localMaxValueString.utf8().data(), node->data().toString().utf8().data());
    202 #endif
    203             return false;
    204         }
    205         if (currentMaxValue)
    206             *currentMaxValue = localMaxValue;
    207         return true;
    208     }
    209 };
    210 
    211 #ifndef NDEBUG
    212 // Support for printing PODIntervals at the PODRedBlackTree level.
    213 template<class T, class UserData>
    214 struct ValueToString<PODInterval<T, UserData> > {
    215     static String string(const PODInterval<T, UserData>& interval)
    216     {
    217         return interval.toString();
    218     }
    219 };
    220 #endif
    221 
    222 } // namespace WebCore
    223 
    224 #endif // PODIntervalTree_h
    225