
(********************************************************************)
(*                                                                  *)
(*  bin32.s7i     32-bit binary value support library               *)
(*  Copyright (C) 2013  Thomas Mertes                               *)
(*                                                                  *)
(*  This file is part of the Seed7 Runtime Library.                 *)
(*                                                                  *)
(*  The Seed7 Runtime Library 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.                                      *)
(*                                                                  *)
(*  The Seed7 Runtime 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 program; if not, write to the    *)
(*  Free Software Foundation, Inc., 51 Franklin Street,             *)
(*  Fifth Floor, Boston, MA  02110-1301, USA.                       *)
(*                                                                  *)
(********************************************************************)


(**
 *  Binary values with 32 bits.
 *  This type is intended for bit operations that are not defined
 *  for integer values. The internal representation is the same as
 *  for integer.
 *)
const type: bin32 is subtype object;

const proc: destroy (ref bin32 param)                          is action "GEN_DESTR";
const proc: (ref bin32 param) ::= (ref bin32 param)            is action "INT_CREATE";
IN_PARAM_IS_VALUE(bin32);

const proc: (inout bin32: dest) := (in bin32: source)          is action "INT_CPY";


(**
 *  Convert to integer.
 *  @return the unchanged value as integer.
 *)
const func integer: (attr integer) conv (in bin32: binValue)   is action "INT_CONV";


(**
 *  Convert to bin32.
 *  @return the unchanged value as bin32.
 *)
const func bin32: (attr bin32) conv (in integer: anInt)        is action "INT_CONV";


(**
 *  Convert to integer.
 *  @return the unchanged value as integer.
 *)
const func integer: ord (in bin32: binValue)                   is action "INT_ORD";


(**
 *  Convert to bin32.
 *  @return the unchanged value as bin32.
 *)
const func bin32: bin32 (in integer: number)                   is action "INT_ORD";


const bin32: (attr bin32) . value   is bin32(0);


(**
 *  Convert to bin32.
 *  @return the unchanged value as bin32.
 *)
const func bin32: bin32 (in char: ch) is
  return bin32(ord(ch));


(**
 *  Convert an ''bin32'' value to a [[string]].
 *  The values is converted to a string with decimal representation.
 *  @return the string result of the conversion.
 *  @exception MEMORY_ERROR Not enough memory to represent the result.
 *)
const func string: str (in bin32: number)                      is action "INT_STR";


(**
 *  Convert an ''bin32'' value to a [[string]] using a radix.
 *  The conversion uses the numeral system with the given ''base''.
 *  Digit values from 10 upward are encoded with lower case letters.
 *  E.g.: 10 is encoded with a, 11 with b, etc.
 *  @return the string result of the conversion.
 *  @exception RANGE_ERROR When base < 2 or base > 36 holds.
 *  @exception MEMORY_ERROR Not enough memory to represent the result.
 *)
const func string: (in bin32: number) radix (in integer: base) is action "INT_radix";


(**
 *  Convert an ''bin32'' value to a [[string]] using a radix.
 *  The conversion uses the numeral system with the given ''base''.
 *  Digit values from 10 upward are encoded with upper case letters.
 *  E.g.: 10 is encoded with A, 11 with B, etc.
 *  @return the string result of the conversion.
 *  @exception RANGE_ERROR When base < 2 or base > 36 holds.
 *  @exception MEMORY_ERROR Not enough memory to represent the result.
 *)
const func string: (in bin32: number) RADIX (in integer: base) is action "INT_RADIX";


(**
 *  Check if two bin32 values are equal.
 *  @return TRUE if the two values are equal,
 *          FALSE otherwise.
 *)
const func boolean: (in bin32: binary1) = (in bin32: binary2)  is action "INT_EQ";


(**
 *  Check if two bin32 values are not equal.
 *  @return FALSE if both values are equal,
 *          TRUE otherwise.
 *)
const func boolean: (in bin32: binary1) <> (in bin32: binary2) is action "INT_NE";


(**
 *  Compute a bitwise ''and'' of two bin32 values.
 *  @return the bitwise ''and'' of the two values.
 *)
const func bin32: (in bin32: binary1) & (in bin32: binary2)    is action "INT_AND";


(**
 *  Compute a bitwise inclusive ''or'' of two bin32 values.
 *  @return the bitwise inclusive ''or'' of the two values.
 *)
const func bin32: (in bin32: binary1) | (in bin32: binary2)    is action "INT_OR";


(**
 *  Compute a bitwise exclusive or (''xor'') of two bin32 values.
 *  @return the bitwise ''xor'' of the two values.
 *)
const func bin32: (in bin32: binary1) >< (in bin32: binary2)   is action "INT_XOR";


(**
 *  Compute a bitwise ''not'' of a bin32 value.
 *  @return the bitwise ''not'' of the value.
 *)
const func bin32: ~ (in bin32: aBinary) is
  return aBinary >< bin32(16#ffffffff);


(**
 *  Shift a bin32 value left by lshift bits.
 *  @return the left shifted value.
 *  @exception NUMERIC_ERROR The shift count is negative (may be raised).
 *)
const func bin32: (in bin32: binValue) << (in integer: lshift) is action "INT_LSHIFT";


(**
 *  Shift a bin32 value right by rshift bits.
 *  @return the right shifted value.
 *  @exception NUMERIC_ERROR The shift count is negative (may be raised).
 *)
const func bin32: (in bin32: binValue) >> (in integer: lshift) is action "INT_URSHIFT";


(**
 *  Shift a bin32 value left by lshift bits and assign the result back to ''binValue''.
 *)
const proc: (inout bin32: binValue) <<:= (in integer: lshift)  is action "INT_LSHIFT_ASSIGN";


(**
 *  Shift a bin32 value right by rshift bits and assign the result back to ''binValue''.
 *)
const proc: (inout bin32: binValue) >>:= (in integer: rshift)  is action "INT_URSHIFT_ASSIGN";


(**
 *  Compute a bitwise ''and'' and assign the result back to ''binary1''.
 *)
const proc: (inout bin32: binary1) &:= (in bin32: binary2)     is action "INT_AND_ASSIGN";


(**
 *  Compute a bitwise inclusive ''or'' and assign the result back to ''binary1''.
 *)
const proc: (inout bin32: binary1) |:= (in bin32: binary2)     is action "INT_OR_ASSIGN";


(**
 *  Compute a bitwise exclusive or (''xor'') and assign the result back to ''binary1''.
 *)
const proc: (inout bin32: binary1) ><:= (in bin32: binary2)    is action "INT_XOR_ASSIGN";


(**
 *  Rotate the bits of a bin32 value left by shiftCount bits.
 *  The vacant bit positions at the right side are filled in with
 *  the bits that are shifted out at the left side.
 *  @return the left rotated value.
 *  @exception NUMERIC_ERROR The shift count is negative (may be raised).
 *)
const func bin32: rotLeft (in bin32: x, in integer: shiftCount) is
  return (x << shiftCount | x >> (32 - shiftCount)) & bin32(16#ffffffff);


(**
 *  Rotate the bits of a bin32 value right by shiftCount bits.
 *  The vacant bit positions at the left side are filled in with
 *  the bits that are shifted out at the right side.
 *  @return the right rotated value.
 *  @exception NUMERIC_ERROR The shift count is negative (may be raised).
 *)
const func bin32: rotRight (in bin32: x, in integer: shiftCount) is
  return (x >> shiftCount | x << (32 - shiftCount)) & bin32(16#ffffffff);


# Allows 'array bin32' everywhere without extra type definition.
const type: _bin32Array is array bin32;


enable_output(bin32);
