Das Modul geht dabei weit über die in Perl bereits integrierten Fähigkeiten zur Behandlung von Bitvektoren hinaus (siehe dazu auch die weiter unten folgende Methodenliste!).
Außerdem können Sie die C-Bibliothek, die den Kern dieses Moduls bildet, auch in anderen C-Anwendungen einsetzen. Perl ist dazu nicht erforderlich!
Das Modul ist als Basisklasse für andere Anwendungen oder Anwendungsklassen gedacht, etwa für die Implementierung von Mengen oder für die Arithmetik mit beliebig großen ganzen Zahlen ("Big Integer"-Arithmetik).
Alle Methoden sind intern in C realisiert, um eine möglichst hohe Performanz zu gewährleisten.
Das Modul stellt zusätzlich zu den Methoden auch überladene arithmetische und relationale Operatoren zur Verfügung, um die Handhabung des Moduls so einfach wie möglich zu gestalten (diese sind jedoch nur unter Perl verfügbar).
Denken Sie aber daran, daß überladene Operatoren (natürlich) mit einem kleinen Geschwindigkeitsverlust verbunden sind. Wenn die Geschwindigkeit für Ihre Anwendung ausschlaggebend ist, sollten Sie ausschließlich mit den Methoden dieses Moduls arbeiten, statt die überladenen Operatoren zu benutzen!
Dieses Modul ist für eine große Zahl unterschiedlicher Aufgaben geeignet:
(Die Komplexität der Methoden dieses Moduls ist in der Regel entweder "O(1)
" oder "O(n/b)
", wobei "b" der Anzahl von Bits entspricht, die ein Maschinenwort auf Ihrem System besitzt.)
und vieles mehr.
(Eine Reihe von Beispielanwendungen ist über meine Website unter der URL http://sb.fluomedia.org/download/ verfügbar.)
Eine große Anzahl von verfügbaren Import/Export-Methoden erlaubt den direkten Zugriff auf einzelne Bits, auf fortlaufende Bereiche (Intervalle) von Bits, auf Maschinenworte, auf beliebige Chunks ("Bit-Pakete"), auf Listen (Arrays) von Chunks von Bits oder Maschinenworten sowie den gesamten Bitvektor auf einmal (z.B. für blockorientierte Schreib-/Lesezugriffe auf Dateien).
Außerdem können Sie den Inhalt eines Bitvektors in binärer, hexadezimaler und dezimaler Form sowie als Aufzählung im ".newsrc"-Stil im- und exportieren.
Beachten Sie, daß dieses Modul mit dem Ziel möglichst hoher Effizienz entwickelt wurde, weshalb alle seine Methoden auch in C implementiert sind.
Um die Ausführungsgeschwindigkeit noch weiter zu erhöhen, verwendet das Modul nicht Bytes als kleinste Speichereinheit, sondern Maschinenworte.
Dabei wird davon ausgegangen, daß ein Maschinenwort auf allen Maschinen der am effizientesten verarbeitete skalare Datentyp ist (was der ANSI C-Standard sowieso vorschlägt und implizit annimmt).
Um dies zu ermöglichen, wird auf jedem System automatisch die Anzahl der Bits in einem Maschinenwort bestimmt und werden die entsprechenden internen Konfigurationskonstanten automatisch angepaßt.
Je größer diese kleinste Speichereinheit ist, desto besser ist die Komplexität (d.h. Ausführungsgeschwindigkeit) der Methoden dieses Moduls. Allerdings steigt damit auch die durchschnittliche Zahl der verschwendeten (ungenutzten) Bits im letzten Maschinenwort.
Das Modul "Math::MatrixBool" ist ein Beispiel für die effiziente Implementierung boolescher Matrizen und der dazugehörigen Operationen.
(Beide Module sind über meine Website unter der URL http://sb.fluomedia.org/download/ bzw. über jeden CPAN-Server (http://www.perl.com/CPAN/authors/id/STBEY/) verfügbar.)
Eine ohne das "Bit::Vector"-Modul undenkbare Anwendung ist "Slice": Mit diesem Werkzeug können mit Hilfe von booleschen Ausdrücken ("erzeuge die englische Version des Textes mit allen Beispielen aber ohne ...") unterschiedliche Varianten eines Dokuments aus derselben Quell-Datei erzeugt werden.
(Siehe dazu auch http://www.engelschall.com/sw/slice/.)
Dieses Werkzeug ist selbst wiederum Teil eines anderen Werkzeugs namens "Website META Language" ("WML"), mit dem ganze Websites aus Vorlagen und Schablonen generiert und verwaltet werden können.
Unter anderem können Sie damit Ihre eigenen HTML-Tags definieren, die je nach Wunsch entweder bei der Generierung oder zur Laufzeit expandiert bzw. ausgeführt werden.
(Siehe dazu auch http://www.engelschall.com/sw/wml/.)
Version $version = Bit::Vector->Version(); Word_Bits $bits = Bit::Vector->Word_Bits(); # Anzahl Bits in Maschinenwort Long_Bits $bits = Bit::Vector->Long_Bits(); # Anzahl Bits in "unsigned long" new $vector = Bit::Vector->new($bits); # Bitvektor-Konstruktor new_Hex $vector = Bit::Vector->new_Hex($bits,$string); new_Bin $vector = Bit::Vector->new_Bin($bits,$string); new_Dec $vector = Bit::Vector->new_Dec($bits,$string); new_Enum $vector = Bit::Vector->new_Enum($bits,$string); Concat_List $vector = Bit::Vector->Concat_List(@vectors);
new $vec2 = $vec1->new($bits); # Alternativer Aufruf des Konstruktors Shadow $vec2 = $vec1->Shadow(); # neuer Bitvektor, gleiche Größe aber leer Clone $vec2 = $vec1->Clone(); # neuer Bitvektor, exaktes Duplikat Concat $vector = $vec1->Concat($vec2); Concat_List $vector = $vec1->Concat_List($vec2,$vec3,...); Size $bits = $vector->Size(); Resize $vector->Resize($bits); $vector->Resize($vector->Size()+5); $vector->Resize($vector->Size()-5); Copy $vec2->Copy($vec1); Empty $vector->Empty(); Fill $vector->Fill(); Flip $vector->Flip(); Primes $vector->Primes(); # Sieb des Erathostenes Reverse $vec2->Reverse($vec1); Interval_Empty $vector->Interval_Empty($min,$max); Interval_Fill $vector->Interval_Fill($min,$max); Interval_Flip $vector->Interval_Flip($min,$max); Interval_Reverse $vector->Interval_Reverse($min,$max); Interval_Scan_inc if (($min,$max) = $vector->Interval_Scan_inc($start)) Interval_Scan_dec if (($min,$max) = $vector->Interval_Scan_dec($start)) Interval_Copy $vec2->Interval_Copy($vec1,$offset2,$offset1,$length); Interval_Substitute $vec2->Interval_Substitute($vec1,$off2,$len2,$off1,$len1); is_empty if ($vector->is_empty()) is_full if ($vector->is_full()) equal if ($vec1->equal($vec2)) Lexicompare (vorzeichenlos) if ($vec1->Lexicompare($vec2) == 0) if ($vec1->Lexicompare($vec2) != 0) if ($vec1->Lexicompare($vec2) < 0) if ($vec1->Lexicompare($vec2) <= 0) if ($vec1->Lexicompare($vec2) > 0) if ($vec1->Lexicompare($vec2) >= 0) Compare (vorzeichenbehaftet) if ($vec1->Compare($vec2) == 0) if ($vec1->Compare($vec2) != 0) if ($vec1->Compare($vec2) < 0) if ($vec1->Compare($vec2) <= 0) if ($vec1->Compare($vec2) > 0) if ($vec1->Compare($vec2) >= 0) to_Hex $string = $vector->to_Hex(); from_Hex $vector->from_Hex($string); to_Bin $string = $vector->to_Bin(); from_Bin $vector->from_Bin($string); to_Dec $string = $vector->to_Dec(); from_Dec $vector->from_Dec($string); to_Enum $string = $vector->to_Enum(); # z.B. "2,3,5-7,11,13-19" from_Enum $vector->from_Enum($string); Bit_Off $vector->Bit_Off($index); Bit_On $vector->Bit_On($index); bit_flip $bit = $vector->bit_flip($index); bit_test, contains $bit = $vector->bit_test($index); $bit = $vector->contains($index); if ($vector->bit_test($index)) if ($vector->contains($index)) Bit_Copy $vector->Bit_Copy($index,$bit); LSB (least significant bit) $vector->LSB($bit); MSB (most significant bit) $vector->MSB($bit); lsb (least significant bit) $bit = $vector->lsb(); msb (most significant bit) $bit = $vector->msb(); rotate_left $carry = $vector->rotate_left(); rotate_right $carry = $vector->rotate_right(); shift_left $carry = $vector->shift_left($carry); shift_right $carry = $vector->shift_right($carry); Move_Left $vector->Move_Left($bits); # Linksshift um "$bits" Positionen Move_Right $vector->Move_Right($bits); # Rechtsshift um "$bits" Positionen Insert $vector->Insert($offset,$bits); Delete $vector->Delete($offset,$bits); increment $carry = $vector->increment(); decrement $carry = $vector->decrement(); add $carry = $vec3->add($vec1,$vec2,$carry); subtract $carry = $vec3->subtract($vec1,$vec2,$carry); Negate $vec2->Negate($vec1); Absolute $vec2->Absolute($vec1); Sign if ($vector->Sign() == 0) if ($vector->Sign() != 0) if ($vector->Sign() < 0) if ($vector->Sign() <= 0) if ($vector->Sign() > 0) if ($vector->Sign() >= 0) Multiply $vec3->Multiply($vec1,$vec2); Divide $quot->Divide($vec1,$vec2,$rest); GCD (Greatest Common Divisor) $vec3->GCD($vec1,$vec2); Block_Store $vector->Block_Store($buffer); Block_Read $buffer = $vector->Block_Read(); Word_Size $size = $vector->Word_Size(); # Anzahl Maschinenworte in "$vector" Word_Store $vector->Word_Store($offset,$word); Word_Read $word = $vector->Word_Read($offset); Word_List_Store $vector->Word_List_Store(@words); Word_List_Read @words = $vector->Word_List_Read(); Word_Insert $vector->Word_Insert($offset,$count); Word_Delete $vector->Word_Delete($offset,$count); Chunk_Store $vector->Chunk_Store($chunksize,$offset,$chunk); Chunk_Read $chunk = $vector->Chunk_Read($chunksize,$offset); Chunk_List_Store $vector->Chunk_List_Store($chunksize,@chunks); Chunk_List_Read @chunks = $vector->Chunk_List_Read($chunksize); Index_List_Remove $vector->Index_List_Remove(@indices); Index_List_Store $vector->Index_List_Store(@indices); Index_List_Read @indices = $vector->Index_List_Read(); Union $set3->Union($set1,$set2); Intersection $set3->Intersection($set1,$set2); Difference $set3->Difference($set1,$set2); ExclusiveOr $set3->ExclusiveOr($set1,$set2); Complement $set2->Complement($set1); subset if ($set1->subset($set2)) # Wahr wenn $set1 Teilmenge von $set2 Norm $norm = $set->Norm(); Min $min = $set->Min(); Max $max = $set->Max(); Multiplication $matrix3->Multiplication($rows3,$cols3, $matrix1,$rows1,$cols1, $matrix2,$rows2,$cols2); Closure $matrix->Closure($rows,$cols); Transpose $matrix2->Transpose($rows2,$cols2,$matrix1,$rows1,$cols1);
Configuration $config = Bit::Vector->Configuration(); Bit::Vector->Configuration($config); $oldconfig = Bit::Vector->Configuration($newconfig);
String-Konvertierung $string = "$vector"; # Abhängig von der Konfiguration print "\$vector = '$vector'\n"; Leerheit if ($vector) # wenn nicht leer (nicht Null) if (! $vector) # wenn leer (Null) unless ($vector) # wenn leer (Null) Komplement (Einerkomplement) $vector2 = ~$vector1; $vector = ~$vector; Negation (Zweierkomplement) $vector2 = -$vector1; $vector = -$vector; Norm $norm = abs($vector); # Abhängig von der Konfiguration Absolutwert $vector2 = abs($vector1); # Abhängig von der Konfiguration Verkettung $vector3 = $vector1 . $vector2; $vector1 .= $vector2; $vector1 = $vector2 . $vector1; $vector2 = $vector1 . $scalar; # Abhängig von der Konfiguration $vector2 = $scalar . $vector1; $vector .= $scalar; Duplizieren $vector2 = $vector1 x $factor; $vector x= $factor; Linksshift $vector2 = $vector1 << $bits; $vector <<= $bits; Rechtsshift $vector2 = $vector1 >> $bits; $vector >>= $bits; Vereinigungsmenge $vector3 = $vector1 | $vector2; $vector1 |= $vector2; $vector2 = $vector1 | $scalar; $vector |= $scalar; $vector3 = $vector1 + $vector2; # Abhängig von der Konfiguration $vector1 += $vector2; $vector2 = $vector1 + $scalar; $vector += $scalar; Schnittmenge $vector3 = $vector1 & $vector2; $vector1 &= $vector2; $vector2 = $vector1 & $scalar; $vector &= $scalar; $vector3 = $vector1 * $vector2; # Abhängig von der Konfiguration $vector1 *= $vector2; $vector2 = $vector1 * $scalar; $vector *= $scalar; Exklusiv-Oder (Symmetrische Differenzmenge) $vector3 = $vector1 ^ $vector2; $vector1 ^= $vector2; $vector2 = $vector1 ^ $scalar; $vector ^= $scalar; Differenzmenge $vector3 = $vector1 - $vector2; # Abhängig von der Konfiguration $vector1 -= $vector2; $vector1 = $vector2 - $vector1; $vector2 = $vector1 - $scalar; $vector2 = $scalar - $vector1; $vector -= $scalar; Addition $vector3 = $vector1 + $vector2; # Abhängig von der Konfiguration $vector1 += $vector2; $vector2 = $vector1 + $scalar; $vector += $scalar; Subtraktion $vector3 = $vector1 - $vector2; # Abhängig von der Konfiguration $vector1 -= $vector2; $vector1 = $vector2 - $vector1; $vector2 = $vector1 - $scalar; $vector2 = $scalar - $vector1; $vector -= $scalar; Multiplikation $vector3 = $vector1 * $vector2; # Abhängig von der Konfiguration $vector1 *= $vector2; $vector2 = $vector1 * $scalar; $vector *= $scalar; Division $vector3 = $vector1 / $vector2; $vector1 /= $vector2; $vector1 = $vector2 / $vector1; $vector2 = $vector1 / $scalar; $vector2 = $scalar / $vector1; $vector /= $scalar; Modulo $vector3 = $vector1 % $vector2; $vector1 %= $vector2; $vector1 = $vector2 % $vector1; $vector2 = $vector1 % $scalar; $vector2 = $scalar % $vector1; $vector %= $scalar; Inkrement ++$vector; $vector++; Dekrement --$vector; $vector--; Lexikalischer Vergleich (vorzeichenlos) $cmp = $vector1 cmp $vector2; if ($vector1 lt $vector2) if ($vector1 le $vector2) if ($vector1 gt $vector2) if ($vector1 ge $vector2) $cmp = $vector cmp $scalar; if ($vector lt $scalar) if ($vector le $scalar) if ($vector gt $scalar) if ($vector ge $scalar) Vergleich (vorzeichenbehaftet) $cmp = $vector1 <=> $vector2; if ($vector1 < $vector2) # Abhängig von der Konfiguration if ($vector1 <= $vector2) if ($vector1 > $vector2) if ($vector1 >= $vector2) $cmp = $vector <=> $scalar; if ($vector < $scalar) # Abhängig von der Konfiguration if ($vector <= $scalar) if ($vector > $scalar) if ($vector >= $scalar) Gleichheit if ($vector1 eq $vector2) if ($vector1 ne $vector2) if ($vector eq $scalar) if ($vector ne $scalar) if ($vector1 == $vector2) if ($vector1 != $vector2) if ($vector == $scalar) if ($vector != $scalar) Teilmengen-Beziehung if ($vector1 <= $vector2) # Abhängig von der Konfiguration Echte Teilmengen-Beziehung if ($vector1 < $vector2) # Abhängig von der Konfiguration Obermengen-Beziehung if ($vector1 >= $vector2) # Abhängig von der Konfiguration Echte Obermengen-Beziehung if ($vector1 > $vector2) # Abhängig von der Konfiguration
Vollständig kleingeschriebene Methodennamen zeigen boolesche Rückgabewerte an.
(Natürlich mit Ausnahme der Bitvektor-Konstruktormethode "new()
".)
Die booleschen Werte dieses Moduls sind immer numerisch Null ("0
") für "falsch" und numerisch Eins ("1
") für "wahr".
Alle numerischen Eingabeparameter, die an irgendeine Methode dieses Moduls oder (im allgemeinen, jedoch siehe auch weiter unten) an überladene Operatoren übergeben werden, werden als VORZEICHENLOS betrachtet.
Mit anderen Worten, sowohl positive als auch negative Zahlen werden als positive Zahlen interpretiert. Dadurch werden negative Zahlen aufgrund ihrer internen binären Darstellung im Zweierkomplement plötzlich zu sehr großen positiven Zahlen.
Überladene Operatoren sind allerdings nur betroffen, wo numerische Faktoren (etwa bei "<<
", ">>
" und "x
") im Spiel sind, oder wenn die Konfiguration festlegt (beachten Sie hierzu auch den unmittelbar folgenden Abschnitt "Konfiguration überladener Operatoren"), daß numerische Eingaben (anstelle eines Bitvektor-Objekts für einen der beiden Operanden des Operators) als Bit-Nummern betrachtet werden sollen (was allerdings der Voreinstellung entspricht).
Die Konsequenz hieraus ist, daß die Übergabe einer negativen Zahl als Argument an eine der Methoden dieses Moduls oder als Bit-Nummer an einen der überladenen Operatoren in der Regel zu einem Überlauf mit entsprechender Fehlermeldung ("index out of range") und zum Programmabbruch führt.
Beachten Sie, daß das nicht für "Big Integer"-Dezimalzahlen gilt, die (normalerweise) als Strings übergeben werden und natürlich auch negativ sein dürfen (beachten Sie hierzu auch den Abschnitt "Big Integer"-Arithmetik etwas weiter unten).
Beachten Sie, daß das Verhalten bestimmter überladener Operatoren mit Hilfe der Methode "Configuration()
" auf verschiedene Weise verändert werden kann (Details finden Sie weiter unten bei der Beschreibung dieser Methode).
Zum Beispiel werden Skalare (d.h. Zahlen und Strings), die als Operanden an überladene Operatoren übergeben werden, intern automatisch in Bitvektoren umgewandelt.
Diese Skalare werden dabei je nach Konfiguration entweder als Bit-Nummern betrachtet, oder als hexadezimale, binäre oder dezimale Zahlen, oder als Aufzählung.
Ebenso verhält es sich mit der Konvertierung von Bitvektoren in Strings mit Hilfe von Anführungszeichen (""), d.h. das Ausgabeformat hängt ebenfalls von der gewählten Konfiguration ab.
Schließlich haben einige der überladenen Operatoren je nach Konfiguration sogar eine unterschiedliche Semantik: Zum Beispiel kann der Operator "+" für den "Vereinigungsmenge"-Operator stehen, oder aber den arithmetischen Additionsoperator bedeuten.
In allen Fällen (Eingabe- und Ausgabe-Umwandlung sowie der Operator-Semantik) wurden die Voreinstellungen so gewählt, daß das Verhalten der aktuellen Version des Moduls mit dem von früheren Versionen erst einmal identisch ist.
Solange die "Großen Ganzen Zahlen" ("Big Integers", für die "Big Integer"-Arithmetik) klein genug sind, um von Perl intern ohne wissenschaftliche Notation (Exponenten) dargestellt werden zu können, dürfen Sie sie in numerischer Form (d.h. als numerische Perl-Konstante, als numerischer Ausdruck oder als Perl-Variable mit numerischem Inhalt) an die überladenen Operatoren dieses Moduls (oder an die Methode "from_Dec()
") übergeben.
Nur diejenigen Zahlen, die für die interne Darstellung als ganze Zahl in Perl zu groß sind, müssen Sie unbedingt als Strings angeben.
Beachten Sie, daß eine Fehlermeldung erfolgt (mit Programmabbruch), wenn Ihre "Big Integer"-Werte größer werden als die größte auf Ihrem System noch darstellbare ganze Zahl, d.h. wenn zu ihrer Darstellung intern auf das "float"- bzw. "double"-Format (mit Exponenten) zurückgegriffen werden muß!
Weil dieses Limit jedoch maschinenabhängig und nicht einfach zu ermitteln ist, wird dringend empfohlen, ALLE "Big Integer"-Werte in Ihren Programmen in Anführungszeichen zu setzen (Hochkommata oder doppelte Anführungszeichen).
Beispiele:
$vector /= 10; # OK, weil Zahl klein ist $vector /= -10; # Aus dem gleichen Grund OK $vector /= "10"; # Immer korrekt $vector += "1152921504606846976"; # Anführungszeichen unbedingt erforderlich!
Die obigen Beispiele setzen alle voraus, daß zuvor
Bit::Vector->Configuration("input=decimal");
gesetzt wurde.
Beachten Sie, daß dieses Modul keine wissenschaftliche Notation (Exponenten) für "Big Integer"-Zahlen unterstützt, weil Sie jeden Bitvektor stets so groß machen können, daß die gesamte Zahl ohne Genauigkeitsverluste (die bei der Verwendung von Exponenten und einer begrenzten Anzahl von Dezimalstellen immer auftreten) hineinpaßt.
Beachten Sie schließlich auch, daß die einzigen erlaubten Zeichen in Strings für "Big Integer"-Konstanten die Ziffern "0..9
" sowie optional ein Vorzeichen ("+
" oder "-
") sind.
Alle anderen Zeichen erzeugen einen (fatalen) Syntaxfehler.
Alle überladenen Operatoren verlangen mindestens einen Bitvektor-Operanden, um erkennen zu können, daß nicht die standardmäßige, sondern die überladene Variante einer Operation ausgeführt werden soll.
Das gilt insbesondere natürlich für alle unären Operatoren:
"$vector" if ($vector) if (!$vector) ~$vector -$vector abs($vector) ++$vector $vector++ --$vector $vector--
Aus offensichtlichen Gründen muß auch der linke Operand (der sogenannte "L-Wert") aller Zuweisungsoperatoren ein Bitvektor sein:
.= x= <<= >>= |= &= ^= += -= *= /= %=
Im Fall dreier spezieller Operatoren, nämlich "<<
", ">>
" und "x
", sowie bei den entsprechenden Zuweisungs-Varianten "<<=
", ">>=
" und "x=
", ist der linke Operand IMMER ein Bitvektor und der rechte Operand ist IMMER eine Zahl (die angibt, wie oft der Operator anzuwenden ist).
Bei allen echten binären Operatoren, d.h. bei:
. | & ^ + - * / % <=> cmp == eq != ne < lt <= le > gt >= ge
kann jeweils einer von beiden Operanden durch einen Perl-Skalar ersetzt werden, d.h. durch eine Zahl oder einen String. Diese Werte können als Perl-Konstante, als Perl-Ausdruck oder als Perl-Variable (die eine Zahl oder einen String ergeben) angegeben werden.
Das gleiche gilt analog für die rechte Seite (den "R-Wert") der übrigen Zuweisungsoperatoren:
.= |= &= ^= += -= *= /= %=
Beachten Sie, daß dieser Perl-Skalar für die gewählte Konfiguration vom richtigen Typ (numerisch oder String) sein sollte, da anderenfalls eine Warnung ausgegeben wird, falls Ihr Programm mit dem Perl-Schalter "-w
" ausgeführt wird.
Nachfolgend eine Übersicht der erlaubten Skalartypen für alle möglichen Konfigurationen:
input = bit indices : numerisch (Voreinstellung) input = hexadecimal : String input = binary : String input = decimal : String (im allgemeinen) input = decimal : numerisch (falls klein genug) input = enumeration : String
Beachten Sie, daß diese skalaren Operanden intern in Bitvektoren umgewandelt werden, die die gleiche Anzahl von Bits besitzen wie der jeweils andere Operand oder "L-Wert" (die ja Bitvektoren sein müssen!).
Die einzige Ausnahme von dieser Regel ist der Verkettungsoperator (".
") und seine Zuweisungsvariante (".=
"):
Ist einer der beiden Operanden des Verkettungsoperators (".
") kein Bitvektor, sondern ein Perl-Skalar, wird der Inhalt des jeweils anderen Operanden (des Bitvektors) in einen String umgewandelt(!), dessen Format wiederum von der mittels der "Configuration()
"-Methode gewählten Konfiguration abhängt. Dieser String wird dann in der richtigen Reihenfolge (d.h. der Reihenfolge der beiden Operanden entsprechend) mit dem Perl-Skalar verkettet. (Mit anderen Worten: Es wird in diesem Fall ein String anstelle eines Bitvektors zurückgegeben!)
Ist der rechte Operand ("R-Wert") der Zuweisungsvariante des Verkettungsoperators (".=
") ein Perl-Skalar, wird er intern in einen Bitvektor umgewandelt. Die Länge dieses Bitvektors hängt dabei von der gewählten Konfiguration ab:
Der resultierende Bitvektor hat die gleiche Anzahl von Bits wie der linke Operand, falls die Konfiguration festlegt, daß Skalare in der Eingabe als Bit-Nummern, Dezimalzahlen oder Aufzählungen zu betrachten sind.
Legt die Konfiguration hingegen fest, daß Skalare in der Eingabe als hexadezimale oder binäre Strings zu behandeln sind, wird der skalare Operand in einen Bitvektor umgewandelt, dessen Anzahl von Bits eine Funktion der Länge des Eingabestrings ist: Viermal die Länge eines hexadezimalen Strings (weil jede hexadezimale Ziffer 4 Bits kodiert) und die einfache Länge eines binären Strings.
Ist eine Dezimalzahl ("Big Integer") zu groß, um in einem Bitvektor der gegebenen Größe abgespeichert werden zu können, kommt es zu einem numerischen Überlauffehler ("numeric overflow error") mit Programmabbruch.
Liegt die gegebene Bit-Nummer außerhalb des gültigen Bereichs, der durch die Anzahl von Bits der an der Operation beteiligten Bitvektoren festgelegt wird, kommt es zu einem Indexfehler ("index out of range") mit Programmabbruch.
Kann ein skalarer Operand aufgrund von Syntaxfehlern nicht erfolgreich umgewandelt werden, kommt es ebenfalls zu einem fatalen Fehler ("input string syntax error") (mit Programmabbruch).
Sind die beiden Operanden der Operatoren "<<
", ">>
" oder "x
" vertauscht, kommt es zu einem fatalen "Vertauschte Operanden"-Fehler ("reversed operands error").
Ist ein Operand weder ein Bitvektor noch ein Skalar, kommt es zu einem fatalen "Falscher Operanden-Typ"-Fehler ("illegal operand type error").
Beachten Sie, daß die Bits in den Bitvektoren dieses Moduls intern in aufsteigender Folge gespeichert sind, d.h. das Bit mit der Nummer "0
" ist mit dem niederwertigsten Bit im niederwertigsten (ersten!) Maschinenwort des Bitvektors identisch.
Mit anderen Worten, das Bit Nummer "0
" eines Bitvektors ist im Bit Nummer "0
" des Wortes Nummer "0
" des Arrays von Maschinenworten gespeichert, aus dem ein Bitvektor intern besteht.
(Wobei das Wort Nummer "0
" in diesem Array das erste Wort ist, d.h. das mit der kleinsten Speicheradresse innerhalb des Arrays.)
Beachten Sie aber, daß Maschinenworte (abhängig von der Implementierung des jeweiligen Systems!) intern mit unterschiedlichen Byte-Reihenfolgen abgespeichert sein können, z.B. in der "low order byte first"- oder der "high order byte first"-Reihenfolge!
Aus diesem Grund erfolgt bei den beiden Methoden "Block_Store()
" und "Block_Read()
" (die zum Im- und Exportieren eines ganzen Bitvektors auf einmal dienen) eine entsprechende Umwandlung aus der und in die "low order byte first"-Reihenfolge, respektive.
Was also "Block_Store()
" als Eingabe erwartet und "Block_Read()
" zurückliefert, ist immer die "low order byte first"-Reihenfolge, unabhängig davon, in welcher Reihenfolge die Bytes eines Maschinenwortes tatsächlich auf der jeweiligen Maschine abgespeichert werden.
Auf diese Weise ist sichergestellt, daß die mit "Block_Read()
" auf einer Maschine exportierten Daten auf einer anderen Maschine (möglicherweise mit einer anderen Byte-Reihenfolge!) mit "Block_Store()
" stets korrekt wieder eingelesen werden können.
Beachten Sie weiterhin, daß jedoch bei der Darstellung von Bitvektoren als binäre oder hexadezimale Strings das NIEDERWERTIGSTE Bit immer GANZ RECHTS steht, das ERSTE Bit (also das GANZ LINKS stehende) daher das HÖCHSTWERTIGE Bit ist.
Das ist so, weil in der westlichen Kultur alle Zahlen auf diese Weise dargestellt werden (die Wertigkeit der Ziffern steigt von rechts nach links an).
Das erfordert natürlich bei der Umwandlung aus einem oder in einen binären oder hexadezimalen String eine Umstellung der Reihenfolge, die die entsprechenden Umwandlungsmethoden (günstigerweise sogar ohne zusätzlichen Aufwand!) automatisch erledigen.
Beachten Sie, daß alle Methoden, deren Namen mit "Word_
" beginnen, MASCHINENABHÄNGIG sind!
Diese Methoden sind alle von der Größe (der Anzahl der Bits) eines Maschinenworts, d.h. des C-Datentyps "unsigned int", auf Ihrer Maschine abhängig.
Aus diesem Grund sollten Sie diese Methoden nur dann verwenden, wenn Sie ABSOLUT SICHER sind, daß die Portabilität Ihres Programms KEINE ROLLE spielt!
Bedenken Sie, daß Sie beliebig große Chunks ("Bit-Pakete") mit bis zu 32 Bits auf einmal AUF PORTABLE WEISE nutzen können, wenn Sie statt dessen die Methoden verwenden, deren Namen mit "Chunk_
" beginnen.
Der erlaubte Bereich für Chunk-Größen (für alle Methoden, deren Namen mit "Chunk_
" beginnen) reicht von "1
" bis "Bit::Vector->Long_Bits()
". Die Chunk-Größe "0
" ist also NICHT erlaubt; jeder Versuch, diese Chunk-Größe zu verwenden, führt zu einem fatalen Fehler!
Um Ihre Programme portabel zu machen, dürfen Sie jedoch keine Chunk-Größen von mehr als 32 Bits verwenden, da dies die maximale, garantiert auf jedem System verfügbare Anzahl von Bits des C-Datentyps "unsigned int", also eines Maschinenwortes, ist (dies wird durch den ANSI C-Standard gewährleistet!).
Generell gilt für alle Methoden, bei denen mehrere Bitvektoren beteiligt sind, daß diese Bitvektoren übereinstimmende Größen (Anzahlen von Bits) haben müssen. Anderenfalls tritt ein fataler "Abweichende Größen"-Fehler ("size mismatch error") auf.
Eine Ausnahme von dieser Regel bilden die Methoden "Concat()
", "Concat_List()
", "Interval_Copy()
" und "Interval_Substitute()
", bei denen keine Bedingungen an die Größe der beteiligten Bitvektoren geknüpft sind. Die "Multiply()
"-Methode bildet eine Ausnahme besonderer Art: Zwar muß auch hier prinzipiell die Regel übereinstimmender Größen eingehalten werden, aber der das Ergebnis der Multiplikation aufnehmende Bitvektor darf ausnahmsweise auch größer sein als die beiden Bitvektoren, die die Faktoren der Multiplikation enthalten.
Alle Bit-Nummern müssen zwischen "0
" und "$vector->Size()-1
" liegen, sonst tritt ein fataler Indexfehler ("index out of range") auf.
$version = Bit::Vector->Version();
Liefert die Versionsnummer des Moduls zurück.
$bits = Bit::Vector->Word_Bits();
Liefert die Anzahl der Bits zurück, die der C-Datentyp "unsigned int" auf der aktuellen Maschine hat.
(Ein "unsigned int" wird auch als ein "Maschinenwort" bezeichnet; daher der Name dieser Methode.)
$bits = Bit::Vector->Long_Bits();
Liefert die Anzahl der Bits zurück, die der C-Datentyp "unsigned long" auf der aktuellen Maschine hat.
$vector = Bit::Vector->new($bits);
Dies ist die Bitvektor-Konstruktormethode.
Rufen Sie diese Methode auf, um einen neuen Bitvektor mit "$bits
" Bits (mit Nummern im Bereich von "0
" bis "$bits-1
") zu erzeugen.
Beachten Sie, daß im Gegensatz zu früheren Versionen dieses Moduls jetzt auch Bitvektoren der Länge Null (also mit "$bits = 0
") zugelassen sind.
Die Methode gibt eine Referenz auf den neu erzeugten Bitvektor zurück.
Ein neuer Bitvektor wird immer so initialisiert, daß alle Bits gelöscht (aus) sind.
Eine Ausnahme wird ausgelöst, wenn die Methode nicht in der Lage ist, den benötigten Speicherplatz zu allozieren.
Beachten Sie, daß die Angabe eines negativen Wertes für "$bits
" als eine (in der Regel sehr große!) positive Zahl interpretiert wird. Der Grund dafür ist die interne Binärdarstellung im Zweierkomplement.
Im Fall einer solchen negativen Anzahl von Bits versucht der Bitvektor-Konstruktor trotzdem pflichtschuldigst, einen Bitvektor dieser Größe zu erzeugen, was in der Regel zu dem oben erwähnten Fehler führt.
$vector = Bit::Vector->new_Hex($bits,$string);
Diese Methode ist ein alternativer Konstruktor, der es Ihnen erlaubt, in einem einzigen Schritt sowohl einen neuen Bitvektor (mit "$bits
" Bits) anzulegen als auch, ihn sofort mit einem Wert zu initialisieren.
Diese Methode ist dabei außerdem noch effizienter als die getrennte Durchführung dieser beiden Schritte, weil diese Methode den neuen Bitvektor nicht zuerst mit Nullen initialisiert (was ja in diesem Fall unnötig ist) und weil der mit einem zusätzlichen Methodenaufruf verbundene Aufwand vermieden wird.
Die Methode ruft dazu allerdings intern zuerst die C-Funktion "new()
" auf und übergibt anschließend den Eingabe-String an die C-Funktion "from_Hex()
".
Eine Ausnahme wird ausgelöst, wenn der benötigte Speicherplatz nicht alloziert werden kann, oder wenn der übergebene String nicht erfolgreich umgewandelt werden kann (Erläuterungen zu möglichen Ursachen hierfür finden Sie weiter unten bei der Beschreibung der Methode "from_Hex()
").
Im letzteren Fall wird der durch den neuen Bitvektor belegte Speicherplatz zuerst freigegeben (mittels "free()
"), bevor der Fehler ausgelöst wird.
$vector = Bit::Vector->new_Bin($bits,$string);
Diese Methode ist ein alternativer Konstruktor, der es Ihnen erlaubt, in einem einzigen Schritt sowohl einen neuen Bitvektor (mit "$bits
" Bits) anzulegen als auch, ihn sofort mit einem Wert zu initialisieren.
Diese Methode ist dabei außerdem noch effizienter als die getrennte Durchführung dieser beiden Schritte, weil diese Methode den neuen Bitvektor nicht zuerst mit Nullen initialisiert (was ja in diesem Fall unnötig ist) und weil der mit einem zusätzlichen Methodenaufruf verbundene Aufwand vermieden wird.
Die Methode ruft dazu allerdings intern zuerst die C-Funktion "new()
" auf und übergibt anschließend den Eingabe-String an die C-Funktion "from_Bin()
".
Eine Ausnahme wird ausgelöst, wenn der benötigte Speicherplatz nicht alloziert werden kann, oder wenn der übergebene String nicht erfolgreich umgewandelt werden kann (Erläuterungen zu möglichen Ursachen hierfür finden Sie weiter unten bei der Beschreibung der Methode "from_Bin()
").
Im letzteren Fall wird der durch den neuen Bitvektor belegte Speicherplatz zuerst freigegeben (mittels "free()
"), bevor der Fehler ausgelöst wird.
$vector = Bit::Vector->new_Dec($bits,$string);
Diese Methode ist ein alternativer Konstruktor, der es Ihnen erlaubt, in einem einzigen Schritt sowohl einen neuen Bitvektor (mit "$bits
" Bits) anzulegen als auch, ihn sofort mit einem Wert zu initialisieren.
Diese Methode ist dabei außerdem noch effizienter als die getrennte Durchführung dieser beiden Schritte, weil diese Methode den neuen Bitvektor nicht zuerst mit Nullen initialisiert (was ja in diesem Fall unnötig ist) und weil der mit einem zusätzlichen Methodenaufruf verbundene Aufwand vermieden wird.
Die Methode ruft dazu allerdings intern zuerst die C-Funktion "new()
" auf und übergibt anschließend den Eingabe-String an die C-Funktion "from_Dec()
".
Eine Ausnahme wird ausgelöst, wenn der benötigte Speicherplatz nicht alloziert werden kann, oder wenn der übergebene String nicht erfolgreich umgewandelt werden kann (Erläuterungen zu möglichen Ursachen hierfür finden Sie weiter unten bei der Beschreibung der Methode "from_Dec()
").
Im letzteren Fall wird der durch den neuen Bitvektor belegte Speicherplatz zuerst freigegeben (mittels "free()
"), bevor der Fehler ausgelöst wird.
$vector = Bit::Vector->new_Enum($bits,$string);
Diese Methode ist ein alternativer Konstruktor, der es Ihnen erlaubt, in einem einzigen Schritt sowohl einen neuen Bitvektor (mit "$bits
" Bits) anzulegen als auch, ihn sofort mit einem Wert zu initialisieren.
Diese Methode ist dabei außerdem noch effizienter als die getrennte Durchführung dieser beiden Schritte, weil diese Methode den neuen Bitvektor nicht zuerst mit Nullen initialisiert (was ja in diesem Fall unnötig ist) und weil der mit einem zusätzlichen Methodenaufruf verbundene Aufwand vermieden wird.
Die Methode ruft dazu allerdings intern zuerst die C-Funktion "new()
" auf und übergibt anschließend den Eingabe-String an die C-Funktion "from_Enum()
".
Eine Ausnahme wird ausgelöst, wenn der benötigte Speicherplatz nicht alloziert werden kann, oder wenn der übergebene String nicht erfolgreich umgewandelt werden kann (Erläuterungen zu möglichen Ursachen hierfür finden Sie weiter unten bei der Beschreibung der Methode "from_Enum()
").
Im letzteren Fall wird der durch den neuen Bitvektor belegte Speicherplatz zuerst freigegeben (mittels "free()
"), bevor der Fehler ausgelöst wird.
$vector = Bit::Vector->Concat_List(@vectors);
Diese Methode erzeugt einen neuen Bitvektor, der alle Bitvektoren der Argumentliste in verketteter Form enthält.
Die Argumentliste kann dabei beliebig viele Argumente (auch keine!) enthalten. Die einzige Bedingung ist, daß alle Argumente Bitvektoren sein müssen.
Eine die Länge (Anzahl der Bits) dieser Argumente betreffende Bedingung gibt es nicht.
Die Bitvektoren der Argumentliste werden in keiner Weise verändert.
Ist die Argumentliste leer, oder besitzen alle Argumente die Länge Null, hat auch der resultierende Bitvektor die Länge Null.
Beachten Sie, daß der GANZ RECHTS stehende Bitvektor der Argumentliste zum NIEDERWERTIGSTEN Teil des resultierenden Bitvektors wird, während der GANZ LINKS stehende Bitvektor der Argumentliste zum HÖCHSTWERTIGEN Teil des resultierenden Bitvektors wird.
$vec2 = $vec1->new($bits);
Eine alternative Art des Aufrufs der Bitvektor-Konstruktormethode.
Der Bitvektor "$vec1
" wird hiervon nicht beeinflußt; er dient nur als Anker für den Methodenaufruf.
Tatsächlich können ALLE Klassenmethoden dieses Moduls auf diese Weise aufgerufen werden, auch wenn das von OO-Verfechtern wohl nicht als "politisch korrekt" ;-)
betrachtet werden dürfte...
Auch wenn Sie zu faul sind, um "Bit::Vector->
" anstelle von "$vec1->
" einzutippen (obwohl die Faulheit ja - laut Perl-Motto! - eine Programmierertugend ist :-)
), sollten Sie dieses Feature vielleicht besser nicht verwenden, wenn Sie nicht als OO-Ignorant gelten wollen... ;-)
$vec2 = $vec1->Shadow();
Erzeugt einen NEUEN Bitvektor "$vec2
". Dieser besitzt die GLEICHE Anzahl von Bits wie "$vec1
", ist aber LEER (d.h. alle Bits sind gelöscht).
Genau wie ein Schatten, der den Umriß des Objekts besitzt, von dem er abstammt. Nur ist er im Gegensatz zu diesem Objekt völlig flach und hat kein Volumen, d.h. er enthält nichts.
$vec2 = $vec1->Clone();
Erzeugt einen NEUEN Bitvektor "$vec2
". Dieser besitzt die GLEICHE Anzahl von Bits wie "$vec1
" und ist eine EXAKTE KOPIE desselben.
$vector = $vec1->Concat($vec2);
Diese Methode gibt ein neues Bitvektor-Objekt zurück, das aus der Verkettung von "$vec1
" und "$vec2
" entsteht.
Beachten Sie, daß der Inhalt von "$vec1
" zum HÖCHSTWERTIGEN Teil und "$vec2
" zum NIEDERWERTIGSTEN Teil des resultierenden Bitvektors wird.
Haben beide Bitvektor-Argumente die Länge Null, hat auch der resultierende Bitvektor die Länge Null.
$vector = $vec1->Concat_List($vec2,$vec3,...);
Eine alternative Möglichkeit, diese (Klassen-) Methode als Objektmethode aufzurufen.
Die Methode gibt ein neues Bitvektor-Objekt zurück, das aus der Verkettung von "$vec1 . $vec2 . $vec3 .
" usw. entsteht.
Eine detailliertere Beschreibung dieser Methode finden Sie im obigen Abschnitt "Klassenmethoden".
Beachten Sie, daß die Argumentliste leer sein kann und daß alle Argumente Bitvektoren sein müssen, falls sie das nicht ist.
$bits = $vector->Size();
Gibt die Größe (Anzahl der Bits) zurück, mit der der gegebene Bitvektor erzeugt wurde, oder die er mittels der Methode "Resize()
" erhalten hat.
$vector->Resize($bits);
Setzt die Größe des gegebenen Bitvektors auf die angegebene Anzahl von Bits.
Mit dieser Methode können Sie die Größe eines bereits existierenden Bitvektors verändern. Dabei bleiben so viele Bits des alten Bitvektors wie nur irgend möglich erhalten, d.h. so viele wie noch in den neuen Bitvektor hineinpassen. (Dies sind alle Bits, deren Nummern kleiner sind als das Minimum aus den Größen des alten und des neuen Bitvektors, d.h alle NIEDERWERTIGSTEN Bits.)
Ist dabei die Anzahl der zur Speicherung des neuen Bitvektors erforderlichen Maschinenworte kleiner oder gleich der Anzahl der vom alten Bitvektor benötigten Maschinenworte, wird der von dem alten Bitvektor belegte Speicherplatz für den neuen Bitvektor wiederverwendet. Nur die zugehörigen Verwaltungsinformationen werden entsprechend angepaßt.
Das bedeutet, daß nicht notwendigerweise neuer Speicher alloziert werden muß, wenn sich die Anzahl der Bits erhöht, nämlich solange die alte und die neue Anzahl von Bits in die gleiche Anzahl von Maschinenworten passt.
Ist die Anzahl der zur Speicherung des neuen Bitvektors benötigten Maschinenworte größer als die des alten Bitvektors, wird für den neuen Bitvektor neuer Speicher alloziert, der alte Bitvektor wird in den neuen Bitvektor kopiert, die restlichen (HÖCHSTWERTIGEN) Bits des neuen Bitvektors werden mit Nullen initialisiert (also gelöscht) und der Speicherplatz für den alten Bitvektor wird wieder freigegeben.
Beachten Sie dabei, daß wenn Sie die Größe eines Bitvektors soweit verringern, daß weniger Maschinenworte benötigt werden als vorher, und wenn Sie dann die Größe des Bitvektors wieder erhöhen, so daß mehr Maschinenworte als unmittelbar vorher, aber immer noch weniger als ursprünglich benötigt werden, muß trotzdem neuer Speicher alloziert werden, weil die Information über die Größe des ursprünglichen Bitvektors bereits mit der ersten Größenänderung verlorengegangen ist.
Eine Ausnahme wird ausgelöst, wenn die Methode nicht in der Lage ist, den für den neuen Bitvektor benötigten Speicherplatz zu allozieren.
Denken Sie auch daran, daß eine negative Anzahl von Bits aufgrund der internen binären Darstellung im Zweierkomplement als (in der Regel sehr große!) positive Zahl interpretiert wird.
Im Fall einer solchen negativen Anzahl von Bits versucht die "Resize()
"-Methode trotzdem pflichtschuldigst, einen Bitvektor dieser Größe zu erzeugen, was in der Regel zu einem fatalen Fehler mit Programmabbruch führt.
Beachten Sie schließlich noch, daß im Gegensatz zu früheren Versionen dieses Moduls jetzt auch Bitvektoren der Länge Null (also mit "$bits = 0
") zugelassen sind.
$vec2->Copy($vec1);
Kopiert den Inhalt von "$vec1
" in den Bitvektor "$vec2
".
Der vorherige Inhalt des Bitvektors "$vec2
" wird dabei überschrieben, geht also verloren.
Beide Bitvektoren müssen bereits existieren, d.h. diese Methode erzeugt KEIN neues Bitvektor-Objekt.
$vector->Empty();
Löscht alle Bits im angegebenen Bitvektor.
$vector->Fill();
Setzt alle Bits im angegebenen Bitvektor.
$vector->Flip();
Komplementiert alle Bits im angegebenen Bitvektor.
$vector->Primes();
Löscht den angegebenen Bitvektor und setzt alle Bits, deren Bit-Nummern Primzahlen sind.
Diese Methode verwendet intern den Algorithmus, der unter dem Namen "Sieb des Erathostenes" bekannt ist.
$vec2->Reverse($vec1);
Diese Methode kopiert den Bitvektor "$vec1
" in den Bitvektor "$vec2
" und kehrt dabei die Reihenfolge aller Bits um.
Das niederwertigste Bit von "$vec1
" wird also zum höchstwertigen Bit von "$vec2
", während das höchstwertige Bit von "$vec1
" zum niederwertigsten Bit von "$vec2
" wird, usw.
Eine Verarbeitung "auf derselben Stelle" ist ebenfalls möglich, d.h. "$vec1
" und "$vec2
" können identisch sein.
(Intern ist das jedoch dasselbe, als würde man statt dessen "$vec1->Interval_Reverse(0,$vec1->Size()-1);
" aufrufen.)
$vector->Interval_Empty($min,$max);
Löscht alle Bits des angegebenen Bitvektors im Intervall [$min..$max]
(inklusive beider Grenzen).
"$min
" und "$max
" können auch denselben Wert annehmen. Dies entspricht dem Löschen eines einzelnen Bits mit "Bit_Off()
", ist aber weniger effizient.
Beachten Sie auch, daß "$vector->Interval_Empty(0,$vector->Size()-1);
" mit "$vector->Empty();
" äquivalent ist (aber ebenfalls weniger effizient).
$vector->Interval_Fill($min,$max);
Setzt alle Bits des angegebenen Bitvektors im Intervall [$min..$max]
(inklusive beider Grenzen).
"$min
" und "$max
" können auch denselben Wert annehmen. Dies entspricht dem Setzen eines einzelnen Bits mit "Bit_On()
", ist aber weniger effizient.
Beachten Sie auch, daß "$vector->Interval_Fill(0,$vector->Size()-1);
" mit "$vector->Fill();
" äquivalent ist (aber ebenfalls weniger effizient).
$vector->Interval_Flip($min,$max);
Komplementiert alle Bits des angegebenen Bitvektors im Intervall [$min..$max]
(inklusive beider Grenzen).
"$min
" und "$max
" können auch denselben Wert annehmen. Dies entspricht der Komplementierung eines einzelnen Bits mit "bit_flip()
", ist aber weniger effizient.
Beachten Sie auch, daß "$vector->Interval_Flip(0,$vector->Size()-1);
" mit "$vector->Flip();
" und "$vector->Complement($vector);
" äquivalent ist (aber ebenfalls weniger effizient).
$vector->Interval_Reverse($min,$max);
Kehrt die Reihenfolge der Bits des angegebenen Bitvektors im Intervall [$min..$max]
(inklusive beider Grenzen) um.
D.h. die Bits mit den Nummern "$min
" und "$max
" tauschen ihre Plätze und alle dazwischen liegenden Bits entsprechend.
"$min
" und "$max
" können auch denselben Wert annehmen. Eine solche Operation hat allerdings keinerlei Effekt.
if (($min,$max) = $vector->Interval_Scan_inc($start))
Gibt die niedrigste und die höchste Bit-Nummer des (in aufsteigender Richtung) nächstfolgenden, zusammenhängenden Blocks von (auf eins) gesetzten Bits zurück.
Die Suche beginnt bei der Bit-Nummer "$start
" (d.h. "$min" >= "$start"
) und verläuft von da ab aufwärts (d.h. "$max" >= "$min"
), wobei der Suchzeiger "$start
" (intern) fortwährend inkrementiert wird.
Der Inhalt der Variablen (oder der Skalar-Konstanten) "$start
" wird dabei jedoch NICHT verändert. Das heißt, daß Sie den gewünschten Wert selbst einstellen müssen, bevor Sie "Interval_Scan_inc()
" aufrufen (beachten Sie hierzu auch das nachfolgende Beispiel).
In Wirklichkeit wird der Bitvektor nicht Bit für Bit durchsucht, sondern jeweils ein Maschinenwort auf einmal, um die Ausführungsgeschwindigkeit zu erhöhen (diese Methode ist daher ziemlich effizient).
Eine leere Liste wird zurückgegeben, wenn kein weiterer solcher Block gefunden werden konnte.
Beachten Sie, daß ein einzelnes gesetztes Bit (beidseitig von gelöschten Bits eingeschlossen) dieser Definition nach ein gültiger Block ist. In einem solchen Fall wird in "$min
" und "$max
" der identische Wert zurückgegeben (nämlich die Nummer des betreffenden Bits).
Typische Anwendung:
$start = 0; while (($start < $vector->Size()) && (($min,$max) = $vector->Interval_Scan_inc($start))) { $start = $max + 2; # Verarbeite $min und $max in geeigneter Weise }
if (($min,$max) = $vector->Interval_Scan_dec($start))
Gibt die niedrigste und die höchste Bit-Nummer des (in absteigender Richtung) nächstfolgenden, zusammenhängenden Blocks von (auf eins) gesetzten Bits zurück.
Die Suche beginnt bei der Bit-Nummer "$start
" (d.h. "$max" <= "$start"
) und verläuft von da an abwärts (d.h. "$min" <= "$max"
), wobei der Suchzeiger "$start
" (intern) fortwährend dekrementiert wird.
Der Inhalt der Variablen (oder der Skalar-Konstanten) "$start
" wird dabei jedoch NICHT verändert. Das heißt, daß Sie den gewünschten Wert selbst einstellen müssen, bevor Sie "Interval_Scan_dec()
" aufrufen (beachten Sie hierzu auch das nachfolgende Beispiel).
In Wirklichkeit wird der Bitvektor nicht Bit für Bit durchsucht, sondern jeweils ein Maschinenwort auf einmal, um die Ausführungsgeschwindigkeit zu erhöhen (diese Methode ist daher ziemlich effizient).
Eine leere Liste wird zurückgegeben, wenn kein weiterer solcher Block gefunden werden konnte.
Beachten Sie, daß ein einzelnes gesetztes Bit (beidseitig von gelöschten Bits eingeschlossen) dieser Definition nach ein gültiger Block ist. In einem solchen Fall wird in "$min
" und "$max
" der identische Wert zurückgegeben (nämlich die Nummer des betreffenden Bits).
Typische Anwendung:
$start = $vector->Size() - 1; while (($start >= 0) && (($min,$max) = $vector->Interval_Scan_dec($start))) { $start = $min - 2; # Verarbeite $min und $max in geeigneter Weise }
$vec2->Interval_Copy($vec1,$offset2,$offset1,$length);
Mit dieser Methode können Sie ein Intervall von Bits (beginnend an einer beliebigen, von Ihnen gewählten Position "$offset1
" und mit einer Länge von "$length
" Bits) von einem Quell-Bitvektor "$vec1
" an die Position "$offset2
" in einem Ziel-Bitvektor "$vec2
" kopieren.
Beachten Sie, daß die beiden Bitvektoren "$vec1
" und "$vec2
" NICHT die gleiche Größe haben müssen!
Sowohl "$offset1 + $length
" als auch "$offset2 + $length
" können daher die tatsächliche Länge des entsprechenden Bitvektors ("$vec1->Size()
" bzw. "$vec2->Size()
") übersteigen.
In einem solchen Fall wird intern automatisch der Längenparameter "$length
" so angepaßt, daß die beiden obigen Terme durch die Anzahl der Bits von BEIDEN Bitvektoren nach oben begrenzt werden, d.h. so, daß sowohl "$offset1 + $length <= $vec1->Size()
" als auch "$offset2 + $length <= $vec2->Size()
" gilt.
Das kann auch zu einer Länge von Null Bits führen; in diesem Fall hat diese Methode keinerlei Effekt.
(Selbstverständlich darf der Längenparameter "$length
" auch von vornherein Null betragen!)
Beachten Sie auch, daß "$offset1
" und "$offset2
" innerhalb des Bereichs "0
" und "$vec1->Size()-1
" bzw. "$vec2->Size()-1
" liegen müssen, sonst kommt es zu einem fatalen Offset-Fehler ("offset out of range").
Beachten Sie weiterhin, daß "$vec1
" und "$vec2
" identisch sein können, d.h. Sie können Bits von einem Ort innerhalb desselben Bitvektors an einen anderen Ort kopieren (und die dortigen Bits damit überschreiben).
Das Quell- und das Ziel-Intervall dürfen sich dabei sogar überlappen. Der Kopiervorgang erfolgt dann automatisch in auf- oder absteigender Richtung, je nachdem ob das Quell- oder das Ziel-Intervall zuunterst liegt (bezogen auf Bit-Nummern). Es werden also keine Bits überschrieben, bevor diese nicht selbst kopiert wurden.
$vec2->Interval_Substitute($vec1,$off2,$len2,$off1,$len1);
Diese Methode ist für Bitvektoren (also Arrays von Bits) in etwa das gleiche, was die Perl-Funktion "splice()
" für Listen (also Arrays von Skalaren) ist.
(Details zur Funktion "splice()
" finden Sie in perlfunc(1).)
Mit dieser Methode können Sie ein Intervall von Bits (ab der Position "$off2
" und mit einer Länge von "$len2
" Bits) in einem Ziel-Bitvektor "$vec2
" durch ein anderes Intervall von Bits (ab der Position "$off1
" und mit einer Länge von "$len1
" Bits) aus einem Quell-Bitvektor "$vec1
" ersetzen.
Beachten Sie, daß die beiden Bitvektoren "$vec1
" und "$vec2
" NICHT die gleiche Länge haben müssen!
Beachten Sie auch, daß "$off1
" und "$off2
" innerhalb des Bereichs "0
" und "$vec1->Size()
" bzw. "$vec2->Size()
" liegen müssen, sonst kommt es zu einem fatalen Offset-Fehler ("offset out of range").
Aufmerksame Leser werden sicherlich bemerkt haben, daß diese Obergrenzen hier NICHT "$vec1->Size()-1
" und "$vec2->Size()-1
" lauten, wie das bei allen anderen Methoden dieses Moduls (wo anwendbar) der Fall ist. Tatsächlich können diese Offsets auf die Stelle genau eine Position HINTER dem Ende des jeweiligen Bitvektors zeigen.
Das ist deswegen unbedingt notwendig, damit man ein gegebenes Quell-Intervall ggfs. auch HINTEN an den Ziel-Bitvektor ANHÄNGEN kann, anstatt ein bestehendes Intervall darin nur zu ERSETZEN.
Aus Gründen der Symmetrie und der Einheitlichkeit gilt das gleiche auch für den Offset im Quell-Bitvektor, auch wenn ein solcher Offset (eine Position hinter dem Ende des Bitvektors) hier keinerlei praktischen Zwecken dient (aber auch keinen Schaden anrichtet).
(Tatsächlich erspart das jedoch unter bestimmten Umständen einen Test für diesen Sonderfall.)
Übersteigt der Term "$off1 + $len1
" die Größe "$vec1->Size()
" des Bitvektors "$vec1
" (oder "$off2 + $len2
" die Größe "$vec2->Size()
"), wird die entsprechende Länge ("$len1
" bzw. "$len2
") intern automatisch so weit reduziert, daß sowohl "$off1 + $len1 <= $vec1->Size()
" als auch "$off2 + $len2 <= $vec2->Size()
" gilt.
(Beachten Sie, daß sich dadurch am gewünschten Ergebnis NICHTS ändert, auch wenn das auf den ersten Blick nicht der Fall zu sein scheint!)
Das kann sogar zu einer Länge ("$len1
" oder "$len2
") von Null Bits führen.
Die Länge Null für das Intervall im QUELL-Bitvektor ("$len1 == 0
") bewirkt, daß das Intervall im Ziel-Bitvektor (beginnend an Position "$off2
") durch NICHTS ersetzt, also GELÖSCHT wird.
Die Länge Null für das Intervall im ZIEL-Bitvektor ("$len2
== 0") bedeutet, daß NICHTS ersetzt werden soll, d.h. das Intervall aus dem Quell-Bitvektor wird im Ziel-Bitvektor an der angegebenen Stelle ("$off2
") einfach nur EINGEFÜGT.
Sind dagegen BEIDE Längenparameter Null, hat diese Methode keinerlei Effekt.
Beachten Sie, daß diese Methode im Gegensatz zu allen anderen Methoden dieses Moduls (speziell zu "
(Die einzige andere Methode dieses Moduls, die die Größe eines Bitvektors verändert, ist "
Mit anderen Worten, das Ersetzen eines Bit-Intervalls im Ziel-Bitvektor durch ein längeres oder kürzeres Intervall aus dem Quell-Bitvektor führt dazu, daß die Länge des Ziel-Bitvektors automatisch vergrößert bzw. verringert wird. Das gleiche gilt auch für das Einfügen eines Bit-Intervalls in ("
Aus Gründen der Allgemeinheit ("OBdA"...
Hierin liegt auch der Grund, warum dieses Modul seit der Version 5.0 überhaupt Bitvektoren der Länge Null zuläßt(!).
Beachten Sie schließlich auch, daß "
(Wenn Sie eine Weile darüber nachdenken oder sich den Code anschauen, werden Sie sehen, daß das alles andere als trivial ist!)
Überprüft, ob der Bitvektor vollständig "leer" ist, d.h. ob ALLE Bits gelöscht ("aus") sind.
Bei "Big Integer"-Arithmetik entspricht das dem Test, ob die im Bitvektor abgelegte Zahl eine Null ("
Gibt "wahr" ("
Beachten Sie, daß die Methode z.B. auch dann "wahr" ("
Überprüft, ob der Bitvektor "voll" ist, d.h. ob ALLE Bits gesetzt ("an") sind.
Bei "Big Integer"-Arithmetik entspricht das dem Test, ob die im Bitvektor abgelegte Zahl eine "
Gibt "wahr" ("
Hat der Bitvektor die Länge Null (sind also darin überhaupt keine Bits enthalten), gibt die Methode IMMER "falsch" ("
Überprüft, ob die beiden übergebenen Bitvektoren gleich sind.
Gibt "wahr" ("
Vergleicht die beiden übergebenen Bitvektoren, die als VORZEICHENLOS angesehen werden.
Die Methode gibt "
Vergleicht die beiden übergebenen Bitvektoren, die als VORZEICHENBEHAFTET angesehen werden.
Die Methode gibt "
Liefert einen String zurück, der die dem gegebenen Bitvektor entsprechende Hexadezimalzahl enthält.
Diese Darstellung ist übrigens recht kompakt (platzsparend), da sie nur doppelt so viele Bytes benötigt, wie zur internen Speicherung des Bitvektors selbst notwendig sind.
Beachten Sie, daß der resultierende String immer einem Vielfachen von vier Bits entspricht, da jede hexadezimale Ziffer genau vier Bits repräsentiert. Diese Anzahl von Bits kann daher ggfs. von der des gegebenen Bitvektors abweichen, falls die Länge des Bitvektors kein Vielfaches von vier ist. Das ist jedoch nicht weiter schlimm, da es sich dabei lediglich um führende Nullen handelt.
Um die Konvertierung weiter zu vereinfachen, werden außerdem die ungenutzten Bits des Bitvektors (falls es welche gibt) ebenfalls mit ausgegeben, was zu zusätzlichen (aber unschädlichen) führenden hexadezimalen Nullen führen kann.
Beachten Sie schließlich noch, daß die NIEDERWERTIGSTE hexadezimale Ziffer am RECHTEN Ende des resultierenden Strings zu finden ist, während die HÖCHSTWERTIGE hexadezimale Ziffer am LINKEN Ende steht.
Erlaubt das Einlesen des Inhalts eines Bitvektors über einen hexadezimalen String, wie er beispielsweise von der Methode "
Denken Sie daran, daß die NIEDERWERTIGSTEN Ziffern immer RECHTS im hexadezimalen String zu finden sind, während die HÖCHSTWERTIGEN Ziffern am LINKEN Ende stehen. Aus diesem Grund wird der String auch immer von rechts nach links eingelesen, wobei der Bitvektor währenddessen in aufsteigender Richtung aufgefüllt wird. Dabei werden immer jeweils vier Bits auf einmal verarbeitet, angefangen vom niederwertigsten Bit bis hin zum höchstwertigen.
Enthält ein String weniger hexadezimale Ziffern, als zum vollständigen Füllen des Bitvektors erforderlich wären, werden die übrigen (höchstwertigen) Bits des Bitvektors alle gelöscht.
Das bedeutet auch, daß der vorherige Inhalt des Bitvektors vollständig gelöscht wird, selbst wenn der String nicht genug Ziffern enthält, um den Bitvektor ganz zu füllen.
Ist der String dagegen länger als für das vollständige Füllen des Bitvektors erforderlich ist, werden die überflüssigen Bits und/oder Zeichen einfach ignoriert.
Tatsächlich werden sie völlig ignoriert - sie werden nicht einmal auf korrekte Syntax untersucht. (Mehr hierzu finden Sie auch weiter unten.)
Dieses Verhalten ermöglicht es, einen Bitvektor in einen String umzuwandeln und diesen String in einem anderen Bitvektor mit u.U. einer ganz anderen Größe wieder einzulesen (zumindest so viel davon, wie in den zweiten Bitvektor hineinpaßt!).
Wird während des Einlesens des Strings ein Zeichen gefunden, das keine hexadezimale Ziffer ist, hat das einen fatalen Syntaxfehler ("input string syntax error") mit Programmabbruch zur Folge.
Liefert einen String zurück, der die dem gegebenen Bitvektor entsprechende Binärzahl enthält.
Beispiel:
Dies führt zu folgender Ausgabe:
(Die Bits 7, 5, 3 und 2 sind gesetzt, also die ersten paar Primzahlen.)
Beachten Sie, daß das NIEDERWERTIGSTE Bit am RECHTEN Ende des resultierenden Strings steht, während das HÖCHSTWERTIGE Bit am LINKEN Ende steht.
Diese Methode erlaubt das Einlesen eines Bitvektors aus einem Binärstring, wie er beispielsweise von der Methode "
Beachten Sie, daß die Methode davon ausgeht, daß das NIEDERWERTIGSTE Bit am RECHTEN Ende des Binärstrings steht und das HÖCHSTWERTIGE Bit am LINKEN Ende. Aus diesem Grund wird der String auch immer von rechts nach links eingelesen, wobei der Bitvektor währenddessen in aufsteigender Richtung aufgefüllt wird, angefangen beim niederwertigsten Bit bis hin zum höchstwertigen.
Enthält der String weniger Binärziffern ("
Das bedeutet auch, daß der vorherige Inhalt des Bitvektors vollständig gelöscht wird, selbst wenn der String nicht genug Ziffern enthält, um den Bitvektor ganz zu füllen.
Ist ein String länger als das zum Füllen des gegebenen Bitvektors notwendig ist, werden die überflüssigen Zeichen einfach ignoriert.
Tatsächlich werden sie völlig ignoriert - sie werden nicht einmal auf korrekte Syntax untersucht. (Mehr hierzu finden Sie auch weiter unten.)
Dieses Verhalten ermöglicht es, einen Bitvektor in einen String umzuwandeln und diesen String in einem anderen Bitvektor mit u.U. einer ganz anderen Größe wieder einzulesen (zumindest so viel davon, wie in den zweiten Bitvektor hineinpaßt!).
Wird während des Einlesens des Strings ein Zeichen gefunden, das nicht "
Diese Methode gibt einen String zurück, der den Inhalt des gegebenen Bitvektors als Dezimalzahl (Zahl zur Basis
Beachten Sie, daß diese Methode davon ausgeht, daß der gegebene Bitvektor VORZEICHENBEHAFTET ist (und eine Zahl in binärer Zweierkomplement-Darstellung enthält).
Das hat zur Folge daß jeder Bitvektor, dessen höchstwertiges Bit gesetzt ist, als eine NEGATIVE Zahl betrachtet wird.
Der zurückgegebene String kann an "
Beachten Sie, daß diese Umwandlung von der internen binären Darstellung nach dezimal sehr aufwendig und somit vergleichsweise langsam ist, da der Bitvektor dafür solange durch
Das gilt im Prinzip auch für die Implementierung dieser Methode in diesem Modul. Es wurden hier jedoch noch einige Maßnahmen getroffen, um die Effizienz zu steigern: Statt wiederholt durch
Meinen Messungen zufolge ist diese Variante etwa 8 mal schneller als der naive Ansatz.
Nichtsdestotrotz sollte die Umwandlung von Bitvektoren in Dezimalzahlen so spärlich wie möglich verwendet werden, da diese Umwandlung trotz der effizienzsteigernden Maßnahmen bei sehr großen Bitvektoren (z.B. einige tausend Bits) ein bis zwei Sekunden dauern kann!
Legen Sie den zurückgegebenen String daher in irgendeiner Variablen ab, falls Sie ihn nochmals benötigen sollten, anstatt den Bitvektor erneut zu konvertieren.
Bedenken Sie, daß wenn Sie die Konfiguration für überladene Operatoren auf "
Diese Methode erlaubt Ihnen die Umwandlung einer gegebenen Dezimalzahl (positiv oder negativ) in eine binäre Zweierkomplement-Darstellung, die im gegebenen Bitvektor abgelegt wird.
Die Dezimalzahl sollte dabei IMMER ALS STRING übergeben werden, um einem möglichen Genauigkeitsverlust durch Abschneiden von Dezimalstellen vorzubeugen, der durch die interne Darstellung von großen Zahlen in Perl im Fließkommaformat (mit Exponenten) auftreten kann.
Ist die Binärdarstellung der gegebenen Dezimalzahl zu groß, um in den gegebenen Bitvektor zu passen (besitzt der Bitvektor also nicht genug Bits, um diesen Wert aufzunehmen), kommt es zu einem fatalen numerischen Überlauffehler ("numeric overflow error").
Um diesen Fehler zu vermeiden, machen Sie den Bitvektor vorher einfach größer!
Enthält der Eingabestring andere Zeichen als die Dezimalziffern "
Ist ein möglicher Programmabbruch unerwünscht oder von Ihrer Anwendung her nicht tolerierbar, können Sie "
Es gibt vier mögliche Fehlermeldungen:
Beachten Sie, daß die Umwandlung von Dezimalzahlen in die interne Binärdarstellung relativ aufwendig ist und somit langsam, da hierfür eine Vielzahl von Multiplikationen ausgeführt werden muß. (Im Prinzip muß dazu jede Dezimalziffer mit der binären Entsprechung derjenigen
Auch hier (wie bei der Methode "
Diese Umwandlung ist zwar nicht ganz so zeitaufwendig wie die umgekehrte Umwandlung von Binär nach Dezimal (bei der anstelle von Multiplikationen noch zeitintensivere Divisionen durchgeführt werden müssen), aber dennoch vergleichsweise langsam.
Aus diesem Grunde sollten Sie diese Methode so spärlich wie nur möglich verwenden, und lieber nach der Umwandlung eine identische Kopie des betreffenden Bitvektors anlegen, als denselben String noch einmal zu konvertieren.
Bedenken Sie, daß wenn Sie die Konfiguration für überladene Operatoren auf "
Wandelt den gegebenen Bitvektor in eine Aufzählung einzelner Bit-Nummern oder zusammenhängender Bereiche von Bit-Nummern (im ".newsrc"-Stil) um, die alle (auf "
Beispiel:
Dies ergibt:
Ist der gegebene Bitvektor leer, so ist der resultierende String ebenfalls leer.
Das obige Beispiel kann man übrigens auch noch etwas kompakter formulieren:
Diese Methode löscht zunächst den gegebenen Bitvektor und setzt dann die Bits zu den im String angegebenen Bit-Nummern und Bereichen von Bit-Nummern auf "
Der String "
Alle anderen Zeichen (auch Leerzeichen!) sind nicht erlaubt und führen zu einem fatalen Syntaxfehler ("input string syntax error").
Bei jeder Bereichsangabe muß die erste Zahl (die untere Grenze des Bereichs) stets kleiner oder gleich der zweiten Zahl (der oberen Grenze) sein, sonst tritt ein fataler Indexfehler ("minimum > maximum index") auf.
Alle Bit-Nummern müssen außerdem im erlaubten Bereich des gegebenen Bitvektors liegen, d.h. zwischen "
Ist diese Bedingung nicht erfüllt, kommt es ebenfalls zu einem fatalen Indexfehler ("index out of range").
Ist ein möglicher Programmabbruch unerwünscht oder von Ihrer Anwendung her nicht tolerierbar, können Sie "
Es gibt vier mögliche Fehlermeldungen:
Die Reihenfolge der Bit-Nummern und der Bereiche ist übrigens unerheblich, d.h.
führt zu dem gleichen Bitvektor wie im obigen Beispiel.
Bereiche und Bit-Nummern können sich auch überlappen.
Das liegt daran, daß intern jede (einzelne) Bit-Nummer aus dem String an die Methode"
Der resultierende Bitvektor ist also einfach die Vereinigungsmenge aller Bit-Nummern und Bereiche, die im String angegeben wurden.
Löscht das Bit mit der Nummer "
Setzt das Bit mit der Nummer "
Komplementiert das Bit mit der Nummer "
Darüber hinaus gibt die Methode den NEUEN Zustand des fraglichen Bits zurück, d.h. sie gibt "
Liefert den aktuellen Zustand des Bits mit der Nummer "
Setzt das Bit mit der Nummer "
Setzt das niederwertigste Bit im gegebenen Bitvektor auf den (booleschen) Wert "
Dies ist eine (effizientere) Abkürzung für "
Setzt das höchstwertige Bit im gegebenen Bitvektor auf den (booleschen) Wert "
Dies ist eine (effizientere) Abkürzung für "
Gibt das niederwertigste Bit im gegebenen Bitvektor zurück.
Dies ist eine (effizientere) Abkürzung für "
Gibt das höchstwertige Bit im gegebenen Bitvektor zurück.
Dies ist eine (effizientere) Abkürzung für "
Das niederwertigste Bit (LSB) ist das Bit mit der Nummer "
Das niederwertigste Bit (LSB) ist das Bit mit der Nummer "
Das niederwertigste Bit (LSB) ist das Bit mit der Nummer "
Das niederwertigste Bit (LSB) ist das Bit mit der Nummer "
Verschiebt den gegebenen Bitvektor um "
Die neu eingefügten Bits werden alle gelöscht (auf "aus" gesetzt).
Die Methode hat keinerlei Wirkung, falls "
Beachten Sie, daß der gesamte Bitvektor OHNE WARNUNG gelöscht wird, wenn "
Diese Methode ist äquivalent zu
ist aber - bei einer Anzahl "
Verschiebt den gegebenen Bitvektor um "
Diese freiwerdenden Bits werden alle gelöscht (auf "aus" gesetzt).
Die Methode hat keinerlei Wirkung, falls "
Beachten Sie, daß der gesamte Bitvektor OHNE WARNUNG gelöscht wird, wenn "
Diese Methode ist äquivalent zu
ist aber - bei einer Anzahl "
Diese Methode fügt "
Die "
Die nun freigewordenen "
Beachten Sie, daß diese Methode die Größe des gegebenen Bitvektors NICHT erhöht, d.h. der Bitvektor wird NICHT an seinem oberen (höchstwertigen) Ende erweitert, um die "
Falls Sie das nicht wollen, müssen Sie die Größe des gegebenen Bitvektors EXPLIZIT erhöhen, und zwar BEVOR Sie die Einfügeoperation durchführen. Dies ist mit der folgenden Anweisung möglich:
Alternativ können Sie anstelle von "
Beachten Sie auch, daß "
Ist der Term "
Diese Methode löscht (d.h. entfernt) alle Bits im gegebenen Bitvektor ab Bit Nummer "
Die höchstwertigen Bits ab Bit Nummer "
Die nun freigewordenen "
Beachten Sie, daß diese Methode die Größe des gegebenen Bitvektors NICHT verringert, d.h. der Bitvektor wird NICHT an seinem oberen (höchstwertigen) Ende abgeschnitten, um die überschüssigen "
Falls Sie das nicht wollen, müssen Sie die Größe des gegebenen Bitvektors EXPLIZIT verringern, und zwar NACH der Löschoperation. Dies ist mit den folgenden Anweisungen möglich:
Alternativ können Sie anstelle von "
Beachten Sie auch, daß "
Ist der Term "
Diese Methode inkrementiert den gegebenen Bitvektor.
Beachten Sie, daß diese Methode Bitvektoren als vorzeichenlos betrachtet, d.h. auf die größtmögliche positive Zahl folgt direkt die kleinstmögliche (oder, absolut gesehen, die größtmögliche) negative Zahl:
(Hierbei steht "
Die Methode gibt stets "falsch" ("
Dies kann für die Abbruchbedingung in einer "while"-Schleife genutzt werden, z.B. wenn Sie einen Bitvektor alle seine möglichen Werte durchlaufen lassen wollen.
Die Methode dekrementiert den gegebenen Bitvektor.
Beachten Sie, daß diese Methode Bitvektoren als vorzeichenlos betrachtet, d.h. auf die kleinstmögliche (oder, absolut gesehen, die größtmögliche) negative Zahl folgt direkt die größtmögliche positive Zahl:
(Hierbei steht "
Die Methode gibt stets "falsch" ("
Dies kann für die Abbruchbedingung in einer "while"-Schleife genutzt werden, z.B. wenn Sie einen Bitvektor alle seine möglichen Werte durchlaufen lassen wollen.
Diese Methode addiert die beiden Zahlen in den Bitvektoren "
Mit anderen Worten:
Beachten Sie, daß der Eingabeparameter "
Die Methode gibt einen booleschen Wert zurück, der anzeigt, ob ein Übertrag (in das nächsthöhere Bit) stattgefunden hat.
Die Ein- und Ausgabe des Übertrags wird hauptsächlich zur Kaskadierung benötigt, d.h. zur Addition von Zahlen, die in mehrere Teile zerlegt sind:
Beachten Sie, daß es für diese Methode keine Rolle spielt, ob die Zahlen in den beiden Bitvektoren ("
Beachten Sie allerdings auch, daß der Rückgabewert (der Übertrag bzw. "Carry") bedeutungslos ist, falls die Zahlen vorzeichenbehaftet sind!
Außerdem kann bei vorzeichenbehafteten Zahlen eine besondere Art von Fehler auftreten, die meist als Überlauffehler ("overflow error") bezeichnet wird:
Ein solcher Überlauffehler tritt dann ein, wenn das Vorzeichen des Ergebnisses (das höchstwertige Bit) durch einen Übertrag aus der direkt darunterliegenden Bit-Position verändert (d.h. verfälscht) wird.
Sie sind selbst dafür verantwortlich, daß kein solcher Überlauffehler auftreten kann, falls Ihre Zahlen vorzeichenbehaftet sind, indem Sie den Bitvektor vorher einfach groß genug machen.
Um ganz sicher zu gehen, daß kein Überlauffehler auftreten kann, machen Sie entweder Ihre Bitvektoren von Anfang an um mindestens ein Bit größer, als zur Darstellung der größten Zahl notwendig ist, die Sie verwenden wollen, oder verfahren Sie wie folgt:
Diese Methode subtrahiert die beiden Zahlen in den Bitvektoren "
Mit anderen Worten:
Beachten Sie, daß der Eingabeparameter "
Die Methode gibt einen booleschen Wert zurück, der anzeigt, ob ein Übertrag (in das nächsthöhere Bit) stattgefunden hat.
Dieser Wert ist "wahr" ("
Die Ein- und Ausgabe des Übertrags wird hauptsächlich zur Kaskadierung benötigt, d.h. zur Subtraktion von Zahlen, die in mehrere Teile zerlegt sind:
Beachten Sie, daß es für diese Methode keine Rolle spielt, ob die Zahlen in den beiden Bitvektoren ("
Beachten Sie allerdings auch, daß der Rückgabewert (der Übertrag bzw. "Carry") bedeutungslos ist, falls die Zahlen vorzeichenbehaftet sind!
Außerdem kann bei vorzeichenbehafteten Zahlen eine besondere Art von Fehler auftreten, die meist als Überlauffehler ("overflow error") bezeichnet wird:
Ein solcher Überlauffehler tritt dann ein, wenn das Vorzeichen des Ergebnisses (das höchstwertige Bit) durch einen Übertrag aus der direkt darunterliegenden Bit-Position verändert (d.h. verfälscht) wird.
Sie sind selbst dafür verantwortlich, daß kein solcher Überlauffehler auftreten kann, falls Ihre Zahlen vorzeichenbehaftet sind, indem Sie den Bitvektor vorher einfach groß genug machen.
Um ganz sicher zu gehen, daß kein Überlauffehler auftreten kann, machen Sie entweder Ihre Bitvektoren von Anfang an um mindestens ein Bit größer, als zur Darstellung der größten Zahl notwendig ist, die Sie verwenden wollen, oder verfahren Sie wie folgt:
Diese Methode berechnet das Zweierkomplement der Zahl in Bitvektor "
Eine Verarbeitung "auf derselben Stelle" ist ebenfalls möglich, d.h. "
Das Zweierkomplement einer Zahl in Binärdarstellung ist gegeben durch das Invertieren aller Bits und das Inkrementieren dieses Ergebnisses um eins.
Das entspricht dem Wechseln des Vorzeichens einer gegebenen Zahl von "
Beachten Sie, daß diese Methode ein Ihrer Intuition möglicherweise widersprechendes Ergebnis liefert, wenn die in dem gegebenen Bitvektor enthaltene Zahl den Wert "
Abhängig vom Vorzeichen (d.h. dem höchstwertigen Bit) der Zahl in Bitvektor "
Eine Verarbeitung "auf derselben Stelle" ist ebenfalls möglich, d.h. "
Die Methode berechnet also den Absolutwert der Zahl in Bitvektor "
Beachten Sie, daß diese Methode ein Ihrer Intuition möglicherweise widersprechendes Ergebnis liefert, wenn die in dem gegebenen Bitvektor enthaltene Zahl den Wert "
Diese Methode gibt den Wert Null ("
Sind nicht alle Bits gelöscht, gibt die Methode den Wert "
Diese Methode multipliziert die beiden Zahlen in den Bitvektoren "
Beachten Sie, daß diese Methode ihre Argumente als VORZEICHENBEHAFTET ansieht.
Wenn Sie sicherstellen wollen, daß eine sehr große Zahl niemals versehentlich als negativ angesehen werden kann, machen Sie entweder Ihre Bitvektoren von Anfang an um mindestens ein Bit größer, als zur Darstellung der größten Zahl notwendig ist, die in Ihren Berechnungen auftreten kann, oder verfahren Sie wie folgt:
Beachten Sie auch, daß im Prinzip alle drei Bitvektoren der Regel übereinstimmender Größen genügen müssen, daß aber der Bitvektor "
Denn schließlich kann die Multiplikation zweier Binärzahlen mit je "
Es ist daher eine gute Idee, den Bitvektor "
Sollten Sie sich dabei allerdings geirrt haben, kommt es zu einem fatalen Überlauffehler ("numeric overflow error") mit Programmabbruch.
Beachten Sie schließlich noch, daß eine Verarbeitung "auf derselben Stelle" möglich ist, d.h. "
Diese Methode dividiert die beiden Zahlen in den Bitvektoren "
Mit anderen Worten:
Aus diesem Grund müssen "
Ein fataler "Division-durch-Null"-Fehler ("division by zero error") tritt auf, falls "
Beachten Sie, daß diese Methode ihre Argumente als VORZEICHENBEHAFTET ansieht.
Wenn Sie sicherstellen wollen, daß eine sehr große Zahl niemals versehentlich als negativ angesehen werden kann, machen Sie entweder Ihre Bitvektoren von Anfang an um mindestens ein Bit größer, als zur Darstellung der größten Zahl notwendig ist, die Sie verwenden wollen, oder verfahren Sie wie folgt:
Beachten Sie schließlich noch, daß eine Verarbeitung "auf derselben Stelle" möglich ist, d.h. "
Diese Methode berechnet den "ggT" ("größten gemeinsamen Teiler" oder "Greatest Common Divisor") der beiden Zahlen in den Bitvektoren "
Die Methode benutzt dazu intern den Euklidischen Algorithmus:
Beachten Sie, daß es zu einem fatalen "Division-durch-Null"-Fehler ("division by zero error") kommt, falls eine der beiden Zahlen Null ist!
Beachten Sie auch, daß diese Methode ihre beiden Argumente als VORZEICHENBEHAFTET ansieht, intern aber mit den ABSOLUTWERTEN der beiden Zahlen arbeitet, d.h. das ERGEBNIS dieser Methode ist IMMER POSITIV.
Diese Methode erlaubt es, den Inhalt eines ganzen Bitvektors auf einmal (als Block) zu importieren.
Das kann nützlich sein, um z.B. Bitvektoren in einer Datei im (platzsparenden) Binärformat abzuspeichern (siehe dazu auch die direkt hierunter anschließende Beschreibung der Methode "
Beachten Sie, daß das Argument "
Eine automatische Umwandlung von Zahlen in Strings, wie sonst in Perl üblich, ist hier NICHT möglich (und macht hier auch keinerlei Sinn)!
Dieser String muß die Daten des Bitvektors in der "low order byte first"-Reihenfolge enthalten.
(Intern findet dann eine Umwandlung in die auf dem jeweiligen System verwendete Byte-Reihenfolge statt.)
Ist der gegebene String kürzer als zum vollständigen Füllen des gegebenen Bitvektors erforderlich wäre, werden die übrigbleibenden (höchstwertigen) Bytes des Bitvektors mit Nullen aufgefüllt. Das bedeutet, daß der vorherige Inhalt des Bitvektors immer vollständig gelöscht (überschrieben) wird.
Ist der gegebene String länger als zum vollständigen Füllen des gegebenen Bitvektors erforderlich, werden die überzähligen Bytes einfach ignoriert.
Wie Sie den Inhalt von "
Diese Methode erlaubt es, den Inhalt eines ganzen Bitvektors auf einmal (als Block) zu exportieren.
Das ist nützlich, wenn Sie beispielsweise den Inhalt eines Bitvektors für einen späteren Zeitpunkt in einer Datei sichern wollen.
Der Vorteil dieser Methode liegt darin, daß dies mit dem geringstmöglichen Speicherplatzbedarf geschehen kann, nämlich im Binärformat.
Die Methode liefert einen Perl-String zurück, der eine exakte Kopie des Inhalts des gegebenen Bitvektors ist, allerdings in die "low order byte first"-Reihenfolge umgewandelt, um sicherzustellen, daß diese Daten auch auf einem anderen Rechner mit einer anderen internen Byte-Reihenfolge genauso wieder eingelesen werden können (mit Hilfe der oben beschriebenen Methode "
Wie Sie diesen String in eine Datei schreiben können, können Sie im Abschnitt zu "
Jeder Bitvektor ist intern als ein Array von Maschinenworten organisiert.
Die Methoden, deren Namen mit "Word_" beginnen, erlauben Ihnen den Zugriff auf dieses interne Array von Maschinenworten.
Beachten Sie, daß diese Methoden alle MACHINENABHÄNGIG sind, weil die Größe eines Maschinenwortes vom jeweiligen System abhängt!
Aus diesem Grund sollten Sie diese Methoden NUR DANN verwenden, wenn die Portabilität Ihres Codes ohne Bedeutung ist!
(Aber können Sie wirklich sicher sein, daß Sie Ihr Programm nicht eines Tages vielleicht DOCH auf einem anderen Rechner einsetzen wollen?!)
Sie sind jedenfalls gewarnt worden!
Um maschinenunabhängig zu sein, sollten Sie statt dessen lieber die Methoden verwenden, deren Namen mit "
Die Methode "
Diese Methode ist das Äquivalent zu dem Ausdruck "
Diese Methode erlaubt es Ihnen, einen gegebenen Wert "
Beachten Sie, daß "
Diese Methode ist das Äquivalent zu dem Ausdruck "
Diese Methode erlaubt Ihnen das Auslesen des Maschinenwortes an der Position "
Beachten Sie, daß "
Diese Methode ist das Äquivalent zu dem Ausdruck "
Diese Methode erlaubt es Ihnen, eine Liste von Werten "
Dabei wird der GANZ LINKS stehende Wert in der Liste ("
Wenn die Liste "
Wenn die Liste "
Diese Methode ist das Äquivalent zu dem Ausdruck "
Diese Methode erlaubt es Ihnen, das interne Array von Maschinenworten eines gegebenen Bitvektors als Ganzes auf einen Schlag auszulesen.
Dabei ist der GANZ LINKS stehende Wert in der zurückgegebenen Liste ("
Diese Methode ist das Äquivalent zu dem Ausdruck "
Diese Methode fügt "
Die "
Die nun freigewordenen "
Beachten Sie, daß diese Methode die Größe des gegebenen Bitvektors NICHT erhöht, d.h. der Bitvektor wird NICHT an seinem oberen (höchstwertigen) Ende erweitert, um die "
Falls Sie das nicht wollen, müssen Sie die Größe des gegebenen Bitvektors EXPLIZIT erhöhen, und zwar BEVOR Sie die Einfügeoperation durchführen. Dies ist mit der folgenden Anweisung möglich:
Beachten Sie auch, daß "
Ist der Term "
Diese Methode löscht (d.h. entfernt) alle Maschinenworte aus dem internen Array des gegebenen Bitvektors ab Wort Nummer "
Die höchstwertigen Maschinenworte ab Wort Nummer "
Die nun freigewordenen "
Beachten Sie, daß diese Methode die Größe des gegebenen Bitvektors NICHT verringert, d.h. der Bitvektor wird NICHT an seinem oberen (höchstwertigen) Ende abgeschnitten, um die überschüssigen "
Falls Sie das nicht wollen, müssen Sie die Größe des gegebenen Bitvektors EXPLIZIT verringern, und zwar NACH der Löschoperation. Dies ist mit den folgenden Anweisungen möglich:
Beachten Sie auch, daß "
Ist der Term "
Diese Methode erlaubt das gleichzeitige Setzen mehrerer nebeneinanderliegender Bits auf einmal auf individuell unterschiedliche Werte (im Unterschied beispielsweise zu den Methoden "
Sie können dabei auf Chunks (d.h. Blöcke zusammenhängender Bits) mit einer Länge von eins bis maximal "
Um portabel zu sein, sollten Sie jedoch nie Chunks von mehr als 32 Bits verwenden.
Liegt die gegebene Chunk-Größe "
Die Methode kopiert die "
(Das bedeutet, daß Bit Nummer "
Ist der Term "
Beachten Sie, daß "
Die "
Diese Methode erlaubt das gleichzeitige Auslesen mehrerer nebeneinanderliegender Bits auf einmal.
Sie können dabei auf Chunks (d.h. Blöcke zusammenhängender Bits) mit einer Länge von eins bis maximal "
Um portabel zu sein, sollten Sie jedoch nie Chunks von mehr als 32 Bits verwenden.
Liegt die gegebene Chunk-Größe "
Die Methode liefert die "
(Das bedeutet, daß Bit Nummer "
Ist der Term "
Beachten Sie, daß "
Diese Methode erlaubt es Ihnen, den gegebenen Bitvektor mit einer Liste von Bit-Paketen ("Chunks") nahezu beliebiger Größe "
Tatsächlich muß die gegebene Chunk-Größe "
Um portabel zu sein, sollten Sie jedoch nie Chunks von mehr als 32 Bits verwenden.
Der gegebene Bitvektor wird von dieser Methode in aufsteigender Richtung gefüllt: Das erste Bit-Paket der Liste ("
Sind weniger Chunks in der Liste enthalten, als zum Füllen des gesamten Bitvektors notwendig sind, werden die verbleibenden (höchstwertigen) Bits des Bitvektors gelöscht, d.h. der vorherige Inhalt des gegebenen Bitvektors wird immer vollständig überschrieben.
Sind mehr Chunks in der Liste vorhanden, als zum Füllen des gesamten Bitvektors notwendig sind, oder ragt ein Chunk über die Grenze "
Die Methode eignet sich (neben vielen anderen Anwendungen) zum Beispiel für die Umwandlung von Paketgrößen in einem Datenstrom.
Diese Methode kann übrigens auch dazu benutzt werden, um einen oktalen String in einem gegebenen Bitvektor abzulegen:
Beachten Sie allerdings, daß hier im Gegensatz zu den Konvertierungsmethoden "
Um eine Syntaxüberprüfung durchzuführen, nehmen Sie einfach noch die folgenden Anweisungen in Ihr Programm mit auf:
Eine weitere Anwendung ist die Speicherung eines sich wiederholenden Musters in einem Bitvektor:
Diese Methode erlaubt das Auslesen des Inhalts eines gegebenen Bitvektors in Form einer Liste von Bit-Paketen ("Chunks") mit einer (innerhalb bestimmter Grenzen) frei wählbaren Anzahl von Bits "
Tatsächlich muß die gegebene Chunk-Größe "
Um portabel zu sein, sollten Sie jedoch nie Chunks von mehr als 32 Bits verwenden.
Der gegebene Bitvektor wird von dieser Methode in aufsteigender Richtung ausgelesen: Die "
Falls "
BEACHTEN SIE, daß bei sehr großen Bitvektoren und/oder sehr kleinen Werten von "
Sie können damit wahrscheinlich Ihre Anwendung aufgrund fehlenden Speichers zum Absturz bringen (jedes Listenelement ist intern ein vollwertiger Perl-Skalar mit einem entsprechenden Speicher-Overhead zu dessen Verwaltung!), oder zumindest ein (mehr oder weniger lang andauerndes) "Einfrieren" Ihrer Anwendung verursachen!
Mögliche Anwendungen:
Diese Methode ist besonders nützlich zur Konvertierung von Paketgrößen in einem Datenstrom.
Die Methode kann übrigens auch dazu verwendet werden, um einen gegebenen Bitvektor in einen String von Oktalzahlen umzuwandeln:
Diese Methode ermöglicht es Ihnen, eine Liste von Bit-Nummern anzugeben, die in einem gegebenen Bitvektor gelöscht werden sollen.
Tatsächlich ist diese Methode eine Abkürzung für
Im Gegensatz zu allen anderen Import-Methoden dieses Moduls löscht diese Methode den gegebenen Bitvektor NICHT, bevor diese Operation durchgeführt wird.
Vielmehr ermöglicht es diese Methode, die Ergebnisse verschiedener aufeinanderfolgender Aufrufe zu akkumulieren.
(Das gleiche gilt auch für die Methode "
Diese Methode ermöglicht es Ihnen, eine Liste von Bit-Nummern anzugeben, die in einem gegebenen Bitvektor gesetzt werden sollen.
Tatsächlich ist diese Methode eine Abkürzung für
Im Gegensatz zu allen anderen Import-Methoden dieses Moduls löscht diese Methode den gegebenen Bitvektor NICHT, bevor diese Operation durchgeführt wird.
Vielmehr ermöglicht es diese Methode, die Ergebnisse verschiedener aufeinanderfolgender Aufrufe zu akkumulieren.
(Das gleiche gilt auch für die Methode "
Diese Methode gibt eine Liste von Bit-Nummern von allen in dem gegebenen Bitvektor gesetzten Bits zurück.
Diese Bit-Nummern werden immer in aufsteigender Reihenfolge zurückgegeben.
Ist der gegebene Bitvektor leer (enthält er also nur gelöschte Bits), oder hat er die Länge Null (sind also überhaupt keine Bits vorhanden), gibt die Methode eine leere Liste zurück.
BEACHTEN SIE, daß bei sehr großen Bitvektoren unter Umständen eine geradezu überwältigende Anzahl von Listenelementen zurückgeliefert werden kann! VORSICHT!
Sie können dadurch einen Programmabbruch durch Speicherüberlauf verursachen, oder zumindest Ihre Anwendung für mehrere Sekunden zum Stocken bringen, also die Geschwindigkeit Ihrer Anwendung erheblich herabsetzen!
Diese Methode ist zum Beispiel nützlich, um eine Liste von Primzahlen zu erzeugen:
Diese Methode berechnet die Vereinigungsmenge von "
In der Mengentheorie schreibt man das üblicherweise als "
(Auf Rechnern ohne ein Zeichen für die Vereinigungsmenge wird dieser Operator häufig durch ein Pluszeichen ("+") ersetzt.)
Eine Verarbeitung "auf derselben Stelle" ist möglich, d.h. "
Diese Methode berechnet den Durchschnitt der beiden Mengen "
In der Mengentheorie schreibt man das üblicherweise als "
(Auf Rechnern ohne ein Zeichen für den (Mengen-) Durchschnitt wird dieser Operator häufig durch ein Sternchen ("*") ersetzt.)
Eine Verarbeitung "auf derselben Stelle" ist möglich, d.h. "
Diese Methode berechnet die Differenzmenge von "
In der Mengentheorie schreibt man das üblicherweise als "
Eine Verarbeitung "auf derselben Stelle" ist möglich, d.h. "
Diese Methode berechnet die symmetrische Differenzmenge von "
In der Mengentheorie kann das als "
Wenn Mengen als Bitvektoren implementiert sind, entspricht die obige Formel einem EXKLUSIV-ODER zwischen den sich entsprechenden Bits der beiden Bitvektoren (daher der Name dieser Methode).
Beachten Sie, daß diese Methode wesentlich effizienter ist als die explizite Evaluierung der obigen Formel, weil sie intern eine (in den Prozessor eingebaute) Anweisung in Maschinensprache verwendet.
Eine Verarbeitung "auf derselben Stelle" ist möglich, d.h. "
Diese Methode berechnet das Komplement von "
Bei der "Big Integer"-Arithmetik entspricht das der Berechnung des Einerkomplements der im Bitvektor "
Eine Verarbeitung "auf derselben Stelle" ist ebenfalls möglich, d.h. "
Gibt "wahr" ("
Das bedeutet, daß jedes in "
Beachten Sie daß wenn beide Mengen identisch sind, diese per Definition auch jeweils sowohl Teilmengen als auch Obermengen voneinander sind. Dies gilt auch dann, wenn beide Mengen keinerlei gesetzte Bits enthalten, wenn sie also beide die "leere Menge" darstellen (dies gilt jedoch NICHT, wenn die beiden Bitvektoren die LÄNGE Null haben, wenn sie also GAR KEINE Bits enthalten!).
Gibt die Norm (d.h. die Anzahl der gesetzten Bits) des gegebenen Bitvektors zurück.
Das entspricht der Anzahl der in einer gegebenen Menge enthaltenen Elemente, also der "Kardinalität" dieser Menge.
Gibt das Minimum der gegebenen Menge zurück, d.h. das Minimum der Bit-Nummern aller gesetzten Bits im gegebenen Bitvektor "
Ist die Menge leer (d.h. enthält der gegebene Bitvektor keinerlei gesetzte Bits), wird plus Unendlich zurückgegeben (was von dieser Methode durch die Konstante "MAX_LONG" auf Ihrem System symbolisiert wird).
(Diese Konstante ist üblicherweise 2 ^ (n-1) - 1, wobei "
Gibt das Maximum der gegebenen Menge zurück, d.h. das Maximum der Bit-Nummern aller gesetzten Bits im gegebenen Bitvektor "
Ist die Menge leer (d.h. enthält der gegebene Bitvektor keinerlei gesetzte Bits), wird minus Unendlich zurückgegeben (was von dieser Methode durch die Konstante "MIN_LONG" auf Ihrem System symbolisiert wird).
(Diese Konstante ist üblicherweise -(2 ^ (n-1) - 1) oder -(2 ^ (n-1)), wobei "
Diese Methode multipliziert zwei (als Bitvektoren gespeicherte) boolesche Matrizen "
Eine Ausnahme wird ausgelöst, wenn das Produkt aus Zeilen- und Spaltenanzahl einer der drei Matrizen nicht mit der Größe des jeweils zugrundeliegenden Bitvektors übereinstimmt.
Eine Ausnahme wird auch ausgelöst, wenn die Anzahlen der Zeilen und Spalten der drei Matrizen nicht in der notwendigen Weise harmonieren:
Diese Methode wird vom Modul "Math::MatrixBool" verwendet.
Nähere Details zu dieser Methode finden Sie in Math::MatrixBool(3).
Diese Methode berechnet mit Hilfe des Kleene-Algorithmus die reflexive transitive Hülle einer (als Bitvektor gespeicherten) booleschen Matrix.
(Eine kurze Einführung in die Theorie hinter Kleenes Algorithmus finden Sie in Math::Kleene(3).)
Mit Hilfe der reflexiven transitiven Hülle läßt sich die Frage beantworten, ob zwischen je zwei beliebigen Knoten eines Graphen (dessen Kanten als Matrix gegeben sind) ein Pfad existiert:
Wenn eine (gerichtete) Kante von Knoten "i" nach Knoten "j" existiert, dann wird das Element in der Matrix mit den Koordinaten "
Falls die Kanten ungerichtet sind, ist die resultierende Matrix symmetrisch, d.h. die Elemente "
Diese Matrix (die die Kanten des Graphen repräsentiert) kann dabei nur die Frage beantworten, ob es zwischen je zwei Knoten des Graphen eine KANTE gibt, während die reflexive transitive Hülle die Frage beantwortet, ob es einen PFAD (eine Folge zusammenhängender, aufeinanderfolgender Kanten) zwischen diesen beiden Knoten des Graphen gibt!
BEACHTEN SIE, daß der Inhalt der gegebenen Matrix durch diese Methode verändert wird! Machen Sie also rechtzeitig eine Kopie der ursprünglichen Matrix, wenn Sie diese später noch benötigen!
Eine Ausnahme wird ausgelöst, falls die gegebene Matrix nicht quadratisch ist, d.h. wenn die Anzahl der Zeilen nicht mit der Anzahl der Spalten der Matrix übereinstimmt.
Eine Ausnahme wird ebenfalls ausgelöst, wenn das Produkt aus der Anzahl der Zeilen und Spalten der gegebenen Matrix von der tatsächlichen Größe des zugrundeliegenden Bitvektors abweicht.
Diese Methode wird vom Modul "Math::MatrixBool" verwendet.
Nähere Details zu dieser Methode finden Sie in Math::MatrixBool(3).
Diese Methode berechnet die Transponierte einer (als Bitvektor gespeicherten) booleschen Matrix "
Die Transponierte einer booleschen Matrix (welche die Kanten eines Graphen repräsentiert) kann dazu verwendet werden, um die stark verbundenen Komponenten des Graphen zu finden.
Eine Ausnahme wird ausgelöst, wenn das Produkt aus Zeilen- und Spaltenanzahl einer der beiden Matrizen nicht mit der Größe des jeweils zugrundeliegenden Bitvektors übereinstimmt.
Eine Ausnahme wird ebenfalls ausgelöst, wenn eine der folgenden Bedingungen nicht erfüllt ist:
Beachten Sie, daß eine Verarbeitung "auf derselben Stelle" ("
Diese Methode wird vom Modul "Math::MatrixBool" verwendet.
Nähere Details zu dieser Methode finden Sie in Math::MatrixBool(3).
Interval_Copy()
", "Insert()
" und "Delete()
") die Länge des resultierenden Bitvektors IMPLIZIT und AUTOMATISCH wie folgt verändert:
$size = $vec2->Size(); # vorher
$size += $len1 - $len2; # nachher
Resize()
".)
$len2 == 0
") und das Löschen eines Bit-Intervalls aus ("$len1 == 0
") dem Ziel-Bitvektor.
:-)
) und Einheitlichkeit kann das sogar zu einem Bitvektor der Länge Null führen (also zu einem Bitvektor, der wirklich keinerlei Bits mehr enthält, also nicht etwa nur auf Null gesetzte Bits!).
$vec1
" und "$vec2
" identisch sein können, d.h. eine Verarbeitung "auf derselben Stelle" ist möglich.
if ($vector->is_empty())
0
") ist.
1
") zurück, wenn der Bitvektor leer ist, anderenfalls wird "falsch" ("0
") zurückgegeben.
1
") zurückgibt, wenn der Bitvektor die Länge Null hat (also überhaupt keine Bits enthält).
if ($vector->is_full())
-1
" ist.
1
") zurück, wenn der Bitvektor voll ist, anderenfalls wird "falsch" ("0
") zurückgegeben.
0
") zurück.
if ($vec1->equal($vec2))
1
") zurück, wenn die beiden Bitvektoren identische Kopien voneinander sind, anderenfalls wird "falsch" ("0
") zurückgegeben.
$cmp = $vec1->Lexicompare($vec2);
-1
" zurück, wenn der erste Bitvektor kleiner ist als der zweite, "0
", falls die beiden Bitvektoren identische Kopien voneinander sind und "1
", wenn der erste Bitvektor größer ist als der zweite.
$cmp = $vec1->Compare($vec2);
-1
" zurück, wenn der erste Bitvektor kleiner ist als der zweite, "0
", falls die beiden Bitvektoren identische Kopien voneinander sind und "1
", wenn der erste Bitvektor größer ist als der zweite.
$string = $vector->to_Hex();
$vector->from_Hex($string);
to_Hex()
" (siehe oben) zurückgegeben wird.
$string = $vector->to_Bin();
$vector = Bit::Vector->new(8);
$vector->Primes();
$string = $vector->to_Bin();
print "'$string'\n";
'10101100'
$vector->from_Bin($string);
to_Bin()
" (siehe oben) zurückgegeben wird.
0
" oder "1
") als zum vollständigen Füllen des gegebenen Bitvektors notwendig sind, werden die übrigen (höchstwertigen) Bits des Bitvektors alle gelöscht.
0
" oder "1
" ist, hat das einen fatalen Syntaxfehler ("input string syntax error") mit Programmabbruch zur Folge.
$string = $vector->to_Dec();
10
) enthält.
from_Dec()
" (siehe unten) übergeben werden, um z.B. den Inhalt dieses Bitvektors in einen anderen zu kopieren (oder um den Inhalt eines Bitvektors wiederherzustellen). Von diesem Vorgehen wird aber dringend abgeraten, weil das extrem ineffizient ist (dieses Modul bietet wesentlich effizientere Methoden zum Abspeichern, Kopieren und Wiedereinlesen von Bitvektoren an!).
10
(mit Rest) geteilt werden muß, bis der Quotient Null ergibt (jeder Rest stellt dabei nur eine einzige Dezimalziffer des resultierenden Strings dar!). Mit anderen Worten, für JEDE Dezimalziffer des Ergebnisses muß der ganze Bitvektor einmal durch 10
dividiert werden!
10
zu teilen, wird der Bitvektor laufend durch die höchste 10
er-Potenz dividiert, die noch in ein Maschinenwort hineinpaßt. Der Rest dieser Division wird dann wiederholt durch 10
geteilt, wobei nur noch Maschinenwort-Arithmetik eingesetzt zu werden braucht, was natürlich wesentlich günstiger ist, als den GESAMTEN Bitvektor durch 10
zu teilen (Prinzip "Teile und Herrsche"!).
output=decimal
" setzen, diese Methode für jeden in Anführungszeichen stehenden Bitvektor ausgeführt wird!
$vector->from_Dec($string);
0..9
" sowie ggfs. ein führendes Vorzeichen ("+
" oder "-
"), so führt dies zu einem fatalen Syntaxfehler ("input string syntax error").
eval
" wie folgt einsetzen, um diesen Fehler abzufangen:
eval { $vector->from_Dec("1152921504606846976"); };
if ($@)
{
# Fehlerbehandlung
}
if ($@ =~ /item is not a string/)
if ($@ =~ /input string syntax error/)
if ($@ =~ /numeric overflow error/)
if ($@ =~ /unable to allocate memory/)
10
er-Potenz multipliziert werden, die der Position dieser Dezimalziffer in der Dezimalzahl (also ihrem Wert) entspricht, also 1, 10, 100, 1000, 10000 usw.)
to_Dec()
") wird jedoch zur Steigerung der Effizienz das Prinzip "Teile und Herrsche" angewandt: Es werden zuerst soviele Dezimalstellen in einem Maschinenwort akkumuliert wie möglich, bevor dieses Maschinenwort mit einer geeigneten 10
er-Potenz multipliziert und zum gegebenen Bitvektor hinzuaddiert wird (dieser wird natürlich anfangs mit Null initialisiert).
input=decimal
" setzen, diese Methode auf jeden skalaren Operanden angewendet wird!
$string = $vector->to_Enum();
1
") gesetzten Bits des Bitvektors enthält.
$vector = Bit::Vector->new(20);
$vector->Bit_On(2);
$vector->Bit_On(3);
$vector->Bit_On(11);
$vector->Interval_Fill(5,7);
$vector->Interval_Fill(13,19);
print "'", $vector->to_Enum(), "'\n";
'2,3,5-7,11,13-19'
Bit::Vector->Configuration("out=enum");
$vector = Bit::Vector->new(20);
$vector->Index_List_Store(2,3,5,6,7,11,13,14,15,16,17,18,19);
print "'$vector'\n";
$vector->from_Enum($string);
1
".
$string
" darf dabei nur positive ganze Zahlen oder Bereichsangaben (zwei durch "-" miteinander verbundene, positive ganze Zahlen) enthalten, die durch Kommata (",") jeweils voneinander getrennt sind.
0
" und "$vector->Size()-1
".
eval
" wie folgt einsetzen, um diesen Fehler abzufangen:
eval { $vector->from_Enum("2,3,5-7,11,13-19"); };
if ($@)
{
# Fehlerbehandlung
}
if ($@ =~ /item is not a string/)
if ($@ =~ /input string syntax error/)
if ($@ =~ /index out of range/)
if ($@ =~ /minimum > maximum index/)
eval { $vector->from_Enum("11,5-7,3,13-19,2"); };
Bit_On()
" übergeben wird und jede Bereichsangabe an die Methode "Interval_Fill()
".
$vector->Bit_Off($index);
$index
" im gegebenen Bitvektor.
$vector->Bit_On($index);
$index
" im gegebenen Bitvektor.
$vector->bit_flip($index)
$index
" im gegebenen Bitvektor.
0
" zurück, wenn das Bit gelöscht ist, und "1
" wenn es gesetzt ist (beides NACHDEM das Bit komplementiert wurde).
if ($vector->bit_test($index))
,
if ($vector->contains($index))
$index
" im gegebenen Bitvektor, d.h. gibt "0
" zurück, wenn es gelöscht ("aus"), bzw. "1
", wenn es gesetzt ("an") ist.
$vector->Bit_Copy($index,$bit);
$index
" im gegebenen Bitvektor auf den (booleschen) Wert "$bit
".
$vector->LSB($bit);
$bit
".
$vector->Bit_Copy(0,$bit);
".
$vector->MSB($bit);
$bit
".
$vector->Bit_Copy($vector->Size()-1,$bit);
".
$bit = $vector->lsb();
$bit = $vector->bit_test(0);
".
$bit = $vector->msb();
$bit = $vector->bit_test($vector->Size()-1);
".
$carry_out = $vector->rotate_left();
carry MSB vector: LSB
out:
+---+ +---+---+---+--- ---+---+---+---+
| | <---+--- | | | | ... | | | | <---+
+---+ | +---+---+---+--- ---+---+---+---+ |
| |
+------------------------------------------------+
0
", das höchstwertige Bit (MSB) ist das Bit mit der Nummer "$vector->Size()-1
".
$carry_out = $vector->rotate_right();
MSB vector: LSB carry
out:
+---+---+---+--- ---+---+---+---+ +---+
+---> | | | | ... | | | | ---+---> | |
| +---+---+---+--- ---+---+---+---+ | +---+
| |
+------------------------------------------------+
0
", das höchstwertige Bit (MSB) ist das Bit mit der Nummer "$vector->Size()-1
".
$carry_out = $vector->shift_left($carry_in);
carry MSB vector: LSB carry
out: in:
+---+ +---+---+---+--- ---+---+---+---+ +---+
| | <--- | | | | ... | | | | <--- | |
+---+ +---+---+---+--- ---+---+---+---+ +---+
0
", das höchstwertige Bit (MSB) ist das Bit mit der Nummer "$vector->Size()-1
".
$carry_out = $vector->shift_right($carry_in);
carry MSB vector: LSB carry
in: out:
+---+ +---+---+---+--- ---+---+---+---+ +---+
| | ---> | | | | ... | | | | ---> | |
+---+ +---+---+---+--- ---+---+---+---+ +---+
0
", das höchstwertige Bit (MSB) ist das Bit mit der Nummer "$vector->Size()-1
".
$vector->Move_Left($bits);
$bits
" Bits nach links, d.h. fügt "$bits
" neue Bits am unteren Ende (LSB) des Bitvektors ein, bewegt alle anderen Bits um "$bits
" Positionen nach oben, wodurch die "$bits
" höchstwertigen Bits verlorengehen.
$bits
" Null ist.
$bits
" größer oder gleich der Größe des Bitvektors ist!
for ( $i = 0; $i < $bits; $i++ ) { $vector->shift_left(0); }
$bits
", die größer oder gleich der Anzahl von Bits in einem Maschinenwort ist - wesentlich effizienter als dieser naive Ansatz.
$vector->Move_Right($bits);
$bits
" Bits nach rechts, d.h. löscht die "$bits
" niederwertigsten Bits des Bitvektors, bewegt alle anderen Bits um "$bits
" Positionen nach unten und erzeugt somit "$bits
" neue Bits am oberen Ende (MSB) des Bitvektors.
$bits
" Null ist.
$bits
" größer oder gleich der Größe des Bitvektors ist!
for ( $i = 0; $i < $bits; $i++ ) { $vector->shift_right(0); }
$bits
", die größer oder gleich der Anzahl von Bits in einem Maschinenwort ist - wesentlich effizienter als dieser naive Ansatz.
$vector->Insert($offset,$bits);
$bits
" neue Bits an der Position "$offset
" in den gegebenen Bitvektor ein.
$bits
" höchstwertigen Bits gehen dabei verloren, und alle Bits von Bit Nummer "$offset
" bis einschließlich Bit Nummer "$vector->Size()-$bits-1
" werden um "$bits
" Positionen nach oben verschoben.
$bits
" Bits von Bit Nummer "$offset
" bis einschließlich Bit Nummer "$offset+$bits-1
" werden anschließend auf Null gesetzt (gelöscht).
$bits
" höchstwertigen Bits zu "retten" - vielmehr gehen diese Bits für immer verloren.
$vector->Resize($vector->Size() + $bits);
Insert()
" die Methode "Interval_Substitute()
" verwenden. Diese nimmt eine automatische Vergrößerung (bzw. Verkleinerung) des Ziel-Bitvektors vor.
$offset
" im erlaubten Bereich zwischen "0
" und "$vector->Size()-1
" liegen muß, sonst kommt es zu einem fatalen Offset-Fehler ("offset out of range").
$offset + $bits
" größer als "$vector->Size()-1
", werden einfach nur alle Bits von Bit Nummer "$offset
" bis zu Bit Nummer "$vector->Size()-1
" gelöscht (d.h. auf Null gesetzt).
$vector->Delete($offset,$bits);
$offset
" bis einschließlich Bit Nummer "$offset+$bits-1
".
$offset+$bits
" bis einschließlich Bit Nummer "$vector->Size()-1
" werden dabei um "$bits
" Positionen nach unten verschoben (rücken also nach).
$bits
" höchstwertigen Bits werden anschließend auf Null gesetzt (gelöscht).
$bits
" höchstwertigen Bits "loszuwerden".
$size = $vector->Size();
if ($bits > $size) { $bits = $size; }
$vector->Resize($size - $bits);
Delete()
" die Methode "Interval_Substitute()
" verwenden. Diese nimmt eine automatische Verkleinerung (bzw. Vergrößerung) des Ziel-Bitvektors vor.
$offset
" im erlaubten Bereich zwischen "0
" und "$vector->Size()-1
" liegen muß, sonst kommt es zu einem fatalen Offset-Fehler ("offset out of range").
$offset + $bits
" größer als "$vector->Size()-1
", werden einfach nur alle Bits von Bit Nummer "$offset
" bis zu Bit Nummer "$vector->Size()-1
" gelöscht (d.h. auf Null gesetzt).
$carry = $vector->increment();
vorher: 2 ^ (b-1) - 1 (= "0111...1111")
nachher: 2 ^ (b-1) (= "1000...0000")
b
" für die Anzahl der Bits des gegebenen Bitvektors.)
0
") zurück, außer bei einem Übertrag, der beim Inkrementieren von "1111...1111" auftritt (was "0000...0000" plus den Übertrag ergibt); in diesem Fall wird statt dessen "wahr" ("1
") zurückgegeben.
$carry = $vector->decrement();
vorher: 2 ^ (b-1) (= "1000...0000")
nachher: 2 ^ (b-1) - 1 (= "0111...1111")
b
" für die Anzahl der Bits des gegebenen Bitvektors.)
0
") zurück, außer bei einem Übertrag, der beim Dekrementieren von "0000...0000" auftritt (was "1111...1111" sowie den Übertrag ergibt); in diesem Fall wird statt dessen "wahr" ("1
") zurückgegeben.
$carry = $vec3->add($vec1,$vec2,$carry);
$vec1
" und "$vec2
", unter Berücksichtigung des Übertrags "$carry
", legt das Ergebnis im Bitvektor "$vec3
" ab und liefert einen neuen Übertrag als Rückgabewert.
$vec3 = $vec1 + $vec2 + $carry
$carry
" ein boolescher Wert ist, d.h. nur das niederwertigste Bit davon wird berücksichtigt (alle anderen Bits werden intern mit Hilfe von "$carry &= 1;
" abgeschnitten).
# Initialisierung
for ( $i = 0; $i < $n; $i++ )
{
$a[$i] = Bit::Vector->new($bits);
$b[$i] = Bit::Vector->new($bits);
$c[$i] = Bit::Vector->new($bits);
}
# Fülle @a und @b
# $a[ 0 ] ist niederwertigster Teil,
# $a[$n-1] ist höchstwertiger Teil.
# Das gleiche gilt für @b
# Addiere
$carry = 0;
for ( $i = 0; $i < $n; $i++ )
{
$carry = $c[$i]->add($a[$i],$b[$i],$carry);
}
$vec1
" und "$vec2
") vorzeichenbehaftet sind oder vorzeichenlos, da sie intern mittels des Zweierkomplements dargestellt werden und die Addition dadurch automatisch für beide Arten von Zahlen korrekt ist.
$msb1 = $vec1->msb();
$msb2 = $vec2->msb();
$vec1->Resize($vec1->Size()+1);
$vec2->Resize($vec2->Size()+1);
$vec3->Resize($vec3->Size()+1);
$vec1->MSB($msb1);
$vec2->MSB($msb2);
$c_o = $vec3->add($vec1,$vec2,$c_i);
$carry = $vec3->subtract($vec1,$vec2,$carry);
$vec1
" und "$vec2
", unter Berücksichtigung des Übertrags "$carry
", legt das Ergebnis im Bitvektor "$vec3
" ab und liefert einen neuen Übertrag als Rückgabewert.
$vec3 = $vec1 - $vec2 - $carry
$carry
" ein boolescher Wert ist, d.h. nur das niederwertigste Bit davon wird berücksichtigt (alle anderen Bits werden intern mit Hilfe von "$carry &= 1;
" abgeschnitten).
1
"), wenn von der nächsthöheren Bit-Position "geborgt" wurde, ansonsten "falsch" ("0
").
# Initialisierung
for ( $i = 0; $i < $n; $i++ )
{
$a[$i] = Bit::Vector->new($bits);
$b[$i] = Bit::Vector->new($bits);
$c[$i] = Bit::Vector->new($bits);
}
# Fülle @a und @b
# $a[ 0 ] ist niederwertigster Teil,
# $a[$n-1] ist höchstwertiger Teil.
# Das gleiche gilt für @b
# Subtrahiere
$carry = 0;
for ( $i = 0; $i < $n; $i++ )
{
$carry = $c[$i]->subtract($a[$i],$b[$i],$carry);
}
$vec1
" und "$vec2
") vorzeichenbehaftet sind oder vorzeichenlos, da sie intern mittels des Zweierkomplements dargestellt werden und die Subtraktion dadurch automatisch für beide Arten von Zahlen korrekt ist.
$msb1 = $vec1->msb();
$msb2 = $vec2->msb();
$vec1->Resize($vec1->Size()+1);
$vec2->Resize($vec2->Size()+1);
$vec3->Resize($vec3->Size()+1);
$vec1->MSB($msb1);
$vec2->MSB($msb2);
$c_o = $vec3->subtract($vec1,$vec2,$c_i);
$vec2->Negate($vec1);
$vec1
" und legt das Ergebnis in Bitvektor "$vec2
" ab.
$vec1
" und "$vec2
" können identisch sein.
+
" nach "-
" oder umgekehrt. Die zweimalige Anwendung dieser Operation liefert also wieder die ursprüngliche Zahl.
2 ^ (n-1)
" (also "1000...0000") hat (wobei "n
" hier die Anzahl der Bits im gegebenen Bitvektor angibt): Der negative Wert dieser Zahl ist diese Zahl selbst!
$vec2->Absolute($vec1);
$vec1
" wird der Inhalt von Bitvektor "$vec1
" entweder mit der Methode "Copy()
" (wenn die Zahl in Bitvektor "$vec1
" positiv ist), oder mit "Negate()
" (wenn die Zahl in Bitvektor "$vec1
" negativ ist) in den Bitvektor "$vec2
" kopiert.
$vec1
" und "$vec2
" können identisch sein.
$vec1
" und speichert das Ergebnis in Bitvektor "$vec2
".
2 ^ (n-1)
" (also "1000...0000") hat (wobei "n
" hier die Anzahl der Bits im gegebenen Bitvektor angibt): Der Absolutwert dieser Zahl ist diese Zahl selbst, obwohl diese Zahl nach dieser Operation per Definition immer noch negativ ist (das höchstwertige Bit ist ja nach wie vor gesetzt)!
$sign = $vector->Sign();
0
") zurück, wenn ALLE Bits des gegebenen Bitvektors gelöscht (d.h. auf Null gesetzt) sind, oder mit anderen Worten, wenn der gegebene Bitvektor die ZAHL Null ("0
") enthält. Dieser Wert wird auch dann zurückgegeben, wenn der Bitvektor die LÄNGE Null hat (also GAR KEINE Bits enthält).
-1
" zurück, falls das höchstwertige Bit gesetzt ist (d.h. wenn der Bitvektor eine negative Zahl enthält), oder den Wert "1
", falls der Bitvektor eine positive Zahl enthält.
$vec3->Multiply($vec1,$vec2);
$vec1
" und "$vec2
" und speichert das Ergebnis in Bitvektor "$vec3
".
$msb1 = $vec1->msb();
$msb2 = $vec2->msb();
$vec1->Resize($vec1->Size()+1);
$vec2->Resize($vec2->Size()+1);
$vec3->Resize($vec3->Size()+1);
$vec1->MSB($msb1);
$vec2->MSB($msb2);
$vec3->Multiply($vec1,$vec2);
$vec3
" zur Aufnahme des Ergebnisses ausnahmsweise auch größer sein darf als die beiden Faktoren "$vec1
" und "$vec2
"!
n
" Bits ein Ergebnis liefern, das bis zu "2n
" Bits lang ist.
$vec3
" doppelt so groß zu machen wie die beiden Bitvektoren "$vec1
" und "$vec2
", es sei denn Sie sind absolut sicher, daß das Ergebnis in einen Bitvektor paßt, der die gleiche Größe hat wie die Bitvektoren der beiden Faktoren.
$vec3
" kann mit "$vec1
" oder "$vec2
" (oder beiden) identisch sein.
$quot->Divide($vec1,$vec2,$rest);
$vec1
" und "$vec2
". Der Quotient dieser Division wird dabei in Bitvektor "$quot
" abgelegt und der Rest in Bitvektor "$rest
".
$quot = $vec1 / $vec2; # Division
$rest = $vec1 % $vec2; # Modulo
$quot
" und "$rest
" UNBEDINGT zwei UNTERSCHIEDLICHE Bitvektoren sein, sonst kommt es zu einem fatalen Fehler ("Q and R must be distinct")!
$vec2
" den Wert Null hat.
$msb1 = $vec1->msb();
$msb2 = $vec2->msb();
$vec1->Resize($vec1->Size()+1);
$vec2->Resize($vec2->Size()+1);
$quot->Resize($quot->Size()+1);
$rest->Resize($rest->Size()+1);
$vec1->MSB($msb1);
$vec2->MSB($msb2);
$quot->Divide($vec1,$vec2,$rest);
$quot
" kann identisch sein mit "$vec1
" oder "$vec2
" (oder beiden), und "$rest
" kann ebenfalls mit "$vec1
" oder "$vec2
" (oder beiden) identisch sein, solange "$quot
" und "$rest
" verschieden sind(!).
$vec3->GCD($vec1,$vec2);
$vec1
" und "$vec2
" und legt das Ergebnis in Bitvektor "$vec3
" ab.
int GCD(int a, int b)
{
int t;
while (b != 0)
{
t = a % b; /* = Rest von (a div b) */
a = b;
b = t;
}
return(a);
}
$vector->Block_Store($buffer);
Block_Read()
") und später wieder einzulesen.
$buffer
" hier UNBEDINGT ein STRING sein MUSS - anderenfalls tritt ein fataler "Ist kein String"-Fehler ("item is not a string") auf!
$buffer
" aus einer Datei einlesen können, können Sie im Abschnitt zu "read()
" bzw. "sysread()
" in perlfunc(1) nachlesen.
$buffer = $vector->Block_Read();
Block_Store()
").
syswrite()
" in perlfunc(1) nachlesen.
$size = $vector->Word_Size();
:-)
Chunk_
" beginnen, und dabei keine Chunk-Größen von mehr als 32 Bit verwenden.
Word_Size()
" gibt die Anzahl der Maschinenworte zurück, die das interne Array des gegebenen Bitvektors enthält.
scalar(@array)
" für ein Perl-Array.
$vector->Word_Store($offset,$word);
$word
" an einer gegebenen Position "$offset
" im internen Wort-Array des gegebenen Bitvektors zu speichern.
$offset
" innerhalb des gültigen Bereichs von "0
" bis "$vector->Word_Size()-1
" liegen muß, anderenfalls kommt es zu einem fatalen Offset-Fehler ("offset out of range").
$array[$offset] = $word;
" für ein Perl-Array.
$word = $vector->Word_Read($offset);
$offset
" im internen Wort-Array des gegebenen Bitvektors.
$offset
" innerhalb des gültigen Bereichs von "0
" bis "$vector->Word_Size()-1
" liegen muß, anderenfalls kommt es zu einem fatalen Offset-Fehler ("offset out of range").
$word = $array[$offset];
" für ein Perl-Array.
$vector->Word_List_Store(@words);
@words
" im internen Wort-Array des gegebenen Bitvektors abzuspeichern.
$words[0]
") im NIEDERWERTIGSTEN Wort des internen Wort-Arrays (also in dem Wort mit dem Offset "0
") gespeichert. Der nächste Wert der Liste ("$words[1]
") wird dann im Wort mit dem Offset "1
" abgelegt, usw. usf.
@words
" weniger Elemente umfaßt, als das interne Wort-Array des gegebenen Bitvektors Maschinenworte enthält, werden die restlichen (höchstwertigen) Maschinenworte mit Nullen aufgefüllt.
@words
" mehr Elemente besitzt, als das interne Wort-Array des gegebenen Bitvektors Maschinenworte enthält, werden die überschüssigen Werte einfach ignoriert.
@array = @words;
" für ein Perl-Array.
@words = $vector->Word_List_Read();
$words[0]
") das NIEDERWERTIGSTE Wort und der GANZ RECHTS stehende Wert ("$words[$#words]
") das HÖCHSTWERTIGE Wort des gegebenen Bitvektors.
@words = @array;
" für ein Perl-Array.
$vector->Word_Insert($offset,$count);
$count
" neue, leere Maschinenworte an der Position "$offset
" in das interne Array des gegebenen Bitvektors ein.
$count
" höchstwertigen Maschinenworte gehen dabei verloren, und alle Maschinenworte von Wort Nummer "$offset
" bis einschließlich Wort Nummer "$vector->Word_Size()-$count-1
" werden um "$count
" Positionen nach oben verschoben.
$count
" Maschinenworte von Wort Nummer "$offset
" bis einschließlich Wort Nummer "$offset+$count-1
" werden anschließend auf Null gesetzt (gelöscht).
$count
" höchstwertigen Maschinenworte zu "retten" - vielmehr gehen diese Maschinenworte für immer verloren.
$vector->Resize($vector->Size() + $count * Bit::Vector->Word_Bits());
$offset
" im erlaubten Bereich zwischen "0
" und "$vector->Word_Size()-1
" liegen muß, sonst kommt es zu einem fatalen Offset-Fehler ("offset out of range").
$offset + $count
" größer als "$vector->Word_Size()-1
", werden einfach nur alle Maschinenworte von Wort Nummer "$offset
" bis zu Wort Nummer "$vector->Word_Size()-1
" gelöscht (d.h. auf Null gesetzt).
$vector->Word_Delete($offset,$count);
$offset
" bis einschließlich Wort Nummer "$offset+$count-1
".
$offset+$count
" bis einschließlich Wort Nummer "$vector->Word_Size()-1
" werden dabei um "$count
" Positionen nach unten verschoben (rücken also nach).
$count
" höchstwertigen Maschinenworte werden anschließend auf Null gesetzt (gelöscht).
$count
" höchstwertigen Maschinenworte "loszuwerden".
$bits = $vector->Size();
$count *= Bit::Vector->Word_Bits();
if ($count > $bits) { $count = $bits; }
$vector->Resize($bits - $count);
$offset
" im erlaubten Bereich zwischen "0
" und "$vector->Word_Size()-1
" liegen muß, sonst kommt es zu einem fatalen Offset-Fehler ("offset out of range").
$offset + $count
" größer als "$vector->Word_Size()-1
", werden einfach nur alle Maschinenworte von Wort Nummer "$offset
" bis zu Wort Nummer "$vector->Word_Size()-1
" gelöscht (d.h. auf Null gesetzt).
$vector->Chunk_Store($chunksize,$offset,$chunk);
Interval_Empty()
" und "Interval_Fill()
", die nur das gleichzeitige Setzen von nebeneinanderliegenden Bits auf DENSELBEN Wert gestatten).
Bit::Vector->Long_Bits()
" Bits auf einmal zugreifen.
$chunksize
" nicht zwischen "1
" und "Bit::Vector->Long_Bits()
", kommt es zu einem fatalen Bereichsfehler ("chunk size out of range").
$chunksize
" niederwertigsten Bits aus "$chunk
" in den gegebenen Bitvektor, beginnend bei Bit-Position "$offset
" und weiter bis Bit Nummer "$offset+$chunksize-1
".
0
" von "$chunk
" zu Bit Nummer "$offset
" im gegebenen Bitvektor wird, und so weiter bis Bit Nummer "$chunksize-1
", welches zu Bit Nummer "$offset+$chunksize-1
" des Bitvektors wird. Die genannten Bits des Bitvektors werden also durch diese Operation überschrieben.)
$offset+$chunksize-1
" größer als "$vector->Size()-1
", werden die überschüssigen (höchstwertigen) Bits aus "$chunk
" einfach ignoriert.
$offset
" selbst innerhalb des erlaubten Bereichs von "0
" bis "$vector->Size()-1
" liegen muß, sonst kommt es zu einem fatalen Offset-Fehler ("offset out of range").
Chunk_
"-Methoden sind nützlich, wenn Sie beispielsweise Daten in Blöcken von z.B. 8 Bits einlesen wollen, auf die Sie später in Blöcken von (beispielsweise) 16 Bit gleichzeitig zugreifen müssen (wie etwa bei Audio-CD Wave-Dateien).
$chunk = $vector->Chunk_Read($chunksize,$offset);
Bit::Vector->Long_Bits()
" Bits auf einmal zugreifen.
$chunksize
" nicht zwischen "1
" und "Bit::Vector->Long_Bits()
", kommt es zu einem fatalen Bereichsfehler ("chunk size out of range").
$chunksize
" Bits beginnend bei Bit-Position "$offset
" und weiter bis Bit Nummer "$offset+$chunksize-1
" zurück.
$offset
" des gegebenen Bitvektors zu Bit Nummer "0
" des Rückgabewertes wird, und so weiter bis Bit Nummer "$offset+$chunksize-1
", welches zu Bit Nummer "$chunksize-1
" des Ergebnisses wird.)
$offset+$chunksize-1
" größer als "$vector->Size()-1
", werden die entsprechenden, nicht existierenden Bits natürlich nicht zurückgegeben, und die entsprechenden Bits des Rückgabewertes bleiben leer.
$offset
" selbst innerhalb des erlaubten Bereichs von "0
" bis "$vector->Size()-1
" liegen muß, sonst kommt es zu einem fatalen Offset-Fehler ("offset out of range").
$vector->Chunk_List_Store($chunksize,@chunks);
$chunksize
" (innerhalb bestimmter Grenzen) zu füllen.
$chunksize
" innerhalb des Bereichs zwischen "1
" und "Bit::Vector->Long_Bits()
" liegen, sonst kommt es zu einem fatalen Bereichsfehler ("chunk size out of range").
$chunks[0]
") füllt die "$chunksize
" niederwertigsten Bits des gegebenen Bitvektors, das nächste Bit-Paket aus der Liste ("$chunks[1]
") füllt die Bits von Nummer "$chunksize
" bis Nummer "2*$chunksize-1
", das dritte Bit-Paket ("$chunks[2]
") füllt die Bits von Nummer "2*$chunksize
" bis Nummer "3*$chunksize-1
", usw. usf.
$vector->Size()-1
" hinaus (was immer dann passiert, wenn "$vector->Size()
" kein ganzzahliges Vielfaches von "$chunksize
" ist), dann werden die überzähligen Chunks bzw. Bits einfach ignoriert.
$vector->Chunk_List_Store(3, split(//, reverse $string));
from_Hex()
", "from_Bin()
", "from_Dec()
" und "from_Enum()
" keinerlei Syntaxprüfung stattfindet, d.h. daß die obige Anweisung ohne Warnung fehlschlagen kann.
if ($string =~ /^[0-7]+$/)
{
# Okay, Konvertierung wie oben beschrieben durchführen
}
else
{
# Fehler, String enthält nichtoktale Zeichen
}
$pattern = 0xDEADBEEF;
$length = 32; # = Länge des Musters "$pattern" in Bits
$size = $vector->Size();
$factor = int($size / $length);
if ($size % $length) { $factor++; }
$vector->Chunk_List_Store($length, ($pattern) x $factor);
@chunks = $vector->Chunk_List_Read($chunksize);
$chunksize
".
$chunksize
" innerhalb des Bereichs zwischen "1
" und "Bit::Vector->Long_Bits()
" liegen, sonst kommt es zu einem fatalen Bereichsfehler ("chunk size out of range").
$chunksize
" niederwertigsten Bits des Bitvektors (Bits Nummer "0
" bis Nummer "$chunksize-1
") werden zum ersten Bit-Paket der zurückgelieferten Liste (also "$chunks[0]
"). Die Bits von Nummer "$chunksize
" an bis "2*$chunksize-1
" bilden das nächste Bit-Paket der Liste ("$chunks[1]
"), usw. usf.
$vector->Size()
" kein ganzzahliges Vielfaches von "$chunksize
" ist, enthält das letzte Bit-Paket der Liste entsprechend weniger Bits als "$chunksize
".
$chunksize
" die Anzahl der zurückgelieferten Listenelemente unter Umständen extrem hoch sein kann! VORSICHT!
$string = reverse join('', $vector->Chunk_List_Read(3));
$vector->Index_List_Remove(@indices);
foreach $index (@indices)
{
$vector->Bit_Off($index);
}
Index_List_Store()
". Sie können deshalb damit alle mit "Index_List_Remove()
" durchgeführten Änderungen wieder rückgängig machen, indem Sie die gleiche Liste von Argumenten an "Index_List_Store()
" übergeben.)
$vector->Index_List_Store(@indices);
foreach $index (@indices)
{
$vector->Bit_On($index);
}
Index_List_Remove()
". Sie können deshalb damit alle mit "Index_List_Store()
" durchgeführten Änderungen wieder rückgängig machen, indem Sie die gleiche Liste von Argumenten an "Index_List_Remove()
" übergeben.)
@indices = $vector->Index_List_Read();
$limit = 1000; # oder was auch immer.
$vector = Bit::Vector->new($limit+1);
$vector->Primes();
@primes = $vector->Index_List_Read();
$set3->Union($set1,$set2);
$set1
" und "$set2
" und legt das Ergebnis in "$set3
" ab.
$set3 = $set1 u $set2
".
$set3
" kann mit "$set1
" oder "$set2
" identisch sein (oder beiden).
$set3->Intersection($set1,$set2);
$set1
" und "$set2
" und legt das Ergebnis in "$set3
" ab.
$set3 = $set1 n $set2
".
$set3
" kann mit "$set1
" oder "$set2
" identisch sein (oder beiden).
$set3->Difference($set1,$set2);
$set1
" ohne "$set2
" und legt das Ergebnis in "$set3
" ab.
$set3 = $set1 \ $set2
".
$set3
" kann mit "$set1
" oder "$set2
" identisch sein (oder beiden).
$set3->ExclusiveOr($set1,$set2);
$set1
" und "$set2
" und legt der Ergebnis in "$set3
" ab.
$set3 = ($set1 u $set2) \ ($set1 n $set2)
" geschrieben werden (die Vereinigungsmenge beider Mengen ohne deren Durchschnitt).
$set3
" kann mit "$set1
" oder "$set2
" identisch sein (oder beiden).
$set2->Complement($set1);
$set1
" und legt der Ergebnis in "$set2
" ab.
$set1
" in Binärdarstellung gespeicherten Zahl.
$set2
" kann mit "$set1
" identisch sein.
if ($set1->subset($set2))
1
") zurück, wenn "$set1
" eine Teilmenge von "$set2
" ist (d.h. in "$set2
" vollständig enthalten ist), und "falsch" ("0
") sonst.
$set1
" gesetzte Bit auch in "$set2
" gesetzt sein muß, damit die Bedingung erfüllt ist, während "$set2
" gesetzte Bits enthalten kann, die in "$set1
" nicht gesetzt sind.
$norm = $set->Norm();
$min = $set->Min();
$set
".
n
" die Anzahl der Bits ist, die der C-Datentyp "unsigned long" auf Ihrem System hat.)
$max = $set->Max();
$set
".
n
" die Anzahl der Bits ist, die der C-Datentyp "unsigned long" auf Ihrem System hat.)
$m3->Multiplication($r3,$c3,$m1,$r1,$c1,$m2,$r2,$c2);
$m1
" und "$m2
" und legt das Ergebnis in der Matrix "$m3
" ab.
rows3 == rows1 # "rows" = "Zeilen"
cols3 == cols2 # "cols" ("colums") = "Spalten"
cols1 == rows2
$matrix->Closure($rows,$cols);
(i,j)
" auf "1
" gesetzt, anderenfalls bleibt es "0
".
(i,j)
" und "(j,i)
" enthalten immer denselben Wert.
$matrix2->Transpose($rows2,$cols2,$matrix1,$rows1,$cols1);
$matrix1
" und legt das Ergebnis im Bitvektor "$matrix2
" ab.
rows2 == cols1 # "rows" = "Zeilen"
cols2 == rows1 # "cols" ("colums") = "Spalten"
$matrix1
" und "$matrix2
" sind identisch) nur möglich ist, falls die Matrix quadratisch ist. Anderenfalls kommt es zu einem fatalen Matrixfehler ("matrix is not quadratic").
$config = Bit::Vector->Configuration();
Bit::Vector->Configuration($config);
$oldconfig = Bit::Vector->Configuration($newconfig);
Diese Methode dient der Änderung der Semantik (d.h. des Verhaltens) bestimmter überladener Operatoren (die übrigens alle in Perl implementiert sind).
Diese Methode hat keinen wie auch immer gearteten Einfluß auf irgendwelche anderen Dinge. Insbesondere hat sie keinerlei Einfluß auf die in C implementierten Methoden.
Die Methode erlaubt einen (optionalen) String als Eingabe, in dem bestimmte Schlüsselworte erwartet werden. Diese Schlüsselworte beeinflussen mehrere Aspekte der überladenen Operatoren und betreffen teils nur einige, teils fast alle überladenen Operatoren auf einmal.
Die Methode gibt außerdem immer einen String zurück, der eine vollständige Aufzählung (in menschenlesbarer Form) der jeweils gerade aktuellen Konfiguration enthält (und zwar der Konfiguration VOR der Durchführung jeglicher, durch den Eingabestring möglicherweise diktierten Änderungen).
Dieser Ausgabestring kann stets zu einem späteren Zeitpunkt wieder als Eingabestring an diese Methode übergeben werden, um eine frühere Konfiguration wiederherzustellen.
Sie können diesen Ausgabestring aber auch ignorieren, wenn Sie nur an der Veränderung der bestehenden Konfiguration und nicht an den ursprünglichen Einstellungen interessiert sind.
Es gibt drei Aspekte, die mit dieser Methode kontrolliert werden können:
Jeder dieser Aspekte wird mit Hilfe einer Zuweisung innerhalb des Eingabestrings verändert.
Der Eingabestring kann dabei beliebig viele dieser Zuweisungen enthalten. Von mehreren Zuweisungen, die sich auf denselben Aspekt beziehen, hat jedoch nur die letzte Gültigkeit.
Jede Zuweisung hat die Form "<was>=<wert>
".
"<was>
" und "<wert>
" dürfen dabei sowohl aus Buchstaben ([a-zA-Z]
) als auch aus Leerzeichen bestehen.
Mehrere Zuweisungen müssen durch eines (oder mehrere) der folgenden Zeichen voneinander getrennt werden:
Komma (","), Semikolon (";"), Doppelpunkt (":"), vertikaler Strich ("|"), Schrägstrich ("/"), Neue Zeile ("\n"), kaufmännisches Und ("&"), Plus ("+"), Bindestrich ("-").
Leere Zeilen oder Anweisungen (die nur aus Leerzeichen bestehen) sind erlaubt, werden aber ignoriert.
"<was>
" kann im Prinzip ein beliebiger Text sein, er muß aber eines (oder mehrere) Schlüsselworte aus einer der folgenden drei Gruppen enthalten (und zwar ausschließlich aus ein- und derselben Gruppe!):
(Jede Gruppe steht dabei für einen der drei Aspekte, die von der "Configuration()
"-Methode kontrolliert werden.)
(Die Zeichen "^" und "$" stehen hier für eine Wortgrenze, d.h. für den Anfang und das Ende eines Wortes.)
Beachten Sie, daß die Groß- und Kleinschreibung hier nicht unterschieden wird(!).
Mit Hilfe dieser Schlüsselworte können Sie beliebige Sätze bilden, vorausgesetzt daß kein Schlüsselwort aus einer der anderen beiden Gruppen darin vorkommt - anderenfalls kommt es zu einem fatalen Syntaxfehler (mit anderen Worten, Mehrdeutigkeiten sind nicht erlaubt!).
Ein Syntaxfehler tritt auch dann auf, wenn keines der obigen Schlüsselworte paßt.
Das gleiche Prinzip gilt auch für "<wert>
"; auch hier können Sie aus einer Reihe von Schlüsselworten sowie sonstigen, neutralen Worten beliebige Sätze bilden, und auch hier dürfen die Schlüsselworte nur aus ein- und derselben Gruppe kommen.
Abhängig davon, welchen Aspekt Sie mit "<was>
" ausgewählt haben, stehen unterschiedliche Gruppen von Schlüsselworten zur Verfügung, die bestimmen, auf welchen Wert der betreffende Aspekt eingestellt werden soll:
"<wert>" =
"<wert>" =
"<wert>" =
Beispiele:
"Any scalar input I provide should be considered to be = a bit index" "I want to have operator semantics suitable for = arithmetics" "Any bit vector in double quotes is to be output as = an enumeration"
^bit$
", "^index
" oder "^indice
", daß alle skalaren Operanden intern als Bit-Nummern aufgefaßt werden, d.h. "$vector ^= 5;
" wechselt in diesem Fall den Zustand von Bit Nummer "5
" im gegebenen Bitvektor (dieser Befehl entspricht übrigens genau dem Methodenaufruf "$vector->bit_flip(5);
").
Dies ist die Voreinstellung für dieses Modul.
Das Schlüsselwort "^hex
" hingegen bewirkt, daß alle skalaren Operanden als hexadezimale Zahlen aufgefaßt werden, d.h. "$vector ^= 5;
" wechselt in diesem Fall den Zustand der Bits Nummer "0
" und "2
" (da eine hexadezimale "5
" dem binären Wert "0101
" entspricht).
(Beachten Sie, daß hexadezimale Eingaben jedoch IMMER zwischen Anführungszeichen stehen sollten, weil sie von Perl sonst als Dezimalzahlen interpretiert werden! Das obige Beispiel macht sich lediglich die Tatsache zunutze, daß hexadezimal "0..9
" und dezimal "0..9
" dasselbe sind!)
Das Schlüsselwort "^bin
" bewirkt, daß alle skalaren Operanden als Zahl in Binärdarstellung aufgefaßt werden. Alle Zeichen außer "0
" und "1
" sind in diesem Fall verboten (und führen zu einem fatalen Syntaxfehler).
Der Befehl "$vector ^= '0101';
" wechselt in diesem Fall beispielsweise den Zustand der beiden Bits Nummer "0
" und "2
".
Das Schlüsselwort "^dec
" bewirkt, daß alle skalaren Operanden als ganze Zahlen im Dezimalsystem aufgefaßt werden, d.h. "$vector ^= 5;
" wechselt in diesem Fall den Zustand der Bits Nummer "0
" und "2
" (da eine dezimale "5
" dem binären Wert "0101
" entspricht).
(Beachten Sie, daß diese dezimalen Eingaben ebenfalls IMMER in Anführungszeichen stehen sollten, weil es sonst aufgrund der internen Darstellung von großen Zahlen in Perl im Fließkommaformat (mit Exponenten) zum Verlust von Dezimalstellen und darüber hinaus zu einem fatalen Syntaxfehler kommen kann, da die wissenschaftliche Notation (Exponentenschreibweise) nicht der vom Modul erwarteten Syntax entspricht!)
(Beachten Sie auch, daß die mit dieser Verwendung von Dezimalzahlen verbundene (notwendige!) Umwandlung von dezimal in die interne Binärdarstellung relativ zeitaufwendig ist und Ihre Anwendung verlangsamen kann!)
Das Schlüsselwort "^enum
" schließlich bewirkt, daß alle skalaren Operanden als eine Liste (Aufzählung) von Bit-Nummern und Bereichen von (fortlaufenden) Bit-Nummern aufgefaßt werden, d.h. der Befehl "$vector |= '2,3,5,7-13,17-23';
" setzt in diesem Fall die Bits mit den Nummern "2
", "3
", "5
", "7
" bis "13
" und "17
" bis "23
".
Die betroffenen Operatoren sind: "+
", "-
", "*
", "<
", "<=
", ">
", ">=
" und "abs()
".
Bei der Einstellung "Mengenoperationen" ("ops=set") - das ist die Voreinstellung! - werden die folgenden Operationen ausgeführt:
+ Vereinigungsmenge ( set1 u set2 ) - Differenzmenge ( set1 \ set2 ) * Durchschnitt ( set1 n set2 ) < echte Teilmenge ( set1 < set2 ) <= Teilmenge ( set1 <= set2 ) > echte Obermenge ( set1 > set2 ) >= Obermenge ( set1 >= set2 ) abs() Norm ( = |{ 1,2,.. }| )
Mit der alternativen Einstellung "arithmetische Operationen" ("ops=arithmetic") werden die folgenden Operationen ausgeführt:
+ Addition ( num1 + num2 ) - Subtraktion ( num1 - num2 ) * Multiplikation ( num1 * num2 ) < "kleiner als" ( num1 < num2 ) <= "kleiner oder gleich" ( num1 <= num2 ) > "größer als" ( num1 > num2 ) >= "größer oder gleich" ( num1 >= num2 ) abs() Absolutwert ( = | z | )
Beachten Sie, daß die obigen Vergleichsoperatoren ("<
", "<=
", ">
" und ">=
") ihre Operanden als VORZEICHENBEHAFTET ansehen.
Um Vergleiche mit VORZEICHENLOSEN Operanden durchzuführen, müssen Sie statt dessen die Operatoren "lt
", "le
", "gt
" und "ge
" verwenden. (Im Gegensatz zu den obigen Operatoren sind letztere von der "Operator-Semantik"-Einstellung NICHT betroffen!)
to_Hex()
", "to_Bin()
", "to_Dec()
" und "to_Enum()
" (die Methode "Block_Read()
" wird hier nicht mitgezählt, weil sie keinen menschenlesbaren String erzeugt).
(Für die Umwandlung eines Bitvektors in Oktalzahlen siehe die Beschreibung der Methode "Chunk_List_Read()
"!)
Dementsprechend gibt es vier mögliche Formate, in die ein Bitvektor bei der Ausgabe umgewandelt werden kann, d.h. wenn er in (doppelten) Anführungszeichen steht:
print "\$vector = '$vector'\n"; $string = "$vector";
Dementsprechend gibt es vier mögliche Einstellungen für den Aspekt "String-Ausgaben" ("string output"):
BEACHTEN SIE, daß die Umwandlung in Dezimalzahlen von Natur aus extrem zeitaufwendig ist und Ihre Anwendung beträchtlich verlangsamen kann!
Daher sollten Sie diese Einstellung nur äußerst sparsam einsetzen und die zurückgelieferten Strings (mit den Dezimalzahlen) wo nötig zwischenspeichern, anstatt einen Bitvektor ein zweites Mal umzuwandeln.
Configuration()
" zurückgegebene Voreinstellung lautet wie folgt:
Scalar Input = Bit Index Operator Semantics = Set Operators String Output = Hexadecimal
Die Ausführung der beiden Anweisungen
Bit::Vector->Configuration("in=bin,ops=arithmetic,out=bin"); print Bit::Vector->Configuration(), "\n";
liefert die folgende Ausgabe:
Scalar Input = Binary Operator Semantics = Arithmetic Operators String Output = Binary
Sie können diese Ausgabe auch wieder an die "Configuration()
"-Methode übergeben, um diese Einstellung später wiederherzustellen.
Beachten Sie, daß alle nicht explizit angegebenen Aspekte auch nicht verändert werden, d.h die Anweisung
Bit::Vector->Configuration("operators = arithmetic");
läßt alle anderen Aspekte außer der "Operator-Semantik" unverändert.
"$vector"
Denken Sie daran, daß Perl alle in (doppelten) Anführungszeichen stehenden Variablen expandiert, oder, um im Perl-Jargon zu bleiben, "interpoliert".
Wann immer eine Perl-Variable, die eine Referenz auf ein "Bit::Vector"-Objekt enthält, in (doppelten) Anführungszeichen steht (egal ob für sich alleine oder zusammen mit anderem Text und/oder Variablen), wird der Inhalt des zugehörigen Bitvektors in einen druckbaren String umgewandelt und die betreffende Variable durch diesen String ersetzt.
Welche der vier vorhandenen Konvertierungsmethoden ("to_Hex()
", "to_Bin()
", "to_Dec()
" oder "to_Enum()
") dabei verwendet wird, hängt von der mit Hilfe der Methode "Configure()
" eingestellten Konfiguration ab (siehe dazu auch die Erläuterungen im vorangegangenen Kapitel).
Zu Programmbeginn ist die Umwandlung in Hexadezimalzahlen (also "to_Hex()
") voreingestellt.
if ($vector)
Es ist möglich, einen Bitvektor als booleschen Ausdruck zu verwenden.
Die Bedingung ist wahr, wenn in dem betreffenden Bitvektor MINDESTENS ein Bit GESETZT ist. Die Bedingung ist falsch, wenn ALLE Bits des betreffenden Bitvektors GELÖSCHT sind.
if (!$vector)
Da es möglich ist, einen Bitvektor als booleschen Ausdruck zu verwenden, können Sie diesen Ausdruck natürlich auch negieren und damit das Ergebnis dieser Auswertung umkehren.
Die Bedingung ist wahr, wenn ALLE Bits des betreffenden Bitvektors GELÖSCHT sind. Sie ist falsch, wenn im betreffenden Bitvektor MINDESTENS ein Bit GESETZT ist.
Beachten Sie, daß dies NICHT das gleiche ist wie die Abfrage mit Hilfe der Methode "is_full()
", die "wahr" zurückgibt, wenn ALLE Bits des betreffenden Bitvektors GESETZT sind!
~$vector
Dieser Term gibt ein neues Bitvektor-Objekt zurück, das das Einerkomplement des gegebenen Bitvektors enthält.
Dies entspricht dem Invertieren aller Bits.
-$vector
(unäres Minus)
Dieser Term gibt ein neues Bitvektor-Objekt zurück, das das Zweierkomplement des gegebenen Bitvektors enthält.
Das entspricht dem Invertieren aller Bits und der anschließenden Inkrementierung dieses Ergebnisses um eins.
(Das entspricht außerdem dem Vorzeichenwechsel der in dem Bitvektor enthaltenen Zahl.)
abs($vector)
Abhängig von der Konfiguration (Details hierzu finden Sie in der Beschreibung der "Configuration()
"-Methode) gibt dieser Term entweder (Voreinstellung) die Anzahl der im gegebenen Bitvektor gesetzten Bits zurück (was der Anzahl von Elementen einer Menge, also ihrer "Kardinalität", entspricht), oder er gibt ein neues Bitvektor-Objekt zurück, das den Absolutwert der in dem gegebenen Bitvektor gespeicherten Zahl enthält.
$vector1 . $vector2
Dieser Term gibt ein neues Bitvektor-Objekt zurück, das das Ergebnis der Verkettung der beiden Bitvektor-Operanden ist.
Der linke Operand wird dabei zum höchstwertigen, der rechte zum niederwertigsten Teil des neuen Bitvektors.
Ist einer der beiden Operanden hingegen kein Bitvektor-Objekt, sondern ein Perl-Skalar, wird der Inhalt des Bitvektor-Operanden in einen String umgewandelt (die dabei verwendete Konvertierungsmethode hängt von der mit der "Configuration()
"-Methode eingestellten Konfiguration ab), der dann wiederum in der richtigen Reihenfolge (d.h. in der Reihenfolge der beiden Operanden) mit dem Perl-Skalar ZU EINEM STRING verkettet wird.
(Es wird also in diesem Fall kein neues Bitvektor-Objekt zurückgegeben, sondern ein String!)
$vector x $factor
Dieser Term gibt ein neues Bitvektor-Objekt zurück, das die Verkettung von so vielen Kopien des gegebenen Bitvektors (also des linken Operanden) ist, wie der Faktor (der rechte Operand) angibt.
Hat dieser Faktor den Wert Null, wird ein Bitvektor-Objekt mit einer Länge von Null Bits zurückgegeben.
Hat der Faktor den Wert Eins, wird einfach eine neue Kopie des Bitvektors zurückgegeben.
Beachten Sie, daß es zu einem fatalen "Vertauschte Operanden"-Fehler ("reversed operands error") kommt, falls die beiden Operanden vertauscht werden.
$vector << $bits
Dieser Term gibt ein neues Bitvektor-Objekt zurück, das eine Kopie des gegebenen Bitvektors (linker Operand) ist, die um so viele Bit-Positionen nach links geschoben wurde (in Richtung zum höchstwertigen Bit), wie der rechte Operand "$bits
" angibt.
Das bedeutet, daß die "$bits
" höchstwertigen Bits verloren gehen, alle anderen Bits um "$bits
" Positionen nach oben verschoben und die freiwerdenden "$bits
" niederwertigsten Bits auf Null gesetzt werden.
Ist "$bits
" größer als die Anzahl der Bits im gegebenen Bitvektor, gibt dieser Term einen leeren Bitvektor zurück (d.h. alle Bits sind gelöscht), der die gleiche Länge hat wie der gegebene Bitvektor.
Beachten Sie, daß es zu einem fatalen "Vertauschte Operanden"-Fehler ("reversed operands error") kommt, falls die beiden Operanden vertauscht werden.
$vector >> $bits
Dieser Term gibt ein neues Bitvektor-Objekt zurück, das eine Kopie des gegebenen Bitvektors (linker Operand) ist, die um so viele Bit-Positionen nach rechts geschoben wurde (in Richtung zum niederwertigsten Bit), wie der rechte Operand "$bits
" angibt.
Das bedeutet, daß die "$bits
" niederwertigsten Bits verloren gehen, alle anderen Bits um "$bits
" Positionen nach unten verschoben und die freiwerdenden "$bits
" höchstwertigen Bits auf Null gesetzt werden.
Ist "$bits
" größer als die Anzahl der Bits im gegebenen Bitvektor, gibt dieser Term einen leeren Bitvektor zurück (d.h. alle Bits sind gelöscht), der die gleiche Länge hat wie der gegebene Bitvektor.
Beachten Sie, daß es zu einem fatalen "Vertauschte Operanden"-Fehler ("reversed operands error") kommt, falls die beiden Operanden vertauscht werden.
$vector1 | $vector2
Dieser Term gibt ein neues Bitvektor-Objekt zurück, das das Ergebnis einer Bit-weisen ODER-Verknüpfung der beiden Bitvektor-Operanden ist.
Das ist äquivalent zu der Berechnung der Vereinigungsmenge dieser beiden Mengen.
$vector1 & $vector2
Dieser Term gibt ein neues Bitvektor-Objekt zurück, das das Ergebnis einer Bit-weisen UND-Verknüpfung der beiden Bitvektor-Operanden ist.
Das ist äquivalent zu der Berechnung der Schnittmenge (des Durchschnitts) dieser beiden Mengen.
$vector1 ^ $vector2
Dieser Term gibt ein neues Bitvektor-Objekt zurück, das das Ergebnis einer Bit-weisen EXKLUSIV-ODER-Verknüpfung der beiden Bitvektor-Operanden ist.
Das ist äquivalent zu der Berechnung der symmetrischen Differenz dieser beiden Mengen.
$vector1 + $vector2
Abhängig von der Konfiguration (Details hierzu finden Sie in der Beschreibung der "Configuration()
"-Methode) gibt dieser Term entweder (Voreinstellung) ein neues Bitvektor-Objekt zurück, das das Ergbnis einer Bit-weisen ODER-Verknüpfung der beiden Bitvektor-Operanden ist (was der Berechnung der Vereinigungsmenge dieser beiden Mengen entspricht), oder es wird ein Bitvektor-Objekt zurückgegeben, das die Summe der beiden Bitvektor-Operanden enthält.
$vector1 - $vector2
Abhängig von der Konfiguration (Details hierzu finden Sie in der Beschreibung der "Configuration()
"-Methode) gibt dieser Term entweder (Voreinstellung) ein neues Bitvektor-Objekt zurück, das die Differenzmenge der beiden Bitvektor-Operanden darstellt, oder es wird ein Bitvektor-Objekt zurückgegeben, das die Differenz der beiden Zahlen in den beiden Bitvektor-Operanden enthält.
$vector1 * $vector2
Abhängig von der Konfiguration (Details hierzu finden Sie in der Beschreibung der "Configuration()
"-Methode) gibt dieser Term entweder (Voreinstellung) ein neues Bitvektor-Objekt zurück, das das Ergbnis einer Bit-weisen UND-Verknüpfung der beiden Bitvektor-Operanden ist (was der Berechnung der Schnittmenge dieser beiden Mengen entspricht), oder es wird ein Bitvektor-Objekt zurückgegeben, das das Produkt aus den beiden Bitvektor-Operanden enthält.
$vector1 / $vector2
Dieser Term gibt ein neues Bitvektor-Objekt zurück, das das Ergebnis der Division der beiden Zahlen in den beiden Bitvektor-Operanden enthält.
$vector1 % $vector2
Dieser Term gibt ein neues Bitvektor-Objekt zurück, das den Rest der Division der beiden Zahlen in den beiden Bitvektor-Operanden enthält.
$vector1 .= $vector2;
Diese Anweisung hängt den rechten Operanden an den linken Bitvektor-Operanden an.
Der vorherige Inhalt des linken Operanden wird dabei zum höchstwertigen Teil des resultierenden Bitvektors, der rechte Operand zum niederwertigsten Teil.
Da Bitvektoren mit den niederwertigsten Bits zuunterst im Speicher abgelegt werden, muß der linke Operand dabei in Wahrheit um die Länge des rechten Operanden nach oben verschoben werden. Anschließend wird der rechte Operand in den nun freigewordenen niederwertigsten Teil des linken Operanden hineinkopiert.
Handelt es sich bei dem rechten Operanden um einen Perl-Skalar, wird dieser zuvor in einen Bitvektor umgewandelt.
Ist die Konfiguration so eingestellt, daß skalare Operanden als Bit-Nummern, Dezimalzahlen oder Aufzählungen interpretiert werden, wird der rechte Operand in einen Bitvektor umgewandelt, der die gleiche Länge hat wie der linke Operand.
Ist die Konfiguration hingegen so eingestellt, daß skalare Operanden als Hexadezimal- oder Binärzahlen interpretiert werden, wird der rechte Operand in einen Bitvektor umgewandelt, dessen Länge von der des rechten (skalaren) Operanden abhägt, und zwar viermal so lang bei einem Hexadezimalstring (weil jede hexadezimale Ziffer 4 Bits kodiert) und genauso lang bei einem Binärstring.
$vector x= $factor;
Diese Anweisung ersetzt den gegebenen Bitvektor durch die Verkettung von so vielen Kopien des ursprünglichen Inhalts dieses Bitvektors, wie das der Faktor (der rechte Operand) angibt.
Hat der Faktor den Wert Null, wird die Länge des Bitvektors auf Null Bits gesetzt.
Hat der Faktor den Wert Eins, wird der Bitvektor nicht verändert.
$vector <<= $bits;
Diese Anweisung verschiebt den Inhalt des gegebenen Bitvektors um so viele Bit-Positionen nach links (in Richtung zum höchstwertigen Bit), wie der rechte Operand "$bits
" angibt.
Das bedeutet, daß die "$bits
" höchstwertigen Bits verloren gehen, alle anderen Bits um "$bits
" Positionen nach oben verschoben und die freiwerdenden "$bits
" niederwertigsten Bits auf Null gesetzt werden.
Ist "$bits
" größer als die Anzahl der Bits im gegebenen Bitvektor, wird der Bitvektor vollständig gelöscht.
$vector >>= $bits;
Diese Anweisung verschiebt den Inhalt des gegebenen Bitvektors um so viele Bit-Positionen nach rechts (in Richtung zum niederwertigsten Bit), wie der rechte Operand "$bits
" angibt.
Das bedeutet, daß die "$bits
" niederwertigsten Bits verloren gehen, alle anderen Bits um "$bits
" Positionen nach unten verschoben und die freiwerdenden "$bits
" höchstwertigen Bits auf Null gesetzt werden.
Ist "$bits
" größer als die Anzahl der Bits im gegebenen Bitvektor, wird der Bitvektor vollständig gelöscht.
$vector1 |= $vector2;
Diese Anweisung führt eine Bit-weise ODER-Verknüpfung der beiden Bitvektor-Operanden durch und legt das Ergebnis dieser Operation im linken Operanden ab.
Das ist äquivalent zu der Berechnung der Vereinigungsmenge dieser beiden Mengen.
$vector1 &= $vector2;
Diese Anweisung führt eine Bit-weise UND-Verknüpfung der beiden Bitvektor-Operanden durch und legt das Ergebnis dieser Operation im linken Operanden ab.
Das ist äquivalent zu der Berechnung der Schnittmenge (des Durchschnitts) dieser beiden Mengen.
$vector1 ^= $vector2;
Diese Anweisung führt eine Bit-weise EXKLUSIV-ODER-Verknüpfung der beiden Bitvektor-Operanden durch und legt das Ergebnis dieser Operation im linken Operanden ab.
Das ist äquivalent zu der Berechnung der symmetrischen Differenz dieser beiden Mengen.
$vector1 += $vector2;
Abhängig von der Konfiguration (Details hierzu finden Sie in der Beschreibung der "Configuration()
"-Methode) führt diese Anweisung entweder (Voreinstellung) eine Bit-weise ODER-Verknüpfung der beiden Bitvektor-Operanden durch (was der Berechnung der Vereinigungsmenge dieser beiden Mengen entspricht), oder es wird die Summe der beiden Zahlen in den beiden Bitvektoren berechnet.
Das Ergebnis dieser Operation wird im linken Operanden abgelegt.
$vector1 -= $vector2;
Abhängig von der Konfiguration (Details hierzu finden Sie in der Beschreibung der "Configuration()
"-Methode) berechnet diese Anweisung entweder (Voreinstellung) die Differenzmenge der beiden Bitvektor-Operanden, oder es wird die Differenz der beiden Zahlen in den beiden Bitvektoren berechnet.
Das Ergebnis dieser Operation wird im linken Operanden abgelegt.
$vector1 *= $vector2;
Abhängig von der Konfiguration (Details hierzu finden Sie in der Beschreibung der "Configuration()
"-Methode) führt diese Anweisung entweder (Voreinstellung) eine Bit-weise UND-Verknüpfung der beiden Bitvektor-Operanden durch (was der Berechnung der Schnittmenge dieser beiden Mengen entspricht), oder es wird das Produkt aus den beiden Zahlen in den beiden Bitvektoren berechnet.
Das Ergebnis dieser Operation wird im linken Operanden abgelegt.
$vector1 /= $vector2;
Diese Anweisung legt das Ergebnis der Division der beiden Zahlen aus den beiden Bitvektor-Operanden im linken Operanden ab.
$vector1 %= $vector2;
Diese Anweisung legt den Rest der Division der beiden Zahlen aus den beiden Bitvektor-Operanden im linken Operanden ab.
++$vector
, $vector++
Dieser Operator führt ein Pre- bzw. Postinkrement des gegebenen Bitvektors durch.
Der von diesem Term zurückgelieferte Wert ist eine Referenz auf das gegebene Bitvektor-Objekt (nach bzw. vor der Inkrementierung).
--$vector
, $vector--
Dieser Operator führt ein Pre- bzw. Postdekrement des gegebenen Bitvektors durch.
Der von diesem Term zurückgelieferte Wert ist eine Referenz auf das gegebene Bitvektor-Objekt (nach bzw. vor der Dekrementierung.)
($vector1 cmp $vector2)
Dieser Term gibt "-1
" zurück, falls "$vector1
" kleiner ist als "$vector2
", "0
", falls "$vector1
" und "$vector2
" gleich sind, und "1
", falls "$vector1
" größer ist als "$vector2
".
Dieser Vergleich geht davon aus, daß die beiden Bitvektoren VORZEICHENLOS sind.
($vector1 eq $vector2)
Dieser Term gibt "wahr" ("1
") zurück, wenn die beiden Bitvektor-Operanden gleich sind, ansonsten "falsch" ("0
").
($vector1 ne $vector2)
Dieser Term gibt "wahr" ("1
") zurück, wenn sich die beiden Bitvektor-Operanden unterscheiden, ansonsten "falsch" ("0
").
($vector1 lt $vector2)
Dieser Term gibt "wahr" ("1
") zurück, wenn "$vector1
" kleiner ist als "$vector2
", ansonsten "falsch" ("0
").
Dieser Vergleich geht davon aus, daß die beiden Bitvektoren VORZEICHENLOS sind.
($vector1 le $vector2)
Dieser Term gibt "wahr" ("1
") zurück, wenn "$vector1
" kleiner als oder gleich "$vector2
" ist, ansonsten "falsch" ("0
").
Dieser Vergleich geht davon aus, daß die beiden Bitvektoren VORZEICHENLOS sind.
($vector1 gt $vector2)
Dieser Term gibt "wahr" ("1
") zurück, wenn "$vector1
" größer ist als "$vector2
", ansonsten "falsch" ("0
").
Dieser Vergleich geht davon aus, daß die beiden Bitvektoren VORZEICHENLOS sind.
($vector1 ge $vector2)
Dieser Term gibt "wahr" ("1
") zurück, wenn "$vector1
" größer als oder gleich "$vector2
" ist, ansonsten "falsch" ("0
").
Dieser Vergleich geht davon aus, daß die beiden Bitvektoren VORZEICHENLOS sind.
($vector1 <=> $vector2)
Dieser Term gibt "-1
" zurück, falls "$vector1
" kleiner ist als "$vector2
", "0
", falls "$vector1
" und "$vector2
" gleich sind, und "1
", falls "$vector1
" größer ist als "$vector2
".
Dieser Vergleich geht davon aus, daß die beiden Bitvektoren VORZEICHENBEHAFTET sind.
($vector1 == $vector2)
Dieser Term gibt "wahr" ("1
") zurück, wenn die beiden Bitvektor-Operanden gleich sind, ansonsten "falsch" ("0
").
($vector1 != $vector2)
Dieser Term gibt "wahr" ("1
") zurück, wenn sich die beiden Bitvektor-Operanden unterscheiden, ansonsten "falsch" ("0
").
($vector1 < $vector2)
Abhängig von der Konfiguration (Details hierzu finden Sie in der Beschreibung der "Configuration()
"-Methode) gibt dieser Term entweder (Voreinstellung) "wahr" ("1
") zurück, falls "$vector1
" eine echte Teilmenge von "$vector2
" ist (ansonsten "falsch" bzw. "0
"), oder er gibt "wahr" ("1
") zurück, falls "$vector1
" kleiner ist als "$vector2
" (ansonsten "falsch" bzw. "0
").
Dieser letztere Vergleich geht davon aus, daß die beiden Bitvektoren VORZEICHENBEHAFTET sind.
($vector1 <= $vector2)
Abhängig von der Konfiguration (Details hierzu finden Sie in der Beschreibung der "Configuration()
"-Methode) gibt dieser Term entweder (Voreinstellung) "wahr" ("1
") zurück, falls "$vector1
" eine Teilmenge von "$vector2
" ist (ansonsten "falsch" bzw. "0
"), oder er gibt "wahr" ("1
") zurück, falls "$vector1
" kleiner ist als "$vector2
" (ansonsten "falsch" bzw. "0
").
Dieser letztere Vergleich geht davon aus, daß die beiden Bitvektoren VORZEICHENBEHAFTET sind.
($vector1 > $vector2)
Abhängig von der Konfiguration (Details hierzu finden Sie in der Beschreibung der "Configuration()
"-Methode) gibt dieser Term entweder (Voreinstellung) "wahr" ("1
") zurück, falls "$vector1
" eine echte Obermenge von "$vector2
" ist (ansonsten "falsch" bzw. "0
"), oder er gibt "wahr" ("1
") zurück, falls "$vector1
" kleiner ist als "$vector2
" (ansonsten "falsch" bzw. "0
").
Dieser letztere Vergleich geht davon aus, daß die beiden Bitvektoren VORZEICHENBEHAFTET sind.
($vector1 >= $vector2)
Abhängig von der Konfiguration (Details hierzu finden Sie in der Beschreibung der "Configuration()
"-Methode) gibt dieser Term entweder (Voreinstellung) "wahr" ("1
") zurück, falls "$vector1
" eine Obermenge von "$vector2
" ist (ansonsten "falsch" bzw. "0
"), oder er gibt "wahr" ("1
") zurück, falls "$vector1
" kleiner ist als "$vector2
" (ansonsten "falsch" bzw. "0
").
Dieser letztere Vergleich geht davon aus, daß die beiden Bitvektoren VORZEICHENBEHAFTET sind.
perl(1),
perlsub(1),
perlmod(1),
perlref(1),
perlobj(1),
perlbot(1),
perltoot(1),
perlxs(1),
perlxstut(1),
perlguts(1),
overload(3).
Steffen Beyer mailto:sb@fluomedia.org http://sb.fluomedia.org/download/
(Vom Modulautor gegengelesen und überarbeitet)
Erschienen in: "Programmieren mit Perl-Modulen", O'Reilly Verlag Köln, 1999.
Verwendung hier mit freundlicher Genehmigung des O'Reilly Verlag, Köln.
Die C-Bibliothek, die den Kern dieses Perl-Moduls bildet, kann darüber hinaus auch unter den Lizenzbedingungen der "GNU Library General Public License" benutzt, modifiziert und weitergegeben werden.
Bitte beachten Sie die Dateien "Artistic.txt", "GNU_GPL.txt" und "GNU_LGPL.txt" in dieser Distribution für die entsprechenden Details!
Siehe dazu auch die "GNU General Public License" für weitere Details.