anchor.diff:          elements.ToArray ()
   
   
  -/// Defines methods which allow a type to be "measured".
  -type private IMeasurer<'T> =
  -    inherit System.Collections.Generic.IComparer<'T>
  -
  -    // "Predecessor"
  -    abstract Previous : x : 'T -> 'T
  -    // "Successor"
  -    abstract Next : x : 'T -> 'T
  -    /// A distance metric. Calculuates the "distance" from the second
  -    /// value to the first value (the ordering is important).
  -    abstract Distance : x : 'T * y : 'T -> int
  -
  -//
  -[<Struct>]
  -[<DebuggerDisplay("Min = {MinValue}, Max = {MaxValue}")>]
  -[<StructuredFormatDisplay("[{MinValue}, {MaxValue}]")>]
  -type private Range<'T when 'T : comparison> =
  -    //
  -    val MinValue : 'T
  -    //
  -    val MaxValue : 'T
  -
  -    //
  -    new (value) = {
  -        MinValue = value;
  -        MaxValue = value; }
  -
  -    //
  -    new (rangeMin, rangeMax) =
  -        // Preconditions
  -        if rangeMin > rangeMax then
  -            invalidArg "rangeMax" "The minimum range value cannot be greater than the maximum range value."
  -
  -        { MinValue = rangeMin;
  -          MaxValue = rangeMax; }
  -
  -    override this.ToString () =
  -        sprintf "[%O, %O]" this.MinValue this.MaxValue
  -
  -    //
  -    member this.ToSeq (measurer : IMeasurer<_>) =
  -        let maxValue = this.MaxValue
  -        let rec loop current = seq {
  -            if current <= maxValue then
  -                yield current
  -                yield! loop (measurer.Next current)
  -            }
  -
  -        loop this.MinValue
  -
  -/// A Discrete Interval Encoding Tree (DIET).
  -type private Diet<'T when 'T : comparison> =
  -    AvlTree<Range<'T>>
  -
  -/// Functional operations for DIETs.
  +/// Additional AVL tree operations needed to implement the DIET.
  +[<RequireQualifiedAccess; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
  +module private AvlDiet =
  +    open System.Collections.Generic
  +    open LanguagePrimitives
  +
  +    //
  +    let [<Literal>] balanceTolerance = 1u
  +
  +    /// Join two trees together at a pivot point, then balance the resulting tree.
  +    let private balance x l (r : AvlTree<'T>) =
  +        let hl = AvlTree.height l
  +        let hr = AvlTree.height r
  +        if hl > hr + balanceTolerance then
  +            match l with
  +            | Empty ->
  +                invalidArg "AvlTree.balance" "The left subtree is empty."
  +            | Node (lvx, ll, lr, _) ->
  +                if AvlTree.height ll >= AvlTree.height lr then
  +                    AvlTree.create lvx ll (AvlTree.create x lr r)
  +                else
  +                    match lr with
  +                    | Empty ->
  +                        invalidArg "AvlTree.balance" "The right subtree is empty."
  +                    | Node (lrx, lrl, lrr, _)->
  +                        AvlTree.create lrx (AvlTree.create lvx ll lrl) (AvlTree.create x lrr r)
  +
  +        else if hr > hl + balanceTolerance then
  +            match r with
  +            | Empty ->
  +                invalidArg "AvlTree.balance" "The right subtree is empty."
  +            | Node (rvx, rl, rr, _) ->
  +                if AvlTree.height rr >= AvlTree.height rl then
  +                    AvlTree.create rvx (AvlTree.create x l rl) rr
  +                else
  +                    match rl with
  +                    | Empty ->
  +                        invalidArg "AvlTree.balance" "The left subtree is empty."
  +                    | Node (rlx, rll, rlr, _) ->
  +                        AvlTree.create rlx (AvlTree.create x l rll) (AvlTree.create rvx rlr rr)
  +
  +        else
  +            Node (x, l, r, (max hl hr) + 1u)
  +    
  +    /// Join two trees together at a pivot point.
  +    /// The resulting tree may be unbalanced.
  +    let rec join v l (r : AvlTree<'T>) =
  +        let rec myadd left x = function
  +            | Empty ->
  +                Node (x, Empty, Empty, 1u)
  +            | Node (vx, l, r, _) ->
  +                if left then
  +                    balance vx (myadd left x l) r
  +                else
  +                    balance vx l (myadd left x r)
  +        
  +        match l, r with
  +        | Empty, _ ->
  +            myadd true v r
  +        | _, Empty ->
  +            myadd false v l
  +        | Node (lx, ll, lr, lh), Node (rx, rl, rr, rh) ->
  +            if lh > rh + balanceTolerance then
  +                balance lx ll (join v lr r)
  +            else if rh > lh + balanceTolerance then
  +                balance rx (join v l rl) rr
  +            else
  +                AvlTree.create v l r
  +
  +    /// Reroot of balanced trees.
  +    let reroot l (r : AvlTree<'T>) =
  +        if AvlTree.height l > AvlTree.height r then
  +            let i, l' = AvlTree.extractMax FastGenericComparer<'T> l
  +            join i l' r
  +        else
  +            if AvlTree.isEmpty r then Empty
  +            else
  +                let i, r' = AvlTree.extractMin FastGenericComparer<'T> r
  +                join i l r'
  +
  +
  +/// A Discrete Interval Encoding Tree (DIET) specialized to the 'char' type.
  +/// This is abbreviated in our documentation as a 'char-DIET'.
  +type private CharDiet = AvlTree<char * char>
  +
  +/// Functional operations for char-DIETs.
   [<RequireQualifiedAccess; CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
   module private Diet =
       open System.Collections.Generic
       open LanguagePrimitives
   
       //
  -    module private AvlTree =
  -        //
  -        let [<Literal>] balanceTolerance = 1u
  -
  -        /// Join two trees together at a pivot point, then balance the resulting tree.
  -        let balance x l (r : AvlTree<'T>) =
  -            let hl = AvlTree.height l
  -            let hr = AvlTree.height r
  -            if hl > hr + balanceTolerance then
  -                match l with
  -                | Empty ->
  -                    invalidArg "AvlTree.balance" "The left subtree is empty."
  -                | Node (lvx, ll, lr, _) ->
  -                    if AvlTree.height ll >= AvlTree.height lr then
  -                        AvlTree.create lvx ll (AvlTree.create x lr r)
  -                    else
  -                        match lr with
  -                        | Empty ->
  -                            invalidArg "AvlTree.balance" "The right subtree is empty."
  -                        | Node (lrx, lrl, lrr, _)->
  -                            AvlTree.create lrx (AvlTree.create lvx ll lrl) (AvlTree.create x lrr r)
  -
  -            else if hr > hl + balanceTolerance then
  -                match r with
  -                | Empty ->
  -                    invalidArg "AvlTree.balance" "The right subtree is empty."
  -                | Node (rvx, rl, rr, _) ->
  -                    if AvlTree.height rr >= AvlTree.height rl then
  -                        AvlTree.create rvx (AvlTree.create x l rl) rr
  -                    else
  -                        match rl with
  -                        | Empty ->
  -                            invalidArg "AvlTree.balance" "The left subtree is empty."
  -                        | Node (rlx, rll, rlr, _) ->
  -                            AvlTree.create rlx (AvlTree.create x l rll) (AvlTree.create rvx rlr rr)
  -
  +    let private charComparer =
  +        FastGenericComparer<char>
  +
  +    //
  +    let inline pred (c : char) : char =
  +        char (int c - 1)
  +    
  +    //
  +    let inline succ (c : char) : char =
  +        char (int c + 1)
  +
  +    //
  +    let inline dist (x : char) (y : char) : int =
  +        int y - int x
  +
  +    //
  +    let inline private safe_pred (limit : char) (c : char) =
  +        if limit < c then
  +            char (int c - 1)
  +        else c
  +
  +    //
  +    let inline private safe_succ (limit : char) (c : char) =
  +        if limit > c then
  +            char (int c + 1)
  +        else c
  +
  +    //
  +    let inline height (t : CharDiet) =
  +        AvlTree.height t
  +
  +    //
  +    let rec private find_del_left p (tree : CharDiet) =
  +        match tree with
  +        | AvlTree.Empty ->
  +            p, AvlTree.Empty
  +        | AvlTree.Node ((x, y), left, right, _) ->
  +            if compare p (succ y) > 0 then
  +                let p', right' = find_del_left p right
  +                p', AvlDiet.join (x, y) left right'
  +            elif compare p x < 0 then
  +                find_del_left p left
               else
  -                Node (x, l, r, (max hl hr) + 1u)
  -    
  -        /// Join two trees together at a pivot point.
  -        /// The resulting tree may be unbalanced.
  -        let rec join v l (r : AvlTree<'T>) =
  -            let rec myadd left x = function
  -                | Empty ->
  -                    Node (x, Empty, Empty, 1u)
  -                | Node (vx, l, r, _) ->
  -                    if left then
  -                        balance vx (myadd left x l) r
  -                    else
  -                        balance vx l (myadd left x r)
  -        
  -            match l, r with
  -            | Empty, _ ->
  -                myadd true v r
  -            | _, Empty ->
  -                myadd false v l
  -            | Node (lx, ll, lr, lh), Node (rx, rl, rr, rh) ->
  -                if lh > rh + balanceTolerance then
  -                    balance lx ll (join v lr r)
  -                else if rh > lh + balanceTolerance then
  -                    balance rx (join v l rl) rr
  -                else
  -                    AvlTree.create v l r
  -
  -        /// Reroot of balanced trees.
  -        let reroot (comparer : IComparer<_>) l (r : AvlTree<'T>) =
  -            if AvlTree.height l > AvlTree.height r then
  -                let i, l' = AvlTree.extractMax comparer l
  -                join i l' r
  +                x, left
  +
  +    //
  +    let rec private find_del_right p (tree : CharDiet) =
  +        match tree with
  +        | AvlTree.Empty ->
  +            p, AvlTree.Empty
  +        | AvlTree.Node ((x, y), left, right, _) ->
  +            if compare p (pred x) < 0 then
  +                let p', left' = find_del_right p left
  +                p', AvlDiet.join (x, y) left' right
  +            elif compare p y > 0 then
  +                find_del_right p right
               else
  -                if AvlTree.isEmpty r then Empty
  -                else
  -                    let i, r' = AvlTree.extractMin comparer r
  -                    join i l r'
  -
  -    //
  -    let inline private safe_pred (measurer : IMeasurer<_>) limit x =
  -        if measurer.Compare (limit, x) < 0 then
  -            measurer.Previous x
  -        else x
  -
  -    //
  -    let inline private safe_succ (measurer : IMeasurer<_>) limit x =
  -        if measurer.Compare (limit, x) > 0 then
  -            measurer.Next x
  -        else x
  -
  -    //
  -    let inline private max (measurer : IMeasurer<_>) x y =
  -        if measurer.Compare (x, y) > 0 then x else y
  -
  -    //
  -    let inline private min (measurer : IMeasurer<_>) x y =
  -        if measurer.Compare (x, y) < 0 then x else y
  -
  -    //
  -    let inline height (t : Diet<'T>) =
  -        AvlTree.height t
  -
  -    // For debugging purposes.
  -    let internal ensureCorrectlyFormed (measurer : IMeasurer<_>) (tree : Diet<'T>) =
  -        let rec ensureCorrectlyFormed tree =
  -            match tree with
  -            | Empty
  -            | Node (_, Empty, Empty, _) -> ()
  -            | Node (rangeXY : Range<_>,
  -                    (Node (leftChildRange : Range<_>,_,_, leftChildHeight) as left), Empty, height) ->
  -                // Make sure the sets aren't overlapping or touching,
  -                // and that the left-child range is "lesser" than this node's range.
  -                Debug.Assert (
  -                    height > leftChildHeight &&
  -                    height - leftChildHeight <= 2u,
  -                    sprintf "Node Height = %i, Left-Child Height = %i" height leftChildHeight)
  -                Debug.Assert (
  -                    measurer.Previous rangeXY.MinValue > leftChildRange.MaxValue,
  -                    sprintf "pred(Node.MinValue) = %O, Left-Child MaxValue = %O" (measurer.Previous rangeXY.MinValue) leftChildRange.MaxValue)
  -                ensureCorrectlyFormed left
  -
  -            | Node (rangeXY : Range<_>, Empty,
  -                    (Node (rightChildRange : Range<_>,_,_, rightChildHeight) as right), height) ->
  -                // Make sure the sets aren't overlapping or touching,
  -                // and that the right-child range is "greater" than this node's range.
  -                Debug.Assert (
  -                    height > rightChildHeight &&
  -                    height - rightChildHeight <= 2u,
  -                    sprintf "Node Height = %i, Right-Child Height = %i" height rightChildHeight)
  -                Debug.Assert (
  -                    measurer.Next rangeXY.MaxValue < rightChildRange.MinValue,
  -                    sprintf "succ(Node.MaxValue) = %O, Right-Child MinValue = %O" (measurer.Next rangeXY.MaxValue) rightChildRange.MinValue)
  -                ensureCorrectlyFormed right
  -
  -            | Node (rangeXY : Range<_>,
  -                    (Node (leftChildRange : Range<_>,_,_,leftChildHeight) as left),
  -                    (Node (rightChildRange : Range<_>,_,_,rightChildHeight) as right), height) ->
  -                // Make sure the sets aren't overlapping or touching,
  -                // and that the left-child range is "lesser" than this node's range.
  -                Debug.Assert (
  -                    height > leftChildHeight &&
  -                    height - leftChildHeight <= 2u,
  -                    sprintf "Node Height = %i, Left-Child Height = %i" height leftChildHeight)
  -                Debug.Assert (
  -                    measurer.Previous rangeXY.MinValue > leftChildRange.MaxValue,
  -                    sprintf "pred(Node.MinValue) = %O, Left-Child MaxValue = %O" (measurer.Previous rangeXY.MinValue) leftChildRange.MaxValue)
  -                ensureCorrectlyFormed left
  -                // Make sure the sets aren't overlapping or touching,
  -                // and that the right-child range is "greater" than this node's range.
  -                Debug.Assert (
  -                    height > rightChildHeight &&
  -                    height - rightChildHeight <= 2u,
  -                    sprintf "Node Height = %i, Right-Child Height = %i" height rightChildHeight)
  -                Debug.Assert (
  -                    measurer.Next rangeXY.MaxValue < rightChildRange.MinValue,
  -                    sprintf "succ(Node.MaxValue) = %O, Right-Child MinValue = %O" (measurer.Next rangeXY.MaxValue) rightChildRange.MinValue)
  -                ensureCorrectlyFormed right
  -
  -        ensureCorrectlyFormed tree
  -        tree
  -
  -    let internal ensureCorrectlyFormed1stAnd3rd measurer (x : Diet<'T>, y, z : Diet<'T>) =
  -        let x' = ensureCorrectlyFormed measurer x
  -        let z' = ensureCorrectlyFormed measurer z
  -        x', y, z'
  -
  -    let internal ensureCorrectlyFormed2Of2 measurer (x, tree : Diet<'T>) =
  -        x, ensureCorrectlyFormed measurer tree
  -
  -    //
  -    let rec private find_del_left_rec (measurer : IMeasurer<_>) p (tree : Diet<'T>) cont =
  -        match tree with
  -        | AvlTree.Empty ->
  -            cont (p, AvlTree.Empty)
  -        | AvlTree.Node (range, left, right, _) ->
  -            if measurer.Compare (p, measurer.Next range.MaxValue) > 0 then
  -                find_del_left_rec measurer p right <| fun (p, right) ->
  -                    cont (p, AvlTree.join range left right)
  -            elif measurer.Compare (p, range.MinValue) < 0 then
  -                find_del_left_rec measurer p left cont
  -            else
  -                cont (range.MinValue, left)
  -
  -    //
  -    let private find_del_left (measurer : IMeasurer<_>) p (tree : Diet<'T>) =
  -        find_del_left_rec measurer p tree id
  -
  -    //
  -    let rec private find_del_right_rec (measurer : IMeasurer<_>) p (tree : Diet<'T>) cont =
  -        match tree with
  -        | AvlTree.Empty ->
  -            cont (p, AvlTree.Empty)
  -        | AvlTree.Node (range, left, right, _) ->
  -            if measurer.Compare (p, measurer.Previous range.MinValue) < 0 then
  -                find_del_right_rec measurer p left <| fun (p, left) ->
  -                    cont (p, AvlTree.join range left right)
  -            elif measurer.Compare (p, range.MaxValue) > 0 then
  -                find_del_right_rec measurer p right cont
  -            else
  -                cont (range.MaxValue, right)
  -    
  -    //
  -    let private find_del_right (measurer : IMeasurer<_>) p (tree : Diet<'T>) =
  -        find_del_right_rec measurer p tree id
  +                y, right
   
       /// An empty DIET.
  -    let empty : Diet<'T> =
  +    let empty : CharDiet =
           AvlTree.empty
   
       /// Determines if a DIET is empty.
  -    let inline isEmpty (tree : Diet<'T>) =
  +    let inline isEmpty (tree : CharDiet) =
           AvlTree.isEmpty tree
   
       /// Determines if a DIET contains a specified value.
  -    let rec contains (measurer : IMeasurer<_>) value (tree : Diet<'T>) =
  +    let rec contains value (tree : CharDiet) =
           match tree with
           | Empty ->
               false
  -        | Node (range, left, right, _) ->
  -            if measurer.Compare (value, range.MinValue) < 0 then
  -                contains measurer value left
  -            elif measurer.Compare (value, range.MaxValue) > 0 then
  -                contains measurer value right
  +        | Node ((x, y), left, right, _) ->
  +            if compare value x < 0 then
  +                contains value left
  +            elif compare value y > 0 then
  +                contains value right
               else true
           
       /// Gets the maximum (greatest) value stored in the DIET.
  -    let maxElement (tree : Diet<'T>) =
  -        (AvlTree.maxElement tree).MaxValue
  +    let maxElement (tree : CharDiet) : char =
  +        snd <| AvlTree.maxElement tree
       
       /// Gets the minimum (least) value stored in the DIET.
  -    let minElement (tree : Diet<'T>) =
  -        (AvlTree.minElement tree).MinValue
  +    let minElement (tree : CharDiet) : char=
  +        fst <| AvlTree.minElement tree
   
       /// Creates a DIET containing the specified value.
  -    let singleton value : Diet<'T> =
  -        AvlTree.singleton <| Range (value)
  +    let singleton value : CharDiet =
  +        AvlTree.singleton <| (value, value)
   
       /// Creates a DIET containing the specified range of values.
  -    let ofRange minValue maxValue : Diet<'T> =
  +    let ofRange minValue maxValue : CharDiet =
           // For compatibility with the F# range operator,
           // when minValue > minValue it's just considered
           // to be an empty range.
           if minValue >= maxValue then
               empty
           else
  -            Range (minValue, maxValue)
  -            |> AvlTree.singleton
  +            AvlTree.singleton (minValue, maxValue)
   
       /// Returns the number of elements in the set.
  -    let count (measurer : IMeasurer<_>) (t : Diet<'T>) =
  +    let count (t : CharDiet) =
  +        // OPTIMIZE : Modify this to use a mutable stack instead of an F# list.
           let rec cardinal_aux acc = function
               | [] -> acc
               | AvlTree.Empty :: ts ->
                   cardinal_aux acc ts
  -            | AvlTree.Node (range : Range<_>, left, right, _) :: ts ->
  -                let dist = measurer.Distance (range.MinValue, range.MaxValue)
  -                cardinal_aux (acc + dist + 1) (left :: right :: ts)
  +            | AvlTree.Node ((x, y), left, right, _) :: ts ->
  +                let d = dist x y
  +                cardinal_aux (acc + d + 1) (left :: right :: ts)
           
           cardinal_aux 0 [t]
   
       /// Returns the number of intervals in the set.
  -    let intervalCount (t : Diet<'T>) =
  +    let intervalCount (t : CharDiet) =
  +        // OPTIMIZE : Modify this to use a mutable stack instead of an F# list.
           let rec cardinal_aux acc = function
               | [] -> acc
               | AvlTree.Empty :: ts ->
                   cardinal_aux acc ts
  -            | AvlTree.Node (range : Range<_>, left, right, _) :: ts ->
  +            | AvlTree.Node (_, left, right, _) :: ts ->
                   cardinal_aux (acc + 1) (left :: right :: ts)
           
           cardinal_aux 0 [t]
   
       /// Applies the given accumulating function to all elements in a DIET.
  -    let fold (folder : 'State -> _ -> 'State) (measurer : IMeasurer<_>) (state : 'State) (tree : Diet<'T>) =
  -        let rangeFolder (state : 'State) (range : Range<_>) =
  -            let q = range.MaxValue
  +    let fold (folder : 'State -> char -> 'State) (state : 'State) (tree : CharDiet) =
  +        // Preconditions
  +        checkNonNull "tree" tree
  +
  +        let folder = FSharpFunc<_,_,_>.Adapt folder
  +
  +        let rangeFolder (state : 'State) (lo, hi) =
               // Fold over the items in increasing order.
               let mutable state = state
  -            let mutable currentItem = range.MinValue
  -            while currentItem <> q do
  -                state <- folder state currentItem
  -                currentItem <- measurer.Next currentItem
  -
  -            // Apply the folder function to the last value in the range 'q'.
  -            folder state q
  +            for x = int lo to int hi do
  +                state <- folder.Invoke (state, char x)
  +            state
   
           AvlTree.fold rangeFolder state tree
   
       /// Applies the given accumulating function to all elements in a DIET.
  -    let foldBack (folder : _ -> 'State -> 'State) (measurer : IMeasurer<_>) (tree : Diet<'T>) (state : 'State) =
  -        let rangeFolder (range : Range<_>) (state : 'State) =
  -            let p = range.MinValue
  -
  +    let foldBack (folder : char -> 'State -> 'State) (tree : CharDiet) (state : 'State) =
  +        // Preconditions
  +        checkNonNull "tree" tree
  +
  +        let folder = FSharpFunc<_,_,_>.Adapt folder
  +
  +        let rangeFolder (lo, hi) (state : 'State) =
               // Fold over the items in decreasing order.
               let mutable state = state
  -            let mutable currentItem = range.MaxValue
  -            while currentItem <> p do
  -                state <- folder currentItem state
  -                currentItem <- measurer.Previous currentItem
  -
  -            // Apply the folder function to the first value in the range 'p'.
  -            folder p state
  +            for x = int hi downto int lo do
  +                state <- folder.Invoke (char x, state)
  +            state
   
           AvlTree.foldBack rangeFolder tree state
   
  -    //
  -    let rec toSeq (measurer : IMeasurer<_>) (tree : Diet<'T>) =
  +    /// Applies the given function to all elements in a DIET.
  +    let iter (action : char -> unit) (tree : CharDiet) =
  +        // Preconditions
  +        checkNonNull "tree" tree
  +
  +        /// Applies the action to all values within an interval.
  +        let intervalApplicator (lo, hi) =
  +            for x = int lo to int hi do
  +                action (char x)
  +
  +        AvlTree.iter intervalApplicator tree
  +
  +    //
  +    let rec toSeq (tree : CharDiet) =
           seq {
           match tree with
           | Empty -> ()
  -        | Node (range : Range<_>, l, r, _) ->
  -            yield! toSeq measurer l
  -            yield! range.ToSeq measurer
  -            yield! toSeq measurer r
  +        | Node ((x, y), l, r, _) ->
  +            yield! toSeq l
  +            yield! seq {x .. y}
  +            yield! toSeq r
           }
   
       //
  -    let toList (measurer : IMeasurer<_>) (tree : Diet<'T>) =
  -        (measurer, [], tree)
  -        |||> fold (fun list el ->
  +    let toList (tree : CharDiet) =
  +        ([], tree)
  +        ||> fold (fun list el ->
               el :: list)
   
       //
  -    let toArray (measurer : IMeasurer<_>) (tree : Diet<'T>) =
  +    let toArray (tree : CharDiet) =
           let elements = ResizeArray ()
  -        // TODO : Simplify this to use 'iter' instead of 'fold'.
  -        (measurer, elements, tree)
  -        |||> fold (fun resizeArr el ->
  -            resizeArr.Add el
  -            resizeArr)
  -        |> ignore
  +        iter elements.Add tree
           elements.ToArray ()
   
       //
  -    let toSet (measurer : IMeasurer<_>) (tree : Diet<'T>) =
  -        (measurer, Set.empty, tree)
  -        |||> fold (fun set el ->
  +    let toSet (tree : CharDiet) =
  +        (Set.empty, tree)
  +        ||> fold (fun set el ->
               Set.add el set)
   
  -    // TEMP
  -    let internal ensureAllElementsUnique (measurer : IMeasurer<_>) (tree : Diet<'T>) =
  -        let uniqueElementCount =
  -            toSet measurer tree
  -            |> Set.count
  -
  -        let actualElementCount = count measurer tree
  -        Debug.Assert (
  -            (actualElementCount = uniqueElementCount),
  -            sprintf "Incorrectly-formed DIET found: contains %i elements, but only %i unique elements." actualElementCount uniqueElementCount)
  -        tree
  -
  -    //
  -    let forall (predicate : 'T -> bool) (measurer : IMeasurer<_>) (t : Diet<'T>) =
  +    //
  +    let forall (predicate : char -> bool) (t : CharDiet) =
           // OPTIMIZE : Rewrite this to short-circuit and return early
           // if we find a non-matching element.
  -        (measurer, true, t)
  -        |||> fold (fun state el ->
  +        (true, t)
  +        ||> fold (fun state el ->
               state && predicate el)
   
  -    //
  -    let rec private addRec (measurer : IMeasurer<_>) p (tree : Diet<'T>) cont : Diet<_> =
  -        let inline compare a b =
  -            measurer.Compare (a, b)
  -
  +    /// Returns a new set with the specified value added to the set.
  +    /// No exception is thrown if the set already contains the value.
  +    let rec add p (tree : CharDiet) : CharDiet =
           match tree with
           | Empty ->
               singleton p
  -            |> cont
  -        | Node (rangeXY, left, right, h) as t ->
  -            if compare p rangeXY.MinValue >= 0 then
  -                if compare p rangeXY.MaxValue <= 0 then
  -                    cont t
  -
  -                elif compare p (measurer.Next rangeXY.MaxValue) > 0 then
  -                    addRec measurer p right <| fun right ->
  -                        AvlTree.join rangeXY left right
  -                        |> cont
  -
  +        | Node ((x, y), left, right, h) as t ->
  +            if compare p x >= 0 then
  +                if compare p y <= 0 then t
  +                elif compare p (succ y) > 0 then
  +                    AvlDiet.join (x, y) left (add p right)
                   elif AvlTree.isEmpty right then
  -                    AvlTree.Node (Range (rangeXY.MinValue, p), left, right, h)
  -                    |> cont
  -
  +                    AvlTree.Node ((x, p), left, right, h)
                   else
  -                    let rangeUV, r = AvlTree.extractMin measurer right
  -                    if measurer.Previous rangeUV.MinValue = p then
  -                        let rangeXV = Range (rangeXY.MinValue, rangeUV.MaxValue)
  -                        AvlTree.join rangeXV left r
  +                    let (u, v), r = AvlTree.extractMin charComparer right
  +                    if pred u = p then
  +                        AvlDiet.join (x, v) left r
                       else
  -                        let rangeXP = Range (rangeXY.MinValue, p)
  -                        AvlTree.Node (rangeXP, left, right, h)
  -                    |> cont
  -
  -            elif compare p (measurer.Previous rangeXY.MinValue) < 0 then
  -                addRec measurer p left <| fun left ->
  -                    AvlTree.join rangeXY left right
  -                    |> cont
  -
  +                        AvlTree.Node ((x, p), left, right, h)
  +
  +            elif compare p (pred x) < 0 then
  +                AvlDiet.join (x, y) (add p left) right
               elif AvlTree.isEmpty left then
  -                let rangePY = Range (p, rangeXY.MaxValue)
  -                AvlTree.Node (rangePY, left, right, h)
  -                |> cont
  -
  +                AvlTree.Node ((p, y), left, right, h)
               else
  -                let rangeUV, l = AvlTree.extractMax measurer left
  -                if measurer.Next rangeUV.MaxValue = p then
  -                    let rangeUY = Range (rangeUV.MinValue, rangeXY.MaxValue)
  -                    AvlTree.join rangeUY l right
  +                let (u, v), l = AvlTree.extractMax charComparer left
  +                if (succ v) = p then
  +                    AvlDiet.join (u, y) l right
                   else
  -                    let rangePY = Range (p, rangeXY.MaxValue)
  -                    AvlTree.Node (rangePY, left, right, h)
  -                |> cont
  -
  -    /// Returns a new set with the specified value added to the set.
  -    /// No exception is thrown if the set already contains the value.
  -    let add (measurer : IMeasurer<_>) p (tree : Diet<'T>) : Diet<_> =
  -        addRec measurer p tree id
  -        //|> ensureAllElementsUnique measurer
  -        |> ensureCorrectlyFormed measurer
  +                    AvlTree.Node ((p, y), left, right, h)
   
       /// Builds a new DIET from the elements of a sequence.
  -    let ofSeq (measurer : IMeasurer<_>) (sequence : seq<_>) : Diet<'T> =
  +    let ofSeq (sequence : seq<_>) : CharDiet =
           (Empty, sequence)
           ||> Seq.fold (fun tree el ->
  -            add measurer el tree)
  +            add el tree)
   
       /// Builds a new DIET from the elements of an F# list.
  -    let ofList (measurer : IMeasurer<_>) (list : _ list) : Diet<'T> =
  +    let ofList (list : _ list) : CharDiet =
           (Empty, list)
           ||> List.fold (fun tree el ->
  -            add measurer el tree)
  +            add el tree)
   
       /// Builds a new DIET from the elements of an array.
  -    let ofArray (measurer : IMeasurer<_>) (array : _[]) : Diet<'T> =
  +    let ofArray (array : _[]) : CharDiet =
           (Empty, array)
           ||> Array.fold (fun tree el ->
  -            add measurer el tree)
  +            add el tree)
   
       /// Builds a new DIET from an F# Set.
  -    let ofSet (measurer : IMeasurer<_>) (set : Set<'T>) : Diet<'T> =
  +    let ofSet (set : Set<_>) : CharDiet =
           (Empty, set)
           ||> Set.fold (fun tree el ->
  -            add measurer el tree)
  +            add el tree)
   
       /// Returns a new set with the specified range of values added to the set.
       /// No exception is thrown if any of the values are already contained in the set.
  -    let rec private addRange' (measurer : IMeasurer<_>) rangePQ (tree : Diet<'T>) : Diet<_> =
  -        let inline compare a b =
  -            measurer.Compare (a, b)
  -
  +    let rec addRange (p, q) (tree : CharDiet) : CharDiet =
           match tree with
           | AvlTree.Empty ->
  -            AvlTree.singleton rangePQ
  -        | AvlTree.Node (rangeXY, left, right, _) ->
  -            if compare rangePQ.MaxValue (measurer.Previous rangeXY.MinValue) < 0 then
  -                let left =
  -                    addRange' measurer rangePQ left
  -                    |> ensureCorrectlyFormed measurer
  -
  -                AvlTree.join rangeXY left right
  -                |> ensureCorrectlyFormed measurer
  -
  -            elif compare rangePQ.MinValue (measurer.Next rangeXY.MaxValue) > 0 then
  -                let right =
  -                    addRange' measurer rangePQ right
  -                    |> ensureCorrectlyFormed measurer
  -                
  -                AvlTree.join rangeXY left right
  -                |> ensureCorrectlyFormed measurer
  +            AvlTree.singleton (p, q)
  +        | AvlTree.Node ((x, y), left, right, _) ->
  +            if compare q (pred x) < 0 then
  +                AvlDiet.join (x, y) (addRange (p, q) left) right
  +            elif compare p (succ y) > 0 then
  +                AvlDiet.join (x, y) left (addRange (p, q) right)
               else
                   let x', left' =
  -                    if compare rangePQ.MinValue rangeXY.MinValue >= 0 then
  -                        rangeXY.MinValue, left
  -                    else
  -                        find_del_left measurer rangePQ.MinValue left
  -                        |> ensureCorrectlyFormed2Of2 measurer
  -
  +                    if compare p x >= 0 then x, left
  +                    else find_del_left p left
                   let y', right' =
  -                    if compare rangePQ.MaxValue rangeXY.MaxValue <= 0 then
  -                        rangeXY.MaxValue, right
  -                    else
  -                        find_del_right measurer rangePQ.MaxValue right
  -                        |> ensureCorrectlyFormed2Of2 measurer
  -
  -                let rangeXY' = Range (x', y')
  -                AvlTree.join rangeXY' left' right'
  -                |> ensureCorrectlyFormed measurer
  -
  -    // TEMP
  -    let rec addRange (measurer : IMeasurer<_>) rangePQ (tree : Diet<'T>) : Diet<_> =
  -        addRange' measurer rangePQ tree
  -        //|> ensureAllElementsUnique measurer
  -        |> ensureCorrectlyFormed measurer
  +                    if compare q y <= 0 then y, right
  +                    else find_del_right q right
  +
  +                AvlDiet.join (x', y') left' right'
   
       /// Returns a new set with the given element removed.
       /// No exception is thrown if the set doesn't contain the specified element.
  -    let rec remove (measurer : IMeasurer<_>) z (tree : Diet<'T>) : Diet<'T> =
  -        let inline compare a b =
  -            measurer.Compare (a, b)
  -
  +    let rec remove z (tree : CharDiet) : CharDiet =
           match tree with
           | AvlTree.Empty ->
               AvlTree.Empty
  -        | AvlTree.Node (range, left, right, h) ->
  -            let czx = compare z range.MinValue
  +        | AvlTree.Node ((x, y), left, right, h) ->
  +            let czx = compare z x
               if czx < 0 then
  -                AvlTree.join range (remove measurer z left) right
  +                AvlDiet.join (x, y) (remove z left) right
               else
  -                let cyz = compare range.MaxValue z
  +                let cyz = compare y z
                   if cyz < 0 then
  -                    AvlTree.join range left (remove measurer z right)
  +                    AvlDiet.join (x, y) left (remove z right)
                   elif cyz = 0 then
                       if czx = 0 then
  -                        AvlTree.reroot measurer left right
  +                        AvlDiet.reroot left right
                       else
  -                        let newRange = Range (range.MinValue, measurer.Previous range.MaxValue)
  -                        AvlTree.Node (newRange, left, right, h)
  +                        AvlTree.Node ((x, pred y), left, right, h)
                   elif czx = 0 then
  -                    let newRange = Range (measurer.Next range.MinValue, range.MaxValue)
  -                    AvlTree.Node (newRange, left, right, h)
  +                    AvlTree.Node ((succ x, y), left, right, h)
                   else
  -                    let newRange = Range (range.MinValue, measurer.Previous z)
  -                    let newRange' = Range (measurer.Next z, range.MaxValue)
  -                    AvlTree.Node (newRange, left, right, h)
  -                    |> addRange measurer newRange'
  -
  -    let rec private union_helper (measurer : IMeasurer<_>) left (rangeAB : Range<_>) right limit head stream =
  -        let inline compare a b =
  -            measurer.Compare (a, b)
  -        
  +                    addRange (succ z, y) (AvlTree.Node ((x, pred z), left, right, h))
  +
  +    let rec private union_helper left (a, b) right limit head stream =        
           match head with
           | None ->
  -            let joined =
  -                AvlTree.join rangeAB left right
  -                |> ensureCorrectlyFormed measurer
  -            joined, None, AvlTree.Empty
  -        | Some (rangeXY : Range<_>) ->
  +            AvlDiet.join (a,b) left right, None, AvlTree.Empty
  +        | Some (x, y) ->
               let greater_limit z =
                   match limit with
                   | None -> false
                   | Some u ->
                       compare z u >= 0
                   
  -            if compare rangeXY.MaxValue rangeAB.MinValue < 0 && compare rangeXY.MaxValue (measurer.Previous rangeAB.MinValue) < 0 then
  -                let left' =
  -                    addRange measurer rangeXY left
  -                    |> ensureCorrectlyFormed measurer
  -                let head, stream =
  -                    AvlTree.tryExtractMin measurer stream
  -                    |> ensureCorrectlyFormed2Of2 measurer
  -                union_helper measurer left' rangeAB right limit head stream
  -                |> ensureCorrectlyFormed1stAnd3rd measurer
  -
  -            elif compare rangeXY.MinValue rangeAB.MaxValue > 0 && compare rangeXY.MinValue (measurer.Next rangeAB.MaxValue) > 0 then
  -                let right', head, stream =
  -                    union' measurer right limit head stream
  -                    |> ensureCorrectlyFormed1stAnd3rd measurer
  -                let joined =
  -                    AvlTree.join rangeAB left right'
  -                    |> ensureCorrectlyFormed measurer
  -                joined, head, stream
  -
  -            elif compare rangeAB.MaxValue rangeXY.MaxValue >= 0 then
  -                let head, stream =
  -                    AvlTree.tryExtractMin measurer stream
  -                    |> ensureCorrectlyFormed2Of2 measurer
  -                let newRange = Range (min measurer rangeAB.MinValue rangeXY.MinValue, rangeAB.MaxValue)
  -                union_helper measurer left newRange right limit head stream
  -                |> ensureCorrectlyFormed1stAnd3rd measurer
  -
  -            elif greater_limit rangeXY.MaxValue then
  -                let newRange = Range (min measurer rangeAB.MinValue rangeXY.MinValue, rangeXY.MaxValue)
  -                (left, Some newRange, stream)
  +            if compare y a < 0 && compare y (pred a) < 0 then
  +                let left' = addRange (x, y) left
  +                let head, stream = AvlTree.tryExtractMin charComparer stream
  +                union_helper left' (a, b) right limit head stream
  +
  +            elif compare x b > 0 && compare x (succ b) > 0 then
  +                let right', head, stream = union' right limit head stream
  +                AvlDiet.join (a,b) left right', head, stream
  +
  +            elif compare b y >= 0 then
  +                let head, stream = AvlTree.tryExtractMin charComparer stream
  +                union_helper left (min a x, b) right limit head stream
  +
  +            elif greater_limit y then
  +                left, Some (min a x, y), stream
   
               else
  -                let right', head, stream =
  -                    let newRange = Range (min measurer rangeAB.MinValue rangeXY.MinValue, rangeXY.MaxValue)
  -                    union' measurer right limit (Some newRange) stream
  -                    |> ensureCorrectlyFormed1stAnd3rd measurer
  -                let rerooted =
  -                    AvlTree.reroot measurer left right'
  -                    |> ensureCorrectlyFormed measurer
  -                rerooted, head, stream
  -
  -    and private union' (measurer : IMeasurer<_>) (input : Diet<_>) limit head (stream : Diet<_>) =
  -        let inline compare a b =
  -            measurer.Compare (a, b)
  -
  +                let right', head, stream = union' right limit (Some (min a x, y)) stream
  +                AvlDiet.reroot left right', head, stream
  +
  +    and private union' (input : CharDiet) limit head (stream : CharDiet) =
           match head with
           | None ->
               input, None, AvlTree.Empty
  -        | Some (rangeXY : Range<_>) ->
  +        | Some (x, y) ->
               match input with
               | AvlTree.Empty ->
                   AvlTree.Empty, head, stream
  -            | AvlTree.Node (rangeAB, left, right, _) ->
  +            | AvlTree.Node ((a, b), left, right, _) ->
                   let left', head, stream =
  -                    if compare rangeXY.MinValue rangeAB.MinValue < 0 then
  -                        union' measurer left (Some (measurer.Previous rangeAB.MinValue)) head stream
  -                        |> ensureCorrectlyFormed1stAnd3rd measurer
  +                    if compare x a < 0 then
  +                        union' left (Some <| pred a) head stream
                       else
                           left, head, stream
  -
  -                union_helper measurer left' rangeAB right limit head stream
  -                |> ensureCorrectlyFormed1stAnd3rd measurer
  +                union_helper left' (a, b) right limit head stream
   
       /// Computes the union of the two sets.
  -    let rec union (measurer : IMeasurer<_>) (input : Diet<_>) (stream : Diet<_>) : Diet<'T> =
  -        let inline compare a b =
  -            measurer.Compare (a, b)
  -
  +    let rec union (input : CharDiet) (stream : CharDiet) : CharDiet =
           if AvlTree.height stream > AvlTree.height input then
  -            union measurer stream input
  +            union stream input
           else
               #if DEBUG
               /// The minimum possible number of elements in the resulting set.
               let minPossibleResultCount =
  -                let inputCount = count measurer input
  -                let streamCount = count measurer stream
  +                let inputCount = count input
  +                let streamCount = count stream
                   GenericMaximum inputCount streamCount
               #endif
   
               let head, stream' =
  -                AvlTree.tryExtractMin measurer stream
  -                |> ensureCorrectlyFormed2Of2 measurer
  +                AvlTree.tryExtractMin charComparer stream
   
               let result, head', stream'' =
  -                union' measurer input None head stream'
  -                |> ensureCorrectlyFormed1stAnd3rd measurer
  +                union' input None head stream'
               let result =
                   match head' with
                   | None ->
                       result
  -                    |> ensureCorrectlyFormed measurer
  -                    |> ensureAllElementsUnique measurer
                   | Some i ->
  -                    AvlTree.join i result stream''
  -                    |> ensureCorrectlyFormed measurer
  -                    |> ensureAllElementsUnique measurer
  +                    AvlDiet.join i result stream''
   
               #if DEBUG
  -            let resultCount = count measurer result
  +            let resultCount = count result
   //            let inputArr =
   //                if resultCount >= minPossibleResultCount then Array.empty
  -//                else toArray measurer input
  +//                else toArray input
   //            let streamArr =
   //                if resultCount >= minPossibleResultCount then Array.empty
  -//                else toArray measurer stream
  +//                else toArray stream
                       
               Debug.Assert (
                   resultCount >= minPossibleResultCount,
  
positive.code:     //
      member __.Count
          with get () =
              Diet.count charMeasurer dietSet
  
      //
      member __.IntervalCount
  
negative.code: 
      //
      static member OfList list =
          CharSet (Diet.ofList list)
  
  //    //
  //    static member ToSet (charSet : CharSet) =
  