man Set::IntSpan () - Manages sets of integers

NAME

Set::IntSpan - Manages sets of integers

SYNOPSIS

  use Set::IntSpan qw(grep_set map_set);

  $Set::IntSpan::Empty_String = $string;

  $set    = new   Set::IntSpan $set_spec;
  $valid  = valid Set::IntSpan $run_list;
  $set    = copy  $set $set_spec;

  $run_list = run_list $set;
  @elements = elements $set;

  $u_set = union      $set $set_spec;
  $i_set = intersect  $set $set_spec;
  $x_set = xor        $set $set_spec;
  $d_set = diff       $set $set_spec;
  $c_set = complement $set;

  equal      $set $set_spec;
  equivalent $set $set_spec;
  superset   $set $set_spec;
  subset     $set $set_spec;

  $n = cardinality $set;

  empty      $set;
  finite     $set;
  neg_inf    $set;
  pos_inf    $set;
  infinite   $set;
  universal  $set;

  member     $set $n;
  insert     $set $n;
  remove     $set $n;

  $min = min $set;
  $max = max $set;

  $subset = grep_set { ... } $set;
  $mapset = map_set  { ... } $set;

  for ($element=$set->first; defined $element; $element=$set->next) { ... }
  for ($element=$set->last ; defined $element; $element=$set->prev) { ... }

  $element = $set->start($n);
  $element = $set->current;

REQUIRES

Perl 5.004, Exporter

EXPORTS

Nothing CWgrep_set, CWmap_set

DESCRIPTION

CWSet::IntSpan manages sets of integers. It is optimized for sets that have long runs of consecutive integers. These arise, for example, in .newsrc files, which maintain lists of articles:

  alt.foo: 1-21,28,31
  alt.bar: 1-14192,14194,14196-14221

Sets are stored internally in a run-length coded form. This provides for both compact storage and efficient computation. In particular, set operations can be performed directly on the encoded representation.

CWSet::IntSpan is designed to manage finite sets. However, it can also represent some simple infinite sets, such as {x | x>n}. This allows operations involving complements to be carried out consistently, without having to worry about the actual value of INT_MAX on your machine.

SET SPECIFICATIONS

Many of the methods take a set specification. There are four kinds of set specifications.

Empty

If a set specification is omitted, then the empty set is assumed. Thus,

  $set = new Set::IntSpan;

creates a new, empty set. Similarly,

  copy $set;

removes all elements from CW$set.

Object reference

If an object reference is given, it is taken to be a CWSet::IntSpan object.

Array reference

If an array reference is given, then the elements of the array are taken to be the elements of the set. The array may contain duplicate elements. The elements of the array may be in any order.

Run list

If a string is given, it is taken to be a run list. A run list specifies a set using a syntax similar to that in newsrc files.

A run list is a comma-separated list of runs. Each run specifies a set of consecutive integers. The set is the union of all the runs.

Runs may be written in any of several forms.

Finite forms

n
{ n }
a-b
{x | a<=x && x<=b}

Infinite forms

(-n
{x | x<=n}
n-)
{x | x>=n}
(-)
The set of all integers

Empty forms

The empty set is consistently written as '' (the null string). It is also denoted by the special form '-' (a single dash).

Restrictions

The runs in a run list must be disjoint, and must be listed in increasing order.

Valid characters in a run list are 0-9, '(', ')', '-' and ','. White space and underscore (_) are ignored. Other characters are not allowed.

Examples

