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://www.engelschall.com/u/sb/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://www.engelschall.com/u/sb/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 "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 10er-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/)
10er-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 10er-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);