1#############################################################################
2# Math/String/Charset/Grouped.pm -- a charset of charsets for Math/String
3#
4# Copyright (C) 1999-2003 by Tels. All rights reserved.
5#############################################################################
6
7package Math::String::Charset::Grouped;
8
9require 5.005;		# requires this Perl version or later
10use strict;
11
12use base 'Math::String::Charset';
13
14our $VERSION;
15$VERSION = '1.30';	# Current version of this package
16
17use Math::BigInt;
18
19our $die_on_error;
20$die_on_error = 1;              # set to 0 to not die
21
22# following hash values are used:
23# _clen  : length of one character (all chars must have same len unless sep)
24# _ones  : list of one-character strings (cross of _end and _start)
25# _start : contains array of all valid start characters
26# _end   : contains hash (for easier lookup) of all valid end characters
27# _order : = 1
28# _type  : = 1
29# _error : error message or ""
30# _count : array of count of different strings with length x
31# _sum   : array of starting number for strings with length x
32#          _sum[x] = _sum[x-1]+_count[x-1]
33# _cnt   : number of elements in _count and _sum (as well as in _scnt & _ssum)
34# _cnum  : number of characters in _ones as BigInt (for speed)
35# _minlen: minimum string length (anything shorter is invalid), default -inf
36# _maxlen: maximum string length (anything longer is invalid), default +inf
37# _scale : optional input/output scale
38
39# simple ones:
40# _sep  : separator string (undef for none)
41# _map  : mapping character to number
42
43# higher orders:
44# _bi   : hash with refs to array of bi-grams
45# _bmap : hash with refs to hash of bi-grams
46# _scnt : array of hashes, count of strings starting with this character
47
48# grouped:
49# _spat	: array with pattern of charsets 8for each stirnglen one ARRAY ref)
50
51#############################################################################
52# private, initialize self
53
54sub _strict_check
55  {
56  # a per class check, to be overwritten by subclasses
57  my $self = shift;
58  my $value = shift;
59
60  my $class = ref($self);
61  return $self->{_error} = "Wrong type '$self->{_type}' for $class"
62    if $self->{_type} != 1;
63  return $self->{_error} = "Wrong order'$self->{_order}' for $class"
64    if $self->{_order} != 1;
65  foreach my $key (keys %$value)
66    {
67    return $self->{_error} = "Illegal parameter '$key' for $class"
68      if $key !~ /^(start|minlen|maxlen|sep|sets|end|charlen|scale)$/;
69    }
70  }
71
72sub _initialize
73  {
74  # set yourself to the value represented by the given string
75  my $self = shift;
76  my $value = shift;
77
78  $self->{_clen} = $value->{charlen};
79  $self->{_sep}  = $value->{sep};	# separator char
80
81  return $self->{_error} = "Need HASH ref as 'sets'"
82    if (ref($value->{sets}) ne 'HASH');
83
84  # make copy at same time
85  foreach my $key (keys %{$value->{sets}})
86    {
87    $self->{_sets}->{$key} = $value->{sets}->{$key};
88    }
89
90  # start/end are sets 1 and -1, respectively, and overwrite 'sets'
91  $self->{_sets}->{1} = $value->{start} if exists $value->{start};
92  $self->{_sets}->{-1} = $value->{end} if exists $value->{end};
93  $self->{_sets}->{0} = $value->{chars} if exists $value->{chars};
94  # default set
95  $self->{_sets}->{0} = ['a'..'z'] if !defined $self->{_sets}->{0};
96
97  my $sets = $self->{_sets};	# shortcut
98  foreach my $set (keys %$sets)
99    {
100    return $self->{_error} =
101      "Entries in 'sets' must be ref to Math::String::Charset or ARRAY"
102     if ((ref($sets->{$set}) ne 'ARRAY') &&
103      (ref($sets->{$set}) ne 'Math::String::Charset'));
104
105    # so for each set, make a Math::String::Charset
106    $sets->{$set} = Math::String::Charset->new($sets->{$set})
107      if ref($sets->{$set}) eq 'ARRAY';
108    }
109  $self->{_start} = $sets->{1} || $sets->{0};
110  $self->{_end} = $sets->{-1} || $sets->{0};
111
112  $self->{_clen} = $self->{_start}->charlen() if
113   ((!defined $self->{_clen}) && (!defined $self->{_sep}));
114
115  # build _ones list (cross from start/end)
116  $self->{_ones} = [];
117
118  # _end is a simple charset, so use it's map directly
119  my $end = $self->{_end}->{_map};
120  my $o = $self->{_ones};
121  foreach ($self->{_start}->start())
122    {
123    push @$o, $_ if exists $end->{$_};
124    }
125  #print "\n";
126
127  # some tests for validity
128  if (!defined $self->{_sep})
129    {
130    foreach (keys %{$self->{_sets}})
131      {
132      my $l = $self->{_sets}->{$_}->charlen();
133      return $self->{_error} =
134        "Illegal character length '$l' for charset '$_', expected '$self->{_clen}'"
135          if $self->{_sets}->{$_}->charlen() != $self->{_clen};
136
137      }
138    }
139  $self->{_cnum} = Math::BigInt->new( scalar @{$self->{_ones}} );
140  # initialize array of counts for len of 0..1
141  $self->{_cnt} = 2;				# cached amount of class-sizes
142  if ($self->{_minlen} <= 0)
143    {
144    $self->{_count}->[0] = 1;			# '' is one string
145    my $sl = $self->{_start}->length();
146    my $el = $self->{_end}->length();
147    $self->{_count}->[1] = $self->{_cnum};
148    $self->{_count}->[2] = $sl * $el;
149    # init _sum array
150    $self->{_sum}->[0] = Math::BigInt->bzero();
151    $self->{_sum}->[1] = Math::BigInt->bone();		# '' is 1 string
152    $self->{_sum}->[2] = $self->{_count}->[1] + $self->{_sum}->[1];
153    $self->{_sum}->[3] = $self->{_count}->[2] + $self->{_sum}->[2];
154    # init set patterns
155    $self->{_spat}->[1] = [ undef, $self->{_sets}->{0} ];
156    $self->{_spat}->[2] = [ undef, $self->{_start}, $self->{_end} ];
157    }
158  else
159    {
160    $self->{_cnt} = 0;				# cached amount of class-sizes
161    }
162
163  # from _ones, make mapping name => number
164  my $i = Math::BigInt->bone();
165  foreach (@{$self->{_ones}})
166    {
167    $self->{_map}->{$_} = $i++;
168    }
169
170  if ($self->{_cnum}->is_zero())
171    {
172    $self->{_minlen} = 2 if $self->{_minlen} == 1;	# no one's
173    # check whether charset can have 2-character long strings
174    if ($self->{_count}->[2] == 0)
175      {
176      $self->{_minlen} = 3 if $self->{_minlen} == 2;	# no two's
177      # check whether some path from start to end set exists, if not: empty
178      }
179    }
180  return $self->{_error} =
181   "Minlen ($self->{_minlen} must be smaller than maxlen ($self->{_maxlen})"
182    if ($self->{_minlen} > $self->{_maxlen});
183  return $self;
184  }
185
186sub dump
187  {
188  my $self = shift;
189
190  my $txt = "type: GROUPED\n";
191
192  foreach my $set (sort { $b<=>$a } keys %{$self->{_sets}})
193    {
194    $txt .= " $set => ". $self->{_sets}->{$set}->dump('   ');
195    }
196  $txt .= "ones : " . join(' ',@{$self->{_ones}}) . "\n";
197  $txt;
198  }
199
200sub _calc
201  {
202  # given count of len 1..x, calculate count for y (y > x) and all between
203  # x and y
204  # currently re-calcs from 2 on, we could save the state and only calculate
205  # the missing counts.
206
207#  print "calc ",caller(),"\n";
208  my $self = shift;
209  my $max = shift || 1; $max = 1 if $max < 1;
210  return if $max <= $self->{_cnt};
211
212#  print "in _calc $self $max\n";
213  my $i = $self->{_cnt};                # last defined element
214  my $last = $self->{_count}->[$i];
215  while ($i++ <= $max)
216    {
217    # build list of charsets for this length
218    my $spat = [];			# set patterns
219    my $sets = $self->{_sets};		# shortcut
220    for (my $j = 1; $j <= $i; $j++)
221      {
222      my $r = $j-$i-1;			# reverse
223#      print "$j reversed $r (for $i)\n";
224      $spat->[$j] = $sets->{$j} || $sets->{$r};			# one of both?
225      $spat->[$j] = $sets->{$j}->merge($sets->{$r}) if
226	exists $sets->{$j} && exists $sets->{$r};		# both?
227      $spat->[$j] = $sets->{0} unless defined $spat->[$j];	# none?
228#      print $spat->[$j]->dump(),"\n";
229      }
230    $self->{_spat}->[$i] = $spat;				# store
231    # for each charset, take size and mul together
232    $last = Math::BigInt->bone();
233    for (my $j = 1; $j <= $i; $j++)
234      {
235#      print "$i $spat->[$j]\n";
236      $last *= $spat->[$j]->length();
237#      print "last $last ",$spat->[$j]->length()," ($spat->[$j])\n";
238      }
239    $self->{_count}->[$i] = $last;
240#    print "$i: count $last ";
241    $self->{_sum}->[$i] = $self->{_sum}->[$i-1] + $self->{_count}->[$i-1];
242#    print "sum $self->{_sum}->[$i]\n";
243    }
244  $self->{_cnt} = $i-1;         # store new cache size
245  return;
246  }
247
248sub is_valid
249  {
250  # check wether a string conforms to the given charset sets
251  my $self = shift;
252  my $str = shift;
253
254  # print "$str\n";
255  return 0 if !defined $str;
256  return 1 if $str eq '' && $self->{_minlen} <= 0;
257
258  my @chars;
259  if (defined $self->{_sep})
260    {
261    @chars = split /$self->{_sep}/,$str;
262    shift @chars if $chars[0] eq '';
263    pop @chars if $chars[-1] eq $self->{_sep};
264    }
265  else
266    {
267    my $i = 0; my $len = CORE::length($str); my $clen = $self->{_clen};
268    while ($i < $len)
269      {
270      push @chars, substr($str,$i,$clen); $i += $clen;
271      }
272    }
273  # length okay?
274  return 0 if scalar @chars < $self->{_minlen};
275  return 0 if scalar @chars > $self->{_maxlen};
276
277  # valid start char?
278  return 0 unless defined $self->{_start}->map($chars[0]);
279  return 1 if @chars == 1;
280  # further checks for strings longer than 1
281  my $k = 1;
282  my $d = scalar @chars;
283  $self->_calc($d) if ($self->{_cnt} < $d);
284  my $spat = $self->{_spat}->[$d];
285  foreach my $c (@chars)
286    {
287    return 0 if !defined $spat->[$k++]->map($c);
288    }
289  # all tests passed
290  1;
291  }
292
293sub minlen
294  {
295  my $self = shift;
296
297  $self->{_minlen};
298  }
299
300sub maxlen
301  {
302  my $self = shift;
303
304  $self->{_maxlen};
305  }
306
307sub start
308  {
309  # this returns all the starting characters in a list, or in case of a simple
310  # charset, simple the charset
311  # in scalar context, returns length of starting set, for simple charsets this
312  # equals the length
313  my $self = shift;
314
315  wantarray ? @{$self->{_start}} : scalar @{$self->{_start}};
316  }
317
318sub end
319  {
320  # this returns all the end characters in a list, or in case of a simple
321  # charset, simple the charset
322  # in scalar context, returns length of end set, for simple charsets this
323  # equals the length
324  my $self = shift;
325
326  wantarray ? sort keys %{$self->{_end}} : scalar keys %{$self->{_end}};
327  }
328
329sub ones
330  {
331  # this returns all the one-char strings (in scalar context the count of them)
332  my $self = shift;
333
334  wantarray ? @{$self->{_ones}} : scalar @{$self->{_ones}};
335  }
336
337sub num2str
338  {
339  # convert Math::BigInt/Math::String to string
340  # in list context, return (string,stringlen)
341  my $self = shift;
342  my $x = shift;
343
344  $x = new Math::BigInt($x) unless ref $x;
345  return undef if ($x->sign() !~ /^[+-]$/);
346  if ($x->is_zero())
347    {
348    return wantarray ? ('',0) : '';
349    }
350  my $j = $self->{_cnum};			# nr of chars
351
352  if ($x <= $j)
353    {
354    my $c =  $self->{_ones}->[$x-1];
355    return wantarray ? ($c,1) : $c;             # string len == 1
356    }
357
358  my $digits = $self->chars($x); my $d = $digits;
359  # now treat the string as it were a zero-padded string of length $digits
360
361  my $es="";                                    # result
362  # copy input, make positive number, correct to $digits and cater for 0
363  my $y = Math::BigInt->new($x); $y->babs();
364  #print "fac $j y: $y new: ";
365  $y -= $self->{_sum}->[$digits];
366
367  $self->_calc($d) if ($self->{_cnt} < $d);
368  #print "y: $y\n";
369  my $mod = 0; my $s = $self->{_sep}; $s = '' if !defined $s;
370  my $spat = $self->{_spat}->[$d];		# set pattern
371  my $k = $d;
372  while (!$y->is_zero())
373    {
374    #print "bfore:  y/fac: $y / $j \n";
375    ($y,$mod) = $y->bdiv($spat->[$k]->length());
376    #$es = $self->{_ones}->[$mod] . $s.$es;
377    $es = $spat->[$k--]->char($mod) . $s.$es;	# find mod'th char
378    #print "after:  div: $y rem: $mod \n";
379    $digits --;                         # one digit done
380    }
381  # padd the remaining digits with the zero-symbol
382  while ($digits-- > 0)
383    {
384    $es = $spat->[$k--]->char(0) . $s . $es;
385    }
386  $es =~ s/$s$//;                               # strip last sep 'char'
387  wantarray ? ($es,$d) : $es;
388  }
389
390sub str2num
391  {
392  # convert Math::String to Math::BigInt
393  my $self = shift;
394  my $str = shift;			# simple string
395
396  my $int = Math::BigInt->bzero();
397  my $i = CORE::length($str);
398
399  return $int if $i == 0;
400  # print "str2num $i $clen '$str'\n";
401  my $map = $self->{_map};
402  my $clen = $self->{_clen};		# len of one char
403
404  if ((!defined $self->{_sep}) && ($i == $clen))
405    {
406    return $int->bnan() if !exists $map->{$str};
407    return $map->{$str}->copy();
408    }
409
410  my $mul = Math::BigInt->bone();
411  my $cs;					# charset at pos i
412  my $k = 1;					# position
413  my $c = 0;					# chars in string
414  if (!defined $self->{_sep})
415    {
416    return $int->bnan() if $i % $clen != 0;	# not multiple times clen
417    $c = int($i/$clen);
418    $self->_calc($c) if ($self->{_cnt} < $c);
419    my $spat = $self->{_spat}->[$c];
420#    print "$c ($self->{_cnt}) spat: ",scalar @$spat,"\n";
421    $i -= $clen;
422    $k = $c;
423    while ($i >= 0)
424      {
425      $cs = $spat->[$k--];			# charset at pos k
426#      print "$i $k $cs nr $int ";
427#      print "mapped ",substr($str,$i,$clen)," => ",
428#       $cs->map(substr($str,$i,$clen)) || 0;
429#      print " mul $mul => ";
430      $int += $mul * $cs->map(substr($str,$i,$clen));
431      $mul *= $cs->length();
432#     print "mul $mul\n";
433      $i -= $clen;
434      }
435    }
436  else
437    {
438    # with sep char
439    my @chars = split /$self->{_sep}/, $str;
440    shift @chars if $chars[0] eq '';                    # strip leading sep
441    pop @chars if $chars[-1] eq $self->{_sep}; 		# strip trailing sep
442    $c = scalar @chars;
443    $self->_calc($c) if ($self->{_cnt} < $c);
444    my $spat = $self->{_spat}->[$c];
445    $k = $c;
446    foreach (reverse @chars)
447      {
448      $cs = $spat->[$k--];				# charset at pos k
449      $int += $mul * $cs->map($_);
450      $mul *= $cs->length();
451      }
452    }
453  $int + $self->{_sum}->[$c];				# add base sum
454  }
455
456#sub char
457#  {
458#  # return nth char from charset
459#  my $self = shift;
460#  my $char = shift || 0;
461#
462#  return undef if $char > scalar @{$self->{_ones}}; # dont create spurios elems
463#  return $self->{_ones}->[$char];
464#  }
465
466sub first
467  {
468  my $self = shift;
469  my $count = abs(shift || 0);
470
471  return if $count < $self->{_minlen};
472  return if defined $self->{_maxlen} && $count > $self->{_maxlen};
473  return '' if $count == 0;
474
475  return $self->{_ones}->[0] if $count == 1;
476
477  $self->_calc($count);
478  my $spat = $self->{_spat}->[$count];
479  my $es = '';
480  my $s = $self->{_sep} || '';
481  for (my $i = 1; $i <= $count; $i++)
482    {
483    $es .= $s . $spat->[$i]->char(0);
484    }
485  $s = quotemeta($s);
486  $es =~ s/^$s// if $s ne '';		# remove first sep
487  $es;
488  }
489
490sub last
491  {
492  my $self = shift;
493  my $count = abs(shift || 0);
494
495  return if $count < $self->{_minlen};
496  return if defined $self->{_maxlen} && $count > $self->{_maxlen};
497  return '' if $count == 0;
498
499  return $self->{_ones}->[-1] if $count == 1;
500
501  $self->_calc($count);
502  my $spat = $self->{_spat}->[$count];
503  my $es = '';
504  my $s = $self->{_sep} || '';
505  for (my $i = 1; $i <= $count; $i++)
506    {
507    $es .= $s . $spat->[$i]->char(-1);
508    }
509  $s = quotemeta($s);
510  $es =~ s/^$s// if $s ne '';		# remove first sep
511  $es;
512  }
513
514sub next
515  {
516  my $self = shift;
517  my $str = shift;
518
519  if ($str->{_cache} eq '')				# 0 => 1
520    {
521    my $min = $self->{_minlen}; $min = 1 if $min <= 0;
522    $str->{_cache} = $self->first($min);
523    return;
524    }
525
526  # only the rightmost digit is adjusted. If this overflows, we simple
527  # invalidate the cache. The time saved by updating the cache would be to
528  # small to be of use, especially since updating the cache takes more time
529  # then. Also, if the cached isn't used later, we would have spent the
530  # update-time in vain.
531
532  # for higher orders not ready yet
533  $str->{_cache} = undef;
534  }
535
536sub prev
537  {
538  my $self = shift;
539  my $str = shift;
540
541  if ($str->{_cache} eq '')				# 0 => -1
542    {
543    my $min = $self->{_minlen}; $min = -1 if $min >= 0;
544    $str->{_cache} = $self->first($min);
545    return;
546    }
547
548  # for higher orders not ready yet
549  $str->{_cache} = undef;
550  }
551
552__END__
553
554#############################################################################
555
556=pod
557
558=head1 NAME
559
560Math::String::Charset::Grouped - A charset of simple charsets for Math::String objects.
561
562=head1 SYNOPSIS
563
564    use Math::String::Charset::Grouped;
565
566=head1 REQUIRES
567
568perl5.005, Exporter, Math::BigInt, Math::String::Charset
569
570=head1 EXPORTS
571
572Exports nothing.
573
574=head1 DESCRIPTION
575
576This module lets you create an charset object, which is used to construct
577Math::String objects.
578
579This object can assign for each position in a Math::String a different simple
580charset (aka a Math::String::Charset object of order => 1, type => 0).
581
582=over 1
583
584=item Default charset
585
586The default charset is the set containing "abcdefghijklmnopqrstuvwxyz"
587(thus producing always lower case output).
588
589=back
590
591=head1 ERORRS
592
593Upon error, the field C<_error> stores the error message, then die() is called
594with this message. If you do not want the program to die (f.i. to catch the
595errors), then use the following:
596
597	use Math::String::Charset::Grouped;
598
599	$Math::String::Charset::Grouped::die_on_error = 0;
600
601	$a = new Math::String::Charset::Grouped ();	# error, empty set!
602	print $a->error(),"\n";
603
604=head1 INTERNAL DETAILS
605
606This object caches certain calculation results (f.i. the number of possible
607combinations for a certain string length), thus greatly speeding up
608sequentiell Math::String conversations from string to number, and vice versa.
609
610=head1 METHODS
611
612=over
613
614=item new()
615
616            new();
617
618Create a new Math::Charset::Grouped object.
619
620The constructor takes a HASH reference. The following keys can be used:
621
622	minlen		Minimum string length, -inf if not defined
623	maxlen		Maximum string length, +inf if not defined
624	sets		hash, table with charsets for the different places
625	start		array ref to list of all valid (starting) characters
626	end		array ref to list of all valid ending characters
627	sep		separator character, none if undef
628
629C<start> and C<end> are synomyms for C<< sets->{1} >> and C<< sets->{-1} >>,
630respectively. The will override what you specify in sets and are only for
631convienence.
632
633The resulting charset will always be of order 1, type 1.
634
635=over 2
636
637=item start
638
639C<start> contains an array reference to all valid starting
640characters, e.g. no valid string can start with a character not listed here.
641
642The same can be acomplished by specifying C<< sets->{1} >>.
643
644=item sets
645
646C<sets> contains a hash reference, each key of the hash indicates an index.
647Each of the hash entries B<MUST> point either to an ARRAY reference or a
648Math::String::Charset of order 1, type 0.
649
650Positive indices (greater than one) count from the left side, negative from
651the right. 0 denotes the default charset to be used for unspecified places.
652
653The index count will be used for all string length, so that C<< sets->{2} >> always
654refers to the second character from the left, no matter how many characters
655the string actually has.
656
657At each of the position indexed by a key, the appropriate charset will be used.
658
659Example for specifying that strings must start with upper case letters,
660followed by lower case letters and can end in either a lower case letter or a
661number:
662
663	sets => {
664	  0 => ['a'..'z'],		# the default
665	  1 => ['A'..'Z'],		# first character is always A..Z
666	 -1 => ['a'..'z','0'..'9'],	# last is q..z,0..9
667	}
668
669In case of overlapping, a cross between the two charsets will be used, that
670contains all characters from both of them. The default charset will only
671be used when none of the charsets counting from left or right matches.
672
673Given the definition above, valid strings with length 1 consist of:
674
675	['A'..'Z','0'..'9']
676
677Imagine having specified a set at position 2, too:
678
679	sets => {
680	  0 => ['a'..'z'],		# the default
681	  1 => ['A'..'Z'],		# first character is always A..Z
682	  2 => ['-','+','2'],		# second character is - or +
683	 -1 => ['a'..'z','0'..'9'],	# last is q..z,0..9
684	}
685
686For strings of length one, this character set will not be used. For strings
687with length 2 it will be crossed with the set at -1, so that the two-character
688long strings will start with ['A'..'Z'] and end in the characters
689['-','+','2','0','1','3'..'9'].
690
691The cross is build from left to right, that is first come all characters that
692are in the set counting from left, and then all characters in the set
693counting from right, except the ones that are in both (since no doubles must be
694used).
695
696=item end
697
698C<end> contains an array reference to all valid ending
699characters, e.g. no valid string can end with a character not listed here.
700Note that strings of length 1 start B<and> end with their only
701character, so the character must be listed in C<end> and C<start> to produce
702a string with one character.
703The same can be acomplished by specifying C<< sets->{-1} >>.
704
705=item minlen
706
707Optional minimum string length. Any string shorter than this will be invalid.
708Must be shorter than a (possible defined) maxlen. If not given is set to -inf.
709Note that the minlen might be adjusted to a greater number, if it is set to 1
710or greater, but there are not valid strings with 2,3 etc. In this case the
711minlen will be set to the first non-empty class of the charset.
712
713=item maxlen
714
715Optional maximum string length. Any string longer than this will be invalid.
716Must be longer than a (possible defined) minlen. If not given is set to +inf.
717
718=back
719
720=item minlen()
721
722	$charset->minlen();
723
724Return minimum string length.
725
726=item maxlen()
727
728	$charset->maxlen();
729
730Return maximum string length.
731
732=item length()
733
734	$charset->length();
735
736Return the number of items in the charset, for higher order charsets the
737number of valid 1-character long strings. Shortcut for
738C<< $charset->class(1) >>.
739
740=item count()
741
742Returns the count of all possible strings described by the charset as a
743positive BigInt. Returns 'inf' if no maxlen is defined, because there should
744be no upper bound on how many strings are possible.
745
746If maxlen is defined, forces a calculation of all possible L</class()> values
747and may therefore be very slow on the first call, it also caches possible
748lot's of values if maxlen is very high.
749
750=item class()
751
752	$charset->class($order);
753
754Return the number of items in a class.
755
756	print $charset->class(5);	# how many strings with length 5?
757
758=item char()
759
760	$charset->char($nr);
761
762Returns the character number $nr from the set, or undef.
763
764	print $charset->char(0);	# first char
765	print $charset->char(1);	# second char
766	print $charset->char(-1);	# last one
767
768=item lowest()
769
770	$charset->lowest($length);
771
772Return the number of the first string of length $length. This is equivalent
773to (but much faster):
774
775	$str = $charset->first($length);
776	$number = $charset->str2num($str);
777
778=item highest()
779
780	$charset->highest($length);
781
782Return the number of the last string of length $length. This is equivalent
783to (but much faster):
784
785	$str = $charset->first($length+1);
786	$number = $charset->str2num($str);
787        $number--;
788
789=item order()
790
791	$order = $charset->order();
792
793Return the order of the charset: is always 1 for grouped charsets.
794See also L</type()>.
795
796=item type()
797
798	$type = $charset->type();
799
800Return the type of the charset: is always 1 for grouped charsets.
801See also L</order()>.
802
803=item charlen()
804
805	$character_length = $charset->charlen();
806
807Return the length of one character in the set. 1 or greater. All charsets
808used in a grouped charset must have the same length, unless you specify a
809seperator char.
810
811=item seperator()
812
813	$sep = $charset->seperator();
814
815Returns the separator string, or undefined if none is used.
816
817=item chars()
818
819	$chars = $charset->chars( $bigint );
820
821Returns the number of characters that the string would have, when you would
822convert $bigint (Math::BigInt or Math::String object) back to a string.
823This is much faster than doing
824
825	$chars = length ("$math_string");
826
827since it does not need to actually construct the string.
828
829=item first()
830
831	$charset->first( $length );
832
833Return the first string with a length of $length, according to the charset.
834See C<lowest()> for the corrospending number.
835
836=item last()
837
838	$charset->last( $length );
839
840Return the last string with a length of $length, according to the charset.
841See C<highest()> for the corrospending number.
842
843=item is_valid()
844
845	$charset->is_valid();
846
847Check wether a string conforms to the charset set or not.
848
849=item error()
850
851	$charset->error();
852
853Returns "" for no error or an error message that occured if construction of
854the charset failed. Set C<$Math::String::Charset::die_on_error> to C<0> to
855get the error message, otherwise the program will die.
856
857=item start()
858
859	$charset->start();
860
861In list context, returns a list of all characters in the start set, that is
862the ones used at the first string position.
863In scalar context returns the lenght of the B<start> set.
864
865Think of the start set as the set of all characters that can start a string
866with one or more characters. The set for one character strings is called
867B<ones> and you can access if via C<< $charset->ones() >>.
868
869=item end()
870
871	$charset->end();
872
873In list context, returns a list of all characters in the end set, aka all
874characters a string can end with.
875In scalar context returns the lenght of the B<end> set.
876
877=item ones()
878
879	$charset->ones();
880
881In list context, returns a list of all strings consisting of one character.
882In scalar context returns the lenght of the B<ones> set.
883
884This list is the cross of B<start> and B<end>.
885
886Think of a string of only one character as if it starts with and ends in this
887character at the same time.
888
889The order of the chars in C<ones> is the same ordering as in C<start>.
890
891=item prev()
892
893	$string = Math::String->new( );
894	$charset->prev($string);
895
896Give the charset and a string, calculates the previous string in the sequence.
897This is faster than decrementing the number of the string and converting the
898new number to a string. This routine is mainly used internally by Math::String
899and updates the cache of the given Math::String.
900
901=item next()
902
903	$string = Math::String->new( );
904	$charset->next($string);
905
906Give the charset and a string, calculates the next string in the sequence.
907This is faster than incrementing the number of the string and converting the
908new number to a string. This routine is mainly used internally by Math::String
909and updates the cache of the given Math::String.
910
911=back
912
913=head1 EXAMPLES
914
915    use Math::String::Charset::Grouped;
916
917    # not ready yet
918
919=head1 BUGS
920
921None doscovered yet.
922
923=head1 AUTHOR
924
925If you use this module in one of your projects, then please email me. I want
926to hear about how my code helps you ;)
927
928This module is (C) Copyright by Tels http://bloodgate.com 2000-2003.
929
930=cut
931