[m-users.] Float array initialisation

Julien Fischer jfischer at opturion.com
Wed May 5 17:07:58 AEST 2021


Hi Fabrice,

On Wed, 5 May 2021, fabrice nicol wrote:

> I have some trouble interpreting the float-to-word/word-to-float
> conversion issue in the particular case of array initialisation.
> 
> This is performed by 'ML_init_array(MR_ArrayPtr array, MR_Integer size, MR_Word item)'  (DEV branch, array.m:1007), using an MR_Word initialiser 'item' in a simple loop:
> 
>         for (i = 0; i < size; i++) {
>             array->elements[i] = item;
>         }
> 
> Now, the manual says that some implementations have sizeof(MR_Float) >
> sizeof(MR_Word), which is why lists of floats should be converted
> using 'MR_word_to_float', as explained in the (snapshot) manual (p.
> 109):
> 
>     "The following fragment of C code illustrates the correct way to extract the head of a
>     Mercury list of floats.
>     MR_Float f;
>     f = MR_word_to_float(MR_list_head(list));
>     Omitting the call to MR_word_to_float in the above example would yield incorrect
>     results for implementations where ‘sizeof(MR_Float)’ is greater than ‘sizeof(MR_Word)’."
> 
> A cursory look at runtime/mercury_float.h points to it being necessary when MR_BOXED_FLOAT is defined.
> 
> So one would expect that the initialiser 'item', if of float type
> (i.e. in an 'array(float)'), would be checked as not exceeding the
> upper bound to MR_Word, when entered in init_2/3 (array.m:1494), at
> least if MR_BOXED_FLOAT is defined elsewhere. If this is the case, my
> guess is that the float initialiser item will not be passed unharmed
> to the above loop (behaviour may possibly be undefined).
> 
> The code in array.m has been too stable and polished for over 20 years
> now for it to be a real bug, so it must be that I did not catch
> something.

'item' does not have type float, it has type T.
If you have a look at the Mercury predicates that call ML_init_array(),
e.g.

     :- pred init_2(int::in, T::in, array(T)::array_uo) is det.
     :- pragma foreign_proc("C",
         init_2(Size::in, Item::in, Array::array_uo),
         [will_not_call_mercury, promise_pure, thread_safe],
     "
         ML_alloc_array(Array, Size + 1, MR_ALLOC_ID);
         ML_init_array(Array, Size, Item);
     ").

you'll see that the argument corresponding to 'item' is type variable,
which as per the reference manual is passed as a value of type MR_Word.
If you call that predicate with a float in the item position, then it
will boxed (if required) before the call.

You only need to use the MR_word_to_float and MR_float_to_word (and
the corresponding 64-bit integer versions) when passing floats to-
and from polymorphic Mercury data structures in C (e.g. lists, arrays
etc).

Julien.


More information about the users mailing list