Task: Find first and last set bit of a long integer




Go: package main

import (
    "fmt"
    "math/big"
)

const (
    mask0, bit0 = (1 << (1 << iota)) - 1, 1 << iota
    mask1, bit1
    mask2, bit2
    mask3, bit3
    mask4, bit4
    mask5, bit5
)

func rupb(x uint64) (out int) {
    if x == 0 {
        return -1
    }
    if x&^mask5 != 0 {
        x >>= bit5
        out |= bit5
    }
    if x&^mask4 != 0 {
        x >>= bit4
        out |= bit4
    }
    if x&^mask3 != 0 {
        x >>= bit3
        out |= bit3
    }
    if x&^mask2 != 0 {
        x >>= bit2
        out |= bit2
    }
    if x&^mask1 != 0 {
        x >>= bit1
        out |= bit1
    }
    if x&^mask0 != 0 {
        out |= bit0
    }
    return
}

func rlwb(x uint64) (out int) {
    if x == 0 {
        return 0
    }
    if x&mask5 == 0 {
        x >>= bit5
        out |= bit5
    }
    if x&mask4 == 0 {
        x >>= bit4
        out |= bit4
    }
    if x&mask3 == 0 {
        x >>= bit3
        out |= bit3
    }
    if x&mask2 == 0 {
        x >>= bit2
        out |= bit2
    }
    if x&mask1 == 0 {
        x >>= bit1
        out |= bit1
    }
    if x&mask0 == 0 {
        out |= bit0
    }
    return
}





func rupbBig(x *big.Int) int {
    return x.BitLen() - 1
}




func rlwbBig(x *big.Int) int {
    if x.BitLen() < 2 {
        return 0
    }
    bit := uint(1)
    mask := big.NewInt(1)
    var ms []*big.Int
    var y, z big.Int
    for y.And(x, z.Lsh(mask, bit)).BitLen() == 0 {
        ms = append(ms, mask)
        mask = new(big.Int).Or(mask, &z)
        bit <<= 1
    }
    out := bit
    for i := len(ms) - 1; i >= 0; i-- {
        bit >>= 1
        if y.And(x, z.Lsh(ms[i], out)).BitLen() == 0 {
            out |= bit
        }
    }
    return int(out)
}

func main() {
    show()
    showBig()
}

func show() {
    fmt.Println("uint64:")
    fmt.Println("power              number  rupb  rlwb")
    const base = 42
    n := uint64(1)
    for i := 0; i < 12; i++ {
        fmt.Printf("%d^%02d %19d %5d %5d\n", base, i, n, rupb(n), rlwb(n))
        n *= base
    }
}

func showBig() {
    fmt.Println("\nbig numbers:")
    fmt.Println("  power                               number  rupb  rlwb")
    base := big.NewInt(1302)
    n := big.NewInt(1)
    for i := 0; i < 12; i++ {
        fmt.Printf("%d^%02d %36d %5d %5d\n", base, i, n, rupbBig(n), rlwbBig(n))
        n.Mul(n, base)
    }
}








Ada: with Ada.Text_IO;
with Ada.Integer_Text_IO;
with Ada.Unchecked_Conversion;

procedure Find_Last_Bit is

   type My_Integer is range -2**63 .. 2**63 - 1;

   procedure Find_Set_Bits (Value   : in     My_Integer;
                            MSB_Bit :    out Integer;
                            LSB_Bit :    out Integer)
   is
      type Bit_Field is array (0 .. My_Integer'Size - 1) of Boolean;
      pragma Pack (Bit_Field);
      for Bit_Field'Size use My_Integer'Size;

      function To_Field is
         new Ada.Unchecked_Conversion (My_Integer, Bit_Field);

      Field : constant Bit_Field := To_Field (Value);
   begin

      LSB_Bit := -1;
      MSB_Bit := -1;

      for Bit in Field'Range loop
         if Field (Bit) then
            LSB_Bit := Bit;
            exit;
         end if;
      end loop;

      for Bit in reverse Field'Range loop
         if Field (Bit) then
            MSB_Bit := Bit;
            exit;
         end if;
      end loop;
   end Find_Set_Bits;


   procedure Put_Result (Value : in My_Integer) is
      package My_Integer_IO is
         new Ada.Text_IO.Integer_IO (My_Integer);
      use Ada.Text_IO;
      use Ada.Integer_Text_IO;
      Use My_Integer_IO;

      LSB_Bit, MSB_Bit : Integer;
      Placeholder : String := " MSB XX LSB YY";
      Image_MSB     : String renames Placeholder ( 6 ..  7);
      Image_LSB     : String renames Placeholder (13 .. 14);
   begin
      Find_Set_Bits (Value,
                     MSB_Bit => MSB_Bit,
                     LSB_Bit => LSB_Bit);
      Put (Value, Width => 18);
      Put (Value, Width => 66, Base => 2);
      Put (Image_MSB, MSB_Bit);
      Put (Image_LSB, LSB_Bit);
      Put_Line (Placeholder);
   end Put_Result;

begin
   Put_Result (Value => 0);
   for A in 0 .. 11 loop
      Put_Result (Value => 42 ** A);
   end loop;
end Find_Last_Bit;