Bit-Vector-7.4/000755 100660 100660 00000000000 12211373041 012406 5ustar00sbsb000000 000000 Bit-Vector-7.4/GNU_LGPL.txt000644 100660 100660 00000061271 12211373040 014424 0ustar00sbsb000000 000000 GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Library General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! Bit-Vector-7.4/MANIFEST000644 100660 100660 00000001631 12211373040 013537 0ustar00sbsb000000 000000 Artistic.txt BitVector.c BitVector.h CHANGES.txt CREDITS.txt GNU_GPL.txt GNU_LGPL.txt INSTALL.txt MANIFEST Makefile.PL README.txt ToolBox.h Vector.pm Vector.pod Vector.xs examples/SetObject.pl examples/benchmk1.pl examples/benchmk2.pl examples/benchmk3.pl examples/primes.pl examples/test.c lib/Bit/Vector/Overload.pm lib/Bit/Vector/Overload.pod lib/Bit/Vector/String.pm lib/Bit/Vector/String.pod t/00_____version.t t/01_________new.t t/02_____destroy.t t/03__operations.t t/04___functions.t t/05______primes.t t/06______subset.t t/07_____compare.t t/08______resize.t t/09__parameters.t t/10___intervals.t t/11_______shift.t t/12______string.t t/13___increment.t t/14_______empty.t t/15_________add.t t/16____subtract.t t/17_________gcd.t t/28___chunklist.t t/30__overloaded.t t/40___auxiliary.t t/50_freeze_thaw.t t/51_file_nstore.t typemap META.yml Module meta-data (added by MakeMaker) Bit-Vector-7.4/Vector.pm000644 100660 100660 00000003140 12211373040 014203 0ustar00sbsb000000 000000 ############################################################################### ## ## ## Copyright (c) 1995 - 2013 by Steffen Beyer. ## ## All rights reserved. ## ## ## ## This package is free software; you can redistribute it ## ## and/or modify it under the same terms as Perl itself. ## ## ## ############################################################################### package Bit::Vector; use strict; use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION @CONFIG); require Exporter; require DynaLoader; @ISA = qw(Exporter DynaLoader); @EXPORT = qw(); @EXPORT_OK = qw(); $VERSION = '7.4'; bootstrap Bit::Vector $VERSION; sub STORABLE_freeze { my($self, $clone) = @_; return( Storable::nfreeze( [ $self->Size(), $self->Block_Read() ] ) ); } sub STORABLE_thaw { my($self, $clone, $string) = @_; my($size,$buffer) = @{ Storable::thaw($string) }; $self->Unfake($size); # Undocumented feature, only for use by "Storable"! $self->Block_Store($buffer); } #sub STORABLE_attach # Does not work properly in nested data structures (see test cases) #{ # my($class, $clone, $string) = @_; # my($size,$buffer) = @{ Storable::thaw($string) }; # my $self = Bit::Vector->new($size); # $self->Block_Store($buffer); # return $self; #} 1; __END__ Bit-Vector-7.4/Vector.xs000644 100660 100660 00000222732 12211373040 014233 0ustar00sbsb000000 000000 /*****************************************************************************/ /* */ /* Copyright (c) 1995 - 2013 by Steffen Beyer. */ /* All rights reserved. */ /* */ /* This package is free software; you can redistribute it */ /* and/or modify it under the same terms as Perl itself. */ /* */ /*****************************************************************************/ #include "EXTERN.h" #include "perl.h" #include "XSUB.h" #include "patchlevel.h" #if ((PATCHLEVEL < 4) || ((PATCHLEVEL == 4) && (SUBVERSION < 5))) /* PL_na was introduced in perl5.004_05 */ #ifndef PL_na #define PL_na na #endif #endif #if (PATCHLEVEL < 4) /* GIMME_V was introduced in perl5.004 */ #ifndef GIMME_V #define GIMME_V GIMME #endif #endif #include "BitVector.h" typedef SV *BitVector_Object; typedef SV *BitVector_Handle; typedef N_word *BitVector_Address; typedef SV *BitVector_Scalar; static char *BitVector_Class = "Bit::Vector"; /* NOT "const" for older Perl versions */ const char *BitVector_OBJECT_ERROR = "item is not a \"Bit::Vector\" object"; const char *BitVector_SCALAR_ERROR = "item is not a scalar"; const char *BitVector_STRING_ERROR = "item is not a string"; const char *BitVector_MIN_ERROR = "minimum index out of range"; const char *BitVector_MAX_ERROR = "maximum index out of range"; const char *BitVector_START_ERROR = "start index out of range"; const char *BitVector_OFFSET_ERROR = "offset out of range"; const char *BitVector_CHUNK_ERROR = "chunk size out of range"; const char *BitVector_SET_ERROR = "set size mismatch"; const char *BitVector_MATRIX_ERROR = "matrix size mismatch"; const char *BitVector_SHAPE_ERROR = "not a square matrix"; const char *BitVector_MEMORY_ERROR = BV_ERRCODE_NULL; const char *BitVector_INDEX_ERROR = BV_ERRCODE_INDX; const char *BitVector_ORDER_ERROR = BV_ERRCODE_ORDR; const char *BitVector_SIZE_ERROR = BV_ERRCODE_SIZE; #define BIT_VECTOR_STASH gv_stashpv(BitVector_Class,1) #define BIT_VECTOR_OBJECT(ref,hdl,adr) \ ( ref && \ SvROK(ref) && \ (hdl = (BitVector_Handle)SvRV(ref)) && \ SvOBJECT(hdl) && \ SvREADONLY(hdl) && \ (SvTYPE(hdl) == SVt_PVMG) && \ (SvSTASH(hdl) == BIT_VECTOR_STASH) && \ (adr = (BitVector_Address)SvIV(hdl)) ) #define BIT_VECTOR_FAKE_OBJECT(ref,hdl) \ ( ref && \ SvROK(ref) && \ (hdl = (BitVector_Handle)SvRV(ref)) && \ SvOBJECT(hdl) && \ !SvREADONLY(hdl) && \ (SvTYPE(hdl) == SVt_PVMG) && \ (SvSTASH(hdl) == BIT_VECTOR_STASH) ) #define BIT_VECTOR_SCALAR(ref,typ,var) \ ( ref && !(SvROK(ref)) && ((var = (typ)SvIV(ref)) | 1) ) #define BIT_VECTOR_STRING(ref,var) \ ( ref && !(SvROK(ref)) && (var = (charptr)SvPV(ref,PL_na)) ) #define BIT_VECTOR_BUFFER(ref,var,len) \ ( ref && !(SvROK(ref)) && SvPOK(ref) && \ (var = (charptr)SvPV(ref,PL_na)) && \ ((len = (N_int)SvCUR(ref)) | 1) ) #define BIT_VECTOR_ERROR(message) \ croak("Bit::Vector::%s(): %s", GvNAME(CvGV(cv)), message) #define BIT_VECTOR_OBJECT_ERROR \ BIT_VECTOR_ERROR( BitVector_OBJECT_ERROR ) #define BIT_VECTOR_SCALAR_ERROR \ BIT_VECTOR_ERROR( BitVector_SCALAR_ERROR ) #define BIT_VECTOR_STRING_ERROR \ BIT_VECTOR_ERROR( BitVector_STRING_ERROR ) #define BIT_VECTOR_MIN_ERROR \ BIT_VECTOR_ERROR( BitVector_MIN_ERROR ) #define BIT_VECTOR_MAX_ERROR \ BIT_VECTOR_ERROR( BitVector_MAX_ERROR ) #define BIT_VECTOR_START_ERROR \ BIT_VECTOR_ERROR( BitVector_START_ERROR ) #define BIT_VECTOR_OFFSET_ERROR \ BIT_VECTOR_ERROR( BitVector_OFFSET_ERROR ) #define BIT_VECTOR_CHUNK_ERROR \ BIT_VECTOR_ERROR( BitVector_CHUNK_ERROR ) #define BIT_VECTOR_SET_ERROR \ BIT_VECTOR_ERROR( BitVector_SET_ERROR ) #define BIT_VECTOR_MATRIX_ERROR \ BIT_VECTOR_ERROR( BitVector_MATRIX_ERROR ) #define BIT_VECTOR_SHAPE_ERROR \ BIT_VECTOR_ERROR( BitVector_SHAPE_ERROR ) #define BIT_VECTOR_MEMORY_ERROR \ BIT_VECTOR_ERROR( BitVector_MEMORY_ERROR ) #define BIT_VECTOR_INDEX_ERROR \ BIT_VECTOR_ERROR( BitVector_INDEX_ERROR ) #define BIT_VECTOR_ORDER_ERROR \ BIT_VECTOR_ERROR( BitVector_ORDER_ERROR ) #define BIT_VECTOR_SIZE_ERROR \ BIT_VECTOR_ERROR( BitVector_SIZE_ERROR ) #define BIT_VECTOR_EXCEPTION(code) \ BIT_VECTOR_ERROR( BitVector_Error(code) ) MODULE = Bit::Vector PACKAGE = Bit::Vector PREFIX = BitVector_ PROTOTYPES: DISABLE BOOT: { BV_ErrCode rc; if ((rc = BitVector_Boot())) { BIT_VECTOR_EXCEPTION(rc); exit((int)rc); } } void BitVector_Version(...) PPCODE: { charptr string; if ((items >= 0) and (items <= 1)) { string = BitVector_Version(); if (string != NULL) { EXTEND(sp,1); PUSHs(sv_2mortal(newSVpv((char *)string,0))); } else BIT_VECTOR_MEMORY_ERROR; } else croak("Usage: Bit::Vector->Version()"); } N_int BitVector_Word_Bits(...) CODE: { if ((items >= 0) and (items <= 1)) { RETVAL = BitVector_Word_Bits(); } else croak("Usage: Bit::Vector->Word_Bits()"); } OUTPUT: RETVAL N_int BitVector_Long_Bits(...) CODE: { if ((items >= 0) and (items <= 1)) { RETVAL = BitVector_Long_Bits(); } else croak("Usage: Bit::Vector->Long_Bits()"); } OUTPUT: RETVAL void BitVector_Create(...) ALIAS: new = 1 PPCODE: { BitVector_Scalar arg1; BitVector_Scalar arg2; BitVector_Address address; BitVector_Handle handle; BitVector_Object reference; bv_listptr list; bv_listptr slot; N_int bits; N_int count; if ((items >= 2) and (items <= 3)) { arg1 = ST(1); if ( BIT_VECTOR_SCALAR(arg1,N_int,bits) ) { if (items > 2) { arg2 = ST(2); if ( BIT_VECTOR_SCALAR(arg2,N_int,count) ) { if (count > 0) { if ((list = BitVector_Create_List(bits,true,count)) != NULL) { EXTEND(sp,(int)count); slot = list; while (count-- > 0) { address = *slot++; handle = newSViv((IV)address); reference = sv_bless(sv_2mortal(newRV(handle)), BIT_VECTOR_STASH); SvREFCNT_dec(handle); SvREADONLY_on(handle); PUSHs(reference); } BitVector_Destroy_List(list,0); } else BIT_VECTOR_MEMORY_ERROR; } } else BIT_VECTOR_SCALAR_ERROR; } else { if ((address = BitVector_Create(bits,true)) != NULL) { handle = newSViv((IV)address); reference = sv_bless(sv_2mortal(newRV(handle)), BIT_VECTOR_STASH); SvREFCNT_dec(handle); SvREADONLY_on(handle); PUSHs(reference); } else BIT_VECTOR_MEMORY_ERROR; } } else BIT_VECTOR_SCALAR_ERROR; } else croak("Usage: %s(class,bits[,count])", GvNAME(CvGV(cv))); } void BitVector_new_Hex(class,bits,string) BitVector_Object class BitVector_Scalar bits BitVector_Scalar string PPCODE: { BitVector_Address address; BitVector_Handle handle; BitVector_Object reference; charptr pointer; BV_ErrCode code; N_int size; if ( BIT_VECTOR_SCALAR(bits,N_int,size) ) { if ( BIT_VECTOR_STRING(string,pointer) ) { if ((address = BitVector_Create(size,false)) != NULL) { if ((code = BitVector_from_Hex(address,pointer))) { BitVector_Destroy(address); BIT_VECTOR_EXCEPTION(code); } else { handle = newSViv((IV)address); reference = sv_bless(sv_2mortal(newRV(handle)), BIT_VECTOR_STASH); SvREFCNT_dec(handle); SvREADONLY_on(handle); PUSHs(reference); } } else BIT_VECTOR_MEMORY_ERROR; } else BIT_VECTOR_STRING_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } void BitVector_new_Bin(class,bits,string) BitVector_Object class BitVector_Scalar bits BitVector_Scalar string PPCODE: { BitVector_Address address; BitVector_Handle handle; BitVector_Object reference; charptr pointer; BV_ErrCode code; N_int size; if ( BIT_VECTOR_SCALAR(bits,N_int,size) ) { if ( BIT_VECTOR_STRING(string,pointer) ) { if ((address = BitVector_Create(size,false)) != NULL) { if ((code = BitVector_from_Bin(address,pointer))) { BitVector_Destroy(address); BIT_VECTOR_EXCEPTION(code); } else { handle = newSViv((IV)address); reference = sv_bless(sv_2mortal(newRV(handle)), BIT_VECTOR_STASH); SvREFCNT_dec(handle); SvREADONLY_on(handle); PUSHs(reference); } } else BIT_VECTOR_MEMORY_ERROR; } else BIT_VECTOR_STRING_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } void BitVector_new_Dec(class,bits,string) BitVector_Object class BitVector_Scalar bits BitVector_Scalar string PPCODE: { BitVector_Address address; BitVector_Handle handle; BitVector_Object reference; charptr pointer; BV_ErrCode code; N_int size; if ( BIT_VECTOR_SCALAR(bits,N_int,size) ) { if ( BIT_VECTOR_STRING(string,pointer) ) { if ((address = BitVector_Create(size,false)) != NULL) { if ((code = BitVector_from_Dec(address,pointer))) { BitVector_Destroy(address); BIT_VECTOR_EXCEPTION(code); } else { handle = newSViv((IV)address); reference = sv_bless(sv_2mortal(newRV(handle)), BIT_VECTOR_STASH); SvREFCNT_dec(handle); SvREADONLY_on(handle); PUSHs(reference); } } else BIT_VECTOR_MEMORY_ERROR; } else BIT_VECTOR_STRING_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } void BitVector_new_Enum(class,bits,string) BitVector_Object class BitVector_Scalar bits BitVector_Scalar string PPCODE: { BitVector_Address address; BitVector_Handle handle; BitVector_Object reference; charptr pointer; BV_ErrCode code; N_int size; if ( BIT_VECTOR_SCALAR(bits,N_int,size) ) { if ( BIT_VECTOR_STRING(string,pointer) ) { if ((address = BitVector_Create(size,false)) != NULL) { if ((code = BitVector_from_Enum(address,pointer))) { BitVector_Destroy(address); BIT_VECTOR_EXCEPTION(code); } else { handle = newSViv((IV)address); reference = sv_bless(sv_2mortal(newRV(handle)), BIT_VECTOR_STASH); SvREFCNT_dec(handle); SvREADONLY_on(handle); PUSHs(reference); } } else BIT_VECTOR_MEMORY_ERROR; } else BIT_VECTOR_STRING_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } void BitVector_Shadow(reference) BitVector_Object reference PPCODE: { BitVector_Handle handle; BitVector_Address address; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ((address = BitVector_Shadow(address)) != NULL) { handle = newSViv((IV)address); reference = sv_bless(sv_2mortal(newRV(handle)), BIT_VECTOR_STASH); SvREFCNT_dec(handle); SvREADONLY_on(handle); PUSHs(reference); } else BIT_VECTOR_MEMORY_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Clone(reference) BitVector_Object reference PPCODE: { BitVector_Handle handle; BitVector_Address address; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ((address = BitVector_Clone(address)) != NULL) { handle = newSViv((IV)address); reference = sv_bless(sv_2mortal(newRV(handle)), BIT_VECTOR_STASH); SvREFCNT_dec(handle); SvREADONLY_on(handle); PUSHs(reference); } else BIT_VECTOR_MEMORY_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Concat(Xref,Yref) BitVector_Object Xref BitVector_Object Yref PPCODE: { BitVector_Handle Xhdl; BitVector_Address Xadr; BitVector_Handle Yhdl; BitVector_Address Yadr; BitVector_Object reference; BitVector_Handle handle; BitVector_Address address; if ( BIT_VECTOR_OBJECT(Xref,Xhdl,Xadr) && BIT_VECTOR_OBJECT(Yref,Yhdl,Yadr) ) { if ((address = BitVector_Concat(Xadr,Yadr)) != NULL) { handle = newSViv((IV)address); reference = sv_bless(sv_2mortal(newRV(handle)), BIT_VECTOR_STASH); SvREFCNT_dec(handle); SvREADONLY_on(handle); PUSHs(reference); } else BIT_VECTOR_MEMORY_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Concat_List(...) PPCODE: { BitVector_Object Xref; BitVector_Handle Xhdl; BitVector_Address Xadr; BitVector_Object reference; BitVector_Handle handle; BitVector_Address address; N_int offset; N_int bits; I32 index; bits = 0; index = items; while (index-- > 0) { Xref = ST(index); if ( BIT_VECTOR_OBJECT(Xref,Xhdl,Xadr) ) { bits += BV_BITS_(Xadr); } else if ((index != 0) or SvROK(Xref)) BIT_VECTOR_OBJECT_ERROR; } if ((address = BitVector_Create(bits,false)) != NULL) { offset = 0; index = items; while (index-- > 0) { Xref = ST(index); if ( BIT_VECTOR_OBJECT(Xref,Xhdl,Xadr) ) { if ((bits = BV_BITS_(Xadr)) > 0) { BitVector_Interval_Copy(address,Xadr,offset,0,bits); offset += bits; } } else if ((index != 0) or SvROK(Xref)) BIT_VECTOR_OBJECT_ERROR; } handle = newSViv((IV)address); reference = sv_bless(sv_2mortal(newRV(handle)), BIT_VECTOR_STASH); SvREFCNT_dec(handle); SvREADONLY_on(handle); PUSHs(reference); } else BIT_VECTOR_MEMORY_ERROR; } N_int BitVector_Size(reference) BitVector_Object reference CODE: { BitVector_Handle handle; BitVector_Address address; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { RETVAL = BV_BITS_(address); } else BIT_VECTOR_OBJECT_ERROR; } OUTPUT: RETVAL void BitVector_Resize(reference,bits) BitVector_Object reference BitVector_Scalar bits CODE: { BitVector_Handle handle; BitVector_Address address; N_int size; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_SCALAR(bits,N_int,size) ) { address = BitVector_Resize(address,size); SvREADONLY_off(handle); sv_setiv(handle,(IV)address); SvREADONLY_on(handle); if (address == NULL) BIT_VECTOR_MEMORY_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Unfake(reference,bits) BitVector_Object reference BitVector_Scalar bits CODE: { BitVector_Handle handle; BitVector_Address address; N_int size; if ( BIT_VECTOR_FAKE_OBJECT(reference,handle) ) { if ( BIT_VECTOR_SCALAR(bits,N_int,size) ) { address = BitVector_Create(size,true); sv_setiv(handle,(IV)address); SvREADONLY_on(handle); if (address == NULL) BIT_VECTOR_MEMORY_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_DESTROY(reference) BitVector_Object reference CODE: { BitVector_Handle handle; BitVector_Address address; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { BitVector_Destroy(address); SvREADONLY_off(handle); sv_setiv(handle,(IV)NULL); SvREADONLY_on(handle); } /* else BIT_VECTOR_OBJECT_ERROR; */ } void BitVector_Copy(Xref,Yref) BitVector_Object Xref BitVector_Object Yref CODE: { BitVector_Handle Xhdl; BitVector_Address Xadr; BitVector_Handle Yhdl; BitVector_Address Yadr; if ( BIT_VECTOR_OBJECT(Xref,Xhdl,Xadr) && BIT_VECTOR_OBJECT(Yref,Yhdl,Yadr) ) { BitVector_Copy(Xadr,Yadr); } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Empty(reference) BitVector_Object reference CODE: { BitVector_Handle handle; BitVector_Address address; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { BitVector_Empty(address); } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Fill(reference) BitVector_Object reference CODE: { BitVector_Handle handle; BitVector_Address address; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { BitVector_Fill(address); } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Flip(reference) BitVector_Object reference CODE: { BitVector_Handle handle; BitVector_Address address; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { BitVector_Flip(address); } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Primes(reference) BitVector_Object reference CODE: { BitVector_Handle handle; BitVector_Address address; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { BitVector_Primes(address); } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Reverse(Xref,Yref) BitVector_Object Xref BitVector_Object Yref CODE: { BitVector_Handle Xhdl; BitVector_Address Xadr; BitVector_Handle Yhdl; BitVector_Address Yadr; if ( BIT_VECTOR_OBJECT(Xref,Xhdl,Xadr) && BIT_VECTOR_OBJECT(Yref,Yhdl,Yadr) ) { if (BV_BITS_(Xadr) == BV_BITS_(Yadr)) { BitVector_Reverse(Xadr,Yadr); } else BIT_VECTOR_SIZE_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Interval_Empty(reference,min,max) BitVector_Object reference BitVector_Scalar min BitVector_Scalar max ALIAS: Empty_Interval = 2 CODE: { BitVector_Handle handle; BitVector_Address address; N_int lower; N_int upper; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_SCALAR(min,N_int,lower) && BIT_VECTOR_SCALAR(max,N_int,upper) ) { if (lower >= BV_BITS_(address)) BIT_VECTOR_MIN_ERROR; else if (upper >= BV_BITS_(address)) BIT_VECTOR_MAX_ERROR; else if (lower > upper) BIT_VECTOR_ORDER_ERROR; else BitVector_Interval_Empty(address,lower,upper); } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Interval_Fill(reference,min,max) BitVector_Object reference BitVector_Scalar min BitVector_Scalar max ALIAS: Fill_Interval = 2 CODE: { BitVector_Handle handle; BitVector_Address address; N_int lower; N_int upper; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_SCALAR(min,N_int,lower) && BIT_VECTOR_SCALAR(max,N_int,upper) ) { if (lower >= BV_BITS_(address)) BIT_VECTOR_MIN_ERROR; else if (upper >= BV_BITS_(address)) BIT_VECTOR_MAX_ERROR; else if (lower > upper) BIT_VECTOR_ORDER_ERROR; else BitVector_Interval_Fill(address,lower,upper); } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Interval_Flip(reference,min,max) BitVector_Object reference BitVector_Scalar min BitVector_Scalar max ALIAS: Flip_Interval = 2 CODE: { BitVector_Handle handle; BitVector_Address address; N_int lower; N_int upper; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_SCALAR(min,N_int,lower) && BIT_VECTOR_SCALAR(max,N_int,upper) ) { if (lower >= BV_BITS_(address)) BIT_VECTOR_MIN_ERROR; else if (upper >= BV_BITS_(address)) BIT_VECTOR_MAX_ERROR; else if (lower > upper) BIT_VECTOR_ORDER_ERROR; else BitVector_Interval_Flip(address,lower,upper); } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Interval_Reverse(reference,min,max) BitVector_Object reference BitVector_Scalar min BitVector_Scalar max CODE: { BitVector_Handle handle; BitVector_Address address; N_int lower; N_int upper; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_SCALAR(min,N_int,lower) && BIT_VECTOR_SCALAR(max,N_int,upper) ) { if (lower >= BV_BITS_(address)) BIT_VECTOR_MIN_ERROR; else if (upper >= BV_BITS_(address)) BIT_VECTOR_MAX_ERROR; else if (lower > upper) BIT_VECTOR_ORDER_ERROR; else BitVector_Interval_Reverse(address,lower,upper); } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Interval_Scan_inc(reference,start) BitVector_Object reference BitVector_Scalar start PPCODE: { BitVector_Handle handle; BitVector_Address address; N_int first; N_int min; N_int max; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_SCALAR(start,N_int,first) ) { if (first < BV_BITS_(address)) { if ( BitVector_interval_scan_inc(address,first,&min,&max) ) { EXTEND(sp,2); PUSHs(sv_2mortal(newSViv((IV)min))); PUSHs(sv_2mortal(newSViv((IV)max))); } /* else return empty list */ } else BIT_VECTOR_START_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Interval_Scan_dec(reference,start) BitVector_Object reference BitVector_Scalar start PPCODE: { BitVector_Handle handle; BitVector_Address address; N_int first; N_int min; N_int max; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_SCALAR(start,N_int,first) ) { if (first < BV_BITS_(address)) { if ( BitVector_interval_scan_dec(address,first,&min,&max) ) { EXTEND(sp,2); PUSHs(sv_2mortal(newSViv((IV)min))); PUSHs(sv_2mortal(newSViv((IV)max))); } /* else return empty list */ } else BIT_VECTOR_START_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Interval_Copy(Xref,Yref,Xoffset,Yoffset,length) BitVector_Object Xref BitVector_Object Yref BitVector_Scalar Xoffset BitVector_Scalar Yoffset BitVector_Scalar length CODE: { BitVector_Handle Xhdl; BitVector_Address Xadr; BitVector_Handle Yhdl; BitVector_Address Yadr; N_int Xoff; N_int Yoff; N_int len; if ( BIT_VECTOR_OBJECT(Xref,Xhdl,Xadr) && BIT_VECTOR_OBJECT(Yref,Yhdl,Yadr) ) { if ( BIT_VECTOR_SCALAR(Xoffset,N_int,Xoff) && BIT_VECTOR_SCALAR(Yoffset,N_int,Yoff) && BIT_VECTOR_SCALAR(length, N_int,len) ) { if ((Xoff < BV_BITS_(Xadr)) and (Yoff < BV_BITS_(Yadr))) { if (len > 0) BitVector_Interval_Copy(Xadr,Yadr,Xoff,Yoff,len); } else BIT_VECTOR_OFFSET_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Interval_Substitute(Xref,Yref,Xoffset,Xlength,Yoffset,Ylength) BitVector_Object Xref BitVector_Object Yref BitVector_Scalar Xoffset BitVector_Scalar Xlength BitVector_Scalar Yoffset BitVector_Scalar Ylength CODE: { BitVector_Handle Xhdl; BitVector_Address Xadr; BitVector_Handle Yhdl; BitVector_Address Yadr; N_int Xoff; N_int Xlen; N_int Yoff; N_int Ylen; if ( BIT_VECTOR_OBJECT(Xref,Xhdl,Xadr) && BIT_VECTOR_OBJECT(Yref,Yhdl,Yadr) ) { if ( BIT_VECTOR_SCALAR(Xoffset,N_int,Xoff) && BIT_VECTOR_SCALAR(Xlength,N_int,Xlen) && BIT_VECTOR_SCALAR(Yoffset,N_int,Yoff) && BIT_VECTOR_SCALAR(Ylength,N_int,Ylen) ) { if ((Xoff <= BV_BITS_(Xadr)) and (Yoff <= BV_BITS_(Yadr))) { Xadr = BitVector_Interval_Substitute(Xadr,Yadr,Xoff,Xlen,Yoff,Ylen); SvREADONLY_off(Xhdl); sv_setiv(Xhdl,(IV)Xadr); SvREADONLY_on(Xhdl); if (Xadr == NULL) BIT_VECTOR_MEMORY_ERROR; } else BIT_VECTOR_OFFSET_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } boolean BitVector_is_empty(reference) BitVector_Object reference CODE: { BitVector_Handle handle; BitVector_Address address; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { RETVAL = BitVector_is_empty(address); } else BIT_VECTOR_OBJECT_ERROR; } OUTPUT: RETVAL boolean BitVector_is_full(reference) BitVector_Object reference CODE: { BitVector_Handle handle; BitVector_Address address; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { RETVAL = BitVector_is_full(address); } else BIT_VECTOR_OBJECT_ERROR; } OUTPUT: RETVAL boolean BitVector_equal(Xref,Yref) BitVector_Object Xref BitVector_Object Yref CODE: { BitVector_Handle Xhdl; BitVector_Address Xadr; BitVector_Handle Yhdl; BitVector_Address Yadr; if ( BIT_VECTOR_OBJECT(Xref,Xhdl,Xadr) && BIT_VECTOR_OBJECT(Yref,Yhdl,Yadr) ) { if (BV_BITS_(Xadr) == BV_BITS_(Yadr)) { RETVAL = BitVector_equal(Xadr,Yadr); } else BIT_VECTOR_SIZE_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } OUTPUT: RETVAL Z_int BitVector_Lexicompare(Xref,Yref) BitVector_Object Xref BitVector_Object Yref CODE: { BitVector_Handle Xhdl; BitVector_Address Xadr; BitVector_Handle Yhdl; BitVector_Address Yadr; if ( BIT_VECTOR_OBJECT(Xref,Xhdl,Xadr) && BIT_VECTOR_OBJECT(Yref,Yhdl,Yadr) ) { if (BV_BITS_(Xadr) == BV_BITS_(Yadr)) { RETVAL = BitVector_Lexicompare(Xadr,Yadr); } else BIT_VECTOR_SIZE_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } OUTPUT: RETVAL Z_int BitVector_Compare(Xref,Yref) BitVector_Object Xref BitVector_Object Yref CODE: { BitVector_Handle Xhdl; BitVector_Address Xadr; BitVector_Handle Yhdl; BitVector_Address Yadr; if ( BIT_VECTOR_OBJECT(Xref,Xhdl,Xadr) && BIT_VECTOR_OBJECT(Yref,Yhdl,Yadr) ) { if (BV_BITS_(Xadr) == BV_BITS_(Yadr)) { RETVAL = BitVector_Compare(Xadr,Yadr); } else BIT_VECTOR_SIZE_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } OUTPUT: RETVAL void BitVector_to_Hex(reference) BitVector_Object reference ALIAS: to_String = 2 PPCODE: { BitVector_Handle handle; BitVector_Address address; charptr string; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { string = BitVector_to_Hex(address); if (string != NULL) { EXTEND(sp,1); PUSHs(sv_2mortal(newSVpv((char *)string,0))); BitVector_Dispose(string); } else BIT_VECTOR_MEMORY_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_from_Hex(reference,string) BitVector_Object reference BitVector_Scalar string ALIAS: from_string = 2 CODE: { BitVector_Handle handle; BitVector_Address address; charptr pointer; BV_ErrCode code; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_STRING(string,pointer) ) { if ((code = BitVector_from_Hex(address,pointer))) BIT_VECTOR_EXCEPTION(code); } else BIT_VECTOR_STRING_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_to_Bin(reference) BitVector_Object reference PPCODE: { BitVector_Handle handle; BitVector_Address address; charptr string; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { string = BitVector_to_Bin(address); if (string != NULL) { EXTEND(sp,1); PUSHs(sv_2mortal(newSVpv((char *)string,0))); BitVector_Dispose(string); } else BIT_VECTOR_MEMORY_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_from_Bin(reference,string) BitVector_Object reference BitVector_Scalar string CODE: { BitVector_Handle handle; BitVector_Address address; charptr pointer; BV_ErrCode code; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_STRING(string,pointer) ) { if ((code = BitVector_from_Bin(address,pointer))) BIT_VECTOR_EXCEPTION(code); } else BIT_VECTOR_STRING_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_to_Dec(reference) BitVector_Object reference PPCODE: { BitVector_Handle handle; BitVector_Address address; charptr string; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { string = BitVector_to_Dec(address); if (string != NULL) { EXTEND(sp,1); PUSHs(sv_2mortal(newSVpv((char *)string,0))); BitVector_Dispose(string); } else BIT_VECTOR_MEMORY_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_from_Dec(reference,string) BitVector_Object reference BitVector_Scalar string CODE: { BitVector_Handle handle; BitVector_Address address; charptr pointer; BV_ErrCode code; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_STRING(string,pointer) ) { if ((code = BitVector_from_Dec(address,pointer))) BIT_VECTOR_EXCEPTION(code); } else BIT_VECTOR_STRING_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_to_Enum(reference) BitVector_Object reference ALIAS: to_ASCII = 2 PPCODE: { BitVector_Handle handle; BitVector_Address address; charptr string; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { string = BitVector_to_Enum(address); if (string != NULL) { EXTEND(sp,1); PUSHs(sv_2mortal(newSVpv((char *)string,0))); BitVector_Dispose(string); } else BIT_VECTOR_MEMORY_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_from_Enum(reference,string) BitVector_Object reference BitVector_Scalar string ALIAS: from_ASCII = 2 CODE: { BitVector_Handle handle; BitVector_Address address; charptr pointer; BV_ErrCode code; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_STRING(string,pointer) ) { if ((code = BitVector_from_Enum(address,pointer))) BIT_VECTOR_EXCEPTION(code); } else BIT_VECTOR_STRING_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Bit_Off(reference,index) BitVector_Object reference BitVector_Scalar index CODE: { BitVector_Handle handle; BitVector_Address address; N_int idx; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_SCALAR(index,N_int,idx) ) { if (idx < BV_BITS_(address)) { BitVector_Bit_Off(address,idx); } else BIT_VECTOR_INDEX_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Bit_On(reference,index) BitVector_Object reference BitVector_Scalar index CODE: { BitVector_Handle handle; BitVector_Address address; N_int idx; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_SCALAR(index,N_int,idx) ) { if (idx < BV_BITS_(address)) { BitVector_Bit_On(address,idx); } else BIT_VECTOR_INDEX_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } boolean BitVector_bit_flip(reference,index) BitVector_Object reference BitVector_Scalar index ALIAS: flip = 2 CODE: { BitVector_Handle handle; BitVector_Address address; N_int idx; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_SCALAR(index,N_int,idx) ) { if (idx < BV_BITS_(address)) { RETVAL = BitVector_bit_flip(address,idx); } else BIT_VECTOR_INDEX_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } OUTPUT: RETVAL boolean BitVector_bit_test(reference,index) BitVector_Object reference BitVector_Scalar index ALIAS: contains = 1 in = 2 CODE: { BitVector_Handle handle; BitVector_Address address; N_int idx; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_SCALAR(index,N_int,idx) ) { if (idx < BV_BITS_(address)) { RETVAL = BitVector_bit_test(address,idx); } else BIT_VECTOR_INDEX_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } OUTPUT: RETVAL void BitVector_Bit_Copy(reference,index,bit) BitVector_Object reference BitVector_Scalar index BitVector_Scalar bit CODE: { BitVector_Handle handle; BitVector_Address address; N_int idx; boolean b; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_SCALAR(index,N_int,idx) && BIT_VECTOR_SCALAR(bit,boolean,b) ) { if (idx < BV_BITS_(address)) { BitVector_Bit_Copy(address,idx,b); } else BIT_VECTOR_INDEX_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_LSB(reference,bit) BitVector_Object reference BitVector_Scalar bit CODE: { BitVector_Handle handle; BitVector_Address address; boolean b; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_SCALAR(bit,boolean,b) ) { BitVector_LSB(address,b); } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_MSB(reference,bit) BitVector_Object reference BitVector_Scalar bit CODE: { BitVector_Handle handle; BitVector_Address address; boolean b; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_SCALAR(bit,boolean,b) ) { BitVector_MSB(address,b); } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } boolean BitVector_lsb(reference) BitVector_Object reference CODE: { BitVector_Handle handle; BitVector_Address address; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { RETVAL = BitVector_lsb_(address); } else BIT_VECTOR_OBJECT_ERROR; } OUTPUT: RETVAL boolean BitVector_msb(reference) BitVector_Object reference CODE: { BitVector_Handle handle; BitVector_Address address; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { RETVAL = BitVector_msb_(address); } else BIT_VECTOR_OBJECT_ERROR; } OUTPUT: RETVAL boolean BitVector_rotate_left(reference) BitVector_Object reference CODE: { BitVector_Handle handle; BitVector_Address address; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { RETVAL = BitVector_rotate_left(address); } else BIT_VECTOR_OBJECT_ERROR; } OUTPUT: RETVAL boolean BitVector_rotate_right(reference) BitVector_Object reference CODE: { BitVector_Handle handle; BitVector_Address address; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { RETVAL = BitVector_rotate_right(address); } else BIT_VECTOR_OBJECT_ERROR; } OUTPUT: RETVAL boolean BitVector_shift_left(reference,carry) BitVector_Object reference BitVector_Scalar carry CODE: { BitVector_Handle handle; BitVector_Address address; boolean c; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_SCALAR(carry,boolean,c) ) { RETVAL = BitVector_shift_left(address,c); } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } OUTPUT: RETVAL boolean BitVector_shift_right(reference,carry) BitVector_Object reference BitVector_Scalar carry CODE: { BitVector_Handle handle; BitVector_Address address; boolean c; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_SCALAR(carry,boolean,c) ) { RETVAL = BitVector_shift_right(address,c); } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } OUTPUT: RETVAL void BitVector_Move_Left(reference,bits) BitVector_Object reference BitVector_Scalar bits CODE: { BitVector_Handle handle; BitVector_Address address; N_int cnt; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_SCALAR(bits,N_int,cnt) ) { BitVector_Move_Left(address,cnt); } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Move_Right(reference,bits) BitVector_Object reference BitVector_Scalar bits CODE: { BitVector_Handle handle; BitVector_Address address; N_int cnt; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_SCALAR(bits,N_int,cnt) ) { BitVector_Move_Right(address,cnt); } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Insert(reference,offset,count) BitVector_Object reference BitVector_Scalar offset BitVector_Scalar count CODE: { BitVector_Handle handle; BitVector_Address address; N_int off; N_int cnt; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_SCALAR(offset,N_int,off) && BIT_VECTOR_SCALAR(count,N_int,cnt) ) { if (off < BV_BITS_(address)) { BitVector_Insert(address,off,cnt,true); } else BIT_VECTOR_OFFSET_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Delete(reference,offset,count) BitVector_Object reference BitVector_Scalar offset BitVector_Scalar count CODE: { BitVector_Handle handle; BitVector_Address address; N_int off; N_int cnt; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_SCALAR(offset,N_int,off) && BIT_VECTOR_SCALAR(count,N_int,cnt) ) { if (off < BV_BITS_(address)) { BitVector_Delete(address,off,cnt,true); } else BIT_VECTOR_OFFSET_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } boolean BitVector_increment(reference) BitVector_Object reference CODE: { BitVector_Handle handle; BitVector_Address address; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { RETVAL = BitVector_increment(address); } else BIT_VECTOR_OBJECT_ERROR; } OUTPUT: RETVAL boolean BitVector_decrement(reference) BitVector_Object reference CODE: { BitVector_Handle handle; BitVector_Address address; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { RETVAL = BitVector_decrement(address); } else BIT_VECTOR_OBJECT_ERROR; } OUTPUT: RETVAL void BitVector_add(Xref,Yref,Zref,carry) BitVector_Object Xref BitVector_Object Yref BitVector_Object Zref BitVector_Scalar carry PPCODE: { BitVector_Handle Xhdl; BitVector_Address Xadr; BitVector_Handle Yhdl; BitVector_Address Yadr; BitVector_Handle Zhdl; BitVector_Address Zadr; boolean c; boolean v; if ( BIT_VECTOR_OBJECT(Xref,Xhdl,Xadr) && BIT_VECTOR_OBJECT(Yref,Yhdl,Yadr) && BIT_VECTOR_OBJECT(Zref,Zhdl,Zadr) ) { if ( BIT_VECTOR_SCALAR(carry,boolean,c) ) { if ((BV_BITS_(Xadr) == BV_BITS_(Yadr)) and (BV_BITS_(Xadr) == BV_BITS_(Zadr))) { v = BitVector_compute(Xadr,Yadr,Zadr,false,&c); if (GIMME_V == G_ARRAY) { EXTEND(sp,2); PUSHs(sv_2mortal(newSViv((IV)c))); PUSHs(sv_2mortal(newSViv((IV)v))); } else { EXTEND(sp,1); PUSHs(sv_2mortal(newSViv((IV)c))); } } else BIT_VECTOR_SIZE_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_subtract(Xref,Yref,Zref,carry) BitVector_Object Xref BitVector_Object Yref BitVector_Object Zref BitVector_Scalar carry ALIAS: sub = 2 PPCODE: { BitVector_Handle Xhdl; BitVector_Address Xadr; BitVector_Handle Yhdl; BitVector_Address Yadr; BitVector_Handle Zhdl; BitVector_Address Zadr; boolean c; boolean v; if ( BIT_VECTOR_OBJECT(Xref,Xhdl,Xadr) && BIT_VECTOR_OBJECT(Yref,Yhdl,Yadr) && BIT_VECTOR_OBJECT(Zref,Zhdl,Zadr) ) { if ( BIT_VECTOR_SCALAR(carry,boolean,c) ) { if ((BV_BITS_(Xadr) == BV_BITS_(Yadr)) and (BV_BITS_(Xadr) == BV_BITS_(Zadr))) { v = BitVector_compute(Xadr,Yadr,Zadr,true,&c); if (GIMME_V == G_ARRAY) { EXTEND(sp,2); PUSHs(sv_2mortal(newSViv((IV)c))); PUSHs(sv_2mortal(newSViv((IV)v))); } else { EXTEND(sp,1); PUSHs(sv_2mortal(newSViv((IV)c))); } } else BIT_VECTOR_SIZE_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } boolean BitVector_inc(Xref,Yref) BitVector_Object Xref BitVector_Object Yref CODE: { BitVector_Handle Xhdl; BitVector_Address Xadr; BitVector_Handle Yhdl; BitVector_Address Yadr; boolean c = true; if ( BIT_VECTOR_OBJECT(Xref,Xhdl,Xadr) && BIT_VECTOR_OBJECT(Yref,Yhdl,Yadr) ) { if (BV_BITS_(Xadr) == BV_BITS_(Yadr)) { RETVAL = BitVector_compute(Xadr,Yadr,NULL,false,&c); } else BIT_VECTOR_SIZE_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } OUTPUT: RETVAL boolean BitVector_dec(Xref,Yref) BitVector_Object Xref BitVector_Object Yref CODE: { BitVector_Handle Xhdl; BitVector_Address Xadr; BitVector_Handle Yhdl; BitVector_Address Yadr; boolean c = true; if ( BIT_VECTOR_OBJECT(Xref,Xhdl,Xadr) && BIT_VECTOR_OBJECT(Yref,Yhdl,Yadr) ) { if (BV_BITS_(Xadr) == BV_BITS_(Yadr)) { RETVAL = BitVector_compute(Xadr,Yadr,NULL,true,&c); } else BIT_VECTOR_SIZE_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } OUTPUT: RETVAL void BitVector_Negate(Xref,Yref) BitVector_Object Xref BitVector_Object Yref ALIAS: Neg = 1 CODE: { BitVector_Handle Xhdl; BitVector_Address Xadr; BitVector_Handle Yhdl; BitVector_Address Yadr; if ( BIT_VECTOR_OBJECT(Xref,Xhdl,Xadr) && BIT_VECTOR_OBJECT(Yref,Yhdl,Yadr) ) { if (BV_BITS_(Xadr) == BV_BITS_(Yadr)) { BitVector_Negate(Xadr,Yadr); } else BIT_VECTOR_SIZE_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Absolute(Xref,Yref) BitVector_Object Xref BitVector_Object Yref ALIAS: Abs = 1 CODE: { BitVector_Handle Xhdl; BitVector_Address Xadr; BitVector_Handle Yhdl; BitVector_Address Yadr; if ( BIT_VECTOR_OBJECT(Xref,Xhdl,Xadr) && BIT_VECTOR_OBJECT(Yref,Yhdl,Yadr) ) { if (BV_BITS_(Xadr) == BV_BITS_(Yadr)) { BitVector_Absolute(Xadr,Yadr); } else BIT_VECTOR_SIZE_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } Z_int BitVector_Sign(reference) BitVector_Object reference CODE: { BitVector_Handle handle; BitVector_Address address; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { RETVAL = BitVector_Sign(address); } else BIT_VECTOR_OBJECT_ERROR; } OUTPUT: RETVAL void BitVector_Multiply(Xref,Yref,Zref) BitVector_Object Xref BitVector_Object Yref BitVector_Object Zref CODE: { BitVector_Handle Xhdl; BitVector_Address Xadr; BitVector_Handle Yhdl; BitVector_Address Yadr; BitVector_Handle Zhdl; BitVector_Address Zadr; BV_ErrCode code; if ( BIT_VECTOR_OBJECT(Xref,Xhdl,Xadr) && BIT_VECTOR_OBJECT(Yref,Yhdl,Yadr) && BIT_VECTOR_OBJECT(Zref,Zhdl,Zadr) ) { if ((BV_BITS_(Xadr) >= BV_BITS_(Yadr)) and (BV_BITS_(Yadr) == BV_BITS_(Zadr))) { if ((code = BitVector_Multiply(Xadr,Yadr,Zadr))) BIT_VECTOR_EXCEPTION(code); } else BIT_VECTOR_SIZE_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Divide(Qref,Xref,Yref,Rref) BitVector_Object Qref BitVector_Object Xref BitVector_Object Yref BitVector_Object Rref CODE: { BitVector_Handle Qhdl; BitVector_Address Qadr; BitVector_Handle Xhdl; BitVector_Address Xadr; BitVector_Handle Yhdl; BitVector_Address Yadr; BitVector_Handle Rhdl; BitVector_Address Radr; BV_ErrCode code; if ( BIT_VECTOR_OBJECT(Qref,Qhdl,Qadr) && BIT_VECTOR_OBJECT(Xref,Xhdl,Xadr) && BIT_VECTOR_OBJECT(Yref,Yhdl,Yadr) && BIT_VECTOR_OBJECT(Rref,Rhdl,Radr) ) { if ((code = BitVector_Divide(Qadr,Xadr,Yadr,Radr))) BIT_VECTOR_EXCEPTION(code); } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_GCD(...) CODE: { BitVector_Object Uref; BitVector_Handle Uhdl; BitVector_Address Uadr; BitVector_Object Vref; BitVector_Handle Vhdl; BitVector_Address Vadr; BitVector_Object Wref; BitVector_Handle Whdl; BitVector_Address Wadr; BitVector_Object Xref; BitVector_Handle Xhdl; BitVector_Address Xadr; BitVector_Object Yref; BitVector_Handle Yhdl; BitVector_Address Yadr; BV_ErrCode code; if (items == 3) { Uref = ST(0); Xref = ST(1); Yref = ST(2); if ( BIT_VECTOR_OBJECT(Uref,Uhdl,Uadr) && BIT_VECTOR_OBJECT(Xref,Xhdl,Xadr) && BIT_VECTOR_OBJECT(Yref,Yhdl,Yadr) ) { if ((code = BitVector_GCD(Uadr,Xadr,Yadr))) BIT_VECTOR_EXCEPTION(code); } else BIT_VECTOR_OBJECT_ERROR; } else if (items == 5) { Uref = ST(0); Vref = ST(1); Wref = ST(2); Xref = ST(3); Yref = ST(4); if ( BIT_VECTOR_OBJECT(Uref,Uhdl,Uadr) && BIT_VECTOR_OBJECT(Vref,Vhdl,Vadr) && BIT_VECTOR_OBJECT(Wref,Whdl,Wadr) && BIT_VECTOR_OBJECT(Xref,Xhdl,Xadr) && BIT_VECTOR_OBJECT(Yref,Yhdl,Yadr) ) { if ((code = BitVector_GCD2(Uadr,Vadr,Wadr,Xadr,Yadr))) BIT_VECTOR_EXCEPTION(code); } else BIT_VECTOR_OBJECT_ERROR; } else croak("Usage: %s(Uref[,Vref,Wref],Xref,Yref)", GvNAME(CvGV(cv))); } void BitVector_Power(Xref,Yref,Zref) BitVector_Object Xref BitVector_Object Yref BitVector_Object Zref CODE: { BitVector_Handle Xhdl; BitVector_Address Xadr; BitVector_Handle Yhdl; BitVector_Address Yadr; BitVector_Handle Zhdl; BitVector_Address Zadr; BV_ErrCode code; if ( BIT_VECTOR_OBJECT(Xref,Xhdl,Xadr) && BIT_VECTOR_OBJECT(Yref,Yhdl,Yadr) && BIT_VECTOR_OBJECT(Zref,Zhdl,Zadr) ) { if ((code = BitVector_Power(Xadr,Yadr,Zadr))) BIT_VECTOR_EXCEPTION(code); } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Block_Store(reference,buffer) BitVector_Object reference BitVector_Scalar buffer CODE: { BitVector_Handle handle; BitVector_Address address; charptr string; N_int length; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_BUFFER(buffer,string,length) ) { BitVector_Block_Store(address,string,length); } else BIT_VECTOR_STRING_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Block_Read(reference) BitVector_Object reference PPCODE: { BitVector_Handle handle; BitVector_Address address; charptr string; N_int length; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { string = BitVector_Block_Read(address,&length); if (string != NULL) { EXTEND(sp,1); PUSHs(sv_2mortal(newSVpv((char *)string,length))); BitVector_Dispose(string); } else BIT_VECTOR_MEMORY_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } N_int BitVector_Word_Size(reference) BitVector_Object reference CODE: { BitVector_Handle handle; BitVector_Address address; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { RETVAL = BV_SIZE_(address); } else BIT_VECTOR_OBJECT_ERROR; } OUTPUT: RETVAL void BitVector_Word_Store(reference,offset,value) BitVector_Object reference BitVector_Scalar offset BitVector_Scalar value CODE: { BitVector_Handle handle; BitVector_Address address; N_int off; N_int val; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_SCALAR(offset,N_int,off) && BIT_VECTOR_SCALAR(value,N_int,val) ) { if (off < BV_SIZE_(address)) { BitVector_Word_Store(address,off,val); } else BIT_VECTOR_OFFSET_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } N_int BitVector_Word_Read(reference,offset) BitVector_Object reference BitVector_Scalar offset CODE: { BitVector_Handle handle; BitVector_Address address; N_int off; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_SCALAR(offset,N_int,off) ) { if (off < BV_SIZE_(address)) { RETVAL = BitVector_Word_Read(address,off); } else BIT_VECTOR_OFFSET_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } OUTPUT: RETVAL void BitVector_Word_List_Store(reference,...) BitVector_Object reference CODE: { BitVector_Handle handle; BitVector_Address address; BitVector_Scalar scalar; N_int offset; N_int value; N_int size; I32 index; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { size = BV_SIZE_(address); for ( offset = 0, index = 1; ((offset < size) and (index < items)); offset++, index++ ) { scalar = ST(index); if ( BIT_VECTOR_SCALAR(scalar,N_int,value) ) { BitVector_Word_Store(address,offset,value); } else BIT_VECTOR_SCALAR_ERROR; } for ( ; (offset < size); offset++ ) { BitVector_Word_Store(address,offset,0); } } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Word_List_Read(reference) BitVector_Object reference PPCODE: { BitVector_Handle handle; BitVector_Address address; N_int offset; N_int value; N_int size; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { size = BV_SIZE_(address); EXTEND(sp,(int)size); for ( offset = 0; (offset < size); offset++ ) { value = BitVector_Word_Read(address,offset); PUSHs(sv_2mortal(newSViv((IV)value))); } } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Word_Insert(reference,offset,count) BitVector_Object reference BitVector_Scalar offset BitVector_Scalar count CODE: { BitVector_Handle handle; BitVector_Address address; N_int off; N_int cnt; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_SCALAR(offset,N_int,off) && BIT_VECTOR_SCALAR(count,N_int,cnt) ) { if (off < BV_SIZE_(address)) { BitVector_Word_Insert(address,off,cnt,true); } else BIT_VECTOR_OFFSET_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Word_Delete(reference,offset,count) BitVector_Object reference BitVector_Scalar offset BitVector_Scalar count CODE: { BitVector_Handle handle; BitVector_Address address; N_int off; N_int cnt; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_SCALAR(offset,N_int,off) && BIT_VECTOR_SCALAR(count,N_int,cnt) ) { if (off < BV_SIZE_(address)) { BitVector_Word_Delete(address,off,cnt,true); } else BIT_VECTOR_OFFSET_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Chunk_Store(reference,chunksize,offset,value) BitVector_Object reference BitVector_Scalar chunksize BitVector_Scalar offset BitVector_Scalar value CODE: { BitVector_Handle handle; BitVector_Address address; N_int bits; N_int off; N_long val; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_SCALAR(chunksize,N_int,bits) && BIT_VECTOR_SCALAR(offset,N_int,off) && BIT_VECTOR_SCALAR(value,N_long,val) ) { if ((bits > 0) and (bits <= BitVector_Long_Bits())) { if (off < BV_BITS_(address)) { BitVector_Chunk_Store(address,bits,off,val); } else BIT_VECTOR_OFFSET_ERROR; } else BIT_VECTOR_CHUNK_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } N_long BitVector_Chunk_Read(reference,chunksize,offset) BitVector_Object reference BitVector_Scalar chunksize BitVector_Scalar offset CODE: { BitVector_Handle handle; BitVector_Address address; N_int bits; N_int off; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_SCALAR(chunksize,N_int,bits) && BIT_VECTOR_SCALAR(offset,N_int,off) ) { if ((bits > 0) and (bits <= BitVector_Long_Bits())) { if (off < BV_BITS_(address)) { RETVAL = BitVector_Chunk_Read(address,bits,off); } else BIT_VECTOR_OFFSET_ERROR; } else BIT_VECTOR_CHUNK_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } OUTPUT: RETVAL void BitVector_Chunk_List_Store(reference,chunksize,...) BitVector_Object reference BitVector_Scalar chunksize CODE: { BitVector_Handle handle; BitVector_Address address; BitVector_Scalar scalar; N_int chunkspan; N_long chunkmask; N_long mask; N_long chunk; N_long value; N_int chunkbits; N_int wordbits; N_int wordsize; N_int offset; N_int size; N_int bits; I32 index; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_SCALAR(chunksize,N_int,chunkspan) ) { if ((chunkspan > 0) and (chunkspan <= BitVector_Long_Bits())) { wordsize = BitVector_Word_Bits(); size = BV_SIZE_(address); chunkmask = ~((~0L << (chunkspan-1)) << 1); /* C bug work-around */ chunk = 0L; value = 0L; index = 2; offset = 0; wordbits = 0; chunkbits = 0; while (offset < size) { if ((chunkbits == 0) and (index < items)) { scalar = ST(index); if ( BIT_VECTOR_SCALAR(scalar,N_long,chunk) ) { chunk &= chunkmask; chunkbits = chunkspan; index++; } else BIT_VECTOR_SCALAR_ERROR; } bits = wordsize - wordbits; if (chunkbits <= bits) { chunk <<= wordbits; value |= chunk; wordbits += chunkbits; chunk = 0L; chunkbits = 0; } else { mask = ~(~0L << bits); mask &= chunk; mask <<= wordbits; value |= mask; wordbits += bits; chunk >>= bits; chunkbits -= bits; } if ((wordbits >= wordsize) or (index >= items)) { BitVector_Word_Store(address,offset,(N_int)value); value = 0L; wordbits = 0; offset++; } } } else BIT_VECTOR_CHUNK_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Chunk_List_Read(reference,chunksize) BitVector_Object reference BitVector_Scalar chunksize PPCODE: { BitVector_Handle handle; BitVector_Address address; N_int chunkspan; N_long chunk; N_long value; N_long mask; N_int chunkbits; N_int wordbits; N_int wordsize; N_int length; N_int index; N_int offset; N_int size; N_int bits; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_SCALAR(chunksize,N_int,chunkspan) ) { if ((chunkspan > 0) and (chunkspan <= BitVector_Long_Bits())) { wordsize = BitVector_Word_Bits(); bits = BV_BITS_(address); size = BV_SIZE_(address); length = (N_int) (bits / chunkspan); if ((length * chunkspan) < bits) length++; EXTEND(sp,(int)length); chunk = 0L; value = 0L; index = 0; offset = 0; wordbits = 0; chunkbits = 0; while (index < length) { if ((wordbits == 0) and (offset < size)) { value = (N_long) BitVector_Word_Read(address,offset); wordbits = wordsize; offset++; } bits = chunkspan - chunkbits; if (wordbits <= bits) { value <<= chunkbits; chunk |= value; chunkbits += wordbits; value = 0L; wordbits = 0; } else { mask = ~(~0L << bits); mask &= value; mask <<= chunkbits; chunk |= mask; chunkbits += bits; value >>= bits; wordbits -= bits; } if ((chunkbits >= chunkspan) or ((offset >= size) and (chunkbits > 0))) { PUSHs(sv_2mortal(newSViv((IV)chunk))); chunk = 0L; chunkbits = 0; index++; } } } else BIT_VECTOR_CHUNK_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Index_List_Remove(reference,...) BitVector_Object reference CODE: { BitVector_Handle handle; BitVector_Address address; BitVector_Scalar scalar; N_int value; N_int bits; I32 index; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { bits = BV_BITS_(address); for ( index = 1; index < items; index++ ) { scalar = ST(index); if ( BIT_VECTOR_SCALAR(scalar,N_int,value) ) { if (value < bits) { BitVector_Bit_Off(address,value); } else BIT_VECTOR_INDEX_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Index_List_Store(reference,...) BitVector_Object reference CODE: { BitVector_Handle handle; BitVector_Address address; BitVector_Scalar scalar; N_int value; N_int bits; I32 index; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { bits = BV_BITS_(address); for ( index = 1; index < items; index++ ) { scalar = ST(index); if ( BIT_VECTOR_SCALAR(scalar,N_int,value) ) { if (value < bits) { BitVector_Bit_On(address,value); } else BIT_VECTOR_INDEX_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } } else BIT_VECTOR_OBJECT_ERROR; } void BitVector_Index_List_Read(reference) BitVector_Object reference PPCODE: { BitVector_Handle handle; BitVector_Address address; N_int size; N_int bits; N_int norm; N_int base; N_int word; N_int index; N_int value; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { size = BV_SIZE_(address); bits = BitVector_Word_Bits(); norm = Set_Norm(address); if (norm > 0) { EXTEND(sp,(int)norm); for ( base = word = 0; word < size; word++, base += bits ) { index = base; value = BitVector_Word_Read(address,word); while (value) { if (value AND 0x0001) PUSHs(sv_2mortal(newSViv((IV)index))); value >>= 1; index++; } } } } else BIT_VECTOR_OBJECT_ERROR; } MODULE = Bit::Vector PACKAGE = Bit::Vector PREFIX = Set_ void Set_Union(Xref,Yref,Zref) BitVector_Object Xref BitVector_Object Yref BitVector_Object Zref ALIAS: Or = 1 CODE: { BitVector_Handle Xhdl; BitVector_Address Xadr; BitVector_Handle Yhdl; BitVector_Address Yadr; BitVector_Handle Zhdl; BitVector_Address Zadr; if ( BIT_VECTOR_OBJECT(Xref,Xhdl,Xadr) && BIT_VECTOR_OBJECT(Yref,Yhdl,Yadr) && BIT_VECTOR_OBJECT(Zref,Zhdl,Zadr) ) { if ((BV_BITS_(Xadr) == BV_BITS_(Yadr)) and (BV_BITS_(Xadr) == BV_BITS_(Zadr))) { Set_Union(Xadr,Yadr,Zadr); } else BIT_VECTOR_SET_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void Set_Intersection(Xref,Yref,Zref) BitVector_Object Xref BitVector_Object Yref BitVector_Object Zref ALIAS: And = 1 CODE: { BitVector_Handle Xhdl; BitVector_Address Xadr; BitVector_Handle Yhdl; BitVector_Address Yadr; BitVector_Handle Zhdl; BitVector_Address Zadr; if ( BIT_VECTOR_OBJECT(Xref,Xhdl,Xadr) && BIT_VECTOR_OBJECT(Yref,Yhdl,Yadr) && BIT_VECTOR_OBJECT(Zref,Zhdl,Zadr) ) { if ((BV_BITS_(Xadr) == BV_BITS_(Yadr)) and (BV_BITS_(Xadr) == BV_BITS_(Zadr))) { Set_Intersection(Xadr,Yadr,Zadr); } else BIT_VECTOR_SET_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void Set_Difference(Xref,Yref,Zref) BitVector_Object Xref BitVector_Object Yref BitVector_Object Zref ALIAS: AndNot = 1 CODE: { BitVector_Handle Xhdl; BitVector_Address Xadr; BitVector_Handle Yhdl; BitVector_Address Yadr; BitVector_Handle Zhdl; BitVector_Address Zadr; if ( BIT_VECTOR_OBJECT(Xref,Xhdl,Xadr) && BIT_VECTOR_OBJECT(Yref,Yhdl,Yadr) && BIT_VECTOR_OBJECT(Zref,Zhdl,Zadr) ) { if ((BV_BITS_(Xadr) == BV_BITS_(Yadr)) and (BV_BITS_(Xadr) == BV_BITS_(Zadr))) { Set_Difference(Xadr,Yadr,Zadr); } else BIT_VECTOR_SET_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void Set_ExclusiveOr(Xref,Yref,Zref) BitVector_Object Xref BitVector_Object Yref BitVector_Object Zref ALIAS: Xor = 1 CODE: { BitVector_Handle Xhdl; BitVector_Address Xadr; BitVector_Handle Yhdl; BitVector_Address Yadr; BitVector_Handle Zhdl; BitVector_Address Zadr; if ( BIT_VECTOR_OBJECT(Xref,Xhdl,Xadr) && BIT_VECTOR_OBJECT(Yref,Yhdl,Yadr) && BIT_VECTOR_OBJECT(Zref,Zhdl,Zadr) ) { if ((BV_BITS_(Xadr) == BV_BITS_(Yadr)) and (BV_BITS_(Xadr) == BV_BITS_(Zadr))) { Set_ExclusiveOr(Xadr,Yadr,Zadr); } else BIT_VECTOR_SET_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void Set_Complement(Xref,Yref) BitVector_Object Xref BitVector_Object Yref ALIAS: Not = 1 CODE: { BitVector_Handle Xhdl; BitVector_Address Xadr; BitVector_Handle Yhdl; BitVector_Address Yadr; if ( BIT_VECTOR_OBJECT(Xref,Xhdl,Xadr) && BIT_VECTOR_OBJECT(Yref,Yhdl,Yadr) ) { if (BV_BITS_(Xadr) == BV_BITS_(Yadr)) { Set_Complement(Xadr,Yadr); } else BIT_VECTOR_SET_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } boolean Set_subset(Xref,Yref) BitVector_Object Xref BitVector_Object Yref ALIAS: inclusion = 2 CODE: { BitVector_Handle Xhdl; BitVector_Address Xadr; BitVector_Handle Yhdl; BitVector_Address Yadr; if ( BIT_VECTOR_OBJECT(Xref,Xhdl,Xadr) && BIT_VECTOR_OBJECT(Yref,Yhdl,Yadr) ) { if (BV_BITS_(Xadr) == BV_BITS_(Yadr)) { RETVAL = Set_subset(Xadr,Yadr); } else BIT_VECTOR_SET_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } OUTPUT: RETVAL N_int Set_Norm(reference) BitVector_Object reference CODE: { BitVector_Handle handle; BitVector_Address address; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { RETVAL = Set_Norm(address); } else BIT_VECTOR_OBJECT_ERROR; } OUTPUT: RETVAL N_int Set_Norm2(reference) BitVector_Object reference CODE: { BitVector_Handle handle; BitVector_Address address; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { RETVAL = Set_Norm2(address); } else BIT_VECTOR_OBJECT_ERROR; } OUTPUT: RETVAL N_int Set_Norm3(reference) BitVector_Object reference CODE: { BitVector_Handle handle; BitVector_Address address; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { RETVAL = Set_Norm3(address); } else BIT_VECTOR_OBJECT_ERROR; } OUTPUT: RETVAL Z_long Set_Min(reference) BitVector_Object reference CODE: { BitVector_Handle handle; BitVector_Address address; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { RETVAL = Set_Min(address); } else BIT_VECTOR_OBJECT_ERROR; } OUTPUT: RETVAL Z_long Set_Max(reference) BitVector_Object reference CODE: { BitVector_Handle handle; BitVector_Address address; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { RETVAL = Set_Max(address); } else BIT_VECTOR_OBJECT_ERROR; } OUTPUT: RETVAL MODULE = Bit::Vector PACKAGE = Bit::Vector PREFIX = Matrix_ void Matrix_Multiplication(Xref,Xrows,Xcols,Yref,Yrows,Ycols,Zref,Zrows,Zcols) BitVector_Object Xref BitVector_Scalar Xrows BitVector_Scalar Xcols BitVector_Object Yref BitVector_Scalar Yrows BitVector_Scalar Ycols BitVector_Object Zref BitVector_Scalar Zrows BitVector_Scalar Zcols CODE: { BitVector_Handle Xhdl; BitVector_Address Xadr; BitVector_Handle Yhdl; BitVector_Address Yadr; BitVector_Handle Zhdl; BitVector_Address Zadr; N_int rowsX; N_int colsX; N_int rowsY; N_int colsY; N_int rowsZ; N_int colsZ; if ( BIT_VECTOR_OBJECT(Xref,Xhdl,Xadr) && BIT_VECTOR_OBJECT(Yref,Yhdl,Yadr) && BIT_VECTOR_OBJECT(Zref,Zhdl,Zadr) ) { if ( BIT_VECTOR_SCALAR(Xrows,N_int,rowsX) && BIT_VECTOR_SCALAR(Xcols,N_int,colsX) && BIT_VECTOR_SCALAR(Yrows,N_int,rowsY) && BIT_VECTOR_SCALAR(Ycols,N_int,colsY) && BIT_VECTOR_SCALAR(Zrows,N_int,rowsZ) && BIT_VECTOR_SCALAR(Zcols,N_int,colsZ) ) { if ((colsY == rowsZ) and (rowsX == rowsY) and (colsX == colsZ) and (BV_BITS_(Xadr) == rowsX*colsX) and (BV_BITS_(Yadr) == rowsY*colsY) and (BV_BITS_(Zadr) == rowsZ*colsZ)) { Matrix_Multiplication(Xadr,rowsX,colsX, Yadr,rowsY,colsY, Zadr,rowsZ,colsZ); } else BIT_VECTOR_MATRIX_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void Matrix_Product(Xref,Xrows,Xcols,Yref,Yrows,Ycols,Zref,Zrows,Zcols) BitVector_Object Xref BitVector_Scalar Xrows BitVector_Scalar Xcols BitVector_Object Yref BitVector_Scalar Yrows BitVector_Scalar Ycols BitVector_Object Zref BitVector_Scalar Zrows BitVector_Scalar Zcols CODE: { BitVector_Handle Xhdl; BitVector_Address Xadr; BitVector_Handle Yhdl; BitVector_Address Yadr; BitVector_Handle Zhdl; BitVector_Address Zadr; N_int rowsX; N_int colsX; N_int rowsY; N_int colsY; N_int rowsZ; N_int colsZ; if ( BIT_VECTOR_OBJECT(Xref,Xhdl,Xadr) && BIT_VECTOR_OBJECT(Yref,Yhdl,Yadr) && BIT_VECTOR_OBJECT(Zref,Zhdl,Zadr) ) { if ( BIT_VECTOR_SCALAR(Xrows,N_int,rowsX) && BIT_VECTOR_SCALAR(Xcols,N_int,colsX) && BIT_VECTOR_SCALAR(Yrows,N_int,rowsY) && BIT_VECTOR_SCALAR(Ycols,N_int,colsY) && BIT_VECTOR_SCALAR(Zrows,N_int,rowsZ) && BIT_VECTOR_SCALAR(Zcols,N_int,colsZ) ) { if ((colsY == rowsZ) and (rowsX == rowsY) and (colsX == colsZ) and (BV_BITS_(Xadr) == rowsX*colsX) and (BV_BITS_(Yadr) == rowsY*colsY) and (BV_BITS_(Zadr) == rowsZ*colsZ)) { Matrix_Product(Xadr,rowsX,colsX, Yadr,rowsY,colsY, Zadr,rowsZ,colsZ); } else BIT_VECTOR_MATRIX_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void Matrix_Closure(reference,rows,cols) BitVector_Object reference BitVector_Scalar rows BitVector_Scalar cols CODE: { BitVector_Handle handle; BitVector_Address address; N_int r; N_int c; if ( BIT_VECTOR_OBJECT(reference,handle,address) ) { if ( BIT_VECTOR_SCALAR(rows,N_int,r) && BIT_VECTOR_SCALAR(cols,N_int,c) ) { if (BV_BITS_(address) == r*c) { if (r == c) { Matrix_Closure(address,r,c); } else BIT_VECTOR_SHAPE_ERROR; } else BIT_VECTOR_MATRIX_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } void Matrix_Transpose(Xref,Xrows,Xcols,Yref,Yrows,Ycols) BitVector_Object Xref BitVector_Scalar Xrows BitVector_Scalar Xcols BitVector_Object Yref BitVector_Scalar Yrows BitVector_Scalar Ycols CODE: { BitVector_Handle Xhdl; BitVector_Address Xadr; BitVector_Handle Yhdl; BitVector_Address Yadr; N_int rowsX; N_int colsX; N_int rowsY; N_int colsY; if ( BIT_VECTOR_OBJECT(Xref,Xhdl,Xadr) && BIT_VECTOR_OBJECT(Yref,Yhdl,Yadr) ) { if ( BIT_VECTOR_SCALAR(Xrows,N_int,rowsX) && BIT_VECTOR_SCALAR(Xcols,N_int,colsX) && BIT_VECTOR_SCALAR(Yrows,N_int,rowsY) && BIT_VECTOR_SCALAR(Ycols,N_int,colsY) ) { if ((rowsX == colsY) and (colsX == rowsY) and (BV_BITS_(Xadr) == rowsX*colsX) and (BV_BITS_(Yadr) == rowsY*colsY)) { if ((Xadr != Yadr) or (rowsY == colsY)) { Matrix_Transpose(Xadr,rowsX,colsX, Yadr,rowsY,colsY); } else BIT_VECTOR_SHAPE_ERROR; } else BIT_VECTOR_MATRIX_ERROR; } else BIT_VECTOR_SCALAR_ERROR; } else BIT_VECTOR_OBJECT_ERROR; } Bit-Vector-7.4/README.txt000644 100660 100660 00000033575 12211373040 014120 0ustar00sbsb000000 000000 ===================================== Package "Bit::Vector" Version 7.4 ===================================== This package is available for download either from my web site at http://www.engelschall.com/u/sb/download/ or from any CPAN (= "Comprehensive Perl Archive Network") mirror server: http://www.perl.com/CPAN/authors/id/S/ST/STBEY/ Abstract: --------- Bit::Vector is an efficient C library which allows you to handle bit vectors, sets (of integers), "big integer arithmetic" and boolean matrices, all of arbitrary sizes. The library is efficient (in terms of algorithmical complexity) and therefore fast (in terms of execution speed) for instance through the widespread use of divide-and-conquer algorithms. The package also includes an object-oriented Perl module for accessing the C library from Perl, and optionally features overloaded operators for maximum ease of use. The C library can nevertheless be used stand-alone, without Perl. What's new in version 7.4: -------------------------- + Modified ToolBox.h to allow bit vectors with more than 2^32 bits What's new since version 6.5: ----------------------------- Object persistence: Since version 6.5, "Bit::Vector" objects can be serialized and de-serialized automatically with "Storable", out-of-the-box, without requiring any further user action for this to work. This is also true for nested data structures (since version 6.8). See the "Storable" documentation for more details. Legal issues: ------------- This package with all its parts is Copyright (c) 1995 - 2013 by Steffen Beyer. All rights reserved. This package is free software; you can use, modify and redistribute it under the same terms as Perl itself, i.e., under the terms of the "Artistic License" or the "GNU General Public License". The C library at the core of this Perl module can additionally be used, modified and redistributed under the terms of the "GNU Library General Public License". Please refer to the files "Artistic.txt", "GNU_GPL.txt" and "GNU_LGPL.txt" in this distribution, respectively, for details! Prerequisites: -------------- Perl version 5.000 or higher, and an ANSI C compiler. (!) ^^^^^^ Module "Carp::Clan" version 5.3 or higher. Optionally, module "Storable" version 2.21 or newer. Note that in order to compile Perl modules which contain C (and/or XS) code (such as this one), you always HAVE to use the very same compiler your Perl itself was compiled with. Many vendors nowadays ship their operating system already comprising a precompiled version of Perl. Many times the compilers used to compile this version of Perl are not available to or not usually used by the users of these operating systems. In such cases building this module (or any other Perl module containing C and/or XS code) will not work. You will either have to get the compiler which was used to compile Perl itself (see for example the section "Compiler:" in the output of the command "perl -V"), or to build your own Perl with the compiler of your choice (which also allows you to take advantage of the various compile- time switches Perl offers). Note that Sun Solaris and Red Hat Linux frequently were reported to suffer from this kind of problem. Moreover, you usually cannot build any modules under Windows 95/98 since the Win 95/98 command shell doesn't support the "&&" operator. You will need the Windows NT command shell ("cmd.exe") or the "4DOS" shell to be installed on your Windows 95/98 system first. Note that Windows NT, Windows 2000 and Windows XP are not affected and just work fine. I don't know about Windows Vista and Windows 7, however. Note that ActiveState provides precompiled binaries of this module for their Win32 port of Perl ("ActivePerl") on their web site, which you should be able to install simply by typing "ppm install Bit-Vector" in your MS-DOS command shell (but note the "-" instead of "::" in the package name!). This also works under Windows 95/98 (!). If your firewall prevents "ppm" from downloading this package, you can also download it manually from http://www.activestate.com/ppmpackages/5.005/zips/ or http://www.activestate.com/ppmpackages/5.6/zips/. Follow the installation instructions included in the "zip" archive. Note to CPAN Testers: --------------------- After completion, version 7.4 of this module has already been tested successfully with the following configurations: Perl 5.12.3 - FreeBSD 8.2-PRERELEASE Installation: ------------- Please see the file "INSTALL.txt" in this distribution for instructions on how to install this package. It is essential that you read this file since one of the special cases described in it might apply to you, especially if you are running Perl under Windows. Changes over previous versions: ------------------------------- Please refer to the file "CHANGES.txt" in this distribution for a more detailed version history log. Documentation: -------------- The documentation of this package is included in POD format (= "Plain Old Documentation") in the files with the extension ".pod" in this distribution, the human-readable markup-language standard for Perl documentation. By building this package, this documentation will automatically be converted into man pages, which will automatically be installed in your Perl tree for further reference through the installation process, where they can be accessed by the commands "man Bit::Vector" (Unix) and "perldoc Bit::Vector" (Unix and Win32 alike), for example. Available man pages: Bit::Vector(3) Bit::Vector::Overload(3) Bit::Vector::String(3) If Perl is not available on your system, you can also read the ".pod" files ./Vector.pod ./lib/Bit/Vector/Overload.pod ./lib/Bit/Vector/String.pod directly. What does it do: ---------------- This package implements bit vectors of arbitrary size and provides efficient methods for handling them. This goes far beyond the built-in capabilities of Perl for handling bit vectors (compare with the method list below!). Moreover, the C core of this package can be used "stand-alone" in other C applications; Perl is not necessarily required. The main module of this package is intended to serve as a base class for other applications or application classes, such as implementing sets or performing big integer arithmetic. All methods are implemented in C internally for maximum performance. An add-on module (named "Bit::Vector::Overload") provides overloaded arithmetic and relational operators for maximum ease of use (Perl only). Note that there is (of course) a little speed penalty to pay for overloaded operators. If speed is crucial, use the "Bit::Vector" module alone! Another module, "Bit::Vector::String", offers additional methods for generic string export and import (also Perl only). This package is useful for a large range of different tasks: - For example for implementing sets and performing set operations (like union, difference, intersection, complement, check for subset relationship etc.), - as a basis for many efficient algorithms, for instance the "Sieve of Erathostenes" (for calculating prime numbers), (The complexities of the methods in this package are usually either O(1) or O(n/b), where "b" is the number of bits in a machine word on your system.) - for shift registers of arbitrary length (for example for cyclic redundancy checksums), - to calculate "look-ahead", "first" and "follow" character sets for parsers and compiler-compilers, - for graph algorithms, - for efficient storage and retrieval of status information, - for performing text synthesis ruled by boolean expressions, - for "big integer" arithmetic with arbitrarily large integers, - for manipulations of chunks of bits of arbitrary size, - for bitwise processing of audio CD wave files, - to convert formats of data files, and more. (A number of example applications is available from my web site at http://www.engelschall.com/u/sb/download/.) A large number of import/export methods allow you to access individual bits, contiguous ranges of bits, machine words, arbitrary chunks of bits, lists (arrays) of chunks of bits or machine words and a whole bit vector at once (for instance for blockwrite/-read to and from a file). You can also import and export the contents of a bit vector in binary, hexadecimal and decimal representation as well as ".newsrc" style enumerations. Note that this package is specifically designed for efficiency, which is also the reason why its methods are implemented in C. To further increase execution speed, the package doesn't use bytes as its basic storage unit, but rather uses machine words, assuming that a machine word is the most efficiently handled size of all scalar types on all machines (that's what the ANSI C standard proposes and assumes anyway). In order to achieve this, it automatically determines the number of bits in a machine word on your system and then adjusts its internal configuration constants accordingly. The greater the size of this basic storage unit, the better the complexity (= execution speed) of the methods in this package, but also the greater the average waste of unused bits in the last word. The range of available methods is exceptionally large for this kind of library; in detail: Version() Word_Bits() Long_Bits() new() new_Hex() new_Bin() new_Dec() new_Enum() Shadow() Clone() Concat() Concat_List() Size() Resize() Copy() Empty() Fill() Flip() Primes() Reverse() Interval_Empty() Interval_Fill() Interval_Flip() Interval_Reverse() Interval_Scan_inc() Interval_Scan_dec() Interval_Copy() Interval_Substitute() is_empty() is_full() equal() Lexicompare() Compare() to_Hex() from_Hex() to_Bin() from_Bin() to_Dec() from_Dec() to_Enum() from_Enum() Bit_Off() Bit_On() bit_flip() bit_test() Bit_Copy() LSB() MSB() lsb() msb() rotate_left() rotate_right() shift_left() shift_right() Move_Left() Move_Right() Insert() Delete() increment() decrement() inc() dec() add() subtract() Negate() Absolute() Sign() Multiply() Divide() GCD() Power() Block_Store() Block_Read() Word_Size() Word_Store() Word_Read() Word_List_Store() Word_List_Read() Word_Insert() Word_Delete() Chunk_Store() Chunk_Read() Chunk_List_Store() Chunk_List_Read() Index_List_Remove() Index_List_Store() Index_List_Read() Union() Intersection() Difference() ExclusiveOr() Complement() subset() Norm() Min() Max() Multiplication() Product() Closure() Transpose() Note to C developers: --------------------- Note again that the C library at the core of this module can also be used stand-alone (i.e., it contains no inter-dependencies whatsoever with Perl). The library itself consists of three files: "BitVector.c", "BitVector.h" and "ToolBox.h". Just compile "BitVector.c" (which automatically includes "ToolBox.h") and link the resulting output file "BitVector.o" with your application, which in turn should include "ToolBox.h" and "BitVector.h" (in this order). See also the file "test.c" in the "examples" subdirectory of this distribution for an example application (play around with it, e.g. by changing the input vectors and the number of bits, and see what happens). Example applications: --------------------- See the module "Set::IntRange" for an easy-to-use module for sets of integers within arbitrary ranges. See the module "Math::MatrixBool" for an efficient implementation of boolean matrices and boolean matrix operations. (Both modules are also available from my web site at http://www.engelschall.com/u/sb/download/ or any CPAN server.) See the file "SetObject.pl" in the "examples" subdirectory of this distribution for a way to emulate the "Set::Object" module from CPAN using "Bit::Vector" - this is a way to perform set operations on sets of arbitrary objects (any Perl objects or Perl data structures you want!). An application relying crucially on this "Bit::Vector" module is "Slice", a tool for generating different document versions out of a single master file, ruled by boolean expressions ("include english version of text plus examples but not ..."). (See also http://www.engelschall.com/sw/slice/.) This tool is itself part of another tool, "Website META Language" ("WML"), which allows you to generate and maintain large web sites. Among many other features, it allows you to define your own HTML tags which will be expanded either at generation or at run time, depending on your choice. (See also http://www.engelschall.com/sw/wml/.) Both tools are written by Ralf S. Engelschall. Credits: -------- Please refer to the file "CREDITS.txt" in this distribution for a list of contributors. Author's note: -------------- If you have any questions, suggestions or need any assistance, please let me know! Please do send feedback, this is essential for improving this module according to your needs! I hope you will find this module useful. Enjoy! Yours, -- Steffen Beyer http://www.engelschall.com/u/sb/ "There is enough for the need of everyone in this world, but not for the greed of everyone." - Mohandas Karamchand "Mahatma" Gandhi Bit-Vector-7.4/INSTALL.txt000644 100660 100660 00000021375 12211373040 014264 0ustar00sbsb000000 000000 ===================================== Package "Bit::Vector" Version 7.4 ===================================== Copyright (c) 1995 - 2013 by Steffen Beyer. All rights reserved. Contents: --------- + Prerequisites + Preliminary steps for use with Perl prior to version 5.002 + Preliminary steps for use with ActiveState's port of Perl 5 + Installation Prerequisites: -------------- Perl version 5.000 or higher, and an ANSI C compiler. (!) ^^^^^^ Module "Carp::Clan" version 5.3 or higher. Optionally, module "Storable" version 2.21 or newer. Note that in order to compile Perl modules which contain C (and/or XS) code (such as this one), you always HAVE to use the very same compiler your Perl itself was compiled with. Many vendors nowadays ship their operating system already comprising a precompiled version of Perl. Many times the compilers used to compile this version of Perl are not available to or not usually used by the users of these operating systems. In such cases building this module (or any other Perl module containing C and/or XS code) will not work. You will either have to get the compiler which was used to compile Perl itself (see for example the section "Compiler:" in the output of the command "perl -V"), or to build your own Perl with the compiler of your choice (which also allows you to take advantage of the various compile- time switches Perl offers). Note that Sun Solaris and Red Hat Linux frequently were reported to suffer from this kind of problem. Moreover, you usually cannot build any modules under Windows 95/98 since the Win 95/98 command shell doesn't support the "&&" operator. You will need the Windows NT command shell ("cmd.exe") or the "4DOS" shell to be installed on your Windows 95/98 system first. Note that Windows NT, Windows 2000 and Windows XP are not affected and just work fine. I don't know about Windows Vista and Windows 7, however. Note that ActiveState provides precompiled binaries of this module for their Win32 port of Perl ("ActivePerl") on their web site, which you should be able to install simply by typing "ppm install Bit-Vector" in your MS-DOS command shell (but note the "-" instead of "::" in the package name!). This also works under Windows 95/98 (!). If your firewall prevents "ppm" from downloading this package, you can also download it manually from http://www.activestate.com/ppmpackages/5.005/zips/ or http://www.activestate.com/ppmpackages/5.6/zips/. Follow the installation instructions included in the "zip" archive. Preliminary steps for use with Perl prior to version 5.002: ----------------------------------------------------------- Edit the file "Makefile.PL" and change the line 'VERSION_FROM' => 'Vector.pm', to 'VERSION' => '7.4', Then edit the file "Vector.pm" and change the line bootstrap Bit::Vector $VERSION; to bootstrap Bit::Vector; Also edit the file "t/00____version.t" and change the line use Bit::Vector 7.4; to use Bit::Vector; Finally, edit the file "Vector.xs" and delete the line PROTOTYPES: DISABLE Preliminary steps for use with ActiveState's port of Perl 5: ------------------------------------------------------------ (For the Win32 platform) Edit the file "Makefile.PL" and remove all of the "#" characters which currently comment out the lines involved with the setting of the attributes "ABSTRACT", "AUTHOR" and "CAPI". Installation: ------------- ============================================================================= ALWAYS unpack and build Perl modules OUTSIDE the Perl source and installation tree! (You might otherwise inadvertently corrupt your Perl installation!) ============================================================================= Quick installation guide for experienced users: ----------------------------------------------- UNIX: Win32/Borland C++: Win32/MS Visual C++: ===== ================== ==================== % perl Makefile.PL % perl Makefile.PL % perl Makefile.PL % make % dmake % nmake % make test % dmake test % nmake test % make install % dmake install % nmake install Detailed installation guide: ---------------------------- 1) Change directory to the directory that has been created by unpacking this package ("cd Bit-Vector-7.4"). 2) Type "perl Makefile.PL" (or whatever the name and path of your Perl 5 binary is). This will create a "Makefile" with the appropriate parameters for your system (for instance, where the install directories are, and so on). See "man ExtUtils::MakeMaker" or "perldoc ExtUtils::MakeMaker" for other useful options to this command, like setting a different installation PREFIX. 3) Type "make". (For installation under Windows NT/95, use "dmake" (Borland C++) or "nmake" (MS Visual C++) instead!) This will create a dynamically linkable library file that will be linked to Perl later, at runtime, provided your system supports dynamic linking. Please refer to the MakeMaker documentation for instructions on how to build a new Perl with statically linked libraries (invoke "perldoc ExtUtils::MakeMaker" for this), if your system does NOT support dynamic linking! Should you encounter any compiler warnings or errors (like the redefi- nition of certain types already defined by your system), please contact me via e-mail at , sending me your compiler output (both STDOUT and STDERR). Thank you! ====================================================================== BEWARE that you need an ANSI C compiler in order to successfully compile this package! ====================================================================== Also note that problems may arise with the c89 compiler of HP, although it allegedly supports ANSI C! I recommend the GNU C compiler ("gcc"), which is freely available on the Internet (see ftp://ftp.gnu.org/pub/gnu/ and mirror sites thereof). (HP users are strongly recommended to install the GNU assembler "gas" first before installing the GNU C compiler "gcc", according to GNU.) Should you get the error messages Vector.c: 15: Unable to find include file 'EXTERN.h'. Vector.c: 16: Unable to find include file 'perl.h'. Vector.c: 17: Unable to find include file 'XSUB.h'. then edit the file "Makefile.PL" and add a line similar to the following so that it points to your Perl 5 distribution tree: 'INC' => '-I/usr/ctr/dlt/private/perl/perl5.003', Then start over with the generation of the "Makefile" at 2). 4) Now issue "make test" (or "dmake test" or "nmake test", respectively). The output should look somewhat like this: PERL_DL_NONLAZY=1 /v/guest/sw/bin/perl "-MExtUtils::Command::MM" "-e" "test_harness(0, 'blib/lib', 'blib/arch')" t/*.t t/00_____version.t .. ok t/01_________new.t .. ok t/02_____destroy.t .. ok t/03__operations.t .. ok t/04___functions.t .. ok t/05______primes.t .. ok t/06______subset.t .. ok t/07_____compare.t .. ok t/08______resize.t .. ok t/09__parameters.t .. ok t/10___intervals.t .. ok t/11_______shift.t .. ok t/12______string.t .. ok t/13___increment.t .. ok t/14_______empty.t .. ok t/15_________add.t .. ok t/16____subtract.t .. ok t/17_________gcd.t .. ok t/28___chunklist.t .. ok t/30__overloaded.t .. ok t/40___auxiliary.t .. ok t/50_freeze_thaw.t .. ok t/51_file_nstore.t .. ok All tests successful. Files=23, Tests=91963, 16 wallclock secs (13.63 usr 0.23 sys + 2.91 cusr 0.56 csys = 17.34 CPU) Result: PASS (Note that the exact number of tests will depend on the number of bits of a machine word/an unsigned long on your system!) 5) At last, type "make install" (or "dmake install", "nmake install"). 6) Now you can run the "primes.pl" demo program from the "examples" sub- directory, for instance. Start it with "perl examples/primes.pl" (or whatever the name and path of your Perl 5 binary is). It will ask you to enter a number which will serve as an upper limit for the calculation of all prime numbers up to that limit, using the algorithm known as "The Sieve of Erathostenes". On my machine (SUN SPARCstation 20/61), calculating all the prime numbers up to one million takes about 1 minute 30 seconds to 2 minutes (depending on the load) when the algorithm is programmed in Perl. If the internal method "Primes()" is used instead (implemented in C), the same machine only takes about 1 second for this task. 7) Share and enjoy! Bit-Vector-7.4/GNU_GPL.txt000644 100660 100660 00000043101 12211373040 014300 0ustar00sbsb000000 000000 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc. 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Library General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 19yy This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) 19yy name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. Bit-Vector-7.4/lib/000755 100660 100660 00000000000 12211373041 013154 5ustar00sbsb000000 000000 Bit-Vector-7.4/BitVector.h000644 100660 100660 00000052501 12211373040 014462 0ustar00sbsb000000 000000 #ifndef MODULE_BIT_VECTOR #define MODULE_BIT_VECTOR #ifdef __cplusplus extern "C" { #endif /*****************************************************************************/ /* MODULE NAME: BitVector.h MODULE TYPE: (adt) */ /*****************************************************************************/ /* MODULE IMPORTS: */ /*****************************************************************************/ #include /* MODULE TYPE: (sys) */ #include /* MODULE TYPE: (sys) */ #include /* MODULE TYPE: (sys) */ #include /* MODULE TYPE: (sys) */ #include "ToolBox.h" /* MODULE TYPE: (dat) */ /*****************************************************************************/ /* MODULE INTERFACE: */ /*****************************************************************************/ typedef enum { BV_ErrCode_Ok = 0, /* everything went allright */ BV_ErrCode_Type, /* types word and size_t have incompatible sizes */ BV_ErrCode_Bits, /* bits of word and sizeof(word) are inconsistent */ BV_ErrCode_Word, /* size of word is less than 16 bits */ BV_ErrCode_Powr, /* number of bits of word is not a power of two */ BV_ErrCode_Loga, /* error in calculation of logarithm */ BV_ErrCode_Lpwr, /* number of bits of long is not a power of two */ BV_ErrCode_WgtL, /* size of word is greater than size of long */ BV_ErrCode_Null, /* unable to allocate memory */ BV_ErrCode_Indx, /* index out of range */ BV_ErrCode_Ordr, /* minimum > maximum index */ BV_ErrCode_Size, /* bit vector size mismatch */ BV_ErrCode_Pars, /* input string syntax error */ BV_ErrCode_Ovfl, /* numeric overflow error */ BV_ErrCode_Same, /* operands must be distinct */ BV_ErrCode_Expo, /* exponent must be positive */ BV_ErrCode_Zero, /* division by zero error */ BV_ErrCode_Oops /* unexpected error (contact author) */ } BV_ErrCode; typedef wordptr *bv_listptr; /* ===> MISCELLANEOUS BASIC FUNCTIONS: <=== */ charptr BitVector_Error (BV_ErrCode error); /* map errcode to string */ BV_ErrCode BitVector_Boot (void); /* 0 = ok, 1..17 = error */ N_word BitVector_Size (N_int bits); /* bit vec. size (# of words) */ N_word BitVector_Mask (N_int bits); /* bit vec. mask (unused bits) */ /* ===> CLASS METHODS: <=== */ charptr BitVector_Version (void); /* return version string */ N_int BitVector_Word_Bits (void); /* return # of bits in machine word */ N_int BitVector_Long_Bits (void); /* return # of bits in unsigned long */ /* ===> CONSTRUCTOR METHODS: <=== */ wordptr BitVector_Create (N_int bits, boolean clear); /* malloc */ bv_listptr BitVector_Create_List(N_int bits, boolean clear, N_int count); wordptr BitVector_Resize (wordptr oldaddr, N_int bits); /* realloc */ wordptr BitVector_Shadow (wordptr addr); /* make same size but empty */ wordptr BitVector_Clone (wordptr addr); /* make exact duplicate */ wordptr BitVector_Concat (wordptr X, wordptr Y); /* return concat'd */ /* ===> DESTRUCTOR METHODS: <=== */ void BitVector_Dispose (charptr string); /* string */ void BitVector_Destroy (wordptr addr); /* bitvec */ void BitVector_Destroy_List (bv_listptr list, N_int count); /* list */ /* ===> OBJECT METHODS: <=== */ /* ===> bit vector copy function: */ void BitVector_Copy (wordptr X, wordptr Y); /* X = Y */ /* ===> bit vector initialization: */ void BitVector_Empty (wordptr addr); /* X = {} */ void BitVector_Fill (wordptr addr); /* X = ~{} */ void BitVector_Flip (wordptr addr); /* X = ~X */ void BitVector_Primes (wordptr addr); /* ===> miscellaneous functions: */ void BitVector_Reverse (wordptr X, wordptr Y); /* ===> bit vector interval operations and functions: */ void BitVector_Interval_Empty (wordptr addr, N_int lower, N_int upper); void BitVector_Interval_Fill (wordptr addr, N_int lower, N_int upper); void BitVector_Interval_Flip (wordptr addr, N_int lower, N_int upper); void BitVector_Interval_Reverse (wordptr addr, N_int lower, N_int upper); boolean BitVector_interval_scan_inc (wordptr addr, N_int start, N_intptr min, N_intptr max); boolean BitVector_interval_scan_dec (wordptr addr, N_int start, N_intptr min, N_intptr max); void BitVector_Interval_Copy (wordptr X, wordptr Y, N_int Xoffset, N_int Yoffset, N_int length); wordptr BitVector_Interval_Substitute(wordptr X, wordptr Y, N_int Xoffset, N_int Xlength, N_int Yoffset, N_int Ylength); /* ===> bit vector test functions: */ boolean BitVector_is_empty (wordptr addr); /* X == {} ? */ boolean BitVector_is_full (wordptr addr); /* X == ~{} ? */ boolean BitVector_equal (wordptr X, wordptr Y); /* X == Y ? */ Z_int BitVector_Lexicompare(wordptr X, wordptr Y); /* X <,=,> Y ? */ Z_int BitVector_Compare (wordptr X, wordptr Y); /* X <,=,> Y ? */ /* ===> bit vector string conversion functions: */ charptr BitVector_to_Hex (wordptr addr); BV_ErrCode BitVector_from_Hex (wordptr addr, charptr string); charptr BitVector_to_Bin (wordptr addr); BV_ErrCode BitVector_from_Bin (wordptr addr, charptr string); charptr BitVector_to_Dec (wordptr addr); BV_ErrCode BitVector_from_Dec (wordptr addr, charptr string); charptr BitVector_to_Enum (wordptr addr); BV_ErrCode BitVector_from_Enum (wordptr addr, charptr string); /* ===> bit vector bit operations, functions & tests: */ void BitVector_Bit_Off (wordptr addr, N_int index); /* X = X \ {x} */ void BitVector_Bit_On (wordptr addr, N_int index); /* X = X + {x} */ boolean BitVector_bit_flip (wordptr addr, N_int index); /* (X+{x})\(X*{x}) */ boolean BitVector_bit_test (wordptr addr, N_int index); /* {x} in X ? */ void BitVector_Bit_Copy (wordptr addr, N_int index, boolean bit); /* ===> bit vector bit shift & rotate functions: */ void BitVector_LSB (wordptr addr, boolean bit); void BitVector_MSB (wordptr addr, boolean bit); boolean BitVector_lsb_ (wordptr addr); boolean BitVector_msb_ (wordptr addr); boolean BitVector_rotate_left (wordptr addr); boolean BitVector_rotate_right (wordptr addr); boolean BitVector_shift_left (wordptr addr, boolean carry_in); boolean BitVector_shift_right (wordptr addr, boolean carry_in); void BitVector_Move_Left (wordptr addr, N_int bits); void BitVector_Move_Right (wordptr addr, N_int bits); /* ===> bit vector insert/delete bits: */ void BitVector_Insert (wordptr addr, N_int offset, N_int count, boolean clear); void BitVector_Delete (wordptr addr, N_int offset, N_int count, boolean clear); /* ===> bit vector arithmetic: */ boolean BitVector_increment (wordptr addr); /* X++ */ boolean BitVector_decrement (wordptr addr); /* X-- */ boolean BitVector_compute (wordptr X, wordptr Y, wordptr Z, boolean minus, boolean *carry); boolean BitVector_add (wordptr X, wordptr Y, wordptr Z, boolean *carry); boolean BitVector_sub (wordptr X, wordptr Y, wordptr Z, boolean *carry); boolean BitVector_inc (wordptr X, wordptr Y); boolean BitVector_dec (wordptr X, wordptr Y); void BitVector_Negate (wordptr X, wordptr Y); void BitVector_Absolute (wordptr X, wordptr Y); Z_int BitVector_Sign (wordptr addr); BV_ErrCode BitVector_Mul_Pos (wordptr X, wordptr Y, wordptr Z, boolean strict); BV_ErrCode BitVector_Multiply (wordptr X, wordptr Y, wordptr Z); BV_ErrCode BitVector_Div_Pos (wordptr Q, wordptr X, wordptr Y, wordptr R); BV_ErrCode BitVector_Divide (wordptr Q, wordptr X, wordptr Y, wordptr R); BV_ErrCode BitVector_GCD (wordptr X, wordptr Y, wordptr Z); BV_ErrCode BitVector_GCD2 (wordptr U, wordptr V, wordptr W, /* O */ wordptr X, wordptr Y); /* I */ BV_ErrCode BitVector_Power (wordptr X, wordptr Y, wordptr Z); /* ===> direct memory access functions: */ void BitVector_Block_Store(wordptr addr, charptr buffer, N_int length); charptr BitVector_Block_Read (wordptr addr, N_intptr length); /* ===> word array functions: */ void BitVector_Word_Store (wordptr addr, N_int offset, N_int value); N_int BitVector_Word_Read (wordptr addr, N_int offset); void BitVector_Word_Insert(wordptr addr, N_int offset, N_int count, boolean clear); void BitVector_Word_Delete(wordptr addr, N_int offset, N_int count, boolean clear); /* ===> arbitrary size chunk functions: */ void BitVector_Chunk_Store(wordptr addr, N_int chunksize, N_int offset, N_long value); N_long BitVector_Chunk_Read (wordptr addr, N_int chunksize, N_int offset); /* ===> set operations: */ void Set_Union (wordptr X, wordptr Y, wordptr Z); /* X = Y + Z */ void Set_Intersection (wordptr X, wordptr Y, wordptr Z); /* X = Y * Z */ void Set_Difference (wordptr X, wordptr Y, wordptr Z); /* X = Y \ Z */ void Set_ExclusiveOr (wordptr X, wordptr Y, wordptr Z); /*(Y+Z)\(Y*Z)*/ void Set_Complement (wordptr X, wordptr Y); /* X = ~Y */ /* ===> set functions: */ boolean Set_subset (wordptr X, wordptr Y); /* X in Y */ N_int Set_Norm (wordptr addr); /* = |X| */ N_int Set_Norm2 (wordptr addr); /* = |X| */ N_int Set_Norm3 (wordptr addr); /* = |X| */ Z_long Set_Min (wordptr addr); /* = min(X) */ Z_long Set_Max (wordptr addr); /* = max(X) */ /* ===> matrix-of-booleans operations: */ void Matrix_Multiplication(wordptr X, N_int rowsX, N_int colsX, wordptr Y, N_int rowsY, N_int colsY, wordptr Z, N_int rowsZ, N_int colsZ); void Matrix_Product (wordptr X, N_int rowsX, N_int colsX, wordptr Y, N_int rowsY, N_int colsY, wordptr Z, N_int rowsZ, N_int colsZ); void Matrix_Closure (wordptr addr, N_int rows, N_int cols); void Matrix_Transpose (wordptr X, N_int rowsX, N_int colsX, wordptr Y, N_int rowsY, N_int colsY); /*****************************************************************************/ /* MODULE RESOURCES: */ /*****************************************************************************/ #define BV_BITS_(BitVector) *(BitVector-3) #define BV_SIZE_(BitVector) *(BitVector-2) #define BV_MASK_(BitVector) *(BitVector-1) #define BV_ERRCODE_TYPE "sizeof(word) > sizeof(size_t)" #define BV_ERRCODE_BITS "bits(word) != sizeof(word)*8" #define BV_ERRCODE_WORD "bits(word) < 16" #define BV_ERRCODE_POWR "bits(word) is not a power of two" #define BV_ERRCODE_LOGA "bits(word) != 2^ld(bits(word))" #define BV_ERRCODE_LPWR "bits(long) is not a power of two" #define BV_ERRCODE_WGTL "bits(word) > bits(long)" #define BV_ERRCODE_NULL "unable to allocate memory" #define BV_ERRCODE_INDX "index out of range" #define BV_ERRCODE_ORDR "minimum > maximum index" #define BV_ERRCODE_SIZE "bit vector size mismatch" #define BV_ERRCODE_PARS "input string syntax error" #define BV_ERRCODE_OVFL "numeric overflow error" #define BV_ERRCODE_SAME "result vector(s) must be distinct" #define BV_ERRCODE_EXPO "exponent must be positive" #define BV_ERRCODE_ZERO "division by zero error" #define BV_ERRCODE_OOPS "unexpected internal error - please contact author" extern const N_int BV_ByteNorm[256]; /* { 0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x03, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, // 0x00 // 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, // 0x10 // 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, // 0x20 // 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, // 0x30 // 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, // 0x40 // 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, // 0x50 // 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, // 0x60 // 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, // 0x70 // 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, // 0x80 // 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, // 0x90 // 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, // 0xA0 // 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, // 0xB0 // 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, // 0xC0 // 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, // 0xD0 // 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, // 0xE0 // 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x05, 0x06, 0x06, 0x07, 0x06, 0x07, 0x07, 0x08 // 0xF0 // }; */ /*****************************************************************************/ /* MODULE IMPLEMENTATION: */ /*****************************************************************************/ /*****************************************************************************/ /* VERSION: 7.4 */ /*****************************************************************************/ /* VERSION HISTORY: */ /*****************************************************************************/ /* */ /* Version 7.4 03.09.13 No changes. */ /* Version 7.3 01.06.13 No changes. */ /* Version 7.2 17.05.12 No changes. */ /* Version 7.1 29.09.09 Added prefix "BV_" to all global identifiers. */ /* Version 7.0 22.08.09 Fixed bugs in "GCD2()" and "Boot()". */ /* Version 6.9 12.08.09 Removed an obsolete warning (memory leak). */ /* Version 6.8 10.08.09 Fixed hard-coded table size BV_MASKTABSIZE. */ /* Version 6.7 08.08.09 No changes. */ /* Version 6.6 27.07.09 Made it thread-safe and MacOS X compatible. */ /* Version 6.5 27.07.09 Added automatic support for module "Storable". */ /* Version 6.4 03.10.04 Added C++ comp. directives. Improved "Norm()". */ /* Version 6.3 28.09.02 Added "Create_List()" and "GCD2()". */ /* Version 6.2 15.09.02 Overhauled error handling. Fixed "GCD()". */ /* Version 6.1 08.10.01 Make VMS linker happy: _lsb,_msb => _lsb_,_msb_ */ /* Version 6.0 08.10.00 Corrected overflow handling. */ /* Version 5.8 14.07.00 Added "Power()". Changed "Copy()". */ /* Version 5.7 19.05.99 Quickened "Div_Pos()". Added "Product()". */ /* Version 5.6 02.11.98 Leading zeros eliminated in "to_Hex()". */ /* Version 5.5 21.09.98 Fixed bug of uninitialized "error" in Multiply. */ /* Version 5.4 07.09.98 Fixed bug of uninitialized "error" in Divide. */ /* Version 5.3 12.05.98 Improved Norm. Completed history. */ /* Version 5.2 31.03.98 Improved Norm. */ /* Version 5.1 09.03.98 No changes. */ /* Version 5.0 01.03.98 Major additions and rewrite. */ /* Version 4.2 16.07.97 Added is_empty, is_full. */ /* Version 4.1 30.06.97 Added word-ins/del, move-left/right, inc/dec. */ /* Version 4.0 23.04.97 Rewrite. Added bit shift and bool. matrix ops. */ /* Version 3.2 04.02.97 Added interval methods. */ /* Version 3.1 21.01.97 Fixed bug on 64 bit machines. */ /* Version 3.0 12.01.97 Added flip. */ /* Version 2.0 14.12.96 Efficiency and consistency improvements. */ /* Version 1.1 08.01.96 Added Resize and ExclusiveOr. */ /* Version 1.0 14.12.95 First version under UNIX (with Perl module). */ /* Version 0.9 01.11.93 First version of C library under MS-DOS. */ /* Version 0.1 ??.??.89 First version in Turbo Pascal under CP/M. */ /* */ /*****************************************************************************/ /* AUTHOR: */ /*****************************************************************************/ /* */ /* Steffen Beyer */ /* mailto:STBEY@cpan.org */ /* http://www.engelschall.com/u/sb/download/ */ /* */ /*****************************************************************************/ /* COPYRIGHT: */ /*****************************************************************************/ /* */ /* Copyright (c) 1995 - 2013 by Steffen Beyer. */ /* All rights reserved. */ /* */ /*****************************************************************************/ /* LICENSE: */ /*****************************************************************************/ /* */ /* This library is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU Library General Public */ /* License as published by the Free Software Foundation; either */ /* version 2 of the License, or (at your option) any later version. */ /* */ /* This library is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ /* Library General Public License for more details. */ /* */ /* You should have received a copy of the GNU Library General Public */ /* License along with this library; if not, write to the */ /* Free Software Foundation, Inc., */ /* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* */ /* or download a copy from ftp://ftp.gnu.org/pub/gnu/COPYING.LIB-2.0 */ /* */ /*****************************************************************************/ #ifdef __cplusplus } #endif #endif Bit-Vector-7.4/t/000755 100660 100660 00000000000 12211373041 012651 5ustar00sbsb000000 000000 Bit-Vector-7.4/Artistic.txt000644 100660 100660 00000013737 12211373040 014743 0ustar00sbsb000000 000000 The "Artistic License" Preamble The intent of this document is to state the conditions under which a Package may be copied, such that the Copyright Holder maintains some semblance of artistic control over the development of the package, while giving the users of the package the right to use and distribute the Package in a more-or-less customary fashion, plus the right to make reasonable modifications. Definitions: "Package" refers to the collection of files distributed by the Copyright Holder, and derivatives of that collection of files created through textual modification. "Standard Version" refers to such a Package if it has not been modified, or has been modified in accordance with the wishes of the Copyright Holder as specified below. "Copyright Holder" is whoever is named in the copyright or copyrights for the package. "You" is you, if you're thinking about copying or distributing this Package. "Reasonable copying fee" is whatever you can justify on the basis of media cost, duplication charges, time of people involved, and so on. (You will not be required to justify it to the Copyright Holder, but only to the computing community at large as a market that must bear the fee.) "Freely Available" means that no fee is charged for the item itself, though there may be fees involved in handling the item. It also means that recipients of the item may redistribute it under the same conditions they received it. 1. You may make and give away verbatim copies of the source form of the Standard Version of this Package without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may apply bug fixes, portability fixes and other modifications derived from the Public Domain or from the Copyright Holder. A Package modified in such a way shall still be considered the Standard Version. 3. You may otherwise modify your copy of this Package in any way, provided that you insert a prominent notice in each changed file stating how and when you changed that file, and provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or placing the modifications on a major archive site such as uunet.uu.net, or by allowing the Copyright Holder to include your modifications in the Standard Version of the Package. b) use the modified Package only within your corporation or organization. c) rename any non-standard executables so the names do not conflict with standard executables, which must also be provided, and provide a separate manual page for each non-standard executable that clearly documents how it differs from the Standard Version. d) make other distribution arrangements with the Copyright Holder. 4. You may distribute the programs of this Package in object code or executable form, provided that you do at least ONE of the following: a) distribute a Standard Version of the executables and library files, together with instructions (in the manual page or equivalent) on where to get the Standard Version. b) accompany the distribution with the machine-readable source of the Package with your modifications. c) give non-standard executables non-standard names, and clearly document the differences in manual pages (or equivalent), together with instructions on where to get the Standard Version. d) make other distribution arrangements with the Copyright Holder. 5. You may charge a reasonable copying fee for any distribution of this Package. You may charge any fee you choose for support of this Package. You may not charge a fee for this Package itself. However, you may distribute this Package in aggregate with other (possibly commercial) programs as part of a larger (possibly commercial) software distribution provided that you do not advertise this Package as a product of your own. You may embed this Package's interpreter within an executable of yours (by linking); this shall be construed as a mere form of aggregation, provided that the complete Standard Version of the interpreter is so embedded. 6. The scripts and library files supplied as input to or produced as output from the programs of this Package do not automatically fall under the copyright of this Package, but belong to whoever generated them, and may be sold commercially, and may be aggregated with this Package. If such scripts or library files are aggregated with this Package via the so-called "undump" or "unexec" methods of producing a binary executable image, then distribution of such an image shall neither be construed as a distribution of this Package nor shall it fall under the restrictions of Paragraphs 3 and 4, provided that you do not represent such an executable image as a Standard Version of this Package. 7. C subroutines (or comparably compiled subroutines in other languages) supplied by you and linked into this Package in order to emulate subroutines and variables of the language defined by this Package shall not be considered part of this Package, but are the equivalent of input as in Paragraph 6, provided these subroutines do not change the language in any way that would cause it to fail the regression tests for the language. 8. Aggregation of this Package with a commercial distribution is always permitted provided that the use of this Package is embedded; that is, when no overt attempt is made to make this Package's interfaces visible to the end user of the commercial distribution. Such use shall not be construed as a distribution of this Package. 9. The name of the Copyright Holder may not be used to endorse or promote products derived from this software without specific prior written permission. 10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. The End Bit-Vector-7.4/typemap000644 100660 100660 00000001743 12211373040 014014 0ustar00sbsb000000 000000 ############################################################################### ## ## ## Typemap for module "Bit::Vector" version 7.4. ## ## ## ## Copyright (c) 1995 - 2013 by Steffen Beyer. ## ## All rights reserved. ## ## ## ## This package is free software; you can redistribute it ## ## and/or modify it under the same terms as Perl itself. ## ## ## ############################################################################### TYPEMAP N_int T_IV N_long T_IV Z_int T_IV Z_long T_IV boolean T_IV BitVector_Object T_SV BitVector_Scalar T_SV Bit-Vector-7.4/CREDITS.txt000644 100660 100660 00000025273 12211373040 014254 0ustar00sbsb000000 000000 ===================================== Package "Bit::Vector" Version 7.4 ===================================== Copyright (c) 1995 - 2013 by Steffen Beyer. All rights reserved. Credits: -------- Many thanks to Andreas Koenig for his efforts as upload-manager for the CPAN, his patience, and lots of good advice and suggestions! Thank you for doing such a tremendous (and time- consuming) job!! Also many thanks to David Jenkins for reviewing the first version of the README file and the man page. Many thanks to Jarkko Hietaniemi for his suggestions while I was developing the first release of this package! Many thanks also to the people of the perl5-porters mailing list, specifically: Andreas Koenig Tim Bunce Jarkko Hietaniemi Felix Gallo Mark A Biggar Nick Ing-Simmons John Macdonald for discussing and clarifying the naming and other issues of this package! Also many thanks to David Thompson for reporting a problem he encountered concerning the inclusion of the Perl distribution ("Unable to find include file ...") and for suggesting a solution for this problem. (That's the most pleasant kind of problem report, of course! ;-) ) Many thanks to Rob Johnson for an improved algorithm for computing binomials with always integer intermediate results (and numbers never getting too big)! Thanks to Banchong Harangsri for reporting the problem of the version 1.1 of this module with Perl 5.002! Special thanks to Dean Roehrich for his assistance in trying to find the cause of and a remedy for the above problem! Many thanks to Andreas Koenig for notifying me of the alternative for the directory structure using the "lib" subdirectory and a way to use "confess" in an XSUB via "perl_eval_sv". Many special thanks to Larry Schwimmer for reporting the bug related to 64 bit machines and finding where an implicit assumption of 32 bit integers was hidden, and for testing the new version on his machine! Many thanks to Ralf S. Engelschall for suggesting the four new methods "Size()", "Empty_Interval()", "Fill_Interval()" and "Flip_Interval()", implemented in version 3.0 of the "Set::IntegerFast" module (and also in the "Set::IntegerRange" module)! Also many thanks to Ralf Engelschall for the many good suggestions that went into version 4.0 of this package (concerning many different aspects)! Many thanks to Stas Bekman for raising the question of bitwise shift and rotation operations in Perl, which gave me the idea to implement such shift registers with arbitrary size, which in turn and with time gave me the idea of implementing a "Bit::Vector" base class capable of this along with already existing functionality (for sets and boolean matrices). Also many thanks to Jon Orwant and Tim Bunce for their suggestions and comments concerning my first attempts at writing a module for bitwise shift and rotate operations in Perl, which eventually went into version 4.0 of this module! Many thanks to Brian S. Julin for sharing his ideas, his questions and the code of his "Bit::File" module with me, which inspired me to write the routines to access arbitrary chunks of bits. Many thanks to Hau-Yung Chen for suggesting the string conversion routines to convert to/from binary representation and the possibility to concatenate bit vectors. Many thanks to Jarkko Hietaniemi for suggesting the implementation of the transpose of a matrix in C for better performance. The transpose can be used in finding the strongly connected components of a graph. Many thanks go to Daniel Koch for suggesting the "Index_List_Store()" and "Index_List_Read()" methods! Many thanks again to Hau-Yung Chen for suggesting a way for speeding up the conversion to decimal in "to_Dec()" (by dividing the bit vector through the largest possible power of ten that will fit into a machine word and then breaking down the rest using only machine words, which is faster than repeatedly dividing the whole bit vector by ten). According to my measurements, this resulted in an 8-fold speed increase. Many thanks go to Krzysztof Koczyjan for suggesting and extensively benchmarking a more efficient method for bit counting in the method "Norm()", which was adopted in version 5.2. Many thanks again to Krzysztof Koczyjan for an additional improvement of the method "Norm()", which was adopted in version 5.3. Many thanks to Bryan Bayerdorffer for notifying me of the bug in the "Divide()" method, which was immediately fixed in version 5.4. Many thanks to Rob W. Koeling for reporting and to Paul J. Schinder for reporting and helping to investigate the error of the failed tests 96-131 of test script "t/01________new.t" under HP-UX 10! This was fixed in version 5.5. Many thanks to the "CPAN testers" (http://www.connect.net/gbarr/cpan-test/) in general and to Jarkko Hietaniemi in particular for testing this module and for reporting the compiler warning which occurred on line 2067 of "BitVector.c" with the native "cc" compiler under Digital Unix, which has been fixed in version 5.6. Also many thanks to Matt Knecht for pushing me hard enough ;-) to suppress those annoying leading zeros in the output from "to_Hex()" in version 5.6! Many thanks to Roland Titze and to Andrew Brown for pointing out the misspelling of "whether" (was: wether) throughout my documentation, corrected in version 5.8. Thanks also go to Steve Tolkin for suggesting that I should emphasize in the README.txt file that the reading of the INSTALL.txt file is important, especially if running Perl under Windows. :-) Many special thanks to Joshua N. Pritikin for sending in valuable patches to make this module ready for Perl 5.6.0 and to optimize the "strEQ" away from the typemap section in Vector.xs. Lots of thanks also to Yitzchak Scott-Thoennes for sending in a patch to make this module ready for Perl 5.6.0 and for extremely useful hints (and a patch) as to why the test suite had failures with Perl 5.6.0 all of a sudden. Many thanks to John Peacock for reporting a problem with the VMS linker which is unable to differentiate case - in violation of the ANSI C standard - and for sending a patch to fix this problem. Many thanks to Tom Oelke for reporting a problem with test "t/01________new.t" when Perl was built to use 64 bit integers and for suggesting two possible fixes. The second one (adding "use integer;" at the top of the script) was adopted in version 6.2. Many thanks to Clint Olsen for his many interesting questions and suggestions, one of which led to my writing the new example file "examples/test.c" in version 6.2. Many thanks to Tels for his criticism of "GCD()" and the documentation (with respect to common method name aliases such as Or, And, Xor, etc.). Both weaknesses have been fixed in version 6.2. Many thanks to Mike Swieton (and many other people in the past) for sending in a patch so that ToolBox.h will compile with C++ compilers. Many thanks to Runip Gopisetty for sending a patch for adding functions for generic string import and export functions. However, I decided to realize these in Perl instead (at least for the time being); you can find them in the new module "Bit::Vector::String". This way even octal representation and enumerations are supported. Many heartfelt thanks go to Jamie Blustein / / for sending me the article "Performance Investigation of Bit-Counting Algorithms with a Speedup to Lookup Table", by Eyas El-Qawasmeh, Department of Computer Science and Information Systems, Jordan University of Science and Technology, cited from the Journal of Research and Practice in Information Technology, Vol. 32, No. 3/4, August/ November 2000, thus prompting my reconsideration of the implementation of the "Norm()" method in this module. See also his web pages, especially the pages about bit vectors, at: http://www.cs.dal.ca/~jamie/ http://www.csd.uwo.ca/~jamie/ http://www.csd.uwo.ca/%7ejamie/.Refs/code.html http://www.csd.uwo.ca/%7ejamie/publications.html#BitVectors http://www.csd.uwo.ca/~jamie/BitVectors/ Thanks a lot to Jesse Vincent and to Alistair Francis for reporting the ongoing problem with the boolean type in MacOS X and to Tatsuhiko Miyagawa (?) and Alistair Francis for providing patches. Also many thanks to Joost Diepenmaat for alerting me about Bit::Vector not being thread-safe, and for providing a patch. Thanks a lot to Adam Kennedy for telling me about STORABLE_attach. Many thanks to Stephen McCamant for alerting me about the fact that the function "BitVector_Boot()" in BitVector.c leaks memory if called more than once, because of the dynamic allocation of the BITMASKTAB. This has been fixed in version 6.6 and improved in version 6.8. Thanks a lot to Christopher Jones for notifying me about the failing tests in "t/28___chunklist.t" under MacOs X / Darwin and for running some test scripts on his machine for me. Many thanks to Nicholas, Zefram, Slaven Rezic and Andreas Koenig for providing a patch for the definition of the "boolean" data type in Toolbox.h: http://cpan.cpantesters.org/authors/id/A/AN/ANDK/patches/Bit-Vector-7.1-ZEFRAMish-01.patch.gz Many thanks to Gisle Aas for his patch to make "t/02_____destroy.t" pass on perl-5.17.11. Many thanks to A. Bernardo Carvalho for letting me use his modification of ToolBox.h in order to allow bit vectors with more than 2^32 bits. On most machines this will allow bit vectors with up to 2^64 bits. He needed this for and successfully used it in his research in genomics. See http://www.ncbi.nlm.nih.gov/pubmed/23921660 or http://genome.cshlp.org/content/early/2013/08/06/gr.156034.113.abstract for his corresponding paper. Bit-Vector-7.4/META.yml000644 100660 100660 00000000772 12211373041 013665 0ustar00sbsb000000 000000 --- #YAML:1.0 name: Bit-Vector version: 7.4 abstract: ~ author: [] license: unknown distribution_type: module configure_requires: ExtUtils::MakeMaker: 0 build_requires: ExtUtils::MakeMaker: 0 requires: Carp::Clan: 5.3 Storable: 2.21 no_index: directory: - t - inc generated_by: ExtUtils::MakeMaker version 6.56 meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 Bit-Vector-7.4/Makefile.PL000644 100660 100660 00000004116 12211373040 014361 0ustar00sbsb000000 000000 #!perl -w ############################################################################### ## ## ## Copyright (c) 1995 - 2013 by Steffen Beyer. ## ## All rights reserved. ## ## ## ## This package is free software; you can redistribute it ## ## and/or modify it under the same terms as Perl itself. ## ## ## ############################################################################### use strict; use ExtUtils::MakeMaker; use Config; WriteMakefile( 'NAME' => 'Bit::Vector', 'VERSION_FROM' => 'Vector.pm', 'PREREQ_PM' => { 'Carp::Clan' => 5.3, 'Storable' => 2.21 }, 'OBJECT' => '$(O_FILES)', # ($] >= 5.005 ? # ('ABSTRACT' => 'Efficient base class implementing bit vectors', # 'AUTHOR' => 'Steffen Beyer (STBEY@cpan.org)') : ()), # ($] >= 5.005 && $^O eq 'MSWin32' && $Config{archname} =~ /-object\b/i ? # ('CAPI' => 'TRUE') : ()), 'dist' => { COMPRESS => "gzip -9", SUFFIX => "gz" } ); my $patchlevel = $0; $patchlevel =~ s![^/\\]*$!patchlevel.h!; my $PATCHLEVEL = $Config{'PATCHLEVEL'} || $Config{'patchlevel'} || substr($],2,3); my $SUBVERSION = $Config{'SUBVERSION'} || $Config{'subversion'} || substr($],5) || 0; if (open(PATCHLEVEL, ">$patchlevel")) { print "Writing $patchlevel for $^X ($])\n"; printf PATCHLEVEL "#define PATCHLEVEL %d\n", $PATCHLEVEL; printf PATCHLEVEL "#define SUBVERSION %d\n", $SUBVERSION; close(PATCHLEVEL); } else { warn "Oops: Couldn't write file '$patchlevel': $!\n"; warn "However, you might succeed in building this module anyway;\n"; warn "Just try it!\n"; } __END__ Bit-Vector-7.4/Vector.pod000644 100660 100660 00000311711 12211373040 014357 0ustar00sbsb000000 000000 =head1 NAME Bit::Vector - Efficient bit vector, set of integers and "big int" math library =head1 SYNOPSIS =head2 OVERLOADED OPERATORS See L. =head2 MORE STRING IMPORT/EXPORT See L. =head2 CLASS METHODS Version $version = Bit::Vector->Version(); Word_Bits $bits = Bit::Vector->Word_Bits(); # bits in a machine word Long_Bits $bits = Bit::Vector->Long_Bits(); # bits in an unsigned long new $vector = Bit::Vector->new($bits); # bit vector constructor @veclist = Bit::Vector->new($bits,$count); 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); =head2 OBJECT METHODS new $vec2 = $vec1->new($bits); # alternative call of constructor @veclist = $vec->new($bits,$count); Shadow $vec2 = $vec1->Shadow(); # new vector, same size but empty Clone $vec2 = $vec1->Clone(); # new vector, exact duplicate 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(); # Sieve of 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 (unsigned) 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 (signed) 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(); # e.g. "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); # shift left "$bits" positions Move_Right $vector->Move_Right($bits); # shift right "$bits" positions Insert $vector->Insert($offset,$bits); Delete $vector->Delete($offset,$bits); increment $carry = $vector->increment(); decrement $carry = $vector->decrement(); inc $overflow = $vec2->inc($vec1); dec $overflow = $vec2->dec($vec1); add $carry = $vec3->add($vec1,$vec2,$carry); ($carry,$overflow) = $vec3->add($vec1,$vec2,$carry); subtract $carry = $vec3->subtract($vec1,$vec2,$carry); ($carry,$overflow) = $vec3->subtract($vec1,$vec2,$carry); Neg Negate $vec2->Neg($vec1); $vec2->Negate($vec1); Abs Absolute $vec2->Abs($vec1); $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) $vecgcd->GCD($veca,$vecb); $vecgcd->GCD($vecx,$vecy,$veca,$vecb); Power $vec3->Power($vec1,$vec2); Block_Store $vector->Block_Store($buffer); Block_Read $buffer = $vector->Block_Read(); Word_Size $size = $vector->Word_Size(); # number of words 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(); Or Union $vec3->Or($vec1,$vec2); $set3->Union($set1,$set2); And Intersection $vec3->And($vec1,$vec2); $set3->Intersection($set1,$set2); AndNot Difference $vec3->AndNot($vec1,$vec2); $set3->Difference($set1,$set2); Xor ExclusiveOr $vec3->Xor($vec1,$vec2); $set3->ExclusiveOr($set1,$set2); Not Complement $vec2->Not($vec1); $set2->Complement($set1); subset if ($set1->subset($set2)) # true if $set1 is subset of $set2 Norm $norm = $set->Norm(); $norm = $set->Norm2(); $norm = $set->Norm3(); Min $min = $set->Min(); Max $max = $set->Max(); Multiplication $matrix3->Multiplication($rows3,$cols3, $matrix1,$rows1,$cols1, $matrix2,$rows2,$cols2); Product $matrix3->Product($rows3,$cols3, $matrix1,$rows1,$cols1, $matrix2,$rows2,$cols2); Closure $matrix->Closure($rows,$cols); Transpose $matrix2->Transpose($rows2,$cols2,$matrix1,$rows1,$cols1); =head1 IMPORTANT NOTES =over 2 =item * Method naming conventions Method names completely in lower case indicate a boolean return value. (Except for the bit vector constructor method "C", of course.) =item * Boolean values Boolean values in this module are always a numeric zero ("C<0>") for "false" and a numeric one ("C<1>") for "true". =item * Negative numbers All numeric input parameters passed to any of the methods in this module are regarded as being B (as opposed to the contents of the bit vectors themselves, which are usually considered to be B). As a consequence, whenever you pass a negative number as an argument to some method of this module, it will be treated as a (usually very large) positive number due to its internal two's complement binary representation, usually resulting in an "index out of range" error message and program abortion. =item * Bit order Note that bit vectors are stored least order bit and least order word first internally. I.e., bit #0 of any given bit vector corresponds to bit #0 of word #0 in the array of machine words representing the bit vector. (Where word #0 comes first in memory, i.e., it is stored at the least memory address in the allocated block of memory holding the given bit vector.) Note however that machine words can be stored least order byte first or last, depending on your system's implementation. When you are exporting or importing a whole bit vector at once using the methods "C" and "C" (the only time in this module where this could make any difference), however, a conversion to and from "least order byte first" order is automatically supplied. In other words, what "C" provides and what "C" expects is always in "least order byte first" order, regardless of the order in which words are stored internally on your machine. This is to make sure that what you export on one machine using "C" can always be read in correctly with "C" on a different machine. Note further that whenever bit vectors are converted to and from (binary or hexadecimal) strings, the B bit is always the B one, and the B bit is always the B bit. This is because in our western culture, numbers are always represented in this way (least significant to most significant digits go from right to left). Of course this requires an internal reversion of order, which the corresponding conversion methods perform automatically (without any additional overhead, it's just a matter of starting the internal loop at the bottom or the top end). =item * "Word" related methods Note that all methods whose names begin with "C" are B! They depend on the size (number of bits) of an "unsigned int" (C type) on your machine. Therefore, you should only use these methods if you are B that portability of your code is not an issue! Note that you can use arbitrarily large chunks (i.e., fragments of bit vectors) of up to 32 bits B using the methods whose names begin with "C". =item * Chunk sizes Note that legal chunk sizes for all methods whose names begin with "C" range from "C<1>" to "CLong_Bits();>" bits ("C<0>" is B allowed!). In order to make your programs portable, however, you shouldn't use chunk sizes larger than 32 bits, since this is the minimum size of an "unsigned long" (C type) on all systems, as prescribed by S. =item * Matching sizes In general, for methods involving several bit vectors at the same time, all bit vector arguments must have identical sizes (number of bits), or a fatal "size mismatch" error will occur. Exceptions from this rule are the methods "C", "C", "C", "C" and "C", where no conditions at all are imposed on the size of their bit vector arguments. In method "C", all three bit vector arguments must in principle obey the rule of matching sizes, but the bit vector in which the result of the multiplication is to be stored may be larger than the two bit vector arguments containing the factors for the multiplication. In method "C", the bit vector for the result must be the same size or greater than the base of the exponentiation term. The exponent can be any size. =item * Index ranges All indices for any given bits must lie between "C<0>" and "C<$vector-ESize()-1>", or a fatal "index out of range" error will occur. =item * Object persistence Since version 6.5, "Bit::Vector" objects can be serialized and de-serialized automatically with "Storable", out-of-the-box, without requiring any further user action for this to work. This is also true for nested data structures (since version 6.8). See the L documentation for more details. =back =head1 DESCRIPTION =head2 OVERLOADED OPERATORS See L. =head2 MORE STRING IMPORT/EXPORT See L. =head2 CLASS METHODS =over 2 =item * C<$version = Bit::Vector-EVersion();> Returns the current version number of this module. =item * C<$bits = Bit::Vector-EWord_Bits();> Returns the number of bits of an "unsigned int" (C type) on your machine. (An "unsigned int" is also called a "machine word", hence the name of this method.) =item * C<$bits = Bit::Vector-ELong_Bits();> Returns the number of bits of an "unsigned long" (C type) on your machine. =item * C<$vector = Bit::Vector-Enew($bits);> This is the bit vector constructor method. Call this method to create a new bit vector containing "C<$bits>" bits (with indices ranging from "C<0>" to "C<$bits-1>"). Note that - in contrast to previous versions - bit vectors of length zero (i.e., with C<$bits = 0>) are permitted now. The method returns a reference to the newly created bit vector. A new bit vector is always initialized so that all bits are cleared (turned off). An exception will be raised if the method is unable to allocate the necessary memory. Note that if you specify a negative number for "C<$bits>" it will be interpreted as a large positive number due to its internal two's complement binary representation. In such a case, the bit vector constructor method will obediently attempt to create a bit vector of that size, probably resulting in an exception, as explained above. =item * C<@veclist = Bit::Vector-Enew($bits,$count);> You can also create more than one bit vector at a time if you specify the optional second parameter "C<$count>". The method returns a list of "C<$count>" bit vectors which all have the same number of bits "C<$bits>" (and which are all initialized, i.e., all bits are cleared). If "C<$count>" is zero, an empty list is returned. If "C<$bits>" is zero, a list of null-sized bit vectors is returned. Note again that if you specify a negative number for "C<$count>" it will be interpreted as a large positive number due to its internal two's complement binary representation. In such a case, the bit vector constructor method will obediently attempt to create that many bit vectors, probably resulting in an exception ("out of memory"). =item * C<$vector = Bit::Vector-Enew_Hex($bits,$string);> This method is an alternative constructor which allows you to create a new bit vector object (with "C<$bits>" bits) and to initialize it all in one go. The method internally first calls the bit vector constructor method "C" and then passes the given string to the method "C". However, this method is more efficient than performing these two steps separately: First because in this method, the memory area occupied by the new bit vector is not initialized to zeros (which is pointless in this case), and second because it saves you from the associated overhead of one additional method invocation. An exception will be raised if the necessary memory cannot be allocated (see the description of the method "C" immediately above for possible causes) or if the given string cannot be converted successfully (see the description of the method "C" further below for details). In the latter case, the memory occupied by the new bit vector is released first (i.e., "free"d) before the exception is actually raised. =item * C<$vector = Bit::Vector-Enew_Bin($bits,$string);> This method is an alternative constructor which allows you to create a new bit vector object (with "C<$bits>" bits) and to initialize it all in one go. The method internally first calls the bit vector constructor method "C" and then passes the given string to the method "C". However, this method is more efficient than performing these two steps separately: First because in this method, the memory area occupied by the new bit vector is not initialized to zeros (which is pointless in this case), and second because it saves you from the associated overhead of one additional method invocation. An exception will be raised if the necessary memory cannot be allocated (see the description of the method "C" above for possible causes) or if the given string cannot be converted successfully (see the description of the method "C" further below for details). In the latter case, the memory occupied by the new bit vector is released first (i.e., "free"d) before the exception is actually raised. =item * C<$vector = Bit::Vector-Enew_Dec($bits,$string);> This method is an alternative constructor which allows you to create a new bit vector object (with "C<$bits>" bits) and to initialize it all in one go. The method internally first calls the bit vector constructor method "C" and then passes the given string to the method "C". However, this method is more efficient than performing these two steps separately: First because in this method, "C" does not initialize the memory area occupied by the new bit vector with zeros (which is pointless in this case, because "C" will do it anyway), and second because it saves you from the associated overhead of one additional method invocation. An exception will be raised if the necessary memory cannot be allocated (see the description of the method "C" above for possible causes) or if the given string cannot be converted successfully (see the description of the method "C" further below for details). In the latter case, the memory occupied by the new bit vector is released first (i.e., "free"d) before the exception is actually raised. =item * C<$vector = Bit::Vector-Enew_Enum($bits,$string);> This method is an alternative constructor which allows you to create a new bit vector object (with "C<$bits>" bits) and to initialize it all in one go. The method internally first calls the bit vector constructor method "C" and then passes the given string to the method "C". However, this method is more efficient than performing these two steps separately: First because in this method, "C" does not initialize the memory area occupied by the new bit vector with zeros (which is pointless in this case, because "C" will do it anyway), and second because it saves you from the associated overhead of one additional method invocation. An exception will be raised if the necessary memory cannot be allocated (see the description of the method "C" above for possible causes) or if the given string cannot be converted successfully (see the description of the method "C" further below for details). In the latter case, the memory occupied by the new bit vector is released first (i.e., "free"d) before the exception is actually raised. =item * C<$vector = Bit::Vector-EConcat_List(@vectors);> This method creates a new vector containing all bit vectors from the argument list in concatenated form. The argument list may contain any number of arguments (including zero); the only condition is that all arguments must be bit vectors. There is no condition concerning the length (in number of bits) of these arguments. The vectors from the argument list are not changed in any way. If the argument list is empty or if all arguments have length zero, the resulting bit vector will also have length zero. Note that the B bit vector from the argument list will become the B significant part of the resulting bit vector, and the B bit vector from the argument list will become the B significant part of the resulting bit vector. =back =head2 OBJECT METHODS =over 2 =item * C<$vec2 = $vec1-Enew($bits);> C<@veclist = $vec-Enew($bits);> This is an alternative way of calling the bit vector constructor method. Vector "C<$vec1>" (or "C<$vec>") is not affected by this, it just serves as an anchor for the method invocation mechanism. In fact B class methods in this module can be called this way, even though this is probably considered to be "politically incorrect" by OO ("object-orientation") aficionados. ;-) So even if you are too lazy to type "C>" instead of "C<$vec1-E>" (and even though laziness is - allegedly - a programmer's virtue C<:-)>), maybe it is better not to use this feature if you don't want to get booed at. ;-) =item * C<$vec2 = $vec1-EShadow();> Creates a B bit vector "C<$vec2>" of the B as "C<$vec1>" but which is B. Just like a shadow that has the same shape as the object it originates from, but is flat and has no volume, i.e., contains nothing. =item * C<$vec2 = $vec1-EClone();> Creates a B bit vector "C<$vec2>" of the B as "C<$vec1>" which is an B of "C<$vec1>". =item * C<$vector = $vec1-EConcat($vec2);> This method returns a new bit vector object which is the result of the concatenation of the contents of "C<$vec1>" and "C<$vec2>". Note that the contents of "C<$vec1>" become the B significant part of the resulting bit vector, and "C<$vec2>" the B significant part. If both bit vector arguments have length zero, the resulting bit vector will also have length zero. =item * C<$vector = $vec1-EConcat_List($vec2,$vec3,...);> This is an alternative way of calling this (class) method as an object method. The method returns a new bit vector object which is the result of the concatenation of the contents of C<$vec1 . $vec2 . $vec3 . ...> See the section "class methods" above for a detailed description of this method. Note that the argument list may be empty and that all arguments must be bit vectors if it isn't. =item * C<$bits = $vector-ESize();> Returns the size (number of bits) the given vector was created with (or "C"d to). =item * C<$vector-EResize($bits);> Changes the size of the given vector to the specified number of bits. This method allows you to change the size of an existing bit vector, preserving as many bits from the old vector as will fit into the new one (i.e., all bits with indices smaller than the minimum of the sizes of both vectors, old and new). If the number of machine words needed to store the new vector is smaller than or equal to the number of words needed to store the old vector, the memory allocated for the old vector is reused for the new one, and only the relevant book-keeping information is adjusted accordingly. This means that even if the number of bits increases, new memory is not necessarily being allocated (i.e., if the old and the new number of bits fit into the same number of machine words). If the number of machine words needed to store the new vector is greater than the number of words needed to store the old vector, new memory is allocated for the new vector, the old vector is copied to the new one, the remaining bits in the new vector are cleared (turned off) and the old vector is deleted, i.e., the memory that was allocated for it is released. (An exception will be raised if the method is unable to allocate the necessary memory for the new vector.) As a consequence, if you decrease the size of a given vector so that it will use fewer machine words, and increase it again later so that it will use more words than immediately before but still less than the original vector, new memory will be allocated anyway because the information about the size of the original vector is lost whenever you resize it. Note also that if you specify a negative number for "C<$bits>" it will be interpreted as a large positive number due to its internal two's complement binary representation. In such a case, "Resize()" will obediently attempt to create a bit vector of that size, probably resulting in an exception, as explained above. Finally, note that - in contrast to previous versions - resizing a bit vector to a size of zero bits (length zero) is now permitted. =item * C<$vec2-ECopy($vec1);> Copies the contents of bit vector "C<$vec1>" to bit vector "C<$vec2>". The previous contents of bit vector "C<$vec2>" get overwritten, i.e., are lost. Both vectors must exist beforehand, i.e., this method does not B any new bit vector object. The two vectors may be of any size. If the source bit vector is larger than the target, this method will copy as much of the least significant bits of the source vector as will fit into the target vector, thereby discarding any extraneous most significant bits. BEWARE that this causes a brutal cutoff in the middle of your data, and it will also leave you with an almost unpredictable sign if subsequently the number in the target vector is going to be interpreted as a number! (You have been warned!) If the target bit vector is larger than the source, this method fills up the remaining most significant bits in the target bit vector with either 0's or 1's, depending on the sign (= the most significant bit) of the source bit vector. This is also known as "sign extension". This makes it possible to copy numbers from a smaller bit vector into a larger one while preserving the number's absolute value as well as its sign (due to the two's complement binary representation of numbers). =item * C<$vector-EEmpty();> Clears all bits in the given vector. =item * C<$vector-EFill();> Sets all bits in the given vector. =item * C<$vector-EFlip();> Flips (i.e., complements) all bits in the given vector. =item * C<$vector-EPrimes();> Clears the given bit vector and sets all bits whose indices are prime numbers. This method uses the algorithm known as the "Sieve of Erathostenes" internally. =item * C<$vec2-EReverse($vec1);> This method copies the given vector "C<$vec1>" to the vector "C<$vec2>", thereby reversing the order of all bits. I.e., the least significant bit of "C<$vec1>" becomes the most significant bit of "C<$vec2>", whereas the most significant bit of "C<$vec1>" becomes the least significant bit of "C<$vec2>", and so forth for all bits in between. Note that in-place processing is also possible, i.e., "C<$vec1>" and "C<$vec2>" may be identical. (Internally, this is the same as C<$vec1-EInterval_Reverse(0,$vec1-ESize()-1);>.) =item * C<$vector-EInterval_Empty($min,$max);> Clears all bits in the interval C<[$min..$max]> (including both limits) in the given vector. "C<$min>" and "C<$max>" may have the same value; this is the same as clearing a single bit with "C" (but less efficient). Note that C<$vector-EInterval_Empty(0,$vector-ESize()-1);> is the same as C<$vector-EEmpty();> (but less efficient). =item * C<$vector-EInterval_Fill($min,$max);> Sets all bits in the interval C<[$min..$max]> (including both limits) in the given vector. "C<$min>" and "C<$max>" may have the same value; this is the same as setting a single bit with "C" (but less efficient). Note that C<$vector-EInterval_Fill(0,$vector-ESize()-1);> is the same as C<$vector-EFill();> (but less efficient). =item * C<$vector-EInterval_Flip($min,$max);> Flips (i.e., complements) all bits in the interval C<[$min..$max]> (including both limits) in the given vector. "C<$min>" and "C<$max>" may have the same value; this is the same as flipping a single bit with "C" (but less efficient). Note that C<$vector-EInterval_Flip(0,$vector-ESize()-1);> is the same as C<$vector-EFlip();> and C<$vector-EComplement($vector);> (but less efficient). =item * C<$vector-EInterval_Reverse($min,$max);> Reverses the order of all bits in the interval C<[$min..$max]> (including both limits) in the given vector. I.e., bits "C<$min>" and "C<$max>" swap places, and so forth for all bits in between. "C<$min>" and "C<$max>" may have the same value; this has no effect whatsoever, though. =item * CInterval_Scan_inc($start))> Returns the minimum and maximum indices of the next contiguous block of set bits (i.e., bits in the "on" state). The search starts at index "C<$start>" (i.e., C<"$min" E= "$start">) and proceeds upwards (i.e., C<"$max" E= "$min">), thus repeatedly increments the search pointer "C<$start>" (internally). Note though that the contents of the variable (or scalar literal value) "C<$start>" is B altered. I.e., you have to set it to the desired value yourself prior to each call to "C" (see also the example given below). Actually, the bit vector is not searched bit by bit, but one machine word at a time, in order to speed up execution (which means that this method is quite efficient). An empty list is returned if no such block can be found. Note that a single set bit (surrounded by cleared bits) is a valid block by this definition. In that case the return values for "C<$min>" and "C<$max>" are the same. Typical use: $start = 0; while (($start < $vector->Size()) && (($min,$max) = $vector->Interval_Scan_inc($start))) { $start = $max + 2; # do something with $min and $max } =item * CInterval_Scan_dec($start))> Returns the minimum and maximum indices of the next contiguous block of set bits (i.e., bits in the "on" state). The search starts at index "C<$start>" (i.e., C<"$max" E= "$start">) and proceeds downwards (i.e., C<"$min" E= "$max">), thus repeatedly decrements the search pointer "C<$start>" (internally). Note though that the contents of the variable (or scalar literal value) "C<$start>" is B altered. I.e., you have to set it to the desired value yourself prior to each call to "C" (see also the example given below). Actually, the bit vector is not searched bit by bit, but one machine word at a time, in order to speed up execution (which means that this method is quite efficient). An empty list is returned if no such block can be found. Note that a single set bit (surrounded by cleared bits) is a valid block by this definition. In that case the return values for "C<$min>" and "C<$max>" are the same. Typical use: $start = $vector->Size() - 1; while (($start >= 0) && (($min,$max) = $vector->Interval_Scan_dec($start))) { $start = $min - 2; # do something with $min and $max } =item * C<$vec2-EInterval_Copy($vec1,$offset2,$offset1,$length);> This method allows you to copy a stretch of contiguous bits (starting at any position "C<$offset1>" you choose, with a length of "C<$length>" bits) from a given "source" bit vector "C<$vec1>" to another position "C<$offset2>" in a "target" bit vector "C<$vec2>". Note that the two bit vectors "C<$vec1>" and "C<$vec2>" do B need to have the same (matching) size! Consequently, any of the two terms "C<$offset1 + $length>" and "C<$offset2 + $length>" (or both) may exceed the actual length of its corresponding bit vector ("C<$vec1-ESize()>" and "C<$vec2-ESize()>", respectively). In such a case, the "C<$length>" parameter is automatically reduced internally so that both terms above are bounded by the number of bits of their corresponding bit vector. This may even result in a length of zero, in which case nothing is copied at all. (Of course the value of the "C<$length>" parameter, supplied by you in the initial method call, may also be zero right from the start!) Note also that "C<$offset1>" and "C<$offset2>" must lie within the range "C<0>" and, respectively, "C<$vec1-ESize()-1>" or "C<$vec2-ESize()-1>", or a fatal "offset out of range" error will occur. Note further that "C<$vec1>" and "C<$vec2>" may be identical, i.e., you may copy a stretch of contiguous bits from one part of a given bit vector to another part. The source and the target interval may even overlap, in which case the copying is automatically performed in ascending or descending order (depending on the direction of the copy - downwards or upwards in the bit vector, respectively) to handle this situation correctly, i.e., so that no bits are being overwritten before they have been copied themselves. =item * C<$vec2-EInterval_Substitute($vec1,$off2,$len2,$off1,$len1);> This method is (roughly) the same for bit vectors (i.e., arrays of booleans) as what the "splice" function in Perl is for lists (i.e., arrays of scalars). (See L for more details about this function.) The method allows you to substitute a stretch of contiguous bits (defined by a position (offset) "C<$off1>" and a length of "C<$len1>" bits) from a given "source" bit vector "C<$vec1>" for a different stretch of contiguous bits (defined by a position (offset) "C<$off2>" and a length of "C<$len2>" bits) in another, "target" bit vector "C<$vec2>". Note that the two bit vectors "C<$vec1>" and "C<$vec2>" do B need to have the same (matching) size! Note further that "C<$off1>" and "C<$off2>" must lie within the range "C<0>" and, respectively, "C<$vec1-ESize()>" or "C<$vec2-ESize()>", or a fatal "offset out of range" error will occur. Alert readers will have noticed that these upper limits are B "C<$vec1-ESize()-1>" and "C<$vec2-ESize()-1>", as they would be for any other method in this module, but that these offsets may actually point to one position B of the corresponding bit vector. This is necessary in order to make it possible to B a given stretch of bits to the target bit vector instead of B something in it. For reasons of symmetry and generality, the same applies to the offset in the source bit vector, even though such an offset (one position past the end of the bit vector) does not serve any practical purpose there (but does not cause any harm either). (Actually this saves you from the need of testing for this special case, in certain circumstances.) Note that whenever the term "C<$off1 + $len1>" exceeds the size "C<$vec1-ESize()>" of bit vector "C<$vec1>" (or if "C<$off2 + $len2>" exceeds "C<$vec2-ESize()>"), the corresponding length ("C<$len1>" or "C<$len2>", respectively) is automatically reduced internally so that "C<$off1 + $len1 E= $vec1-ESize()>" (and "C<$off2 + $len2 E= $vec2-ESize()>") holds. (Note that this does B alter the intended result, even though this may seem counter-intuitive at first!) This may even result in a length ("C<$len1>" or "C<$len2>") of zero. A length of zero for the interval in the B bit vector ("C<$len1 == 0>") means that the indicated stretch of bits in the target bit vector (starting at position "C<$off2>") is to be replaced by B, i.e., is to be B. A length of zero for the interval in the B bit vector ("C<$len2> == 0") means that B is replaced, and that the stretch of bits from the source bit vector is simply B into the target bit vector at the indicated position ("C<$off2>"). If both length parameters are zero, nothing is done at all. Note that in contrast to any other method in this module (especially "C", "C" and "C"), this method B and B adapts the length of the resulting bit vector as needed, as given by $size = $vec2->Size(); # before $size += $len1 - $len2; # after (The only other method in this module that changes the size of a bit vector is the method "C".) In other words, replacing a given interval of bits in the target bit vector with a longer or shorter stretch of bits from the source bit vector, or simply inserting ("C<$len2 == 0>") a stretch of bits into or deleting ("C<$len1 == 0>") an interval of bits from the target bit vector will automatically increase or decrease, respectively, the size of the target bit vector accordingly. For the sake of generality, this may even result in a bit vector with a size of zero (containing no bits at all). This is also the reason why bit vectors of length zero are permitted in this module in the first place, starting with version 5.0. Finally, note that "C<$vec1>" and "C<$vec2>" may be identical, i.e., in-place processing is possible. (If you think about that for a while or if you look at the code, you will see that this is far from trivial!) =item * Cis_empty())> Tests whether the given bit vector is empty, i.e., whether B of its bits are cleared (in the "off" state). In "big integer" arithmetic, this is equivalent to testing whether the number stored in the bit vector is zero ("C<0>"). Returns "true" ("C<1>") if the bit vector is empty and "false" ("C<0>") otherwise. Note that this method also returns "true" ("C<1>") if the given bit vector has a length of zero, i.e., if it contains no bits at all. =item * Cis_full())> Tests whether the given bit vector is full, i.e., whether B of its bits are set (in the "on" state). In "big integer" arithmetic, this is equivalent to testing whether the number stored in the bit vector is minus one ("-1"). Returns "true" ("C<1>") if the bit vector is full and "false" ("C<0>") otherwise. If the given bit vector has a length of zero (i.e., if it contains no bits at all), this method returns "false" ("C<0>"). =item * Cequal($vec2))> Tests the two given bit vectors for equality. Returns "true" ("C<1>") if the two bit vectors are exact copies of one another and "false" ("C<0>") otherwise. =item * C<$cmp = $vec1-ELexicompare($vec2);> Compares the two given bit vectors, which are regarded as B numbers in binary representation. The method returns "C<-1>" if the first bit vector is smaller than the second bit vector, "C<0>" if the two bit vectors are exact copies of one another and "C<1>" if the first bit vector is greater than the second bit vector. =item * C<$cmp = $vec1-ECompare($vec2);> Compares the two given bit vectors, which are regarded as B numbers in binary representation. The method returns "C<-1>" if the first bit vector is smaller than the second bit vector, "C<0>" if the two bit vectors are exact copies of one another and "C<1>" if the first bit vector is greater than the second bit vector. =item * C<$string = $vector-Eto_Hex();> Returns a hexadecimal string representing the given bit vector. Note that this representation is quite compact, in that it only needs at most twice the number of bytes needed to store the bit vector itself, internally. Note also that since a hexadecimal digit is always worth four bits, the length of the resulting string is always a multiple of four bits, regardless of the true length (in bits) of the given bit vector. Finally, note that the B significant hexadecimal digit is located at the B end of the resulting string, and the B significant digit at the B end. =item * C<$vector-Efrom_Hex($string);> Allows to read in the contents of a bit vector from a hexadecimal string, such as returned by the method "C" (see above). Remember that the least significant bits are always to the right of a hexadecimal string, and the most significant bits to the left. Therefore, the string is actually read in from right to left while the bit vector is filled accordingly, 4 bits at a time, starting with the least significant bits and going upward to the most significant bits. If the given string contains less hexadecimal digits than are needed to completely fill the given bit vector, the remaining (most significant) bits are all cleared. This also means that, even if the given string does not contain enough digits to completely fill the given bit vector, the previous contents of the bit vector are erased completely. If the given string is longer than it needs to fill the given bit vector, the superfluous characters are simply ignored. (In fact they are ignored completely - they are not even checked for proper syntax. See also below for more about that.) This behaviour is intentional so that you may read in the string representing one bit vector into another bit vector of different size, i.e., as much of it as will fit. If during the process of reading the given string any character is encountered which is not a hexadecimal digit, a fatal syntax error ensues ("input string syntax error"). =item * C<$string = $vector-Eto_Bin();> Returns a binary string representing the given bit vector. Example: $vector = Bit::Vector->new(8); $vector->Primes(); $string = $vector->to_Bin(); print "'$string'\n"; This prints: '10101100' (Bits #7, #5, #3 and #2 are set.) Note that the B significant bit is located at the B end of the resulting string, and the B significant bit at the B end. =item * C<$vector-Efrom_Bin($string);> This method allows you to read in the contents of a bit vector from a binary string, such as returned by the method "C" (see above). Note that this method assumes that the B significant bit is located at the B end of the binary string, and the B significant bit at the B end. Therefore, the string is actually read in from right to left while the bit vector is filled accordingly, one bit at a time, starting with the least significant bit and going upward to the most significant bit. If the given string contains less binary digits ("C<0>" and "C<1>") than are needed to completely fill the given bit vector, the remaining (most significant) bits are all cleared. This also means that, even if the given string does not contain enough digits to completely fill the given bit vector, the previous contents of the bit vector are erased completely. If the given string is longer than it needs to fill the given bit vector, the superfluous characters are simply ignored. (In fact they are ignored completely - they are not even checked for proper syntax. See also below for more about that.) This behaviour is intentional so that you may read in the string representing one bit vector into another bit vector of different size, i.e., as much of it as will fit. If during the process of reading the given string any character is encountered which is not either "C<0>" or "C<1>", a fatal syntax error ensues ("input string syntax error"). =item * C<$string = $vector-Eto_Dec();> This method returns a string representing the contents of the given bit vector converted to decimal (base C<10>). Note that this method assumes the given bit vector to be B (and to contain a number in two's complement binary representation). Consequently, whenever the most significant bit of the given bit vector is set, the number stored in it is regarded as being B. The resulting string can be fed into "C" (see below) in order to copy the contents of this bit vector to another one (or to restore the contents of this one). This is not advisable, though, since this would be very inefficient (there are much more efficient methods for storing and copying bit vectors in this module). Note that such conversion from binary to decimal is inherently slow since the bit vector has to be repeatedly divided by C<10> with remainder until the quotient becomes C<0> (each remainder in turn represents a single decimal digit of the resulting string). This is also true for the implementation of this method in this module, even though a considerable effort has been made to speed it up: instead of repeatedly dividing by C<10>, the bit vector is repeatedly divided by the largest power of C<10> that will fit into a machine word. The remainder is then repeatedly divided by C<10> using only machine word arithmetics, which is much faster than dividing the whole bit vector ("divide and rule" principle). According to my own measurements, this resulted in an 8-fold speed increase over the straightforward approach. Still, conversion to decimal should be used only where absolutely necessary. Keep the resulting string stored in some variable if you need it again, instead of converting the bit vector all over again. Beware that if you set the configuration for overloaded operators to "output=decimal", this method will be called for every bit vector enclosed in double quotes! =item * C<$vector-Efrom_Dec($string);> This method allows you to convert a given decimal number, which may be positive or negative, into two's complement binary representation, which is then stored in the given bit vector. The decimal number should always be provided as a string, to avoid possible truncation (due to the limited precision of integers in Perl) or formatting (due to Perl's use of scientific notation for large numbers), which would lead to errors. If the binary representation of the given decimal number is too big to fit into the given bit vector (if the given bit vector does not contain enough bits to hold it), a fatal "numeric overflow error" occurs. If the input string contains other characters than decimal digits (C<0-9>) and an optional leading sign ("C<+>" or "C<->"), a fatal "input string syntax error" occurs. Beware that large positive numbers which cause the most significant bit to be set (e.g. "255" in a bit vector with 8 bits) will be printed as negative numbers when converted back to decimal using the method "to_Dec()" (e.g. "-1", in our example), because numbers with the most significant bit set are considered to be negative in two's complement binary representation. Note also that while it is possible to thusly enter negative numbers as large positive numbers (e.g. "255" for "-1" in a bit vector with 8 bits), the contrary isn't, i.e., you cannot enter "-255" for "+1", in our example. A fatal "numeric overflow error" will occur if you try to do so. If possible program abortion is unwanted or intolerable, use "C", like this: eval { $vector->from_Dec("1152921504606846976"); }; if ($@) { # an error occurred } There are four possible error messages: if ($@ =~ /item is not a string/) if ($@ =~ /input string syntax error/) if ($@ =~ /numeric overflow error/) if ($@ =~ /unable to allocate memory/) Note that the conversion from decimal to binary is costly in terms of processing time, since a lot of multiplications have to be carried out (in principle, each decimal digit must be multiplied with the binary representation of the power of C<10> corresponding to its position in the decimal number, i.e., 1, 10, 100, 1000, 10000 and so on). This is not as time consuming as the opposite conversion, from binary to decimal (where successive divisions have to be carried out, which are even more expensive than multiplications), but still noticeable. Again (as in the case of "C"), the implementation of this method in this module uses the principle of "divide and rule" in order to speed up the conversion, i.e., as many decimal digits as possible are first accumulated (converted) in a machine word and only then stored in the given bit vector. Even so, use this method only where absolutely necessary if speed is an important consideration in your application. Beware that if you set the configuration for overloaded operators to "input=decimal", this method will be called for every scalar operand you use! =item * C<$string = $vector-Eto_Enum();> Converts the given bit vector or set into an enumeration of single indices and ranges of indices (".newsrc" style), representing the bits that are set ("C<1>") in the bit vector. Example: $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"; which prints '2,3,5-7,11,13-19' If the given bit vector is empty, the resulting string will also be empty. Note, by the way, that the above example can also be written a little handier, perhaps, as follows: 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"; =item * C<$vector-Efrom_Enum($string);> This method first empties the given bit vector and then tries to set the bits and ranges of bits specified in the given string. The string "C<$string>" must only contain unsigned integers or ranges of integers (two unsigned integers separated by a dash "-"), separated by commas (","). All other characters are disallowed (including white space!) and will lead to a fatal "input string syntax error". In each range, the first integer (the lower limit of the range) must always be less than or equal to the second integer (the upper limit), or a fatal "minimum > maximum index" error occurs. All integers must lie in the permitted range for the given bit vector, i.e., they must lie between "C<0>" and "C<$vector-ESize()-1>". If this condition is not met, a fatal "index out of range" error occurs. If possible program abortion is unwanted or intolerable, use "C", like this: eval { $vector->from_Enum("2,3,5-7,11,13-19"); }; if ($@) { # an error occurred } There are four possible error messages: if ($@ =~ /item is not a string/) if ($@ =~ /input string syntax error/) if ($@ =~ /index out of range/) if ($@ =~ /minimum > maximum index/) Note that the order of the indices and ranges is irrelevant, i.e., eval { $vector->from_Enum("11,5-7,3,13-19,2"); }; results in the same vector as in the example above. Ranges and indices may also overlap. This is because each (single) index in the string is passed to the method "C", internally, and each range to the method "C". This means that the resulting bit vector is just the union of all the indices and ranges specified in the given string. =item * C<$vector-EBit_Off($index);> Clears the bit with index "C<$index>" in the given vector. =item * C<$vector-EBit_On($index);> Sets the bit with index "C<$index>" in the given vector. =item * C<$vector-Ebit_flip($index)> Flips (i.e., complements) the bit with index "C<$index>" in the given vector. Moreover, this method returns the B state of the bit in question, i.e., it returns "C<0>" if the bit is cleared or "C<1>" if the bit is set (B flipping it). =item * Cbit_test($index))> Ccontains($index))> Returns the current state of the bit with index "C<$index>" in the given vector, i.e., returns "C<0>" if it is cleared (in the "off" state) or "C<1>" if it is set (in the "on" state). =item * C<$vector-EBit_Copy($index,$bit);> Sets the bit with index "C<$index>" in the given vector either to "C<0>" or "C<1>" depending on the boolean value "C<$bit>". =item * C<$vector-ELSB($bit);> Allows you to set the least significant bit in the given bit vector to the value given by the boolean parameter "C<$bit>". This is a (faster) shortcut for "C<$vector-EBit_Copy(0,$bit);>". =item * C<$vector-EMSB($bit);> Allows you to set the most significant bit in the given bit vector to the value given by the boolean parameter "C<$bit>". This is a (faster) shortcut for "C<$vector-EBit_Copy($vector-ESize()-1,$bit);>". =item * C<$bit = $vector-Elsb();> Returns the least significant bit of the given bit vector. This is a (faster) shortcut for "C<$bit = $vector-Ebit_test(0);>". =item * C<$bit = $vector-Emsb();> Returns the most significant bit of the given bit vector. This is a (faster) shortcut for "C<$bit = $vector-Ebit_test($vector-ESize()-1);>". =item * C<$carry_out = $vector-Erotate_left();> carry MSB vector: LSB out: +---+ +---+---+---+--- ---+---+---+---+ | | <---+--- | | | | ... | | | | <---+ +---+ | +---+---+---+--- ---+---+---+---+ | | | +------------------------------------------------+ The least significant bit (LSB) is the bit with index "C<0>", the most significant bit (MSB) is the bit with index "C<$vector-ESize()-1>". =item * C<$carry_out = $vector-Erotate_right();> MSB vector: LSB carry out: +---+---+---+--- ---+---+---+---+ +---+ +---> | | | | ... | | | | ---+---> | | | +---+---+---+--- ---+---+---+---+ | +---+ | | +------------------------------------------------+ The least significant bit (LSB) is the bit with index "C<0>", the most significant bit (MSB) is the bit with index "C<$vector-ESize()-1>". =item * C<$carry_out = $vector-Eshift_left($carry_in);> carry MSB vector: LSB carry out: in: +---+ +---+---+---+--- ---+---+---+---+ +---+ | | <--- | | | | ... | | | | <--- | | +---+ +---+---+---+--- ---+---+---+---+ +---+ The least significant bit (LSB) is the bit with index "C<0>", the most significant bit (MSB) is the bit with index "C<$vector-ESize()-1>". =item * C<$carry_out = $vector-Eshift_right($carry_in);> carry MSB vector: LSB carry in: out: +---+ +---+---+---+--- ---+---+---+---+ +---+ | | ---> | | | | ... | | | | ---> | | +---+ +---+---+---+--- ---+---+---+---+ +---+ The least significant bit (LSB) is the bit with index "C<0>", the most significant bit (MSB) is the bit with index "C<$vector-ESize()-1>". =item * C<$vector-EMove_Left($bits);> Shifts the given bit vector left by "C<$bits>" bits, i.e., inserts "C<$bits>" new bits at the lower end (least significant bit) of the bit vector, moving all other bits up by "C<$bits>" places, thereby losing the "C<$bits>" most significant bits. The inserted new bits are all cleared (set to the "off" state). This method does nothing if "C<$bits>" is equal to zero. Beware that the whole bit vector is cleared B if "C<$bits>" is greater than or equal to the size of the given bit vector! In fact this method is equivalent to for ( $i = 0; $i < $bits; $i++ ) { $vector->shift_left(0); } except that it is much more efficient (for "C<$bits>" greater than or equal to the number of bits in a machine word on your system) than this straightforward approach. =item * C<$vector-EMove_Right($bits);> Shifts the given bit vector right by "C<$bits>" bits, i.e., deletes the "C<$bits>" least significant bits of the bit vector, moving all other bits down by "C<$bits>" places, thereby creating "C<$bits>" new bits at the upper end (most significant bit) of the bit vector. These new bits are all cleared (set to the "off" state). This method does nothing if "C<$bits>" is equal to zero. Beware that the whole bit vector is cleared B if "C<$bits>" is greater than or equal to the size of the given bit vector! In fact this method is equivalent to for ( $i = 0; $i < $bits; $i++ ) { $vector->shift_right(0); } except that it is much more efficient (for "C<$bits>" greater than or equal to the number of bits in a machine word on your system) than this straightforward approach. =item * C<$vector-EInsert($offset,$bits);> This method inserts "C<$bits>" fresh new bits at position "C<$offset>" in the given bit vector. The "C<$bits>" most significant bits are lost, and all bits starting with bit number "C<$offset>" up to and including bit number "C<$vector-ESize()-$bits-1>" are moved up by "C<$bits>" places. The now vacant "C<$bits>" bits starting at bit number "C<$offset>" (up to and including bit number "C<$offset+$bits-1>") are then set to zero (cleared). Note that this method does B increase the size of the given bit vector, i.e., the bit vector is B extended at its upper end to "rescue" the "C<$bits>" uppermost (most significant) bits - instead, these bits are lost forever. If you don't want this to happen, you have to increase the size of the given bit vector B and B you perform the "Insert" operation, with a statement such as the following: $vector->Resize($vector->Size() + $bits); Or use the method "C" instead of "C", which performs automatic growing and shrinking of its target bit vector. Note also that "C<$offset>" must lie in the permitted range between "C<0>" and "C<$vector-ESize()-1>", or a fatal "offset out of range" error will occur. If the term "C<$offset + $bits>" exceeds "C<$vector-ESize()-1>", all the bits starting with bit number "C<$offset>" up to bit number "C<$vector-ESize()-1>" are simply cleared. =item * C<$vector-EDelete($offset,$bits);> This method deletes, i.e., removes the bits starting at position "C<$offset>" up to and including bit number "C<$offset+$bits-1>" from the given bit vector. The remaining uppermost bits (starting at position "C<$offset+$bits>" up to and including bit number "C<$vector-ESize()-1>") are moved down by "C<$bits>" places. The now vacant uppermost (most significant) "C<$bits>" bits are then set to zero (cleared). Note that this method does B decrease the size of the given bit vector, i.e., the bit vector is B clipped at its upper end to "get rid of" the vacant "C<$bits>" uppermost bits. If you don't want this, i.e., if you want the bit vector to shrink accordingly, you have to do so B and B the "Delete" operation, with a couple of statements such as these: $size = $vector->Size(); if ($bits > $size) { $bits = $size; } $vector->Resize($size - $bits); Or use the method "C" instead of "C", which performs automatic growing and shrinking of its target bit vector. Note also that "C<$offset>" must lie in the permitted range between "C<0>" and "C<$vector-ESize()-1>", or a fatal "offset out of range" error will occur. If the term "C<$offset + $bits>" exceeds "C<$vector-ESize()-1>", all the bits starting with bit number "C<$offset>" up to bit number "C<$vector-ESize()-1>" are simply cleared. =item * C<$carry = $vector-Eincrement();> This method increments the given bit vector. Note that this method regards bit vectors as being unsigned, i.e., the largest possible positive number is directly followed by the smallest possible (or greatest possible, speaking in absolute terms) negative number: before: 2 ^ (b-1) - 1 (= "0111...1111") after: 2 ^ (b-1) (= "1000...0000") where "C" is the number of bits of the given bit vector. The method returns "false" ("C<0>") in all cases except when a carry over occurs (in which case it returns "true", i.e., "C<1>"), which happens when the number "1111...1111" is incremented, which gives "0000...0000" plus a carry over to the next higher (binary) digit. This can be used for the terminating condition of a "while" loop, for instance, in order to cycle through all possible values the bit vector can assume. =item * C<$carry = $vector-Edecrement();> This method decrements the given bit vector. Note that this method regards bit vectors as being unsigned, i.e., the smallest possible (or greatest possible, speaking in absolute terms) negative number is directly followed by the largest possible positive number: before: 2 ^ (b-1) (= "1000...0000") after: 2 ^ (b-1) - 1 (= "0111...1111") where "C" is the number of bits of the given bit vector. The method returns "false" ("C<0>") in all cases except when a carry over occurs (in which case it returns "true", i.e., "C<1>"), which happens when the number "0000...0000" is decremented, which gives "1111...1111" minus a carry over to the next higher (binary) digit. This can be used for the terminating condition of a "while" loop, for instance, in order to cycle through all possible values the bit vector can assume. =item * C<$overflow = $vec2-Einc($vec1);> This method copies the contents of bit vector "C<$vec1>" to bit vector "C<$vec2>" and increments the copy (not the original). If by incrementing the number its sign becomes invalid, the return value ("overflow" flag) will be true ("C<1>"), or false ("C<0>") if not. (See the description of the method "add()" below for a more in-depth explanation of what "overflow" means). Note that in-place operation is also possible, i.e., "C<$vec1>" and "C<$vec2>" may be identical. =item * C<$overflow = $vec2-Edec($vec1);> This method copies the contents of bit vector "C<$vec1>" to bit vector "C<$vec2>" and decrements the copy (not the original). If by decrementing the number its sign becomes invalid, the return value ("overflow" flag) will be true ("C<1>"), or false ("C<0>") if not. (See the description of the method "subtract()" below for a more in-depth explanation of what "overflow" means). Note that in-place operation is also possible, i.e., "C<$vec1>" and "C<$vec2>" may be identical. =item * C<$carry = $vec3-Eadd($vec1,$vec2,$carry);> C<($carry,$overflow) = $vec3-Eadd($vec1,$vec2,$carry);> This method adds the two numbers contained in bit vector "C<$vec1>" and "C<$vec2>" with carry "C<$carry>" and stores the result in bit vector "C<$vec3>". I.e., $vec3 = $vec1 + $vec2 + $carry Note that the "C<$carry>" parameter is a boolean value, i.e., only its least significant bit is taken into account. (Think of it as though "C<$carry &= 1;>" was always executed internally.) In scalar context, the method returns a boolean value which indicates if a carry over (to the next higher bit position) has occured. In list context, the method returns the carry and the overflow flag (in this order). The overflow flag is true ("C<1>") if the sign (i.e., the most significant bit) of the result is wrong. This can happen when adding two very large positive numbers or when adding two (by their absolute value) very large negative numbers. See also further below. The carry in- and output is needed mainly for cascading, i.e., to add numbers that are fragmented into several pieces. Example: # initialize for ( $i = 0; $i < $n; $i++ ) { $a[$i] = Bit::Vector->new($bits); $b[$i] = Bit::Vector->new($bits); $c[$i] = Bit::Vector->new($bits); } # fill @a and @b # $a[ 0 ] is low order part, # $a[$n-1] is high order part, # and same for @b # add $carry = 0; for ( $i = 0; $i < $n; $i++ ) { $carry = $c[$i]->add($a[$i],$b[$i],$carry); } Note that it makes no difference to this method whether the numbers in "C<$vec1>" and "C<$vec2>" are unsigned or signed (i.e., in two's complement binary representation). Note however that the return value (carry flag) is not meaningful when the numbers are B. Moreover, when the numbers are signed, a special type of error can occur which is commonly called an "overflow error". An overflow error occurs when the sign of the result (its most significant bit) is flipped (i.e., falsified) by a carry over from the next-lower bit position ("MSB-1"). In fact matters are a bit more complicated than that: the overflow flag is set to "true" whenever there is a carry over from bit position MSB-1 to the most significant bit (MSB) but no carry over from the MSB to the output carry flag, or vice-versa, i.e., when there is no carry over from bit position MSB-1 to the most significant bit (MSB) but a carry over to the output carry flag. Thus the overflow flag is the result of an exclusive-or operation between incoming and outgoing carry over at the most significant bit position. =item * C<$carry = $vec3-Esubtract($vec1,$vec2,$carry);> C<($carry,$overflow) = $vec3-Esubtract($vec1,$vec2,$carry);> This method subtracts the two numbers contained in bit vector "C<$vec1>" and "C<$vec2>" with carry "C<$carry>" and stores the result in bit vector "C<$vec3>". I.e., $vec3 = $vec1 - $vec2 - $carry Note that the "C<$carry>" parameter is a boolean value, i.e., only its least significant bit is taken into account. (Think of it as though "C<$carry &= 1;>" was always executed internally.) In scalar context, the method returns a boolean value which indicates if a carry over (to the next higher bit position) has occured. In list context, the method returns the carry and the overflow flag (in this order). The overflow flag is true ("C<1>") if the sign (i.e., the most significant bit) of the result is wrong. This can happen when subtracting a very large negative number from a very large positive number or vice-versa. See also further below. The carry in- and output is needed mainly for cascading, i.e., to subtract numbers that are fragmented into several pieces. Example: # initialize for ( $i = 0; $i < $n; $i++ ) { $a[$i] = Bit::Vector->new($bits); $b[$i] = Bit::Vector->new($bits); $c[$i] = Bit::Vector->new($bits); } # fill @a and @b # $a[ 0 ] is low order part, # $a[$n-1] is high order part, # and same for @b # subtract $carry = 0; for ( $i = 0; $i < $n; $i++ ) { $carry = $c[$i]->subtract($a[$i],$b[$i],$carry); } Note that it makes no difference to this method whether the numbers in "C<$vec1>" and "C<$vec2>" are unsigned or signed (i.e., in two's complement binary representation). Note however that the return value (carry flag) is not meaningful when the numbers are B. Moreover, when the numbers are signed, a special type of error can occur which is commonly called an "overflow error". An overflow error occurs when the sign of the result (its most significant bit) is flipped (i.e., falsified) by a carry over from the next-lower bit position ("MSB-1"). In fact matters are a bit more complicated than that: the overflow flag is set to "true" whenever there is a carry over from bit position MSB-1 to the most significant bit (MSB) but no carry over from the MSB to the output carry flag, or vice-versa, i.e., when there is no carry over from bit position MSB-1 to the most significant bit (MSB) but a carry over to the output carry flag. Thus the overflow flag is the result of an exclusive-or operation between incoming and outgoing carry over at the most significant bit position. =item * C<$vec2-ENeg($vec1);> C<$vec2-ENegate($vec1);> This method calculates the two's complement of the number in bit vector "C<$vec1>" and stores the result in bit vector "C<$vec2>". Calculating the two's complement of a given number in binary representation consists of inverting all bits and incrementing the result by one. This is the same as changing the sign of the given number from "C<+>" to "C<->" or vice-versa. In other words, applying this method twice on a given number yields the original number again. Note that in-place processing is also possible, i.e., "C<$vec1>" and "C<$vec2>" may be identical. Most importantly, beware that this method produces a counter-intuitive result if the number contained in bit vector "C<$vec1>" is C<2 ^ (n-1)> (i.e., "1000...0000"), where "C" is the number of bits the given bit vector contains: The negated value of this number is the number itself! =item * C<$vec2-EAbs($vec1);> C<$vec2-EAbsolute($vec1);> Depending on the sign (i.e., the most significant bit) of the number in bit vector "C<$vec1>", the contents of bit vector "C<$vec1>" are copied to bit vector "C<$vec2>" either with the method "C" (if the number in bit vector "C<$vec1>" is positive), or with "C" (if the number in bit vector "C<$vec1>" is negative). In other words, this method calculates the absolute value of the number in bit vector "C<$vec1>" and stores the result in bit vector "C<$vec2>". Note that in-place processing is also possible, i.e., "C<$vec1>" and "C<$vec2>" may be identical. Most importantly, beware that this method produces a counter-intuitive result if the number contained in bit vector "C<$vec1>" is C<2 ^ (n-1)> (i.e., "1000...0000"), where "C" is the number of bits the given bit vector contains: The absolute value of this number is the number itself, even though this number is still negative by definition (the most significant bit is still set)! =item * C<$sign = $vector-ESign();> This method returns "C<0>" if all bits in the given bit vector are cleared, i.e., if the given bit vector contains the number "C<0>", or if the given bit vector has a length of zero (contains no bits at all). If not all bits are cleared, this method returns "C<-1>" if the most significant bit is set (i.e., if the bit vector contains a negative number), or "C<1>" otherwise (i.e., if the bit vector contains a positive number). =item * C<$vec3-EMultiply($vec1,$vec2);> This method multiplies the two numbers contained in bit vector "C<$vec1>" and "C<$vec2>" and stores the result in bit vector "C<$vec3>". Note that this method regards its arguments as B. If you want to make sure that a large number can never be treated as being negative by mistake, make your bit vectors at least one bit longer than the largest number you wish to represent, right from the start, or proceed as follows: $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); Note also that all three bit vector arguments must in principle obey the rule of matching sizes, but that the bit vector "C<$vec3>" may be larger than the two factors "C<$vec1>" and "C<$vec2>". In fact multiplying two binary numbers with "C" bits may yield a result which is at most "C<2n>" bits long. Therefore, it is usually a good idea to let bit vector "C<$vec3>" have twice the size of bit vector "C<$vec1>" and "C<$vec2>", unless you are absolutely sure that the result will fit into a bit vector of the same size as the two factors. If you are wrong, a fatal "numeric overflow error" will occur. Finally, note that in-place processing is possible, i.e., "C<$vec3>" may be identical with "C<$vec1>" or "C<$vec2>", or both. =item * C<$quot-EDivide($vec1,$vec2,$rest);> This method divides the two numbers contained in bit vector "C<$vec1>" and "C<$vec2>" and stores the quotient in bit vector "C<$quot>" and the remainder in bit vector "C<$rest>". I.e., $quot = $vec1 / $vec2; # div $rest = $vec1 % $vec2; # mod Therefore, "C<$quot>" and "C<$rest>" must be two B bit vectors, or a fatal "result vector(s) must be distinct" error will occur. Note also that a fatal "division by zero error" will occur if "C<$vec2>" is equal to zero. Note further that this method regards its arguments as B. If you want to make sure that a large number can never be treated as being negative by mistake, make your bit vectors at least one bit longer than the largest number you wish to represent, right from the start, or proceed as follows: $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); Finally, note that in-place processing is possible, i.e., "C<$quot>" may be identical with "C<$vec1>" or "C<$vec2>" or both, and "C<$rest>" may also be identical with "C<$vec1>" or "C<$vec2>" or both, as long as "C<$quot>" and "C<$rest>" are distinct. (!) =item * C<$vecgcd-EGCD($veca,$vecb);> This method calculates the "Greatest Common Divisor" of the two numbers contained in bit vector "C<$veca>" and "C<$vecb>" and stores the result in bit vector "C<$vecgcd>". The method uses Euklid's algorithm internally: int GCD(int a, int b) { int t; while (b != 0) { t = a % b; /* = remainder of (a div b) */ a = b; b = t; } return(a); } Note that C. =item * C<$vecgcd-EGCD($vecx,$vecy,$veca,$vecb);> This variant of the "GCD" method calculates the "Greatest Common Divisor" of the two numbers contained in bit vector "C<$veca>" and "C<$vecb>" and stores the result in bit vector "C<$vecgcd>". Moreover, it determines the two factors which are necessary in order to represent the greatest common divisor as a linear combination of its two arguments, i.e., the two factors C<"x"> and C<"y"> so that C, and stores them in bit vector "C<$vecx>" and "C<$vecy>", respectively. For example: a = 2322 b = 654 GCD( 2322, 654 ) == 6 x = 20 y = -71 20 * 2322 - 71 * 654 == 6 Please see http://www.cut-the-knot.org/blue/extension.shtml for an explanation of how this extension of Euklid's algorithm works. =item * C<$vec3-EPower($vec1,$vec2);> This method calculates the exponentiation of base "C<$vec1>" elevated to the "C<$vec2>" power, i.e., "C<$vec1 ** $vec2>", and stores the result in bit vector "C<$vec3>". The method uses an efficient divide-and-conquer algorithm: Suppose the exponent is (decimal) 13, for example. The binary representation of this exponent is "1101". This means we want to calculate $vec1 * $vec1 * $vec1 * $vec1 * $vec1 * $vec1 * $vec1 * $vec1 * $vec1 * $vec1 * $vec1 * $vec1 * $vec1 That is, "C<$vec1>" multiplied with itself 13 times. The grouping into lines above is no coincidence. The first line comprises 8 factors, the second contains 4, and the last line just one. This just happens to be the binary representation of 13. C<;-)> We then calculate a series of squares (of squares of squares...) of the base, i.e., $power[0] = $vec1; $power[1] = $vec1 * $vec1; $power[2] = $power[1] * $power[1]; $power[3] = $power[2] * $power[2]; etc. To calculate the power of our example, we simply initialize our result with 1 and consecutively multiply it with the items of the series of powers we just calculated, if the corresponding bit of the binary representation of the exponent is set: $result = 1; $result *= $power[0] if ($vec2 & 1); $result *= $power[1] if ($vec2 & 2); $result *= $power[2] if ($vec2 & 4); $result *= $power[3] if ($vec2 & 8); etc. The bit vector "C<$vec3>" must be of the same size as the base "C<$vec1>" or greater. "C<$vec3>" and "C<$vec1>" may be the same vector (i.e., in-place calculation as in "C<$vec1 **= $vec2;>" is possible), but "C<$vec3>" and "C<$vec2>" must be distinct. Finally, the exponent "C<$vec2>" must be positive. A fatal error occurs if any of these conditions is not met. =item * C<$vector-EBlock_Store($buffer);> This method allows you to load the contents of a given bit vector in one go. This is useful when you store the contents of a bit vector in a file, for instance (using method "C"), and when you want to restore the previously saved bit vector. For this, "C<$buffer>" B be a string (B automatic conversion from numeric to string is provided here as would normally in Perl!) containing the bit vector in "low order byte first" order. If the given string is shorter than what is needed to completely fill the given bit vector, the remaining (most significant) bytes of the bit vector are filled with zeros, i.e., the previous contents of the bit vector are always erased completely. If the given string is longer than what is needed to completely fill the given bit vector, the superfluous bytes are simply ignored. See L for how to read in the contents of "C<$buffer>" from a file prior to passing it to this method. =item * C<$buffer = $vector-EBlock_Read();> This method allows you to export the contents of a given bit vector in one block. This is useful when you want to save the contents of a bit vector for later, for instance in a file. The advantage of this method is that it allows you to do so in the compactest possible format, in binary. The method returns a Perl string which contains an exact copy of the contents of the given bit vector in "low order byte first" order. See L for how to write the data from this string to a file. =item * C<$size = $vector-EWord_Size();> Each bit vector is internally organized as an array of machine words. The methods whose names begin with "Word_" allow you to access this internal array of machine words. Note that because the size of a machine word may vary from system to system, these methods are inherently B! Therefore, B these methods unless you are absolutely certain that portability of your code is not an issue! You have been warned! To be machine-independent, use the methods whose names begin with "C" instead, with chunk sizes no greater than 32 bits. The method "C" returns the number of machine words that the internal array of words of the given bit vector contains. This is similar in function to the term "C" for a Perl array. =item * C<$vector-EWord_Store($offset,$word);> This method allows you to store a given value "C<$word>" at a given position "C<$offset>" in the internal array of words of the given bit vector. Note that "C<$offset>" must lie in the permitted range between "C<0>" and "C<$vector-EWord_Size()-1>", or a fatal "offset out of range" error will occur. This method is similar in function to the expression "C<$array[$offset] = $word;>" for a Perl array. =item * C<$word = $vector-EWord_Read($offset);> This method allows you to access the value of a given machine word at position "C<$offset>" in the internal array of words of the given bit vector. Note that "C<$offset>" must lie in the permitted range between "C<0>" and "C<$vector-EWord_Size()-1>", or a fatal "offset out of range" error will occur. This method is similar in function to the expression "C<$word = $array[$offset];>" for a Perl array. =item * C<$vector-EWord_List_Store(@words);> This method allows you to store a list of values "C<@words>" in the internal array of machine words of the given bit vector. Thereby the B value in the list ("C<$words[0]>") is stored in the B significant word of the internal array of words (the one with offset "C<0>"), the next value from the list ("C<$words[1]>") is stored in the word with offset "C<1>", and so on, as intuitively expected. If the list "C<@words>" contains fewer elements than the internal array of words of the given bit vector contains machine words, the remaining (most significant) words are filled with zeros. If the list "C<@words>" contains more elements than the internal array of words of the given bit vector contains machine words, the superfluous values are simply ignored. This method is comparable in function to the expression "C<@array = @words;>" for a Perl array. =item * C<@words = $vector-EWord_List_Read();> This method allows you to retrieve the internal array of machine words of the given bit vector all at once. Thereby the B value in the returned list ("C<$words[0]>") is the B significant word from the given bit vector, and the B value in the returned list ("C<$words[$#words]>") is the B significant word of the given bit vector. This method is similar in function to the expression "C<@words = @array;>" for a Perl array. =item * C<$vector-EWord_Insert($offset,$count);> This method inserts "C<$count>" empty new machine words at position "C<$offset>" in the internal array of words of the given bit vector. The "C<$count>" most significant words are lost, and all words starting with word number "C<$offset>" up to and including word number "C<$vector-EWord_Size()-$count-1>" are moved up by "C<$count>" places. The now vacant "C<$count>" words starting at word number "C<$offset>" (up to and including word number "C<$offset+$count-1>") are then set to zero (cleared). Note that this method does B increase the size of the given bit vector, i.e., the bit vector is B extended at its upper end to "rescue" the "C<$count>" uppermost (most significant) words - instead, these words are lost forever. If you don't want this to happen, you have to increase the size of the given bit vector B and B you perform the "Insert" operation, with a statement such as the following: $vector->Resize($vector->Size() + $count * Bit::Vector->Word_Bits()); Note also that "C<$offset>" must lie in the permitted range between "C<0>" and "C<$vector-EWord_Size()-1>", or a fatal "offset out of range" error will occur. If the term "C<$offset + $count>" exceeds "C<$vector-EWord_Size()-1>", all the words starting with word number "C<$offset>" up to word number "C<$vector-EWord_Size()-1>" are simply cleared. =item * C<$vector-EWord_Delete($offset,$count);> This method deletes, i.e., removes the words starting at position "C<$offset>" up to and including word number "C<$offset+$count-1>" from the internal array of machine words of the given bit vector. The remaining uppermost words (starting at position "C<$offset+$count>" up to and including word number "C<$vector-EWord_Size()-1>") are moved down by "C<$count>" places. The now vacant uppermost (most significant) "C<$count>" words are then set to zero (cleared). Note that this method does B decrease the size of the given bit vector, i.e., the bit vector is B clipped at its upper end to "get rid of" the vacant "C<$count>" uppermost words. If you don't want this, i.e., if you want the bit vector to shrink accordingly, you have to do so B and B the "Delete" operation, with a couple of statements such as these: $bits = $vector->Size(); $count *= Bit::Vector->Word_Bits(); if ($count > $bits) { $count = $bits; } $vector->Resize($bits - $count); Note also that "C<$offset>" must lie in the permitted range between "C<0>" and "C<$vector-EWord_Size()-1>", or a fatal "offset out of range" error will occur. If the term "C<$offset + $count>" exceeds "C<$vector-EWord_Size()-1>", all the words starting with word number "C<$offset>" up to word number "C<$vector-EWord_Size()-1>" are simply cleared. =item * C<$vector-EChunk_Store($chunksize,$offset,$chunk);> This method allows you to set more than one bit at a time with different values. You can access chunks (i.e., ranges of contiguous bits) between one and at most "CLong_Bits()>" bits wide. In order to be portable, though, you should never use chunk sizes larger than 32 bits. If the given "C<$chunksize>" does not lie between "C<1>" and "CLong_Bits()>", a fatal "chunk size out of range" error will occur. The method copies the "C<$chunksize>" least significant bits from the value "C<$chunk>" to the given bit vector, starting at bit position "C<$offset>" and proceeding upwards until bit number "C<$offset+$chunksize-1>". (I.e., bit number "C<0>" of "C<$chunk>" becomes bit number "C<$offset>" in the given bit vector, and bit number "C<$chunksize-1>" becomes bit number "C<$offset+$chunksize-1>".) If the term "C<$offset+$chunksize-1>" exceeds "C<$vector-ESize()-1>", the corresponding superfluous (most significant) bits from "C<$chunk>" are simply ignored. Note that "C<$offset>" itself must lie in the permitted range between "C<0>" and "C<$vector-ESize()-1>", or a fatal "offset out of range" error will occur. This method (as well as the other "C" methods) is useful, for example, when you are reading in data in chunks of, say, 8 bits, which you need to access later, say, using 16 bits at a time (like audio CD wave files, for instance). =item * C<$chunk = $vector-EChunk_Read($chunksize,$offset);> This method allows you to read the values of more than one bit at a time. You can read chunks (i.e., ranges of contiguous bits) between one and at most "CLong_Bits()>" bits wide. In order to be portable, though, you should never use chunk sizes larger than 32 bits. If the given "C<$chunksize>" does not lie between "C<1>" and "CLong_Bits()>", a fatal "chunk size out of range" error will occur. The method returns the "C<$chunksize>" bits from the given bit vector starting at bit position "C<$offset>" and proceeding upwards until bit number "C<$offset+$chunksize-1>". (I.e., bit number "C<$offset>" of the given bit vector becomes bit number "C<0>" of the returned value, and bit number "C<$offset+$chunksize-1>" becomes bit number "C<$chunksize-1>".) If the term "C<$offset+$chunksize-1>" exceeds "C<$vector-ESize()-1>", the non-existent bits are simply not returned. Note that "C<$offset>" itself must lie in the permitted range between "C<0>" and "C<$vector-ESize()-1>", or a fatal "offset out of range" error will occur. =item * C<$vector-EChunk_List_Store($chunksize,@chunks);> This method allows you to fill the given bit vector with a list of data packets ("chunks") of any size ("C<$chunksize>") you like (within certain limits). In fact the given "C<$chunksize>" must lie in the range between "C<1>" and "CLong_Bits()>", or a fatal "chunk size out of range" error will occur. In order to be portable, though, you should never use chunk sizes larger than 32 bits. The given bit vector is thereby filled in ascending order: The first chunk from the list (i.e., "C<$chunks[0]>") fills the "C<$chunksize>" least significant bits, the next chunk from the list ("C<$chunks[1]>") fills the bits number "C<$chunksize>" to number "C<2*$chunksize-1>", the third chunk ("C<$chunks[2]>") fills the bits number "C<2*$chunksize>", to number "C<3*$chunksize-1>", and so on. If there a less chunks in the list than are needed to fill the entire bit vector, the remaining (most significant) bits are cleared, i.e., the previous contents of the given bit vector are always erased completely. If there are more chunks in the list than are needed to fill the entire bit vector, and/or if a chunk extends beyond "C<$vector-ESize()-1>" (which happens whenever "C<$vector-ESize()>" is not a multiple of "C<$chunksize>"), the superfluous chunks and/or bits are simply ignored. The method is useful, for example (and among many other applications), for the conversion of packet sizes in a data stream. This method can also be used to store an octal string in a given bit vector: $vector->Chunk_List_Store(3, split(//, reverse $string)); Note however that unlike the conversion methods "C", "C", "C" and "C", this statement does not include any syntax checking, i.e., it may fail silently, without warning. To perform syntax checking, add the following statements: if ($string =~ /^[0-7]+$/) { # okay, go ahead with conversion as shown above } else { # error, string contains other than octal characters } Another application is to store a repetitive pattern in a given bit vector: $pattern = 0xDEADBEEF; $length = 32; # = length of $pattern in bits $size = $vector->Size(); $factor = int($size / $length); if ($size % $length) { $factor++; } $vector->Chunk_List_Store($length, ($pattern) x $factor); =item * C<@chunks = $vector-EChunk_List_Read($chunksize);> This method allows you to access the contents of the given bit vector in form of a list of data packets ("chunks") of a size ("C<$chunksize>") of your choosing (within certain limits). In fact the given "C<$chunksize>" must lie in the range between "C<1>" and "CLong_Bits()>", or a fatal "chunk size out of range" error will occur. In order to be portable, though, you should never use chunk sizes larger than 32 bits. The given bit vector is thereby read in ascending order: The "C<$chunksize>" least significant bits (bits number "C<0>" to "C<$chunksize-1>") become the first chunk in the returned list (i.e., "C<$chunks[0]>"). The bits number "C<$chunksize>" to "C<2*$chunksize-1>" become the next chunk in the list ("C<$chunks[1]>"), and so on. If "C<$vector-ESize()>" is not a multiple of "C<$chunksize>", the last chunk in the list will contain fewer bits than "C<$chunksize>". B that for large bit vectors and/or small values of "C<$chunksize>", the number of returned list elements can be extremely large! B You could blow up your application with lack of memory (each list element is a full-grown Perl scalar, internally, with an associated memory overhead for its administration!) or at least cause a noticeable, more or less long-lasting "freeze" of your application! Possible applications: The method is especially useful in the conversion of packet sizes in a data stream. This method can also be used to convert a given bit vector to a string of octal numbers: $string = reverse join('', $vector->Chunk_List_Read(3)); =item * C<$vector-EIndex_List_Remove(@indices);> This method allows you to specify a list of indices of bits which should be turned off in the given bit vector. In fact this method is a shortcut for foreach $index (@indices) { $vector->Bit_Off($index); } In contrast to all other import methods in this module, this method does B clear the given bit vector before processing its list of arguments. Instead, this method allows you to accumulate the results of various consecutive calls. (The same holds for the method "C". As a consequence, you can "wipe out" what you did using the method "C" by passing the identical argument list to the method "C".) =item * C<$vector-EIndex_List_Store(@indices);> This method allows you to specify a list of indices of bits which should be turned on in the given bit vector. In fact this method is a shortcut for foreach $index (@indices) { $vector->Bit_On($index); } In contrast to all other import methods in this module, this method does B clear the given bit vector before processing its list of arguments. Instead, this method allows you to accumulate the results of various consecutive calls. (The same holds for the method "C". As a consequence, you can "wipe out" what you did using the method "C" by passing the identical argument list to the method "C".) =item * C<@indices = $vector-EIndex_List_Read();> This method returns a list of Perl scalars. The list contains one scalar for each set bit in the given bit vector. B that for large bit vectors, this can result in a literally overwhelming number of list elements! B You could run out of memory or slow down your application considerably! Each scalar contains the number of the index corresponding to the bit in question. These indices are always returned in ascending order. If the given bit vector is empty (contains only cleared bits) or if it has a length of zero (if it contains no bits at all), the method returns an empty list. This method can be useful, for instance, to obtain a list of prime numbers: $limit = 1000; # or whatever $vector = Bit::Vector->new($limit+1); $vector->Primes(); @primes = $vector->Index_List_Read(); =item * C<$vec3-EOr($vec1,$vec2);> C<$set3-EUnion($set1,$set2);> This method calculates the union of "C<$set1>" and "C<$set2>" and stores the result in "C<$set3>". This is usually written as "C<$set3 = $set1 u $set2>" in set theory (where "u" is the "cup" operator). (On systems where the "cup" character is unavailable this operator is often denoted by a plus sign "+".) In-place calculation is also possible, i.e., "C<$set3>" may be identical with "C<$set1>" or "C<$set2>" or both. =item * C<$vec3-EAnd($vec1,$vec2);> C<$set3-EIntersection($set1,$set2);> This method calculates the intersection of "C<$set1>" and "C<$set2>" and stores the result in "C<$set3>". This is usually written as "C<$set3 = $set1 n $set2>" in set theory (where "n" is the "cap" operator). (On systems where the "cap" character is unavailable this operator is often denoted by an asterisk "*".) In-place calculation is also possible, i.e., "C<$set3>" may be identical with "C<$set1>" or "C<$set2>" or both. =item * C<$vec3-EAndNot($vec1,$vec2);> C<$set3-EDifference($set1,$set2);> This method calculates the difference of "C<$set1>" less "C<$set2>" and stores the result in "C<$set3>". This is usually written as "C<$set3 = $set1 \ $set2>" in set theory (where "\" is the "less" operator). In-place calculation is also possible, i.e., "C<$set3>" may be identical with "C<$set1>" or "C<$set2>" or both. =item * C<$vec3-EXor($vec1,$vec2);> C<$set3-EExclusiveOr($set1,$set2);> This method calculates the symmetric difference of "C<$set1>" and "C<$set2>" and stores the result in "C<$set3>". This can be written as "C<$set3 = ($set1 u $set2) \ ($set1 n $set2)>" in set theory (the union of the two sets less their intersection). When sets are implemented as bit vectors then the above formula is equivalent to the exclusive-or between corresponding bits of the two bit vectors (hence the name of this method). Note that this method is also much more efficient than evaluating the above formula explicitly since it uses a built-in machine language instruction internally. In-place calculation is also possible, i.e., "C<$set3>" may be identical with "C<$set1>" or "C<$set2>" or both. =item * C<$vec2-ENot($vec1);> C<$set2-EComplement($set1);> This method calculates the complement of "C<$set1>" and stores the result in "C<$set2>". In "big integer" arithmetic, this is equivalent to calculating the one's complement of the number stored in the bit vector "C<$set1>" in binary representation. In-place calculation is also possible, i.e., "C<$set2>" may be identical with "C<$set1>". =item * Csubset($set2))> Returns "true" ("C<1>") if "C<$set1>" is a subset of "C<$set2>" (i.e., completely contained in "C<$set2>") and "false" ("C<0>") otherwise. This means that any bit which is set ("C<1>") in "C<$set1>" must also be set in "C<$set2>", but "C<$set2>" may contain set bits which are not set in "C<$set1>", in order for the condition of subset relationship to be true between these two sets. Note that by definition, if two sets are identical, they are also subsets (and also supersets) of each other. =item * C<$norm = $set-ENorm();> Returns the norm (number of bits which are set) of the given vector. This is equivalent to the number of elements contained in the given set. Uses a byte lookup table for calculating the number of set bits per byte, and thus needs a time for evaluation (and a number of loops) linearly proportional to the length of the given bit vector (in bytes). This should be the fastest algorithm on average. =item * C<$norm = $set-ENorm2();> Returns the norm (number of bits which are set) of the given vector. This is equivalent to the number of elements contained in the given set. This does the same as the method "C" above, only with a different algorithm: This method counts the number of set and cleared bits at the same time and will stop when either of them has been exhausted, thus needing at most half as many loops per machine word as the total number of bits in a machine word - in fact it will need a number of loops equal to the minimum of the number of set bits and the number of cleared bits. This might be a faster algorithm than of the method "C" above on some systems, depending on the system's architecture and the compiler and optimisation used, for bit vectors with sparse set bits and for bit vectors with sparse cleared bits (i.e., predominantly set bits). =item * C<$norm = $set-ENorm3();> Returns the norm (number of bits which are set) of the given vector. This is equivalent to the number of elements contained in the given set. This does the same as the two methods "C" and "C" above, however with a different algorithm. In fact this is the implementation of the method "C" used in previous versions of this module. The method needs a number of loops per machine word equal to the number of set bits in that machine word. Only for bit vectors with sparse set bits will this method be fast; it will depend on a system's architecture and compiler whether the method will be faster than any of the two methods above in such cases. On average however, this is probably the slowest method of the three. =item * C<$min = $set-EMin();> Returns the minimum of the given set, i.e., the minimum of all indices of all set bits in the given bit vector "C<$set>". If the set is empty (no set bits), plus infinity (represented by the constant "MAX_LONG" on your system) is returned. (This constant is usually S<2 ^ (n-1) - 1>, where "C" is the number of bits of an unsigned long on your machine.) =item * C<$max = $set-EMax();> Returns the maximum of the given set, i.e., the maximum of all indices of all set bits in the given bit vector "C<$set>". If the set is empty (no set bits), minus infinity (represented by the constant "MIN_LONG" on your system) is returned. (This constant is usually S<-(2 ^ (n-1) - 1)> or S<-(2 ^ (n-1))>, where "C" is the number of bits of an unsigned long on your machine.) =item * C<$m3-EMultiplication($r3,$c3,$m1,$r1,$c1,$m2,$r2,$c2);> This method multiplies two boolean matrices (stored as bit vectors) "C<$m1>" and "C<$m2>" and stores the result in matrix "C<$m3>". The method uses the binary "xor" operation ("C<^>") as the boolean addition operator ("C<+>"). An exception is raised if the product of the number of rows and columns of any of the three matrices differs from the actual size of their underlying bit vector. An exception is also raised if the numbers of rows and columns of the three matrices do not harmonize in the required manner: rows3 == rows1 cols3 == cols2 cols1 == rows2 This method is used by the module "Math::MatrixBool". See L for details. =item * C<$m3-EProduct($r3,$c3,$m1,$r1,$c1,$m2,$r2,$c2);> This method multiplies two boolean matrices (stored as bit vectors) "C<$m1>" and "C<$m2>" and stores the result in matrix "C<$m3>". This special method uses the binary "or" operation ("C<|>") as the boolean addition operator ("C<+>"). An exception is raised if the product of the number of rows and columns of any of the three matrices differs from the actual size of their underlying bit vector. An exception is also raised if the numbers of rows and columns of the three matrices do not harmonize in the required manner: rows3 == rows1 cols3 == cols2 cols1 == rows2 This method is used by the module "Math::MatrixBool". See L for details. =item * C<$matrix-EClosure($rows,$cols);> This method calculates the reflexive transitive closure of the given boolean matrix (stored as a bit vector) using Kleene's algoritm. (See L for a brief introduction into the theory behind Kleene's algorithm.) The reflexive transitive closure answers the question whether a path exists between any two vertices of a graph whose edges are given as a matrix: If a (directed) edge exists going from vertex "i" to vertex "j", then the element in the matrix with coordinates (i,j) is set to "C<1>" (otherwise it remains set to "C<0>"). If the edges are undirected, the resulting matrix is symmetric, i.e., elements (i,j) and (j,i) always contain the same value. The matrix representing the edges of the graph only answers the question whether an B exists between any two vertices of the graph or not, whereas the reflexive transitive closure answers the question whether a B (a series of adjacent edges) exists between any two vertices of the graph! Note that the contents of the given matrix are modified by this method, so make a copy of the initial matrix in time if you are going to need it again later. An exception is raised if the given matrix is not quadratic, i.e., if the number of rows and columns of the given matrix is not identical. An exception is also raised if the product of the number of rows and columns of the given matrix differs from the actual size of its underlying bit vector. This method is used by the module "Math::MatrixBool". See L for details. =item * C<$matrix2-ETranspose($rows2,$cols2,$matrix1,$rows1,$cols1);> This method calculates the transpose of a boolean matrix "C<$matrix1>" (stored as a bit vector) and stores the result in matrix "C<$matrix2>". The transpose of a boolean matrix, representing the edges of a graph, can be used for finding the strongly connected components of that graph. An exception is raised if the product of the number of rows and columns of any of the two matrices differs from the actual size of its underlying bit vector. An exception is also raised if the following conditions are not met: rows2 == cols1 cols2 == rows1 Note that in-place processing ("C<$matrix1>" and "C<$matrix2>" are identical) is only possible if the matrix is quadratic. Otherwise, a fatal "matrix is not quadratic" error will occur. This method is used by the module "Math::MatrixBool". See L for details. =back =head1 SEE ALSO Bit::Vector::Overload(3), Bit::Vector::String(3), Storable(3). Set::IntRange(3), Math::MatrixBool(3), Math::MatrixReal(3), DFA::Kleene(3), Math::Kleene(3), Graph::Kruskal(3). =head1 VERSION This man page documents "Bit::Vector" version 7.4. =head1 AUTHOR Steffen Beyer mailto:STBEY@cpan.org http://www.engelschall.com/u/sb/download/ =head1 COPYRIGHT Copyright (c) 1995 - 2013 by Steffen Beyer. All rights reserved. =head1 LICENSE This package is free software; you can redistribute it and/or modify it under the same terms as Perl itself, i.e., under the terms of the "Artistic License" or the "GNU General Public License". The C library at the core of this Perl module can additionally be redistributed and/or modified under the terms of the "GNU Library General Public License". Please refer to the files "Artistic.txt", "GNU_GPL.txt" and "GNU_LGPL.txt" in this distribution for details! =head1 DISCLAIMER This package is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the "GNU General Public License" for more details. Bit-Vector-7.4/CHANGES.txt000644 100660 100660 00000035622 12211373040 014226 0ustar00sbsb000000 000000 ===================================== Package "Bit::Vector" Version 7.4 ===================================== Copyright (c) 1995 - 2013 by Steffen Beyer. All rights reserved. Version history: ---------------- Version 7.4 03.09.2013 + Modified ToolBox.h to allow bit vectors with more than 2^32 bits Version 7.3 01.06.2013 + Fixed t/02_____destroy.t to make it pass on perl-5.17.11 Version 7.2 17.05.2012 + Changed the definition of the "boolean" data type in ToolBox.h Version 7.1 29.09.2009 + Added prefix "BV_" to all global identifiers in "BitVector.c", "BitVector.h" and "Vector.xs" Version 7.0 22.08.2009 + Fixed a bug in "GCD2()" in "BitVector.c" with null-size vectors + Added more test cases for "GCD()" in "t/17_________gcd.t" + Almost completely rewrote "BitVector_Boot()" in "BitVector.c" in order to fix the problem that it calculated an unsigned long to have 33 bits under MacOS X (Darwin), leading to failing tests in "t/28___chunklist.t" + BEWARE that the type "ErrCode", which is part of the inter- face of the C library "BitVector.c", has been changed! + Added more tests and a debugging aid to "t/28___chunklist.t" + Removed the two example files showing how to freeze/thaw "Bit::Vector" objects using "Data::Dumper", because after closer inspection this proved to be a can of worms Version 6.9 12.08.2009 + Replaced "Storable::freeze()" by "Storable::nfreeze()" + Added more test cases for "Storable" + Added two example files showing how to freeze/thaw using "Data::Dumper" Version 6.8 10.08.2009 + Fixed the bug of "Storable" not reconstructing nested data structures properly which contain several references to the same "Bit::Vector" object + Fixed hard-coded table size "MASKTABSIZE" in "BitVector.c" + Small cosmetic fixes to the documentation Version 6.7 08.08.2009 + Replaced "STORABLE_thaw()" by "STORABLE_attach()" Version 6.6 27.07.2009 + Made the module thread-safe and MacOS X compatible + Prevented "BitVector_Boot()" in "BitVector.c" to leak memory when called repeatedly Version 6.5 27.07.2009 + Added automatic support for module "Storable" Version 6.4 03.10.2004 + Added compiler directives for C++. + Improved the method "Norm()". + Removed "Carp::Clan" from the distribution (available separately). + Added "Bit::Vector::String" for generic string import/export functions. + Added a new test file "t/40__auxiliary.t" for "Bit::Vector::String". + Fixed a bug in method "Copy()" concerning sign (MSB) extension. Version 6.3 28.09.2002 + Added "Create_List()" and "GCD2()" in "BitVector.c". + "new()" now can optionally return a list of bit vectors. + "GCD()" now can optionally return the two integer factors "x" and "y" for the linear combination of its input values "a" and "b" so that gcd(a,b) = x * a + y * b. + Changed the test files "t/01________new.t" and "t/09_parameters.t" as well as the documentation accordingly. + Added a new test file "t/17________gcd.t". + Further simplified the error handlers in "Vector.xs", making the resulting object library file substantially smaller (about 20%!) and thus faster to load. Version 6.2 15.09.2002 + Fixed missing "\" in regular expression in "t/00____version.t". + Overhauled the error handlers in "BitVector.c" and "Vector.xs". + Added a demo "examples/test.c" to play around with the C library. + Attempted to fix all compiler warnings. + Fixed a problem in test "t/01________new.t" with Perl using 64 bit integers; now contains "use integer;" to avoid failure. + Synchronized "Carp::Clan" and "ToolBox.h" with "Date::Calc" 5.2. + Revealed common method aliases (Or, And, etc.) in the documentation. + Fixed GCD(), now GCD(z,0) == GCD(0,z) == z and negative values are handled correctly. Version 6.1 08.10.2001 + Fixed the problem which caused some of the tests with overloaded operators to fail under Perl 5.7.1 and Perl 5.7.2. + Added the module "Carp::Clan" to the distribution. + Changed most of the error messages in Bit::Vector::Overload. + Changed the test script "t/30_overloaded.t" accordingly. + Changed "Makefile.PL" to write a "patchlevel.h" file so that "Vector.xs" can automatically detect the Perl version and whether to use the macro PL_na or na, GIMME_V or GIMME. Tweaking the code before installing is not necessary anymore. + Changed the documentation in files README.txt and INSTALL.txt accordingly. + Changed the internal names BitVector_msb and BitVector_lsb to BitVector_msb_ and BitVector_lsb_ in order to make the (non- ANSI C-standard-compliant!) VMS linker happy. This does NOT affect the Perl interface, though. Version 6.0 08.10.2000 + Splitted the Vector.pm module; separated XS and overloaded Perl part for improved performance (reduces loading time for XS part). + Corrected the handling of numerical overflow in arithmetic methods ("add()", "subtract()", "Multiply()", "from_Dec()", "new_Dec()"). + Methods "add()" and "subtract()" now return the carry as well as the overflow flag if called in list context (only the carry in scalar context, as before). + Added two new methods "inc()" and "dec()", which return the overflow flag (whereas "increment()" and "decrement()" return the carry flag). The new methods also allow to copy-and-increment/decrement in addition to in-place operation. + Methods "from_Dec()" and "new_Dec()" now allow you to enter large positive numbers which will have the MSB set (this was forbidden previously because these numbers are considered to be negative in two's complement binary representation). Version 5.8 14.07.2000 + Changed "na" to "PL_na" in Vector.xs in order to make the module ready for Perl 5.6.0. + Removed the error messages which appeared at global destruction time with Perl 5.6.0. + Changed the corresponding test script (t/02____destroy.t) accordingly. + Optimized the "strEQ" away from the typemap section in Vector.xs. + Fixed the misspelled word "whether" in the documentation. + Added method "Power()". + Added overloaded operator "**" (for exponentiation). + Changed method "Copy()"; the two vectors do not need to have the same size anymore. The method will copy as much as will fit or fill up with 0's or 1's (depending on the sign of the source) if necessary. + Changed the corresponding test script (t/09_parameters.t) accordingly. Version 5.7 19.05.1999 + Improved method "Div_Pos()": It now uses only one instead of the former two (very costly) "shift" operations in its main loop, and it now depends on the (variable) length of the numbers involved rather than the (constant) length of their respective bit vectors, making this method tremendously faster now. The methods "to_Dec()", "Divide()" and "GCD()" also profit from this change in the same way since they rely crucially on the "Div_Pos()" method, internally. + Added a matrix multiplication method (for "Math::MatrixBool") named "Product()" which determines paths in matrices representing graphs. + Fixed the problems with anchored error messages in the regression test suite under MacPerl. Version 5.6 02.11.1998 + Removed the leading zeros from the output of "to_Hex()". + Fixed compiler warning on line 2067 of "BitVector.c". Version 5.5 21.09.1998 + Fixed the bug of the uninitialized return code in method "Multiply()". + Fixed the failure of tests 96-131 of test script "t/01________new.t" under HP-UX 10. Version 5.4 07.09.1998 + Fixed the bug of the uninitialized return code in method "Divide()". + Introduced an additional header "Preface" in the POD documentation to avoid clobbering of the information displayed by CPAN.pm et al. + Added the new attributes to "Makefile.PL" for ActiveState's port of Perl 5.005 to the Win32 platform. Version 5.3 12.05.1998 + Changed "Norm()" to become still a bit more efficient. + Ported the "upgrade_BV52" utility to Perl ("upgrade_BV53.pl"), making it faster, more flexible and easier to read and maintain. + Added "upgrade_BV42.pl". + Enhanced support for Windows NT/95. + Complete rewrite of this "CHANGES.txt" document. Version 5.2 31.03.1998 + Changed "Norm()", "<<" and ">>" to become more efficient. + Added "new_Hex()", "new_Bin()", "new_Dec()" and "new_Enum()". + Made the exception handling in "Vector.pm" more elegant. Version 5.1 09.03.1998 + Added systematic exception handling to "Vector.pm". Version 5.0 01.03.1998 + "Outsourced" all example modules (now available separately). + Added: Word_Bits(), Long_Bits(), Concat(), Concat_List(), Primes(), Reverse(), Interval_Reverse(), Interval_Copy(), Interval_Substitute(), Lexicompare(), to_Bin(), from_Bin(), to_Dec(), from_Dec(), Bit_Copy(), LSB(), MSB(), lsb(), msb(), Insert(), Delete(), add(), subtract(), Negate(), Absolute(), Sign(), Multiply(), Divide(), GCD(), Block_Store(), Block_Read(), Word_Size(), Word_Store(), Word_Read(), Word_List_Store(), Word_List_Read(), Word_Insert(), Word_Delete(), Chunk_Store(), Chunk_Read(), Chunk_List_Store(), Chunk_List_Read(), Index_List_Remove(), Index_List_Store(), Index_List_Read(), Transpose(). + Ported to C: "Version()", "Shadow()", "Clone()", "to_Enum()", "from_Enum()". + Changed: "Compare()" (now assumes bit vectors are SIGNED). + Renamed: "to_String()" ==> "to_Hex()", "from_string()" ==> "from_Hex()", "to_ASCII()" ==> "to_Enum()", "from_ASCII()" ==> "from_Enum()" (aliases are still available but deprecated). + Dropped: "lexorder()", "new_from_String()". + Dropped: Module "Set::IntegerFast" (replaced by "Bit::Vector"). + Definitely abandoned the possibility for subclassing because it doesn't make any sense in this module (use embedding instead!). + Fixed: Module "Set::IntegerRange" version 4.2 broke with "Bit::Vector" version 5.0. Issued quick fix "Set::IntRange" version 5.0. More thorough implementation is under construction. Version 4.2 16.07.1997 + Added "is_empty()" and "is_full()". Version 4.1 30.06.1997 + Added "Move_Left()" and "Move_Right()". + Changed "<<" and ">>" to call "Move_Left()" and "Move_Right()" instead. + Added "increment()" and "decrement()". + Changed "++" and "--" to call "increment()" and "decrement()" instead. + Added "Resize()", "Interval_Scan_inc()", "Interval_Scan_dec()" and "BitVector()" to "Set::IntegerRange". Version 4.0 23.04.1997 + Complete rewrite of the "Set::IntegerFast" module. + Renamed "Set::IntegerFast" to "Bit::Vector". + United the separate C cores and XS files for sets, matrices of booleans and bit shift operations in a single module. + Abandoned the individual version numbers. + Dropped the separate "Makefile.PL"s, adopted the solution using a "lib" subdirectory. + Added: Flip(), Interval_Scan_inc(), Interval_Scan_dec(), rotate_left(), rotate_right(), shift_left(), shift_right(), to_String(), from_string(), Multiplication(), Closure(), Shadow(), Clone(), new_from_String(), to_ASCII(), from_ASCII(). + Added overloaded operators for: emptyness, equality, lexical comparison, shift register, rotate register, string conversion, union, intersection, difference, exclusive-or, complement, subset relationship, true subset relationship, superset relationship, true superset relationship, norm. Version 3.2 04.02.1997 + Added "Empty_Interval()", "Fill_Interval()", "Flip_Interval()" and "Size()" to "Set::IntegerFast" and "Set::IntegerRange". + "Set::IntegerFast" and "Set::IntegerRange" both switched to version number 3.0. + Improved the "Math::MatrixBool" module (new version number: 2.0) to use C routines for matrix multiplication and closure and fixed some bugs in these methods at the same time. + Added "new_from_string()" and "Dim()" to "Math::MatrixBool". + Fixed a severe bug in the "kleene()" method of "Math::MatrixReal" (new version number: 1.1). Version 3.1 21.01.1997 + Fixed a bug that caused the initialization routine of the module to fail on 64 bit machines due to a wrong conditional expression (type "int" and "size_t" do not necessarily have the same size!). + "Set::IntegerFast" switched to version number 2.2. Version 3.0 12.01.1997 + Added "flip()" to "Set::IntegerFast" and "Set::IntegerRange". + Transformed the "kruskal" demo program to a Perl module "Graph::Kruskal". + Added new companion modules: "Math::MatrixBool", "Math::MatrixReal" and "DFA::Kleene", all with separate "Makefile.PL"s. + Added introductory article about theory behind Kleene's algorithm. + Introduced independent version numbers for all modules: "Set::IntegerFast" ==> version 2.1, "Set::IntegerRange" ==> version 2.0. + Added overloaded operators to "Set::IntegerRange". + Bugfix: Changed "gv_stashpv(class,0)" to "gv_stashpv(class,1)" in the XS file (caused core dumps in previous versions when "new()" was called with a nonexistent class name and subclassing enabled). Version 2.0 14.12.1996 + Changed "Create()" to "new()". + Now supports "$set = new Set::IntegerFast($elements);" instead of "$set = Set::IntegerFast::Create($elements);". + Changed "Destroy()" to "DESTROY()", which doesn't need to (and shouldn't!) be called explicitly anymore. + Fixed the "bad free() ignored" warnings caused by "Destroy()" in version 1.1 (in conjunction with Perl version 5.002) which led some of the tests in "make test" to fail. + Complete rewrite of the XS part. + Changed "lexorder()" and "Compare()" to become more efficient (complexity n/b instead of n/8). + Changed parameters visible externally from "word"/"unit" to "N_int" in the C core. + Complete rewrite of the documentation, now in POD format. + Added a new (wrapper) module named "Set::IntegerRange". Version 1.1 08.01.1996 + Added "Resize()". + Changed "Create()", "Empty()", "Fill()" and "Copy()" to have complexity n/b rather than n/8. + Made interfaces in C core more consistent: Pointer to a set object is now always the first parameter. + Added new paragraphs to the documentation. + Added "ExclusiveOr()" (for symmetric difference X = (Y + Z) \ (Y * Z)). Version 1.0 14.12.1995 First version under UNIX (with Perl module). + Initial release as a C library and Perl module. Version 0.9 01.11.1993 First version of C library under MS-DOS. + Ported the Pascal code to C because I thought sets of arbitrary sizes are always useful to have. Version 0.1 ??.??.1989 First version in Turbo Pascal under CP/M. + I first wrote this library (on my Apple ][+) because I needed more bits in a set than Turbo Pascal would support in order to calculate "first", "follow" and "look-ahead" character sets for a compiler-compiler. ---------------------------------------------------------------------------- Bit-Vector-7.4/ToolBox.h000644 100660 100660 00000022163 12211373040 014150 0ustar00sbsb000000 000000 #ifndef MODULE_TOOLBOX #define MODULE_TOOLBOX #ifdef __cplusplus extern "C" { #endif /*****************************************************************************/ /* MODULE NAME: ToolBox.h MODULE TYPE: (dat) */ /*****************************************************************************/ /* MODULE IMPORTS: */ /*****************************************************************************/ #ifdef PERL_DARWIN #include #endif /*****************************************************************************/ /* MODULE INTERFACE: */ /*****************************************************************************/ /*****************************************************************************/ /* MODULE RESOURCES: */ /*****************************************************************************/ /*****************************************************************************/ /* NOTE: The type names that have been chosen here are somewhat weird on */ /* purpose, in order to avoid name clashes with system header files */ /* and your own application(s) which might - directly or indirectly - */ /* include this definitions file. */ /*****************************************************************************/ typedef unsigned char N_char; typedef unsigned char N_byte; typedef unsigned short N_short; typedef unsigned short N_shortword; typedef unsigned long N_int; /* used to be "int"! */ typedef unsigned long N_word; /* used to be "int"! */ typedef unsigned long N_long; typedef unsigned long N_longword; /* Mnemonic 1: The natural numbers, N = { 0, 1, 2, 3, ... } */ /* Mnemonic 2: Nnnn = u_N_signed, _N_ot signed */ typedef signed char Z_char; typedef signed char Z_byte; typedef signed short Z_short; typedef signed short Z_shortword; typedef signed long Z_int; /* used to be "int"! */ typedef signed long Z_word; /* used to be "int"! */ typedef signed long Z_long; typedef signed long Z_longword; /* Mnemonic 1: The whole numbers, Z = { 0, -1, 1, -2, 2, -3, 3, ... } */ /* Mnemonic 2: Zzzz = Ssss_igned */ typedef void *voidptr; typedef N_char *charptr; typedef N_byte *byteptr; typedef N_short *shortptr; typedef N_shortword *shortwordptr; typedef N_int *intptr; typedef N_word *wordptr; typedef N_long *longptr; typedef N_longword *longwordptr; typedef N_char *N_charptr; typedef N_byte *N_byteptr; typedef N_short *N_shortptr; typedef N_shortword *N_shortwordptr; typedef N_int *N_intptr; typedef N_word *N_wordptr; typedef N_long *N_longptr; typedef N_longword *N_longwordptr; typedef Z_char *Z_charptr; typedef Z_byte *Z_byteptr; typedef Z_short *Z_shortptr; typedef Z_shortword *Z_shortwordptr; typedef Z_int *Z_intptr; typedef Z_word *Z_wordptr; typedef Z_long *Z_longptr; typedef Z_longword *Z_longwordptr; #undef FALSE #define FALSE (0!=0) #undef TRUE #define TRUE (0==0) #ifdef __cplusplus typedef bool boolean; #else #ifdef MACOS_TRADITIONAL #define boolean Boolean #elif PERL_DARWIN #define boolean bool #else typedef int boolean; #ifndef I_STDBOOL enum { false, true }; #endif #endif #endif #define and && /* logical (boolean) operators: lower case */ #define or || #define not ! #define AND & /* binary (bitwise) operators: UPPER CASE */ #define OR | #define XOR ^ #define NOT ~ #define SHL << #define SHR >> #ifdef ENABLE_MODULO #define mod % /* arithmetic operators */ #endif #define blockdef(name,size) unsigned char name[size] #define blocktypedef(name,size) typedef unsigned char name[size] /*****************************************************************************/ /* MODULE IMPLEMENTATION: */ /*****************************************************************************/ /*****************************************************************************/ /* VERSION: 5.8 */ /*****************************************************************************/ /* VERSION HISTORY: */ /*****************************************************************************/ /* */ /* Version 5.8 03.09.13 Allows bit vectors with > 2^32 bits. */ /* Version 5.7 17.05.12 Changed boolean data type. */ /* Version 5.6 27.07.09 Made it MacOS X compatible. */ /* Version 5.5 03.10.04 Added compiler directives for C++. */ /* Version 5.4 08.09.02 Added conditional changes for MacOS/MacPerl. */ /* Version 5.3 12.05.98 Completed history. */ /* Version 5.0 01.03.98 "Definitions.h" -> "ToolBox.h". */ /* Version 4.0 24.03.97 "lib_defs.h" -> "Definitions.h". */ /* Version 3.0 16.02.97 Changed frames from 40 to 80 columns. */ /* Version 2.0 30.11.96 byte -> base etc. */ /* Version 1.2a 21.11.95 unchar -> N_char etc. Added MS-DOS specifics. */ /* Version 1.1 18.11.95 uchar -> unchar etc. */ /* Version 1.01 16.11.95 Removed MS-DOS specifics. */ /* Version 1.0 12.11.95 First version under UNIX (with Perl modules). */ /* Version 0.9 01.11.93 First version under MS-DOS. */ /* */ /*****************************************************************************/ /* AUTHOR: */ /*****************************************************************************/ /* */ /* Steffen Beyer */ /* mailto:STBEY@cpan.org */ /* http://www.engelschall.com/u/sb/download/ */ /* */ /*****************************************************************************/ /* COPYRIGHT: */ /*****************************************************************************/ /* */ /* Copyright (c) 1995 - 2013 by Steffen Beyer. */ /* All rights reserved. */ /* */ /*****************************************************************************/ /* LICENSE: */ /*****************************************************************************/ /* */ /* This library is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU Library General Public */ /* License as published by the Free Software Foundation; either */ /* version 2 of the License, or (at your option) any later version. */ /* */ /* This library is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ /* Library General Public License for more details. */ /* */ /* You should have received a copy of the GNU Library General Public */ /* License along with this library; if not, write to the */ /* Free Software Foundation, Inc., */ /* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* or download a copy from ftp://ftp.gnu.org/pub/gnu/COPYING.LIB-2.0 */ /* */ /*****************************************************************************/ #ifdef __cplusplus } #endif #endif Bit-Vector-7.4/examples/000755 100660 100660 00000000000 12211373041 014224 5ustar00sbsb000000 000000 Bit-Vector-7.4/BitVector.c000644 100660 100660 00000350562 12211373040 014465 0ustar00sbsb000000 000000 #ifndef MODULE_BIT_VECTOR #define MODULE_BIT_VECTOR /*****************************************************************************/ /* MODULE NAME: BitVector.c MODULE TYPE: (adt) */ /*****************************************************************************/ /* MODULE IMPORTS: */ /*****************************************************************************/ #include /* MODULE TYPE: (sys) */ #include /* MODULE TYPE: (sys) */ #include /* MODULE TYPE: (sys) */ #include /* MODULE TYPE: (sys) */ #include "ToolBox.h" /* MODULE TYPE: (dat) */ /*****************************************************************************/ /* MODULE INTERFACE: */ /*****************************************************************************/ typedef enum { BV_ErrCode_Ok = 0, /* everything went allright */ BV_ErrCode_Type, /* types word and size_t have incompatible sizes */ BV_ErrCode_Bits, /* bits of word and sizeof(word) are inconsistent */ BV_ErrCode_Word, /* size of word is less than 16 bits */ BV_ErrCode_Powr, /* number of bits of word is not a power of two */ BV_ErrCode_Loga, /* error in calculation of logarithm */ BV_ErrCode_Lpwr, /* number of bits of long is not a power of two */ BV_ErrCode_WgtL, /* size of word is greater than size of long */ BV_ErrCode_Null, /* unable to allocate memory */ BV_ErrCode_Indx, /* index out of range */ BV_ErrCode_Ordr, /* minimum > maximum index */ BV_ErrCode_Size, /* bit vector size mismatch */ BV_ErrCode_Pars, /* input string syntax error */ BV_ErrCode_Ovfl, /* numeric overflow error */ BV_ErrCode_Same, /* operands must be distinct */ BV_ErrCode_Expo, /* exponent must be positive */ BV_ErrCode_Zero, /* division by zero error */ BV_ErrCode_Oops /* unexpected error (contact author) */ } BV_ErrCode; typedef wordptr *bv_listptr; /* ===> MISCELLANEOUS BASIC FUNCTIONS: <=== */ charptr BitVector_Error (BV_ErrCode error); /* map errcode to string */ BV_ErrCode BitVector_Boot (void); /* 0 = ok, 1..17 = error */ N_word BitVector_Size (N_int bits); /* bit vec. size (# of words) */ N_word BitVector_Mask (N_int bits); /* bit vec. mask (unused bits) */ /* ===> CLASS METHODS: <=== */ charptr BitVector_Version (void); /* return version string */ N_int BitVector_Word_Bits (void); /* return # of bits in machine word */ N_int BitVector_Long_Bits (void); /* return # of bits in unsigned long */ /* ===> CONSTRUCTOR METHODS: <=== */ wordptr BitVector_Create (N_int bits, boolean clear); /* malloc */ bv_listptr BitVector_Create_List(N_int bits, boolean clear, N_int count); wordptr BitVector_Resize (wordptr oldaddr, N_int bits); /* realloc */ wordptr BitVector_Shadow (wordptr addr); /* make same size but empty */ wordptr BitVector_Clone (wordptr addr); /* make exact duplicate */ wordptr BitVector_Concat (wordptr X, wordptr Y); /* return concat'd */ /* ===> DESTRUCTOR METHODS: <=== */ void BitVector_Dispose (charptr string); /* string */ void BitVector_Destroy (wordptr addr); /* bitvec */ void BitVector_Destroy_List (bv_listptr list, N_int count); /* list */ /* ===> OBJECT METHODS: <=== */ /* ===> bit vector copy function: */ void BitVector_Copy (wordptr X, wordptr Y); /* X = Y */ /* ===> bit vector initialization: */ void BitVector_Empty (wordptr addr); /* X = {} */ void BitVector_Fill (wordptr addr); /* X = ~{} */ void BitVector_Flip (wordptr addr); /* X = ~X */ void BitVector_Primes (wordptr addr); /* ===> miscellaneous functions: */ void BitVector_Reverse (wordptr X, wordptr Y); /* ===> bit vector interval operations and functions: */ void BitVector_Interval_Empty (wordptr addr, N_int lower, N_int upper); void BitVector_Interval_Fill (wordptr addr, N_int lower, N_int upper); void BitVector_Interval_Flip (wordptr addr, N_int lower, N_int upper); void BitVector_Interval_Reverse (wordptr addr, N_int lower, N_int upper); boolean BitVector_interval_scan_inc (wordptr addr, N_int start, N_intptr min, N_intptr max); boolean BitVector_interval_scan_dec (wordptr addr, N_int start, N_intptr min, N_intptr max); void BitVector_Interval_Copy (wordptr X, wordptr Y, N_int Xoffset, N_int Yoffset, N_int length); wordptr BitVector_Interval_Substitute(wordptr X, wordptr Y, N_int Xoffset, N_int Xlength, N_int Yoffset, N_int Ylength); /* ===> bit vector test functions: */ boolean BitVector_is_empty (wordptr addr); /* X == {} ? */ boolean BitVector_is_full (wordptr addr); /* X == ~{} ? */ boolean BitVector_equal (wordptr X, wordptr Y); /* X == Y ? */ Z_int BitVector_Lexicompare(wordptr X, wordptr Y); /* X <,=,> Y ? */ Z_int BitVector_Compare (wordptr X, wordptr Y); /* X <,=,> Y ? */ /* ===> bit vector string conversion functions: */ charptr BitVector_to_Hex (wordptr addr); BV_ErrCode BitVector_from_Hex (wordptr addr, charptr string); charptr BitVector_to_Bin (wordptr addr); BV_ErrCode BitVector_from_Bin (wordptr addr, charptr string); charptr BitVector_to_Dec (wordptr addr); BV_ErrCode BitVector_from_Dec (wordptr addr, charptr string); charptr BitVector_to_Enum (wordptr addr); BV_ErrCode BitVector_from_Enum (wordptr addr, charptr string); /* ===> bit vector bit operations, functions & tests: */ void BitVector_Bit_Off (wordptr addr, N_int index); /* X = X \ {x} */ void BitVector_Bit_On (wordptr addr, N_int index); /* X = X + {x} */ boolean BitVector_bit_flip (wordptr addr, N_int index); /* (X+{x})\(X*{x}) */ boolean BitVector_bit_test (wordptr addr, N_int index); /* {x} in X ? */ void BitVector_Bit_Copy (wordptr addr, N_int index, boolean bit); /* ===> bit vector bit shift & rotate functions: */ void BitVector_LSB (wordptr addr, boolean bit); void BitVector_MSB (wordptr addr, boolean bit); boolean BitVector_lsb_ (wordptr addr); boolean BitVector_msb_ (wordptr addr); boolean BitVector_rotate_left (wordptr addr); boolean BitVector_rotate_right (wordptr addr); boolean BitVector_shift_left (wordptr addr, boolean carry_in); boolean BitVector_shift_right (wordptr addr, boolean carry_in); void BitVector_Move_Left (wordptr addr, N_int bits); void BitVector_Move_Right (wordptr addr, N_int bits); /* ===> bit vector insert/delete bits: */ void BitVector_Insert (wordptr addr, N_int offset, N_int count, boolean clear); void BitVector_Delete (wordptr addr, N_int offset, N_int count, boolean clear); /* ===> bit vector arithmetic: */ boolean BitVector_increment (wordptr addr); /* X++ */ boolean BitVector_decrement (wordptr addr); /* X-- */ boolean BitVector_compute (wordptr X, wordptr Y, wordptr Z, boolean minus, boolean *carry); boolean BitVector_add (wordptr X, wordptr Y, wordptr Z, boolean *carry); boolean BitVector_sub (wordptr X, wordptr Y, wordptr Z, boolean *carry); boolean BitVector_inc (wordptr X, wordptr Y); boolean BitVector_dec (wordptr X, wordptr Y); void BitVector_Negate (wordptr X, wordptr Y); void BitVector_Absolute (wordptr X, wordptr Y); Z_int BitVector_Sign (wordptr addr); BV_ErrCode BitVector_Mul_Pos (wordptr X, wordptr Y, wordptr Z, boolean strict); BV_ErrCode BitVector_Multiply (wordptr X, wordptr Y, wordptr Z); BV_ErrCode BitVector_Div_Pos (wordptr Q, wordptr X, wordptr Y, wordptr R); BV_ErrCode BitVector_Divide (wordptr Q, wordptr X, wordptr Y, wordptr R); BV_ErrCode BitVector_GCD (wordptr X, wordptr Y, wordptr Z); BV_ErrCode BitVector_GCD2 (wordptr U, wordptr V, wordptr W, /* O */ wordptr X, wordptr Y); /* I */ BV_ErrCode BitVector_Power (wordptr X, wordptr Y, wordptr Z); /* ===> direct memory access functions: */ void BitVector_Block_Store(wordptr addr, charptr buffer, N_int length); charptr BitVector_Block_Read (wordptr addr, N_intptr length); /* ===> word array functions: */ void BitVector_Word_Store (wordptr addr, N_int offset, N_int value); N_int BitVector_Word_Read (wordptr addr, N_int offset); void BitVector_Word_Insert(wordptr addr, N_int offset, N_int count, boolean clear); void BitVector_Word_Delete(wordptr addr, N_int offset, N_int count, boolean clear); /* ===> arbitrary size chunk functions: */ void BitVector_Chunk_Store(wordptr addr, N_int chunksize, N_int offset, N_long value); N_long BitVector_Chunk_Read (wordptr addr, N_int chunksize, N_int offset); /* ===> set operations: */ void Set_Union (wordptr X, wordptr Y, wordptr Z); /* X = Y + Z */ void Set_Intersection (wordptr X, wordptr Y, wordptr Z); /* X = Y * Z */ void Set_Difference (wordptr X, wordptr Y, wordptr Z); /* X = Y \ Z */ void Set_ExclusiveOr (wordptr X, wordptr Y, wordptr Z); /*(Y+Z)\(Y*Z)*/ void Set_Complement (wordptr X, wordptr Y); /* X = ~Y */ /* ===> set functions: */ boolean Set_subset (wordptr X, wordptr Y); /* X in Y */ N_int Set_Norm (wordptr addr); /* = |X| */ N_int Set_Norm2 (wordptr addr); /* = |X| */ N_int Set_Norm3 (wordptr addr); /* = |X| */ Z_long Set_Min (wordptr addr); /* = min(X) */ Z_long Set_Max (wordptr addr); /* = max(X) */ /* ===> matrix-of-booleans operations: */ void Matrix_Multiplication(wordptr X, N_int rowsX, N_int colsX, wordptr Y, N_int rowsY, N_int colsY, wordptr Z, N_int rowsZ, N_int colsZ); void Matrix_Product (wordptr X, N_int rowsX, N_int colsX, wordptr Y, N_int rowsY, N_int colsY, wordptr Z, N_int rowsZ, N_int colsZ); void Matrix_Closure (wordptr addr, N_int rows, N_int cols); void Matrix_Transpose (wordptr X, N_int rowsX, N_int colsX, wordptr Y, N_int rowsY, N_int colsY); /*****************************************************************************/ /* MODULE RESOURCES: */ /*****************************************************************************/ #define BV_BITS_(BitVector) *(BitVector-3) #define BV_SIZE_(BitVector) *(BitVector-2) #define BV_MASK_(BitVector) *(BitVector-1) #define BV_ERRCODE_TYPE "sizeof(word) > sizeof(size_t)" #define BV_ERRCODE_BITS "bits(word) != sizeof(word)*8" #define BV_ERRCODE_WORD "bits(word) < 16" #define BV_ERRCODE_POWR "bits(word) is not a power of two" #define BV_ERRCODE_LOGA "bits(word) != 2^ld(bits(word))" #define BV_ERRCODE_LPWR "bits(long) is not a power of two" #define BV_ERRCODE_WGTL "bits(word) > bits(long)" #define BV_ERRCODE_NULL "unable to allocate memory" #define BV_ERRCODE_INDX "index out of range" #define BV_ERRCODE_ORDR "minimum > maximum index" #define BV_ERRCODE_SIZE "bit vector size mismatch" #define BV_ERRCODE_PARS "input string syntax error" #define BV_ERRCODE_OVFL "numeric overflow error" #define BV_ERRCODE_SAME "result vector(s) must be distinct" #define BV_ERRCODE_EXPO "exponent must be positive" #define BV_ERRCODE_ZERO "division by zero error" #define BV_ERRCODE_OOPS "unexpected internal error - please contact author" const N_int BV_ByteNorm[256] = { 0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x03, 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, /* 0x00 */ 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, /* 0x10 */ 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, /* 0x20 */ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, /* 0x30 */ 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, /* 0x40 */ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, /* 0x50 */ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, /* 0x60 */ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, /* 0x70 */ 0x01, 0x02, 0x02, 0x03, 0x02, 0x03, 0x03, 0x04, 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, /* 0x80 */ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, /* 0x90 */ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, /* 0xA0 */ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, /* 0xB0 */ 0x02, 0x03, 0x03, 0x04, 0x03, 0x04, 0x04, 0x05, 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, /* 0xC0 */ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, /* 0xD0 */ 0x03, 0x04, 0x04, 0x05, 0x04, 0x05, 0x05, 0x06, 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, /* 0xE0 */ 0x04, 0x05, 0x05, 0x06, 0x05, 0x06, 0x06, 0x07, 0x05, 0x06, 0x06, 0x07, 0x06, 0x07, 0x07, 0x08 /* 0xF0 */ }; /*****************************************************************************/ /* MODULE IMPLEMENTATION: */ /*****************************************************************************/ /**********************************************/ /* global implementation-intrinsic constants: */ /**********************************************/ #define BV_HIDDENWORDS 3 /*****************************************************************/ /* global machine-dependent constants (set by "BitVector_Boot"): */ /*****************************************************************/ static N_word BV_WordBits; /* = # of bits in a machine word (power of 2) */ static N_word BV_ModMask; /* = BV_WordBits-1 (for "modulo BV_WordBits") */ static N_word BV_LogBits; /* = ld(BV_WordBits) (logarithmus dualis) */ static N_word BV_Factor; /* = ld(BV_WordBits / 8) (ld of # of bytes) */ static N_word BV_LSB = 1; /* = mask for least significant bit */ static N_word BV_MSB; /* = mask for most significant bit */ static N_word BV_LongBits; /* = # of bits in unsigned long */ static N_word BV_Log10; /* = logarithm to base 10 of BV_WordBits - 1 */ static N_word BV_Exp10; /* = largest possible power of 10 in signed int */ /********************************************************************/ /* global bit mask table for fast access (set by "BitVector_Boot"): */ /********************************************************************/ #define BV_MASKTABSIZE (sizeof(N_word) << 3) static N_word BV_BitMaskTab[BV_MASKTABSIZE]; /*****************************/ /* global macro definitions: */ /*****************************/ #define BIT_VECTOR_ZERO_WORDS(target,count) \ while (count-- > 0) *target++ = 0; #define BIT_VECTOR_FILL_WORDS(target,fill,count) \ while (count-- > 0) *target++ = fill; #define BIT_VECTOR_FLIP_WORDS(target,flip,count) \ while (count-- > 0) *target++ ^= flip; #define BIT_VECTOR_COPY_WORDS(target,source,count) \ while (count-- > 0) *target++ = *source++; #define BIT_VECTOR_BACK_WORDS(target,source,count) \ { target += count; source += count; while (count-- > 0) *--target = *--source; } #define BIT_VECTOR_CLR_BIT(address,index) \ *(address+(index>>BV_LogBits)) &= NOT BV_BitMaskTab[index AND BV_ModMask]; #define BIT_VECTOR_SET_BIT(address,index) \ *(address+(index>>BV_LogBits)) |= BV_BitMaskTab[index AND BV_ModMask]; #define BIT_VECTOR_TST_BIT(address,index) \ ((*(address+(index>>BV_LogBits)) AND BV_BitMaskTab[index AND BV_ModMask]) != 0) #define BIT_VECTOR_FLP_BIT(address,index,mask) \ (mask = BV_BitMaskTab[index AND BV_ModMask]), \ (((*(addr+(index>>BV_LogBits)) ^= mask) AND mask) != 0) #define BIT_VECTOR_DIGITIZE(type,value,digit) \ value = (type) ((digit = value) / 10); \ digit -= value * 10; \ digit += (type) '0'; /*********************************************************/ /* private low-level functions (potentially dangerous!): */ /*********************************************************/ static N_word BIT_VECTOR_power10(N_word x) { N_word y = 1; while (x-- > 0) y *= 10; return(y); } static void BIT_VECTOR_zro_words(wordptr addr, N_word count) { BIT_VECTOR_ZERO_WORDS(addr,count) } static void BIT_VECTOR_cpy_words(wordptr target, wordptr source, N_word count) { BIT_VECTOR_COPY_WORDS(target,source,count) } static void BIT_VECTOR_mov_words(wordptr target, wordptr source, N_word count) { if (target != source) { if (target < source) BIT_VECTOR_COPY_WORDS(target,source,count) else BIT_VECTOR_BACK_WORDS(target,source,count) } } static void BIT_VECTOR_ins_words(wordptr addr, N_word total, N_word count, boolean clear) { N_word length; if ((total > 0) and (count > 0)) { if (count > total) count = total; length = total - count; if (length > 0) BIT_VECTOR_mov_words(addr+count,addr,length); if (clear) BIT_VECTOR_zro_words(addr,count); } } static void BIT_VECTOR_del_words(wordptr addr, N_word total, N_word count, boolean clear) { N_word length; if ((total > 0) and (count > 0)) { if (count > total) count = total; length = total - count; if (length > 0) BIT_VECTOR_mov_words(addr,addr+count,length); if (clear) BIT_VECTOR_zro_words(addr+length,count); } } static void BIT_VECTOR_reverse(charptr string, N_word length) { charptr last; N_char temp; if (length > 1) { last = string + length - 1; while (string < last) { temp = *string; *string = *last; *last = temp; string++; last--; } } } static N_word BIT_VECTOR_int2str(charptr string, N_word value) { N_word length; N_word digit; charptr work; work = string; if (value > 0) { length = 0; while (value > 0) { BIT_VECTOR_DIGITIZE(N_word,value,digit) *work++ = (N_char) digit; length++; } BIT_VECTOR_reverse(string,length); } else { length = 1; *work++ = (N_char) '0'; } return(length); } static N_word BIT_VECTOR_str2int(charptr string, N_word *value) { N_word length; N_word digit; *value = 0; length = 0; digit = (N_word) *string++; /* separate because isdigit() is likely a macro! */ while (isdigit((int)digit) != 0) { length++; digit -= (N_word) '0'; if (*value) *value *= 10; *value += digit; digit = (N_word) *string++; } return(length); } /********************************************/ /* routine to convert error code to string: */ /********************************************/ charptr BitVector_Error(BV_ErrCode error) { switch (error) { case BV_ErrCode_Ok: return( (charptr) NULL ); break; case BV_ErrCode_Type: return( (charptr) BV_ERRCODE_TYPE ); break; case BV_ErrCode_Bits: return( (charptr) BV_ERRCODE_BITS ); break; case BV_ErrCode_Word: return( (charptr) BV_ERRCODE_WORD ); break; case BV_ErrCode_Powr: return( (charptr) BV_ERRCODE_POWR ); break; case BV_ErrCode_Loga: return( (charptr) BV_ERRCODE_LOGA ); break; case BV_ErrCode_Lpwr: return( (charptr) BV_ERRCODE_LPWR ); break; case BV_ErrCode_WgtL: return( (charptr) BV_ERRCODE_WGTL ); break; case BV_ErrCode_Null: return( (charptr) BV_ERRCODE_NULL ); break; case BV_ErrCode_Indx: return( (charptr) BV_ERRCODE_INDX ); break; case BV_ErrCode_Ordr: return( (charptr) BV_ERRCODE_ORDR ); break; case BV_ErrCode_Size: return( (charptr) BV_ERRCODE_SIZE ); break; case BV_ErrCode_Pars: return( (charptr) BV_ERRCODE_PARS ); break; case BV_ErrCode_Ovfl: return( (charptr) BV_ERRCODE_OVFL ); break; case BV_ErrCode_Same: return( (charptr) BV_ERRCODE_SAME ); break; case BV_ErrCode_Expo: return( (charptr) BV_ERRCODE_EXPO ); break; case BV_ErrCode_Zero: return( (charptr) BV_ERRCODE_ZERO ); break; default: return( (charptr) BV_ERRCODE_OOPS ); break; } } /*****************************************/ /* automatic self-configuration routine: */ /*****************************************/ /*******************************************************/ /* */ /* MUST be called once prior to any other function */ /* to initialize the machine dependent constants */ /* of this package! */ /* */ /*******************************************************/ BV_ErrCode BitVector_Boot(void) { N_word sample; N_long longsample; if (sizeof(N_word) > sizeof(size_t)) return(BV_ErrCode_Type); BV_WordBits = 0; sample = ~0; while (sample) /* determine # of bits in a machine word */ { sample &= sample - 1; BV_WordBits++; } if (BV_WordBits != (sizeof(N_word) << 3)) return(BV_ErrCode_Bits); if (BV_WordBits < 16) return(BV_ErrCode_Word); BV_LongBits = 0; longsample = ~0L; while (longsample) /* determine # of bits in an unsigned long */ { longsample &= longsample - 1L; BV_LongBits++; } BV_LogBits = 0; sample = BV_ModMask = BV_WordBits - 1; if (sample AND BV_WordBits) return(BV_ErrCode_Powr); /* not a power of 2 */ while (sample) { sample &= sample - 1; BV_LogBits++; } if (BV_WordBits != (BV_LSB << BV_LogBits)) return(BV_ErrCode_Loga); /* ld wrong */ longsample = BV_LongBits - 1; if ((longsample AND BV_LongBits) or (BV_LongBits != (sizeof(N_long) << 3))) { BV_LongBits = (sizeof(N_long) << 3); longsample = BV_LongBits - 1; if (longsample AND BV_LongBits) return(BV_ErrCode_Lpwr); } if (BV_WordBits > BV_LongBits) return(BV_ErrCode_WgtL); if (BV_WordBits > BV_MASKTABSIZE) return(BV_ErrCode_Oops); for ( sample = 0; sample < BV_WordBits; sample++ ) { BV_BitMaskTab[sample] = (BV_LSB << sample); } BV_Factor = BV_LogBits - 3; /* ld(Bits/8) = ld(Bits)-ld(8) = ld(Bits)-3 */ BV_MSB = (BV_LSB << BV_ModMask); BV_Log10 = (N_word) (BV_ModMask * 0.30103); /* (Bits-1) * ln(2) / ln(10) */ BV_Exp10 = BIT_VECTOR_power10(BV_Log10); return(BV_ErrCode_Ok); } N_word BitVector_Size(N_int bits) /* bit vector size (# of words) */ { N_word size; size = bits >> BV_LogBits; if (bits AND BV_ModMask) size++; return(size); } N_word BitVector_Mask(N_int bits) /* bit vector mask (unused bits) */ { N_word mask; mask = bits AND BV_ModMask; if (mask) mask = (N_word) ~(~0L << mask); else mask = (N_word) ~0L; return(mask); } charptr BitVector_Version(void) { return((charptr)"7.4"); } N_int BitVector_Word_Bits(void) { return(BV_WordBits); } N_int BitVector_Long_Bits(void) { return(BV_LongBits); } /********************************************************************/ /* */ /* WARNING: Do not "free()" constant character strings, i.e., */ /* don't call "BitVector_Dispose()" for strings returned */ /* by "BitVector_Error()" or "BitVector_Version()"! */ /* */ /* ONLY call this function for strings allocated with "malloc()", */ /* i.e., the strings returned by the functions "BitVector_to_*()" */ /* and "BitVector_Block_Read()"! */ /* */ /********************************************************************/ void BitVector_Dispose(charptr string) /* free string */ { if (string != NULL) free((voidptr) string); } void BitVector_Destroy(wordptr addr) /* free bitvec */ { if (addr != NULL) { addr -= BV_HIDDENWORDS; free((voidptr) addr); } } void BitVector_Destroy_List(bv_listptr list, N_int count) /* free list */ { bv_listptr slot; if (list != NULL) { slot = list; while (count-- > 0) { BitVector_Destroy(*slot++); } free((voidptr) list); } } wordptr BitVector_Create(N_int bits, boolean clear) /* malloc */ { N_word size; N_word mask; N_word bytes; wordptr addr; wordptr zero; size = BitVector_Size(bits); mask = BitVector_Mask(bits); bytes = (size + BV_HIDDENWORDS) << BV_Factor; addr = (wordptr) malloc((size_t) bytes); if (addr != NULL) { *addr++ = bits; *addr++ = size; *addr++ = mask; if (clear) { zero = addr; BIT_VECTOR_ZERO_WORDS(zero,size) } } return(addr); } bv_listptr BitVector_Create_List(N_int bits, boolean clear, N_int count) { bv_listptr list = NULL; bv_listptr slot; wordptr addr; N_int i; if (count > 0) { list = (bv_listptr) malloc(sizeof(wordptr) * count); if (list != NULL) { slot = list; for ( i = 0; i < count; i++ ) { addr = BitVector_Create(bits,clear); if (addr == NULL) { BitVector_Destroy_List(list,i); return(NULL); } *slot++ = addr; } } } return(list); } wordptr BitVector_Resize(wordptr oldaddr, N_int bits) /* realloc */ { N_word bytes; N_word oldsize; N_word oldmask; N_word newsize; N_word newmask; wordptr newaddr; wordptr source; wordptr target; oldsize = BV_SIZE_(oldaddr); oldmask = BV_MASK_(oldaddr); newsize = BitVector_Size(bits); newmask = BitVector_Mask(bits); if (oldsize > 0) *(oldaddr+oldsize-1) &= oldmask; if (newsize <= oldsize) { newaddr = oldaddr; BV_BITS_(newaddr) = bits; BV_SIZE_(newaddr) = newsize; BV_MASK_(newaddr) = newmask; if (newsize > 0) *(newaddr+newsize-1) &= newmask; } else { bytes = (newsize + BV_HIDDENWORDS) << BV_Factor; newaddr = (wordptr) malloc((size_t) bytes); if (newaddr != NULL) { *newaddr++ = bits; *newaddr++ = newsize; *newaddr++ = newmask; target = newaddr; source = oldaddr; newsize -= oldsize; BIT_VECTOR_COPY_WORDS(target,source,oldsize) BIT_VECTOR_ZERO_WORDS(target,newsize) } BitVector_Destroy(oldaddr); } return(newaddr); } wordptr BitVector_Shadow(wordptr addr) /* makes new, same size but empty */ { return( BitVector_Create(BV_BITS_(addr),true) ); } wordptr BitVector_Clone(wordptr addr) /* makes exact duplicate */ { N_word bits; wordptr twin; bits = BV_BITS_(addr); twin = BitVector_Create(bits,false); if ((twin != NULL) and (bits > 0)) BIT_VECTOR_cpy_words(twin,addr,BV_SIZE_(addr)); return(twin); } wordptr BitVector_Concat(wordptr X, wordptr Y) /* returns concatenation */ { /* BEWARE that X = most significant part, Y = least significant part! */ N_word bitsX; N_word bitsY; N_word bitsZ; wordptr Z; bitsX = BV_BITS_(X); bitsY = BV_BITS_(Y); bitsZ = bitsX + bitsY; Z = BitVector_Create(bitsZ,false); if ((Z != NULL) and (bitsZ > 0)) { BIT_VECTOR_cpy_words(Z,Y,BV_SIZE_(Y)); BitVector_Interval_Copy(Z,X,bitsY,0,bitsX); *(Z+BV_SIZE_(Z)-1) &= BV_MASK_(Z); } return(Z); } void BitVector_Copy(wordptr X, wordptr Y) /* X = Y */ { N_word sizeX = BV_SIZE_(X); N_word sizeY = BV_SIZE_(Y); N_word maskX = BV_MASK_(X); N_word maskY = BV_MASK_(Y); N_word fill = 0; wordptr lastX; wordptr lastY; if ((X != Y) and (sizeX > 0)) { lastX = X + sizeX - 1; if (sizeY > 0) { lastY = Y + sizeY - 1; if ( (*lastY AND (maskY AND NOT (maskY >> 1))) == 0 ) *lastY &= maskY; else { fill = (N_word) ~0L; *lastY |= NOT maskY; } while ((sizeX > 0) and (sizeY > 0)) { *X++ = *Y++; sizeX--; sizeY--; } *lastY &= maskY; } while (sizeX-- > 0) *X++ = fill; *lastX &= maskX; } } void BitVector_Empty(wordptr addr) /* X = {} clr all */ { N_word size = BV_SIZE_(addr); BIT_VECTOR_ZERO_WORDS(addr,size) } void BitVector_Fill(wordptr addr) /* X = ~{} set all */ { N_word size = BV_SIZE_(addr); N_word mask = BV_MASK_(addr); N_word fill = (N_word) ~0L; if (size > 0) { BIT_VECTOR_FILL_WORDS(addr,fill,size) *(--addr) &= mask; } } void BitVector_Flip(wordptr addr) /* X = ~X flip all */ { N_word size = BV_SIZE_(addr); N_word mask = BV_MASK_(addr); N_word flip = (N_word) ~0L; if (size > 0) { BIT_VECTOR_FLIP_WORDS(addr,flip,size) *(--addr) &= mask; } } void BitVector_Primes(wordptr addr) { N_word bits = BV_BITS_(addr); N_word size = BV_SIZE_(addr); wordptr work; N_word temp; N_word i,j; if (size > 0) { temp = 0xAAAA; i = BV_WordBits >> 4; while (--i > 0) { temp <<= 16; temp |= 0xAAAA; } i = size; work = addr; *work++ = temp XOR 0x0006; while (--i > 0) *work++ = temp; for ( i = 3; (j = i * i) < bits; i += 2 ) { for ( ; j < bits; j += i ) BIT_VECTOR_CLR_BIT(addr,j) } *(addr+size-1) &= BV_MASK_(addr); } } void BitVector_Reverse(wordptr X, wordptr Y) { N_word bits = BV_BITS_(X); N_word mask; N_word bit; N_word value; if (bits > 0) { if (X == Y) BitVector_Interval_Reverse(X,0,bits-1); else if (bits == BV_BITS_(Y)) { /* mask = BV_MASK_(Y); */ /* mask &= NOT (mask >> 1); */ mask = BV_BitMaskTab[(bits-1) AND BV_ModMask]; Y += BV_SIZE_(Y) - 1; value = 0; bit = BV_LSB; while (bits-- > 0) { if ((*Y AND mask) != 0) { value |= bit; } if (not (mask >>= 1)) { Y--; mask = BV_MSB; } if (not (bit <<= 1)) { *X++ = value; value = 0; bit = BV_LSB; } } if (bit > BV_LSB) *X = value; } } } void BitVector_Interval_Empty(wordptr addr, N_int lower, N_int upper) { /* X = X \ [lower..upper] */ N_word bits = BV_BITS_(addr); N_word size = BV_SIZE_(addr); wordptr loaddr; wordptr hiaddr; N_word lobase; N_word hibase; N_word lomask; N_word himask; N_word diff; if ((size > 0) and (lower < bits) and (upper < bits) and (lower <= upper)) { lobase = lower >> BV_LogBits; hibase = upper >> BV_LogBits; diff = hibase - lobase; loaddr = addr + lobase; hiaddr = addr + hibase; lomask = (N_word) (~0L << (lower AND BV_ModMask)); himask = (N_word) ~((~0L << (upper AND BV_ModMask)) << 1); if (diff == 0) { *loaddr &= NOT (lomask AND himask); } else { *loaddr++ &= NOT lomask; while (--diff > 0) { *loaddr++ = 0; } *hiaddr &= NOT himask; } } } void BitVector_Interval_Fill(wordptr addr, N_int lower, N_int upper) { /* X = X + [lower..upper] */ N_word bits = BV_BITS_(addr); N_word size = BV_SIZE_(addr); N_word fill = (N_word) ~0L; wordptr loaddr; wordptr hiaddr; N_word lobase; N_word hibase; N_word lomask; N_word himask; N_word diff; if ((size > 0) and (lower < bits) and (upper < bits) and (lower <= upper)) { lobase = lower >> BV_LogBits; hibase = upper >> BV_LogBits; diff = hibase - lobase; loaddr = addr + lobase; hiaddr = addr + hibase; lomask = (N_word) (~0L << (lower AND BV_ModMask)); himask = (N_word) ~((~0L << (upper AND BV_ModMask)) << 1); if (diff == 0) { *loaddr |= (lomask AND himask); } else { *loaddr++ |= lomask; while (--diff > 0) { *loaddr++ = fill; } *hiaddr |= himask; } *(addr+size-1) &= BV_MASK_(addr); } } void BitVector_Interval_Flip(wordptr addr, N_int lower, N_int upper) { /* X = X ^ [lower..upper] */ N_word bits = BV_BITS_(addr); N_word size = BV_SIZE_(addr); N_word flip = (N_word) ~0L; wordptr loaddr; wordptr hiaddr; N_word lobase; N_word hibase; N_word lomask; N_word himask; N_word diff; if ((size > 0) and (lower < bits) and (upper < bits) and (lower <= upper)) { lobase = lower >> BV_LogBits; hibase = upper >> BV_LogBits; diff = hibase - lobase; loaddr = addr + lobase; hiaddr = addr + hibase; lomask = (N_word) (~0L << (lower AND BV_ModMask)); himask = (N_word) ~((~0L << (upper AND BV_ModMask)) << 1); if (diff == 0) { *loaddr ^= (lomask AND himask); } else { *loaddr++ ^= lomask; while (--diff > 0) { *loaddr++ ^= flip; } *hiaddr ^= himask; } *(addr+size-1) &= BV_MASK_(addr); } } void BitVector_Interval_Reverse(wordptr addr, N_int lower, N_int upper) { N_word bits = BV_BITS_(addr); wordptr loaddr; wordptr hiaddr; N_word lomask; N_word himask; if ((bits > 0) and (lower < bits) and (upper < bits) and (lower < upper)) { loaddr = addr + (lower >> BV_LogBits); hiaddr = addr + (upper >> BV_LogBits); lomask = BV_BitMaskTab[lower AND BV_ModMask]; himask = BV_BitMaskTab[upper AND BV_ModMask]; for ( bits = upper - lower + 1; bits > 1; bits -= 2 ) { if (((*loaddr AND lomask) != 0) XOR ((*hiaddr AND himask) != 0)) { *loaddr ^= lomask; /* swap bits only if they differ! */ *hiaddr ^= himask; } if (not (lomask <<= 1)) { lomask = BV_LSB; loaddr++; } if (not (himask >>= 1)) { himask = BV_MSB; hiaddr--; } } } } boolean BitVector_interval_scan_inc(wordptr addr, N_int start, N_intptr min, N_intptr max) { N_word size = BV_SIZE_(addr); N_word mask = BV_MASK_(addr); N_word offset; N_word bitmask; N_word value; boolean empty; if ((size == 0) or (start >= BV_BITS_(addr))) return(false); *min = start; *max = start; offset = start >> BV_LogBits; *(addr+size-1) &= mask; addr += offset; size -= offset; bitmask = BV_BitMaskTab[start AND BV_ModMask]; mask = NOT (bitmask OR (bitmask - 1)); value = *addr++; if ((value AND bitmask) == 0) { value &= mask; if (value == 0) { offset++; empty = true; while (empty and (--size > 0)) { if ((value = *addr++)) empty = false; else offset++; } if (empty) return(false); } start = offset << BV_LogBits; bitmask = BV_LSB; mask = value; while (not (mask AND BV_LSB)) { bitmask <<= 1; mask >>= 1; start++; } mask = NOT (bitmask OR (bitmask - 1)); *min = start; *max = start; } value = NOT value; value &= mask; if (value == 0) { offset++; empty = true; while (empty and (--size > 0)) { if ((value = NOT *addr++)) empty = false; else offset++; } if (empty) value = BV_LSB; } start = offset << BV_LogBits; while (not (value AND BV_LSB)) { value >>= 1; start++; } *max = --start; return(true); } boolean BitVector_interval_scan_dec(wordptr addr, N_int start, N_intptr min, N_intptr max) { N_word size = BV_SIZE_(addr); N_word mask = BV_MASK_(addr); N_word offset; N_word bitmask; N_word value; boolean empty; if ((size == 0) or (start >= BV_BITS_(addr))) return(false); *min = start; *max = start; offset = start >> BV_LogBits; if (offset >= size) return(false); *(addr+size-1) &= mask; addr += offset; size = ++offset; bitmask = BV_BitMaskTab[start AND BV_ModMask]; mask = (bitmask - 1); value = *addr--; if ((value AND bitmask) == 0) { value &= mask; if (value == 0) { offset--; empty = true; while (empty and (--size > 0)) { if ((value = *addr--)) empty = false; else offset--; } if (empty) return(false); } start = offset << BV_LogBits; bitmask = BV_MSB; mask = value; while (not (mask AND BV_MSB)) { bitmask >>= 1; mask <<= 1; start--; } mask = (bitmask - 1); *max = --start; *min = start; } value = NOT value; value &= mask; if (value == 0) { offset--; empty = true; while (empty and (--size > 0)) { if ((value = NOT *addr--)) empty = false; else offset--; } if (empty) value = BV_MSB; } start = offset << BV_LogBits; while (not (value AND BV_MSB)) { value <<= 1; start--; } *min = start; return(true); } void BitVector_Interval_Copy(wordptr X, wordptr Y, N_int Xoffset, N_int Yoffset, N_int length) { N_word bitsX = BV_BITS_(X); N_word bitsY = BV_BITS_(Y); N_word source = 0; /* silence compiler warning */ N_word target = 0; /* silence compiler warning */ N_word s_lo_base; N_word s_hi_base; N_word s_lo_bit; N_word s_hi_bit; N_word s_base; N_word s_lower = 0; /* silence compiler warning */ N_word s_upper = 0; /* silence compiler warning */ N_word s_bits; N_word s_min; N_word s_max; N_word t_lo_base; N_word t_hi_base; N_word t_lo_bit; N_word t_hi_bit; N_word t_base; N_word t_lower = 0; /* silence compiler warning */ N_word t_upper = 0; /* silence compiler warning */ N_word t_bits; N_word t_min; N_word mask; N_word bits; N_word select; boolean ascending; boolean notfirst; wordptr Z = X; if ((length > 0) and (Xoffset < bitsX) and (Yoffset < bitsY)) { if ((Xoffset + length) > bitsX) length = bitsX - Xoffset; if ((Yoffset + length) > bitsY) length = bitsY - Yoffset; ascending = (Xoffset <= Yoffset); s_lo_base = Yoffset >> BV_LogBits; s_lo_bit = Yoffset AND BV_ModMask; Yoffset += --length; s_hi_base = Yoffset >> BV_LogBits; s_hi_bit = Yoffset AND BV_ModMask; t_lo_base = Xoffset >> BV_LogBits; t_lo_bit = Xoffset AND BV_ModMask; Xoffset += length; t_hi_base = Xoffset >> BV_LogBits; t_hi_bit = Xoffset AND BV_ModMask; if (ascending) { s_base = s_lo_base; t_base = t_lo_base; } else { s_base = s_hi_base; t_base = t_hi_base; } s_bits = 0; t_bits = 0; Y += s_base; X += t_base; notfirst = false; while (true) { if (t_bits == 0) { if (notfirst) { *X = target; if (ascending) { if (t_base == t_hi_base) break; t_base++; X++; } else { if (t_base == t_lo_base) break; t_base--; X--; } } select = ((t_base == t_hi_base) << 1) OR (t_base == t_lo_base); switch (select) { case 0: t_lower = 0; t_upper = BV_WordBits - 1; t_bits = BV_WordBits; target = 0; break; case 1: t_lower = t_lo_bit; t_upper = BV_WordBits - 1; t_bits = BV_WordBits - t_lo_bit; mask = (N_word) (~0L << t_lower); target = *X AND NOT mask; break; case 2: t_lower = 0; t_upper = t_hi_bit; t_bits = t_hi_bit + 1; mask = (N_word) ((~0L << t_upper) << 1); target = *X AND mask; break; case 3: t_lower = t_lo_bit; t_upper = t_hi_bit; t_bits = t_hi_bit - t_lo_bit + 1; mask = (N_word) (~0L << t_lower); mask &= (N_word) ~((~0L << t_upper) << 1); target = *X AND NOT mask; break; } } if (s_bits == 0) { if (notfirst) { if (ascending) { if (s_base == s_hi_base) break; s_base++; Y++; } else { if (s_base == s_lo_base) break; s_base--; Y--; } } source = *Y; select = ((s_base == s_hi_base) << 1) OR (s_base == s_lo_base); switch (select) { case 0: s_lower = 0; s_upper = BV_WordBits - 1; s_bits = BV_WordBits; break; case 1: s_lower = s_lo_bit; s_upper = BV_WordBits - 1; s_bits = BV_WordBits - s_lo_bit; break; case 2: s_lower = 0; s_upper = s_hi_bit; s_bits = s_hi_bit + 1; break; case 3: s_lower = s_lo_bit; s_upper = s_hi_bit; s_bits = s_hi_bit - s_lo_bit + 1; break; } } notfirst = true; if (s_bits > t_bits) { bits = t_bits - 1; if (ascending) { s_min = s_lower; s_max = s_lower + bits; } else { s_max = s_upper; s_min = s_upper - bits; } t_min = t_lower; } else { bits = s_bits - 1; if (ascending) t_min = t_lower; else t_min = t_upper - bits; s_min = s_lower; s_max = s_upper; } bits++; mask = (N_word) (~0L << s_min); mask &= (N_word) ~((~0L << s_max) << 1); if (s_min == t_min) target |= (source AND mask); else { if (s_min < t_min) target |= (source AND mask) << (t_min-s_min); else target |= (source AND mask) >> (s_min-t_min); } if (ascending) { s_lower += bits; t_lower += bits; } else { s_upper -= bits; t_upper -= bits; } s_bits -= bits; t_bits -= bits; } *(Z+BV_SIZE_(Z)-1) &= BV_MASK_(Z); } } wordptr BitVector_Interval_Substitute(wordptr X, wordptr Y, N_int Xoffset, N_int Xlength, N_int Yoffset, N_int Ylength) { N_word Xbits = BV_BITS_(X); N_word Ybits = BV_BITS_(Y); N_word limit; N_word diff; if ((Xoffset <= Xbits) and (Yoffset <= Ybits)) { limit = Xoffset + Xlength; if (limit > Xbits) { limit = Xbits; Xlength = Xbits - Xoffset; } if ((Yoffset + Ylength) > Ybits) { Ylength = Ybits - Yoffset; } if (Xlength == Ylength) { if ((Ylength > 0) and ((X != Y) or (Xoffset != Yoffset))) { BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength); } } else /* Xlength != Ylength */ { if (Xlength > Ylength) { diff = Xlength - Ylength; if (Ylength > 0) BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength); if (limit < Xbits) BitVector_Delete(X,Xoffset+Ylength,diff,false); if ((X = BitVector_Resize(X,Xbits-diff)) == NULL) return(NULL); } else /* Ylength > Xlength ==> Ylength > 0 */ { diff = Ylength - Xlength; if (X != Y) { if ((X = BitVector_Resize(X,Xbits+diff)) == NULL) return(NULL); if (limit < Xbits) BitVector_Insert(X,limit,diff,false); BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength); } else /* in-place */ { if ((Y = X = BitVector_Resize(X,Xbits+diff)) == NULL) return(NULL); if (limit >= Xbits) { BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength); } else /* limit < Xbits */ { BitVector_Insert(X,limit,diff,false); if ((Yoffset+Ylength) <= limit) { BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength); } else /* overlaps or lies above critical area */ { if (limit <= Yoffset) { Yoffset += diff; BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength); } else /* Yoffset < limit */ { Xlength = limit - Yoffset; BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Xlength); Yoffset = Xoffset + Ylength; /* = limit + diff */ Xoffset += Xlength; Ylength -= Xlength; BitVector_Interval_Copy(X,Y,Xoffset,Yoffset,Ylength); } } } } } } } return(X); } boolean BitVector_is_empty(wordptr addr) /* X == {} ? */ { N_word size = BV_SIZE_(addr); boolean r = true; if (size > 0) { *(addr+size-1) &= BV_MASK_(addr); while (r and (size-- > 0)) r = ( *addr++ == 0 ); } return(r); } boolean BitVector_is_full(wordptr addr) /* X == ~{} ? */ { N_word size = BV_SIZE_(addr); N_word mask = BV_MASK_(addr); boolean r = false; wordptr last; if (size > 0) { r = true; last = addr + size - 1; *last |= NOT mask; while (r and (size-- > 0)) r = ( NOT *addr++ == 0 ); *last &= mask; } return(r); } boolean BitVector_equal(wordptr X, wordptr Y) /* X == Y ? */ { N_word size = BV_SIZE_(X); N_word mask = BV_MASK_(X); boolean r = false; if (BV_BITS_(X) == BV_BITS_(Y)) { r = true; if (size > 0) { *(X+size-1) &= mask; *(Y+size-1) &= mask; while (r and (size-- > 0)) r = (*X++ == *Y++); } } return(r); } Z_int BitVector_Lexicompare(wordptr X, wordptr Y) /* X <,=,> Y ? */ { /* unsigned */ N_word bitsX = BV_BITS_(X); N_word bitsY = BV_BITS_(Y); N_word size = BV_SIZE_(X); boolean r = true; if (bitsX == bitsY) { if (size > 0) { X += size; Y += size; while (r and (size-- > 0)) r = (*(--X) == *(--Y)); } if (r) return((Z_int) 0); else { if (*X < *Y) return((Z_int) -1); else return((Z_int) 1); } } else { if (bitsX < bitsY) return((Z_int) -1); else return((Z_int) 1); } } Z_int BitVector_Compare(wordptr X, wordptr Y) /* X <,=,> Y ? */ { /* signed */ N_word bitsX = BV_BITS_(X); N_word bitsY = BV_BITS_(Y); N_word size = BV_SIZE_(X); N_word mask = BV_MASK_(X); N_word sign; boolean r = true; if (bitsX == bitsY) { if (size > 0) { X += size; Y += size; mask &= NOT (mask >> 1); if ((sign = (*(X-1) AND mask)) != (*(Y-1) AND mask)) { if (sign) return((Z_int) -1); else return((Z_int) 1); } while (r and (size-- > 0)) r = (*(--X) == *(--Y)); } if (r) return((Z_int) 0); else { if (*X < *Y) return((Z_int) -1); else return((Z_int) 1); } } else { if (bitsX < bitsY) return((Z_int) -1); else return((Z_int) 1); } } charptr BitVector_to_Hex(wordptr addr) { N_word bits = BV_BITS_(addr); N_word size = BV_SIZE_(addr); N_word value; N_word count; N_word digit; N_word length; charptr string; length = bits >> 2; if (bits AND 0x0003) length++; string = (charptr) malloc((size_t) (length+1)); if (string == NULL) return(NULL); string += length; *string = (N_char) '\0'; if (size > 0) { *(addr+size-1) &= BV_MASK_(addr); while ((size-- > 0) and (length > 0)) { value = *addr++; count = BV_WordBits >> 2; while ((count-- > 0) and (length > 0)) { digit = value AND 0x000F; if (digit > 9) digit += (N_word) 'A' - 10; else digit += (N_word) '0'; *(--string) = (N_char) digit; length--; if ((count > 0) and (length > 0)) value >>= 4; } } } return(string); } BV_ErrCode BitVector_from_Hex(wordptr addr, charptr string) { N_word size = BV_SIZE_(addr); N_word mask = BV_MASK_(addr); boolean ok = true; N_word length; N_word value; N_word count; int digit; if (size > 0) { length = strlen((char *) string); string += length; while (size-- > 0) { value = 0; for ( count = 0; (ok and (length > 0) and (count < BV_WordBits)); count += 4 ) { digit = (int) *(--string); length--; /* separate because toupper() is likely a macro! */ digit = toupper(digit); if ((ok = (isxdigit(digit) != 0))) { if (digit >= (int) 'A') digit -= (int) 'A' - 10; else digit -= (int) '0'; value |= (((N_word) digit) << count); } } *addr++ = value; } *(--addr) &= mask; } if (ok) return(BV_ErrCode_Ok); else return(BV_ErrCode_Pars); } charptr BitVector_to_Bin(wordptr addr) { N_word size = BV_SIZE_(addr); N_word value; N_word count; N_word digit; N_word length; charptr string; length = BV_BITS_(addr); string = (charptr) malloc((size_t) (length+1)); if (string == NULL) return(NULL); string += length; *string = (N_char) '\0'; if (size > 0) { *(addr+size-1) &= BV_MASK_(addr); while (size-- > 0) { value = *addr++; count = BV_WordBits; if (count > length) count = length; while (count-- > 0) { digit = value AND 0x0001; digit += (N_word) '0'; *(--string) = (N_char) digit; length--; if (count > 0) value >>= 1; } } } return(string); } BV_ErrCode BitVector_from_Bin(wordptr addr, charptr string) { N_word size = BV_SIZE_(addr); N_word mask = BV_MASK_(addr); boolean ok = true; N_word length; N_word value; N_word count; int digit; if (size > 0) { length = strlen((char *) string); string += length; while (size-- > 0) { value = 0; for ( count = 0; (ok and (length > 0) and (count < BV_WordBits)); count++ ) { digit = (int) *(--string); length--; switch (digit) { case (int) '0': break; case (int) '1': value |= BV_BitMaskTab[count]; break; default: ok = false; break; } } *addr++ = value; } *(--addr) &= mask; } if (ok) return(BV_ErrCode_Ok); else return(BV_ErrCode_Pars); } charptr BitVector_to_Dec(wordptr addr) { N_word bits = BV_BITS_(addr); N_word length; N_word digits; N_word count; N_word q; N_word r; boolean loop; charptr result; charptr string; wordptr quot; wordptr rest; wordptr temp; wordptr base; Z_int sign; length = (N_word) (bits / 3.3); /* digits = bits * ln(2) / ln(10) */ length += 2; /* compensate for truncating & provide space for minus sign */ result = (charptr) malloc((size_t) (length+1)); /* remember the '\0'! */ if (result == NULL) return(NULL); string = result; sign = BitVector_Sign(addr); if ((bits < 4) or (sign == 0)) { if (bits > 0) digits = *addr; else digits = (N_word) 0; if (sign < 0) digits = ((N_word)(-((Z_word)digits))) AND BV_MASK_(addr); *string++ = (N_char) digits + (N_char) '0'; digits = 1; } else { quot = BitVector_Create(bits,false); if (quot == NULL) { BitVector_Dispose(result); return(NULL); } rest = BitVector_Create(bits,false); if (rest == NULL) { BitVector_Dispose(result); BitVector_Destroy(quot); return(NULL); } temp = BitVector_Create(bits,false); if (temp == NULL) { BitVector_Dispose(result); BitVector_Destroy(quot); BitVector_Destroy(rest); return(NULL); } base = BitVector_Create(bits,true); if (base == NULL) { BitVector_Dispose(result); BitVector_Destroy(quot); BitVector_Destroy(rest); BitVector_Destroy(temp); return(NULL); } if (sign < 0) BitVector_Negate(quot,addr); else BitVector_Copy(quot,addr); digits = 0; *base = BV_Exp10; loop = (bits >= BV_WordBits); do { if (loop) { BitVector_Copy(temp,quot); if (BitVector_Div_Pos(quot,temp,base,rest)) { BitVector_Dispose(result); /* emergency exit */ BitVector_Destroy(quot); BitVector_Destroy(rest); /* should never occur */ BitVector_Destroy(temp); /* under normal operation */ BitVector_Destroy(base); return(NULL); } loop = not BitVector_is_empty(quot); q = *rest; } else q = *quot; count = BV_Log10; while (((loop and (count-- > 0)) or ((not loop) and (q != 0))) and (digits < length)) { if (q != 0) { BIT_VECTOR_DIGITIZE(N_word,q,r) } else r = (N_word) '0'; *string++ = (N_char) r; digits++; } } while (loop and (digits < length)); BitVector_Destroy(quot); BitVector_Destroy(rest); BitVector_Destroy(temp); BitVector_Destroy(base); } if ((sign < 0) and (digits < length)) { *string++ = (N_char) '-'; digits++; } *string = (N_char) '\0'; BIT_VECTOR_reverse(result,digits); return(result); } BV_ErrCode BitVector_from_Dec(wordptr addr, charptr string) { BV_ErrCode error = BV_ErrCode_Ok; N_word bits = BV_BITS_(addr); N_word mask = BV_MASK_(addr); boolean init = (bits > BV_WordBits); boolean minus; boolean shift; boolean carry; wordptr term; wordptr base; wordptr prod; wordptr rank; wordptr temp; N_word accu; N_word powr; N_word count; N_word length; int digit; if (bits > 0) { length = strlen((char *) string); if (length == 0) return(BV_ErrCode_Pars); digit = (int) *string; if ((minus = (digit == (int) '-')) or (digit == (int) '+')) { string++; if (--length == 0) return(BV_ErrCode_Pars); } string += length; term = BitVector_Create(BV_WordBits,false); if (term == NULL) { return(BV_ErrCode_Null); } base = BitVector_Create(BV_WordBits,false); if (base == NULL) { BitVector_Destroy(term); return(BV_ErrCode_Null); } prod = BitVector_Create(bits,init); if (prod == NULL) { BitVector_Destroy(term); BitVector_Destroy(base); return(BV_ErrCode_Null); } rank = BitVector_Create(bits,init); if (rank == NULL) { BitVector_Destroy(term); BitVector_Destroy(base); BitVector_Destroy(prod); return(BV_ErrCode_Null); } temp = BitVector_Create(bits,false); if (temp == NULL) { BitVector_Destroy(term); BitVector_Destroy(base); BitVector_Destroy(prod); BitVector_Destroy(rank); return(BV_ErrCode_Null); } BitVector_Empty(addr); *base = BV_Exp10; shift = false; while ((not error) and (length > 0)) { accu = 0; powr = 1; count = BV_Log10; while ((not error) and (length > 0) and (count-- > 0)) { digit = (int) *(--string); length--; /* separate because isdigit() is likely a macro! */ if (isdigit(digit) != 0) { accu += ((N_word) digit - (N_word) '0') * powr; powr *= 10; } else error = BV_ErrCode_Pars; } if (not error) { if (shift) { *term = accu; BitVector_Copy(temp,rank); error = BitVector_Mul_Pos(prod,temp,term,false); } else { *prod = accu; if ((not init) and ((accu AND NOT mask) != 0)) error = BV_ErrCode_Ovfl; } if (not error) { carry = false; BitVector_compute(addr,addr,prod,false,&carry); /* ignores sign change (= overflow) but not */ /* numbers too large (= carry) for resulting bit vector */ if (carry) error = BV_ErrCode_Ovfl; else { if (length > 0) { if (shift) { BitVector_Copy(temp,rank); error = BitVector_Mul_Pos(rank,temp,base,false); } else { *rank = *base; shift = true; } } } } } } BitVector_Destroy(term); BitVector_Destroy(base); BitVector_Destroy(prod); BitVector_Destroy(rank); BitVector_Destroy(temp); if (not error and minus) { BitVector_Negate(addr,addr); if ((*(addr + BV_SIZE_(addr) - 1) AND mask AND NOT (mask >> 1)) == 0) error = BV_ErrCode_Ovfl; } } return(error); } charptr BitVector_to_Enum(wordptr addr) { N_word bits = BV_BITS_(addr); N_word sample; N_word length; N_word digits; N_word factor; N_word power; N_word start; N_word min; N_word max; charptr string; charptr target; boolean comma; if (bits > 0) { sample = bits - 1; /* greatest possible index */ length = 2; /* account for index 0 and terminating '\0' */ digits = 1; /* account for intervening dashes and commas */ factor = 1; power = 10; while (sample >= (power-1)) { length += ++digits * factor * 6; /* 9,90,900,9000,... (9*2/3 = 6) */ factor = power; power *= 10; } if (sample > --factor) { sample -= factor; factor = (N_word) ( sample / 3 ); factor = (factor << 1) + (sample - (factor * 3)); length += ++digits * factor; } } else length = 1; string = (charptr) malloc((size_t) length); if (string == NULL) return(NULL); start = 0; comma = false; target = string; while ((start < bits) and BitVector_interval_scan_inc(addr,start,&min,&max)) { start = max + 2; if (comma) *target++ = (N_char) ','; if (min == max) { target += BIT_VECTOR_int2str(target,min); } else { if (min+1 == max) { target += BIT_VECTOR_int2str(target,min); *target++ = (N_char) ','; target += BIT_VECTOR_int2str(target,max); } else { target += BIT_VECTOR_int2str(target,min); *target++ = (N_char) '-'; target += BIT_VECTOR_int2str(target,max); } } comma = true; } *target = (N_char) '\0'; return(string); } BV_ErrCode BitVector_from_Enum(wordptr addr, charptr string) { BV_ErrCode error = BV_ErrCode_Ok; N_word bits = BV_BITS_(addr); N_word state = 1; N_word start = 0; /* silence compiler warning */ N_word token; N_word index; if (bits > 0) { BitVector_Empty(addr); while ((not error) and (state != 0)) { token = (N_word) *string; /* separate because isdigit() is likely a macro! */ if (isdigit((int)token) != 0) { string += BIT_VECTOR_str2int(string,&index); if (index < bits) token = (N_word) '0'; else error = BV_ErrCode_Indx; } else string++; if (not error) switch (state) { case 1: switch (token) { case (N_word) '0': state = 2; break; case (N_word) '\0': state = 0; break; default: error = BV_ErrCode_Pars; break; } break; case 2: switch (token) { case (N_word) '-': start = index; state = 3; break; case (N_word) ',': BIT_VECTOR_SET_BIT(addr,index) state = 5; break; case (N_word) '\0': BIT_VECTOR_SET_BIT(addr,index) state = 0; break; default: error = BV_ErrCode_Pars; break; } break; case 3: switch (token) { case (N_word) '0': if (start < index) BitVector_Interval_Fill(addr,start,index); else if (start == index) BIT_VECTOR_SET_BIT(addr,index) else error = BV_ErrCode_Ordr; state = 4; break; default: error = BV_ErrCode_Pars; break; } break; case 4: switch (token) { case (N_word) ',': state = 5; break; case (N_word) '\0': state = 0; break; default: error = BV_ErrCode_Pars; break; } break; case 5: switch (token) { case (N_word) '0': state = 2; break; default: error = BV_ErrCode_Pars; break; } break; } } } return(error); } void BitVector_Bit_Off(wordptr addr, N_int index) /* X = X \ {x} */ { if (index < BV_BITS_(addr)) BIT_VECTOR_CLR_BIT(addr,index) } void BitVector_Bit_On(wordptr addr, N_int index) /* X = X + {x} */ { if (index < BV_BITS_(addr)) BIT_VECTOR_SET_BIT(addr,index) } boolean BitVector_bit_flip(wordptr addr, N_int index) /* X=(X+{x})\(X*{x}) */ { N_word mask; if (index < BV_BITS_(addr)) return( BIT_VECTOR_FLP_BIT(addr,index,mask) ); else return( false ); } boolean BitVector_bit_test(wordptr addr, N_int index) /* {x} in X ? */ { if (index < BV_BITS_(addr)) return( BIT_VECTOR_TST_BIT(addr,index) ); else return( false ); } void BitVector_Bit_Copy(wordptr addr, N_int index, boolean bit) { if (index < BV_BITS_(addr)) { if (bit) BIT_VECTOR_SET_BIT(addr,index) else BIT_VECTOR_CLR_BIT(addr,index) } } void BitVector_LSB(wordptr addr, boolean bit) { if (BV_BITS_(addr) > 0) { if (bit) *addr |= BV_LSB; else *addr &= NOT BV_LSB; } } void BitVector_MSB(wordptr addr, boolean bit) { N_word size = BV_SIZE_(addr); N_word mask = BV_MASK_(addr); if (size-- > 0) { if (bit) *(addr+size) |= mask AND NOT (mask >> 1); else *(addr+size) &= NOT mask OR (mask >> 1); } } boolean BitVector_lsb_(wordptr addr) { if (BV_SIZE_(addr) > 0) return( (*addr AND BV_LSB) != 0 ); else return( false ); } boolean BitVector_msb_(wordptr addr) { N_word size = BV_SIZE_(addr); N_word mask = BV_MASK_(addr); if (size-- > 0) return( (*(addr+size) AND (mask AND NOT (mask >> 1))) != 0 ); else return( false ); } boolean BitVector_rotate_left(wordptr addr) { N_word size = BV_SIZE_(addr); N_word mask = BV_MASK_(addr); N_word msb; boolean carry_in; boolean carry_out = false; if (size > 0) { msb = mask AND NOT (mask >> 1); carry_in = ((*(addr+size-1) AND msb) != 0); while (size-- > 1) { carry_out = ((*addr AND BV_MSB) != 0); *addr <<= 1; if (carry_in) *addr |= BV_LSB; carry_in = carry_out; addr++; } carry_out = ((*addr AND msb) != 0); *addr <<= 1; if (carry_in) *addr |= BV_LSB; *addr &= mask; } return(carry_out); } boolean BitVector_rotate_right(wordptr addr) { N_word size = BV_SIZE_(addr); N_word mask = BV_MASK_(addr); N_word msb; boolean carry_in; boolean carry_out = false; if (size > 0) { msb = mask AND NOT (mask >> 1); carry_in = ((*addr AND BV_LSB) != 0); addr += size-1; *addr &= mask; carry_out = ((*addr AND BV_LSB) != 0); *addr >>= 1; if (carry_in) *addr |= msb; carry_in = carry_out; addr--; size--; while (size-- > 0) { carry_out = ((*addr AND BV_LSB) != 0); *addr >>= 1; if (carry_in) *addr |= BV_MSB; carry_in = carry_out; addr--; } } return(carry_out); } boolean BitVector_shift_left(wordptr addr, boolean carry_in) { N_word size = BV_SIZE_(addr); N_word mask = BV_MASK_(addr); N_word msb; boolean carry_out = carry_in; if (size > 0) { msb = mask AND NOT (mask >> 1); while (size-- > 1) { carry_out = ((*addr AND BV_MSB) != 0); *addr <<= 1; if (carry_in) *addr |= BV_LSB; carry_in = carry_out; addr++; } carry_out = ((*addr AND msb) != 0); *addr <<= 1; if (carry_in) *addr |= BV_LSB; *addr &= mask; } return(carry_out); } boolean BitVector_shift_right(wordptr addr, boolean carry_in) { N_word size = BV_SIZE_(addr); N_word mask = BV_MASK_(addr); N_word msb; boolean carry_out = carry_in; if (size > 0) { msb = mask AND NOT (mask >> 1); addr += size-1; *addr &= mask; carry_out = ((*addr AND BV_LSB) != 0); *addr >>= 1; if (carry_in) *addr |= msb; carry_in = carry_out; addr--; size--; while (size-- > 0) { carry_out = ((*addr AND BV_LSB) != 0); *addr >>= 1; if (carry_in) *addr |= BV_MSB; carry_in = carry_out; addr--; } } return(carry_out); } void BitVector_Move_Left(wordptr addr, N_int bits) { N_word count; N_word words; if (bits > 0) { count = bits AND BV_ModMask; words = bits >> BV_LogBits; if (bits >= BV_BITS_(addr)) BitVector_Empty(addr); else { while (count-- > 0) BitVector_shift_left(addr,0); BitVector_Word_Insert(addr,0,words,true); } } } void BitVector_Move_Right(wordptr addr, N_int bits) { N_word count; N_word words; if (bits > 0) { count = bits AND BV_ModMask; words = bits >> BV_LogBits; if (bits >= BV_BITS_(addr)) BitVector_Empty(addr); else { while (count-- > 0) BitVector_shift_right(addr,0); BitVector_Word_Delete(addr,0,words,true); } } } void BitVector_Insert(wordptr addr, N_int offset, N_int count, boolean clear) { N_word bits = BV_BITS_(addr); N_word last; if ((count > 0) and (offset < bits)) { last = offset + count; if (last < bits) { BitVector_Interval_Copy(addr,addr,last,offset,(bits-last)); } else last = bits; if (clear) BitVector_Interval_Empty(addr,offset,(last-1)); } } void BitVector_Delete(wordptr addr, N_int offset, N_int count, boolean clear) { N_word bits = BV_BITS_(addr); N_word last; if ((count > 0) and (offset < bits)) { last = offset + count; if (last < bits) { BitVector_Interval_Copy(addr,addr,offset,last,(bits-last)); } else count = bits - offset; if (clear) BitVector_Interval_Empty(addr,(bits-count),(bits-1)); } } boolean BitVector_increment(wordptr addr) /* X++ */ { N_word size = BV_SIZE_(addr); N_word mask = BV_MASK_(addr); wordptr last = addr + size - 1; boolean carry = true; if (size > 0) { *last |= NOT mask; while (carry and (size-- > 0)) { carry = (++(*addr++) == 0); } *last &= mask; } return(carry); } boolean BitVector_decrement(wordptr addr) /* X-- */ { N_word size = BV_SIZE_(addr); N_word mask = BV_MASK_(addr); wordptr last = addr + size - 1; boolean carry = true; if (size > 0) { *last &= mask; while (carry and (size-- > 0)) { carry = (*addr == 0); --(*addr++); } *last &= mask; } return(carry); } boolean BitVector_compute(wordptr X, wordptr Y, wordptr Z, boolean minus, boolean *carry) { N_word size = BV_SIZE_(X); N_word mask = BV_MASK_(X); N_word vv = 0; N_word cc; N_word mm; N_word yy; N_word zz; N_word lo; N_word hi; if (size > 0) { if (minus) cc = (*carry == 0); else cc = (*carry != 0); /* deal with (size-1) least significant full words first: */ while (--size > 0) { yy = *Y++; if (minus) zz = (N_word) NOT ( Z ? *Z++ : 0 ); else zz = (N_word) ( Z ? *Z++ : 0 ); lo = (yy AND BV_LSB) + (zz AND BV_LSB) + cc; hi = (yy >> 1) + (zz >> 1) + (lo >> 1); cc = ((hi AND BV_MSB) != 0); *X++ = (hi << 1) OR (lo AND BV_LSB); } /* deal with most significant word (may be used only partially): */ yy = *Y AND mask; if (minus) zz = (N_word) NOT ( Z ? *Z : 0 ); else zz = (N_word) ( Z ? *Z : 0 ); zz &= mask; if (mask == BV_LSB) /* special case, only one bit used */ { vv = cc; lo = yy + zz + cc; cc = (lo >> 1); vv ^= cc; *X = lo AND BV_LSB; } else { if (NOT mask) /* not all bits are used, but more than one */ { mm = (mask >> 1); vv = (yy AND mm) + (zz AND mm) + cc; mm = mask AND NOT mm; lo = yy + zz + cc; cc = (lo >> 1); vv ^= cc; vv &= mm; cc &= mm; *X = lo AND mask; } else /* other special case, all bits are used */ { mm = NOT BV_MSB; lo = (yy AND mm) + (zz AND mm) + cc; vv = lo AND BV_MSB; hi = ((yy AND BV_MSB) >> 1) + ((zz AND BV_MSB) >> 1) + (vv >> 1); cc = hi AND BV_MSB; vv ^= cc; *X = (hi << 1) OR (lo AND mm); } } if (minus) *carry = (cc == 0); else *carry = (cc != 0); } return(vv != 0); } boolean BitVector_add(wordptr X, wordptr Y, wordptr Z, boolean *carry) { return(BitVector_compute(X,Y,Z,false,carry)); } boolean BitVector_sub(wordptr X, wordptr Y, wordptr Z, boolean *carry) { return(BitVector_compute(X,Y,Z,true,carry)); } boolean BitVector_inc(wordptr X, wordptr Y) { boolean carry = true; return(BitVector_compute(X,Y,NULL,false,&carry)); } boolean BitVector_dec(wordptr X, wordptr Y) { boolean carry = true; return(BitVector_compute(X,Y,NULL,true,&carry)); } void BitVector_Negate(wordptr X, wordptr Y) { N_word size = BV_SIZE_(X); N_word mask = BV_MASK_(X); boolean carry = true; if (size > 0) { while (size-- > 0) { *X = NOT *Y++; if (carry) { carry = (++(*X) == 0); } X++; } *(--X) &= mask; } } void BitVector_Absolute(wordptr X, wordptr Y) { N_word size = BV_SIZE_(Y); N_word mask = BV_MASK_(Y); if (size > 0) { if (*(Y+size-1) AND (mask AND NOT (mask >> 1))) BitVector_Negate(X,Y); else BitVector_Copy(X,Y); } } Z_int BitVector_Sign(wordptr addr) { N_word size = BV_SIZE_(addr); N_word mask = BV_MASK_(addr); wordptr last = addr + size - 1; boolean r = true; if (size > 0) { *last &= mask; while (r and (size-- > 0)) r = ( *addr++ == 0 ); } if (r) return((Z_int) 0); else { if (*last AND (mask AND NOT (mask >> 1))) return((Z_int) -1); else return((Z_int) 1); } } BV_ErrCode BitVector_Mul_Pos(wordptr X, wordptr Y, wordptr Z, boolean strict) { N_word mask; N_word limit; N_word count; Z_long last; wordptr sign; boolean carry; boolean overflow; boolean ok = true; /* Requirements: - X, Y and Z must be distinct - X and Y must have equal sizes (whereas Z may be any size!) - Z should always contain the SMALLER of the two factors Y and Z Constraints: - The contents of Y (and of X, of course) are destroyed (only Z is preserved!) */ if ((X == Y) or (X == Z) or (Y == Z)) return(BV_ErrCode_Same); if (BV_BITS_(X) != BV_BITS_(Y)) return(BV_ErrCode_Size); BitVector_Empty(X); if (BitVector_is_empty(Y)) return(BV_ErrCode_Ok); /* also if BV_BITS_(Y)==0 */ if ((last = Set_Max(Z)) < 0L) return(BV_ErrCode_Ok); limit = (N_word) last; sign = Y + BV_SIZE_(Y) - 1; mask = BV_MASK_(Y); *sign &= mask; mask &= NOT (mask >> 1); for ( count = 0; (ok and (count <= limit)); count++ ) { if ( BIT_VECTOR_TST_BIT(Z,count) ) { carry = false; overflow = BitVector_compute(X,X,Y,false,&carry); if (strict) ok = not (carry or overflow); else ok = not carry; } if (ok and (count < limit)) { carry = BitVector_shift_left(Y,0); if (strict) { overflow = ((*sign AND mask) != 0); ok = not (carry or overflow); } else ok = not carry; } } if (ok) return(BV_ErrCode_Ok); else return(BV_ErrCode_Ovfl); } BV_ErrCode BitVector_Multiply(wordptr X, wordptr Y, wordptr Z) { BV_ErrCode error = BV_ErrCode_Ok; N_word bit_x = BV_BITS_(X); N_word bit_y = BV_BITS_(Y); N_word bit_z = BV_BITS_(Z); N_word size; N_word mask; N_word msb; wordptr ptr_y; wordptr ptr_z; boolean sgn_x; boolean sgn_y; boolean sgn_z; boolean zero; wordptr A; wordptr B; /* Requirements: - Y and Z must have equal sizes - X must have at least the same size as Y and Z but may be larger (!) Features: - The contents of Y and Z are preserved - X may be identical with Y or Z (or both!) (in-place multiplication is possible!) */ if ((bit_y != bit_z) or (bit_x < bit_y)) return(BV_ErrCode_Size); if (BitVector_is_empty(Y) or BitVector_is_empty(Z)) { BitVector_Empty(X); } else { A = BitVector_Create(bit_y,false); if (A == NULL) return(BV_ErrCode_Null); B = BitVector_Create(bit_z,false); if (B == NULL) { BitVector_Destroy(A); return(BV_ErrCode_Null); } size = BV_SIZE_(Y); mask = BV_MASK_(Y); msb = (mask AND NOT (mask >> 1)); sgn_y = (((*(Y+size-1) &= mask) AND msb) != 0); sgn_z = (((*(Z+size-1) &= mask) AND msb) != 0); sgn_x = sgn_y XOR sgn_z; if (sgn_y) BitVector_Negate(A,Y); else BitVector_Copy(A,Y); if (sgn_z) BitVector_Negate(B,Z); else BitVector_Copy(B,Z); ptr_y = A + size; ptr_z = B + size; zero = true; while (zero and (size-- > 0)) { zero &= (*(--ptr_y) == 0); zero &= (*(--ptr_z) == 0); } if (*ptr_y > *ptr_z) { if (bit_x > bit_y) { A = BitVector_Resize(A,bit_x); if (A == NULL) { BitVector_Destroy(B); return(BV_ErrCode_Null); } } error = BitVector_Mul_Pos(X,A,B,true); } else { if (bit_x > bit_z) { B = BitVector_Resize(B,bit_x); if (B == NULL) { BitVector_Destroy(A); return(BV_ErrCode_Null); } } error = BitVector_Mul_Pos(X,B,A,true); } if ((not error) and sgn_x) BitVector_Negate(X,X); BitVector_Destroy(A); BitVector_Destroy(B); } return(error); } BV_ErrCode BitVector_Div_Pos(wordptr Q, wordptr X, wordptr Y, wordptr R) { N_word bits = BV_BITS_(Q); N_word mask; wordptr addr; Z_long last; boolean flag; boolean copy = false; /* flags whether valid rest is in R (0) or X (1) */ /* Requirements: - All bit vectors must have equal sizes - Q, X, Y and R must all be distinct bit vectors - Y must be non-zero (of course!) Constraints: - The contents of X (and Q and R, of course) are destroyed (only Y is preserved!) */ if ((bits != BV_BITS_(X)) or (bits != BV_BITS_(Y)) or (bits != BV_BITS_(R))) return(BV_ErrCode_Size); if ((Q == X) or (Q == Y) or (Q == R) or (X == Y) or (X == R) or (Y == R)) return(BV_ErrCode_Same); if (BitVector_is_empty(Y)) return(BV_ErrCode_Zero); BitVector_Empty(R); BitVector_Copy(Q,X); if ((last = Set_Max(Q)) < 0L) return(BV_ErrCode_Ok); bits = (N_word) ++last; while (bits-- > 0) { addr = Q + (bits >> BV_LogBits); mask = BV_BitMaskTab[bits AND BV_ModMask]; flag = ((*addr AND mask) != 0); if (copy) { BitVector_shift_left(X,flag); flag = false; BitVector_compute(R,X,Y,true,&flag); } else { BitVector_shift_left(R,flag); flag = false; BitVector_compute(X,R,Y,true,&flag); } if (flag) *addr &= NOT mask; else { *addr |= mask; copy = not copy; } } if (copy) BitVector_Copy(R,X); return(BV_ErrCode_Ok); } BV_ErrCode BitVector_Divide(wordptr Q, wordptr X, wordptr Y, wordptr R) { BV_ErrCode error = BV_ErrCode_Ok; N_word bits = BV_BITS_(Q); N_word size = BV_SIZE_(Q); N_word mask = BV_MASK_(Q); N_word msb = (mask AND NOT (mask >> 1)); boolean sgn_q; boolean sgn_x; boolean sgn_y; wordptr A; wordptr B; /* Requirements: - All bit vectors must have equal sizes - Q and R must be two distinct bit vectors - Y must be non-zero (of course!) Features: - The contents of X and Y are preserved - Q may be identical with X or Y (or both) (in-place division is possible!) - R may be identical with X or Y (or both) (but not identical with Q!) */ if ((bits != BV_BITS_(X)) or (bits != BV_BITS_(Y)) or (bits != BV_BITS_(R))) return(BV_ErrCode_Size); if (Q == R) return(BV_ErrCode_Same); if (BitVector_is_empty(Y)) return(BV_ErrCode_Zero); if (BitVector_is_empty(X)) { BitVector_Empty(Q); BitVector_Empty(R); } else { A = BitVector_Create(bits,false); if (A == NULL) return(BV_ErrCode_Null); B = BitVector_Create(bits,false); if (B == NULL) { BitVector_Destroy(A); return(BV_ErrCode_Null); } size--; sgn_x = (((*(X+size) &= mask) AND msb) != 0); sgn_y = (((*(Y+size) &= mask) AND msb) != 0); sgn_q = sgn_x XOR sgn_y; if (sgn_x) BitVector_Negate(A,X); else BitVector_Copy(A,X); if (sgn_y) BitVector_Negate(B,Y); else BitVector_Copy(B,Y); if (not (error = BitVector_Div_Pos(Q,A,B,R))) { if (sgn_q) BitVector_Negate(Q,Q); if (sgn_x) BitVector_Negate(R,R); } BitVector_Destroy(A); BitVector_Destroy(B); } return(error); } BV_ErrCode BitVector_GCD(wordptr X, wordptr Y, wordptr Z) { BV_ErrCode error = BV_ErrCode_Ok; N_word bits = BV_BITS_(X); N_word size = BV_SIZE_(X); N_word mask = BV_MASK_(X); N_word msb = (mask AND NOT (mask >> 1)); boolean sgn_a; boolean sgn_b; boolean sgn_r; wordptr Q; wordptr R; wordptr A; wordptr B; wordptr T; /* Requirements: - All bit vectors must have equal sizes Features: - The contents of Y and Z are preserved - X may be identical with Y or Z (or both) (in-place is possible!) - GCD(0,z) == GCD(z,0) == z - negative values are handled correctly */ if ((bits != BV_BITS_(Y)) or (bits != BV_BITS_(Z))) return(BV_ErrCode_Size); if (BitVector_is_empty(Y)) { if (X != Z) BitVector_Copy(X,Z); return(BV_ErrCode_Ok); } if (BitVector_is_empty(Z)) { if (X != Y) BitVector_Copy(X,Y); return(BV_ErrCode_Ok); } Q = BitVector_Create(bits,false); if (Q == NULL) { return(BV_ErrCode_Null); } R = BitVector_Create(bits,false); if (R == NULL) { BitVector_Destroy(Q); return(BV_ErrCode_Null); } A = BitVector_Create(bits,false); if (A == NULL) { BitVector_Destroy(Q); BitVector_Destroy(R); return(BV_ErrCode_Null); } B = BitVector_Create(bits,false); if (B == NULL) { BitVector_Destroy(Q); BitVector_Destroy(R); BitVector_Destroy(A); return(BV_ErrCode_Null); } size--; sgn_a = (((*(Y+size) &= mask) AND msb) != 0); sgn_b = (((*(Z+size) &= mask) AND msb) != 0); if (sgn_a) BitVector_Negate(A,Y); else BitVector_Copy(A,Y); if (sgn_b) BitVector_Negate(B,Z); else BitVector_Copy(B,Z); while (not error) { if (not (error = BitVector_Div_Pos(Q,A,B,R))) { if (BitVector_is_empty(R)) break; T = A; sgn_r = sgn_a; A = B; sgn_a = sgn_b; B = R; sgn_b = sgn_r; R = T; } } if (not error) { if (sgn_b) BitVector_Negate(X,B); else BitVector_Copy(X,B); } BitVector_Destroy(Q); BitVector_Destroy(R); BitVector_Destroy(A); BitVector_Destroy(B); return(error); } BV_ErrCode BitVector_GCD2(wordptr U, wordptr V, wordptr W, wordptr X, wordptr Y) { BV_ErrCode error = BV_ErrCode_Ok; N_word bits = BV_BITS_(U); N_word size = BV_SIZE_(U); N_word mask = BV_MASK_(U); N_word msb = (mask AND NOT (mask >> 1)); bv_listptr L; boolean minus; boolean carry; boolean sgn_q; boolean sgn_r; boolean sgn_a; boolean sgn_b; boolean sgn_x; boolean sgn_y; wordptr Q; wordptr R; wordptr A; wordptr B; wordptr T; wordptr X1; wordptr X2; wordptr X3; wordptr Y1; wordptr Y2; wordptr Y3; wordptr Z; /* Requirements: - All bit vectors must have equal sizes - U, V, and W must all be distinct bit vectors Features: - The contents of X and Y are preserved - U, V and W may be identical with X or Y (or both, provided that U, V and W are mutually distinct) (i.e., in-place is possible!) - GCD(0,z) == GCD(z,0) == z - negative values are handled correctly */ if ((bits != BV_BITS_(V)) or (bits != BV_BITS_(W)) or (bits != BV_BITS_(X)) or (bits != BV_BITS_(Y))) { return(BV_ErrCode_Size); } if ((U == V) or (U == W) or (V == W)) { return(BV_ErrCode_Same); } if ((bits == 0) or (size == 0)) { return(BV_ErrCode_Ok); } if (BitVector_is_empty(X)) { if (U != Y) BitVector_Copy(U,Y); BitVector_Empty(V); BitVector_Empty(W); if (BV_SIZE_(W)) *W = 1; return(BV_ErrCode_Ok); } if (BitVector_is_empty(Y)) { if (U != X) BitVector_Copy(U,X); BitVector_Empty(V); BitVector_Empty(W); if (BV_SIZE_(V)) *V = 1; return(BV_ErrCode_Ok); } if ((L = BitVector_Create_List(bits,false,11)) == NULL) { return(BV_ErrCode_Null); } Q = L[0]; R = L[1]; A = L[2]; B = L[3]; X1 = L[4]; X2 = L[5]; X3 = L[6]; Y1 = L[7]; Y2 = L[8]; Y3 = L[9]; Z = L[10]; size--; sgn_a = (((*(X+size) &= mask) AND msb) != 0); sgn_b = (((*(Y+size) &= mask) AND msb) != 0); if (sgn_a) BitVector_Negate(A,X); else BitVector_Copy(A,X); if (sgn_b) BitVector_Negate(B,Y); else BitVector_Copy(B,Y); BitVector_Empty(X1); BitVector_Empty(X2); *X1 = 1; BitVector_Empty(Y1); BitVector_Empty(Y2); *Y2 = 1; sgn_x = false; sgn_y = false; while (not error) { if ((error = BitVector_Div_Pos(Q,A,B,R))) { break; } if (BitVector_is_empty(R)) { break; } sgn_q = sgn_a XOR sgn_b; if (sgn_x) BitVector_Negate(Z,X2); else BitVector_Copy(Z,X2); if ((error = BitVector_Mul_Pos(X3,Z,Q,true))) { break; } minus = not (sgn_x XOR sgn_q); carry = 0; if (BitVector_compute(X3,X1,X3,minus,&carry)) { error = BV_ErrCode_Ovfl; break; } sgn_x = (((*(X3+size) &= mask) AND msb) != 0); if (sgn_y) BitVector_Negate(Z,Y2); else BitVector_Copy(Z,Y2); if ((error = BitVector_Mul_Pos(Y3,Z,Q,true))) { break; } minus = not (sgn_y XOR sgn_q); carry = 0; if (BitVector_compute(Y3,Y1,Y3,minus,&carry)) { error = BV_ErrCode_Ovfl; break; } sgn_y = (((*(Y3+size) &= mask) AND msb) != 0); T = A; sgn_r = sgn_a; A = B; sgn_a = sgn_b; B = R; sgn_b = sgn_r; R = T; T = X1; X1 = X2; X2 = X3; X3 = T; T = Y1; Y1 = Y2; Y2 = Y3; Y3 = T; } if (not error) { if (sgn_b) BitVector_Negate(U,B); else BitVector_Copy(U,B); BitVector_Copy(V,X2); BitVector_Copy(W,Y2); } BitVector_Destroy_List(L,11); return(error); } BV_ErrCode BitVector_Power(wordptr X, wordptr Y, wordptr Z) { BV_ErrCode error = BV_ErrCode_Ok; N_word bits = BV_BITS_(X); boolean first = true; Z_long last; N_word limit; N_word count; wordptr T; /* Requirements: - X must have at least the same size as Y but may be larger (!) - X may not be identical with Z - Z must be positive Features: - The contents of Y and Z are preserved */ if (X == Z) return(BV_ErrCode_Same); if (bits < BV_BITS_(Y)) return(BV_ErrCode_Size); if (BitVector_msb_(Z)) return(BV_ErrCode_Expo); if ((last = Set_Max(Z)) < 0L) { if (bits < 2) return(BV_ErrCode_Ovfl); BitVector_Empty(X); *X |= BV_LSB; return(BV_ErrCode_Ok); /* anything ^ 0 == 1 */ } if (BitVector_is_empty(Y)) { if (X != Y) BitVector_Empty(X); return(BV_ErrCode_Ok); /* 0 ^ anything not zero == 0 */ } T = BitVector_Create(bits,false); if (T == NULL) return(BV_ErrCode_Null); limit = (N_word) last; for ( count = 0; ((!error) and (count <= limit)); count++ ) { if ( BIT_VECTOR_TST_BIT(Z,count) ) { if (first) { first = false; if (count) { BitVector_Copy(X,T); } else { if (X != Y) BitVector_Copy(X,Y); } } else error = BitVector_Multiply(X,T,X); /* order important because T > X */ } if ((!error) and (count < limit)) { if (count) error = BitVector_Multiply(T,T,T); else error = BitVector_Multiply(T,Y,Y); } } BitVector_Destroy(T); return(error); } void BitVector_Block_Store(wordptr addr, charptr buffer, N_int length) { N_word size = BV_SIZE_(addr); N_word mask = BV_MASK_(addr); N_word value; N_word count; /* provide translation for independence of endian-ness: */ if (size > 0) { while (size-- > 0) { value = 0; for ( count = 0; (length > 0) and (count < BV_WordBits); count += 8 ) { value |= (((N_word) *buffer++) << count); length--; } *addr++ = value; } *(--addr) &= mask; } } charptr BitVector_Block_Read(wordptr addr, N_intptr length) { N_word size = BV_SIZE_(addr); N_word value; N_word count; charptr buffer; charptr target; /* provide translation for independence of endian-ness: */ *length = size << BV_Factor; buffer = (charptr) malloc((size_t) ((*length)+1)); if (buffer == NULL) return(NULL); target = buffer; if (size > 0) { *(addr+size-1) &= BV_MASK_(addr); while (size-- > 0) { value = *addr++; count = BV_WordBits >> 3; while (count-- > 0) { *target++ = (N_char) (value AND 0x00FF); if (count > 0) value >>= 8; } } } *target = (N_char) '\0'; return(buffer); } void BitVector_Word_Store(wordptr addr, N_int offset, N_int value) { N_word size = BV_SIZE_(addr); if (size > 0) { if (offset < size) *(addr+offset) = value; *(addr+size-1) &= BV_MASK_(addr); } } N_int BitVector_Word_Read(wordptr addr, N_int offset) { N_word size = BV_SIZE_(addr); if (size > 0) { *(addr+size-1) &= BV_MASK_(addr); if (offset < size) return( *(addr+offset) ); } return( (N_int) 0 ); } void BitVector_Word_Insert(wordptr addr, N_int offset, N_int count, boolean clear) { N_word size = BV_SIZE_(addr); N_word mask = BV_MASK_(addr); wordptr last = addr+size-1; if (size > 0) { *last &= mask; if (offset > size) offset = size; BIT_VECTOR_ins_words(addr+offset,size-offset,count,clear); *last &= mask; } } void BitVector_Word_Delete(wordptr addr, N_int offset, N_int count, boolean clear) { N_word size = BV_SIZE_(addr); N_word mask = BV_MASK_(addr); wordptr last = addr+size-1; if (size > 0) { *last &= mask; if (offset > size) offset = size; BIT_VECTOR_del_words(addr+offset,size-offset,count,clear); *last &= mask; } } void BitVector_Chunk_Store(wordptr addr, N_int chunksize, N_int offset, N_long value) { N_word bits = BV_BITS_(addr); N_word mask; N_word temp; if ((chunksize > 0) and (offset < bits)) { if (chunksize > BV_LongBits) chunksize = BV_LongBits; if ((offset + chunksize) > bits) chunksize = bits - offset; addr += offset >> BV_LogBits; offset &= BV_ModMask; while (chunksize > 0) { mask = (N_word) (~0L << offset); bits = offset + chunksize; if (bits < BV_WordBits) { mask &= (N_word) ~(~0L << bits); bits = chunksize; } else bits = BV_WordBits - offset; temp = (N_word) (value << offset); temp &= mask; *addr &= NOT mask; *addr++ |= temp; value >>= bits; chunksize -= bits; offset = 0; } } } N_long BitVector_Chunk_Read(wordptr addr, N_int chunksize, N_int offset) { N_word bits = BV_BITS_(addr); N_word chunkbits = 0; N_long value = 0L; N_long temp; N_word mask; if ((chunksize > 0) and (offset < bits)) { if (chunksize > BV_LongBits) chunksize = BV_LongBits; if ((offset + chunksize) > bits) chunksize = bits - offset; addr += offset >> BV_LogBits; offset &= BV_ModMask; while (chunksize > 0) { bits = offset + chunksize; if (bits < BV_WordBits) { mask = (N_word) ~(~0L << bits); bits = chunksize; } else { mask = (N_word) ~0L; bits = BV_WordBits - offset; } temp = (N_long) ((*addr++ AND mask) >> offset); value |= temp << chunkbits; chunkbits += bits; chunksize -= bits; offset = 0; } } return(value); } /*******************/ /* set operations: */ /*******************/ void Set_Union(wordptr X, wordptr Y, wordptr Z) /* X = Y + Z */ { N_word bits = BV_BITS_(X); N_word size = BV_SIZE_(X); N_word mask = BV_MASK_(X); if ((size > 0) and (bits == BV_BITS_(Y)) and (bits == BV_BITS_(Z))) { while (size-- > 0) *X++ = *Y++ OR *Z++; *(--X) &= mask; } } void Set_Intersection(wordptr X, wordptr Y, wordptr Z) /* X = Y * Z */ { N_word bits = BV_BITS_(X); N_word size = BV_SIZE_(X); N_word mask = BV_MASK_(X); if ((size > 0) and (bits == BV_BITS_(Y)) and (bits == BV_BITS_(Z))) { while (size-- > 0) *X++ = *Y++ AND *Z++; *(--X) &= mask; } } void Set_Difference(wordptr X, wordptr Y, wordptr Z) /* X = Y \ Z */ { N_word bits = BV_BITS_(X); N_word size = BV_SIZE_(X); N_word mask = BV_MASK_(X); if ((size > 0) and (bits == BV_BITS_(Y)) and (bits == BV_BITS_(Z))) { while (size-- > 0) *X++ = *Y++ AND NOT *Z++; *(--X) &= mask; } } void Set_ExclusiveOr(wordptr X, wordptr Y, wordptr Z) /* X=(Y+Z)\(Y*Z) */ { N_word bits = BV_BITS_(X); N_word size = BV_SIZE_(X); N_word mask = BV_MASK_(X); if ((size > 0) and (bits == BV_BITS_(Y)) and (bits == BV_BITS_(Z))) { while (size-- > 0) *X++ = *Y++ XOR *Z++; *(--X) &= mask; } } void Set_Complement(wordptr X, wordptr Y) /* X = ~Y */ { N_word size = BV_SIZE_(X); N_word mask = BV_MASK_(X); if ((size > 0) and (BV_BITS_(X) == BV_BITS_(Y))) { while (size-- > 0) *X++ = NOT *Y++; *(--X) &= mask; } } /******************/ /* set functions: */ /******************/ boolean Set_subset(wordptr X, wordptr Y) /* X subset Y ? */ { N_word size = BV_SIZE_(X); boolean r = false; if ((size > 0) and (BV_BITS_(X) == BV_BITS_(Y))) { r = true; while (r and (size-- > 0)) r = ((*X++ AND NOT *Y++) == 0); } return(r); } N_int Set_Norm(wordptr addr) /* = | X | */ { byteptr byte; N_word bytes; N_int n; byte = (byteptr) addr; bytes = BV_SIZE_(addr) << BV_Factor; n = 0; while (bytes-- > 0) { n += BV_ByteNorm[*byte++]; } return(n); } N_int Set_Norm2(wordptr addr) /* = | X | */ { N_word size = BV_SIZE_(addr); N_word w0,w1; N_int n,k; n = 0; while (size-- > 0) { k = 0; w1 = NOT (w0 = *addr++); while (w0 and w1) { w0 &= w0 - 1; w1 &= w1 - 1; k++; } if (w0 == 0) n += k; else n += BV_WordBits - k; } return(n); } N_int Set_Norm3(wordptr addr) /* = | X | */ { N_word size = BV_SIZE_(addr); N_int count = 0; N_word c; while (size-- > 0) { c = *addr++; while (c) { c &= c - 1; count++; } } return(count); } Z_long Set_Min(wordptr addr) /* = min(X) */ { boolean empty = true; N_word size = BV_SIZE_(addr); N_word i = 0; N_word c = 0; /* silence compiler warning */ while (empty and (size-- > 0)) { if ((c = *addr++)) empty = false; else i++; } if (empty) return((Z_long) LONG_MAX); /* plus infinity */ i <<= BV_LogBits; while (not (c AND BV_LSB)) { c >>= 1; i++; } return((Z_long) i); } Z_long Set_Max(wordptr addr) /* = max(X) */ { boolean empty = true; N_word size = BV_SIZE_(addr); N_word i = size; N_word c = 0; /* silence compiler warning */ addr += size-1; while (empty and (size-- > 0)) { if ((c = *addr--)) empty = false; else i--; } if (empty) return((Z_long) LONG_MIN); /* minus infinity */ i <<= BV_LogBits; while (not (c AND BV_MSB)) { c <<= 1; i--; } return((Z_long) --i); } /**********************************/ /* matrix-of-booleans operations: */ /**********************************/ void Matrix_Multiplication(wordptr X, N_int rowsX, N_int colsX, wordptr Y, N_int rowsY, N_int colsY, wordptr Z, N_int rowsZ, N_int colsZ) { N_word i; N_word j; N_word k; N_word indxX; N_word indxY; N_word indxZ; N_word termX; N_word termY; N_word sum; if ((colsY == rowsZ) and (rowsX == rowsY) and (colsX == colsZ) and (BV_BITS_(X) == rowsX*colsX) and (BV_BITS_(Y) == rowsY*colsY) and (BV_BITS_(Z) == rowsZ*colsZ)) { for ( i = 0; i < rowsY; i++ ) { termX = i * colsX; termY = i * colsY; for ( j = 0; j < colsZ; j++ ) { indxX = termX + j; sum = 0; for ( k = 0; k < colsY; k++ ) { indxY = termY + k; indxZ = k * colsZ + j; if ( BIT_VECTOR_TST_BIT(Y,indxY) && BIT_VECTOR_TST_BIT(Z,indxZ) ) sum ^= 1; } if (sum) BIT_VECTOR_SET_BIT(X,indxX) else BIT_VECTOR_CLR_BIT(X,indxX) } } } } void Matrix_Product(wordptr X, N_int rowsX, N_int colsX, wordptr Y, N_int rowsY, N_int colsY, wordptr Z, N_int rowsZ, N_int colsZ) { N_word i; N_word j; N_word k; N_word indxX; N_word indxY; N_word indxZ; N_word termX; N_word termY; N_word sum; if ((colsY == rowsZ) and (rowsX == rowsY) and (colsX == colsZ) and (BV_BITS_(X) == rowsX*colsX) and (BV_BITS_(Y) == rowsY*colsY) and (BV_BITS_(Z) == rowsZ*colsZ)) { for ( i = 0; i < rowsY; i++ ) { termX = i * colsX; termY = i * colsY; for ( j = 0; j < colsZ; j++ ) { indxX = termX + j; sum = 0; for ( k = 0; k < colsY; k++ ) { indxY = termY + k; indxZ = k * colsZ + j; if ( BIT_VECTOR_TST_BIT(Y,indxY) && BIT_VECTOR_TST_BIT(Z,indxZ) ) sum |= 1; } if (sum) BIT_VECTOR_SET_BIT(X,indxX) else BIT_VECTOR_CLR_BIT(X,indxX) } } } } void Matrix_Closure(wordptr addr, N_int rows, N_int cols) { N_word i; N_word j; N_word k; N_word ii; N_word ij; N_word ik; N_word kj; N_word termi; N_word termk; if ((rows == cols) and (BV_BITS_(addr) == rows*cols)) { for ( i = 0; i < rows; i++ ) { ii = i * cols + i; BIT_VECTOR_SET_BIT(addr,ii) } for ( k = 0; k < rows; k++ ) { termk = k * cols; for ( i = 0; i < rows; i++ ) { termi = i * cols; ik = termi + k; for ( j = 0; j < rows; j++ ) { ij = termi + j; kj = termk + j; if ( BIT_VECTOR_TST_BIT(addr,ik) && BIT_VECTOR_TST_BIT(addr,kj) ) BIT_VECTOR_SET_BIT(addr,ij) } } } } } void Matrix_Transpose(wordptr X, N_int rowsX, N_int colsX, wordptr Y, N_int rowsY, N_int colsY) { N_word i; N_word j; N_word ii; N_word ij; N_word ji; N_word addii; N_word addij; N_word addji; N_word bitii; N_word bitij; N_word bitji; N_word termi; N_word termj; boolean swap; /* BEWARE that "in-place" is ONLY possible if the matrix is quadratic!! */ if ((rowsX == colsY) and (colsX == rowsY) and (BV_BITS_(X) == rowsX*colsX) and (BV_BITS_(Y) == rowsY*colsY)) { if (rowsY == colsY) /* in-place is possible! */ { for ( i = 0; i < rowsY; i++ ) { termi = i * colsY; for ( j = 0; j < i; j++ ) { termj = j * colsX; ij = termi + j; ji = termj + i; addij = ij >> BV_LogBits; addji = ji >> BV_LogBits; bitij = BV_BitMaskTab[ij AND BV_ModMask]; bitji = BV_BitMaskTab[ji AND BV_ModMask]; swap = ((*(Y+addij) AND bitij) != 0); if ((*(Y+addji) AND bitji) != 0) *(X+addij) |= bitij; else *(X+addij) &= NOT bitij; if (swap) *(X+addji) |= bitji; else *(X+addji) &= NOT bitji; } ii = termi + i; addii = ii >> BV_LogBits; bitii = BV_BitMaskTab[ii AND BV_ModMask]; if ((*(Y+addii) AND bitii) != 0) *(X+addii) |= bitii; else *(X+addii) &= NOT bitii; } } else /* rowsX != colsX, in-place is NOT possible! */ { for ( i = 0; i < rowsY; i++ ) { termi = i * colsY; for ( j = 0; j < colsY; j++ ) { termj = j * colsX; ij = termi + j; ji = termj + i; addij = ij >> BV_LogBits; addji = ji >> BV_LogBits; bitij = BV_BitMaskTab[ij AND BV_ModMask]; bitji = BV_BitMaskTab[ji AND BV_ModMask]; if ((*(Y+addij) AND bitij) != 0) *(X+addji) |= bitji; else *(X+addji) &= NOT bitji; } } } } } /*****************************************************************************/ /* VERSION: 7.4 */ /*****************************************************************************/ /* VERSION HISTORY: */ /*****************************************************************************/ /* */ /* Version 7.4 03.09.13 No changes. */ /* Version 7.3 01.06.13 No changes. */ /* Version 7.2 17.05.12 No changes. */ /* Version 7.1 29.09.09 Added prefix "BV_" to all global identifiers. */ /* Version 7.0 22.08.09 Fixed bugs in "GCD2()" and "Boot()". */ /* Version 6.9 12.08.09 Removed an obsolete warning (memory leak). */ /* Version 6.8 10.08.09 Fixed hard-coded table size BV_MASKTABSIZE. */ /* Version 6.7 08.08.09 No changes. */ /* Version 6.6 27.07.09 Made it thread-safe and MacOS X compatible. */ /* Version 6.5 27.07.09 Added automatic support for module "Storable". */ /* Version 6.4 03.10.04 Added C++ comp. directives. Improved "Norm()". */ /* Version 6.3 28.09.02 Added "Create_List()" and "GCD2()". */ /* Version 6.2 15.09.02 Overhauled error handling. Fixed "GCD()". */ /* Version 6.1 08.10.01 Make VMS linker happy: _lsb,_msb => _lsb_,_msb_ */ /* Version 6.0 08.10.00 Corrected overflow handling. */ /* Version 5.8 14.07.00 Added "Power()". Changed "Copy()". */ /* Version 5.7 19.05.99 Quickened "Div_Pos()". Added "Product()". */ /* Version 5.6 02.11.98 Leading zeros eliminated in "to_Hex()". */ /* Version 5.5 21.09.98 Fixed bug of uninitialized "error" in Multiply. */ /* Version 5.4 07.09.98 Fixed bug of uninitialized "error" in Divide. */ /* Version 5.3 12.05.98 Improved Norm. Completed history. */ /* Version 5.2 31.03.98 Improved Norm. */ /* Version 5.1 09.03.98 No changes. */ /* Version 5.0 01.03.98 Major additions and rewrite. */ /* Version 4.2 16.07.97 Added is_empty, is_full. */ /* Version 4.1 30.06.97 Added word-ins/del, move-left/right, inc/dec. */ /* Version 4.0 23.04.97 Rewrite. Added bit shift and bool. matrix ops. */ /* Version 3.2 04.02.97 Added interval methods. */ /* Version 3.1 21.01.97 Fixed bug on 64 bit machines. */ /* Version 3.0 12.01.97 Added flip. */ /* Version 2.0 14.12.96 Efficiency and consistency improvements. */ /* Version 1.1 08.01.96 Added Resize and ExclusiveOr. */ /* Version 1.0 14.12.95 First version under UNIX (with Perl module). */ /* Version 0.9 01.11.93 First version of C library under MS-DOS. */ /* Version 0.1 ??.??.89 First version in Turbo Pascal under CP/M. */ /* */ /*****************************************************************************/ /* AUTHOR: */ /*****************************************************************************/ /* */ /* Steffen Beyer */ /* mailto:STBEY@cpan.org */ /* http://www.engelschall.com/u/sb/download/ */ /* */ /*****************************************************************************/ /* COPYRIGHT: */ /*****************************************************************************/ /* */ /* Copyright (c) 1995 - 2013 by Steffen Beyer. */ /* All rights reserved. */ /* */ /*****************************************************************************/ /* LICENSE: */ /*****************************************************************************/ /* */ /* This library is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU Library General Public */ /* License as published by the Free Software Foundation; either */ /* version 2 of the License, or (at your option) any later version. */ /* */ /* This library is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU */ /* Library General Public License for more details. */ /* */ /* You should have received a copy of the GNU Library General Public */ /* License along with this library; if not, write to the */ /* Free Software Foundation, Inc., */ /* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* */ /* or download a copy from ftp://ftp.gnu.org/pub/gnu/COPYING.LIB-2.0 */ /* */ /*****************************************************************************/ #endif Bit-Vector-7.4/examples/SetObject.pl000755 100660 100660 00000010162 12211373040 016445 0ustar00sbsb000000 000000 #!perl ############################################################################### ## ## ## Copyright (c) 2000 - 2013 by Steffen Beyer. ## ## All rights reserved. ## ## ## ## This program is free software; you can redistribute it ## ## and/or modify it under the same terms as Perl itself. ## ## ## ############################################################################### ###################################################################### # # # How to emulate the Set::Object module using Bit::Vector (example): # # # ###################################################################### package InheritMe; use strict; use vars qw( @ISA @EXPORT @EXPORT_OK %EXPORT_TAGS $VERSION ); require Exporter; @ISA = qw(Exporter); @EXPORT = qw(); @EXPORT_OK = qw( RegisterMe ID2Obj Obj2ID Registered ); %EXPORT_TAGS = (all => [@EXPORT_OK]); $VERSION = 1.0; my $ID = 0; my(%id2obj) = (); my(%obj2id) = (); sub RegisterMe { my($self) = @_; if (exists $obj2id{$self}) { warn "Object '$self' has already been registered!\n"; return $obj2id{$self}; } else { $id2obj{$ID} = $self; $obj2id{$self} = $ID; return $ID++; } } sub ID2Obj { my($self,$id) = @_; return exists($id2obj{$id}) ? $id2obj{$id} : undef; } sub Obj2ID { my($self) = @_; return exists($obj2id{$self}) ? $obj2id{$self} : undef; } sub Registered { return $ID; } package main; use strict; use Date::Calc::Object; use Bit::Vector::Overload; push( @Date::Calc::ISA, 'InheritMe' ); # (make Date::Calc a subclass) InheritMe->import(':all'); # (as a convenience for dealing with non-objects) Date::Calc->date_format(2); my $today = Date::Calc->today(); my $yesterday = $today - 1; my $tomorrow = $today + 1; print "\nDates:\n"; print "'$yesterday' has got ID #", $yesterday->RegisterMe(), "\n"; print "'$today' has got ID #", $today->RegisterMe(), "\n"; print "'$tomorrow' has got ID #", $tomorrow->RegisterMe(), "\n"; my $pears = 50; my $apples = 1; my $oranges = 'out of stock'; print "\nFruit:\n"; print "\$pears ('$pears') has got ID #", RegisterMe(\$pears), "\n"; print "\$apples ('$apples') has got ID #", RegisterMe(\$apples), "\n"; print "\$oranges ('$oranges') has got ID #", RegisterMe(\$oranges), "\n"; my $set1 = Bit::Vector->new(&Registered); my $set2 = Bit::Vector->new(&Registered); $set1->Bit_On( $today->Obj2ID() ); $set1->Bit_On( Obj2ID(\$pears) ); $set1->Bit_On( Obj2ID(\$apples) ); $set1->Bit_On( Obj2ID(\$oranges) ); $set2->Bit_On( $yesterday->Obj2ID() ); $set2->Bit_On( $today->Obj2ID() ); $set2->Bit_On( $tomorrow->Obj2ID() ); $set2->Bit_On( Obj2ID(\$oranges) ); print "\nSet #1:\n"; print "<", join ( '> <', map ( ref($_) =~ /^[A-Z]+$/ ? "${$_}" : "$_", map ( InheritMe->ID2Obj($_), $set1->Index_List_Read() ) ) ), ">\n"; print "\nSet #2:\n"; print "<", join ( '> <', map ( ref($_) =~ /^[A-Z]+$/ ? "${$_}" : "$_", map ( InheritMe->ID2Obj($_), $set2->Index_List_Read() ) ) ), ">\n"; my $intersection = $set1 & $set2; print "\nIntersection:\n"; print "<", join ( '> <', map ( ref($_) =~ /^[A-Z]+$/ ? "${$_}" : "$_", map ( InheritMe->ID2Obj($_), $intersection->Index_List_Read() ) ) ), ">\n"; __END__ Bit-Vector-7.4/examples/test.c000644 100660 100660 00000007763 12211373040 015363 0ustar00sbsb000000 000000 /*****************************************************************************/ /* */ /* Copyright (c) 2002 - 2013 by Steffen Beyer. */ /* All rights reserved. */ /* */ /* This program is free software; you can redistribute it */ /* and/or modify it under the same terms as Perl itself. */ /* */ /*****************************************************************************/ /******************************************************/ /* */ /* Example for using the BitVector.c library from C */ /* */ /* (Just for playing around; also shows how one can */ /* deal with error handling) */ /* */ /* Copy ToolBox.h, BitVector.h and BitVector.o to */ /* this directory, then compile this file and link */ /* with BitVector.o, e.g. with */ /* */ /* gcc -o test test.c BitVector.o */ /* */ /******************************************************/ #include #include "ToolBox.h" #include "BitVector.h" void ListErrCode(ErrCode code) { if (code) fprintf(stdout, "BitVector ErrCode %2d: %s\n", code, BitVector_Error(code)); } void PrintErrorMessage(ErrCode code, char *name) { if (code) fprintf(stdout, "Bit::Vector::%s(): %s\n", name, BitVector_Error(code)); } #define FATAL_ERROR(name,code) \ { fprintf(stderr, "Bit::Vector::" name "(): %s\n", BitVector_Error(code)); exit(code); } int main(void) { N_int bits = 5; // N_char x[] = "001010"; /* 10 */ N_char x[] = "001x10"; /* 10 */ // N_char y[] = "000100"; /* 4 */ // N_char y[] = "000111"; /* 7 */ N_char y[] = "001111"; /* 63 */ wordptr X; wordptr Y; wordptr Z; ErrCode err; boolean ovrflw; boolean carry = false; ListErrCode( 0); ListErrCode( 1); ListErrCode( 2); ListErrCode( 3); ListErrCode( 4); ListErrCode( 5); ListErrCode( 6); ListErrCode( 7); ListErrCode( 8); ListErrCode( 9); ListErrCode(10); ListErrCode(11); ListErrCode(12); ListErrCode(13); ListErrCode(14); ListErrCode(15); ListErrCode(16); ListErrCode(17); ListErrCode(18); ListErrCode(19); ListErrCode(20); err = BitVector_Boot(); if (err) FATAL_ERROR("Boot", err); printf("Number of bits in a WORD: %d\n", BitVector_Word_Bits()); printf("Number of bits in a LONG: %d\n", BitVector_Long_Bits()); X = BitVector_Create(bits, 1); if (X == NULL) FATAL_ERROR("Create", ErrCode_Null); err = BitVector_from_Bin(X, x); PrintErrorMessage(err,"from_Bin"); Y = BitVector_Create(bits, 1); if (Y == NULL) FATAL_ERROR("Create", ErrCode_Null); err = BitVector_from_Bin(Y, y); PrintErrorMessage(err,"from_Bin"); Z = BitVector_Create(bits, 1); if (Z == NULL) FATAL_ERROR("Create", ErrCode_Null); ovrflw = BitVector_add(Z, X, Y, &carry); printf("result of %s + %s is %s (carry = %d, overflow = %d)\n", BitVector_to_Dec(X), /* Beware of the memory leaks here! */ BitVector_to_Dec(Y), /* Should call "BitVector_Dispose()" */ BitVector_to_Dec(Z), /* on these strings after use! */ carry, ovrflw); err = BitVector_Multiply(Z, X, Y); printf("result of %s * %s is %s\n", BitVector_to_Dec(X), /* Beware of the memory leaks here! */ BitVector_to_Dec(Y), /* Should call "BitVector_Dispose()" */ BitVector_to_Dec(Z)); /* on these strings after use! */ PrintErrorMessage(err,"Multiply"); return(0); } Bit-Vector-7.4/examples/primes.pl000755 100660 100660 00000005077 12211373040 016073 0ustar00sbsb000000 000000 #!perl -w ############################################################################### ## ## ## Copyright (c) 1995 - 2013 by Steffen Beyer. ## ## All rights reserved. ## ## ## ## This program is free software; you can redistribute it ## ## and/or modify it under the same terms as Perl itself. ## ## ## ############################################################################### use strict; use vars qw($limit $set $start $stop $min $max $norm $i $j); use Bit::Vector; print "\n***** Calculating Prime Numbers - The Sieve Of Erathostenes *****\n"; $limit = 0; if (-t STDIN) { while ($limit < 16) { print "\nPlease enter an upper limit (>15): "; $limit = ; if ($limit =~ /^\s*(\d+)\s*$/) { $limit = $1; } else { $limit = 0; } } print "\n"; } else { $limit = 100; print "\nRunning in batch mode - using $limit as upper limit.\n\n"; } $set = Bit::Vector->new($limit+1); print "Calculating the prime numbers in the range [2..$limit]...\n\n"; $start = time; $set->Primes(); ## Alternative (slower!): #$set->Fill(); #$set->Bit_Off(0); #$set->Bit_Off(1); #for ( $j = 4; $j <= $limit; $j += 2 ) { $set->Bit_Off($j); } #for ( $i = 3; ($j = $i * $i) <= $limit; $i += 2 ) #{ # for ( ; $j <= $limit; $j += $i ) { $set->Bit_Off($j); } #} $stop = time; &print_elapsed_time; $min = $set->Min(); $max = $set->Max(); $norm = $set->Norm(); print "Found $norm prime numbers in the range [2..$limit]:\n\n"; for ( $i = $min, $j = 0; $i <= $max; $i++ ) { if ($set->contains($i)) { print "prime number #", ++$j, " = $i\n"; } } print "\n"; exit; sub print_elapsed_time { my($flag) = 0; my($sec,$min,$hour,$year,$yday) = (gmtime($stop - $start))[0,1,2,5,7]; $year -= 70; print "Elapsed time: "; if ($year > 0) { printf("%d year%s ", $year, ($year!=1)?"s":""); $flag = 1; } if (($yday > 0) || $flag) { printf("%d day%s ", $yday, ($yday!=1)?"s":""); $flag = 1; } if (($hour > 0) || $flag) { printf("%d hour%s ", $hour, ($hour!=1)?"s":""); $flag = 1; } if (($min > 0) || $flag) { printf("%d minute%s ", $min, ($min!=1)?"s":""); } printf("%d second%s.\n\n", $sec, ($sec!=1)?"s":""); } __END__ Bit-Vector-7.4/examples/benchmk1.pl000755 100660 100660 00000000723 12211373040 016255 0ustar00sbsb000000 000000 #!/usr/local/bin/perl use Benchmark; sub init { delete $INC{'Carp.pm'}; delete $INC{'Exporter.pm'}; delete $INC{'overload.pm'}; delete $INC{'Bit/Vector/Overload.pm'}; delete $INC{'Bit/Vector.pm'}; delete $INC{'DynaLoader.pm'}; } sub plain { init(); require Bit::Vector; } sub ovrld { init(); require Bit::Vector::Overload; } timethese ( 100, { plain => \&plain, ovrld => \&ovrld } ); __END__ Bit-Vector-7.4/examples/benchmk2.pl000755 100660 100660 00000001230 12211373040 016250 0ustar00sbsb000000 000000 #!perl use Benchmark; use Bit::Vector::String; $v = Bit::Vector->new(1024); $v->Primes(); $s = ''; $b = $v->to_Bin(); $o = $v->to_Oct(); $h = $v->to_Hex(); sub to_Bin { $s = $v->to_Bin(); } sub to_Oct { $s = $v->to_Oct(); } sub to_Hex { $s = $v->to_Hex(); } sub from_Bin { $v->from_Bin($b); } sub from_Oct { $v->from_Oct($o); } sub from_Hex { $v->from_Hex($h); } timethese ( 10000, { to_Bin => \&to_Bin, to_Oct => \&to_Oct, to_Hex => \&to_Hex } ); timethese ( 10000, { from_Bin => \&from_Bin, from_Oct => \&from_Oct, from_Hex => \&from_Hex } ); __END__ Bit-Vector-7.4/examples/benchmk3.pl000755 100660 100660 00000002032 12211373040 016252 0ustar00sbsb000000 000000 #!perl -w package Bit::Vector; use strict; sub Pattern_Fill { my($vector,$pattern,$length) = @_; my($size,$factor); $size = $vector->Size(); $factor = int($size / $length); if ($size % $length) { $factor++; } $vector->Chunk_List_Store($length, ($pattern) x $factor); return $vector; } package main; use strict; use Bit::Vector; use Benchmark; my($i,$n); my $b = 1024; my(@v) = Bit::Vector->new($b,8); $v[1]->Pattern_Fill(0x01,5); $v[2]->Pattern_Fill(0x01,3); $v[3]->Pattern_Fill(0x01,2); $v[4]->Pattern_Fill(0x03,3); $v[5]->Pattern_Fill(0x07,4); $v[6]->Pattern_Fill(0x0F,5); $v[7]->Fill(); for ( $i = 0; $i < 8; $i++ ) { $n = $v[$i]->to_Bin(); print "\nTiming vector #$i:\n$n\n\n"; timethese ( 500000, { 'Norm1' => sub { $n = $v[$i]->Norm(); }, 'Norm2' => sub { $n = $v[$i]->Norm2(); }, 'Norm3' => sub { $n = $v[$i]->Norm3(); } } ); print "<<< n = $n, b = $b, ", ( int( ($n / $b) * 1000 + 0.5 ) / 10 ), "% >>>\n"; } __END__ Bit-Vector-7.4/t/03__operations.t000644 100660 100660 00000035275 12211373040 015675 0ustar00sbsb000000 000000 #!perl -w use strict; no strict "vars"; use Bit::Vector; # ====================================================================== # $set->Flip(); # $set->Fill(); # $set->Empty(); # $set->is_empty(); # $set->is_full(); # $set1->equal($set2); # $set1->subset($set2); # $set1->Union($set2,$set3); # $set1->Intersection($set2,$set3); # $set1->Difference($set2,$set3); # $set1->ExclusiveOr($set2,$set3); # $set1->Complement($set2); # $set1->Copy($set2); # ====================================================================== print "1..232\n"; $n = 1; $limit = 999; # must be odd! $set0 = new Bit::Vector($limit+1); $set1 = new Bit::Vector($limit+1); $set2 = new Bit::Vector($limit+1); $set3 = new Bit::Vector($limit+1); $set4 = new Bit::Vector($limit+1); $set3->Fill(); for ( $i = 0; $i <= $limit; $i += 2 ) { $set1->Bit_On($i); } $set2->Copy($set1); $set2->Flip(); &test; $set1->Fill(); $set1->Bit_Off(0); $set1->Bit_Off(1); for ( $j = 4; $j <= $limit; $j += 2 ) { $set1->Bit_Off($j); } for ( $i = 3; ($j = $i * $i) <= $limit; $i += 2 ) { for ( ; $j <= $limit; $j += $i ) { $set1->Bit_Off($j); } } $set2->Copy($set1); $set2->Flip(); &test; exit; sub test { # equal if ($set0->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (! $set0->equal($set1)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (! $set0->equal($set2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (! $set0->equal($set3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (! $set1->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set1->equal($set1)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (! $set1->equal($set2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (! $set1->equal($set3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (! $set2->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (! $set2->equal($set1)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set2->equal($set2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (! $set2->equal($set3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (! $set3->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (! $set3->equal($set1)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (! $set3->equal($set2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set3->equal($set3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # subset if ($set0->subset($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set0->subset($set1)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set0->subset($set2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set0->subset($set3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (! $set1->subset($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set1->subset($set1)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (! $set1->subset($set2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set1->subset($set3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (! $set2->subset($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (! $set2->subset($set1)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set2->subset($set2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set2->subset($set3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (! $set3->subset($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (! $set3->subset($set1)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (! $set3->subset($set2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set3->subset($set3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # Union $set4->Union($set0,$set0); if ($set4->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Union($set0,$set1); if ($set4->equal($set1)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Union($set0,$set2); if ($set4->equal($set2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Union($set0,$set3); if ($set4->equal($set3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Union($set1,$set0); if ($set4->equal($set1)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Union($set1,$set1); if ($set4->equal($set1)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Union($set1,$set2); if ($set4->equal($set3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Union($set1,$set3); if ($set4->equal($set3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Union($set2,$set0); if ($set4->equal($set2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Union($set2,$set1); if ($set4->equal($set3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Union($set2,$set2); if ($set4->equal($set2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Union($set2,$set3); if ($set4->equal($set3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Union($set3,$set0); if ($set4->equal($set3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Union($set3,$set1); if ($set4->equal($set3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Union($set3,$set2); if ($set4->equal($set3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Union($set3,$set3); if ($set4->equal($set3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # Intersection $set4->Intersection($set0,$set0); if ($set4->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Intersection($set0,$set1); if ($set4->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Intersection($set0,$set2); if ($set4->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Intersection($set0,$set3); if ($set4->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Intersection($set1,$set0); if ($set4->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Intersection($set1,$set1); if ($set4->equal($set1)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Intersection($set1,$set2); if ($set4->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Intersection($set1,$set3); if ($set4->equal($set1)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Intersection($set2,$set0); if ($set4->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Intersection($set2,$set1); if ($set4->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Intersection($set2,$set2); if ($set4->equal($set2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Intersection($set2,$set3); if ($set4->equal($set2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Intersection($set3,$set0); if ($set4->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Intersection($set3,$set1); if ($set4->equal($set1)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Intersection($set3,$set2); if ($set4->equal($set2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Intersection($set3,$set3); if ($set4->equal($set3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # Difference $set4->Difference($set0,$set0); if ($set4->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Difference($set0,$set1); if ($set4->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Difference($set0,$set2); if ($set4->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Difference($set0,$set3); if ($set4->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Difference($set1,$set0); if ($set4->equal($set1)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Difference($set1,$set1); if ($set4->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Difference($set1,$set2); if ($set4->equal($set1)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Difference($set1,$set3); if ($set4->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Difference($set2,$set0); if ($set4->equal($set2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Difference($set2,$set1); if ($set4->equal($set2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Difference($set2,$set2); if ($set4->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Difference($set2,$set3); if ($set4->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Difference($set3,$set0); if ($set4->equal($set3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Difference($set3,$set1); if ($set4->equal($set2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Difference($set3,$set2); if ($set4->equal($set1)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Difference($set3,$set3); if ($set4->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # ExclusiveOr $set4->ExclusiveOr($set0,$set0); if ($set4->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->ExclusiveOr($set0,$set1); if ($set4->equal($set1)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->ExclusiveOr($set0,$set2); if ($set4->equal($set2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->ExclusiveOr($set0,$set3); if ($set4->equal($set3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->ExclusiveOr($set1,$set0); if ($set4->equal($set1)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->ExclusiveOr($set1,$set1); if ($set4->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->ExclusiveOr($set1,$set2); if ($set4->equal($set3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->ExclusiveOr($set1,$set3); if ($set4->equal($set2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->ExclusiveOr($set2,$set0); if ($set4->equal($set2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->ExclusiveOr($set2,$set1); if ($set4->equal($set3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->ExclusiveOr($set2,$set2); if ($set4->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->ExclusiveOr($set2,$set3); if ($set4->equal($set1)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->ExclusiveOr($set3,$set0); if ($set4->equal($set3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->ExclusiveOr($set3,$set1); if ($set4->equal($set2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->ExclusiveOr($set3,$set2); if ($set4->equal($set1)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->ExclusiveOr($set3,$set3); if ($set4->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # Complement $set4->Complement($set0); if ($set4->equal($set3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Complement($set1); if ($set4->equal($set2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Complement($set2); if ($set4->equal($set1)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Complement($set3); if ($set4->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # Copy $set4->Copy($set0); if ($set4->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Copy($set1); if ($set4->equal($set1)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Copy($set2); if ($set4->equal($set2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Copy($set3); if ($set4->equal($set3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # in-place: $set4->Copy($set1); $set4->Union($set2,$set4); if ($set4->equal($set3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Copy($set2); $set4->Union($set4,$set1); if ($set4->equal($set3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Copy($set3); $set4->Intersection($set1,$set4); if ($set4->equal($set1)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Copy($set3); $set4->Intersection($set4,$set2); if ($set4->equal($set2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Copy($set3); $set4->Difference($set4,$set2); if ($set4->equal($set1)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Copy($set3); $set4->Difference($set2,$set4); if ($set4->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Copy($set1); $set4->ExclusiveOr($set4,$set3); if ($set4->equal($set2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Copy($set2); $set4->ExclusiveOr($set1,$set4); if ($set4->equal($set3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Copy($set1); $set4->Complement($set4); if ($set4->equal($set2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Copy($set3); $set4->Complement($set4); if ($set4->equal($set0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Copy($set1); $set4->Copy($set4); if ($set4->equal($set1)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set4->Copy($set2); $set4->Copy($set4); if ($set4->equal($set2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } __END__ Bit-Vector-7.4/t/04___functions.t000644 100660 100660 00000004713 12211373040 015653 0ustar00sbsb000000 000000 #!perl -w use strict; no strict "vars"; use Bit::Vector; # ====================================================================== # $set->Norm(); # $set->Min(); # $set->Max(); # ====================================================================== print "1..21\n"; $lim = 997; $set = new Bit::Vector($lim); $norm = $set->Norm(); $min = $set->Min(); $max = $set->Max(); $n = 1; if ($norm == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($min > $lim) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($max < -$lim) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set->Fill(); $norm = $set->Norm(); $min = $set->Min(); $max = $set->Max(); if ($norm == $lim) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($min == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($max == $lim-1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set->Empty(); $set->Bit_On(0); $set->Bit_On($lim-1); $norm = $set->Norm(); $min = $set->Min(); $max = $set->Max(); if ($norm == 2) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($min == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($max == $lim-1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set->Empty(); $set->Bit_On(0); $norm = $set->Norm(); $min = $set->Min(); $max = $set->Max(); if ($norm == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($min == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($max == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set->Empty(); $set->Bit_On($lim-1); $norm = $set->Norm(); $min = $set->Min(); $max = $set->Max(); if ($norm == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($min == $lim-1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($max == $lim-1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set->Empty(); $set->Bit_On(1); $set->Bit_On($lim-2); $norm = $set->Norm(); $min = $set->Min(); $max = $set->Max(); if ($norm == 2) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($min == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($max == $lim-2) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set->Empty(); $set->Bit_On(int($lim/2)); $norm = $set->Norm(); $min = $set->Min(); $max = $set->Max(); if ($norm == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($min == int($lim/2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($max == int($lim/2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; __END__ Bit-Vector-7.4/t/16____subtract.t000644 100660 100660 00000012525 12211373040 015634 0ustar00sbsb000000 000000 #!perl -w use strict; no strict "vars"; use Bit::Vector; # ====================================================================== # $carry_out = $vector1->subtract($vector2,$vector3,$carry_in); # ====================================================================== print "1..1001\n"; $n = 1; $result0{'FE'}{'FE'} = '00'; $carry0{'FE'}{'FE'} = 0; $result0{'FE'}{'FF'} = 'FF'; $carry0{'FE'}{'FF'} = 1; $result0{'FE'}{'00'} = 'FE'; $carry0{'FE'}{'00'} = 0; $result0{'FE'}{'01'} = 'FD'; $carry0{'FE'}{'01'} = 0; $result0{'FE'}{'02'} = 'FC'; $carry0{'FE'}{'02'} = 0; $result0{'FF'}{'FE'} = '01'; $carry0{'FF'}{'FE'} = 0; $result0{'FF'}{'FF'} = '00'; $carry0{'FF'}{'FF'} = 0; $result0{'FF'}{'00'} = 'FF'; $carry0{'FF'}{'00'} = 0; $result0{'FF'}{'01'} = 'FE'; $carry0{'FF'}{'01'} = 0; $result0{'FF'}{'02'} = 'FD'; $carry0{'FF'}{'02'} = 0; $result0{'00'}{'FE'} = '02'; $carry0{'00'}{'FE'} = 1; $result0{'00'}{'FF'} = '01'; $carry0{'00'}{'FF'} = 1; $result0{'00'}{'00'} = '00'; $carry0{'00'}{'00'} = 0; $result0{'00'}{'01'} = 'FF'; $carry0{'00'}{'01'} = 1; $result0{'00'}{'02'} = 'FE'; $carry0{'00'}{'02'} = 1; $result0{'01'}{'FE'} = '03'; $carry0{'01'}{'FE'} = 1; $result0{'01'}{'FF'} = '02'; $carry0{'01'}{'FF'} = 1; $result0{'01'}{'00'} = '01'; $carry0{'01'}{'00'} = 0; $result0{'01'}{'01'} = '00'; $carry0{'01'}{'01'} = 0; $result0{'01'}{'02'} = 'FF'; $carry0{'01'}{'02'} = 1; $result0{'02'}{'FE'} = '04'; $carry0{'02'}{'FE'} = 1; $result0{'02'}{'FF'} = '03'; $carry0{'02'}{'FF'} = 1; $result0{'02'}{'00'} = '02'; $carry0{'02'}{'00'} = 0; $result0{'02'}{'01'} = '01'; $carry0{'02'}{'01'} = 0; $result0{'02'}{'02'} = '00'; $carry0{'02'}{'02'} = 0; $result1{'FE'}{'FE'} = 'FF'; $carry1{'FE'}{'FE'} = 1; $result1{'FE'}{'FF'} = 'FE'; $carry1{'FE'}{'FF'} = 1; $result1{'FE'}{'00'} = 'FD'; $carry1{'FE'}{'00'} = 0; $result1{'FE'}{'01'} = 'FC'; $carry1{'FE'}{'01'} = 0; $result1{'FE'}{'02'} = 'FB'; $carry1{'FE'}{'02'} = 0; $result1{'FF'}{'FE'} = '00'; $carry1{'FF'}{'FE'} = 0; $result1{'FF'}{'FF'} = 'FF'; $carry1{'FF'}{'FF'} = 1; $result1{'FF'}{'00'} = 'FE'; $carry1{'FF'}{'00'} = 0; $result1{'FF'}{'01'} = 'FD'; $carry1{'FF'}{'01'} = 0; $result1{'FF'}{'02'} = 'FC'; $carry1{'FF'}{'02'} = 0; $result1{'00'}{'FE'} = '01'; $carry1{'00'}{'FE'} = 1; $result1{'00'}{'FF'} = '00'; $carry1{'00'}{'FF'} = 1; $result1{'00'}{'00'} = 'FF'; $carry1{'00'}{'00'} = 1; $result1{'00'}{'01'} = 'FE'; $carry1{'00'}{'01'} = 1; $result1{'00'}{'02'} = 'FD'; $carry1{'00'}{'02'} = 1; $result1{'01'}{'FE'} = '02'; $carry1{'01'}{'FE'} = 1; $result1{'01'}{'FF'} = '01'; $carry1{'01'}{'FF'} = 1; $result1{'01'}{'00'} = '00'; $carry1{'01'}{'00'} = 0; $result1{'01'}{'01'} = 'FF'; $carry1{'01'}{'01'} = 1; $result1{'01'}{'02'} = 'FE'; $carry1{'01'}{'02'} = 1; $result1{'02'}{'FE'} = '03'; $carry1{'02'}{'FE'} = 1; $result1{'02'}{'FF'} = '02'; $carry1{'02'}{'FF'} = 1; $result1{'02'}{'00'} = '01'; $carry1{'02'}{'00'} = 0; $result1{'02'}{'01'} = '00'; $carry1{'02'}{'01'} = 0; $result1{'02'}{'02'} = 'FF'; $carry1{'02'}{'02'} = 1; foreach $bits (31, 32, 33, 63, 64, 65, 127, 128, 129, 997) { $vec0 = Bit::Vector->new($bits); $vec1 = Bit::Vector->new($bits); $vec2 = Bit::Vector->new($bits); $vec3 = Bit::Vector->new($bits); foreach $arg1 (sort hexadecimal (keys %result0)) { foreach $arg2 (sort hexadecimal (keys %{$result0{$arg1}})) { # print "subtract '$arg1' - '$arg2'\n"; $vec1->from_Hex(convert($arg1)); $vec2->from_Hex(convert($arg2)); $vec3->from_Hex(convert($result0{$arg1}{$arg2})); $carry3 = $carry0{$arg1}{$arg2}; $carry0 = $vec0->subtract($vec1,$vec2,0); # print "Result: '", $vec0->to_Hex(), "' $carry0\n"; # print "Should be: '", $vec3->to_Hex(), "' $carry3\n"; if ($vec0->equal($vec3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($carry0 == $carry3) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } } foreach $arg1 (sort hexadecimal (keys %result0)) { foreach $arg2 (sort hexadecimal (keys %{$result0{$arg1}})) { # print "subtract '$arg1' - '$arg2' - 1\n"; $vec1->from_Hex(convert($arg1)); $vec2->from_Hex(convert($arg2)); $vec3->from_Hex(convert($result1{$arg1}{$arg2})); $carry3 = $carry1{$arg1}{$arg2}; $carry0 = $vec0->subtract($vec1,$vec2,1); # print "Result: '", $vec0->to_Hex(), "' $carry0\n"; # print "Should be: '", $vec3->to_Hex(), "' $carry3\n"; if ($vec0->equal($vec3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($carry0 == $carry3) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } } } $vec = Bit::Vector->new(1024); $vec->subtract($vec,$vec,5); if ($vec->is_full()) {print "ok $n\n";} else {print "not ok $n\n";} $n++; exit; sub hexadecimal { my($x,$y) = (hex($a),hex($b)); if ($x > 127) { $x -= 256; } if ($y > 127) { $y -= 256; } return( $x <=> $y ); } sub convert { my($hex) = shift; my($dec) = hex($hex); my($len); $len = int($bits / 4); if ($len * 4 < $bits) { $len++; } $len -= 2; if ($dec > 127) { return( ('F' x $len) . $hex ); } else { return( ('0' x $len) . $hex ); } } __END__ Bit-Vector-7.4/t/05______primes.t000644 100660 100660 00000010726 12211373040 015601 0ustar00sbsb000000 000000 #!perl -w use strict; no strict "vars"; use Bit::Vector; # ====================================================================== # $set = new Bit::Vector($elements); # $set->Fill(); # $set->Empty(); # $set->Primes(); # $set->Bit_Off($i); # $set->Bit_On($i); # $set->bit_flip($i); # $set->contains($i); # $set->Norm(); # $set1->equal($set2); # ====================================================================== $limit = 1000; print "1..", ($limit+4)*2, "\n"; @prime = (0) x ($limit+1); $prime[2] = 1; $prime[3] = 1; $prime[5] = 1; $prime[7] = 1; $prime[11] = 1; $prime[13] = 1; $prime[17] = 1; $prime[19] = 1; $prime[23] = 1; $prime[29] = 1; $prime[31] = 1; $prime[37] = 1; $prime[41] = 1; $prime[43] = 1; $prime[47] = 1; $prime[53] = 1; $prime[59] = 1; $prime[61] = 1; $prime[67] = 1; $prime[71] = 1; $prime[73] = 1; $prime[79] = 1; $prime[83] = 1; $prime[89] = 1; $prime[97] = 1; $prime[101] = 1; $prime[103] = 1; $prime[107] = 1; $prime[109] = 1; $prime[113] = 1; $prime[127] = 1; $prime[131] = 1; $prime[137] = 1; $prime[139] = 1; $prime[149] = 1; $prime[151] = 1; $prime[157] = 1; $prime[163] = 1; $prime[167] = 1; $prime[173] = 1; $prime[179] = 1; $prime[181] = 1; $prime[191] = 1; $prime[193] = 1; $prime[197] = 1; $prime[199] = 1; $prime[211] = 1; $prime[223] = 1; $prime[227] = 1; $prime[229] = 1; $prime[233] = 1; $prime[239] = 1; $prime[241] = 1; $prime[251] = 1; $prime[257] = 1; $prime[263] = 1; $prime[269] = 1; $prime[271] = 1; $prime[277] = 1; $prime[281] = 1; $prime[283] = 1; $prime[293] = 1; $prime[307] = 1; $prime[311] = 1; $prime[313] = 1; $prime[317] = 1; $prime[331] = 1; $prime[337] = 1; $prime[347] = 1; $prime[349] = 1; $prime[353] = 1; $prime[359] = 1; $prime[367] = 1; $prime[373] = 1; $prime[379] = 1; $prime[383] = 1; $prime[389] = 1; $prime[397] = 1; $prime[401] = 1; $prime[409] = 1; $prime[419] = 1; $prime[421] = 1; $prime[431] = 1; $prime[433] = 1; $prime[439] = 1; $prime[443] = 1; $prime[449] = 1; $prime[457] = 1; $prime[461] = 1; $prime[463] = 1; $prime[467] = 1; $prime[479] = 1; $prime[487] = 1; $prime[491] = 1; $prime[499] = 1; $prime[503] = 1; $prime[509] = 1; $prime[521] = 1; $prime[523] = 1; $prime[541] = 1; $prime[547] = 1; $prime[557] = 1; $prime[563] = 1; $prime[569] = 1; $prime[571] = 1; $prime[577] = 1; $prime[587] = 1; $prime[593] = 1; $prime[599] = 1; $prime[601] = 1; $prime[607] = 1; $prime[613] = 1; $prime[617] = 1; $prime[619] = 1; $prime[631] = 1; $prime[641] = 1; $prime[643] = 1; $prime[647] = 1; $prime[653] = 1; $prime[659] = 1; $prime[661] = 1; $prime[673] = 1; $prime[677] = 1; $prime[683] = 1; $prime[691] = 1; $prime[701] = 1; $prime[709] = 1; $prime[719] = 1; $prime[727] = 1; $prime[733] = 1; $prime[739] = 1; $prime[743] = 1; $prime[751] = 1; $prime[757] = 1; $prime[761] = 1; $prime[769] = 1; $prime[773] = 1; $prime[787] = 1; $prime[797] = 1; $prime[809] = 1; $prime[811] = 1; $prime[821] = 1; $prime[823] = 1; $prime[827] = 1; $prime[829] = 1; $prime[839] = 1; $prime[853] = 1; $prime[857] = 1; $prime[859] = 1; $prime[863] = 1; $prime[877] = 1; $prime[881] = 1; $prime[883] = 1; $prime[887] = 1; $prime[907] = 1; $prime[911] = 1; $prime[919] = 1; $prime[929] = 1; $prime[937] = 1; $prime[941] = 1; $prime[947] = 1; $prime[953] = 1; $prime[967] = 1; $prime[971] = 1; $prime[977] = 1; $prime[983] = 1; $prime[991] = 1; $prime[997] = 1; $set1 = new Bit::Vector($limit+1); $set2 = new Bit::Vector($limit+1); $set3 = new Bit::Vector($limit+1); $set1->Fill(); $set2->Empty(); $set3->Primes(); $set1->Bit_Off(0); $set1->Bit_Off(1); $set2->Bit_On(0); $set2->Bit_On(1); for ( $j = 4; $j <= $limit; $j += 2 ) { $set1->Bit_Off($j); $set2->Bit_On($j); } for ( $i = 3; ($j = $i * $i) <= $limit; $i += 2 ) { for ( ; $j <= $limit; $j += $i ) { $set1->Bit_Off($j); $set2->Bit_On($j); } } $n = 1; for ( $i = 0; $i <= $limit; ++$i ) { if ($set1->contains($i) == $prime[$i]) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set2->bit_flip($i) == $prime[$i]) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } if ($set1->Norm() == 168) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set2->Norm() == 168) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set3->Norm() == 168) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set1->equal($set2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set1->equal($set3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set2->equal($set3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; __END__ Bit-Vector-7.4/t/06______subset.t000644 100660 100660 00000002605 12211373040 015605 0ustar00sbsb000000 000000 #!perl -w use strict; no strict "vars"; use Bit::Vector; # ====================================================================== # $set1->subset($set2); # ====================================================================== $bits = 6; print "1..$bits\n"; $n = 1; for ( $b = 1; $b <= $bits; ++$b ) { $set1 = new Bit::Vector($b); $set2 = new Bit::Vector($b); $c1 = 0; $c2 = 0; for ( $k = 0; $k <= $b; ++$k ) { $c1 += (1<<$k) * &binomial($b,$k); } for ( $i = 0; $i < (1<<$b); ++$i ) { $c = $i; for ( $k = 0; $k < $b; ++$k ) { if ($c & 1) { $set1->Bit_On($k); } else { $set1->Bit_Off($k); } $c >>= 1; } for ( $j = 0; $j < (1<<$b); ++$j ) { $c = $j; for ( $k = 0; $k < $b; ++$k ) { if ($c & 1) { $set2->Bit_On($k); } else { $set2->Bit_Off($k); } $c >>= 1; } if ($set1->subset($set2)) { ++$c2; } } } if ($c1 == $c2) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } exit; sub binomial { my($n,$k) = @_; my($prod) = 1; my($j) = 0; if (($n <= 0) || ($k <= 0) || ($n <= $k)) { return(1); } if ($k > $n - $k) { $k = $n - $k; } while ($j < $k) { $prod *= $n--; $prod /= ++$j; } return(int($prod + 0.5)); } __END__ Bit-Vector-7.4/t/28___chunklist.t000644 100660 100660 00000004725 12211373040 015660 0ustar00sbsb000000 000000 #!perl -w use strict; use Bit::Vector; # ====================================================================== # $value = $vector->Chunk_Read($bits,$offset); # $vector->Chunk_Store($bits,$offset,$value); # @values = $vector->Chunk_List_Read($bits); # $vector->Chunk_List_Store($bits,@values); # ====================================================================== my $limit = 1013; # Prime number in order to avoid trivial cases my $longbits = Bit::Vector::Long_Bits(); print "1..", 12*$longbits, "\n"; my($set,$tst,$bits,$ok,$i,$offset); my(@primes,@chunks); my(@vec) = Bit::Vector->new($limit,5); $vec[0]->Primes(); # Make sure all chunks here are unique, i.e., mutually different (as far as possible) $vec[3]->Fill(); $tst = $vec[4]; my $k = 0; while ($k < $limit) { $vec[1]->Bit_On($k++); $vec[2]->Bit_On($k++) if ($k < $limit); } my $n = 1; for ( $k = 0; $k < 4; $k++ ) { $set = $vec[$k]; for ( $bits = 1; $bits <= $longbits; $bits++ ) { undef @primes; $tst->Empty(); @primes = $set->Chunk_List_Read($bits); $tst->Chunk_List_Store($bits,@primes); if ($set->equal($tst)) {print "ok $n\n";} else {print "not ok $n\n";print "k = $k\nvect. bits: $limit bits\nchunk size: $bits bits\nset=".$set->to_Hex()."\ntst=".$tst->to_Hex()."\n";$tst->Xor($tst,$set);print "xor=".$tst->to_Hex()."\n";Dump(\@primes,'primes',$bits);} $n++; undef @chunks; $tst->Empty(); $ok = 1; for ( $i = 0, $offset = 0; $offset < $limit; $i++, $offset += $bits ) { $chunks[$i] = $set->Chunk_Read($bits,$offset); if ($primes[$i] != $chunks[$i]) { $ok = 0; } } if ($ok) {print "ok $n\n";} else {print "not ok $n\n";} $n++; for ( $i = 0; $i <= $#chunks; $i++ ) { $tst->Chunk_Store($bits,$i*$bits,$chunks[$i]); } if ($set->equal($tst)) {print "ok $n\n";} else {print "not ok $n\n";print "k = $k\nvect. bits: $limit bits\nchunk size: $bits bits\nset=".$set->to_Hex()."\ntst=".$tst->to_Hex()."\n";$tst->Xor($tst,$set);print "xor=".$tst->to_Hex()."\n";Dump(\@chunks,'chunks',$bits);} $n++; } } sub Dump { my($list,$name,$size) = @_; my($i,$len); my($sum) = 0; $len = $size >> 2; $len++ if ($size & 0x03); for ( $i = 0; $i < @{$list}; $i++ ) { $sum += $bits; printf('$' . $name . "[%02d] = '%0${len}X'; # %d\n", $i, $list->[$i], $sum); } } __END__ Bit-Vector-7.4/t/17_________gcd.t000644 100660 100660 00000014734 12211373040 015502 0ustar00sbsb000000 000000 #!perl -w use strict; use Bit::Vector; print "1..693\n"; my $n = 1; my $x = Bit::Vector->new(128); my $y = Bit::Vector->new(128); my $z = Bit::Vector->new(128); my $u = Bit::Vector->new(128); my $v = Bit::Vector->new(128); my $w = Bit::Vector->new(128); my($uu,$vv,$ww,$xx,$yy,$zz); sub gcd($$$$$) { my($a,$b,$c,$d,$e) = @_; my($q,$r,$i); my(@t); $t[0] = [ $a, 1, 0, 0 ]; $t[1] = [ $b, 0, 1, 0 ]; $x->from_Dec($a); $y->from_Dec($b); # printf("\n[ %6d, %6d, %6d, %6d ]\n", @{$t[0]}); $i = 0; if ($t[$i][0]) { while ($t[$i+1][0]) { $a = $t[$i][0]; $b = $t[$i+1][0]; $q = int( $a / $b ); $r = $a - $q * $b; $t[$i+2][0] = $r; $t[$i+2][1] = $t[$i][1] - $t[$i+1][1] * $q; $t[$i+2][2] = $t[$i][2] - $t[$i+1][2] * $q; $t[$i+1][3] = $q; # printf("[ %6d, %6d, %6d, %6d ]\n", @{$t[$i+1]}); $i++; } } else { $t[$i][0] = $t[$i+1][0]; $t[$i][1] = 0; $t[$i][2] = 1; } # printf("[ %6d, %6d, %6d, %6d ]\n", @{$t[$i+1]}); # print "\nGCD1( $t[0][0], $t[1][0] ) = ", $t[$i][0], "\n"; if ($t[$i][0] == $c) {print "ok $n\n";} else {print "not ok $n\n";warn "#1: $t[$i][0] != $c\n";} # 1 $n++; $z->GCD($x,$y); $xx = $x->to_Dec(); $yy = $y->to_Dec(); $zz = $z->to_Dec(); # printf("GCD2( %s, %s ) = %s\n", $xx, $yy, $zz); if ($zz == $c) {print "ok $n\n";} else {print "not ok $n\n";warn "#2: $zz != $c\n";} # 2 $n++; $z->GCD($v,$w,$x,$y); $xx = $x->to_Dec(); $yy = $y->to_Dec(); $zz = $z->to_Dec(); $vv = $v->to_Dec(); $ww = $w->to_Dec(); # printf("GCD3( %s, %s ) = %s\n", $xx, $yy, $zz); if ($zz == $c) {print "ok $n\n";} else {print "not ok $n\n";warn "#3: $zz != $c\n";} # 3 $n++; $v->Multiply($v,$x); $w->Multiply($w,$y); $u->add($v,$w,0); $uu = $u->to_Dec(); # printf("\n%d * %d + %d * %d = %d\n", # $t[$i][1], $t[0][0], # $t[$i][2], $t[1][0], # $t[$i][1] * $t[0][0] + # $t[$i][2] * $t[1][0]); if (($t[$i][1] * $t[0][0] + $t[$i][2] * $t[1][0]) == $c) {print "ok $n\n";} else {print "not ok $n\n";warn "#4: $t[$i][1] * $t[0][0] + $t[$i][2] * $t[1][0] != $c\n";} # 4 $n++; if ($t[$i][1] == $d) {print "ok $n\n";} else {print "not ok $n\n";warn "#5: $t[$i][1] != $d\n";} # 5 $n++; if ($t[$i][2] == $e) {print "ok $n\n";} else {print "not ok $n\n";warn "#6: $t[$i][2] != $e\n";} # 6 $n++; # printf("%s * %s + %s * %s = %s\n\n", $vv, $xx, $ww, $yy, $uu); if ($uu == $c) {print "ok $n\n";} else {print "not ok $n\n";warn "#7: $uu != $c\n";} # 7 $n++; if ($vv == $d) {print "ok $n\n";} else {print "not ok $n\n";warn "#8: $vv != $d\n";} # 8 $n++; if ($ww == $e) {print "ok $n\n";} else {print "not ok $n\n";warn "#9: $ww != $e\n";} # 9 $n++; } gcd( 0, 0, 0, 0, 1 ); gcd( 0, 1, 1, 0, 1 ); gcd( 1, 0, 1, 1, 0 ); gcd( 0, -1, -1, 0, 1 ); gcd( -1, 0, -1, 1, 0 ); gcd( 0, 2, 2, 0, 1 ); gcd( 2, 0, 2, 1, 0 ); gcd( 0, -2, -2, 0, 1 ); gcd( -2, 0, -2, 1, 0 ); gcd( 0, 3, 3, 0, 1 ); gcd( 3, 0, 3, 1, 0 ); gcd( 0, -3, -3, 0, 1 ); gcd( -3, 0, -3, 1, 0 ); gcd( 1, 1, 1, 0, 1 ); gcd( 1, -1, -1, 0, 1 ); gcd( -1, 1, 1, 0, 1 ); gcd( -1, -1, -1, 0, 1 ); gcd( 1, 2, 1, 1, 0 ); gcd( 2, 1, 1, 0, 1 ); gcd( -1, 2, -1, 1, 0 ); gcd( 2, -1, -1, 0, 1 ); gcd( 1, -2, 1, 1, 0 ); gcd( -2, 1, 1, 0, 1 ); gcd( -1, -2, -1, 1, 0 ); gcd( -2, -1, -1, 0, 1 ); gcd( 2, 3, 1, -1, 1 ); gcd( 3, 2, 1, 1, -1 ); gcd( -2, 3, 1, 1, 1 ); gcd( 3, -2, 1, 1, 1 ); gcd( 2, -3, -1, 1, 1 ); gcd( -3, 2, -1, 1, 1 ); gcd( -2, -3, -1, -1, 1 ); gcd( -3, -2, -1, 1, -1 ); gcd( 3, 5, 1, 2, -1 ); gcd( 5, 3, 1, -1, 2 ); gcd( -3, 5, -1, 2, 1 ); gcd( 5, -3, -1, 1, 2 ); gcd( 3, -5, 1, 2, 1 ); gcd( -5, 3, 1, 1, 2 ); gcd( -3, -5, -1, 2, -1 ); gcd( -5, -3, -1, -1, 2 ); gcd( 5, 7, 1, 3, -2 ); gcd( 7, 5, 1, -2, 3 ); gcd( -5, 7, -1, 3, 2 ); gcd( 7, -5, -1, 2, 3 ); gcd( 5, -7, 1, 3, 2 ); gcd( -7, 5, 1, 2, 3 ); gcd( -5, -7, -1, 3, -2 ); gcd( -7, -5, -1, -2, 3 ); gcd( 6, 30, 6, 1, 0 ); gcd( 30, 6, 6, 0, 1 ); gcd( -6, 30, -6, 1, 0 ); gcd( 30, -6, -6, 0, 1 ); gcd( 6, -30, 6, 1, 0 ); gcd( -30, 6, 6, 0, 1 ); gcd( -6, -30, -6, 1, 0 ); gcd( -30, -6, -6, 0, 1 ); gcd( 2322, 0, 2322, 1, 0 ); gcd( 0, 654, 654, 0, 1 ); gcd( -2322, 0, -2322, 1, 0 ); gcd( 0, -654, -654, 0, 1 ); gcd( 2322, 654, 6, 20, -71 ); gcd( 2322, -654, 6, 20, 71 ); gcd( -2322, 654, -6, 20, 71 ); gcd( -2322, -654, -6, 20, -71 ); gcd( 654, 2322, 6, -71, 20 ); gcd( 654, -2322, -6, 71, 20 ); gcd( -654, 2322, 6, 71, 20 ); gcd( -654, -2322, -6, -71, 20 ); gcd( 12345, 54321, 3, 3617, -822 ); gcd( 12345, -54321, 3, 3617, 822 ); gcd( -12345, 54321, -3, 3617, 822 ); gcd( -12345, -54321, -3, 3617, -822 ); gcd( 54321, 12345, 3, -822, 3617 ); gcd( 54321, -12345, -3, 822, 3617 ); gcd( -54321, 12345, 3, 822, 3617 ); gcd( -54321, -12345, -3, -822, 3617 ); __END__ Bit-Vector-7.4/t/15_________add.t000644 100660 100660 00000012513 12211373040 015464 0ustar00sbsb000000 000000 #!perl -w use strict; no strict "vars"; use Bit::Vector; # ====================================================================== # $carry_out = $vector1->add($vector2,$vector3,$carry_in); # ====================================================================== print "1..1001\n"; $n = 1; $result0{'FE'}{'FE'} = 'FC'; $carry0{'FE'}{'FE'} = 1; $result0{'FE'}{'FF'} = 'FD'; $carry0{'FE'}{'FF'} = 1; $result0{'FE'}{'00'} = 'FE'; $carry0{'FE'}{'00'} = 0; $result0{'FE'}{'01'} = 'FF'; $carry0{'FE'}{'01'} = 0; $result0{'FE'}{'02'} = '00'; $carry0{'FE'}{'02'} = 1; $result0{'FF'}{'FE'} = 'FD'; $carry0{'FF'}{'FE'} = 1; $result0{'FF'}{'FF'} = 'FE'; $carry0{'FF'}{'FF'} = 1; $result0{'FF'}{'00'} = 'FF'; $carry0{'FF'}{'00'} = 0; $result0{'FF'}{'01'} = '00'; $carry0{'FF'}{'01'} = 1; $result0{'FF'}{'02'} = '01'; $carry0{'FF'}{'02'} = 1; $result0{'00'}{'FE'} = 'FE'; $carry0{'00'}{'FE'} = 0; $result0{'00'}{'FF'} = 'FF'; $carry0{'00'}{'FF'} = 0; $result0{'00'}{'00'} = '00'; $carry0{'00'}{'00'} = 0; $result0{'00'}{'01'} = '01'; $carry0{'00'}{'01'} = 0; $result0{'00'}{'02'} = '02'; $carry0{'00'}{'02'} = 0; $result0{'01'}{'FE'} = 'FF'; $carry0{'01'}{'FE'} = 0; $result0{'01'}{'FF'} = '00'; $carry0{'01'}{'FF'} = 1; $result0{'01'}{'00'} = '01'; $carry0{'01'}{'00'} = 0; $result0{'01'}{'01'} = '02'; $carry0{'01'}{'01'} = 0; $result0{'01'}{'02'} = '03'; $carry0{'01'}{'02'} = 0; $result0{'02'}{'FE'} = '00'; $carry0{'02'}{'FE'} = 1; $result0{'02'}{'FF'} = '01'; $carry0{'02'}{'FF'} = 1; $result0{'02'}{'00'} = '02'; $carry0{'02'}{'00'} = 0; $result0{'02'}{'01'} = '03'; $carry0{'02'}{'01'} = 0; $result0{'02'}{'02'} = '04'; $carry0{'02'}{'02'} = 0; $result1{'FE'}{'FE'} = 'FD'; $carry1{'FE'}{'FE'} = 1; $result1{'FE'}{'FF'} = 'FE'; $carry1{'FE'}{'FF'} = 1; $result1{'FE'}{'00'} = 'FF'; $carry1{'FE'}{'00'} = 0; $result1{'FE'}{'01'} = '00'; $carry1{'FE'}{'01'} = 1; $result1{'FE'}{'02'} = '01'; $carry1{'FE'}{'02'} = 1; $result1{'FF'}{'FE'} = 'FE'; $carry1{'FF'}{'FE'} = 1; $result1{'FF'}{'FF'} = 'FF'; $carry1{'FF'}{'FF'} = 1; $result1{'FF'}{'00'} = '00'; $carry1{'FF'}{'00'} = 1; $result1{'FF'}{'01'} = '01'; $carry1{'FF'}{'01'} = 1; $result1{'FF'}{'02'} = '02'; $carry1{'FF'}{'02'} = 1; $result1{'00'}{'FE'} = 'FF'; $carry1{'00'}{'FE'} = 0; $result1{'00'}{'FF'} = '00'; $carry1{'00'}{'FF'} = 1; $result1{'00'}{'00'} = '01'; $carry1{'00'}{'00'} = 0; $result1{'00'}{'01'} = '02'; $carry1{'00'}{'01'} = 0; $result1{'00'}{'02'} = '03'; $carry1{'00'}{'02'} = 0; $result1{'01'}{'FE'} = '00'; $carry1{'01'}{'FE'} = 1; $result1{'01'}{'FF'} = '01'; $carry1{'01'}{'FF'} = 1; $result1{'01'}{'00'} = '02'; $carry1{'01'}{'00'} = 0; $result1{'01'}{'01'} = '03'; $carry1{'01'}{'01'} = 0; $result1{'01'}{'02'} = '04'; $carry1{'01'}{'02'} = 0; $result1{'02'}{'FE'} = '01'; $carry1{'02'}{'FE'} = 1; $result1{'02'}{'FF'} = '02'; $carry1{'02'}{'FF'} = 1; $result1{'02'}{'00'} = '03'; $carry1{'02'}{'00'} = 0; $result1{'02'}{'01'} = '04'; $carry1{'02'}{'01'} = 0; $result1{'02'}{'02'} = '05'; $carry1{'02'}{'02'} = 0; foreach $bits (31, 32, 33, 63, 64, 65, 127, 128, 129, 997) { $vec0 = Bit::Vector->new($bits); $vec1 = Bit::Vector->new($bits); $vec2 = Bit::Vector->new($bits); $vec3 = Bit::Vector->new($bits); foreach $arg1 (sort hexadecimal (keys %result0)) { foreach $arg2 (sort hexadecimal (keys %{$result0{$arg1}})) { # print "add '$arg1' + '$arg2'\n"; $vec1->from_Hex(convert($arg1)); $vec2->from_Hex(convert($arg2)); $vec3->from_Hex(convert($result0{$arg1}{$arg2})); $carry3 = $carry0{$arg1}{$arg2}; $carry0 = $vec0->add($vec1,$vec2,0); # print "Result: '", $vec0->to_Hex(), "' $carry0\n"; # print "Should be: '", $vec3->to_Hex(), "' $carry3\n"; if ($vec0->equal($vec3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($carry0 == $carry3) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } } foreach $arg1 (sort hexadecimal (keys %result0)) { foreach $arg2 (sort hexadecimal (keys %{$result0{$arg1}})) { # print "add '$arg1' + '$arg2' + 1\n"; $vec1->from_Hex(convert($arg1)); $vec2->from_Hex(convert($arg2)); $vec3->from_Hex(convert($result1{$arg1}{$arg2})); $carry3 = $carry1{$arg1}{$arg2}; $carry0 = $vec0->add($vec1,$vec2,1); # print "Result: '", $vec0->to_Hex(), "' $carry0\n"; # print "Should be: '", $vec3->to_Hex(), "' $carry3\n"; if ($vec0->equal($vec3)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($carry0 == $carry3) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } } } $vec = Bit::Vector->new(1024); $vec->add($vec,$vec,5); $vec->bit_flip(0); if ($vec->is_empty()) {print "ok $n\n";} else {print "not ok $n\n";} $n++; exit; sub hexadecimal { my($x,$y) = (hex($a),hex($b)); if ($x > 127) { $x -= 256; } if ($y > 127) { $y -= 256; } return( $x <=> $y ); } sub convert { my($hex) = shift; my($dec) = hex($hex); my($len); $len = int($bits / 4); if ($len * 4 < $bits) { $len++; } $len -= 2; if ($dec > 127) { return( ('F' x $len) . $hex ); } else { return( ('0' x $len) . $hex ); } } __END__ Bit-Vector-7.4/t/12______string.t000644 100660 100660 00000020031 12211373040 015574 0ustar00sbsb000000 000000 #!perl -w use strict; no strict "vars"; use Bit::Vector::Overload; $Bit::Vector::CONFIG[2] = 3; # ====================================================================== # $vector->to_Hex(); # $vector->from_Hex(); # $vector->to_Enum(); # $vector->from_Enum(); # ====================================================================== print "1..192\n"; $limit = 100; $vec1 = Bit::Vector->new($limit+1); $vec2 = Bit::Vector->new($limit+1); $n = 1; eval { $vec1->from_Hex("FEDCBA9876543210"); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $str1 = $vec1->to_Hex(); if ($str1 =~ /^0*FEDCBA9876543210$/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $vec2->from_Hex("fedcba9876543210"); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $str2 = $vec2->to_Hex(); if ($str2 =~ /^0*FEDCBA9876543210$/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $vec1->from_Hex("deadbeef"); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $str1 = $vec1->to_Hex(); if ($str1 =~ /^0*DEADBEEF$/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $vec1->from_Hex("dead beef"); }; if ($@ =~ /syntax error/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $vec2->from_Hex("beef"); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($vec1->equal($vec2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $str1 = $vec1->to_Hex(); if ($str1 =~ /^0*BEEF$/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $str2 = $vec2->to_Enum(); if ($str2 eq "0-3,5-7,9-13,15") {print "ok $n\n";} else {print "not ok $n\n";} $n++; $vec1->Primes(); $str1 = $vec1->to_Hex(); if ($str1 =~ /^0*20208828828208A20A08A28AC$/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $str2 = $vec1->to_Enum(); if ($str2 eq "2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97") {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $vec2->from_Hex("20208828828208A20A08A28AC"); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($vec1->equal($vec2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $vec2->Flip(); $str1 = "2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97"; eval { $vec2->from_Enum($str1); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($vec1->equal($vec2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $str2 = "43,4,19,2,12,67,31,11,3,23,29,6-9,79-97,14-16,47,53-59,71,37-41,61"; eval { $vec2->from_Enum($str2); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $str1 = $vec2->to_Enum(); $str2 = "2-4,6-9,11,12,14-16,19,23,29,31,37-41,43,47,53-59,61,67,71,79-97"; if ($str1 eq $str2) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $str1 = $vec2->to_Hex(); if ($str1 =~ /^0*3FFFF80882FE08BE0A089DBDC$/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $vec2->Fill(); if ($vec2->Norm() == $limit+1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $vec2->from_Hex("0000000000000000"); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($vec2->Norm() == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $vec2->Fill(); if ($vec2->Norm() == $limit+1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $vec2->from_Hex("0"); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($vec2->Norm() == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $vec2->Fill(); if ($vec2->Norm() == $limit+1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $vec2->from_Hex(""); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($vec2->Norm() == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $vec1 = Bit::Vector->new(64); eval { $vec1->from_Hex("FEDCBA9876543210"); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $str1 = $vec1->to_Hex(); if ($str1 =~ /^0*FEDCBA9876543210$/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $vec2 = Bit::Vector->new(64); eval { $vec2->from_Hex("fedcba9876543210"); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $str2 = $vec2->to_Hex(); if ($str2 =~ /^0*FEDCBA9876543210$/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $vec1 = Bit::Vector->new(32); eval { $vec1->from_Hex("DEADbeef"); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $str1 = $vec1->to_Hex(); if ($str1 =~ /^0*DEADBEEF$/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $vec2 = Bit::Vector->new(36); eval { $vec2->from_Hex("DEAD beef"); }; if ($@ =~ /syntax error/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $str2 = $vec2->to_Hex(); if ($str2 =~ /^0*00000BEEF$/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $vec1 = Bit::Vector->new(64); eval { $vec1->from_Hex("0000000000000000"); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($vec1->Norm() == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($vec1->Size() == 64) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $vec2 = Bit::Vector->new(64); eval { $vec2->from_Hex("00000g0000000000"); }; if ($@ =~ /syntax error/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $vec2->from_Hex(""); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $vec1 = Bit::Vector->new($limit+1); $str1 = 3.1415926 * 2.0E+7; eval { $vec1->from_Hex($str1); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $str2 = $vec1->to_Hex(); if ($str2 =~ /^0*62831852$/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $vec2 = Bit::Vector->new($limit+1); eval { $vec2->from_Hex($str1); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $str2 = $vec2->to_Hex(); if ($str2 =~ /^0*62831852$/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $str2 = 3.1415926 * 2.0; eval { $vec1->from_Hex($str2); }; if ($@ =~ /syntax error/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $vec2->from_Hex($str2); }; if ($@ =~ /syntax error/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $str1 = "ERRORFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"; # _123456789ABCDEF_123456789ABCDEF_123456789ABCDEF_123456789ABCDEF eval { $vec1->from_Hex($str1); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $str2 = $vec1->to_Hex(); if ($str2 =~ /^0*1FFFFFFFFFFFFFFFFFFFFFFFFF$/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $vec2 = $vec1->Shadow(); eval { $vec1->from_Enum("0-$limit"); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $vec2->Fill(); if ($vec1->equal($vec2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $vec1->from_Enum("0..$limit"); }; if ($@ =~ /syntax error/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $vec1->from_Enum("0,$limit"); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $vec2->Empty(); $vec2->Bit_On(0); $vec2->Bit_On($limit); if ($vec1->equal($vec2)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $vec1->from_Enum("0,$limit,"); }; if ($@ =~ /syntax error/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $vec1->from_Enum("0,\$limit"); }; if ($@ =~ /syntax error/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $vec1->from_Enum("101-102"); }; if ($@ =~ /index out of range/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $vec1->from_Enum("100-102"); }; if ($@ =~ /index out of range/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $vec1->from_Enum("100-99"); }; if ($@ =~ /minimum > maximum index/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $vec1->from_Enum("100,101"); }; if ($@ =~ /index out of range/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $vec1->from_Enum("101,100"); }; if ($@ =~ /index out of range/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; @first = ('', '1', '3', '7'); for ( $bits = 0; $bits <= 129; $bits++ ) { $vec = Bit::Vector->new($bits); $vec->Fill(); if ($vec->to_Hex() eq $first[$bits & 3] . ('F' x ($bits >> 2))) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } __END__ Bit-Vector-7.4/t/09__parameters.t000644 100660 100660 00000040504 12211373040 015652 0ustar00sbsb000000 000000 #!perl -w use strict; no strict "vars"; use Bit::Vector; # ====================================================================== # parameter checks # ====================================================================== $prefix = 'Bit::Vector'; print "1..964\n"; $n = 1; # parameter types: # 0 = object reference # 1 = number of bits # 2 = index ( 0 <= index < bits ) # 3 = offset ( 0 <= offset <= bits ) # 4 = word index ( 0 <= index < size ) # 5 = length ( 0 <= offset+length <= bits ) # 6 = arbitrary (non-negative) number # 7 = boolean # 8 = string # 9 = chunksize # 10 = anything # 11 = rows # 12 = columns # 16 = any number of object references # 18 = any number of indices # 22 = any number of arbitrary numbers $method_list{'Version'} = [ ]; $method_list{'Word_Bits'} = [ ]; $method_list{'Long_Bits'} = [ ]; $method_list{'Create'} = [ 10, 1 ]; $method_list{'Shadow'} = [ 0 ]; $method_list{'Clone'} = [ 0 ]; $method_list{'Concat'} = [ 0, 0 ]; $method_list{'Concat_List'} = [ 16, 16, 16, 16, 16 ]; $method_list{'Size'} = [ 0 ]; $method_list{'Resize'} = [ 0, 1 ]; $method_list{'Copy'} = [ 0, 0 ]; $method_list{'Empty'} = [ 0 ]; $method_list{'Fill'} = [ 0 ]; $method_list{'Flip'} = [ 0 ]; $method_list{'Primes'} = [ 0 ]; $method_list{'Reverse'} = [ 0, 0 ]; $method_list{'Interval_Empty'} = [ 0, 2, 2 ]; $method_list{'Interval_Fill'} = [ 0, 2, 2 ]; $method_list{'Interval_Flip'} = [ 0, 2, 2 ]; $method_list{'Interval_Reverse'} = [ 0, 2, 2 ]; $method_list{'Interval_Scan_inc'} = [ 0, 2 ]; $method_list{'Interval_Scan_dec'} = [ 0, 2 ]; $method_list{'Interval_Copy'} = [ 0, 0, 2, 2, 5 ]; $method_list{'Interval_Substitute'} = [ 0, 0, 3, 5, 3, 5 ]; $method_list{'is_empty'} = [ 0 ]; $method_list{'is_full'} = [ 0 ]; $method_list{'equal'} = [ 0, 0 ]; $method_list{'Lexicompare'} = [ 0, 0 ]; $method_list{'Compare'} = [ 0, 0 ]; $method_list{'to_Hex'} = [ 0 ]; $method_list{'from_Hex'} = [ 0, 8 ]; $method_list{'to_Bin'} = [ 0 ]; $method_list{'from_Bin'} = [ 0, 8 ]; $method_list{'to_Dec'} = [ 0 ]; $method_list{'from_Dec'} = [ 0, 8 ]; $method_list{'to_Enum'} = [ 0 ]; $method_list{'from_Enum'} = [ 0, 8 ]; $method_list{'new_Hex'} = [ 10, 1, 8 ]; $method_list{'new_Bin'} = [ 10, 1, 8 ]; $method_list{'new_Dec'} = [ 10, 1, 8 ]; $method_list{'new_Enum'} = [ 10, 1, 8 ]; $method_list{'Bit_Off'} = [ 0, 2 ]; $method_list{'Bit_On'} = [ 0, 2 ]; $method_list{'bit_flip'} = [ 0, 2 ]; $method_list{'bit_test'} = [ 0, 2 ]; $method_list{'Bit_Copy'} = [ 0, 2, 7 ]; $method_list{'LSB'} = [ 0, 7 ]; $method_list{'MSB'} = [ 0, 7 ]; $method_list{'lsb'} = [ 0 ]; $method_list{'msb'} = [ 0 ]; $method_list{'rotate_left'} = [ 0 ]; $method_list{'rotate_right'} = [ 0 ]; $method_list{'shift_left'} = [ 0, 7 ]; $method_list{'shift_right'} = [ 0, 7 ]; $method_list{'Move_Left'} = [ 0, 6 ]; $method_list{'Move_Right'} = [ 0, 6 ]; $method_list{'Insert'} = [ 0, 2, 6 ]; $method_list{'Delete'} = [ 0, 2, 6 ]; $method_list{'increment'} = [ 0 ]; $method_list{'decrement'} = [ 0 ]; $method_list{'add'} = [ 0, 0, 0, 7 ]; $method_list{'subtract'} = [ 0, 0, 0, 7 ]; $method_list{'Negate'} = [ 0, 0 ]; $method_list{'Absolute'} = [ 0, 0 ]; $method_list{'Sign'} = [ 0 ]; $method_list{'Multiply'} = [ 0, 0, 0 ]; $method_list{'Divide'} = [ 0, 0, 0, 0 ]; $method_list{'GCD'} = [ 0, 0, 0 ]; $method_list{'Power'} = [ 0, 0, 0 ]; $method_list{'Block_Store'} = [ 0, 8 ]; $method_list{'Block_Read'} = [ 0 ]; $method_list{'Word_Size'} = [ 0 ]; $method_list{'Word_Store'} = [ 0, 4, 6 ]; $method_list{'Word_Read'} = [ 0, 4 ]; $method_list{'Word_List_Store'} = [ 0, 22, 22, 22, 22, 22 ]; $method_list{'Word_List_Read'} = [ 0 ]; $method_list{'Word_Insert'} = [ 0, 4, 6 ]; $method_list{'Word_Delete'} = [ 0, 4, 6 ]; $method_list{'Chunk_Store'} = [ 0, 9, 2, 6 ]; $method_list{'Chunk_Read'} = [ 0, 9, 2 ]; $method_list{'Chunk_List_Store'} = [ 0, 9, 22, 22, 22, 22, 22 ]; $method_list{'Chunk_List_Read'} = [ 0, 9 ]; $method_list{'Index_List_Remove'} = [ 0, 18, 18, 18, 18, 18 ]; $method_list{'Index_List_Store'} = [ 0, 18, 18, 18, 18, 18 ]; $method_list{'Index_List_Read'} = [ 0 ]; $method_list{'Union'} = [ 0, 0, 0 ]; $method_list{'Intersection'} = [ 0, 0, 0 ]; $method_list{'Difference'} = [ 0, 0, 0 ]; $method_list{'ExclusiveOr'} = [ 0, 0, 0 ]; $method_list{'Complement'} = [ 0, 0 ]; $method_list{'subset'} = [ 0, 0 ]; $method_list{'Norm'} = [ 0 ]; $method_list{'Min'} = [ 0 ]; $method_list{'Max'} = [ 0 ]; $method_list{'Multiplication'} = [ 0, 11, 12, 0, 11, 12, 0, 11, 12 ]; $method_list{'Product'} = [ 0, 11, 12, 0, 11, 12, 0, 11, 12 ]; $method_list{'Closure'} = [ 0, 11, 12 ]; $method_list{'Transpose'} = [ 0, 11, 12, 0, 11, 12 ]; foreach $method (sort keys(%method_list)) { $definition = $method_list{$method}; $count = @{$definition}; if ($count == 0) { $action = "\$dummy = ${prefix}::${method}();"; eval "$action"; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $action = "\$dummy = ${prefix}::${method}(\$dummy);"; eval "$action"; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $action = "\$dummy = ${prefix}::${method}(\$dummy,\$dummy);"; $message = "Usage: ${prefix}->${method}\\(\\)"; eval "$action"; if ($@ =~ /$message/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } else { $action = "${prefix}::${method}(\@parameter_list);"; $leadin = "${prefix}::${method}\\(\\): "; foreach $bits (1024) { &init_objects(); &correct_values(0); undef @parameters; @parameters = @parameter_list; eval "$action"; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($objects > 1) { &init_objects(); &correct_values(1); eval "$action"; if (($method eq "Divide") or ($method eq "Power")) { if ($@ =~ /result vector\(s\) must be distinct/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } else { unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } } if ($limited) { $message = "Usage: (?:${prefix}::)?${method}\\([a-zA-Z\\[\\]_, ]+\\)"; &refresh(); pop(@parameter_list); eval "$action"; if ($@ =~ /$message/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; &refresh(); push(@parameter_list,0); push(@parameter_list,0) if ($method eq "Create"); eval "$action"; if ($@ =~ /$message/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } &init_values(); for ( $i = 0; $i < $count; $i++ ) { $type = $definition->[$i]; $type &= 0x0F; $values = @{$wrong_values[$type]}; for ( $j = 0; $j < $values; $j++ ) { &refresh(); $parameter_list[$i] = $wrong_values[$type]->[$j]; $message = $leadin . $error_message[$type]->[$j]; eval "$action"; # Special cases "Copy()" and "Power()": if (($n == 170) or ($n == 174) or ($n == 574) or ($n == 578)) { unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} } else { if ($@ =~ /$message/) {print "ok $n\n";} else {print "not ok $n\n";} } $n++; } } } } } sub refresh { if ($method eq "Resize") { &init_objects(); &correct_values(0); } else { undef @parameter_list; @parameter_list = @parameters; } } sub init_objects { undef @vector; $vector[0] = Bit::Vector->new($bits); $vector[1] = Bit::Vector->new($bits); $vector[2] = Bit::Vector->new($bits); $vector[3] = Bit::Vector->new($bits); $vector[4] = Bit::Vector->new($bits); $vector[5] = Bit::Vector->new($bits); $vector[6] = Bit::Vector->new($bits); if ($bits > 0) { $vector[0]->Bit_On(0); $vector[1]->Bit_On(0); $vector[2]->Bit_On(0); $vector[3]->Bit_On(0); $vector[4]->Bit_On(0); $vector[5]->Bit_On(0); $vector[6]->Bit_On(0); } } sub correct_values { my($flag) = @_; my($i,$type); # 0 = object reference # 1 = number of bits # 2 = index ( 0 <= index < bits ) # 3 = offset ( 0 <= offset <= bits ) # 4 = word index ( 0 <= index < size ) # 5 = length ( 0 <= offset+length <= bits ) # 6 = arbitrary (non-negative) number # 7 = boolean # 8 = string # 9 = chunksize # 10 = anything # 11 = rows # 12 = columns $objects = 0; $limited = 1; undef @parameter_list; for ( $i = 0; $i < $count; $i++ ) { $type = $definition->[$i]; if ($type >= 16) { $limited = 0; } $type &= 0x0F; if ($type == 0) { $objects++; if ($flag) { $parameter_list[$i] = $vector[0]; } else { $parameter_list[$i] = $vector[$i]; } } elsif ($type == 1) { $parameter_list[$i] = ($bits << 1) | 1; } elsif ($type == 2) { $parameter_list[$i] = $bits - 1; } elsif ($type == 3) { $parameter_list[$i] = $bits; } elsif ($type == 4) { $parameter_list[$i] = $vector[0]->Word_Size() - 1; } elsif ($type == 5) { $parameter_list[$i] = $bits + 1; } elsif ($type == 6) { $parameter_list[$i] = (1 << (Bit::Vector->Word_Bits()-1)) - 1; } elsif ($type == 7) { $parameter_list[$i] = 1; } elsif ($type == 8) { $parameter_list[$i] = '1011'; } elsif ($type == 9) { $parameter_list[$i] = Bit::Vector->Long_Bits(); } elsif ($type == 10) { $parameter_list[$i] = 'anything'; } elsif ($type == 11) { $parameter_list[$i] = int(sqrt($bits) + 0.5); } elsif ($type == 12) { $parameter_list[$i] = int(sqrt($bits) + 0.5); } else { die "internal error"; } } } sub init_values { undef @fake; undef @wrong_values; undef @error_message; $wrong_values[0] = [ ]; $error_message[0] = [ ]; $wrong_values[1] = [ ]; $error_message[1] = [ ]; $wrong_values[2] = [ ]; $error_message[2] = [ ]; $wrong_values[3] = [ ]; $error_message[3] = [ ]; $wrong_values[4] = [ ]; $error_message[4] = [ ]; $wrong_values[5] = [ ]; $error_message[5] = [ ]; $wrong_values[6] = [ ]; $error_message[6] = [ ]; $wrong_values[7] = [ ]; $error_message[7] = [ ]; $wrong_values[8] = [ ]; $error_message[8] = [ ]; $wrong_values[9] = [ ]; $error_message[9] = [ ]; $wrong_values[10] = [ ]; $error_message[10] = [ ]; $wrong_values[11] = [ ]; $error_message[11] = [ ]; $wrong_values[12] = [ ]; $error_message[12] = [ ]; # 0 = object reference # 1 = number of bits # 2 = index ( 0 <= index < bits ) # 3 = offset ( 0 <= offset <= bits ) # 4 = word index ( 0 <= index < size ) # 5 = length ( 0 <= offset+length <= bits ) # 6 = arbitrary (non-negative) number # 7 = boolean # 8 = string # 9 = chunksize # 10 = anything # 11 = rows # 12 = columns if ($objects > 1) { if ($method !~ /^(?:Concat(?:_List)?|Interval_(?:Copy|Substitute))$/) { push(@{$wrong_values[0]}, Bit::Vector->new($bits-1)); push(@{$error_message[0]}, "(?:bit vector|set|matrix) size mismatch"); } } $global = 0x000E9CE0; if ($method ne "Concat_List") { push(@{$wrong_values[0]}, $global); push(@{$error_message[0]}, "item is not a \"$prefix\" object"); } $fake[0] = Bit::Vector->new($bits); $fake[0]->DESTROY(); push(@{$wrong_values[0]}, $fake[0]); push(@{$error_message[0]}, "item is not a \"$prefix\" object"); $fake[1] = \$global; bless($fake[1], $prefix); push(@{$wrong_values[0]}, $fake[1]); push(@{$error_message[0]}, "item is not a \"$prefix\" object"); # push(@{$wrong_values[1]}, -1); # push(@{$error_message[1]}, "unable to allocate memory"); push(@{$wrong_values[2]}, $bits); push(@{$error_message[2]}, "(?:(?:start |m(?:in|ax)imum )?index|offset) out of range"); push(@{$wrong_values[2]}, -1); push(@{$error_message[2]}, "(?:(?:start |m(?:in|ax)imum )?index|offset) out of range"); push(@{$wrong_values[3]}, $bits+1); push(@{$error_message[3]}, "offset out of range"); push(@{$wrong_values[3]}, -1); push(@{$error_message[3]}, "offset out of range"); push(@{$wrong_values[4]}, $vector[0]->Word_Size()); push(@{$error_message[4]}, "offset out of range"); push(@{$wrong_values[4]}, -1); push(@{$error_message[4]}, "offset out of range"); push(@{$wrong_values[9]}, 0); push(@{$error_message[9]}, "chunk size out of range"); push(@{$wrong_values[9]}, Bit::Vector->Long_Bits()+1); push(@{$error_message[9]}, "chunk size out of range"); push(@{$wrong_values[9]}, -1); push(@{$error_message[9]}, "chunk size out of range"); push(@{$wrong_values[11]}, 0); push(@{$error_message[11]}, "matrix size mismatch"); push(@{$wrong_values[12]}, 0); push(@{$error_message[12]}, "matrix size mismatch"); push(@{$wrong_values[1]}, \$global); push(@{$error_message[1]}, "item is not a (?:string|scalar)"); push(@{$wrong_values[2]}, \$global); push(@{$error_message[2]}, "item is not a (?:string|scalar)"); push(@{$wrong_values[3]}, \$global); push(@{$error_message[3]}, "item is not a (?:string|scalar)"); push(@{$wrong_values[4]}, \$global); push(@{$error_message[4]}, "item is not a (?:string|scalar)"); push(@{$wrong_values[5]}, \$global); push(@{$error_message[5]}, "item is not a (?:string|scalar)"); push(@{$wrong_values[6]}, \$global); push(@{$error_message[6]}, "item is not a (?:string|scalar)"); push(@{$wrong_values[7]}, \$global); push(@{$error_message[7]}, "item is not a (?:string|scalar)"); push(@{$wrong_values[8]}, \$global); push(@{$error_message[8]}, "item is not a (?:string|scalar)"); push(@{$wrong_values[9]}, \$global); push(@{$error_message[9]}, "item is not a (?:string|scalar)"); push(@{$wrong_values[11]}, \$global); push(@{$error_message[11]}, "item is not a (?:string|scalar)"); push(@{$wrong_values[12]}, \$global); push(@{$error_message[12]}, "item is not a (?:string|scalar)"); } __END__ Bit-Vector-7.4/t/30__overloaded.t000644 100660 100660 00000054431 12211373040 015631 0ustar00sbsb000000 000000 #!perl -w use strict; no strict "vars"; use Bit::Vector::Overload; $Bit::Vector::CONFIG[2] = 3; # ====================================================================== # test overloaded operators # ====================================================================== $operator_list{'+='} = 1; $operator_list{'|='} = 1; $operator_list{'-='} = 1; $operator_list{'*='} = 1; $operator_list{'&='} = 1; $operator_list{'^='} = 1; $operator_list{'<<='} = 1; $operator_list{'>>='} = 1; $operator_list{'x='} = 1; $operator_list{'.='} = 1; $operator_list{'+'} = 2; $operator_list{'|'} = 2; $operator_list{'-'} = 2; $operator_list{'*'} = 2; $operator_list{'&'} = 2; $operator_list{'^'} = 2; $operator_list{'<<'} = 2; $operator_list{'>>'} = 2; $operator_list{'x'} = 2; $operator_list{'.'} = 2; $operator_list{'=='} = 2; $operator_list{'!='} = 2; $operator_list{'<'} = 2; $operator_list{'<='} = 2; $operator_list{'>'} = 2; $operator_list{'>='} = 2; $operator_list{'cmp'} = 2; $operator_list{'eq'} = 2; $operator_list{'ne'} = 2; $operator_list{'lt'} = 2; $operator_list{'le'} = 2; $operator_list{'gt'} = 2; $operator_list{'ge'} = 2; print "1..15695\n"; $n = 1; $set = Bit::Vector->new(500); if (abs($set) == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Min() >= 500) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Max() < 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; unless ($set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (! $set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set += 0; if (abs($set) == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Min() == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Max() == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; unless (! $set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set += 1; if (abs($set) == 2) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Min() == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Max() == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; unless (! $set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set ^= 0; if (abs($set) == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Min() == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Max() == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set += 400; if (abs($set) == 2) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Min() == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Max() == 400) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set ^= 0; if (abs($set) == 3) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Min() == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Max() == 400) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $ref = $set; if ($ref == $set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $ref = $set->new(500); if (! $ref) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $ref->Copy($set); if ($ref == $set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($ref) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $ref = $set + 11; if (abs($ref) == 4) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($ref->Min() == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($ref->Max() == 400) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($ref->bit_test(11)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (!($ref == $set)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($ref != $set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set < $ref) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set <= $ref) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($ref > $set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($ref >= $set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $ref = $set + 499; if (abs($ref) == 4) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($ref->Min() == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($ref->Max() == 499) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $ref = $ref - 400; if (abs($ref) == 3) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($ref->Min() == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($ref->Max() == 499) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $ref = $ref - 0; if (abs($ref) == 2) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($ref->Min() == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($ref->Max() == 499) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $ref -= 499; if (abs($ref) == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($ref->Min() == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($ref->Max() == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $ref -= 1; if (abs($ref) == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($ref->Min() >= 500) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($ref->Max() < 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $limit = 1000; # some tests below assume this limit to be even! $primes = Bit::Vector->new($limit+1); if (! $primes) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $primes->Fill(); if ($primes) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (abs($primes) == $limit+1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($primes->Min() == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($primes->Max() == $limit) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $primes -= 0; $primes -= 1; for ( $j = 4; $j <= $limit; $j += 2 ) { $primes -= $j; } for ( $i = 3; ($j = $i * $i) <= $limit; $i += 2 ) { for ( ; $j <= $limit; $j += $i ) { $primes -= $j; } } if (abs($primes) == 168) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($primes->Min() == 2) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($primes->Max() == 997) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $odd = $primes->new($limit+1); if (! $odd) {print "ok $n\n";} else {print "not ok $n\n";} $n++; for ( $i = 1; $i <= $limit; $i += 2 ) { $odd += $i; } if ($odd) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (abs($odd) == $limit/2) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($odd->Min() == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($odd->Max() == 999) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (!($odd == $primes)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($odd != $primes) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (!($primes < $odd)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (!($primes <= $odd)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (!($primes > $odd)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (!($primes >= $odd)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp = $primes - $odd; if ($temp == 2) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (2 == $temp) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $odd = $odd + 2; if (abs($odd) == ($limit/2)+1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($odd->Min() == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($odd->Max() == 999) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (!($odd == $primes)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($odd != $primes) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($primes < $odd) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($primes <= $odd) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (!($primes > $odd)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (!($primes >= $odd)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($odd > $primes) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($odd >= $primes) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (!($odd < $primes)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (!($odd <= $primes)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp = $primes * $odd; if ($temp == $primes) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp = $primes + $odd; if ($temp == $odd) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp = $primes ^ $odd; $xor = $primes->new($limit+1); if (! $xor) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $xor->ExclusiveOr($primes,$odd); if ($xor) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($temp == $xor) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($temp->equal($xor)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (23 < $primes) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (23 <= $primes) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (!(23 > $primes)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (!(23 >= $primes)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($primes > 23) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($primes >= 23) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (!($primes < 23)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (!($primes <= 23)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp = ($primes + $odd) - ($primes * $odd); if ($temp == $xor) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($temp->equal($xor)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $even = $xor; $even->Empty(); for ( $i = 0; $i <= $limit; $i += 2 ) { $even += $i; } if (($primes * $even) == 2) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (($odd * $even) == 2) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $full = $temp; $full->Fill(); if (($odd + $even) == $full) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (($primes + $even) == ~($odd - $primes)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (($primes + $even) == ~($odd * ~$primes)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set = Bit::Vector->new(500); if (abs($set) == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Min() >= 500) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Max() < 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; unless ($set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (++$set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (abs($set) == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Min() == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Max() == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (++$set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (abs($set) == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Min() == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Max() == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (++$set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (abs($set) == 2) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Min() == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Max() == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (--$set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (abs($set) == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Min() == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Max() == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (--$set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (abs($set) == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Min() == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Max() == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; unless (--$set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (abs($set) == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Min() >= 500) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Max() < 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; unless ($set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (--$set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (abs($set) == 500) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Min() == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Max() == 499) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; unless (++$set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (abs($set) == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Min() >= 500) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Max() < 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; unless ($set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set->Empty(); unless ($set++) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set->Empty(); if (++$set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set->Empty(); unless ($set--) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set->Empty(); if (--$set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set->Empty(); if (($set++)->Norm() == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set->Empty(); if ((++$set)->Norm() == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set->Empty(); if (($set--)->Norm() == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set->Empty(); if ((--$set)->Norm() == 500) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (($primes cmp $odd) == -1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (($odd cmp $primes) == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ((($odd + $even) cmp $full) == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ((($odd * $even) cmp 2) == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ((2 cmp ($odd * $even)) == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (($odd ^= 2) == ($full - $even)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # systematic tests: $temp = $odd + $even; if ($temp == $full) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp->Copy($odd); if ($temp == $odd) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp += $even; if ($temp == $full) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp = $odd + 2; if (abs($temp) == abs($odd) + 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp->Copy($odd); $temp += 4; if (abs($temp) == abs($odd) + 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp = $odd | $even; if ($temp == $full) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp->Copy($odd); if ($temp == $odd) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp |= $even; if ($temp == $full) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp = $odd | 2; if (abs($temp) == abs($odd) + 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp->Copy($odd); $temp |= 4; if (abs($temp) == abs($odd) + 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp = $full - $even; if ($temp == $odd) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $empty = $temp->new($limit+1); $temp -= $odd; if ($temp == $empty) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp = $even - 2; if (abs($temp) == abs($even) - 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp->Copy($even); if ($temp == $even) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp -= 8; if (abs($temp) == abs($even) - 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp = $primes * $even; if ($temp == 2) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp->Copy($primes); if ($temp == $primes) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp *= $even; if ($temp == 2) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp = $primes * 2; if ($temp == 2) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp->Copy($primes); $temp *= 2; if ($temp == 2) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp = $primes & $even; if ($temp == 2) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp->Copy($primes); if ($temp == $primes) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp &= $even; if ($temp == 2) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp = $primes & 2; if ($temp == 2) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp->Copy($primes); $temp &= 2; if ($temp == 2) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp = $odd ^ $even; if ($temp == $full) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp->Copy($odd); if ($temp == $odd) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp ^= $even; if ($temp == $full) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp = $odd ^ 2; if (abs($temp) == abs($odd) + 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp->Copy($odd); $temp ^= 4; if (abs($temp) == abs($odd) + 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (($odd cmp $even) == -1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (($even cmp $odd) == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $temp ^= 4; if ($temp == $odd) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (($temp cmp $odd) == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (($odd cmp $temp) == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($odd eq $temp) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (!($odd ne $temp)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (!($primes eq $odd)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($primes ne $odd) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($odd lt $even) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($odd le $even) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (!($even lt $odd)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (!($even le $odd)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (!($odd gt $even)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (!($odd ge $even)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($even gt $odd) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($even ge $odd) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # wrong parameter checks: $set = Bit::Vector->new(500); if ($set->Norm() == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set->Fill(); if ($set->Norm() == 500) {print "ok $n\n";} else {print "not ok $n\n";} $n++; foreach $operator (keys %operator_list) { $parms = $operator_list{$operator}; $obj = 0x000E9CE0; $fake = \$obj; if (ref($fake) eq 'SCALAR') {print "ok $n\n";} else {print "not ok $n\n";} $n++; &test_fake($parms); $fake = [ ]; if (ref($fake) eq 'ARRAY') {print "ok $n\n";} else {print "not ok $n\n";} $n++; &test_fake($parms); $fake = { }; if (ref($fake) eq 'HASH') {print "ok $n\n";} else {print "not ok $n\n";} $n++; &test_fake($parms); $fake = sub { }; if (ref($fake) eq 'CODE') {print "ok $n\n";} else {print "not ok $n\n";} $n++; &test_fake($parms); $obj = { }; $fake = \$obj; if (ref($fake) eq 'REF') {print "ok $n\n";} else {print "not ok $n\n";} $n++; &test_fake($parms); } # bit shift operator tests: foreach $bits (0,1,2,3,4,16,32,61,97,256,257,499,512) { $shift = ($primes << $bits); &verify($bits); $shift = $primes->Clone(); $shift <<= $bits; &verify($bits); $shift = ($primes >> $bits); &verify(-$bits); $shift = $primes->Clone(); $shift >>= $bits; &verify(-$bits); } eval { $shift = (0 << $primes); }; if ($@ =~ /\billegal reversed operands in overloaded '<<' operator\b/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $shift = (1 << $primes); }; if ($@ =~ /\billegal reversed operands in overloaded '<<' operator\b/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $shift = (0 >> $primes); }; if ($@ =~ /\billegal reversed operands in overloaded '>>' operator\b/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $shift = (1 >> $primes); }; if ($@ =~ /\billegal reversed operands in overloaded '>>' operator\b/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $shift = (0 x $primes); }; if ($@ =~ /\billegal reversed operands in overloaded 'x' operator\b/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $shift = (1 x $primes); }; if ($@ =~ /\billegal reversed operands in overloaded 'x' operator\b/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; exit; sub test_fake { my($parms) = @_; my($op,$message); $op = $operator; $op =~ s/^[a-wyz]+$/cmp/; $message = quotemeta("illegal operand type in overloaded '$op' operator"); if ($parms == 1) { $action = "\$set $operator \$fake"; eval "$action"; if ($@ =~ /$message/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } elsif ($parms == 2) { $action = "\$temp = \$set $operator \$fake"; eval "$action"; if ($@ =~ /$message/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $action = "\$temp = \$fake $operator \$set"; eval "$action"; if ($@ =~ /$message/) {print "ok $n\n";} else {print "not ok $n)\n";} $n++; } else { } } sub verify { my($offset) = @_; my($i,$j); for ( $i = 0; $i <= $limit; $i++ ) { if ($primes->contains($i)) { $j = $i + $offset; if (($j >= 0) && ($j <= $limit)) { if ($shift->contains($j)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } } if ($shift->contains($i)) { $j = $i - $offset; if (($j >= 0) && ($j <= $limit)) { if ($primes->contains($j)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } } } } __END__ Bit-Vector-7.4/t/10___intervals.t000644 100660 100660 00000020377 12211373040 015653 0ustar00sbsb000000 000000 #!perl -w use strict; no strict "vars"; use Bit::Vector; # ====================================================================== # $set->Interval_Empty($lower,$upper); # $set->Interval_Fill($lower,$upper); # $set->Interval_Flip($lower,$upper); # $set->Interval_Reverse($lower,$upper); # ($min,$max) = $set->Interval_Scan_inc($start); # ($min,$max) = $set->Interval_Scan_dec($start); # ====================================================================== print "1..4024\n"; $lim = 32768; $n = 1; $set = new Bit::Vector($lim); $rev = new Bit::Vector($lim); $rev->Primes(); $vec = $rev->Clone(); $primes = $rev->Norm(); if ($rev->equal($vec)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Norm() == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Min() > $lim) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Max() < -$lim) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set->Fill(); if ($set->Norm() == $lim) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Min() == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Max() == $lim-1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set->Empty(); if ($set->Norm() == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Min() > $lim) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Max() < -$lim) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set->Complement($set); if ($set->Norm() == $lim) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Min() == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Max() == $lim-1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set->Flip(); if ($set->Norm() == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Min() > $lim) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Max() < -$lim) {print "ok $n\n";} else {print "not ok $n\n";} $n++; test_set_clr(1,14); test_flip(1,14); test_rev(1,14); test_set_clr(1,30); test_flip(1,30); test_rev(1,30); test_set_clr(1,62); test_flip(1,62); test_rev(1,62); test_set_clr(1,126); test_flip(1,126); test_rev(1,126); test_set_clr(1,254); test_flip(1,254); test_rev(1,254); test_set_clr(1,$lim-2); test_flip(1,$lim-2); test_rev(1,$lim-2); test_set_clr(0,14); test_flip(0,14); test_rev(0,14); test_set_clr(0,30); test_flip(0,30); test_rev(0,30); test_set_clr(0,62); test_flip(0,62); test_rev(0,62); test_set_clr(0,126); test_flip(0,126); test_rev(0,126); test_set_clr(0,254); test_flip(0,254); test_rev(0,254); test_set_clr(0,$lim-2); test_flip(0,$lim-2); test_rev(0,$lim-2); test_set_clr(1,15); test_flip(1,15); test_rev(1,15); test_set_clr(1,31); test_flip(1,31); test_rev(1,31); test_set_clr(1,63); test_flip(1,63); test_rev(1,63); test_set_clr(1,127); test_flip(1,127); test_rev(1,127); test_set_clr(1,255); test_flip(1,255); test_rev(1,255); test_set_clr(1,$lim-1); test_flip(1,$lim-1); test_rev(1,$lim-1); test_set_clr(0,15); test_flip(0,15); test_rev(0,15); test_set_clr(0,31); test_flip(0,31); test_rev(0,31); test_set_clr(0,63); test_flip(0,63); test_rev(0,63); test_set_clr(0,127); test_flip(0,127); test_rev(0,127); test_set_clr(0,255); test_flip(0,255); test_rev(0,255); test_set_clr(0,$lim-1); test_flip(0,$lim-1); test_rev(0,$lim-1); for ( $i = 0; $i < 256; $i++ ) { test_set_clr($i,$i); test_flip($i,$i); } eval { $set->Interval_Empty(-1,$lim-1); }; if ($@ =~ /[^:]+::[^:]+::Interval_Empty\(\): minimum index out of range/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set->Interval_Fill(-1,$lim-1); }; if ($@ =~ /[^:]+::[^:]+::Interval_Fill\(\): minimum index out of range/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set->Interval_Flip(-1,$lim-1); }; if ($@ =~ /[^:]+::[^:]+::Interval_Flip\(\): minimum index out of range/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set->Interval_Reverse(-1,$lim-1); }; if ($@ =~ /[^:]+::[^:]+::Interval_Reverse\(\): minimum index out of range/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set->Interval_Empty(0,-1); }; if ($@ =~ /[^:]+::[^:]+::Interval_Empty\(\): maximum index out of range/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set->Interval_Fill(0,-1); }; if ($@ =~ /[^:]+::[^:]+::Interval_Fill\(\): maximum index out of range/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set->Interval_Flip(0,-1); }; if ($@ =~ /[^:]+::[^:]+::Interval_Flip\(\): maximum index out of range/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set->Interval_Reverse(0,-1); }; if ($@ =~ /[^:]+::[^:]+::Interval_Reverse\(\): maximum index out of range/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set->Interval_Empty(1,0); }; if ($@ =~ /[^:]+::[^:]+::Interval_Empty\(\): minimum > maximum index/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set->Interval_Fill(1,0); }; if ($@ =~ /[^:]+::[^:]+::Interval_Fill\(\): minimum > maximum index/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set->Interval_Flip(1,0); }; if ($@ =~ /[^:]+::[^:]+::Interval_Flip\(\): minimum > maximum index/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set->Interval_Reverse(1,0); }; if ($@ =~ /[^:]+::[^:]+::Interval_Reverse\(\): minimum > maximum index/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { ($min,$max) = $set->Interval_Scan_inc($lim); }; if ($@ =~ /[^:]+::[^:]+::Interval_Scan_inc\(\): start index out of range/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { ($min,$max) = $set->Interval_Scan_inc(-1); }; if ($@ =~ /[^:]+::[^:]+::Interval_Scan_inc\(\): start index out of range/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { ($min,$max) = $set->Interval_Scan_dec($lim); }; if ($@ =~ /[^:]+::[^:]+::Interval_Scan_dec\(\): start index out of range/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { ($min,$max) = $set->Interval_Scan_dec(-1); }; if ($@ =~ /[^:]+::[^:]+::Interval_Scan_dec\(\): start index out of range/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; exit; sub test_set_clr { my($lower,$upper) = @_; my($span) = $upper - $lower + 1; $set->Interval_Fill($lower,$upper); if ($set->Norm() == $span) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (($min,$max) = $set->Interval_Scan_inc(0)) {print "ok $n\n";} else {print "not ok $n\n"; $min = $set->Min(); $max = $set->Max(); } $n++; if ($min == $lower) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($max == $upper) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set->Interval_Empty($lower,$upper); if ($set->Norm() == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Min() > $lim) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Max() < -$lim) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } sub test_flip { my($lower,$upper) = @_; my($span) = $upper - $lower + 1; $set->Interval_Flip($lower,$upper); if ($set->Norm() == $span) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (($min,$max) = $set->Interval_Scan_dec($set->Size()-1)) {print "ok $n\n";} else {print "not ok $n\n"; $min = $set->Min(); $max = $set->Max(); } $n++; if ($min == $lower) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($max == $upper) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set->Interval_Flip($lower,$upper); if ($set->Norm() == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Min() > $lim) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Max() < -$lim) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } sub test_rev { my($lower,$upper) = @_; $rev->Interval_Reverse($lower,$upper); if ($rev->Norm() == $primes) {print "ok $n\n";} else {print "not ok $n\n";} $n++; unless ($rev->equal($vec)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $rev->Interval_Reverse($lower,$upper); if ($rev->equal($vec)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } __END__ Bit-Vector-7.4/t/50_freeze_thaw.t000644 100660 100660 00000032145 12211373040 015651 0ustar00sbsb000000 000000 #!perl -w use strict; no strict "vars"; eval { require Storable; *freeze = \&Storable::freeze; *nfreeze = \&Storable::nfreeze; *thaw = \&Storable::thaw; *dclone = \&Storable::dclone; }; if ($@ or $Storable::VERSION < 2.21) { print "1..0 # skip module Storable 2.21 or newer not found (we have $Storable::VERSION)\n"; exit 0; } require Bit::Vector; # ====================================================================== # Determine the size of the nested data structure to be tested in the second part: $length = 20; # Create a set of numbers which will represent vector lengths to be tested: $limit = 4096; $set = Bit::Vector->new($limit); $set->Primes(); # Initialize the set with prime numbers (pseudo-random) $set->Bit_On(0); # Also test special cases with vectors of 0 and 1 bits length $set->Bit_On(1); for ( $i = 4; $i-1 < $limit; $i <<= 1 ) # Also test special cases of multiples of two and +/- 1 { $set->Bit_On($i-1) if ($i-1 < $limit); $set->Bit_On($i) if ($i < $limit); $set->Bit_On($i+1) if ($i+1 < $limit); } $tests = (24 * $set->Norm()) + (69 * $length) - 14; # Determine number of test cases print "1..$tests\n"; $n = 1; $start = 0; while (($start < $set->Size()) && (($min,$max) = $set->Interval_Scan_inc($start))) { $start = $max + 2; for ( $bits = $min; $bits <= $max; $bits++ ) { $vector = Bit::Vector->new($bits); $vector->Primes(); $twin = thaw(freeze($vector)); if (ref($twin) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} # 01 $n++; if ($twin->Size() == $bits) {print "ok $n\n";} else {print "not ok $n\n";} # 02 $n++; if (${$vector} != ${$twin}) {print "ok $n\n";} else {print "not ok $n\n";} # 03 $n++; if ($vector->equal($twin)) {print "ok $n\n";} else {print "not ok $n\n";} # 04 $n++; $clone = dclone($vector); if (ref($clone) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} # 05 $n++; if ($clone->Size() == $bits) {print "ok $n\n";} else {print "not ok $n\n";} # 06 $n++; if (${$vector} != ${$clone}) {print "ok $n\n";} else {print "not ok $n\n";} # 07 $n++; if ($vector->equal($clone)) {print "ok $n\n";} else {print "not ok $n\n";} # 08 $n++; if (${$twin} != ${$clone}) {print "ok $n\n";} else {print "not ok $n\n";} # 09 $n++; if ($twin->equal($clone)) {print "ok $n\n";} else {print "not ok $n\n";} # 10 $n++; if ($bits > 0) { $vector->Flip(); $twin = thaw(nfreeze($vector)); if (ref($twin) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} # 11 $n++; if ($twin->Size() == $bits) {print "ok $n\n";} else {print "not ok $n\n";} # 12 $n++; if (${$vector} != ${$twin}) {print "ok $n\n";} else {print "not ok $n\n";} # 13 $n++; if ($vector->equal($twin)) {print "ok $n\n";} else {print "not ok $n\n";} # 14 $n++; if (${$twin} != ${$clone}) {print "ok $n\n";} else {print "not ok $n\n";} # 15 $n++; unless ($twin->equal($clone)) {print "ok $n\n";} else {print "not ok $n\n";} # 16 $n++; $twin->Flip(); if ($twin->equal($clone)) {print "ok $n\n";} else {print "not ok $n\n";} # 17 $n++; $clone = dclone($vector); if (ref($clone) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} # 18 $n++; if ($clone->Size() == $bits) {print "ok $n\n";} else {print "not ok $n\n";} # 19 $n++; if (${$vector} != ${$clone}) {print "ok $n\n";} else {print "not ok $n\n";} # 20 $n++; if ($vector->equal($clone)) {print "ok $n\n";} else {print "not ok $n\n";} # 21 $n++; if (${$twin} != ${$clone}) {print "ok $n\n";} else {print "not ok $n\n";} # 22 $n++; unless ($twin->equal($clone)) {print "ok $n\n";} else {print "not ok $n\n";} # 23 $n++; $twin->Flip(); if ($twin->equal($clone)) {print "ok $n\n";} else {print "not ok $n\n";} # 24 $n++; } } } $i = 0; $table = []; $vector->Primes(); $start = $vector->Size() - 1; while (($start >= 0) && ($i < $length) && (($min,$max) = $vector->Interval_Scan_dec($start))) { $start = $min - 2; for ( $bits = $max; ($bits >= $min) && ($i < $length); $bits-- ) { $temp = Bit::Vector->new($bits); $temp->Primes(); $temp->Flip() if ($i & 1); $table->[$i][0] = $temp; $table->[$i][1] = $temp->Clone(); $table->[$i][2] = $temp; $i++; } } $twin = thaw(freeze( $table )); $clone = dclone( $table ); for ( $i = 0; $i < $length; $i++ ) { if (ref($twin->[$i][0]) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} # 01 $n++; if (ref($twin->[$i][1]) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} # 02 $n++; if (ref($twin->[$i][2]) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} # 03 $n++; if (ref($clone->[$i][0]) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} # 04 $n++; if (ref($clone->[$i][1]) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} # 05 $n++; if (ref($clone->[$i][2]) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} # 06 $n++; ##################################################### if ($twin->[$i][0]->Size() == $table->[$i][0]->Size()) {print "ok $n\n";} else {print "not ok $n\n";} # 07 $n++; if ($twin->[$i][1]->Size() == $table->[$i][1]->Size()) {print "ok $n\n";} else {print "not ok $n\n";} # 08 $n++; if ($twin->[$i][2]->Size() == $table->[$i][2]->Size()) {print "ok $n\n";} else {print "not ok $n\n";} # 09 $n++; if ($twin->[$i][0]->equal( $table->[$i][0] )) {print "ok $n\n";} else {print "not ok $n\n";} # 10 $n++; if ($twin->[$i][1]->equal( $table->[$i][1] )) {print "ok $n\n";} else {print "not ok $n\n";} # 11 $n++; if ($twin->[$i][2]->equal( $table->[$i][2] )) {print "ok $n\n";} else {print "not ok $n\n";} # 12 $n++; if ($twin->[$i][0]->Size() == $twin->[$i][1]->Size()) {print "ok $n\n";} else {print "not ok $n\n";} # 13 $n++; if ($twin->[$i][1]->Size() == $twin->[$i][2]->Size()) {print "ok $n\n";} else {print "not ok $n\n";} # 14 $n++; if ($twin->[$i][2]->Size() == $twin->[$i][0]->Size()) {print "ok $n\n";} else {print "not ok $n\n";} # 15 $n++; if ($twin->[$i][0]->equal( $twin->[$i][1] )) {print "ok $n\n";} else {print "not ok $n\n";} # 16 $n++; if ($twin->[$i][1]->equal( $twin->[$i][2] )) {print "ok $n\n";} else {print "not ok $n\n";} # 17 $n++; if ($twin->[$i][2]->equal( $twin->[$i][0] )) {print "ok $n\n";} else {print "not ok $n\n";} # 18 $n++; if (${$twin->[$i][0]} != ${$table->[$i][0]}) {print "ok $n\n";} else {print "not ok $n\n";} # 19 $n++; if (${$twin->[$i][1]} != ${$table->[$i][0]}) {print "ok $n\n";} else {print "not ok $n\n";} # 20 $n++; if (${$twin->[$i][2]} != ${$table->[$i][0]}) {print "ok $n\n";} else {print "not ok $n\n";} # 21 $n++; if (${$twin->[$i][0]} != ${$table->[$i][1]}) {print "ok $n\n";} else {print "not ok $n\n";} # 22 $n++; if (${$twin->[$i][1]} != ${$table->[$i][1]}) {print "ok $n\n";} else {print "not ok $n\n";} # 23 $n++; if (${$twin->[$i][2]} != ${$table->[$i][1]}) {print "ok $n\n";} else {print "not ok $n\n";} # 24 $n++; if (${$twin->[$i][0]} != ${$table->[$i][2]}) {print "ok $n\n";} else {print "not ok $n\n";} # 25 $n++; if (${$twin->[$i][1]} != ${$table->[$i][2]}) {print "ok $n\n";} else {print "not ok $n\n";} # 26 $n++; if (${$twin->[$i][2]} != ${$table->[$i][2]}) {print "ok $n\n";} else {print "not ok $n\n";} # 27 $n++; if ($twin->[$i][0] ne $twin->[$i][1]) {print "ok $n\n";} else {print "not ok $n\n";} # 28 $n++; if ($twin->[$i][1] ne $twin->[$i][2]) {print "ok $n\n";} else {print "not ok $n\n";} # 29 $n++; if ($twin->[$i][2] eq $twin->[$i][0]) {print "ok $n\n";} else {print "not ok $n\n";} # 30 $n++; if (${$twin->[$i][0]} != ${$twin->[$i][1]}) {print "ok $n\n";} else {print "not ok $n\n";} # 31 $n++; if (${$twin->[$i][1]} != ${$twin->[$i][2]}) {print "ok $n\n";} else {print "not ok $n\n";} # 32 $n++; if (${$twin->[$i][2]} == ${$twin->[$i][0]}) {print "ok $n\n";} else {print "not ok $n\n";} # 33 $n++; ##################################################### if ($clone->[$i][0]->Size() == $table->[$i][0]->Size()) {print "ok $n\n";} else {print "not ok $n\n";} # 34 $n++; if ($clone->[$i][1]->Size() == $table->[$i][1]->Size()) {print "ok $n\n";} else {print "not ok $n\n";} # 35 $n++; if ($clone->[$i][2]->Size() == $table->[$i][2]->Size()) {print "ok $n\n";} else {print "not ok $n\n";} # 36 $n++; if ($clone->[$i][0]->equal( $table->[$i][0] )) {print "ok $n\n";} else {print "not ok $n\n";} # 37 $n++; if ($clone->[$i][1]->equal( $table->[$i][1] )) {print "ok $n\n";} else {print "not ok $n\n";} # 38 $n++; if ($clone->[$i][2]->equal( $table->[$i][2] )) {print "ok $n\n";} else {print "not ok $n\n";} # 39 $n++; if ($clone->[$i][0]->Size() == $clone->[$i][1]->Size()) {print "ok $n\n";} else {print "not ok $n\n";} # 40 $n++; if ($clone->[$i][1]->Size() == $clone->[$i][2]->Size()) {print "ok $n\n";} else {print "not ok $n\n";} # 41 $n++; if ($clone->[$i][2]->Size() == $clone->[$i][0]->Size()) {print "ok $n\n";} else {print "not ok $n\n";} # 42 $n++; if ($clone->[$i][0]->equal( $clone->[$i][1] )) {print "ok $n\n";} else {print "not ok $n\n";} # 43 $n++; if ($clone->[$i][1]->equal( $clone->[$i][2] )) {print "ok $n\n";} else {print "not ok $n\n";} # 44 $n++; if ($clone->[$i][2]->equal( $clone->[$i][0] )) {print "ok $n\n";} else {print "not ok $n\n";} # 45 $n++; if (${$clone->[$i][0]} != ${$table->[$i][0]}) {print "ok $n\n";} else {print "not ok $n\n";} # 46 $n++; if (${$clone->[$i][1]} != ${$table->[$i][0]}) {print "ok $n\n";} else {print "not ok $n\n";} # 47 $n++; if (${$clone->[$i][2]} != ${$table->[$i][0]}) {print "ok $n\n";} else {print "not ok $n\n";} # 48 $n++; if (${$clone->[$i][0]} != ${$table->[$i][1]}) {print "ok $n\n";} else {print "not ok $n\n";} # 49 $n++; if (${$clone->[$i][1]} != ${$table->[$i][1]}) {print "ok $n\n";} else {print "not ok $n\n";} # 50 $n++; if (${$clone->[$i][2]} != ${$table->[$i][1]}) {print "ok $n\n";} else {print "not ok $n\n";} # 51 $n++; if (${$clone->[$i][0]} != ${$table->[$i][2]}) {print "ok $n\n";} else {print "not ok $n\n";} # 52 $n++; if (${$clone->[$i][1]} != ${$table->[$i][2]}) {print "ok $n\n";} else {print "not ok $n\n";} # 53 $n++; if (${$clone->[$i][2]} != ${$table->[$i][2]}) {print "ok $n\n";} else {print "not ok $n\n";} # 54 $n++; if ($clone->[$i][0] ne $clone->[$i][1]) {print "ok $n\n";} else {print "not ok $n\n";} # 55 $n++; if ($clone->[$i][1] ne $clone->[$i][2]) {print "ok $n\n";} else {print "not ok $n\n";} # 56 $n++; if ($clone->[$i][2] eq $clone->[$i][0]) {print "ok $n\n";} else {print "not ok $n\n";} # 57 $n++; if (${$clone->[$i][0]} != ${$clone->[$i][1]}) {print "ok $n\n";} else {print "not ok $n\n";} # 58 $n++; if (${$clone->[$i][1]} != ${$clone->[$i][2]}) {print "ok $n\n";} else {print "not ok $n\n";} # 59 $n++; if (${$clone->[$i][2]} == ${$clone->[$i][0]}) {print "ok $n\n";} else {print "not ok $n\n";} # 60 $n++; ##################################################### if (${$twin->[$i][0]} != ${$clone->[$i][0]}) {print "ok $n\n";} else {print "not ok $n\n";} # 61 $n++; if (${$twin->[$i][1]} != ${$clone->[$i][0]}) {print "ok $n\n";} else {print "not ok $n\n";} # 62 $n++; if (${$twin->[$i][2]} != ${$clone->[$i][0]}) {print "ok $n\n";} else {print "not ok $n\n";} # 63 $n++; if (${$twin->[$i][0]} != ${$clone->[$i][1]}) {print "ok $n\n";} else {print "not ok $n\n";} # 64 $n++; if (${$twin->[$i][1]} != ${$clone->[$i][1]}) {print "ok $n\n";} else {print "not ok $n\n";} # 65 $n++; if (${$twin->[$i][2]} != ${$clone->[$i][1]}) {print "ok $n\n";} else {print "not ok $n\n";} # 66 $n++; if (${$twin->[$i][0]} != ${$clone->[$i][2]}) {print "ok $n\n";} else {print "not ok $n\n";} # 67 $n++; if (${$twin->[$i][1]} != ${$clone->[$i][2]}) {print "ok $n\n";} else {print "not ok $n\n";} # 68 $n++; if (${$twin->[$i][2]} != ${$clone->[$i][2]}) {print "ok $n\n";} else {print "not ok $n\n";} # 69 $n++; } __END__ Bit-Vector-7.4/t/00_____version.t000644 100660 100660 00000004346 12211373040 015624 0ustar00sbsb000000 000000 #!perl -w use strict; no strict "vars"; $Bit::Vector::VERSION = 0; $Bit::Vector::Overload::VERSION = 0; $Bit::Vector::String::VERSION = 0; # ====================================================================== # $ver = $Bit::Vector::VERSION; # $ver = Bit::Vector::Version(); # $ver = Bit::Vector->Version(); # $bits = Bit::Vector::Word_Bits(); # $bits = Bit::Vector->Word_Bits(); # $bits = Bit::Vector::Long_Bits(); # $bits = Bit::Vector->Long_Bits(); # $ver = $Bit::Vector::String::VERSION; # $ver = $Bit::Vector::Overload::VERSION; # ====================================================================== print "1..15\n"; $n = 1; if ($Bit::Vector::VERSION eq "0") {print "ok $n\n";} else {print "not ok $n\n";} $n++; require Bit::Vector; if ($Bit::Vector::VERSION eq "7.4") {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (Bit::Vector::Version() eq "7.4") {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (Bit::Vector::Word_Bits() >= 32) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (Bit::Vector::Long_Bits() >= 32) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (Bit::Vector->Version() eq "7.4") {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (Bit::Vector->Word_Bits() >= 32) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (Bit::Vector->Long_Bits() >= 32) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { Bit::Vector->Version(0); }; if ($@ =~ /Usage: Bit::Vector->Version\(\)/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { Bit::Vector->Word_Bits(0); }; if ($@ =~ /Usage: Bit::Vector->Word_Bits\(\)/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { Bit::Vector->Long_Bits(0); }; if ($@ =~ /Usage: Bit::Vector->Long_Bits\(\)/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($Bit::Vector::Overload::VERSION eq "0") {print "ok $n\n";} else {print "not ok $n\n";} $n++; require Bit::Vector::Overload; if ($Bit::Vector::Overload::VERSION eq "7.4") {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($Bit::Vector::String::VERSION eq "0") {print "ok $n\n";} else {print "not ok $n\n";} $n++; require Bit::Vector::String; if ($Bit::Vector::String::VERSION eq "7.4") {print "ok $n\n";} else {print "not ok $n\n";} $n++; __END__ Bit-Vector-7.4/t/13___increment.t000644 100660 100660 00000004677 12211373040 015640 0ustar00sbsb000000 000000 #!perl -w use strict; no strict "vars"; use Bit::Vector; # ====================================================================== # $vector->increment(); # $vector->decrement(); # ====================================================================== print "1..5296\n"; $n = 1; $bits = 10; $limit = (1 << $bits) - 1; $k = 0; $test_vector = bitvector($bits,$k); for ( $i = 0; $i <= $limit; $i++ ) { if ($k++ == $limit) { $k = 0; } $ref_carry = ($test_vector->Norm() == $bits); $test_carry = $test_vector->increment(); if ($test_carry == $ref_carry) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $ref_vector = bitvector($bits,$k); if ($test_vector->equal($ref_vector)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } $k = $limit; $test_vector = bitvector($bits,$k); for ( $i = $limit; $i >= 0; $i-- ) { if ($k-- == 0) { $k = $limit; } $ref_carry = ($test_vector->Norm() == 0); $test_carry = $test_vector->decrement(); if ($test_carry == $ref_carry) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $ref_vector = bitvector($bits,$k); if ($test_vector->equal($ref_vector)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } $bits = 2000; $upper = 150; $lower = -150; $k = $lower; $test_vector = bitvector($bits,$k); while (++$k <= $upper) { $ref_carry = ($test_vector->Norm() == $bits); $test_carry = $test_vector->increment(); if ($test_carry == $ref_carry) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $ref_vector = bitvector($bits,$k); if ($test_vector->equal($ref_vector)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } $k = $upper; $test_vector = bitvector($bits,$k); while (--$k >= $lower) { $ref_carry = ($test_vector->Norm() == 0); $test_carry = $test_vector->decrement(); if ($test_carry == $ref_carry) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $ref_vector = bitvector($bits,$k); if ($test_vector->equal($ref_vector)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } exit; sub bitvector { my($bits,$value) = @_; my($vector,$bit); $vector = Bit::Vector->new($bits); if ($value < 0) { $value = -1 - $value; $vector->Fill(); } $bit = 0; while ($value) { if ($value & 1) { $vector->bit_flip($bit); } $value >>= 1; $bit++; } return($vector); } __END__ Bit-Vector-7.4/t/01_________new.t000644 100660 100660 00000023156 12211373040 015525 0ustar00sbsb000000 000000 #!perl -w use strict; no strict "vars"; use integer; use Bit::Vector; @ISA = qw(Bit::Vector); # ====================================================================== # $set = Bit::Vector::new('Bit::Vector',$elements); # ====================================================================== print "1..131\n"; $n = 1; # test if the constructor works at all: $set = Bit::Vector::new('Bit::Vector',1); if (defined $set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (ref($set) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$set} != 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # test if the constructor handles NULL pointers as expected: eval { $ref = Bit::Vector::new('Bit::Vector',0); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # test if the copy of an object reference works as expected: $ref = $set; if (defined $ref) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (ref($ref) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$ref} != 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$ref} == ${$set}) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # test the constructor with a large set (13,983,816 elements): $set = Bit::Vector::new('Bit::Vector',&binomial(49,6)); if (defined $set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (ref($set) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$set} != 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # are the two sets really distinct and set objects behaving as expected? if (${$ref} != ${$set}) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # are set objects behaving as expected, i.e. are they write-protected? eval { ${$set} = 0x00088850; }; if ($@ =~ /Modification of a read-only value attempted/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set = 0x00088850; if ($set == 559184) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { ${$ref} = 0x000E9CE0; }; if ($@ =~ /Modification of a read-only value attempted/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $ref = 0x000E9CE0; if ($ref == 957664) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # test various ways of calling the constructor: # 1: $set = Bit::Vector::new('Bit::Vector',1); # 2: $class = 'Bit::Vector'; $set = Bit::Vector::new($class,2); # 3: $set = new Bit::Vector(3); # 4: $set = Bit::Vector->new(4); # 5: $ref = $set->new(5); # 6: $set = $set->new(6); # (test case #1 has been handled above) # test case #2: $class = 'Bit::Vector'; $set = Bit::Vector::new($class,2); if (defined $set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (ref($set) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$set} != 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # test case #3: $ref = new Bit::Vector(3); if (defined $ref) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (ref($ref) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$ref} != 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # coherence test: if (${$ref} != ${$set}) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # test case #4: $set = Bit::Vector->new(4); if (defined $set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (ref($set) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$set} != 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # coherence test: if (${$ref} != ${$set}) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # prepare possibility for id check: $old = ${$set}; if (${$set} == $old) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # test case #5: $ref = $set->new(5); if (defined $ref) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (ref($ref) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$ref} != 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # coherence tests: if (defined $set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (ref($set) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$set} != 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$set} == $old) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$ref} != ${$set}) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # prepare exact copy of object reference: $ref = $set; if (defined $ref) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (ref($ref) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$ref} != 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$ref} == ${$set}) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$ref} == $old) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # test case #6 (pseudo auto-destruction test): $set = $set->new(6); if (defined $set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (ref($set) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$set} != 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # coherence tests: if (defined $ref) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (ref($ref) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$ref} != 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$ref} == $old) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$ref} != ${$set}) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # auto-destruction test: $set = $set->new(7); if (defined $set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (ref($set) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$set} != 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # coherence test: if (${$ref} != ${$set}) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # test weird ways of calling the constructor: eval { $set = Bit::Vector::new("",8); }; if (ref($set) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set = Bit::Vector::new('',9); }; if (ref($set) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set = Bit::Vector::new(undef,10); }; if (ref($set) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set = Bit::Vector::new(6502,11); }; if (ref($set) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set = Bit::Vector::new('main',12); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (defined $set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ( (ref($set) eq 'main') || (ref($set) eq 'Bit::Vector') ) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$set} != 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set = 0; }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set = Bit::Vector::new('nonsense',13); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (defined $set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ( (ref($set) eq 'nonsense') || (ref($set) eq 'Bit::Vector') ) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$set} != 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set = 0; }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set = new main(14); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (defined $set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ( (ref($set) eq 'main') || (ref($set) eq 'Bit::Vector') ) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$set} != 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set = 0; }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; @parameters = ( 'main', 15 ); eval { $set = Bit::Vector::new(@parameters); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (defined $set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ( (ref($set) eq 'main') || (ref($set) eq 'Bit::Vector') ) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$set} != 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set = 0; }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # test syntactically incorrect constructor calls: eval { $set = Bit::Vector::new(16); }; if ($@ =~ /Usage: new\(class,bits\[,count\]\)/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set = Bit::Vector::new('main'); }; if ($@ =~ /Usage: new\(class,bits\[,count\]\)/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set = Bit::Vector::new($set); }; if ($@ =~ /Usage: new\(class,bits\[,count\]\)/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set = Bit::Vector::new('main',17,1,0); }; if ($@ =~ /Usage: new\(class,bits\[,count\]\)/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set = Bit::Vector::Create($set,'main',18,0); }; if ($@ =~ /Usage: Create\(class,bits\[,count\]\)/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set = Bit::Vector::new($set,19,'main',0); }; if ($@ =~ /Usage: new\(class,bits\[,count\]\)/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; # test if size is correct: for ( $i = 1; $i <= 16; $i++ ) { $k = int(2 ** $i + 0.5); for ( $j = $k-1; $j <= $k+1; $j++ ) { $set = Bit::Vector->new($j); if ($set->Size() == $j) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } } exit; sub binomial { my($n,$k) = @_; my($prod) = 1; my($j) = 0; if (($n <= 0) || ($k <= 0) || ($n <= $k)) { return(1); } if ($k > $n - $k) { $k = $n - $k; } while ($j < $k) { $prod *= $n--; $prod /= ++$j; } return(int($prod + 0.5)); } __END__ Bit-Vector-7.4/t/14_______empty.t000644 100660 100660 00000003663 12211373040 015601 0ustar00sbsb000000 000000 #!perl -w use strict; no strict "vars"; use Bit::Vector; # ====================================================================== # $vec->is_empty(); # $vec->is_full(); # ====================================================================== print "1..40\n"; $n = 1; $vec = Bit::Vector->new(5000); if ($vec->is_empty()) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (!$vec->is_full()) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $vec->Flip(); if (!$vec->is_empty()) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($vec->is_full()) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $vec->Complement($vec); if ($vec->is_empty()) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (!$vec->is_full()) {print "ok $n\n";} else {print "not ok $n\n";} $n++; &Empty( 0); &Empty( 1); &Empty(4999); &Empty(4998); $vec->Fill(); if (!$vec->is_empty()) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($vec->is_full()) {print "ok $n\n";} else {print "not ok $n\n";} $n++; &Full( 0); &Full( 1); &Full(4999); &Full(4998); exit; sub Empty { my($bit) = @_; $vec->bit_flip($bit); if (!$vec->is_empty()) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (!$vec->is_full()) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $vec->bit_flip($bit); if ($vec->is_empty()) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (!$vec->is_full()) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } sub Full { my($bit) = @_; $vec->bit_flip($bit); if (!$vec->is_empty()) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (!$vec->is_full()) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $vec->bit_flip($bit); if (!$vec->is_empty()) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($vec->is_full()) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } __END__ Bit-Vector-7.4/t/51_file_nstore.t000644 100660 100660 00000016314 12211373040 015660 0ustar00sbsb000000 000000 #!perl -w use strict; no strict "vars"; $file = $0; #$file =~ s!^.*[/\\:]+!!; $file =~ s!\.+[^.]*$!!; $file .= '.tmp'; eval { require Storable; *store = \&Storable::store; *nstore = \&Storable::nstore; *retrieve = \&Storable::retrieve; }; if ($@ or $Storable::VERSION < 2.21) { print "1..0 # skip module Storable 2.21 or newer not found (we have $Storable::VERSION)\n"; exit 0; } unless (open(TMP, ">$file") and print(TMP "$file\n") and close(TMP) and unlink($file)) { print "1..0 # skip cannot write temporary file <$file>: $!\n"; exit 0; } require Bit::Vector; # ====================================================================== # Determine the size of the nested data structure to be tested in the second part: $length = 20; # Create a set of numbers which will represent vector lengths to be tested: $limit = 4096; $set = Bit::Vector->new($limit); $set->Primes(); # Initialize the set with prime numbers (pseudo-random) $set->Bit_On(0); # Also test special cases with vectors of 0 and 1 bits length $set->Bit_On(1); for ( $i = 4; $i-1 < $limit; $i <<= 1 ) # Also test special cases of multiples of two and +/- 1 { $set->Bit_On($i-1) if ($i-1 < $limit); $set->Bit_On($i) if ($i < $limit); $set->Bit_On($i+1) if ($i+1 < $limit); } $tests = (11 * $set->Norm()) + (30 * $length) - 7; # Determine number of test cases print "1..$tests\n"; $n = 1; $start = 0; while (($start < $set->Size()) && (($min,$max) = $set->Interval_Scan_inc($start))) { $start = $max + 2; for ( $bits = $min; $bits <= $max; $bits++ ) { $vector = Bit::Vector->new($bits); $vector->Primes(); store($vector,$file); $twin = retrieve($file); unlink($file); if (ref($twin) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} # 01 $n++; if ($twin->Size() == $bits) {print "ok $n\n";} else {print "not ok $n\n";} # 02 $n++; if (${$vector} != ${$twin}) {print "ok $n\n";} else {print "not ok $n\n";} # 03 $n++; if ($vector->equal($twin)) {print "ok $n\n";} else {print "not ok $n\n";} # 04 $n++; if ($bits > 0) { $vector->Flip(); nstore($vector,$file); $clone = retrieve($file); unlink($file); if (ref($clone) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} # 05 $n++; if ($clone->Size() == $bits) {print "ok $n\n";} else {print "not ok $n\n";} # 06 $n++; if (${$vector} != ${$clone}) {print "ok $n\n";} else {print "not ok $n\n";} # 07 $n++; if ($vector->equal($clone)) {print "ok $n\n";} else {print "not ok $n\n";} # 08 $n++; if (${$twin} != ${$clone}) {print "ok $n\n";} else {print "not ok $n\n";} # 09 $n++; unless ($twin->equal($clone)) {print "ok $n\n";} else {print "not ok $n\n";} # 10 $n++; $twin->Flip(); if ($twin->equal($clone)) {print "ok $n\n";} else {print "not ok $n\n";} # 11 $n++; } } } $i = 0; $table = []; $vector->Primes(); $start = $vector->Size() - 1; while (($start >= 0) && ($i < $length) && (($min,$max) = $vector->Interval_Scan_dec($start))) { $start = $min - 2; for ( $bits = $max; ($bits >= $min) && ($i < $length); $bits-- ) { $temp = Bit::Vector->new($bits); $temp->Primes(); $temp->Flip() if ($i & 1); $table->[$i][0] = $temp; $table->[$i][1] = $temp->Clone(); $table->[$i][2] = $temp; $i++; } } nstore($table,$file); $twin = retrieve($file); unlink($file); for ( $i = 0; $i < $length; $i++ ) { if (ref($twin->[$i][0]) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} # 01 $n++; if (ref($twin->[$i][1]) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} # 02 $n++; if (ref($twin->[$i][2]) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} # 03 $n++; if ($twin->[$i][0]->Size() == $table->[$i][0]->Size()) {print "ok $n\n";} else {print "not ok $n\n";} # 04 $n++; if ($twin->[$i][1]->Size() == $table->[$i][1]->Size()) {print "ok $n\n";} else {print "not ok $n\n";} # 05 $n++; if ($twin->[$i][2]->Size() == $table->[$i][2]->Size()) {print "ok $n\n";} else {print "not ok $n\n";} # 06 $n++; if ($twin->[$i][0]->equal( $table->[$i][0] )) {print "ok $n\n";} else {print "not ok $n\n";} # 07 $n++; if ($twin->[$i][1]->equal( $table->[$i][1] )) {print "ok $n\n";} else {print "not ok $n\n";} # 08 $n++; if ($twin->[$i][2]->equal( $table->[$i][2] )) {print "ok $n\n";} else {print "not ok $n\n";} # 09 $n++; if ($twin->[$i][0]->Size() == $twin->[$i][1]->Size()) {print "ok $n\n";} else {print "not ok $n\n";} # 10 $n++; if ($twin->[$i][1]->Size() == $twin->[$i][2]->Size()) {print "ok $n\n";} else {print "not ok $n\n";} # 11 $n++; if ($twin->[$i][2]->Size() == $twin->[$i][0]->Size()) {print "ok $n\n";} else {print "not ok $n\n";} # 12 $n++; if ($twin->[$i][0]->equal( $twin->[$i][1] )) {print "ok $n\n";} else {print "not ok $n\n";} # 13 $n++; if ($twin->[$i][1]->equal( $twin->[$i][2] )) {print "ok $n\n";} else {print "not ok $n\n";} # 14 $n++; if ($twin->[$i][2]->equal( $twin->[$i][0] )) {print "ok $n\n";} else {print "not ok $n\n";} # 15 $n++; if (${$twin->[$i][0]} != ${$table->[$i][0]}) {print "ok $n\n";} else {print "not ok $n\n";} # 16 $n++; if (${$twin->[$i][1]} != ${$table->[$i][0]}) {print "ok $n\n";} else {print "not ok $n\n";} # 17 $n++; if (${$twin->[$i][2]} != ${$table->[$i][0]}) {print "ok $n\n";} else {print "not ok $n\n";} # 18 $n++; if (${$twin->[$i][0]} != ${$table->[$i][1]}) {print "ok $n\n";} else {print "not ok $n\n";} # 19 $n++; if (${$twin->[$i][1]} != ${$table->[$i][1]}) {print "ok $n\n";} else {print "not ok $n\n";} # 20 $n++; if (${$twin->[$i][2]} != ${$table->[$i][1]}) {print "ok $n\n";} else {print "not ok $n\n";} # 21 $n++; if (${$twin->[$i][0]} != ${$table->[$i][2]}) {print "ok $n\n";} else {print "not ok $n\n";} # 22 $n++; if (${$twin->[$i][1]} != ${$table->[$i][2]}) {print "ok $n\n";} else {print "not ok $n\n";} # 23 $n++; if (${$twin->[$i][2]} != ${$table->[$i][2]}) {print "ok $n\n";} else {print "not ok $n\n";} # 24 $n++; if ($twin->[$i][0] ne $twin->[$i][1]) {print "ok $n\n";} else {print "not ok $n\n";} # 25 $n++; if ($twin->[$i][1] ne $twin->[$i][2]) {print "ok $n\n";} else {print "not ok $n\n";} # 26 $n++; if ($twin->[$i][2] eq $twin->[$i][0]) {print "ok $n\n";} else {print "not ok $n\n";} # 27 $n++; if (${$twin->[$i][0]} != ${$twin->[$i][1]}) {print "ok $n\n";} else {print "not ok $n\n";} # 28 $n++; if (${$twin->[$i][1]} != ${$twin->[$i][2]}) {print "ok $n\n";} else {print "not ok $n\n";} # 29 $n++; if (${$twin->[$i][2]} == ${$twin->[$i][0]}) {print "ok $n\n";} else {print "not ok $n\n";} # 30 $n++; } __END__ Bit-Vector-7.4/t/08______resize.t000644 100660 100660 00000013232 12211373040 015601 0ustar00sbsb000000 000000 #!perl -w use strict; no strict "vars"; use Bit::Vector; # ====================================================================== # $set->Resize($elements); # ====================================================================== print "1..57\n"; $n = 1; $set = Bit::Vector->new(1); if (defined $set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (ref($set) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$set} != 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { ${$set} = 0; }; if ($@ =~ /Modification of a read-only value attempted/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set->Resize(0); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (ref($set) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$set} != 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { ${$set} = 1; }; if ($@ =~ /Modification of a read-only value attempted/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set = Bit::Vector->new(8); if (defined $set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (ref($set) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$set} != 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $old = ${$set}; if (${$set} == $old) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set->Resize(65536); if (defined $set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (ref($set) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$set} != 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$set} != $old) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $old = ${$set}; if (${$set} == $old) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Size() == 65536) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set->Resize(4090); if (defined $set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (ref($set) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$set} != 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$set} == $old) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Size() == 4090) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set->Resize(4096); if (defined $set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (ref($set) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$set} != 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$set} == $old) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Size() == 4096) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set->Resize(&binomial(49,6)); if (defined $set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (ref($set) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$set} != 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$set} != $old) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $old = ${$set}; if (${$set} == $old) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Size() == &binomial(49,6)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $limit = 65536; $count = 24; $set->Resize($limit); if (defined $set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (ref($set) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$set} != 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$set} == $old) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Size() == $limit) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $inv = Bit::Vector->new($limit); $inv->Fill(); $set->Bit_On(0); $inv->Bit_Off(0); @fib = ( 0, 1 ); while (1) { $index = ( $fib[0] + $fib[1] ); $fib[0] = $fib[1]; $fib[1] = $index; last if $index >= $limit; $set->Bit_On($index); $inv->Bit_Off($index); } if ($set->Norm() == $count) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($limit - $inv->Norm() == $count) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set->Resize($limit * 2); if (defined $set) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (ref($set) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$set} != 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$set} != $old) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Size() == $limit * 2) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Norm() == $count) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $inv->Resize($limit * 2); if (defined $inv) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (ref($inv) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (${$inv} != 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($inv->Size() == $limit * 2) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($limit - $inv->Norm() == $count) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $inv->Complement($inv); if ($inv->Norm() == $limit + $count) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->inclusion($inv)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set->ExclusiveOr($inv,$set); if ($set->Norm() == $limit) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Min() == $limit) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set->Max() == (($limit * 2) - 1)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; exit; sub binomial { my($n,$k) = @_; my($prod) = 1; my($j) = 0; if (($n <= 0) || ($k <= 0) || ($n <= $k)) { return(1); } if ($k > $n - $k) { $k = $n - $k; } while ($j < $k) { $prod *= $n--; $prod /= ++$j; } return(int($prod + 0.5)); } __END__ Bit-Vector-7.4/t/40___auxiliary.t000644 100660 100660 00000020447 12211373040 015654 0ustar00sbsb000000 000000 #!perl -w use strict; no strict "vars"; use Bit::Vector::String; my @l = (31,32,33,127,128,129,1023,1024,1025); my($b,$i,$n,$r,$s,$t,$u,$v,$w,$x); print "1..", @l * 81, "\n"; $n = 1; # ------------------------------------------------------- foreach $b (@l) { $v = Bit::Vector->new($b); $w = Bit::Vector->new($b); for ( $i = 0; $i < 3; $i++ ) { if ($i == 0) { $v->Primes(); } elsif ($i == 1) { $v->Fill(); } else { $v->Empty(); for ( $x = 0; $x < $b; $x += 12 ) { $v->Bit_On($x); } if ($v->to_Oct() =~ /^[01]+$/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($v->to_Hex() =~ /^[01]+$/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } # ======================================================= $x = '$w->from_Oct( $s = $v->to_Oct() );'; $t = 2; $r = 'OCT'; $w->from_Oct( $s = $v->to_Oct() ); if ($v->equal($w)) {print "ok $n\n";} else {print "not ok $n\n";trace($b,$r,$s,$t,$v,$w,$x);} $n++; $x = '$t = $w->String_Import( $s = $v->String_Export( $r ) );'; $t = $w->String_Import( $s = $v->String_Export( $r = 'bin' ) ); if ($v->equal($w)) {print "ok $n\n";} else {print "not ok $n\n";trace($b,$r,$s,$t,$v,$w,$x);} $n++; $t = $w->String_Import( $s = $v->String_Export( $r = 'oct' ) ); if ($v->equal($w)) {print "ok $n\n";} else {print "not ok $n\n";trace($b,$r,$s,$t,$v,$w,$x);} $n++; $t = $w->String_Import( $s = $v->String_Export( $r = 'hex' ) ); if ($v->equal($w)) {print "ok $n\n";} else {print "not ok $n\n";trace($b,$r,$s,$t,$v,$w,$x);} $n++; $t = $w->String_Import( $s = $v->String_Export( $r = 'dec' ) ); if ($v->equal($w)) {print "ok $n\n";} else {print "not ok $n\n";trace($b,$r,$s,$t,$v,$w,$x);} $n++; $t = $w->String_Import( $s = $v->String_Export( $r = 'enum' ) ); if ($v->equal($w)) {print "ok $n\n";} else {print "not ok $n\n";trace($b,$r,$s,$t,$v,$w,$x);} $n++; $t = $w->String_Import( $s = $v->String_Export( $r = 'pack' ) ); if ($v->equal($w)) {print "ok $n\n";} else {print "not ok $n\n";trace($b,$r,$s,$t,$v,$w,$x);} $n++; # ======================================================= $x = '$t = $w->String_Import( $s = $v->to_Type() );'; $r = 'bin'; $t = $w->String_Import( $s = $v->to_Bin() ); if ($v->equal($w)) {print "ok $n\n";} else {print "not ok $n\n";trace($b,$r,$s,$t,$v,$w,$x);} $n++; if ($i < 2) { $r = 'oct'; $t = $w->String_Import( $s = $v->to_Oct() ); if ($v->equal($w)) {print "ok $n\n";} else {print "not ok $n\n";trace($b,$r,$s,$t,$v,$w,$x);} $n++; $r = 'hex'; $t = $w->String_Import( $s = $v->to_Hex() ); if ($v->equal($w)) {print "ok $n\n";} else {print "not ok $n\n";trace($b,$r,$s,$t,$v,$w,$x);} $n++; } $r = 'dec'; $t = $w->String_Import( $s = $v->to_Dec() ); if ($v->equal($w)) {print "ok $n\n";} else {print "not ok $n\n";trace($b,$r,$s,$t,$v,$w,$x);} $n++; $r = 'enum'; $t = $w->String_Import( $s = $v->to_Enum() ); if ($v->equal($w)) {print "ok $n\n";} else {print "not ok $n\n";trace($b,$r,$s,$t,$v,$w,$x);} $n++; $r = 'pack'; $t = $w->String_Import( $s = ':' . $v->Size(). ':' . $v->Block_Read() ); if ($v->equal($w)) {print "ok $n\n";} else {print "not ok $n\n";trace($b,$r,$s,$t,$v,$w,$x);} $n++; # ======================================================= $x = '$w = Bit::Vector->new_Oct( $b, $s = $v->to_Oct() );'; $t = 2; $r = 'OCT'; $w = Bit::Vector->new_Oct( $b, $s = $v->to_Oct() ); if ($v->equal($w)) {print "ok $n\n";} else {print "not ok $n\n";trace($b,$r,$s,$t,$v,$w,$x);} $n++; $x = '($w,$t) = Bit::Vector->new_String( $b, $s = $v->String_Export( $r ) );'; ($w,$t) = Bit::Vector->new_String( $b, $s = $v->String_Export( $r = 'bin' ) ); if ($v->equal($w)) {print "ok $n\n";} else {print "not ok $n\n";trace($b,$r,$s,$t,$v,$w,$x);} $n++; ($w,$t) = Bit::Vector->new_String( $b, $s = $v->String_Export( $r = 'oct' ) ); if ($v->equal($w)) {print "ok $n\n";} else {print "not ok $n\n";trace($b,$r,$s,$t,$v,$w,$x);} $n++; ($w,$t) = Bit::Vector->new_String( $b, $s = $v->String_Export( $r = 'hex' ) ); if ($v->equal($w)) {print "ok $n\n";} else {print "not ok $n\n";trace($b,$r,$s,$t,$v,$w,$x);} $n++; ($w,$t) = Bit::Vector->new_String( $b, $s = $v->String_Export( $r = 'dec' ) ); if ($v->equal($w)) {print "ok $n\n";} else {print "not ok $n\n";trace($b,$r,$s,$t,$v,$w,$x);} $n++; ($w,$t) = Bit::Vector->new_String( $b, $s = $v->String_Export( $r = 'enum' ) ); if ($v->equal($w)) {print "ok $n\n";} else {print "not ok $n\n";trace($b,$r,$s,$t,$v,$w,$x);} $n++; ($w,$t) = Bit::Vector->new_String( $b, $s = $v->String_Export( $r = 'pack' ) ); if ($v->equal($w)) {print "ok $n\n";} else {print "not ok $n\n";trace($b,$r,$s,$t,$v,$w,$x);} $n++; # ======================================================= $x = '$w = Bit::Vector->new_Oct( undef, $s = $v->to_Oct() );'; $t = 2; $r = 'OCT'; $w = Bit::Vector->new_Oct( undef, $s = $v->to_Oct() ); $w->Resize($b) if ($w->Size() != $b); if ($v->equal($w)) {print "ok $n\n";} else {print "not ok $n\n";trace($b,$r,$s,$t,$v,$w,$x);} $n++; $x = '($w,$t) = Bit::Vector->new_String( undef, $s = $v->String_Export( $r ) );'; ($w,$t) = Bit::Vector->new_String( undef, $s = $v->String_Export( $r = 'bin' ) ); $w->Resize($b) if ($w->Size() != $b); if ($v->equal($w)) {print "ok $n\n";} else {print "not ok $n\n";trace($b,$r,$s,$t,$v,$w,$x);} $n++; ($w,$t) = Bit::Vector->new_String( undef, $s = $v->String_Export( $r = 'oct' ) ); $w->Resize($b) if ($w->Size() != $b); if ($v->equal($w)) {print "ok $n\n";} else {print "not ok $n\n";trace($b,$r,$s,$t,$v,$w,$x);} $n++; ($w,$t) = Bit::Vector->new_String( undef, $s = $v->String_Export( $r = 'hex' ) ); $w->Resize($b) if ($w->Size() != $b); if ($v->equal($w)) {print "ok $n\n";} else {print "not ok $n\n";trace($b,$r,$s,$t,$v,$w,$x);} $n++; ($w,$t) = Bit::Vector->new_String( undef, $s = $v->String_Export( $r = 'dec' ) ); if ($w->Size() != $b) { if ($v->msb and $w->Size() < $b) # needs sign extension when increasing size { $u = $w; $w = Bit::Vector->new($b); $w->Copy($u); } else { $w->Resize($b); } } if ($v->equal($w)) {print "ok $n\n";} else {print "not ok $n\n";trace($b,$r,$s,$t,$v,$w,$x);} $n++; ($w,$t) = Bit::Vector->new_String( undef, $s = $v->String_Export( $r = 'enum' ) ); $w->Resize($b) if ($w->Size() != $b); if ($v->equal($w)) {print "ok $n\n";} else {print "not ok $n\n";trace($b,$r,$s,$t,$v,$w,$x);} $n++; ($w,$t) = Bit::Vector->new_String( undef, $s = $v->String_Export( $r = 'pack' ) ); $w->Resize($b) if ($w->Size() != $b); if ($v->equal($w)) {print "ok $n\n";} else {print "not ok $n\n";trace($b,$r,$s,$t,$v,$w,$x);} $n++; # ======================================================= } # for ( $i = 0; $i < 3; $i++ ) } # foreach $b (@l) # ------------------------------------------------------- sub type { return 'bin' if ($_[0] == 1); return 'oct' if ($_[0] == 2); return 'dec' if ($_[0] == 3); return 'hex' if ($_[0] == 4); return 'enum' if ($_[0] == 5); return 'pack' if ($_[0] == 6); return undef; } sub trace { my($b,$r,$s,$t,$v,$w,$x) = @_; warn( "$x\n" ); warn( "$r, $b bits\n" ); warn( type($t) . ": <$s>\n" ); warn( "v = <" . $v->to_Hex() . ">\n" ); warn( "w = <" . $w->to_Hex() . ">\n" ); } __END__ Bit-Vector-7.4/t/02_____destroy.t000644 100660 100660 00000003626 12211373040 015632 0ustar00sbsb000000 000000 #!perl -w use strict; no strict "vars"; use Bit::Vector; # ====================================================================== # $set->DESTROY(); # ====================================================================== print "1..15\n"; $n = 1; $set = 1; if (ref($set) eq '') {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set->DESTROY(); }; if (($@ =~ /Can't call method "DESTROY" without a package or object reference/) || ($@ =~ /Can't locate object method "DESTROY" via package "1"/)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { Bit::Vector::DESTROY($set); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $obj = 0x00088850; $set = \$obj; if (ref($set) eq 'SCALAR') {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set->DESTROY(); }; if ($@ =~ /Can't call method "DESTROY" on unblessed reference/) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { Bit::Vector::DESTROY($set); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $obj = 0x000E9CE0; $set = \$obj; bless($set, 'Bit::Vector'); if (ref($set) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set->DESTROY(); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { Bit::Vector::DESTROY($set); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $set = new Bit::Vector(1); if (ref($set) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set->DESTROY(); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (ref($set) eq 'Bit::Vector') {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (defined(${$set}) && (${$set} == 0)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set->DESTROY(); }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; eval { $set = 0; }; unless ($@) {print "ok $n\n";} else {print "not ok $n\n";} $n++; __END__ Bit-Vector-7.4/t/07_____compare.t000644 100660 100660 00000011467 12211373040 015576 0ustar00sbsb000000 000000 #!perl -w use strict; no strict "vars"; use Bit::Vector; # ====================================================================== # $set1->Compare($set2); # $set1->Lexicompare($set2); # ====================================================================== print "1..50\n"; $set0 = new Bit::Vector(65536); $set1 = new Bit::Vector(65536); $set2 = new Bit::Vector(65536); $set3 = new Bit::Vector(65536); $set4 = new Bit::Vector(65536); $set1->Bit_On(0); $set2->Bit_On(1); $set3->Fill(); $set3->Bit_Off(0); $set4->Fill(); $n = 1; if ($set0->Compare($set0) == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set0->Compare($set1) == -1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set0->Compare($set2) == -1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set0->Compare($set3) == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set0->Compare($set4) == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set1->Compare($set0) == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set1->Compare($set1) == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set1->Compare($set2) == -1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set1->Compare($set3) == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set1->Compare($set4) == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set2->Compare($set0) == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set2->Compare($set1) == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set2->Compare($set2) == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set2->Compare($set3) == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set2->Compare($set4) == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set3->Compare($set0) == -1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set3->Compare($set1) == -1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set3->Compare($set2) == -1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set3->Compare($set3) == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set3->Compare($set4) == -1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set4->Compare($set0) == -1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set4->Compare($set1) == -1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set4->Compare($set2) == -1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set4->Compare($set3) == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set4->Compare($set4) == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set0->Lexicompare($set0) == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set0->Lexicompare($set1) == -1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set0->Lexicompare($set2) == -1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set0->Lexicompare($set3) == -1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set0->Lexicompare($set4) == -1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set1->Lexicompare($set0) == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set1->Lexicompare($set1) == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set1->Lexicompare($set2) == -1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set1->Lexicompare($set3) == -1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set1->Lexicompare($set4) == -1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set2->Lexicompare($set0) == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set2->Lexicompare($set1) == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set2->Lexicompare($set2) == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set2->Lexicompare($set3) == -1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set2->Lexicompare($set4) == -1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set3->Lexicompare($set0) == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set3->Lexicompare($set1) == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set3->Lexicompare($set2) == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set3->Lexicompare($set3) == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set3->Lexicompare($set4) == -1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set4->Lexicompare($set0) == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set4->Lexicompare($set1) == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set4->Lexicompare($set2) == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set4->Lexicompare($set3) == 1) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($set4->Lexicompare($set4) == 0) {print "ok $n\n";} else {print "not ok $n\n";} $n++; __END__ Bit-Vector-7.4/t/11_______shift.t000644 100660 100660 00000013407 12211373040 015552 0ustar00sbsb000000 000000 #!perl -w use strict; no strict "vars"; use Bit::Vector::Overload; # ====================================================================== # $carry_out = $vector->rotate_left(); # $carry_out = $vector->rotate_right(); # $carry_out = $vector->shift_left($carry_in); # $carry_out = $vector->shift_right($carry_in); # $vector->Move_Left($bits); # $vector->Move_Right($bits); # ====================================================================== # $vec1 = $vec2->Shadow(); # $vec1 = $vec2->Clone(); # ====================================================================== print "1..36416\n"; $n = 1; foreach $limit (15,16,31,32,63,64,127,128,255,256,511,512,1023,1024) { $ref = Bit::Vector->new($limit); $ref->Fill(); $ref->Bit_Off(0); $ref->Bit_Off(1); for ( $j = 4; $j < $limit; $j += 2 ) { $ref->Bit_Off($j); } for ( $i = 3; ($j = $i * $i) < $limit; $i += 2 ) { for ( ; $j < $limit; $j += $i ) { $ref->Bit_Off($j); } } $rol = $ref->Clone(); $ror = $ref->Clone(); $shl = $ref->Clone(); $shr = $ref->Clone(); $crl = $rol->Shadow(); $crr = $ror->Shadow(); $csl = $shl->Shadow(); $csr = $shr->Shadow(); &test_rotat_reg_same(0); &test_shift_reg_same(0); &test_rotat_carry_same(1); &test_shift_carry_same(1); for ( $i = 0; $i < $limit; $i++ ) { $crl->shift_left ( $rol->rotate_left () ); $crr->shift_right( $ror->rotate_right() ); $csl->shift_left ( $shl->shift_left ( $shl->bit_test($limit-1) ) ); $csr->shift_right( $shr->shift_right ( $shr->bit_test(0) ) ); if (($i == 0) || ($i == ($limit-2))) { &test_rotat_reg_same(1); &test_shift_reg_same(1); &test_rotat_carry_same(1); &test_shift_carry_same(1); &test_rotat_reg_diff; &test_rotat_carry_diff if ($i); &test_shift_reg_diff; &test_shift_carry_diff if ($i); } } &test_rotat_reg_same(0); &test_shift_reg_same(0); &test_rotat_carry_same(0); &test_shift_carry_same(0); } $ref = Bit::Vector->new(1); $Minimum = $ref->Min(); $Maximum = $ref->Max(); if ($Minimum >= 32767) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($Maximum <= -32767) {print "ok $n\n";} else {print "not ok $n\n";} $n++; foreach $limit (15,16,31,32,63,64,127,128,1023,1024) { $ref = Bit::Vector->new($limit); for ( $bits = -2; $bits <= $limit + 1; $bits++ ) { $ref->Fill(); $vec = ($ref << $bits); $ref->Move_Left($bits); $norm_ = $limit - $bits; $min_ = $bits; $max_ = $limit - 1; if (($norm_ <= 0) || ($bits < 0)) { $norm_ = 0; $min_ = $Minimum; $max_ = $Maximum; } &verify; if ($vec->equal($ref)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $vec->Fill(); $vec <<= $bits; if ($vec->equal($ref)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $ref->Fill(); $vec = ($ref >> $bits); $ref->Move_Right($bits); $norm_ = $limit - $bits; $min_ = 0; $max_ = $limit - $bits - 1; if (($norm_ <= 0) || ($bits < 0)) { $norm_ = 0; $min_ = $Minimum; $max_ = $Maximum; } &verify; if ($vec->equal($ref)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; $vec->Fill(); $vec >>= $bits; if ($vec->equal($ref)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } } exit; sub test_rotat_reg_same { my($flag) = @_; if (($ref->equal($rol)) ^ $flag) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (($ref->equal($ror)) ^ $flag) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } sub test_shift_reg_same { my($flag) = @_; if (($ref->equal($shl)) ^ $flag) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (($ref->equal($shr)) ^ $flag) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } sub test_rotat_carry_same { my($flag) = @_; if (($ref->equal($crl)) ^ $flag) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (($ref->equal($crr)) ^ $flag) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } sub test_shift_carry_same { my($flag) = @_; if (($ref->equal($csl)) ^ $flag) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if (($ref->equal($csr)) ^ $flag) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } sub test_rotat_reg_diff { unless ($rol->equal($ror)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } sub test_rotat_carry_diff { unless ($crl->equal($crr)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } sub test_shift_reg_diff { unless ($shl->equal($shr)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } sub test_shift_carry_diff { unless ($csl->equal($csr)) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } sub verify { $norm = $ref->Norm(); if ($norm == $norm_) {print "ok $n\n";} else {print "not ok $n\n";} $n++; unless (($min,$max) = $ref->Interval_Scan_inc(0)) { $min = $ref->Min(); $max = $ref->Max(); } if ($min == $min_) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($max == $max_) {print "ok $n\n";} else {print "not ok $n\n";} $n++; unless (($min,$max) = $ref->Interval_Scan_dec($limit-1)) { $min = $ref->Min(); $max = $ref->Max(); } if ($min == $min_) {print "ok $n\n";} else {print "not ok $n\n";} $n++; if ($max == $max_) {print "ok $n\n";} else {print "not ok $n\n";} $n++; } __END__ Bit-Vector-7.4/lib/Bit/000755 100660 100660 00000000000 12211373041 013672 5ustar00sbsb000000 000000 Bit-Vector-7.4/lib/Bit/Vector/000755 100660 100660 00000000000 12211373041 015134 5ustar00sbsb000000 000000 Bit-Vector-7.4/lib/Bit/Vector/String.pm000644 100660 100660 00000015452 12211373040 016746 0ustar00sbsb000000 000000 ############################################################################### ## ## ## Copyright (c) 2004 - 2013 by Steffen Beyer. ## ## All rights reserved. ## ## ## ## This package is free software; you can redistribute it ## ## and/or modify it under the same terms as Perl itself. ## ## ## ############################################################################### package Bit::Vector::String; use strict; use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION); use Bit::Vector; require Exporter; @ISA = qw(Exporter Bit::Vector); @EXPORT = qw(); @EXPORT_OK = qw(); $VERSION = '7.4'; package Bit::Vector; use strict; use Carp::Clan '^Bit::Vector\b'; my $Factor = log(10) / log(2); sub to_Oct { croak('Usage: $vector->to_Oct();') unless (@_ == 1); my($self) = @_; my($string) = ''; local $@; eval { $string = reverse(join('', $self->Chunk_List_Read(3))); }; if ($@) { $string = $@; $string =~ s!^[A-Za-z0-9_]+(?:::[A-Za-z0-9_]+)*\(\):\s+!!; $string =~ s!\s+at\s.*$!!; croak($string); } return $string; } sub from_Oct { croak('Usage: $vector->from_Oct($string);') unless (@_ == 2); my($self,$string) = @_; local $@; if ($string =~ /^[0-7]+$/) { eval { $self->Chunk_List_Store(3, split(//, reverse($string))); }; if ($@) { $string = $@; $string =~ s!^[A-Za-z0-9_]+(?:::[A-Za-z0-9_]+)*\(\):\s+!!; $string =~ s!\s+at\s.*$!!; croak($string); } } else { croak("unknown string type"); } return $self; } sub new_Oct { croak('Usage: Bit::Vector->new_Oct($bits,$string);') unless (@_ == 3); my($class,$bits,$string) = @_; my($self); local $@; if ($string =~ /^[0-7]+$/) { unless (defined $bits) { $bits = 3 * length($string); } eval { $self = Bit::Vector->new($bits); $self->Chunk_List_Store(3, split(//, reverse($string))); }; if ($@) { $string = $@; $string =~ s!^[A-Za-z0-9_]+(?:::[A-Za-z0-9_]+)*\(\):\s+!!; $string =~ s!\s+at\s.*$!!; croak($string); } } else { croak("unknown string type"); } return $self; } sub String_Export { croak('Usage: $vector->String_Export($type);') unless (@_ == 1 or @_ == 2); my($self,$type) = @_; my($string) = ''; local $@; if (not defined $type or not $type) { eval { $string = '0x' . $self->to_Hex(); }; } elsif ($type eq '1' or $type =~ /^b(?:in)?$/i) { eval { $string = '0b' . $self->to_Bin(); }; } elsif ($type eq '2' or $type =~ /^o(?:ct)?$/i) { eval { $string = '0o' . reverse(join('', $self->Chunk_List_Read(3))); }; } elsif ($type eq '3' or $type =~ /^d(?:ec)?$/i) { eval { $string = $self->to_Dec(); }; } elsif ($type eq '4' or $type =~ /^(?:h(?:ex)?|x)$/i) { eval { $string = '0x' . $self->to_Hex(); }; } elsif ($type eq '5' or $type =~ /^e(?:num)?$/i) { eval { $string = '{' . $self->to_Enum() . '}'; }; } elsif ($type eq '6' or $type =~ /^p(?:ack)?$/i) { eval { $string = ':' . $self->Size() . ':' . $self->Block_Read(); }; } else { croak("unknown string type '$type'"); } if ($@) { $string = $@; $string =~ s!^[A-Za-z0-9_]+(?:::[A-Za-z0-9_]+)*\(\):\s+!!; $string =~ s!\s+at\s.*$!!; croak($string); } return $string; } sub String_Import { croak('Usage: $vector->String_Import($string);') unless (@_ == 2); my($self,$string) = @_; my($type) = 0; local $@; if ($string =~ /^(?:0[bB])?([01]+)$/) { $type = 1; eval { $self->from_Bin($1); }; } elsif ($string =~ /^(?:0[oO])?([0-7]+)$/) { $type = 2; eval { $self->Chunk_List_Store(3, split(//, reverse($1))); }; } elsif ($string =~ /^(?:[+-])?[0-9]+$/) { $type = 3; eval { $self->from_Dec($string); }; } elsif ($string =~ /^(?:0[hHxX])?([0-9A-Fa-f]+)$/) { $type = 4; eval { $self->from_Hex($1); }; } elsif ($string =~ /^[(<{\[]?([0-9]+(?:-[0-9]+)?(?:,[0-9]+(?:-[0-9]+)?)*)[)>}\]]?$/) { $type = 5; eval { $self->from_Enum($1); }; } elsif ($string =~ s!^:\d+:!!) { $type = 6; eval { $self->Block_Store($string); }; } else { croak("unknown string type"); } if ($@) { $string = $@; $string =~ s!^[A-Za-z0-9_]+(?:::[A-Za-z0-9_]+)*\(\):\s+!!; $string =~ s!\s+at\s.*$!!; croak($string); } return $type; } sub new_String { croak('Usage: Bit::Vector->new_String($bits,$string);') unless (@_ == 3); my($class,$bits,$string) = @_; my($type) = 0; my($self); local $@; if ($string =~ /^(?:0[bB])?([01]+)$/) { $type = 1; unless (defined $bits) { $bits = length($1); } eval { $self = Bit::Vector->new_Bin($bits,$1); }; } elsif ($string =~ /^(?:0[oO])?([0-7]+)$/) { $type = 2; unless (defined $bits) { $bits = 3 * length($1); } eval { $self = Bit::Vector->new($bits); $self->Chunk_List_Store(3, split(//, reverse($1))); }; } elsif ($string =~ /^(?:[+-])?([0-9]+)$/) { $type = 3; unless (defined $bits) { $bits = int( length($1) * $Factor + 1 ); } eval { $self = Bit::Vector->new_Dec($bits,$string); }; } elsif ($string =~ /^(?:0[hHxX])?([0-9A-Fa-f]+)$/) { $type = 4; unless (defined $bits) { $bits = 4 * length($1); } eval { $self = Bit::Vector->new_Hex($bits,$1); }; } elsif ($string =~ /^[(<{\[]?([0-9]+(?:-[0-9]+)?(?:,[0-9]+(?:-[0-9]+)?)*)[)>}\]]?$/) { $type = 5; $string = $1; unless (defined $bits) { $bits = 0; while ($string =~ /([0-9]+)/g) { $bits = $1 if ($1 > $bits); } $bits++; } eval { $self = Bit::Vector->new_Enum($bits,$string); }; } elsif ($string =~ s!^:(\d+):!!) { $type = 6; $bits = $1 unless (defined $bits); eval { $self = Bit::Vector->new($bits); $self->Block_Store($string); }; } else { croak("unknown string type"); } if ($@) { $string = $@; $string =~ s!^[A-Za-z0-9_]+(?:::[A-Za-z0-9_]+)*\(\):\s+!!; $string =~ s!\s+at\s.*$!!; croak($string); } if (wantarray) { return($self,$type); } return $self; } 1; __END__ Bit-Vector-7.4/lib/Bit/Vector/Overload.pm000644 100660 100660 00000065355 12211373040 017262 0ustar00sbsb000000 000000 ############################################################################### ## ## ## Copyright (c) 2000 - 2013 by Steffen Beyer. ## ## All rights reserved. ## ## ## ## This package is free software; you can redistribute it ## ## and/or modify it under the same terms as Perl itself. ## ## ## ############################################################################### package Bit::Vector::Overload; use strict; use vars qw(@ISA @EXPORT @EXPORT_OK $VERSION); use Bit::Vector; require Exporter; @ISA = qw(Exporter Bit::Vector); @EXPORT = qw(); @EXPORT_OK = qw(); $VERSION = '7.4'; package Bit::Vector; use Carp::Clan '^Bit::Vector\b'; use overload '""' => '_stringify', 'bool' => '_boolean', '!' => '_not_boolean', '~' => '_complement', 'neg' => '_negate', 'abs' => '_absolute', '.' => '_concat', 'x' => '_xerox', '<<' => '_shift_left', '>>' => '_shift_right', '|' => '_union', '&' => '_intersection', '^' => '_exclusive_or', '+' => '_add', '-' => '_sub', '*' => '_mul', '/' => '_div', '%' => '_mod', '**' => '_pow', '.=' => '_assign_concat', 'x=' => '_assign_xerox', '<<=' => '_assign_shift_left', '>>=' => '_assign_shift_right', '|=' => '_assign_union', '&=' => '_assign_intersection', '^=' => '_assign_exclusive_or', '+=' => '_assign_add', '-=' => '_assign_sub', '*=' => '_assign_mul', '/=' => '_assign_div', '%=' => '_assign_mod', '**=' => '_assign_pow', '++' => '_increment', '--' => '_decrement', 'cmp' => '_lexicompare', # also enables lt, le, gt, ge, eq, ne '<=>' => '_compare', '==' => '_equal', '!=' => '_not_equal', '<' => '_less_than', '<=' => '_less_equal', '>' => '_greater_than', '>=' => '_greater_equal', '=' => '_clone', 'fallback' => undef; $CONFIG[0] = 0; $CONFIG[1] = 0; $CONFIG[2] = 0; # Configuration: # # 0 = Scalar Input: 0 = Bit Index (default) # 1 = from_Hex # 2 = from_Bin # 3 = from_Dec # 4 = from_Enum # # 1 = Operator Semantics: 0 = Set Ops (default) # 1 = Arithmetic Ops # # Affected Operators: "+" "-" "*" # "<" "<=" ">" ">=" # "abs" # # 2 = String Output: 0 = to_Hex() (default) # 1 = to_Bin() # 2 = to_Dec() # 3 = to_Enum() sub Configuration { my(@commands); my($assignment); my($which,$value); my($m0,$m1,$m2,$m3,$m4); my($result); my($ok); if (@_ > 2) { croak('Usage: $oldconfig = Bit::Vector->Configuration( [ $newconfig ] );'); } $result = "Scalar Input = "; if ($CONFIG[0] == 4) { $result .= "Enumeration"; } elsif ($CONFIG[0] == 3) { $result .= "Decimal"; } elsif ($CONFIG[0] == 2) { $result .= "Binary"; } elsif ($CONFIG[0] == 1) { $result .= "Hexadecimal"; } else { $result .= "Bit Index"; } $result .= "\nOperator Semantics = "; if ($CONFIG[1] == 1) { $result .= "Arithmetic Operators"; } else { $result .= "Set Operators"; } $result .= "\nString Output = "; if ($CONFIG[2] == 3) { $result .= "Enumeration"; } elsif ($CONFIG[2] == 2) { $result .= "Decimal"; } elsif ($CONFIG[2] == 1) { $result .= "Binary"; } else { $result .= "Hexadecimal"; } shift if (@_ > 0); if (@_ > 0) { $ok = 1; @commands = split(/[,;:|\/\n&+-]/, $_[0]); foreach $assignment (@commands) { if ($assignment =~ /^\s*$/) { } # ignore empty lines elsif ($assignment =~ /^([A-Za-z\s]+)=([A-Za-z\s]+)$/) { $which = $1; $value = $2; $m0 = 0; $m1 = 0; $m2 = 0; if ($which =~ /\bscalar|\binput|\bin\b/i) { $m0 = 1; } if ($which =~ /\boperator|\bsemantic|\bops\b/i) { $m1 = 1; } if ($which =~ /\bstring|\boutput|\bout\b/i) { $m2 = 1; } if ($m0 && !$m1 && !$m2) { $m0 = 0; $m1 = 0; $m2 = 0; $m3 = 0; $m4 = 0; if ($value =~ /\bbit\b|\bindex|\bindice/i) { $m0 = 1; } if ($value =~ /\bhex/i) { $m1 = 1; } if ($value =~ /\bbin/i) { $m2 = 1; } if ($value =~ /\bdec/i) { $m3 = 1; } if ($value =~ /\benum/i) { $m4 = 1; } if ($m0 && !$m1 && !$m2 && !$m3 && !$m4) { $CONFIG[0] = 0; } elsif (!$m0 && $m1 && !$m2 && !$m3 && !$m4) { $CONFIG[0] = 1; } elsif (!$m0 && !$m1 && $m2 && !$m3 && !$m4) { $CONFIG[0] = 2; } elsif (!$m0 && !$m1 && !$m2 && $m3 && !$m4) { $CONFIG[0] = 3; } elsif (!$m0 && !$m1 && !$m2 && !$m3 && $m4) { $CONFIG[0] = 4; } else { $ok = 0; last; } } elsif (!$m0 && $m1 && !$m2) { $m0 = 0; $m1 = 0; if ($value =~ /\bset\b/i) { $m0 = 1; } if ($value =~ /\barithmetic/i) { $m1 = 1; } if ($m0 && !$m1) { $CONFIG[1] = 0; } elsif (!$m0 && $m1) { $CONFIG[1] = 1; } else { $ok = 0; last; } } elsif (!$m0 && !$m1 && $m2) { $m0 = 0; $m1 = 0; $m2 = 0; $m3 = 0; if ($value =~ /\bhex/i) { $m0 = 1; } if ($value =~ /\bbin/i) { $m1 = 1; } if ($value =~ /\bdec/i) { $m2 = 1; } if ($value =~ /\benum/i) { $m3 = 1; } if ($m0 && !$m1 && !$m2 && !$m3) { $CONFIG[2] = 0; } elsif (!$m0 && $m1 && !$m2 && !$m3) { $CONFIG[2] = 1; } elsif (!$m0 && !$m1 && $m2 && !$m3) { $CONFIG[2] = 2; } elsif (!$m0 && !$m1 && !$m2 && $m3) { $CONFIG[2] = 3; } else { $ok = 0; last; } } else { $ok = 0; last; } } else { $ok = 0; last; } } unless ($ok) { croak('configuration string syntax error'); } } return($result); } sub _error { my($name,$code) = @_; my($text); if ($code == 0) { $text = $@; $text =~ s!\s+! !g; $text =~ s!\s+at\s.*$!!; $text =~ s!^(?:Bit::Vector::)?[a-zA-Z0-9_]+\(\):\s*!!i; $text =~ s!\s+$!!; } elsif ($code == 1) { $text = 'illegal operand type'; } elsif ($code == 2) { $text = 'illegal reversed operands'; } else { croak('unexpected internal error - please contact author'); } $text .= " in overloaded "; if (length($name) > 5) { $text .= "$name operation"; } else { $text .= "'$name' operator"; } croak($text); } sub _vectorize_ { my($vector,$scalar) = @_; if ($CONFIG[0] == 4) { $vector->from_Enum($scalar); } elsif ($CONFIG[0] == 3) { $vector->from_Dec ($scalar); } elsif ($CONFIG[0] == 2) { $vector->from_Bin ($scalar); } elsif ($CONFIG[0] == 1) { $vector->from_Hex ($scalar); } else { $vector->Bit_On ($scalar); } } sub _scalarize_ { my($vector) = @_; if ($CONFIG[2] == 3) { return( $vector->to_Enum() ); } elsif ($CONFIG[2] == 2) { return( $vector->to_Dec () ); } elsif ($CONFIG[2] == 1) { return( $vector->to_Bin () ); } else { return( $vector->to_Hex () ); } } sub _fetch_operand { my($object,$argument,$flag,$name,$build) = @_; my($operand); if ((defined $argument) && ref($argument) && (ref($argument) !~ /^[A-Z]+$/)) { eval { if ($build && (defined $flag)) { $operand = $argument->Clone(); } else { $operand = $argument; } }; if ($@) { &_error($name,0); } } elsif ((defined $argument) && (!ref($argument))) { eval { $operand = $object->Shadow(); &_vectorize_($operand,$argument); }; if ($@) { &_error($name,0); } } else { &_error($name,1); } return($operand); } sub _check_operand { my($argument,$flag,$name) = @_; if ((defined $argument) && (!ref($argument))) { if ((defined $flag) && $flag) { &_error($name,2); } } else { &_error($name,1); } } sub _stringify { my($vector) = @_; my($name) = 'string interpolation'; my($result); eval { $result = &_scalarize_($vector); }; if ($@) { &_error($name,0); } return($result); } sub _boolean { my($object) = @_; my($name) = 'boolean test'; my($result); eval { $result = $object->is_empty(); }; if ($@) { &_error($name,0); } return(! $result); } sub _not_boolean { my($object) = @_; my($name) = 'negated boolean test'; my($result); eval { $result = $object->is_empty(); }; if ($@) { &_error($name,0); } return($result); } sub _complement { my($object) = @_; my($name) = '~'; my($result); eval { $result = $object->Shadow(); $result->Complement($object); }; if ($@) { &_error($name,0); } return($result); } sub _negate { my($object) = @_; my($name) = 'unary minus'; my($result); eval { $result = $object->Shadow(); $result->Negate($object); }; if ($@) { &_error($name,0); } return($result); } sub _absolute { my($object) = @_; my($name) = 'abs()'; my($result); eval { if ($CONFIG[1] == 1) { $result = $object->Shadow(); $result->Absolute($object); } else { $result = $object->Norm(); } }; if ($@) { &_error($name,0); } return($result); } sub _concat { my($object,$argument,$flag) = @_; my($name) = '.'; my($result); $name .= '=' unless (defined $flag); if ((defined $argument) && ref($argument) && (ref($argument) !~ /^[A-Z]+$/)) { eval { if (defined $flag) { if ($flag) { $result = $argument->Concat($object); } else { $result = $object->Concat($argument); } } else { $object->Interval_Substitute($argument,0,0,0,$argument->Size()); $result = $object; } }; if ($@) { &_error($name,0); } return($result); } elsif ((defined $argument) && (!ref($argument))) { eval { if (defined $flag) { if ($flag) { $result = $argument . &_scalarize_($object); } else { $result = &_scalarize_($object) . $argument; } } else { if ($CONFIG[0] == 2) { $result = $object->new( length($argument) ); } elsif ($CONFIG[0] == 1) { $result = $object->new( length($argument) << 2 ); } else { $result = $object->Shadow(); } &_vectorize_($result,$argument); $object->Interval_Substitute($result,0,0,0,$result->Size()); $result = $object; } }; if ($@) { &_error($name,0); } return($result); } else { &_error($name,1); } } sub _xerox # (in Brazil, a photocopy is called a "xerox") { my($object,$argument,$flag) = @_; my($name) = 'x'; my($result); my($offset); my($index); my($size); $name .= '=' unless (defined $flag); &_check_operand($argument,$flag,$name); eval { $size = $object->Size(); if (defined $flag) { $result = $object->new($size * $argument); $offset = 0; $index = 0; } else { $result = $object; $result->Resize($size * $argument); $offset = $size; $index = 1; } for ( ; $index < $argument; $index++, $offset += $size ) { $result->Interval_Copy($object,$offset,0,$size); } }; if ($@) { &_error($name,0); } return($result); } sub _shift_left { my($object,$argument,$flag) = @_; my($name) = '<<'; my($result); $name .= '=' unless (defined $flag); &_check_operand($argument,$flag,$name); eval { if (defined $flag) { $result = $object->Clone(); $result->Insert(0,$argument); # $result->Move_Left($argument); } else { # $object->Move_Left($argument); $object->Insert(0,$argument); $result = $object; } }; if ($@) { &_error($name,0); } return($result); } sub _shift_right { my($object,$argument,$flag) = @_; my($name) = '>>'; my($result); $name .= '=' unless (defined $flag); &_check_operand($argument,$flag,$name); eval { if (defined $flag) { $result = $object->Clone(); $result->Delete(0,$argument); # $result->Move_Right($argument); } else { # $object->Move_Right($argument); $object->Delete(0,$argument); $result = $object; } }; if ($@) { &_error($name,0); } return($result); } sub _union_ { my($object,$operand,$flag) = @_; if (defined $flag) { $operand->Union($object,$operand); return($operand); } else { $object->Union($object,$operand); return($object); } } sub _union { my($object,$argument,$flag) = @_; my($name) = '|'; my($operand); $name .= '=' unless (defined $flag); $operand = &_fetch_operand($object,$argument,$flag,$name,1); eval { $operand = &_union_($object,$operand,$flag); }; if ($@) { &_error($name,0); } return($operand); } sub _intersection_ { my($object,$operand,$flag) = @_; if (defined $flag) { $operand->Intersection($object,$operand); return($operand); } else { $object->Intersection($object,$operand); return($object); } } sub _intersection { my($object,$argument,$flag) = @_; my($name) = '&'; my($operand); $name .= '=' unless (defined $flag); $operand = &_fetch_operand($object,$argument,$flag,$name,1); eval { $operand = &_intersection_($object,$operand,$flag); }; if ($@) { &_error($name,0); } return($operand); } sub _exclusive_or { my($object,$argument,$flag) = @_; my($name) = '^'; my($operand); $name .= '=' unless (defined $flag); $operand = &_fetch_operand($object,$argument,$flag,$name,1); eval { if (defined $flag) { $operand->ExclusiveOr($object,$operand); } else { $object->ExclusiveOr($object,$operand); $operand = $object; } }; if ($@) { &_error($name,0); } return($operand); } sub _add { my($object,$argument,$flag) = @_; my($name) = '+'; my($operand); $name .= '=' unless (defined $flag); $operand = &_fetch_operand($object,$argument,$flag,$name,1); eval { if ($CONFIG[1] == 1) { if (defined $flag) { $operand->add($object,$operand,0); } else { $object->add($object,$operand,0); $operand = $object; } } else { $operand = &_union_($object,$operand,$flag); } }; if ($@) { &_error($name,0); } return($operand); } sub _sub { my($object,$argument,$flag) = @_; my($name) = '-'; my($operand); $name .= '=' unless (defined $flag); $operand = &_fetch_operand($object,$argument,$flag,$name,1); eval { if ($CONFIG[1] == 1) { if (defined $flag) { if ($flag) { $operand->subtract($operand,$object,0); } else { $operand->subtract($object,$operand,0); } } else { $object->subtract($object,$operand,0); $operand = $object; } } else { if (defined $flag) { if ($flag) { $operand->Difference($operand,$object); } else { $operand->Difference($object,$operand); } } else { $object->Difference($object,$operand); $operand = $object; } } }; if ($@) { &_error($name,0); } return($operand); } sub _mul { my($object,$argument,$flag) = @_; my($name) = '*'; my($operand); $name .= '=' unless (defined $flag); $operand = &_fetch_operand($object,$argument,$flag,$name,1); eval { if ($CONFIG[1] == 1) { if (defined $flag) { $operand->Multiply($object,$operand); } else { $object->Multiply($object,$operand); $operand = $object; } } else { $operand = &_intersection_($object,$operand,$flag); } }; if ($@) { &_error($name,0); } return($operand); } sub _div { my($object,$argument,$flag) = @_; my($name) = '/'; my($operand); my($temp); $name .= '=' unless (defined $flag); $operand = &_fetch_operand($object,$argument,$flag,$name,1); eval { $temp = $object->Shadow(); if (defined $flag) { if ($flag) { $operand->Divide($operand,$object,$temp); } else { $operand->Divide($object,$operand,$temp); } } else { $object->Divide($object,$operand,$temp); $operand = $object; } }; if ($@) { &_error($name,0); } return($operand); } sub _mod { my($object,$argument,$flag) = @_; my($name) = '%'; my($operand); my($temp); $name .= '=' unless (defined $flag); $operand = &_fetch_operand($object,$argument,$flag,$name,1); eval { $temp = $object->Shadow(); if (defined $flag) { if ($flag) { $temp->Divide($operand,$object,$operand); } else { $temp->Divide($object,$operand,$operand); } } else { $temp->Divide($object,$operand,$object); $operand = $object; } }; if ($@) { &_error($name,0); } return($operand); } sub _pow { my($object,$argument,$flag) = @_; my($name) = '**'; my($operand,$result); $name .= '=' unless (defined $flag); $operand = &_fetch_operand($object,$argument,$flag,$name,0); eval { if (defined $flag) { $result = $object->Shadow(); if ($flag) { $result->Power($operand,$object); } else { $result->Power($object,$operand); } } else { $object->Power($object,$operand); $result = $object; } }; if ($@) { &_error($name,0); } return($result); } sub _assign_concat { my($object,$argument) = @_; return( &_concat($object,$argument,undef) ); } sub _assign_xerox { my($object,$argument) = @_; return( &_xerox($object,$argument,undef) ); } sub _assign_shift_left { my($object,$argument) = @_; return( &_shift_left($object,$argument,undef) ); } sub _assign_shift_right { my($object,$argument) = @_; return( &_shift_right($object,$argument,undef) ); } sub _assign_union { my($object,$argument) = @_; return( &_union($object,$argument,undef) ); } sub _assign_intersection { my($object,$argument) = @_; return( &_intersection($object,$argument,undef) ); } sub _assign_exclusive_or { my($object,$argument) = @_; return( &_exclusive_or($object,$argument,undef) ); } sub _assign_add { my($object,$argument) = @_; return( &_add($object,$argument,undef) ); } sub _assign_sub { my($object,$argument) = @_; return( &_sub($object,$argument,undef) ); } sub _assign_mul { my($object,$argument) = @_; return( &_mul($object,$argument,undef) ); } sub _assign_div { my($object,$argument) = @_; return( &_div($object,$argument,undef) ); } sub _assign_mod { my($object,$argument) = @_; return( &_mod($object,$argument,undef) ); } sub _assign_pow { my($object,$argument) = @_; return( &_pow($object,$argument,undef) ); } sub _increment { my($object) = @_; my($name) = '++'; my($result); eval { $result = $object->increment(); }; if ($@) { &_error($name,0); } return($result); } sub _decrement { my($object) = @_; my($name) = '--'; my($result); eval { $result = $object->decrement(); }; if ($@) { &_error($name,0); } return($result); } sub _lexicompare { my($object,$argument,$flag) = @_; my($name) = 'cmp'; my($operand); my($result); $operand = &_fetch_operand($object,$argument,$flag,$name,0); eval { if ((defined $flag) && $flag) { $result = $operand->Lexicompare($object); } else { $result = $object->Lexicompare($operand); } }; if ($@) { &_error($name,0); } return($result); } sub _compare { my($object,$argument,$flag) = @_; my($name) = '<=>'; my($operand); my($result); $operand = &_fetch_operand($object,$argument,$flag,$name,0); eval { if ((defined $flag) && $flag) { $result = $operand->Compare($object); } else { $result = $object->Compare($operand); } }; if ($@) { &_error($name,0); } return($result); } sub _equal { my($object,$argument,$flag) = @_; my($name) = '=='; my($operand); my($result); $operand = &_fetch_operand($object,$argument,$flag,$name,0); eval { $result = $object->equal($operand); }; if ($@) { &_error($name,0); } return($result); } sub _not_equal { my($object,$argument,$flag) = @_; my($name) = '!='; my($operand); my($result); $operand = &_fetch_operand($object,$argument,$flag,$name,0); eval { $result = $object->equal($operand); }; if ($@) { &_error($name,0); } return(! $result); } sub _less_than { my($object,$argument,$flag) = @_; my($name) = '<'; my($operand); my($result); $operand = &_fetch_operand($object,$argument,$flag,$name,0); eval { if ($CONFIG[1] == 1) { if ((defined $flag) && $flag) { $result = ($operand->Compare($object) < 0); } else { $result = ($object->Compare($operand) < 0); } } else { if ((defined $flag) && $flag) { $result = ((!$operand->equal($object)) && ($operand->subset($object))); } else { $result = ((!$object->equal($operand)) && ($object->subset($operand))); } } }; if ($@) { &_error($name,0); } return($result); } sub _less_equal { my($object,$argument,$flag) = @_; my($name) = '<='; my($operand); my($result); $operand = &_fetch_operand($object,$argument,$flag,$name,0); eval { if ($CONFIG[1] == 1) { if ((defined $flag) && $flag) { $result = ($operand->Compare($object) <= 0); } else { $result = ($object->Compare($operand) <= 0); } } else { if ((defined $flag) && $flag) { $result = $operand->subset($object); } else { $result = $object->subset($operand); } } }; if ($@) { &_error($name,0); } return($result); } sub _greater_than { my($object,$argument,$flag) = @_; my($name) = '>'; my($operand); my($result); $operand = &_fetch_operand($object,$argument,$flag,$name,0); eval { if ($CONFIG[1] == 1) { if ((defined $flag) && $flag) { $result = ($operand->Compare($object) > 0); } else { $result = ($object->Compare($operand) > 0); } } else { if ((defined $flag) && $flag) { $result = ((!$object->equal($operand)) && ($object->subset($operand))); } else { $result = ((!$operand->equal($object)) && ($operand->subset($object))); } } }; if ($@) { &_error($name,0); } return($result); } sub _greater_equal { my($object,$argument,$flag) = @_; my($name) = '>='; my($operand); my($result); $operand = &_fetch_operand($object,$argument,$flag,$name,0); eval { if ($CONFIG[1] == 1) { if ((defined $flag) && $flag) { $result = ($operand->Compare($object) >= 0); } else { $result = ($object->Compare($operand) >= 0); } } else { if ((defined $flag) && $flag) { $result = $object->subset($operand); } else { $result = $operand->subset($object); } } }; if ($@) { &_error($name,0); } return($result); } sub _clone { my($object) = @_; my($name) = 'automatic duplication'; my($result); eval { $result = $object->Clone(); }; if ($@) { &_error($name,0); } return($result); } 1; __END__ Bit-Vector-7.4/lib/Bit/Vector/String.pod000644 100660 100660 00000034637 12211373040 017122 0ustar00sbsb000000 000000 =head1 NAME Bit::Vector::String - Generic string import/export for Bit::Vector =head1 SYNOPSIS use Bit::Vector::String; to_Oct $string = $vector->to_Oct(); from_Oct $vector->from_Oct($string); new_Oct $vector = Bit::Vector->new_Oct($bits,$string); String_Export $string = $vector->String_Export($type); String_Import $type = $vector->String_Import($string); new_String $vector = Bit::Vector->new_String($bits,$string); ($vector,$type) = Bit::Vector->new_String($bits,$string); =head1 DESCRIPTION =over 2 =item * C<$string = $vector-Eto_Oct();> Returns an octal string representing the given bit vector. Note that this method is not particularly efficient, since it is almost completely realized in Perl, and moreover internally operates on a Perl list of individual octal digits which it concatenates into the final string using "C". A benchmark reveals that this method is about 40 times slower than the method "C" (which is realized in C): Benchmark: timing 10000 iterations of to_Bin, to_Hex, to_Oct... to_Bin: 1 wallclock secs ( 1.09 usr + 0.00 sys = 1.09 CPU) to_Hex: 1 wallclock secs ( 0.53 usr + 0.00 sys = 0.53 CPU) to_Oct: 40 wallclock secs (40.16 usr + 0.05 sys = 40.21 CPU) Note that since an octal digit is always worth three bits, the length of the resulting string is always a multiple of three bits, regardless of the true length (in bits) of the given bit vector. Also note that the B significant octal digit is located at the B end of the resulting string, and the B significant digit at the B end. Finally, note that this method does B prepend any uniquely identifying format prefix (such as "0o") to the resulting string (which means that the result of this method only contains valid octal digits, i.e., [0-7]). However, this can of course most easily be done as needed, as follows: $string = '0o' . $vector->to_Oct(); =item * C<$vector-Efrom_Oct($string);> Allows to read in the contents of a bit vector from an octal string, such as returned by the method "C" (see above). Note that this method is not particularly efficient, since it is almost completely realized in Perl, and moreover chops the input string into individual characters using "C". Remember also that the least significant bits are always to the right of an octal string, and the most significant bits to the left. Therefore, the string is actually reversed internally before storing it in the given bit vector using the method "C", which expects the least significant chunks of data at the beginning of a list. A benchmark reveals that this method is about 40 times slower than the method "C" (which is realized in C): Benchmark: timing 10000 iterations of from_Bin, from_Hex, from_Oct... from_Bin: 1 wallclock secs ( 1.13 usr + 0.00 sys = 1.13 CPU) from_Hex: 1 wallclock secs ( 0.80 usr + 0.00 sys = 0.80 CPU) from_Oct: 46 wallclock secs (44.95 usr + 0.00 sys = 44.95 CPU) If the given string contains any character which is not an octal digit (i.e., [0-7]), a fatal syntax error ensues ("unknown string type"). Note especially that this method does B accept any uniquely identifying format prefix (such as "0o") in the given string; the presence of such a prefix will also lead to the fatal "unknown string type" error. If the given string contains less octal digits than are needed to completely fill the given bit vector, the remaining (most significant) bits all remain cleared (i.e., set to zero). This also means that, even if the given string does not contain enough digits to completely fill the given bit vector, the previous contents of the bit vector are erased completely. If the given string is longer than it needs to fill the given bit vector, the superfluous characters are simply ignored. This behaviour is intentional so that you may read in the string representing one bit vector into another bit vector of different size, i.e., as much of it as will fit. =item * C<$vector = Bit::Vector-Enew_Oct($bits,$string);> This method is an alternative constructor which allows you to create a new bit vector object (with "C<$bits>" bits) and to initialize it all in one go. The method internally first calls the bit vector constructor method "C" and then stores the given string in the newly created bit vector using the same approach as the method "C" (described above). Note that this approach is not particularly efficient, since it is almost completely realized in Perl, and moreover chops the input string into individual characters using "C". An exception will be raised if the necessary memory cannot be allocated (see the description of the method "C" in L for possible causes) or if the given string cannot be converted successfully (see the description of the method "C" above for details). Note especially that this method does B accept any uniquely identifying format prefix (such as "0o") in the given string and that such a prefix will lead to a fatal "unknown string type" error. In case of an error, the memory occupied by the new bit vector is released again before the exception is actually thrown. If the number of bits "C<$bits>" given has the value "C", the method will automatically allocate a bit vector with a size (i.e., number of bits) of three times the length of the given string (since every octal digit is worth three bits). Note that this behaviour is different from that of the methods "C", "C", "C" and "C" (which are realized in C, internally); these methods will silently assume a value of 0 bits if "C" is given (and may warn about the "Use of uninitialized value" if warnings are enabled). =item * C<$string = $vector-EString_Export($type);> Returns a string representing the given bit vector in the format specified by "C<$type>": 1 | b | bin => binary (using "to_Bin()") 2 | o | oct => octal (using "to_Oct()") 3 | d | dec => decimal (using "to_Dec()") 4 | h | hex | x => hexadecimal (using "to_Hex()") 5 | e | enum => enumeration (using "to_Enum()") 6 | p | pack => packed binary (using "Block_Read()") The case (lower/upper/mixed case) of "C<$type>" is ignored. If "C<$type>" is omitted or "C" or false ("0" or the empty string), a hexadecimal string is returned as the default format. If "C<$type>" does not have any of the values described above, a fatal "unknown string type" will occur. Beware that in order to guarantee that the strings can be correctly parsed and read in by the methods "C" and "C" (described below), the method "C" provides uniquely identifying prefixes (and, in one case, a suffix) as follows: 1 | b | bin => '0b' . $vector->to_Bin(); 2 | o | oct => '0o' . $vector->to_Oct(); 3 | d | dec => $vector->to_Dec(); # prefix is [+-] 4 | h | hex | x => '0x' . $vector->to_Hex(); 5 | e | enum => '{' . $vector->to_Enum() . '}'; 6 | p | pack => ':' . $vector->Size() . ':' . $vector->Block_Read(); This is necessary because certain strings can be valid representations in more than one format. All strings in binary format, i.e., which only contain "0" and "1", are also valid number representations (of a different value, of course) in octal, decimal and hexadecimal. Likewise, a string in octal format is also valid in decimal and hexadecimal, and a string in decimal format is also valid in hexadecimal. Moreover, if the enumeration of set bits (as returned by "C") only contains one element, this element could be mistaken for a representation of the entire bit vector (instead of just one bit) in decimal. Beware also that the string returned by format "6" ("packed binary") will in general B, because it will usually consist of many unprintable characters! =item * C<$type = $vector-EString_Import($string);> Allows to read in the contents of a bit vector from a string which has previously been produced by "C", "C", "C", "C", "C", "C", "C" or manually or by another program. Beware however that the string must have the correct format; otherwise a fatal "unknown string type" error will occur. The correct format is the one returned by "C" (see immediately above). The method will also try to automatically recognize formats without identifying prefix such as returned by the methods "C", "C", "C", "C" and "C". However, as explained above for the method "C", due to the fact that a string may be a valid representation in more than one format, this may lead to unwanted results. The method will try to match the format of the given string in the following order: If the string consists only of [01], it will be considered to be in binary format (although it could be in octal, decimal or hexadecimal format or even be an enumeration with only one element as well). If the string consists only of [0-7], it will be considered to be in octal format (although it could be in decimal or hexadecimal format or even be an enumeration with only one element as well). If the string consists only of [0-9], it will be considered to be in decimal format (although it could be in hexadecimal format or even be an enumeration with only one element as well). If the string consists only of [0-9A-Fa-f], it will be considered to be in hexadecimal format. If the string only contains numbers in decimal format, separated by commas (",") or dashes ("-"), it is considered to be an enumeration (a single decimal number also qualifies). And if the string starts with ":[0-9]:", the remainder of the string is read in with "C". To avoid misinterpretations, it is therefore recommendable to always either use the method "C" or to provide some uniquely identifying prefix (and suffix, in one case) yourself: binary => '0b' . $string; octal => '0o' . $string; decimal => '+' . $string; # in case "$string" => '-' . $string; # has no sign yet hexadecimal => '0x' . $string; => '0h' . $string; enumeration => '{' . $string . '}'; => '[' . $string . ']'; => '<' . $string . '>'; => '(' . $string . ')'; packed binary => ':' . $vector->Size() . ':' . $vector->Block_Read(); Note that case (lower/upper/mixed case) is not important and will be ignored by this method. Internally, the method uses the methods "C", "C", "C", "C", "C" and "C" for actually importing the contents of the string into the given bit vector. See their descriptions here in this document and in L for any further conditions that must be met and corresponding possible fatal error messages. The method returns the number of the format that has been recognized: 1 => binary 2 => octal 3 => decimal 4 => hexadecimal 5 => enumeration 6 => packed binary =item * C<$vector = Bit::Vector-Enew_String($bits,$string);> C<($vector,$type) = Bit::Vector-Enew_String($bits,$string);> This method is an alternative constructor which allows you to create a new bit vector object (with "C<$bits>" bits) and to initialize it all in one go. The method internally first calls the bit vector constructor method "C" and then stores the given string in the newly created bit vector using the same approach as the method "C" (described immediately above). An exception will be raised if the necessary memory cannot be allocated (see the description of the method "C" in L for possible causes) or if the given string cannot be converted successfully (see the description of the method "C" above for details). In case of an error, the memory occupied by the new bit vector is released again before the exception is actually thrown. If the number of bits "C<$bits>" given has the value "C", the method will automatically determine this value for you and allocate a bit vector of the calculated size. Note that this behaviour is different from that of the methods "C", "C", "C" and "C" (which are realized in C, internally); these methods will silently assume a value of 0 bits if "C" is given (and may warn about the "Use of uninitialized value" if warnings are enabled). The necessary number of bits is calculated as follows: binary => length($string); octal => 3 * length($string); decimal => int( length($string) * log(10) / log(2) + 1 ); hexadecimal => 4 * length($string); enumeration => maximum of values found in $string + 1 packed binary => $string =~ /^:(\d+):/; If called in scalar context, the method returns the newly created bit vector object. If called in list context, the method additionally returns the number of the format which has been recognized, as explained above for the method "C". =back =head1 SEE ALSO Bit::Vector(3), Bit::Vector::Overload(3). =head1 VERSION This man page documents "Bit::Vector::String" version 7.4. =head1 AUTHOR Steffen Beyer mailto:STBEY@cpan.org http://www.engelschall.com/u/sb/download/ =head1 COPYRIGHT Copyright (c) 2004 - 2013 by Steffen Beyer. All rights reserved. =head1 LICENSE This package is free software; you can redistribute it and/or modify it under the same terms as Perl itself, i.e., under the terms of the "Artistic License" or the "GNU General Public License". The C library at the core of this Perl module can additionally be redistributed and/or modified under the terms of the "GNU Library General Public License". Please refer to the files "Artistic.txt", "GNU_GPL.txt" and "GNU_LGPL.txt" in this distribution for details! =head1 DISCLAIMER This package is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the "GNU General Public License" for more details. Bit-Vector-7.4/lib/Bit/Vector/Overload.pod000644 100660 100660 00000125326 12211373040 017423 0ustar00sbsb000000 000000 =head1 NAME Bit::Vector::Overload - Overloaded operators add-on for Bit::Vector =head1 USAGE Note that you do not need to "C" in addition to this module. Simply "C" B of "C". You can still use all the methods from the "Bit::Vector" module in addition to the overloaded operators and methods provided here after that. =head1 SYNOPSIS Configuration $config = Bit::Vector->Configuration(); Bit::Vector->Configuration($config); $oldconfig = Bit::Vector->Configuration($newconfig); String Conversion $string = "$vector"; # depending on configuration print "\$vector = '$vector'\n"; Emptyness if ($vector) # if not empty (non-zero) if (! $vector) # if empty (zero) unless ($vector) # if empty (zero) Complement (one's complement) $vector2 = ~$vector1; $vector = ~$vector; Negation (two's complement) $vector2 = -$vector1; $vector = -$vector; Norm $norm = abs($vector); # depending on configuration Absolute $vector2 = abs($vector1); # depending on configuration Concatenation $vector3 = $vector1 . $vector2; $vector1 .= $vector2; $vector1 = $vector2 . $vector1; $vector2 = $vector1 . $scalar; # depending on configuration $vector2 = $scalar . $vector1; $vector .= $scalar; Duplication $vector2 = $vector1 x $factor; $vector x= $factor; Shift Left $vector2 = $vector1 << $bits; $vector <<= $bits; Shift Right $vector2 = $vector1 >> $bits; $vector >>= $bits; Union $vector3 = $vector1 | $vector2; $vector1 |= $vector2; $vector2 = $vector1 | $scalar; $vector |= $scalar; $vector3 = $vector1 + $vector2; # depending on configuration $vector1 += $vector2; $vector2 = $vector1 + $scalar; $vector += $scalar; Intersection $vector3 = $vector1 & $vector2; $vector1 &= $vector2; $vector2 = $vector1 & $scalar; $vector &= $scalar; $vector3 = $vector1 * $vector2; # depending on configuration $vector1 *= $vector2; $vector2 = $vector1 * $scalar; $vector *= $scalar; ExclusiveOr $vector3 = $vector1 ^ $vector2; $vector1 ^= $vector2; $vector2 = $vector1 ^ $scalar; $vector ^= $scalar; Set Difference $vector3 = $vector1 - $vector2; # depending on configuration $vector1 -= $vector2; $vector1 = $vector2 - $vector1; $vector2 = $vector1 - $scalar; $vector2 = $scalar - $vector1; $vector -= $scalar; Addition $vector3 = $vector1 + $vector2; # depending on configuration $vector1 += $vector2; $vector2 = $vector1 + $scalar; $vector += $scalar; Subtraction $vector3 = $vector1 - $vector2; # depending on configuration $vector1 -= $vector2; $vector1 = $vector2 - $vector1; $vector2 = $vector1 - $scalar; $vector2 = $scalar - $vector1; $vector -= $scalar; Multiplication $vector3 = $vector1 * $vector2; # depending on configuration $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; Exponentiation $vector3 = $vector1 ** $vector2; $vector1 **= $vector2; $vector2 = $vector1 ** $scalar; $vector2 = $scalar ** $vector1; $vector **= $scalar; Increment ++$vector; $vector++; Decrement --$vector; $vector--; Lexical Comparison (unsigned) $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) Comparison (signed) $cmp = $vector1 <=> $vector2; if ($vector1 < $vector2) # depending on configuration if ($vector1 <= $vector2) if ($vector1 > $vector2) if ($vector1 >= $vector2) $cmp = $vector <=> $scalar; if ($vector < $scalar) # depending on configuration if ($vector <= $scalar) if ($vector > $scalar) if ($vector >= $scalar) Equality 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) Subset Relationship if ($vector1 <= $vector2) # depending on configuration True Subset Relationship if ($vector1 < $vector2) # depending on configuration Superset Relationship if ($vector1 >= $vector2) # depending on configuration True Superset Relationship if ($vector1 > $vector2) # depending on configuration =head1 IMPORTANT NOTES =over 2 =item * Boolean values Boolean values in this module are always a numeric zero ("C<0>") for "false" and a numeric one ("C<1>") for "true". =item * Negative numbers Numeric factors (as needed for the "CE>", "CE>" and "C" operators) and bit numbers are always regarded as being B. As a consequence, whenever you pass a negative number for such a factor or bit number, it will be treated as a (usually very large) positive number due to its internal two's complement binary representation, usually resulting in malfunctions or an "index out of range" error message and program abortion. Note that this does not apply to "big integer" decimal numbers, which are (usually) passed as strings, and which may of course be negative (see also the section "Big integers" a little further below). =item * Overloaded operators configuration Note that the behaviour of certain overloaded operators can be changed in various ways by means of the "C" method (for more details, see the description of this method further below). For instance, scalars (i.e., numbers and strings) provided as operands to overloaded operators are automatically converted to bit vectors, internally. These scalars are thereby automatically assumed to be indices or to be in hexadecimal, binary, decimal or enumeration format, depending on the configuration. Similarly, when converting bit vectors to strings using double quotes (""), the output format will also depend on the previously chosen configuration. Finally, some overloaded operators may have different semantics depending on the proper configuration; for instance, the operator "+" can be the "union" operator from set theory or the arithmetic "add" operator. In all cases (input, output and operator semantics), the defaults have been chosen in such a way so that the behaviour of the module is backward compatible with previous versions. =item * "Big integers" As long as "big integers" (for "big integer" arithmetic) are small enough so that Perl doesn't need scientific notation (exponents) to be able to represent them internally, you can provide these "big integer" constants to the overloaded operators of this module (or to the method "C") in numeric form (i.e., either as a numeric constant or expression or as a Perl variable containing a numeric value). Note that you will get an error message (resulting in program abortion) if your "big integer" numbers exceed that limit. Because this limit is machine-dependent and not obvious to find out, it is strongly recommended that you enclose B your "big integer" constants in your programs in (double or single) quotes. Examples: $vector /= 10; # ok because number is small $vector /= -10; # ok for same reason $vector /= "10"; # always correct $vector += "1152921504606846976"; # quotes probably required here All examples assume Bit::Vector->Configuration("input=decimal"); having been set beforehand. Note also that this module does not support scientific notation (exponents) for "big integer" decimal numbers because you can always make the bit vector large enough for the whole number to fit without loss of precision (as it would occur if scientific notation were used). Finally, note that the only characters allowed in "big integer" constant strings are the digits C<0..9> and an optional leading sign ("C<+>" or "C<->"). All other characters produce a syntax error. =item * Valid operands for overloaded operators All overloaded operators expect at least one bit vector operand, in order for the operator to "know" that not the usual operation is to be carried out, but rather the overloaded variant. This is especially true for all unary operators: "$vector" if ($vector) if (!$vector) ~$vector -$vector abs($vector) ++$vector $vector++ --$vector $vector-- For obvious reasons the left operand (the "lvalue") of all assignment operators is also required to be a bit vector: .= x= <<= >>= |= &= ^= += -= *= /= %= **= In the case of three special operators, namely "CE>", "CE>" and "C", as well as their related assignment variants, "CE=>", "CE=>" and "C", the left operand is B a bit vector and the right operand is B a number (which is the factor indicating how many times the operator is to be applied). In all truly binary operators, i.e., . | & ^ + - * / % ** <=> cmp == eq != ne < lt <= le > gt >= ge one of either operands may be replaced by a Perl scalar, i.e., a number or a string, either as a Perl constant, a Perl expression or a Perl variable yielding a number or a string. The same applies to the right side operand (the "rvalue") of the remaining assignment operators, i.e., .= |= &= ^= += -= *= /= %= **= Note that this Perl scalar should be of the correct type, i.e., numeric or string, for the chosen configuration, because otherwise a warning message will occur if your program runs under the "C<-w>" switch of Perl. The acceptable scalar types for each possible configuration are the following: input = bit indices (default) : numeric input = hexadecimal : string input = binary : string input = decimal : string (in general) input = decimal : numeric (if small enough) input = enumeration : string NOTE ALSO THAT THESE SCALAR OPERANDS ARE CONVERTED TO BIT VECTORS OF THE SAME SIZE AS THE BIT VECTOR WHICH IS THE OTHER OPERAND. The only exception from this rule is the concatenation operator ("C<.>") and its assignment variant ("C<.=>"): If one of the two operands of the concatenation operator ("C<.>") is not a bit vector object but a Perl scalar, the contents of the remaining bit vector operand are converted into a string (the format of which depends on the configuration set with the "C" method), which is then concatenated in the proper order (i.e., as indicated by the order of the two operands) with the Perl scalar (in other words, a string is returned in such a case instead of a bit vector object!). If the right side operand (the "rvalue") of the assignment variant ("C<.=>") of the concatenation operator is a Perl scalar, it is converted internally to a bit vector of the same size as the left side operand provided that the configuration states that scalars are to be regarded as indices, decimal strings or enumerations. If the configuration states that scalars are to be regarded as hexadecimal or boolean strings, however, these strings are converted to bit vectors of a size matching the length of the input string, i.e., four times the length for hexadecimal strings (because each hexadecimal digit is worth 4 bits) and once the length for binary strings. If a decimal number ("big integer") is too large to be stored in a bit vector of the given size, a "numeric overflow error" occurs. If a bit index is out of range for the given bit vector, an "index out of range" error occurs. If a scalar operand cannot be converted successfully due to invalid syntax, a fatal "input string syntax error" is issued. If the two operands of the operator "CE>", "CE>" or "C" are reversed, a fatal "reversed operands error" occurs. If an operand is neither a bit vector nor a scalar, then a fatal "illegal operand type error" occurs. =item * Bit order Note that bit vectors are stored least order bit and least order word first internally. I.e., bit #0 of any given bit vector corresponds to bit #0 of word #0 in the array of machine words representing the bit vector. (Where word #0 comes first in memory, i.e., it is stored at the least memory address in the allocated block of memory holding the given bit vector.) Note however that machine words can be stored least order byte first or last, depending on your system's implementation. Note further that whenever bit vectors are converted to and from (binary or hexadecimal) strings, the B bit is always the B one, and the B bit is always the B bit. This is because in our western culture, numbers are always represented in this way (least significant to most significant digits go from right to left). Of course this requires an internal reversion of order, which the corresponding conversion methods perform automatically (without any additional overhead, it's just a matter of starting the internal loop at the bottom or the top end). =item * Matching sizes In general, for methods involving several bit vectors at the same time, all bit vector arguments must have identical sizes (number of bits), or a fatal "size mismatch" error will occur. Exceptions from this rule are the methods "C", "C", "C", "C" and "C", where no conditions at all are imposed on the size of their bit vector arguments. In method "C", all three bit vector arguments must in principle obey the rule of matching sizes, but the bit vector in which the result of the multiplication is to be stored may be larger than the two bit vector arguments containing the factors for the multiplication. In method "C", the bit vector for the result must be the same size or greater than the base of the exponentiation term. The exponent can be any size. The same applies to the corresponding overloaded operators. =item * Index ranges All indices for any given bits must lie between "C<0>" and "C<$vector-ESize()-1>", or a fatal "index out of range" error will occur. =back =head1 DESCRIPTION =over 2 =item * C<$config = Bit::Vector-EConfiguration();> =item * CConfiguration($config);> =item * C<$oldconfig = Bit::Vector-EConfiguration($newconfig);> This method serves to alter the semantics (i.e., behaviour) of certain overloaded operators (which are all implemented in Perl, by the way). It does not have any effect whatsoever on anything else. In particular, it does not affect the methods implemented in C. The method accepts an (optional) string as input in which certain keywords are expected, which influence some or almost all of the overloaded operators in several possible ways. The method always returns a string (which you do not need to take care of, i.e., to store, in case you aren't interested in keeping it) which is a complete representation of the current configuration (i.e., B any modifications are applied) and which can be fed back to this method later in order to restore the previous configuration. There are three aspects of the way certain overloaded operators behave which can be controlled with this method: + the way scalar operands (replacing one of the two bit vector object operands) are automatically converted internally into a bit vector object of their own, + the operation certain overloaded operators perform, i.e., an operation with sets or an arithmetic operation, + the format to which bit vectors are converted automatically when they are enclosed in double quotes. The input string may contain any number of assignments, each of which controls one of these three aspects. Each assignment has the form "CwhichE=EvalueE>". "CwhichE>" and "CvalueE>" thereby consist of letters (C<[a-zA-Z]>) and white space. Multiple assignments have to be separated by one or more comma (","), semi-colon (";"), colon (":"), vertical bar ("|"), slash ("/"), newline ("\n"), ampersand ("&"), plus ("+") or dash ("-"). Empty lines or statements (only white space) are allowed but will be ignored. "CwhichE>" has to contain one or more keywords from one of three groups, each group representing one of the three aspects that the "C" method controls: + "^scalar", "^input", "^in$" + "^operator", "^semantic", "^ops$" + "^string", "^output", "^out$" The character "^" thereby denotes the beginning of a word, and "$" denotes the end. Case is ignored (!). Using these keywords, you can build any phrase you like to select one of the three aspects (see also examples given below). The only condition is that no other keyword from any of the other two groups may match - otherwise a syntax error will occur (i.e., ambiguities are forbidden). A syntax error also occurs if none of the keywords matches. This same principle applies to "CvalueE>": Depending on which aspect you specified for "CwhichE>", there are different groups of keywords that determine the value the selected aspect will be set to: + "" = "^scalar", "^input", "^in$": "" = * "^bit$", "^index", "^indice" * "^hex" * "^bin" * "^dec" * "^enum" + "" = "^operator", "^semantic", "^ops$": "" = * "^set$" * "^arithmetic" + "" = "^string", "^output", "^out$": "" = * "^hex" * "^bin" * "^dec" * "^enum" Examples: "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" B In the case of scalar input, "C<^bit$>", "C<^index>", or "C<^indice>" all cause scalar input to be considered to represent a bit index, i.e., "C<$vector ^= 5;>" will flip bit #5 in the given bit vector (this is essentially the same as "C<$vector-Ebit_flip(5);>"). Note that "bit indices" is the default setting for "scalar input". The keyword "C<^hex>" will cause scalar input to be considered as being in hexadecimal, i.e., "C<$vector ^= 5;>" will flip bit #0 and bit #2 (because hexadecimal "C<5>" is binary "C<0101>"). (Note though that hexadecimal input should always be enclosed in quotes, otherwise it will be interpreted as a decimal number by Perl! The example relies on the fact that hexadecimal C<0-9> and decimal C<0-9> are the same.) The keyword "C<^bin>" will cause scalar input to be considered as being in binary format. All characters except "C<0>" and "C<1>" are forbidden in this case (i.e., produce a syntax error). "C<$vector ^= '0101';>", for instance, will flip bit #0 and bit #2. The keyword "C<^dec>" causes scalar input to be considered as integers in decimal format, i.e., "C<$vector ^= 5;>" will flip bit #0 and bit #2 (because decimal "C<5>" is binary "C<0101>"). (Note though that all decimal input should be enclosed in quotes, because for large numbers, Perl will use scientific notation internally for representing them, which produces a syntax error because scientific notation is neither supported by this module nor needed.) Finally, the keyword "C<^enum>" causes scalar input to be considered as being a list ("enumeration") of indices and ranges of (contiguous) indices, i.e., "C<$vector |= '2,3,5,7-13,17-23';>" will cause bits #2, #3, #5, #7 through #13 and #17 through #23 to be set. B Several overloaded operators can have two distinct functions depending on this setting. The affected operators are: "C<+>", "C<->", "C<*>", "C>", "C=>", "C>" and "C=>". With the default setting, "set operations", these operators perform: + set union ( set1 u set2 ) - set difference ( set1 \ set2 ) * set intersection ( set1 n set2 ) < true subset relationship ( set1 < set2 ) <= subset relationship ( set1 <= set2 ) > true superset relationship ( set1 > set2 ) >= superset relationship ( set1 >= set2 ) With the alternative setting, "arithmetic operations", these operators perform: + addition ( num1 + num2 ) - subtraction ( num1 - num2 ) * multiplication ( num1 * num2 ) < "less than" comparison ( num1 < num2 ) <= "less than or equal" comparison ( num1 <= num2 ) > "greater than" comparison ( num1 > num2 ) >= "greater than or equal" comparison ( num1 >= num2 ) Note that these latter comparison operators ("C>", "C=>", "C>" and "C=>") regard their operands as being B. To perform comparisons with B operands, use the operators "C", "C", "C" and "C" instead (in contrast to the operators above, these operators are B affected by the "operator semantics" setting). B There are four methods which convert the contents of a given bit vector into a string: "C", "C", "C" and "C" (not counting "C", since this method does not return a human-readable string). (For conversion to octal, see the description of the method "C".) Therefore, there are four possible formats into which a bit vector can be converted when it is enclosed in double quotes, for example: print "\$vector = '$vector'\n"; $string = "$vector"; Hence you can set "string output" to four different values: To "hex" for hexadecimal format (which is the default), to "bin" for binary format, to "dec" for conversion to decimal numbers and to "enum" for conversion to enumerations (".newsrc" style sets). B that the conversion to decimal numbers is inherently slow; it can easily take up several seconds for a single large bit vector! Therefore you should store the decimal strings returned to you rather than converting a given bit vector again. B The default setting as returned by the method "C" is: Scalar Input = Bit Index Operator Semantics = Set Operators String Output = Hexadecimal Performing a statement such as: Bit::Vector->Configuration("in=bin,ops=arithmetic,out=bin"); print Bit::Vector->Configuration(), "\n"; yields the following output: Scalar Input = Binary Operator Semantics = Arithmetic Operators String Output = Binary Note that you can always feed this output back into the "C" method to restore that setting later. This also means that you can enter the same given setting with almost any degree of verbosity you like (as long as the required keywords appear and no ambiguities arise). Note further that any aspect you do not specify is not changed, i.e., the statement Bit::Vector->Configuration("operators = arithmetic"); leaves all other aspects unchanged. =item * C<"$vector"> Remember that variables enclosed in double quotes are always interpolated in Perl. Whenever a Perl variable containing the reference of a "Bit::Vector" object is enclosed in double quotes (either alone or together with other text and/or variables), the contents of the corresponding bit vector are converted into a printable string. Since there are several conversion methods available in this module (see the description of the methods "C", "C", "C" and "C"), it is of course desirable to be able to choose which of these methods should be applied in this case. This can actually be done by changing the configuration of this module using the method "C" (see the previous chapter, immediately above). The default is conversion to hexadecimal. =item * C It is possible to use a Perl variable containing the reference of a "Bit::Vector" object as a boolean expression. The condition above is true if the corresponding bit vector contains at least one set bit, and it is false if B bits of the corresponding bit vector are cleared. =item * C Since it is possible to use a Perl variable containing the reference of a "Bit::Vector" object as a boolean expression, you can of course also negate this boolean expression. The condition above is true if B bits of the corresponding bit vector are cleared, and it is false if the corresponding bit vector contains at least one set bit. Note that this is B the same as using the method "C", which returns true if B bits of the corresponding bit vector are B. =item * C<~$vector> This term returns a new bit vector object which is the one's complement of the given bit vector. This is equivalent to inverting all bits. =item * C<-$vector> (unary minus) This term returns a new bit vector object which is the two's complement of the given bit vector. This is equivalent to inverting all bits and incrementing the result by one. (This is the same as changing the sign of a number in two's complement binary representation.) =item * C Depending on the configuration (see the description of the method "C" for more details), this term either returns the number of set bits in the given bit vector (this is the same as calculating the number of elements which are contained in the given set) - which is the default behaviour, or it returns a new bit vector object which contains the absolute value of the number stored in the given bit vector. =item * C<$vector1 . $vector2> This term usually returns a new bit vector object which is the result of the concatenation of the two bit vector operands. The left operand becomes the most significant, and the right operand becomes the least significant part of the new bit vector object. If one of the two operands is not a bit vector object but a Perl scalar, however, the contents of the remaining bit vector operand are converted into a string (the format of which depends on the configuration set with the "C" method), which is then concatenated in the proper order (i.e., as indicated by the order of the two operands) with the Perl scalar. In other words, a string is returned in such a case instead of a bit vector object! =item * C<$vector x $factor> This term returns a new bit vector object which is the concatenation of as many copies of the given bit vector operand (the left operand) as the factor (the right operand) specifies. If the factor is zero, a bit vector object with a length of zero bits is returned. If the factor is one, just a new copy of the given bit vector is returned. Note that a fatal "reversed operands error" occurs if the two operands are swapped. =item * C<$vector EE $bits> This term returns a new bit vector object which is a copy of the given bit vector (the left operand), which is then shifted left (towards the most significant bit) by as many places as the right operand, "C<$bits>", specifies. This means that the "C<$bits>" most significant bits are lost, all other bits move up by "C<$bits>" positions, and the "C<$bits>" least significant bits that have been left unoccupied by this shift are all set to zero. If "C<$bits>" is greater than the number of bits of the given bit vector, this term returns an empty bit vector (i.e., with all bits cleared) of the same size as the given bit vector. Note that a fatal "reversed operands error" occurs if the two operands are swapped. =item * C<$vector EE $bits> This term returns a new bit vector object which is a copy of the given bit vector (the left operand), which is then shifted right (towards the least significant bit) by as many places as the right operand, "C<$bits>", specifies. This means that the "C<$bits>" least significant bits are lost, all other bits move down by "C<$bits>" positions, and the "C<$bits>" most significant bits that have been left unoccupied by this shift are all set to zero. If "C<$bits>" is greater than the number of bits of the given bit vector, this term returns an empty bit vector (i.e., with all bits cleared) of the same size as the given bit vector. Note that a fatal "reversed operands error" occurs if the two operands are swapped. =item * C<$vector1 | $vector2> This term returns a new bit vector object which is the result of a bitwise OR operation between the two bit vector operands. This is the same as calculating the union of two sets. =item * C<$vector1 & $vector2> This term returns a new bit vector object which is the result of a bitwise AND operation between the two bit vector operands. This is the same as calculating the intersection of two sets. =item * C<$vector1 ^ $vector2> This term returns a new bit vector object which is the result of a bitwise XOR (exclusive-or) operation between the two bit vector operands. This is the same as calculating the symmetric difference of two sets. =item * C<$vector1 + $vector2> Depending on the configuration (see the description of the method "C" for more details), this term either returns a new bit vector object which is the result of a bitwise OR operation between the two bit vector operands (this is the same as calculating the union of two sets) - which is the default behaviour, or it returns a new bit vector object which contains the sum of the two numbers stored in the two bit vector operands. =item * C<$vector1 - $vector2> Depending on the configuration (see the description of the method "C" for more details), this term either returns a new bit vector object which is the set difference of the two sets represented in the two bit vector operands - which is the default behaviour, or it returns a new bit vector object which contains the difference of the two numbers stored in the two bit vector operands. =item * C<$vector1 * $vector2> Depending on the configuration (see the description of the method "C" for more details), this term either returns a new bit vector object which is the result of a bitwise AND operation between the two bit vector operands (this is the same as calculating the intersection of two sets) - which is the default behaviour, or it returns a new bit vector object which contains the product of the two numbers stored in the two bit vector operands. =item * C<$vector1 / $vector2> This term returns a new bit vector object containing the result of the division of the two numbers stored in the two bit vector operands. =item * C<$vector1 % $vector2> This term returns a new bit vector object containing the remainder of the division of the two numbers stored in the two bit vector operands. =item * C<$vector1 ** $vector2> This term returns a new bit vector object containing the result of the exponentiation of the left bit vector elevated to the right bit vector's power. =item * C<$vector1 .= $vector2;> This statement "appends" the right bit vector operand (the "rvalue") to the left one (the "lvalue"). The former contents of the left operand become the most significant part of the resulting bit vector, and the right operand becomes the least significant part. Since bit vectors are stored in "least order bit first" order, this actually requires the left operand to be shifted "up" by the length of the right operand, which is then copied to the now freed least significant part of the left operand. If the right operand is a Perl scalar, it is first converted to a bit vector of the same size as the left operand, provided that the configuration states that scalars are to be regarded as indices, decimal strings or enumerations. If the configuration states that scalars are to be regarded as hexadecimal or boolean strings, however, these strings are converted to bit vectors of a size matching the length of the input string, i.e., four times the length for hexadecimal strings (because each hexadecimal digit is worth 4 bits) and once the length for binary strings. =item * C<$vector x= $factor;> This statement replaces the given bit vector by a concatenation of as many copies of the original contents of the given bit vector as the factor (the right operand) specifies. If the factor is zero, the given bit vector is resized to a length of zero bits. If the factor is one, the given bit vector is not changed at all. =item * C<$vector EE= $bits;> This statement moves the contents of the given bit vector left by "C<$bits>" positions (towards the most significant bit). This means that the "C<$bits>" most significant bits are lost, all other bits move up by "C<$bits>" positions, and the "C<$bits>" least significant bits that have been left unoccupied by this shift are all set to zero. If "C<$bits>" is greater than the number of bits of the given bit vector, the given bit vector is erased completely (i.e., all bits are cleared). =item * C<$vector EE= $bits;> This statement moves the contents of the given bit vector right by "C<$bits>" positions (towards the least significant bit). This means that the "C<$bits>" least significant bits are lost, all other bits move down by "C<$bits>" positions, and the "C<$bits>" most significant bits that have been left unoccupied by this shift are all set to zero. If "C<$bits>" is greater than the number of bits of the given bit vector, the given bit vector is erased completely (i.e., all bits are cleared). =item * C<$vector1 |= $vector2;> This statement performs a bitwise OR operation between the two bit vector operands and stores the result in the left operand. This is the same as calculating the union of two sets. =item * C<$vector1 &= $vector2;> This statement performs a bitwise AND operation between the two bit vector operands and stores the result in the left operand. This is the same as calculating the intersection of two sets. =item * C<$vector1 ^= $vector2;> This statement performs a bitwise XOR (exclusive-or) operation between the two bit vector operands and stores the result in the left operand. This is the same as calculating the symmetric difference of two sets. =item * C<$vector1 += $vector2;> Depending on the configuration (see the description of the method "C" for more details), this statement either performs a bitwise OR operation between the two bit vector operands (this is the same as calculating the union of two sets) - which is the default behaviour, or it calculates the sum of the two numbers stored in the two bit vector operands. The result of this operation is stored in the left operand. =item * C<$vector1 -= $vector2;> Depending on the configuration (see the description of the method "C" for more details), this statement either calculates the set difference of the two sets represented in the two bit vector operands - which is the default behaviour, or it calculates the difference of the two numbers stored in the two bit vector operands. The result of this operation is stored in the left operand. =item * C<$vector1 *= $vector2;> Depending on the configuration (see the description of the method "C" for more details), this statement either performs a bitwise AND operation between the two bit vector operands (this is the same as calculating the intersection of two sets) - which is the default behaviour, or it calculates the product of the two numbers stored in the two bit vector operands. The result of this operation is stored in the left operand. =item * C<$vector1 /= $vector2;> This statement puts the result of the division of the two numbers stored in the two bit vector operands into the left operand. =item * C<$vector1 %= $vector2;> This statement puts the remainder of the division of the two numbers stored in the two bit vector operands into the left operand. =item * C<$vector1 **= $vector2;> This statement puts the result of the exponentiation of the left operand elevated to the right operand's power into the left operand. =item * C<++$vector>, C<$vector++> This operator performs pre- and post-incrementation of the given bit vector. The value returned by this term is a reference of the given bit vector object (after or before the incrementation, respectively). =item * C<--$vector>, C<$vector--> This operator performs pre- and post-decrementation of the given bit vector. The value returned by this term is a reference of the given bit vector object (after or before the decrementation, respectively). =item * C<($vector1 cmp $vector2)> This term returns "C<-1>" if "C<$vector1>" is less than "C<$vector2>", "C<0>" if "C<$vector1>" and "C<$vector2>" are the same, and "C<1>" if "C<$vector1>" is greater than "C<$vector2>". This comparison assumes B bit vectors. =item * C<($vector1 eq $vector2)> This term returns true ("C<1>") if the contents of the two bit vector operands are the same and false ("C<0>") otherwise. =item * C<($vector1 ne $vector2)> This term returns true ("C<1>") if the two bit vector operands differ and false ("C<0>") otherwise. =item * C<($vector1 lt $vector2)> This term returns true ("C<1>") if "C<$vector1>" is less than "C<$vector2>", and false ("C<0>") otherwise. This comparison assumes B bit vectors. =item * C<($vector1 le $vector2)> This term returns true ("C<1>") if "C<$vector1>" is less than or equal to "C<$vector2>", and false ("C<0>") otherwise. This comparison assumes B bit vectors. =item * C<($vector1 gt $vector2)> This term returns true ("C<1>") if "C<$vector1>" is greater than "C<$vector2>", and false ("C<0>") otherwise. This comparison assumes B bit vectors. =item * C<($vector1 ge $vector2)> This term returns true ("C<1>") if "C<$vector1>" is greater than or equal to "C<$vector2>", and false ("C<0>") otherwise. This comparison assumes B bit vectors. =item * C<($vector1 E=E $vector2)> This term returns "C<-1>" if "C<$vector1>" is less than "C<$vector2>", "C<0>" if "C<$vector1>" and "C<$vector2>" are the same, and "C<1>" if "C<$vector1>" is greater than "C<$vector2>". This comparison assumes B bit vectors. =item * C<($vector1 == $vector2)> This term returns true ("C<1>") if the contents of the two bit vector operands are the same and false ("C<0>") otherwise. =item * C<($vector1 != $vector2)> This term returns true ("C<1>") if the two bit vector operands differ and false ("C<0>") otherwise. =item * C<($vector1 E $vector2)> Depending on the configuration (see the description of the method "C" for more details), this term either returns true ("C<1>") if "C<$vector1>" is a true subset of "C<$vector2>" (and false ("C<0>") otherwise) - which is the default behaviour, or it returns true ("C<1>") if "C<$vector1>" is less than "C<$vector2>" (and false ("C<0>") otherwise). The latter comparison assumes B bit vectors. =item * C<($vector1 E= $vector2)> Depending on the configuration (see the description of the method "C" for more details), this term either returns true ("C<1>") if "C<$vector1>" is a subset of "C<$vector2>" (and false ("C<0>") otherwise) - which is the default behaviour, or it returns true ("C<1>") if "C<$vector1>" is less than or equal to "C<$vector2>" (and false ("C<0>") otherwise). The latter comparison assumes B bit vectors. =item * C<($vector1 E $vector2)> Depending on the configuration (see the description of the method "C" for more details), this term either returns true ("C<1>") if "C<$vector1>" is a true superset of "C<$vector2>" (and false ("C<0>") otherwise) - which is the default behaviour, or it returns true ("C<1>") if "C<$vector1>" is greater than "C<$vector2>" (and false ("C<0>") otherwise). The latter comparison assumes B bit vectors. =item * C<($vector1 E= $vector2)> Depending on the configuration (see the description of the method "C" for more details), this term either returns true ("C<1>") if "C<$vector1>" is a superset of "C<$vector2>" (and false ("C<0>") otherwise) - which is the default behaviour, or it returns true ("C<1>") if "C<$vector1>" is greater than or equal to "C<$vector2>" (and false ("C<0>") otherwise). The latter comparison assumes B bit vectors. =back =head1 SEE ALSO Bit::Vector(3), Bit::Vector::String(3). =head1 VERSION This man page documents "Bit::Vector::Overload" version 7.4. =head1 AUTHOR Steffen Beyer mailto:STBEY@cpan.org http://www.engelschall.com/u/sb/download/ =head1 COPYRIGHT Copyright (c) 2000 - 2013 by Steffen Beyer. All rights reserved. =head1 LICENSE This package is free software; you can redistribute it and/or modify it under the same terms as Perl itself, i.e., under the terms of the "Artistic License" or the "GNU General Public License". The C library at the core of this Perl module can additionally be redistributed and/or modified under the terms of the "GNU Library General Public License". Please refer to the files "Artistic.txt", "GNU_GPL.txt" and "GNU_LGPL.txt" in this distribution for details! =head1 DISCLAIMER This package is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the "GNU General Public License" for more details.