-
{ }
1
{ 1 }
1-2
{ 1, 2 }
-5--1
{ -5, -4, -3, -2, -1 }
(-)
the integers
(--1
the negative integers
1-3, 4, 18-21
{ 1, 2, 3, 4, 18, 19, 20, 21 }

ITERATORS

Each set has a single iterator, which is shared by all calls to CWfirst, CWlast, CWstart, CWnext, CWprev, and CWcurrent. At all times, the iterator is either an element of the set, or CWundef.

CWfirst, CWlast, and CWstart set the iterator; CWnext, and CWprev move it; and CWcurrent returns it. Calls to these methods may be freely intermixed.

Using CWnext and CWprev, a single loop can move both forwards and backwards through a set. Using CWstart, a loop can iterate over portions of an infinite set.

METHODS

Creation

Creates and returns a CWSet::IntSpan object. The initial contents of the set are given by $set_spec. Returns true if $run_list is a valid run list. Otherwise, returns false and leaves an error message in $@. Copies $set_spec into $set. The previous contents of $set are lost. For convenience, CWcopy returns $set. Returns a run list that represents $set. The run list will not contain white space. $set is not affected. By default, the empty set is formatted as '-'; a different string may be specified in CW$Set::IntSpan::Empty_String. Returns an array containing the elements of $set. The elements will be sorted in numerical order. In scalar context, returns an array reference. $set is not affected.

Set operations

Returns the set of integers in either $set or $set_spec. Returns the set of integers in both $set and $set_spec. Returns the set of integers in $set or $set_spec, but not both. Returns the set of integers in $set but not in $set_spec. Returns the set of integers that are not in $set.

For all set operations, a new CWSet::IntSpan object is created and returned. The operands are not affected.

Comparison

Returns true iff $set and $set_spec contain the same elements. Returns true iff $set and $set_spec contain the same number of elements. All infinite sets are equivalent. Returns true iff $set is a superset of $set_spec. Returns true iff $set is a subset of $set_spec.

Cardinality

Returns the number of elements in $set. Returns -1 for infinite sets. Returns true iff $set is empty. Returns true iff $set is finite. Returns true iff $set contains {x | x<n} for some n. Returns true iff $set contains {x | x>n} for some n. Returns true iff $set is infinite.

universal $set
Returns true iff $set contains all integers.

Membership

Returns true iff the integer $n is a member of $set. Inserts the integer $n into $set. Does nothing if $n is already a member of $set. Removes the integer $n from $set. Does nothing if $n is not a member of $set.

Extrema

Returns the smallest element of $set, or CWundef if there is none. Returns the largest element of $set, or CWundef if there is none.

Iterators

Sets the iterator for $set to the smallest element of $set. If there is no smallest element, sets the iterator to CWundef. Returns the iterator. Sets the iterator for $set to the largest element of $set. If there is no largest element, sets the iterator to CWundef. Returns the iterator. Sets the iterator for $set to $n. If $n is not an element of $set, sets the iterator to CWundef. Returns the iterator. Sets the iterator for $set to the next element of $set. If there is no next element, sets the iterator to CWundef. Returns the iterator. CWnext will return CWundef only once; the next call to CWnext will reset the iterator to the smallest element of $set. Sets the iterator for $set to the previous element of $set. If there is no previous element, sets the iterator to CWundef. Returns the iterator. CWprev will return CWundef only once; the next call to CWprev will reset the iterator to the largest element of $set. Returns the iterator for $set.

FUNCTIONS

Evaluates the BLOCK for each integer in $set (locally setting CW$_ to each integer) and returns a CWSet::IntSpan object containing those integers for which the BLOCK returns TRUE. Returns CWundef if $set is infinite. Evaluates the BLOCK for each integer in $set (locally setting CW$_ to each integer) and returns a CWSet::IntSpan object containg all the integers returned as results of all those evaluations. Evaluates the BLOCK in list context, so each element of $set may produce zero, one, or more elements in the returned set. Returns CWundef if $set is infinite.

CLASS VARIABLES

CW$Set::IntSpan::Empty_String contains the string that is returned when CWrun_list is called on the empty set. CW$Empty_String is initially '-'; alternatively, it may be set to ''. Other values should be avoided, to ensure that CWrun_list always returns a valid run list. CWrun_list accesses CW$Empty_String through a reference stored in $set->{CWempty_string}. Subclasses that wish to override the value of CW$Empty_String can reassign this reference.

DIAGNOSTICS

Any method (except CWvalid) will CWdie if it is passed an invalid run list. (F) $run_list has bad syntax (F) $run_list has overlapping runs or runs that are out of order. (F) An infinte set was passed to CWelements.

Out of memory!
(X) CWelements $set can generate an Out of memory! message on sufficiently large finite sets.

NOTES

Traps

Beware of forms like

  union $set [1..5];

This passes an element of CW@set to union, which is probably not what you want. To force interpretation of CW$set and [1..5] as separate arguments, use forms like

    union $set +[1..5];

or

    $set->union([1..5]);

Cardinality

You cannot use the obvious comparison routine

  { $a->cardinality <=> $b->cardinality }

to sort sets by size, because CWcardinality returns -1 for infinte sets. (All the non-negative integers were taken. Sorry.)

Instead, you have to write something like

  {  my $a_card = $a->cardinality;
     my $b_card = $b->cardinality;

     $a_card == $b_card and return  0;
     $a_card <  0       and return  1;
     $b_card <  0       and return -1;
     $a_card <=> $b_card                }

grep_set and map_set

CWgrep_set and CWmap_set make it easy to construct sets for which the internal representation used by CWSet::IntSpan is not small. Consider:

  $billion = new Set::IntSpan '0-1_000_000_000';   # OK
  $odd     = grep_set { $_ & 1 } $billion;         # trouble
  $even    = map_set  { $_ * 2 } $billion;         # double trouble

Error handling

There are two common approaches to error handling: exceptions and return codes. There seems to be some religion on the topic, so CWSet::IntSpan provides support for both.

To catch exceptions, protect method calls with an eval:

    $run_list = <STDIN>;
    eval { $set = new Set::IntSpan $run_list };
    $@ and print "$@: try again\n";

To check return codes, use an appropriate method call to validate arguments:

    $run_list = <STDIN>;
    if (valid Set::IntSpan $run_list) 
       { $set = new Set::IntSpan $run_list }
    else
       { print "$@ try again\n" }

Similarly, use CWfinite to protect calls to CWelements:

    finite $set and @elements = elements $set;

Calling CWelements on a large, finite set can generate an Out of memory! message, which cannot (easily) be trapped. Applications that must retain control after an error can use CWintersect to protect calls to CWelements:

    @elements = elements { intersect $set "-1_000_000 - 1_000_000" };

or check the size of CW$set first:

    finite $set and cardinality $set < 2_000_000 and @elements = elements $set;

Limitations

Although CWSet::IntSpan can represent some infinite sets, it does not perform infinite-precision arithmetic. Therefore, finite elements are restricted to the range of integers on your machine.

Roots

The sets implemented here are based on a Macintosh data structure called a region. See Inside Macintosh for more information.

AUTHOR

Steven McDougall, swmcd@world.std.com

COPYRIGHT

Copyright 1996-1998 by Steven McDougall. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.