create or replace package bw as /************************************************************************** ** ** Generic Binary Operations Library for Signed and Unsigned ** Numbers of Variable Word Size ** ** Version 1.0, 6/11/98 ** Licensing updated 4/29/02 ** ** Based on Kevin Taufner's version 1.0, 7/20/97, Util package. ** ** Written by Keith Gardner ** Email: keith.gardner@earthlink.net ** ** Please note that the software defaults to signed and variable word ** size. Most software uses 32-bit unsigned operations. Use of the ** library with default settings to variable word size may result ** in failure of your application since an intended 32-bit word can ** "grow" into an unintended 33-bit word with the use of variable word ** sizes. fast_bw.txt provides an optimized library that performs only ** 32-bit unsigned operations and automatically trims computations to ** 32-bit word size. ** ** Please send comments, corrections, and improvements. ** **------------------------------------------------------------------------- ** ** Copyright (C) 1998, 2002 Wallace Keith Gardner. ** All rights reserved. ** ** This file is free software; you can redistribute it and/or ** modify it under the terms of the GNU Lesser General Public ** License as published by the Free Software Foundation; either ** version 2.1 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 ** Lesser General Public License for more details. ** ** You should have received a copy of the GNU Lesser 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 ** ** You must download, read, agree, and retain a copy of the GNU Lesser ** General Public License with this software. It can be found at: ** ** http://cellar.sourceforge.net/lesser.txt ** ** You must download, read, agree, and retain a copy of the Terms ** of Use and Disclaimer with this software. It can be found at: ** ** http://cellar.sourceforge.net/terms.txt ** ***************************************************************************/ function op ( value1 in number, operation in varchar2, value2 in number, signed in integer := 1, bits in integer := null) return number; function comp ( value in number, signed in integer := 1, bits in integer := null) return number; function lshift ( value in number, times in integer := 1, signed in integer := 1, bits in integer := null) return number; function rshift ( value in number, times in integer := 1, signed in integer := 1, bits in integer := null) return number; function lrot ( value in number, times in integer := 1, signed in integer := 1, bits in integer := null) return number; function rrot ( value in number, times in integer := 1, signed in integer := 1, bits in integer := null) return number; function reword ( value in number, signed in integer := 1, bits in integer := null) return number; function hexdump ( value in varchar2) return varchar2; PRAGMA RESTRICT_REFERENCES(bw, WNDS); PRAGMA RESTRICT_REFERENCES(op, WNDS); PRAGMA RESTRICT_REFERENCES(comp, WNDS); PRAGMA RESTRICT_REFERENCES(lshift, WNDS); PRAGMA RESTRICT_REFERENCES(rshift, WNDS); PRAGMA RESTRICT_REFERENCES(lrot, WNDS); PRAGMA RESTRICT_REFERENCES(rrot, WNDS); PRAGMA RESTRICT_REFERENCES(reword, WNDS); PRAGMA RESTRICT_REFERENCES(hexdump, WNDS); end bw; / create or replace package body bw as /********************************************************************** ** ** FUNCTION op ** **********************************************************************/ function op ( value1 in number, operation in varchar2, value2 in number, signed in integer := 1, bits in integer := null) return number is do_op varchar2(3); working1 integer; working2 integer; bits1 integer; bits2 integer; greatest_bits integer; result1 number; result2 number; result number := 0; begin -- make all upper do_op := upper(operation); -- determine number of bits of each number if (bits is not null) then working1 := bw.reword(value1, signed, bits); working2 := bw.reword(value2, signed, bits); bits1 := bits; bits2 := bits; else select vsize(value1)*8 into bits1 from dual; select vsize(value2)*8 into bits2 from dual; working1 := value1; working2 := value2; end if; greatest_bits := greatest(bits1,bits2); -- get the two's complement representation of negative numbers if (working1 < 0) then working1 := bw.comp(abs(working1), 0, greatest_bits) + 1; end if; if (working2 < 0) then working2 := bw.comp(abs(working2), 0, greatest_bits) + 1; end if; -- XOR operation if (do_op = 'XOR') then for i in reverse 0..greatest_bits loop result1 := working1 - (2**(i)); result2 := working2 - (2**(i)); if (result1 >= 0 and result2 < 0) then -- 1 and 0 working1 := result1; result := result + (2**(i)); elsif (result1 < 0 and result2 >= 0) then -- 0 and 1 working2 := result2; result := result + (2**(i)); elsif (result1 >= 0 and result2 >= 0) then -- 1 and 1 working1 := result1; working2 := result2; end if; end loop; -- OR operation elsif (do_op = 'OR') then for i in reverse 0..greatest_bits loop result1 := working1 - (2**(i)); result2 := working2 - (2**(i)); if (result1 >= 0 and result2 < 0) then -- 1 and 0 working1 := result1; result := result + (2**(i)); elsif (result1 < 0 and result2 >= 0) then -- 0 and 1 working2 := result2; result := result + (2**(i)); elsif (result1 >= 0 and result2 >= 0) then -- 1 and 1 working1 := result1; working2 := result2; result := result + (2**(i)); end if; end loop; -- AND operation else for i in reverse 0..greatest_bits loop result1 := working1 - (2**(i)); result2 := working2 - (2**(i)); if (result1 >= 0 and result2 < 0) then -- 1 and 0 working1 := result1; elsif (result1 < 0 and result2 >= 0) then -- 0 and 1 working2 := result2; elsif (result1 >= 0 and result2 >= 0) then -- 1 and 1 working1 := result1; working2 := result2; result := result + (2**(i)); end if; end loop; end if; -- if the result is signed, then find the signed representation if (signed = 1) then if (result >= (2**(greatest_bits - 1))) then result := -1 * bw.comp(result - 1, 0, greatest_bits); end if; end if; -- return the result return result; end op; /********************************************************************** ** ** FUNCTION comp ** **********************************************************************/ function comp ( value in number, signed in integer := 1, bits in integer := null) return number is working1 integer; working2 integer; bits1 integer; bits2 integer; result1 number; result2 number; result number := 0; begin -- determine the bits and second value of Xor operation if (bits is not null) then bits1 := bits; working1 := bw.reword(value, signed, bits); else select vsize(value)*8 into bits1 from dual; working1 := value; end if; bits2 := bits1; working2 := (2**(bits1)) - 1; -- get the two's complement representation of negative numbers if (working1 < 0) then working1 := bw.comp(abs(working1), 0, bits1) + 1; end if; -- calculate the complement by taking the Xor for i in reverse 0..bits1 loop result1 := working1 - (2**(i)); result2 := working2 - (2**(i)); if (result1 >= 0 and result2 < 0) then -- 1 and 0 working1 := result1; result := result + 2**(i); elsif (result1 < 0 and result2 >= 0) then -- 0 and 1 working2 := result2; result := result + 2**(i); elsif (result1 >= 0 and result2 >= 0) then -- 1 and 1 working1 := result1; working2 := result2; end if; end loop; -- if the result is signed, then find the signed representation if (signed = 1) then if (result >= (2**(bits1 - 1))) then result := -1 * bw.comp(result - 1, 0, bits1); end if; end if; -- return the result return result; end comp; /********************************************************************** ** ** FUNCTION lshift ** **********************************************************************/ function lshift ( value in number, times in integer := 1, signed in integer := 1, bits in integer := null) return number is working number; working_bits integer; result number := 0; begin -- determine number of bits. if (bits is not null) then working_bits := bits; else select vsize(value)*8 into working_bits from dual; end if; -- get the two's complement representation of negative numbers if (value < 0) then working := bw.comp(abs(value), 0, working_bits) + 1; else working := value; end if; -- left shift result := working * (2**(times)); -- truncate left side result := mod(result, 2**working_bits); -- truncate right side for negative times result := trunc(result); -- if the result is signed, then find the signed representation if (signed = 1) then if (result >= (2**(working_bits - 1))) then result := -1 * bw.comp(working_bits - 1, 0, working_bits); end if; end if; -- return the result return result; end lshift; /********************************************************************** ** ** FUNCTION rshift ** **********************************************************************/ function rshift ( value in number, times in integer := 1, signed in integer := 1, bits in integer := null) return number is working number; working_bits integer; result number := 0; begin -- determine number of bits if (bits is not null) then working_bits := bits; else select vsize(value)*8 into working_bits from dual; end if; -- get the two's complement representation of negative numbers if (value < 0) then working := bw.comp(abs(value), 0, working_bits) + 1; else working := value; end if; -- right shift (shift in 1 bits for signed negative numbers) if (value < 0 and signed = 1) then result := working / (2**(times)); for i in (working_bits - times + 1)..working_bits loop result := result + (2**(i - 1)); end loop; else result := working / (2**(times)); end if; -- truncate left side for negative times result := mod(result, 2**working_bits); -- truncate right side result := trunc(result); -- if the result is signed, then find the signed representation if (signed = 1) then if (result >= (2**(working_bits - 1))) then result := -1 * bw.comp(working_bits - 1, 0, working_bits); end if; end if; -- return the result return result; end rshift; /********************************************************************** ** ** FUNCTION lrot ** **********************************************************************/ function lrot ( value in number, times in integer := 1, signed in integer := 1, bits in integer := null) return number is bits1 integer; result number := 0; begin -- get the two's complement representation of negative numbers if (value < 0) then result := bw.comp(abs(value), 0, bits) + 1; else result := value; end if; -- determine the bits if (bits is not null) then bits1 := bits; result := bw.reword(result, signed, bits); else select vsize(result)*8 into bits1 from dual; end if; -- perform the rotation result := bw.op( bw.lshift(result, times, signed, bits1), 'OR', bw.rshift(result, bits1 - times, signed, bits1), signed, bits1); -- if the result is signed, then find the signed representation if (signed = 1) then if (result >= (2**(bits1 - 1))) then result := -1 * bw.comp(result - 1, 0, bits1); end if; end if; -- return the result return result; end lrot; /********************************************************************** ** ** FUNCTION rrot ** **********************************************************************/ function rrot ( value in number, times in integer := 1, signed in integer := 1, bits in integer := null) return number is bits1 integer; result number := 0; begin -- get the two's complement representation of negative numbers if (value < 0) then result := bw.comp(abs(value), 0, bits) + 1; else result := value; end if; -- determine the bits if (bits is not null) then bits1 := bits; result := bw.reword(result, signed, bits); else select vsize(result)*8 into bits1 from dual; end if; -- perform the rotation result := bw.op( bw.lshift(result, bits1 - times, signed, bits1), 'OR', bw.rshift(result, times, signed, bits1), signed, bits1); -- if the result is signed, then find the signed representation if (signed = 1) then if (result >= (2**(bits1 - 1))) then result := -1 * bw.comp(result - 1, 0, bits1); end if; end if; -- return the result return result; end rrot; /********************************************************************** ** ** FUNCTION reword ** **********************************************************************/ function reword ( value in number, signed in integer := 1, bits in integer := null) return number is result number := 0; begin -- get the two's complement representation of negative numbers if (value < 0) then result := bw.comp(abs(value), 0, bits) + 1; else result := value; end if; -- truncate high bits greater than the preferred word size if (bits is not null) then if (signed = 0) then result := mod(result,(2**(bits))); else result := mod(result,(2**(bits - 1))); end if; end if; -- if the result is signed, then find the signed representation if (signed = 1) then if (result >= (2**(bits - 1))) then result := -1 * bw.comp(result - 1, 0, bits); end if; end if; -- return the result return result; end reword; /********************************************************************** ** ** FUNCTION hexdump ** **********************************************************************/ function hexdump ( value in varchar2) return varchar2 is len integer; dec_value integer; dec_nibble1 integer; dec_nibble2 integer; result varchar2(2000); hex_digits varchar2(16) := '0123456789abcdef'; tmpf number; begin -- determine length of string len := length (value); if (len is null) then len := 0; end if; -- find the hex represenation of each character result := ''; for i in 1..len loop dec_value := ascii(substr(value, i, 1)); tmpf := dec_value; dec_nibble1 := trunc( tmpf / 16); dec_nibble2 := mod(dec_value, 16); result := result || substr(hex_digits, dec_nibble1 + 1, 1); result := result || substr(hex_digits, dec_nibble2 + 1, 1); end loop; -- return the result as a string of hex return result; end hexdump; end bw; / show errors;