Converting an integer value to Universal_Integer

The original task is to multiply a Fixed’Small by some integer value in order to convert an integral value to the corresponding fixed-point value. This seems impossible in Ada. Well, GNAT has a secret attribute for the purpose T’Fixed_Value (V), but I want it be vendor-independent.

The idea is use this:

function "*"(Left : root_real; Right : root_integer) return root_real;

So I could do it if I managed to convert an integer V to Universal_Integer. So the question is what were the best easiest way to do so. Here is what I came to so far. I used the A’Length attribute. Let V be an integer value and Fixed be a fixed-point type. Then:

declare
   type A is array (1..V) of Boolean;
   Result : Fixed := Fixed  (Fixed'Small * A'Length); -- Fixed 'Small * V

Which indeed works.

Any ideas to make it better?

So I found this in the RM 3.5.4 14

This makes me think that universal integer is bounded by Min_Int and Max_Int since it says that Integer literals are all of the type universal_integer, the universal type (see 3.4.1) for the class rooted at root_integer, allowing their use with the operations of any integer type. and then root_integer, an anonymous predefined (specific) integer type, whose base range is System.Min_Int .. System.Max_Int

Just my thoughts, but I don’t know for sure.

You should be able to declare an array indexed by a modular type, therefore you could come to values larger than Max_Int.
Robert Duff once explained in comp.lang.ada how universal types leak into run-time, though I do not remember the details, in particular how much could you lean out of the window of built-in types.

The Pos attribute also returns universal integer, so you might be able to use that to convert a value to universal integer?

function S'Pos(Arg : S'Base)
  return universal_integer

You keep running into the exact motivations for the abstracted-type/-interface (the meta-language or traits or whatever you want to term them) that I want.

Yes! This is a much better one!

Fixed (Fixed'Small * V_Type'Pos (V));

Nope, the problem is that universal types lack run-time instances unless leaking through attributes. I think it was so by design. Otherwise the root types would require unbounded implementations at run time and conversions between them and scalar descendants, which for Ada 83 was unthinkable. Not to mention that unbounded real types are fundamentally non-implementable on a finite-state machine. You can only implement rational ones.

But you are welcome to illustrate how traits would solve the problem.