comparison Tree/Interval.pm @ 0:acc8d8bfeb9a

Uploaded
author jjohnson
date Wed, 08 Feb 2012 16:59:24 -0500
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:acc8d8bfeb9a
1 package Tree::Interval;
2
3 use strict;
4 use Carp;
5
6 use Tree::Interval::Node qw[set_color color_of parent_of left_of right_of];
7 use Tree::Interval::Node::Constants;
8 use Tree::DAG_Node;
9 use vars qw( $VERSION @EXPORT_OK );
10 $VERSION = 0.1;
11
12 require Exporter;
13 *import = \&Exporter::import;
14 @EXPORT_OK = qw[LUEQUAL LUGTEQ LULTEQ LUGREAT LULESS LUNEXT LUPREV];
15
16 use enum qw{ LUEQUAL LUGTEQ LULTEQ LUGREAT LULESS LUNEXT LUPREV };
17
18 # object slots
19 use enum qw{ ROOT CMP SIZE };
20
21 sub new {
22 my ($class, $cmp) = @_;
23 my $obj = [];
24 $obj->[SIZE] = 0;
25 if($cmp) {
26 ref $cmp eq 'CODE'
27 or croak('Invalid arg: codref expected');
28 $obj->[CMP] = $cmp;
29 }
30 else {
31 # default compare
32 $obj->[CMP] = sub { $_[0]->[0] <=> $_[1]->[0] || $_[0]->[1] <=> $_[1]->[1]};
33 }
34 return bless $obj => $class;
35 }
36
37
38 sub DESTROY { $_[0]->[ROOT]->DESTROY if $_[0]->[ROOT] }
39
40 sub root { $_[0]->[ROOT] }
41 sub size { $_[0]->[SIZE] }
42
43 sub left_most {
44 my $self = shift;
45 return undef unless $self->[ROOT];
46 return $self->[ROOT]->left_most;
47 }
48
49 sub right_most {
50 my $self = shift;
51 return undef unless $self->[ROOT];
52 return $self->[ROOT]->right_most;
53 }
54
55 # return all the intervals intersect with the interval
56 sub intersect {
57 my $self = shift;
58 my $interval = shift;
59 return my @tmp unless $self->[ROOT];
60 return $self->[ROOT]->intersect($interval);
61 }
62
63 sub lookup {
64 my $self = shift;
65 my $key = shift;
66 defined $key
67 or croak("Can't use undefined value as key");
68 my $mode = shift || LUEQUAL;
69 my $cmp = $self->[CMP];
70
71 my $y;
72 my $x = $self->[ROOT]
73 or return;
74 my $next_child;
75 while($x) {
76 $y = $x;
77 if($cmp ? $cmp->($key, $x->[_KEY]) == 0
78 : $key eq $x->[_KEY]) {
79 # found it!
80 if($mode == LUGREAT || $mode == LUNEXT) {
81 $x = $x->successor;
82 }
83 elsif($mode == LULESS || $mode == LUPREV) {
84 $x = $x->predecessor;
85 }
86 return wantarray
87 ? ($x->[_VAL], $x)
88 : $x->[_VAL];
89 }
90 if($cmp ? $cmp->($key, $x->[_KEY]) < 0
91 : $key lt $x->[_KEY]) {
92 $next_child = _LEFT;
93 }
94 else {
95 $next_child = _RIGHT;
96 }
97 $x = $x->[$next_child];
98 }
99 # Didn't find it :(
100 if($mode == LUGTEQ || $mode == LUGREAT) {
101 if($next_child == _LEFT) {
102 return wantarray ? ($y->[_VAL], $y) : $y->[_VAL];
103 }
104 else {
105 my $next = $y->successor
106 or return;
107 return wantarray ? ($next->[_VAL], $next) : $next->[_VAL];
108 }
109 }
110 elsif($mode == LULTEQ || $mode == LULESS) {
111 if($next_child == _RIGHT) {
112 return wantarray ? ($y->[_VAL], $y) : $y->[_VAL];
113 }
114 else {
115 my $next = $y->predecessor
116 or return;
117 return wantarray ? ($next->[_VAL], $next) : $next->[_VAL];
118 }
119 }
120 return;
121 }
122
123 sub insert {
124 my $self = shift;
125 my $key_or_node = shift;
126 defined $key_or_node
127 or croak("Can't use undefined value as key or node");
128 my $val = shift;
129
130 my $cmp = $self->[CMP];
131 my $z = (ref $key_or_node eq 'Tree::Interval::Node')
132 ? $key_or_node
133 : Tree::Interval::Node->new($key_or_node => $val);
134
135 my $y;
136 my $x = $self->[ROOT];
137 while($x) {
138 $y = $x;
139 # Handle case of inserting node with duplicate key.
140 if($cmp ? $cmp->($z->[_KEY], $x->[_KEY]) == 0
141 : $z->[_KEY] eq $x->[_KEY])
142 {
143 warn "The same key (range) is already in the tree
144 it will be replaced!";
145 my $old_val = $x->[_VAL];
146 $x->[_VAL] = $z->[_VAL];
147 return $old_val;
148 }
149
150 if($cmp ? $cmp->($z->[_KEY], $x->[_KEY]) < 0
151 : $z->[_KEY] lt $x->[_KEY])
152 {
153 $x = $x->[_LEFT];
154 }
155 else {
156 $x = $x->[_RIGHT];
157 }
158 }
159 # insert new node
160 $z->[_PARENT] = $y;
161 if(not defined $y) {
162 $self->[ROOT] = $z;
163 }
164 else {
165 if($cmp ? $cmp->($z->[_KEY], $y->[_KEY]) < 0
166 : $z->[_KEY] lt $y->[_KEY])
167 {
168 $y->[_LEFT] = $z;
169 }
170 else {
171 $y->[_RIGHT] = $z;
172 }
173 }
174 _update_max($z);
175 $self->_fix_after_insertion($z);
176 $self->[SIZE]++;
177 }
178
179 sub _fix_after_insertion {
180 my $self = shift;
181 my $x = shift or croak('Missing arg: node');
182
183 $x->[_COLOR] = RED;
184 while($x != $self->[ROOT] && $x->[_PARENT][_COLOR] == RED) {
185 my ($child, $rotate1, $rotate2);
186 if(($x->[_PARENT] || 0) == ($x->[_PARENT][_PARENT][_LEFT] || 0)) {
187 ($child, $rotate1, $rotate2) = (_RIGHT, '_left_rotate', '_right_rotate');
188 }
189 else {
190 ($child, $rotate1, $rotate2) = (_LEFT, '_right_rotate', '_left_rotate');
191 }
192 my $y = $x->[_PARENT][_PARENT][$child];
193
194 if($y && $y->[_COLOR] == RED) {
195 $x->[_PARENT][_COLOR] = BLACK;
196 $y->[_COLOR] = BLACK;
197 $x->[_PARENT][_PARENT][_COLOR] = RED;
198 $x = $x->[_PARENT][_PARENT];
199 }
200 else {
201 if($x == ($x->[_PARENT][$child] || 0)) {
202 $x = $x->[_PARENT];
203 $self->$rotate1($x);
204 }
205 $x->[_PARENT][_COLOR] = BLACK;
206 $x->[_PARENT][_PARENT][_COLOR] = RED;
207 $self->$rotate2($x->[_PARENT][_PARENT]);
208 }
209 }
210 $self->[ROOT][_COLOR] = BLACK;
211 }
212
213 sub delete {
214 my ($self, $key_or_node) = @_;
215 defined $key_or_node
216 or croak("Can't use undefined value as key or node");
217
218 my $z = (ref $key_or_node eq 'Tree::Interval::Node')
219 ? $key_or_node
220 : ($self->lookup($key_or_node))[1];
221 return unless $z;
222
223 my $y;
224 if($z->[_LEFT] && $z->[_RIGHT]) {
225 # (Notes kindly provided by Christopher Gurnee)
226 # When deleting a node 'z' which has two children from a binary search tree, the
227 # typical algorithm is to delete the successor node 'y' instead (which is
228 # guaranteed to have at most one child), and then to overwrite the key/values of
229 # node 'z' (which is still in the tree) with the key/values (which we don't want
230 # to lose) from the now-deleted successor node 'y'.
231
232 # Since we need to return the deleted item, it's not good enough to overwrite the
233 # key/values of node 'z' with those of node 'y'. Instead we swap them so we can
234 # return the deleted values.
235
236 $y = $z->predecessor;
237 ($z->[_KEY], $y->[_KEY]) = ($y->[_KEY], $z->[_KEY]);
238 ($z->[_VAL], $y->[_VAL]) = ($y->[_VAL], $z->[_VAL]);
239 ($z->[_INTERVAL], $y->[_INTERVAL]) = ($y->[_INTERVAL], $z->[_INTERVAL]);
240 }
241 else {
242 $y = $z;
243 }
244
245 # splice out $y
246 my $x = $y->[_LEFT] || $y->[_RIGHT];
247 if(defined $x) {
248 $x->[_PARENT] = $y->[_PARENT];
249 if(! defined $y->[_PARENT]) {
250 $self->[ROOT] = $x;
251 }
252 elsif($y == $y->[_PARENT][_LEFT]) {
253 $y->[_PARENT][_LEFT] = $x;
254 }
255 else {
256 $y->[_PARENT][_RIGHT] = $x;
257 }
258 # Null out links so they are OK to use by _fix_after_deletion
259 delete @{$y}[_PARENT, _LEFT, _RIGHT];
260 _update_max($x);
261 # Fix replacement
262 if($y->[_COLOR] == BLACK) {
263 $self->_fix_after_deletion($x);
264 }
265 }
266 elsif(! defined $y->[_PARENT]) {
267 # return if we are the only node
268 delete $self->[ROOT];
269 }
270 else {
271 # No children. Use self as phantom replacement and unlink
272 if($y->[_COLOR] == BLACK) {
273 $self->_fix_after_deletion($y);
274 }
275 if(defined $y->[_PARENT]) {
276 no warnings 'uninitialized';
277 if($y == $y->[_PARENT][_LEFT]) {
278 delete $y->[_PARENT][_LEFT];
279 }
280 elsif($y == $y->[_PARENT][_RIGHT]) {
281 delete $y->[_PARENT][_RIGHT];
282 }
283 my $tmp = $y->[_PARENT];
284 delete $y->[_PARENT];
285 _update_max($tmp);
286 }
287 }
288 $self->[SIZE]--;
289 return $y;
290 }
291
292 sub _fix_after_deletion {
293 my $self = shift;
294 my $x = shift or croak('Missing arg: node');
295
296 while($x != $self->[ROOT] && color_of($x) == BLACK) {
297 my ($child1, $child2, $rotate1, $rotate2);
298 no warnings 'uninitialized';
299 if($x == left_of(parent_of($x))) {
300 ($child1, $child2, $rotate1, $rotate2) =
301 (\&right_of, \&left_of, '_left_rotate', '_right_rotate');
302 }
303 else {
304 ($child1, $child2, $rotate1, $rotate2) =
305 (\&left_of, \&right_of, '_right_rotate', '_left_rotate');
306 }
307 use warnings;
308
309 my $w = $child1->(parent_of($x));
310 if(color_of($w) == RED) {
311 set_color($w, BLACK);
312 set_color(parent_of($x), RED);
313 $self->$rotate1(parent_of($x));
314 $w = right_of(parent_of($x));
315 }
316 if(color_of($child2->($w)) == BLACK &&
317 color_of($child1->($w)) == BLACK) {
318 set_color($w, RED);
319 $x = parent_of($x);
320 }
321 else {
322 if(color_of($child1->($w)) == BLACK) {
323 set_color($child2->($w), BLACK);
324 set_color($w, RED);
325 $self->$rotate2($w);
326 $w = $child1->(parent_of($x));
327 }
328 set_color($w, color_of(parent_of($x)));
329 set_color(parent_of($x), BLACK);
330 set_color($child1->($w), BLACK);
331 $self->$rotate1(parent_of($x));
332 $x = $self->[ROOT];
333 }
334 }
335 set_color($x, BLACK);
336 }
337
338
339 sub _max3 {
340 my ($a, $b, $c) = @_;
341 my $min = ($a || $b || $c) - 1;
342 $a = $a || $min;
343 $b = $b || $min;
344 $c = $c || $min;
345 return $a if($a >= $b && $a >= $c);
346 return $b if($b >= $a && $b >= $c);
347 return $c if($c >= $a && $c >= $b);
348 }
349
350 sub _max {
351 my $x = shift;
352 my $tmp = _max3($x->[_INTERVAL][1],
353 $x->[_LEFT] ? $x->[_LEFT][_MAX] : undef,
354 $x->[_RIGHT] ? $x->[_RIGHT][_MAX] : undef);
355 $x->[_MAX] = $tmp;
356 return $tmp;
357 }
358
359 sub _update_max {
360 my $x = shift;
361 #update the max field for each parent node
362 _max($x);
363 my $k = $x->[_PARENT];
364 while($k) {
365 my $tmp = $k->[_MAX];
366 _max($k);
367 last if($tmp == $k->[_MAX]); # no need to update further
368 $k = $k->[_PARENT];
369 }
370 }
371
372 sub _left_rotate {
373 my $self = shift;
374 my $x = shift or croak('Missing arg: node');
375
376 my $y = $x->[_RIGHT]
377 or return;
378 $x->[_RIGHT] = $y->[_LEFT];
379 if($y->[_LEFT]) {
380 $y->[_LEFT]->[_PARENT] = $x;
381 }
382 $y->[_PARENT] = $x->[_PARENT];
383 if(not defined $x->[_PARENT]) {
384 $self->[ROOT] = $y;
385 }
386 else {
387 $x == $x->[_PARENT]->[_LEFT]
388 ? $x->[_PARENT]->[_LEFT] = $y
389 : $x->[_PARENT]->[_RIGHT] = $y;
390 }
391 $y->[_LEFT] = $x;
392 $x->[_PARENT] = $y;
393 #update max
394 _max($x); _max($y);
395 }
396
397 sub _right_rotate {
398 my $self = shift;
399 my $y = shift or croak('Missing arg: node');
400
401 my $x = $y->[_LEFT]
402 or return;
403 $y->[_LEFT] = $x->[_RIGHT];
404 if($x->[_RIGHT]) {
405 $x->[_RIGHT]->[_PARENT] = $y
406 }
407 $x->[_PARENT] = $y->[_PARENT];
408 if(not defined $y->[_PARENT]) {
409 $self->[ROOT] = $x;
410 }
411 else {
412 $y == $y->[_PARENT]->[_RIGHT]
413 ? $y->[_PARENT]->[_RIGHT] = $x
414 : $y->[_PARENT]->[_LEFT] = $x;
415 }
416 $x->[_RIGHT] = $y;
417 $y->[_PARENT] = $x;
418 _max($y); _max($x);
419 }
420
421 1;
422
423 # Magic true value required at end of module
424 __END__
425
426 =head1 NAME
427
428 Tree::RB - Perl implementation of the Red/Black tree, a type of balanced binary search tree.
429
430
431 =head1 VERSION
432
433 This document describes Tree::RB version 0.1
434
435
436 =head1 SYNOPSIS
437
438 use Tree::RB;
439
440 my $tree = Tree::RB->new;
441 $tree->put('France' => 'Paris');
442 $tree->put('England' => 'London');
443 $tree->put('Hungary' => 'Budapest');
444 $tree->put('Ireland' => 'Dublin');
445 $tree->put('Egypt' => 'Cairo');
446 $tree->put('Germany' => 'Berlin');
447
448 $tree->put('Alaska' => 'Anchorage'); # D'oh!
449 $tree->delete('Alaska');
450
451 print $tree->get('Ireland'); # 'Dublin'
452
453 print $tree->min->key; # 'Egypt'
454 print $tree->max->key; # 'Ireland'
455 print $tree->size; # 6
456
457 # print items, ordered by key
458 my $it = $tree->iter;
459
460 while(my $node = $it->next) {
461 sprintf "key = %s, value = %s\n", $node->key, $node->val;
462 }
463
464 # print items in reverse order
465 $it = $tree->rev_iter;
466
467 while(my $node = $it->next) {
468 sprintf "key = %s, value = %s\n", $node->key, $node->val;
469 }
470
471 # Hash interface
472 tie my %capital, 'Tree::RB';
473
474 # or do this to store items in descending order
475 tie my %capital, 'Tree::RB', sub { $_[1] cmp $_[0] };
476
477 $capital{'France'} = 'Paris';
478 $capital{'England'} = 'London';
479 $capital{'Hungary'} = 'Budapest';
480 $capital{'Ireland'} = 'Dublin';
481 $capital{'Egypt'} = 'Cairo';
482 $capital{'Germany'} = 'Berlin';
483
484 # print items in order
485 while(my ($key, $val) = each %capital) {
486 printf "key = $key, value = $val\n";
487 }
488
489 =head1 DESCRIPTION
490
491 This is a Perl implementation of the Red/Black tree, a type of balanced binary search tree.
492
493 A tied hash interface is also provided to allow ordered hashes to be used.
494
495 See the Wikipedia article at L<http://en.wikipedia.org/wiki/Red-black_tree> for more on Red/Black trees.
496
497
498 =head1 INTERFACE
499
500 =head2 new([CODEREF])
501
502 Creates and returns a new tree. If a reference to a subroutine is passed to
503 new(), the subroutine will be used to override the tree's default lexical
504 ordering and provide a user a defined ordering.
505
506 This subroutine should be just like a comparator subroutine used with L<sort>,
507 except that it doesn't do the $a, $b trick.
508
509 For example, to get a case insensitive ordering
510
511 my $tree = Tree::RB->new(sub { lc $_[0] cmp lc $_[1]});
512 $tree->put('Wall' => 'Larry');
513 $tree->put('Smith' => 'Agent');
514 $tree->put('mouse' => 'micky');
515 $tree->put('duck' => 'donald');
516
517 my $it = $tree->iter;
518
519 while(my $node = $it->next) {
520 sprintf "key = %s, value = %s\n", $node->key, $node->val;
521 }
522
523 =head2 resort(CODEREF)
524
525 Changes the ordering of nodes within the tree. The new ordering is
526 specified by a comparator subroutine which must be passed to resort().
527
528 See L</new> for further information about the comparator.
529
530 =head2 size()
531
532 Returns the number of nodes in the tree.
533
534 =head2 root()
535
536 Returns the root node of the tree. This will either be undef
537 if no nodes have been added to the tree, or a L<Tree::RB::Node> object.
538 See the L<Tree::RB::Node> manual page for details on the Node object.
539
540 =head2 min()
541
542 Returns the node with the minimal key.
543
544 =head2 max()
545
546 Returns the node with the maximal key.
547
548 =head2 lookup(KEY, [MODE])
549
550 When called in scalar context, lookup(KEY) returns the value
551 associated with KEY.
552
553 When called in list context, lookup(KEY) returns a list whose first
554 element is the value associated with KEY, and whose second element
555 is the node containing the key/value.
556
557 An optional MODE parameter can be passed to lookup() to influence
558 which key is returned.
559
560 The values of MODE are constants that are exported on demand by
561 Tree::RB
562
563 use Tree::RB qw[LUEQUAL LUGTEQ LULTEQ LUGREAT LULESS LUNEXT LUPREV];
564
565 =over
566
567 =item LUEQUAL
568
569 Returns node exactly matching the key.
570
571 =item LUGTEQ
572
573 Returns the node exactly matching the specified key,
574 if this is not found then the next node that is greater than the specified key is returned.
575
576 =item LULTEQ
577
578 Returns the node exactly matching the specified key,
579 if this is not found then the next node that is less than the specified key is returned.
580
581 =item LUGREAT
582
583 Returns the node that is just greater than the specified key - not equal to.
584 This mode is similar to LUNEXT except that the specified key need not exist in the tree.
585
586 =item LULESS
587
588 Returns the node that is just less than the specified key - not equal to.
589 This mode is similar to LUPREV except that the specified key need not exist in the tree.
590
591 =item LUNEXT
592
593 Looks for the key specified, if not found returns C<undef>.
594 If the node is found returns the next node that is greater than
595 the one found (or C<undef> if there is no next node).
596
597 This can be used to step through the tree in order.
598
599 =item LUPREV
600
601 Looks for the key specified, if not found returns C<undef>.
602 If the node is found returns the previous node that is less than
603 the one found (or C<undef> if there is no previous node).
604
605 This can be used to step through the tree in reverse order.
606
607 =back
608
609 =head2 get(KEY)
610
611 get() is an alias for lookup().
612
613 =head2 iter([KEY])
614
615 Returns an iterator object that can be used to traverse the tree in order.
616
617 The iterator object supports a 'next' method that returns the next node in the
618 tree or undef if all of the nodes have been visited.
619
620 See the synopsis for an example.
621
622 If a key is supplied, the iterator returned will traverse the tree in order starting from
623 the node with key greater than or equal to the specified key.
624
625 $it = $tree->iter('France');
626 my $node = $it->next;
627 print $node->key; # -> 'France'
628
629 =head2 rev_iter([KEY])
630
631 Returns an iterator object that can be used to traverse the tree in reverse order.
632
633 If a key is supplied, the iterator returned will traverse the tree in order starting from
634 the node with key less than or equal to the specified key.
635
636 $it = $tree->rev_iter('France');
637 my $node = $it->next;
638 print $node->key; # -> 'England'
639
640 =head2 hseek(KEY, [{-reverse => 1|0}])
641
642 For tied hashes, determines the next entry to be returned by each.
643
644 tie my %capital, 'Tree::RB';
645
646 $capital{'France'} = 'Paris';
647 $capital{'England'} = 'London';
648 $capital{'Hungary'} = 'Budapest';
649 $capital{'Ireland'} = 'Dublin';
650 $capital{'Egypt'} = 'Cairo';
651 $capital{'Germany'} = 'Berlin';
652 tied(%capital)->hseek('Germany');
653
654 ($key, $val) = each %capital;
655 print "$key, $val"; # -> Germany, Berlin
656
657 The direction of iteration can be reversed by passing a hashref with key '-reverse' and value 1
658 to hseek after or instead of KEY, e.g. to iterate over the hash in reverse order:
659
660 tied(%capital)->hseek({-reverse => 1});
661 $key = each %capital;
662 print $key; # -> Ireland
663
664 The following calls are equivalent
665
666 tied(%capital)->hseek('Germany', {-reverse => 1});
667 tied(%capital)->hseek({-key => 'Germany', -reverse => 1});
668
669 =head2 put(KEY, VALUE)
670
671 Adds a new node to the tree.
672
673 The first argument is the key of the node, the second is its value.
674
675 If a node with that key already exists, its value is replaced with
676 the given value and the old value is returned. Otherwise, undef is returned.
677
678 =head2 delete(KEY)
679
680 If the tree has a node with the specified key, that node is
681 deleted from the tree and returned, otherwise C<undef> is returned.
682
683
684 =head1 DEPENDENCIES
685
686 L<enum>
687
688
689 =head1 INCOMPATIBILITIES
690
691 None reported.
692
693
694 =head1 BUGS AND LIMITATIONS
695
696 Please report any bugs or feature requests to
697 C<bug-tree-rb@rt.cpan.org>, or through the web interface at
698 L<http://rt.cpan.org>.
699
700
701 =head1 AUTHOR
702
703 Arun Prasad C<< <arunbear@cpan.org> >>
704
705 Some documentation has been borrowed from Benjamin Holzman's L<Tree::RedBlack>
706 and Damian Ivereigh's libredblack (L<http://libredblack.sourceforge.net/>).
707
708 =head1 ACKNOWLEDGEMENTS
709
710 Thanks for bug reports go to Anton Petrusevich, Wes Thompson and Christopher Gurnee.
711
712 =head1 LICENCE AND COPYRIGHT
713
714 Copyright (c) 2007, Arun Prasad C<< <arunbear@cpan.org> >>. All rights reserved.
715
716 This module is free software; you can redistribute it and/or
717 modify it under the same terms as Perl itself. See L<perlartistic>.
718
719
720 =head1 DISCLAIMER OF WARRANTY
721
722 BECAUSE THIS SOFTWARE IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
723 FOR THE SOFTWARE, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
724 OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
725 PROVIDE THE SOFTWARE "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
726 EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
727 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE
728 ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE SOFTWARE IS WITH
729 YOU. SHOULD THE SOFTWARE PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
730 NECESSARY SERVICING, REPAIR, OR CORRECTION.
731
732 IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
733 WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
734 REDISTRIBUTE THE SOFTWARE AS PERMITTED BY THE ABOVE LICENCE, BE
735 LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL,
736 OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE
737 THE SOFTWARE (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
738 RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
739 FAILURE OF THE SOFTWARE TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
740 SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
741 SUCH DAMAGES.