diff: float.m changes

Fergus Henderson fjh at cs.mu.oz.au
Mon Jul 14 16:11:37 AEST 1997


Hi,

Tom, can you please review this one?
(Since I moved a fair bit of stuff around, the diff may be a bit hard to
follow, and so I've included the float.m at the end as well.)

library/float.m:
	- Add a function `:- func float(int) = float.' for converting
	  from int to float.
	- Add function versions of all the predicates.
	- Reorder the declarations so that the functions and predicates
	  defined are grouped according to their purpose.
	- Add `pragma obsolete' declarations for all the
	  `builtin_float_*' predicates (XXX commented out for now,
	  until my recently committed change to simplify.m to avoid
	  spurious warnings has been installed on all our machines)
	  and move the declarations of those predicates so that they
	  don't appear in the Mercury Library Reference Manual.
	- Update the old `pragma(c_code, ...)' declarations to use
	  the next syntax for `pragma c_code'.

library/mercury_builtin.m:
	Use `<' and `>' rather than the obsolete predicates
	`builtin_float_lt' and `builtin_float_gt'.

Index: float.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/library/float.m,v
retrieving revision 1.21
diff -u -r1.21 float.m
--- float.m	1997/02/28 05:25:32	1.21
+++ float.m	1997/07/14 06:03:47
@@ -1,5 +1,5 @@
 %---------------------------------------------------------------------------%
-% Copyright (C) 1995 University of Melbourne.
+% Copyright (C) 1994-1997 University of Melbourne.
 % This file may only be copied under the terms of the GNU Library General
 % Public License - see the file COPYING.LIB in the Mercury distribution.
 %---------------------------------------------------------------------------%
@@ -17,57 +17,33 @@
 :- module float.
 :- interface.
 
-	% less than
-:- pred <(float, float).
-:- mode <(in, in) is semidet.
-
-	% greater than
-:- pred >(float, float).
-:- mode >(in, in) is semidet.
-
-	% less than or equal
-:- pred =<(float, float).
-:- mode =<(in, in) is semidet.
-
-	% greater than or equal
-:- pred >=(float, float).
-:- mode >=(in, in) is semidet.
-
-	% absolute value
-:- pred float__abs(float, float).
-:- mode float__abs(in, out) is det.
-
-	% maximum
-:- pred float__max(float, float, float).
-:- mode float__max(in, in, out) is det.
-
-	% minumim
-:- pred float__min(float, float, float).
-:- mode float__min(in, in, out) is det.
+%
+% Arithmetic functions
+%
 
 	% addition
 :- func float + float = float.
 :- mode in    + in    = uo  is det.
-:- mode uo  + in  = in  is det.
-:- mode in  + uo  = in  is det.
+:- mode uo    + in    = in  is det.
+:- mode in    + uo    = in  is det.
 
 	% subtraction
 :- func float - float = float.
 :- mode in    - in    = uo  is det.
-:- mode uo  - in  = in  is det.
-:- mode in  - uo  = in  is det.
+:- mode uo    - in    = in  is det.
+:- mode in    - uo    = in  is det.
 
 	% multiplication
 :- func float * float = float.
 :- mode in    * in    = uo  is det.
-:- mode uo  * in  = in  is det.
-:- mode in  * uo  = in  is det.
+:- mode uo    * in    = in  is det.
+:- mode in    * uo    = in  is det.
 
 	% division
 :- func float / float = float.
 :- mode in    / in    = uo  is det.
-:- mode uo  / in  = in  is det.
-:- mode in  / uo  = in  is det.
+:- mode uo    / in    = in  is det.
+:- mode in    / uo    = in  is det.
 
 	% unary plus
 :- func + float = float.
@@ -77,71 +53,152 @@
 :- func - float = float.
 :- mode - in    = uo  is det.
 
-%---------------------------------------------------------------------------%
+%
+% Comparison predicates
+%
 
-/* The following are predicates which do the same thing as the
-   above functions.  They are obsolete.  Don't use them.
-   They will eventually disappear in some future release.
-*/
+	% less than
+:- pred <(float, float).
+:- mode <(in, in) is semidet.
 
-:- pred builtin_float_plus(float, float, float).
-:- mode builtin_float_plus(in, in, uo) is det.
+	% greater than
+:- pred >(float, float).
+:- mode >(in, in) is semidet.
 
-:- pred builtin_float_minus(float, float, float).
-:- mode builtin_float_minus(in, in, uo) is det.
+	% less than or equal
+:- pred =<(float, float).
+:- mode =<(in, in) is semidet.
 
-:- pred builtin_float_times(float, float, float).
-:- mode builtin_float_times(in, in, uo) is det.
+	% greater than or equal
+:- pred >=(float, float).
+:- mode >=(in, in) is semidet.
 
-:- pred builtin_float_divide(float, float, float).
-:- mode builtin_float_divide(in, in, uo) is det.
+%
+% Conversion functions
+%
 
-:- pred builtin_float_gt(float, float).
-:- mode builtin_float_gt(in, in) is semidet.
+	% Convert int to float
+:- func float(int) = float.
 
-:- pred builtin_float_lt(float, float).
-:- mode builtin_float_lt(in, in) is semidet.
+	% ceiling_to_int(X) returns the
+	% smallest integer not less than X.
+:- func ceiling_to_int(float) = int.
 
-:- pred builtin_float_ge(float, float).
-:- mode builtin_float_ge(in, in) is semidet.
+	% floor_to_int(X) returns the
+	% largest integer not greater than X.
+:- func floor_to_int(float) = int.
 
-:- pred builtin_float_le(float, float).
-:- mode builtin_float_le(in, in) is semidet.
+	% round_to_int(X) returns the integer closest to X.
+	% If X has a fractional value of 0.5, it is rounded up.
+:- func round_to_int(float) = int.
+
+	% truncate_to_int(X) returns 
+	% the integer closest to X such that |truncate_to_int(X)| =< |X|.
+:- func truncate_to_int(float) = int.
+
+%
+% Miscellaneous functions
+%
+
+	% absolute value
+:- func abs(float) = float.
+
+	% maximum
+:- func max(float, float) = float.
+
+	% minimum
+:- func min(float, float) = float.
+
+	% pow(Base, Exponent) returns Base raised to the power Exponent.
+	% The exponent must be an integer greater or equal to 0.
+	% Currently this function runs at O(n), where n is the value
+	% of the exponent.
+:- func pow(float, int) = float.
+
+	% Compute a non-negative integer hash value for a float.
+	% (Note: the hash values computed by the Mercury implementation of
+	% this predicate are different to those computed by the Prolog
+	% implementation.)
+:- func hash(float) = int.
+
+%
+% System constants
+%
+
+	% Maximum floating-point number
+:- func float__max = float.
+
+	% Minimum normalised floating-point number
+:- func float__min = float.
+
+	% Smallest number x such that 1.0 + x \= 1.0
+:- func float__epsilon = float.
 
 %---------------------------------------------------------------------------%
 
-        % float__ceiling_to_int(X, Ceil) is true if Ceil is the
+% Predicate versions of the functions declared above.
+% These are intended for use in programs that need to work
+% in both Prolog and Mercury (e.g. for debugging).
+% These predicate versions will eventually become obsolete.
+
+%
+% Conversion predicates
+%
+
+	% float__ceiling_to_int(X, Ceil) is true if Ceil is the
 	% smallest integer not less than X.
 :- pred float__ceiling_to_int(float, int).
 :- mode float__ceiling_to_int(in, out) is det.
 
-        % float__floor_to_int(X, Ceil) is true if Ceil is the
+	% float__floor_to_int(X, Ceil) is true if Ceil is the
 	% largest integer not greater than X.
 :- pred float__floor_to_int(float, int).
 :- mode float__floor_to_int(in, out) is det.
 
-        % float__round_to_int(X, Round) is true if Round is the
+	% float__round_to_int(X, Round) is true if Round is the
 	% integer closest to X.  If X has a fractional value of
 	% 0.5, it is rounded up.
 :- pred float__round_to_int(float, int).
 :- mode float__round_to_int(in, out) is det.
 
-        % float__truncate_to_int(X, Trunc) is true if Trunc is
+	% float__truncate_to_int(X, Trunc) is true if Trunc is
 	% the integer closest to X such that |Trunc| =< |X|.
 :- pred float__truncate_to_int(float, int).
 :- mode float__truncate_to_int(in, out) is det.
 
-%---------------------------------------------------------------------------%
+%
+% Miscellaneous predicates
+%
 
-:- pred float__pow( float, int, float).
-:- mode float__pow( in, in, out) is det.
-%	float__pow( Base, Exponent, Answer)
-%		A limited way to calculate powers.  The exponent must be an 
-%		integer greater or equal to 0.  Currently this function runs
-%		at O(n), where n is the value of the exponent.
+	% absolute value
+:- pred float__abs(float, float).
+:- mode float__abs(in, out) is det.
 
-%---------------------------------------------------------------------------%
-% System constants
+	% maximum
+:- pred float__max(float, float, float).
+:- mode float__max(in, in, out) is det.
+
+	% minimum
+:- pred float__min(float, float, float).
+:- mode float__min(in, in, out) is det.
+
+	% float__pow(Base, Exponent, Answer) is true iff Answer is
+	% Base raised to the power Exponent.  The exponent must be an 
+	% integer greater or equal to 0.  Currently this function runs
+	% at O(n), where n is the value of the exponent.
+:- pred float__pow(float, int, float).
+:- mode float__pow(in, in, out) is det.
+
+	% Compute a non-negative integer hash value for a float.
+	% (Note: the hash values computed by the Mercury implementation of
+	% this predicate are different to those computed by the Prolog
+	% implementation.)
+:- pred float__hash(float, int).
+:- mode float__hash(in, out) is det.
+
+%
+% System constant predicates
+%
 
 	% Maximum floating-point number
 :- pred float__max(float).
@@ -156,14 +213,53 @@
 :- mode float__epsilon(out) is det.
 
 %---------------------------------------------------------------------------%
-% Compute a non-negative integer hash value for a float.
-% (Note: the hash values computed by the Mercury implementation of
-% this predicate are different to those computed by the Prolog
-% implementation.)
+%---------------------------------------------------------------------------%
 
-:- pred float__hash(float, int).
-:- mode float__hash(in, out) is det.
+:- implementation.
+:- interface.
+
+	% Everything below here will not appear in the
+	% Mercury Library Reference Manual.
+
+%---------------------------------------------------------------------------%
+
+/* The following predicates are obsolete.  Don't use them.
+   They will eventually disappear in some future release.
+*/
+
+% :- pragma obsolete(builtin_float_plus/3).
+:- pred builtin_float_plus(float, float, float).
+:- mode builtin_float_plus(in, in, uo) is det.
+
+% :- pragma obsolete(builtin_float_minus/3).
+:- pred builtin_float_minus(float, float, float).
+:- mode builtin_float_minus(in, in, uo) is det.
+
+% :- pragma obsolete(builtin_float_times/3).
+:- pred builtin_float_times(float, float, float).
+:- mode builtin_float_times(in, in, uo) is det.
+
+% :- pragma obsolete(builtin_float_divide/3).
+:- pred builtin_float_divide(float, float, float).
+:- mode builtin_float_divide(in, in, uo) is det.
+
+% :- pragma obsolete(builtin_float_gt/2).
+:- pred builtin_float_gt(float, float).
+:- mode builtin_float_gt(in, in) is semidet.
+
+% :- pragma obsolete(builtin_float_lt/2).
+:- pred builtin_float_lt(float, float).
+:- mode builtin_float_lt(in, in) is semidet.
+
+% :- pragma obsolete(builtin_float_ge/2).
+:- pred builtin_float_ge(float, float).
+:- mode builtin_float_ge(in, in) is semidet.
 
+% :- pragma obsolete(builtin_float_le/2).
+:- pred builtin_float_le(float, float).
+:- mode builtin_float_le(in, in) is semidet.
+
+%---------------------------------------------------------------------------%
 %---------------------------------------------------------------------------%
 
 :- implementation.
@@ -182,10 +278,67 @@
 
 %---------------------------------------------------------------------------%
 
-
 % The arithmetic and comparison operators are builtins,
 % which the compiler expands inline.  We don't need to define them here.
 
+%---------------------------------------------------------------------------%
+%
+% Conversion functions
+%
+
+float(Int) = Float :-
+	int__to_float(Int, Float).
+
+	% float__ceiling_to_int(X, Ceil) is true if Ceil is the
+	% smallest integer not less than X.
+:- pragma c_code(
+	float__ceiling_to_int(X :: in, Ceil :: out),
+	will_not_call_mercury,
+"
+	Ceil = (Integer) ceil(X);
+").
+
+float__ceiling_to_int(X) = Ceil :- float__ceiling_to_int(X, Ceil).
+
+	% float__floor_to_int(X, Floor) is true if Floor is the
+	% largest integer not greater than X.
+:- pragma c_code(
+	float__floor_to_int(X :: in, Floor :: out),
+	will_not_call_mercury,
+"
+	Floor = (Integer) floor(X);
+").
+
+float__floor_to_int(X) = Floor :- float__floor_to_int(X, Floor).
+
+	% float__round_to_int(X, Round) is true if Round is the
+	% integer closest to X.  If X has a fractional value of
+	% 0.5, it is rounded up.
+:- pragma c_code(
+	float__round_to_int(X :: in, Round :: out),
+	will_not_call_mercury,
+"
+	Round = (Integer) floor(X + 0.5);
+").
+
+float__round_to_int(X) = Round :- float__round_to_int(X, Round).
+
+	% float__truncate_to_int(X, Trunc) is true if Trunc is
+	% the integer closest to X such that |Trunc| =< |X|.
+:- pragma c_code(
+	float__truncate_to_int(X :: in, Trunc :: out),
+	will_not_call_mercury,
+"
+	Trunc = (Integer) X;
+").
+
+float__truncate_to_int(X) = Trunc :- float__truncate_to_int(X, Trunc).
+
+%---------------------------------------------------------------------------%
+%
+% Miscellaneous functions
+%
+
 float__abs(Num, Abs) :-
 	(
 		Num =< 0.0
@@ -195,6 +348,8 @@
 		Abs = Num
 	).
 
+float__abs(Num) = Abs :- float__abs(Num, Abs).
+
 float__max(X, Y, Max) :-
 	(
 		X >= Y
@@ -204,6 +359,8 @@
 		Max = Y
 	).
 
+float__max(X, Y) = Max :- float__max(X, Y, Max).
+
 float__min(X, Y, Min) :-
 	(
 		X =< Y
@@ -213,42 +370,7 @@
 		Min = Y
 	).
 
-%---------------------------------------------------------------------------%
-
-        % float__ceiling_to_int(X, Ceil) is true if Ceil is the
-	% smallest integer not less than X.
-:- pragma(c_code,
-	float__ceiling_to_int(X :: in, Ceil :: out),
-"
-	Ceil = (Integer)ceil(X);
-").
-
-        % float__floor_to_int(X, Floor) is true if Floor is the
-	% largest integer not greater than X.
-:- pragma(c_code,
-	float__floor_to_int(X :: in, Floor :: out),
-"
-	Floor = (Integer)floor(X);
-").
-
-        % float__round_to_int(X, Round) is true if Round is the
-	% integer closest to X.  If X has a fractional value of
-	% 0.5, it is rounded up.
-:- pragma(c_code,
-	float__round_to_int(X :: in, Round :: out),
-"
-	Round = (Integer)floor(X+0.5);
-").
-
-        % float__truncate_to_int(X, Trunc) is true if Trunc is
-	% the integer closest to X such that |Trunc| =< |X|.
-:- pragma(c_code,
-	float__truncate_to_int(X :: in, Trunc :: out),
-"
-	Trunc = (Integer)X;
-").
-
-%---------------------------------------------------------------------------%
+float__min(X, Y) = Min :- float__min(X, Y, Min).
 
 % float_pow(Base, Exponent, Answer).
 %	XXXX This function could be more efficient, with an int_mod pred, to
@@ -263,15 +385,26 @@
 	;
 		New_e is Exp - 1,
 		float__pow(X, New_e, A2),
-		builtin_float_times(X, A2, Ans)
+		Ans is X * A2
 	).
 
-%---------------------------------------------------------------------------%
+float__pow(X, Exp) = Pow :- float__pow(X, Exp, Pow).
+
+:- pragma c_code(
+	float__hash(F::in, H::out),
+	will_not_call_mercury,
+"
+	H = hash_float(F);
+").
 
+float__hash(F) = H :- float__hash(F, H).
+
+%---------------------------------------------------------------------------%
+%
+% System constants
 %
 % The floating-point system constants are derived from <float.h> and
 % implemented using the C interface.
-%
 
 :- pragma(c_header_code, "
 
@@ -288,21 +421,22 @@
 ").
 
 	% Maximum floating-point number
-:- pragma(c_code, float__max(Max::out), "Max = MERCURY_FLOAT_MAX;").
+:- pragma c_code(float__max(Max::out), will_not_call_mercury,
+	"Max = MERCURY_FLOAT_MAX;").
 
-	% Minimum normalised floating-point number */
-:- pragma(c_code, float__min(Min::out), "Min = MERCURY_FLOAT_MIN;").
+float__max = Max :- float__max(Max).
 
-	% Smallest x such that x \= 1.0 + x
-:- pragma(c_code, float__epsilon(Eps::out), "Eps = MERCURY_FLOAT_EPSILON;").
-
-%---------------------------------------------------------------------------%
+	% Minimum normalised floating-point number */
+:- pragma c_code(float__min(Min::out), will_not_call_mercury,
+	"Min = MERCURY_FLOAT_MIN;").
 
-:- pragma c_code(float__hash(F::in, H::out), will_not_call_mercury, "
+float__min = Min :- float__min(Min).
 
-	H = hash_float(F);
+	% Smallest x such that x \= 1.0 + x
+:- pragma c_code(float__epsilon(Eps::out), will_not_call_mercury,
+	"Eps = MERCURY_FLOAT_EPSILON;").
 
-").
+float__epsilon = Epsilon :- float__epsilon(Epsilon).
 
 %---------------------------------------------------------------------------%
 %---------------------------------------------------------------------------%
Index: mercury_builtin.m
===================================================================
RCS file: /home/staff/zs/imp/mercury/library/mercury_builtin.m,v
retrieving revision 1.75
diff -u -r1.75 mercury_builtin.m
--- mercury_builtin.m	1997/06/04 09:59:33	1.75
+++ mercury_builtin.m	1997/07/14 05:34:47
@@ -297,9 +304,9 @@
 builtin_index_float(_, -1).
 
 builtin_compare_float(R, F1, F2) :-
-	( builtin_float_lt(F1, F2) ->
+	( F1 < F2 ->
 		R = (<)
-	; builtin_float_gt(F1, F2) ->
+	; F1 > F2 ->
 		R = (>)
 	;
 		R = (=)

%---------------------------------------------------------------------------%
% Copyright (C) 1994-1997 University of Melbourne.
% This file may only be copied under the terms of the GNU Library General
% Public License - see the file COPYING.LIB in the Mercury distribution.
%---------------------------------------------------------------------------%
%
% File: float.m.
% Main author: fjh.
% Stability: medium.
%
% Floating point support.
%
% XXX - What should we do about unification of two Nan's?
%
%---------------------------------------------------------------------------%

:- module float.
:- interface.

%
% Arithmetic functions
%

	% addition
:- func float + float = float.
:- mode in    + in    = uo  is det.
:- mode uo    + in    = in  is det.
:- mode in    + uo    = in  is det.

	% subtraction
:- func float - float = float.
:- mode in    - in    = uo  is det.
:- mode uo    - in    = in  is det.
:- mode in    - uo    = in  is det.

	% multiplication
:- func float * float = float.
:- mode in    * in    = uo  is det.
:- mode uo    * in    = in  is det.
:- mode in    * uo    = in  is det.

	% division
:- func float / float = float.
:- mode in    / in    = uo  is det.
:- mode uo    / in    = in  is det.
:- mode in    / uo    = in  is det.

	% unary plus
:- func + float = float.
:- mode + in    = uo  is det.

	% unary minus
:- func - float = float.
:- mode - in    = uo  is det.

%
% Comparison predicates
%

	% less than
:- pred <(float, float).
:- mode <(in, in) is semidet.

	% greater than
:- pred >(float, float).
:- mode >(in, in) is semidet.

	% less than or equal
:- pred =<(float, float).
:- mode =<(in, in) is semidet.

	% greater than or equal
:- pred >=(float, float).
:- mode >=(in, in) is semidet.

%
% Conversion functions
%

	% Convert int to float
:- func float(int) = float.

	% ceiling_to_int(X) returns the
	% smallest integer not less than X.
:- func ceiling_to_int(float) = int.

	% floor_to_int(X) returns the
	% largest integer not greater than X.
:- func floor_to_int(float) = int.

	% round_to_int(X) returns the integer closest to X.
	% If X has a fractional value of 0.5, it is rounded up.
:- func round_to_int(float) = int.

	% truncate_to_int(X) returns 
	% the integer closest to X such that |truncate_to_int(X)| =< |X|.
:- func truncate_to_int(float) = int.

%
% Miscellaneous functions
%

	% absolute value
:- func abs(float) = float.

	% maximum
:- func max(float, float) = float.

	% minimum
:- func min(float, float) = float.

	% pow(Base, Exponent) returns Base raised to the power Exponent.
	% The exponent must be an integer greater or equal to 0.
	% Currently this function runs at O(n), where n is the value
	% of the exponent.
:- func pow(float, int) = float.

	% Compute a non-negative integer hash value for a float.
	% (Note: the hash values computed by the Mercury implementation of
	% this predicate are different to those computed by the Prolog
	% implementation.)
:- func hash(float) = int.

%
% System constants
%

	% Maximum floating-point number
:- func float__max = float.

	% Minimum normalised floating-point number
:- func float__min = float.

	% Smallest number x such that 1.0 + x \= 1.0
:- func float__epsilon = float.

%---------------------------------------------------------------------------%

% Predicate versions of the functions declared above.
% These are intended for use in programs that need to work
% in both Prolog and Mercury (e.g. for debugging).
% These predicate versions will eventually become obsolete.

%
% Conversion predicates
%

	% float__ceiling_to_int(X, Ceil) is true if Ceil is the
	% smallest integer not less than X.
:- pred float__ceiling_to_int(float, int).
:- mode float__ceiling_to_int(in, out) is det.

	% float__floor_to_int(X, Ceil) is true if Ceil is the
	% largest integer not greater than X.
:- pred float__floor_to_int(float, int).
:- mode float__floor_to_int(in, out) is det.

	% float__round_to_int(X, Round) is true if Round is the
	% integer closest to X.  If X has a fractional value of
	% 0.5, it is rounded up.
:- pred float__round_to_int(float, int).
:- mode float__round_to_int(in, out) is det.

	% float__truncate_to_int(X, Trunc) is true if Trunc is
	% the integer closest to X such that |Trunc| =< |X|.
:- pred float__truncate_to_int(float, int).
:- mode float__truncate_to_int(in, out) is det.

%
% Miscellaneous predicates
%

	% absolute value
:- pred float__abs(float, float).
:- mode float__abs(in, out) is det.

	% maximum
:- pred float__max(float, float, float).
:- mode float__max(in, in, out) is det.

	% minimum
:- pred float__min(float, float, float).
:- mode float__min(in, in, out) is det.

	% float__pow(Base, Exponent, Answer) is true iff Answer is
	% Base raised to the power Exponent.  The exponent must be an 
	% integer greater or equal to 0.  Currently this function runs
	% at O(n), where n is the value of the exponent.
:- pred float__pow(float, int, float).
:- mode float__pow(in, in, out) is det.

	% Compute a non-negative integer hash value for a float.
	% (Note: the hash values computed by the Mercury implementation of
	% this predicate are different to those computed by the Prolog
	% implementation.)
:- pred float__hash(float, int).
:- mode float__hash(in, out) is det.

%
% System constant predicates
%

	% Maximum floating-point number
:- pred float__max(float).
:- mode float__max(out) is det.

	% Minimum normalised floating-point number
:- pred float__min(float).
:- mode float__min(out) is det.

	% Smallest number x such that 1.0 + x \= 1.0
:- pred float__epsilon(float).
:- mode float__epsilon(out) is det.

%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%

:- implementation.
:- interface.

	% Everything below here will not appear in the
	% Mercury Library Reference Manual.

%---------------------------------------------------------------------------%

/* The following predicates are obsolete.  Don't use them.
   They will eventually disappear in some future release.
*/

% :- pragma obsolete(builtin_float_plus/3).
:- pred builtin_float_plus(float, float, float).
:- mode builtin_float_plus(in, in, uo) is det.

% :- pragma obsolete(builtin_float_minus/3).
:- pred builtin_float_minus(float, float, float).
:- mode builtin_float_minus(in, in, uo) is det.

% :- pragma obsolete(builtin_float_times/3).
:- pred builtin_float_times(float, float, float).
:- mode builtin_float_times(in, in, uo) is det.

% :- pragma obsolete(builtin_float_divide/3).
:- pred builtin_float_divide(float, float, float).
:- mode builtin_float_divide(in, in, uo) is det.

% :- pragma obsolete(builtin_float_gt/2).
:- pred builtin_float_gt(float, float).
:- mode builtin_float_gt(in, in) is semidet.

% :- pragma obsolete(builtin_float_lt/2).
:- pred builtin_float_lt(float, float).
:- mode builtin_float_lt(in, in) is semidet.

% :- pragma obsolete(builtin_float_ge/2).
:- pred builtin_float_ge(float, float).
:- mode builtin_float_ge(in, in) is semidet.

% :- pragma obsolete(builtin_float_le/2).
:- pred builtin_float_le(float, float).
:- mode builtin_float_le(in, in) is semidet.

%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%

:- implementation.
:- import_module int, require.

%
% Header files of mathematical significance.
%

:- pragma(c_header_code, "

	#include <float.h>
	#include <math.h>

").

%---------------------------------------------------------------------------%

% The arithmetic and comparison operators are builtins,
% which the compiler expands inline.  We don't need to define them here.

%---------------------------------------------------------------------------%
%
% Conversion functions
%

float(Int) = Float :-
	int__to_float(Int, Float).

	% float__ceiling_to_int(X, Ceil) is true if Ceil is the
	% smallest integer not less than X.
:- pragma c_code(
	float__ceiling_to_int(X :: in, Ceil :: out),
	will_not_call_mercury,
"
	Ceil = (Integer) ceil(X);
").

float__ceiling_to_int(X) = Ceil :- float__ceiling_to_int(X, Ceil).

	% float__floor_to_int(X, Floor) is true if Floor is the
	% largest integer not greater than X.
:- pragma c_code(
	float__floor_to_int(X :: in, Floor :: out),
	will_not_call_mercury,
"
	Floor = (Integer) floor(X);
").

float__floor_to_int(X) = Floor :- float__floor_to_int(X, Floor).

	% float__round_to_int(X, Round) is true if Round is the
	% integer closest to X.  If X has a fractional value of
	% 0.5, it is rounded up.
:- pragma c_code(
	float__round_to_int(X :: in, Round :: out),
	will_not_call_mercury,
"
	Round = (Integer) floor(X + 0.5);
").

float__round_to_int(X) = Round :- float__round_to_int(X, Round).

	% float__truncate_to_int(X, Trunc) is true if Trunc is
	% the integer closest to X such that |Trunc| =< |X|.
:- pragma c_code(
	float__truncate_to_int(X :: in, Trunc :: out),
	will_not_call_mercury,
"
	Trunc = (Integer) X;
").

float__truncate_to_int(X) = Trunc :- float__truncate_to_int(X, Trunc).

%---------------------------------------------------------------------------%
%
% Miscellaneous functions
%

float__abs(Num, Abs) :-
	(
		Num =< 0.0
	->
		Abs = - Num
	;
		Abs = Num
	).

float__abs(Num) = Abs :- float__abs(Num, Abs).

float__max(X, Y, Max) :-
	(
		X >= Y
	->
		Max = X
	;
		Max = Y
	).

float__max(X, Y) = Max :- float__max(X, Y, Max).

float__min(X, Y, Min) :-
	(
		X =< Y
	->
		Min = X
	;
		Min = Y
	).

float__min(X, Y) = Min :- float__min(X, Y, Min).

% float_pow(Base, Exponent, Answer).
%	XXXX This function could be more efficient, with an int_mod pred, to
%	reduce O(N) to O(logN) of the exponent.
float__pow( X, Exp, Ans) :-
	( Exp < 0 ->
		error("float__pow taken with exponent < 0\n")
	; Exp = 1 ->
		Ans =  X
	; Exp = 0 ->
		Ans = 1.0
	;
		New_e is Exp - 1,
		float__pow(X, New_e, A2),
		Ans is X * A2
	).

float__pow(X, Exp) = Pow :- float__pow(X, Exp, Pow).

:- pragma c_code(
	float__hash(F::in, H::out),
	will_not_call_mercury,
"
	H = hash_float(F);
").

float__hash(F) = H :- float__hash(F, H).

%---------------------------------------------------------------------------%
%
% System constants
%
% The floating-point system constants are derived from <float.h> and
% implemented using the C interface.

:- pragma(c_header_code, "

	#if defined USE_SINGLE_PREC_FLOAT
		#define	MERCURY_FLOAT_MAX	FLT_MAX
		#define	MERCURY_FLOAT_MIN	FLT_MIN
		#define	MERCURY_FLOAT_EPSILON	FLT_EPSILON
	#else
		#define	MERCURY_FLOAT_MAX	DBL_MAX
		#define	MERCURY_FLOAT_MIN	DBL_MIN
		#define	MERCURY_FLOAT_EPSILON	DBL_EPSILON
	#endif

").

	% Maximum floating-point number
:- pragma c_code(float__max(Max::out), will_not_call_mercury,
	"Max = MERCURY_FLOAT_MAX;").

float__max = Max :- float__max(Max).

	% Minimum normalised floating-point number */
:- pragma c_code(float__min(Min::out), will_not_call_mercury,
	"Min = MERCURY_FLOAT_MIN;").

float__min = Min :- float__min(Min).

	% Smallest x such that x \= 1.0 + x
:- pragma c_code(float__epsilon(Eps::out), will_not_call_mercury,
	"Eps = MERCURY_FLOAT_EPSILON;").

float__epsilon = Epsilon :- float__epsilon(Epsilon).

%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%

-- 
Fergus Henderson <fjh at cs.mu.oz.au>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3         |     -- the last words of T. S. Garp.



More information about the developers mailing list