Task: Isqrt (integer square root) of X


C++: #include <iomanip>
#include <iostream>
#include <sstream>
#include <boost/multiprecision/cpp_int.hpp>

using big_int = boost::multiprecision::cpp_int;

template <typename integer>
integer isqrt(integer x) {
    integer q = 1;
    while (q <= x)
        q <<= 2;
    integer r = 0;
    while (q > 1) {
        q >>= 2;
        integer t = x - r - q;
        r >>= 1;
        if (t >= 0) {
            x = t;
            r += q;
        }
    }
    return r;
}

std::string commatize(const big_int& n) {
    std::ostringstream out;
    out << n;
    std::string str(out.str());
    std::string result;
    size_t digits = str.size();
    result.reserve(4 * digits/3);
    for (size_t i = 0; i < digits; ++i) {
        if (i > 0 && i % 3 == digits % 3)
            result += ',';
        result += str[i];
    }
    return result;
}

int main() {
    std::cout << "Integer square root for numbers 0 to 65:\n";
    for (int n = 0; n <= 65; ++n)
        std::cout << isqrt(n) << ' ';
    std::cout << "\n\n";

    std::cout << "Integer square roots of odd powers of 7 from 1 to 73:\n";
    const int power_width = 83, isqrt_width = 42;
    std::cout << " n |"
        << std::setw(power_width) << "7 ^ n" << " |"
        << std::setw(isqrt_width) << "isqrt(7 ^ n)"
        << '\n';
    std::cout << std::string(6 + power_width + isqrt_width, '-') << '\n';
    big_int p = 7;
    for (int n = 1; n <= 73; n += 2, p *= 49) {
        std::cout << std::setw(2) << n << " |"
            << std::setw(power_width) << commatize(p) << " |"
            << std::setw(isqrt_width) << commatize(isqrt(p))
            << '\n';
    }
    return 0;
}










Ada: with Ada.Text_Io;
with Ada.Numerics.Big_Numbers.Big_Integers;
with Ada.Strings.Fixed;

procedure Integer_Square_Root is

   use Ada.Numerics.Big_Numbers.Big_Integers;
   use Ada.Text_Io;

   function Isqrt (X : Big_Integer) return Big_Integer is
      Q       : Big_Integer := 1;
      Z, T, R : Big_Integer;
   begin
      while Q <= X loop
         Q := Q * 4;
      end loop;
      Z := X;
      R := 0;
      while Q > 1 loop
         Q := Q / 4;
         T := Z - R - Q;
         R := R / 2;
         if T >= 0 then
            Z := T;
            R := R + Q;
         end if;
      end loop;
      return R;
   end Isqrt;

   function Commatize (N : Big_Integer; Width : Positive) return String is
      S     : constant String := To_String (N, Width);
      Image : String (1 .. Width + Width / 3) := (others => ' ');
      Pos   : Natural := Image'Last;
   begin
      for I in S'Range loop
         Image (Pos) := S (S'Last - I + S'First);
         exit when Image (Pos) = ' ';
         Pos := Pos - 1;
         if I mod 3 = 0 and S (S'Last - I + S'First - 1) /= ' ' then
            Image (Pos) := ''';
            Pos := Pos - 1;
         end if;
      end loop;
      return Image;
   end Commatize;

   type Mode_Kind is (Tens, Ones, Spacer, Result);
begin
   Put_Line ("Integer square roots of integers 0 .. 65:");
   for Mode in Mode_Kind loop
      for N in 0 .. 65 loop
         case Mode is
            when Tens   =>  Put ((if N / 10 = 0
                                  then "  "
                                  else Natural'Image (N / 10)));
            when Ones   =>  Put (Natural'Image (N mod 10));
            when Spacer =>  Put ("
            when Result =>  Put (To_String (Isqrt (To_Big_Integer (N))));
         end case;
      end loop;
      New_Line;
   end loop;
   New_Line;

   declare
      package Integer_Io is new Ada.Text_Io.Integer_Io (Natural);
      use Ada.Strings.Fixed;
      N    : Integer    := 1;
      P, R : Big_Integer;
   begin
      Put_Line ("|  N|" & 80 * " " & "7**N|" & 30 * " " & "isqrt (7**N)|");
      Put_Line (133 * "=");
      loop
         P := 7**N;
         R := Isqrt (P);
         Put ("|");  Integer_Io.Put (N, Width => 3);
         Put ("|");  Put (Commatize (P, Width => 63));
         Put ("|");  Put (Commatize (R, Width => 32));
         Put ("|");  New_Line;
         exit when N >= 73;
         N := N + 2;
      end loop;
      Put_Line (133 * "=");
   end;

end Integer_Square_Root;