package TestCase::BitOperator {
  # Complement
  sub complement : int () {
    my $num_byte = (byte)0xF0;
    my $num_short = (short)0xFFF0;
    my $num_int = 0xFFFFFFF0;
    my $num_long = 0xFFFFFFFFFFFFFFF0L;
    
    my $num_byte_complement : int = ~$num_byte;
    my $num_short_complement : int = ~$num_short;
    my $num_int_complement = ~$num_int;
    my $num_long_complement = ~$num_long;
    
    if ($num_byte_complement == (byte)0xF) {
      if ($num_short_complement == (short)0xF) {
        if ($num_int_complement == 0xF) {
          if ($num_long_complement == 0xFL) {
            return 1;
          }
        }
      }
    }
    
    return 0;
  }

  sub bit_shift_left_int_max : int () {
    
    # 01000000 00000000 00000000 00000000 << 1
    my $value = 0x40000000 << 1;
    
    # 10000000 00000000 00000000 00000000
    if ($value == 0x80000000) {
      return 1;
    }
    else {
      return 0;
    }
  }
  
  sub bit_shift_left_int_overflow : int () {
    
    # 10000000 00000000 00000000 00000000 << 1
    my $value = 0x80000000 << 1;
    
    # 00000000 00000000 00000000 00000000
    if ($value == 0) {
      return 1;
    }
    else {
      return 0;
    }
  }

  sub bit_shift_left_long : int () {
    
    # 00000011 00000000 00000000 00000000 00000000 00000000 00000000 00000000 << 2
    my $value = 0x3000000000000000L << 2;
    
    # 00001100 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
    if ($value == 0xC000000000000000L) {
      return 1;
    }
    else {
      return 0;
    }
  }
  
  sub bit_shift_left_long_max : int () {
    
    # 01000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000  << 1
    my $value = 0x4000000000000000L << 1;
    
    # 10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
    if ($value == 0x8000000000000000L) {
      return 1;
    }
    else {
      return 0;
    }
  }
  
  sub bit_shift_left_long_overflow : int () {
    
    # 10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000  << 1
    my $value = 0x8000000000000000L << 1;
    
    # 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 
    if ($value == 0L) {
      return 1;
    }
    else {
      return 0;
    }
  }
  sub bit_and : int () {
    # byte
    my $byte_success = 0;
    {
      my $value1 : int = (byte)0xFF & (byte)0x0F;
      if (($value1 & 0xFF) == 0x0F) {
        $byte_success = 1;
      }
    }

    unless ($byte_success) {
      return 0;
    }
    
    # short
    my $short_success = 0;
    {
      my $value1 : int = (short)0xFF00 & (short)0xF0F0;
      if (($value1 & 0xFFFF) == 0xF000) {
        $short_success = 1;
      }
    }
    
    unless ($short_success) {
      return 0;
    }
    
    # int
    my $int_success = 0;
    {
      my $value1 = 0xFF00 & 0xF0F0;
      if ($value1 == 0xF000) {
        $int_success = 1;
      }
    }
    
    # long
    my $long_success = 0;
    {
      my $value1 = 0xFF00FF00L & 0xF0F0F0F0L;
      if ($value1 == 0xF000F000L) {
        $long_success = 1;
      }
    }
    
    unless ($long_success) {
      return 0;
    }
    
    return 1;
  }

  sub bit_or : int () {
    # byte
    my $byte_success = 0;
    {
      my $value1 : int = (byte)0xF0 | (byte)0xFF;
      if (($value1 & 0xFF) == 0xFF) {
        $byte_success = 1;
      }
    }

    # short
    my $short_success = 0;
    {
      my $value1 : int = (short)0xFF00 | (short)0xF0F0;
      if (($value1 & 0xFFFF) == 0xFFF0) {
        $short_success = 1;
      }
    }

    # int
    my $int_success = 0;
    {
      my $value1 = 0xFF00 | 0xF0F0;
      if ($value1 == 0xFFF0) {
        $int_success = 1;
      }
    }
    
    # long
    my $long_success = 0;
    {
      my $value2 = 0xFF00FF00L | 0xF0F0F0F0L;
      if ($value2 == 0xFFF0FFF0L) {
        $long_success = 1;
      }
    }

    if ($byte_success && $short_success && $int_success && $long_success) {
      return 1;
    }
    
    return 0;
  }

  sub bit_xor : int () {
    # byte
    my $byte_success = 0;
    {
      my $value1 : int = (byte)0xF0 ^ (byte)0x0F;
      if (($value1 & 0xFF) == 0xFF) {
        $byte_success = 1;
      }
    }
    
    # short
    my $short_success = 0;
    {
      my $value1 : int = (short)0xFF00 ^ (short)0xF0F0;
      if (($value1 & 0xFFFF) == 0x0FF0) {
        $short_success = 1;
      }
    }
    
    # int
    my $int_success = 0;
    {
      my $value1 = 0xFF00 ^ 0xF0F0;
      if ($value1 == 0x0FF0) {
        $int_success = 1;
      }
    }
    
    # long
    my $long_success = 0;
    {
      my $value1 = 0xFF00FF00L ^ 0xF0F0F0F0L;
      if ($value1 == 0x0FF00FF0L) {
        $long_success = 1;
      }
    }
    
    if ($byte_success && $short_success && $int_success && $long_success) {
      return 1;
    }
    
    return 0;
  }

  sub bit_shift_right_logical_int : int () {
    # 11000000 00000000 00000000 00000001 >>> 2
    my $value = 0xC0000001 >>> 2;
    
    # 00110000 00000000 00000000 00000000
    if ($value == 0x30000000) {
      return 1;
    }
    else {
      return 0;
    }
  }
  
  sub bit_shift_right_logical_long : int () {
    # 11000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001 >>> 2
    my $value = 0xC000000000000001L >>> 2;
    
    # 00110000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
    if ($value == 0x3000000000000000L) {
      return 1;
    }
    else {
      return 0;
    }
  }

  sub bit_shift_right_int : int () {
    # 11000000 00000000 00000000 00000001 >> 2
    my $value = 0xC0000001 >> 2;
    
    # 11110000 00000000 00000000 00000000
    if ($value == 0xF0000000) {
      return 1;
    }
    else {
      return 0;
    }
  }
  
  sub bit_shift_right_long : int () {
    # 11000000 00000000 00000000 00000000 00000000 00000000 00000000 00000001 >> 2
    my $value = 0xC000000000000001L >> 2;
    
    # 11110000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
    if ($value == 0xF000000000000000L) {
      return 1;
    }
    else {
      return 0;
    }
  }
  
  # Bit shift left
  sub bit_shift_left_int : int () {
    
    # 00000011 00000000 00000000 00000000 << 2
    my $value = 0x30000000 << 2;
    
    # 00001100 00000000 00000000 00000000
    if ($value == 0xC0000000) {
      return 1;
    }
    else {
      return 0;
    }
  }
}