[mercury-users] Question
Ralph Becket
rafe at csse.unimelb.edu.au
Thu Oct 12 13:47:25 AEST 2006
doug.auclair at logicaltypes.com, Wednesday, 11 October 2006:
> >Anthony Lee Senyard did a PhD here at Melbourne a few years ago on just
> >this topic and used Mercury for his work. He would be a good person to
> >talk to if you want to track him down.
>
> Can I get in touch with Anthony and is the work available for perusal?
Anthony's University web page is
http://www.cs.mu.oz.au/~anthls/php/home.php
which should tell you how to contact him. I don't know about the status
of his code.
> >For Anthony I implemented a special unboxed, full-precision float array
> >type which sped his programs up substantially. I'd be happy to let you
> >have a copy.
>
> Would you please provide me a copy as well? I will be using it immediately.
Attached, usual disclaimers of no warranty etc. apply.
> >but it has not been highly
> >optimized for floating point intensive applications. (Of course, that
> >could change if enough users make the request...)
>
> Even though there is not this optimization, so far Mercury has been
> more than up to the task for our needs (a floating-point enhancement
> will be icing on the cake).
As I say, on a 64 bit machine Mercury should perform about as well as
any other general purpose language in this regard. As far as I know,
it's only the boxing issue that can affect performance on 32 bit
machines.
-- Ralph
-------------- next part --------------
%------------------------------------------------------------------------------%
% farray.m
% Ralph Becket <rbeck at microsoft.com>
% Mon Oct 8 15:20:35 EST 2001
% vim: ts=4 sw=4 et tw=0 wm=0 ff=unix ft=mercury
%
% Basic unboxed float array ADT.
%
%------------------------------------------------------------------------------%
:- module farray.
:- interface.
:- import_module int, float, list, string.
:- type farray.
:- inst farray == ground. % XXX A hack: should not be public...
:- mode farray_uo == out(farray). % XXX )
:- mode farray_ui == in(farray). % XXX ) To be fixed when unique modes
:- mode farray_di == in(farray). % XXX ) get sorted out.
% new(N): a new array of N floats indexed from 0 to N-1
% initialized to 0.0. An exception is thrown if N is
% negative.
%
:- func new(int) = farray.
:- mode new(in) = farray_uo is det.
% Construct a new farray from a list of floats.
%
:- func farray(list(float)) = farray.
:- mode farray(in) = farray_uo is det.
% Copy an farray.
%
:- func copy(farray) = farray.
:- mode copy(farray_ui) = farray_uo is det.
% Resize an farray. Any new members are initialized to 0.0.
% An exception is thrown if the new size is negative.
%
:- func resize(farray, int) = farray.
:- mode resize(farray_ui, in) = farray_uo is det.
% size(A): the number of elements in the farray A.
%
:- func size(farray) = int.
:- mode size(farray_ui) = out is det.
% A ^ elem(I): the element of farray A with index I. An exception
% is raised if I is outside the range 0..size(A).
%
:- func elem(int, farray) = float.
:- mode elem(in, farray_ui) = out is det.
% A version of the above that does not perform bounds checking.
%
:- func unsafe_elem(int, farray) = float.
:- mode unsafe_elem(in, farray_ui) = out is det.
% lookup(A, I, X): succeeds with X = A ^ elem(I) iff 0 =< I < size(A).
%
:- pred lookup(farray, int, float).
:- mode lookup(farray_ui, in, out) is semidet.
% A ^ elem(I) := X: the farray A destructively updated s.t.
% element I now contains X. An exception is thrown if I is outside
% the range 0..size(A).
%
:- func 'elem :='(int, farray, float) = farray.
:- mode 'elem :='(in, farray_di, in) = farray_uo is det.
% A version of the above that does not perform bounds checking.
%
:- func 'unsafe_elem :='(int, farray, float) = farray.
:- mode 'unsafe_elem :='(in, farray_di, in) = farray_uo is det.
% to_str(A): a string representation of farray A.
%
:- func to_str(farray) = string.
:- mode to_str(farray_ui) = out is det.
%------------------------------------------------------------------------------%
%------------------------------------------------------------------------------%
:- implementation.
:- import_module exception, string, pprint.
:- pragma foreign_decl("C",
"
typedef struct {
MR_Integer size;
MR_Float* elem;
} farray;
#define FARRAY(A) ((farray *) A)
").
% This helps avoid confusing farrays with other types defined
% via c_pointer.
%
:- type farray ---> farray(c_pointer).
%------------------------------------------------------------------------------%
new(N) = unsafe_new(N) :-
( if N < 0 then throw("farray__new: negative array size") else true ).
:- func unsafe_new(int::in) = (farray::farray_uo) is det.
:- pragma foreign_proc(
"C",
unsafe_new(N::in) = (A::farray_uo),
[will_not_call_mercury, thread_safe],
"
{
int i;
FARRAY(A) = FARRAY(malloc(sizeof(farray)));
FARRAY(A)->size = N;
FARRAY(A)->elem = (MR_Float *) calloc(N, sizeof(MR_Float));
for(i = 0; i < N; i++)
FARRAY(A)->elem[i] = 0.0;
}
").
%------------------------------------------------------------------------------%
resize(A0, N) = copy_elems(0, min(N, size(A0)), A0, farray__new(N)).
:- func copy_elems(int, int, farray, farray) = farray.
:- mode copy_elems(in, in, farray_ui, farray_di) = farray_uo is det.
copy_elems(I, Hi, A, B) =
( if I < Hi then copy_elems(I + 1, Hi, A, B ^ elem(I) := A ^ elem(I))
else B
).
%------------------------------------------------------------------------------%
:- pragma foreign_proc(
"C",
copy(A0::farray_ui) = (A::farray_uo),
[will_not_call_mercury, thread_safe],
"
{
int i;
MR_Integer N = FARRAY(A0)->size;
FARRAY(A) = FARRAY(malloc(sizeof(farray)));
FARRAY(A)->size = N;
FARRAY(A)->elem = (MR_Float *) calloc(N, sizeof(MR_Float));
for(i = 0; i < N; i++)
FARRAY(A)->elem[i] = FARRAY(A0)->elem[i];
}
").
%------------------------------------------------------------------------------%
farray(Xs) = assign_elems(Xs, 0, farray__new(length(Xs))).
:- func assign_elems(list(float), int, farray) = farray.
:- mode assign_elems(in, in, farray_di) = farray_uo is det.
assign_elems([], _, A) = A.
assign_elems([X | Xs], I, A) = assign_elems(Xs, I + 1, A ^ elem(I) := X).
%------------------------------------------------------------------------------%
:- pragma foreign_proc(
"C",
size(A::farray_ui) = (N::out),
[will_not_call_mercury, thread_safe],
"
N = FARRAY(A)->size;
").
%------------------------------------------------------------------------------%
elem(I, A) = unsafe_elem(I, A) :-
range_check("farray__elem", A, I).
:- pragma foreign_proc(
"C",
unsafe_elem(I::in, A::farray_ui) = (X::out),
[will_not_call_mercury, thread_safe],
"
X = FARRAY(A)->elem[I];
").
lookup(A, I, X) :-
0 =< I,
I =< size(A),
X = A ^ unsafe_elem(I).
%------------------------------------------------------------------------------%
'elem :='(I, A, X) = 'unsafe_elem :='(I, A, X) :-
range_check("farray__'elem :='", A, I).
:- pragma foreign_proc(
"C",
'unsafe_elem :='(I::in, A0::farray_di, X::in) = (A::farray_uo),
[will_not_call_mercury, thread_safe],
"
FARRAY(A0)->elem[I] = X;
A = A0;
").
%------------------------------------------------------------------------------%
:- pred range_check(string::in, farray::farray_ui, int::in) is det.
range_check(Str, A, I) :-
( if I < 0 ; size(A) =< I then throw(Str ++ ": index out of bounds")
else true
).
%------------------------------------------------------------------------------%
to_str(A) = S :-
Xs = elems(0, A),
S =
to_string(80,
text("farray") `<>` parentheses(
brackets(separated(to_doc, group(comma_space_line), Xs))
)
).
:- func elems(int, farray) = list(float).
:- mode elems(in, farray_ui) = out is det.
elems(I, A) =
( if I < size(A) then [A ^ elem(I) | elems(I + 1, A)] else [] ).
%------------------------------------------------------------------------------%
%------------------------------------------------------------------------------%
More information about the users
mailing list