Files
mercury/library/float.m
Fergus Henderson d421728586 Implement the builtin arithmetic operations using functions,
Estimated hours taken: 1

int.m, float.m:
	Implement the builtin arithmetic operations using functions,
	rather than ad-hoc hacks in the parser.  You can know use
	use arithmetic operators such as `+', `-', etc. on floats.
	(You can't yet use relational operators such as <, >=, etc.
	-- that's coming soon.)
1996-04-07 13:41:50 +00:00

239 lines
5.8 KiB
Mathematica

%---------------------------------------------------------------------------%
% Copyright (C) 1995 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: low.
%
% Floating point support.
%
% XXX - What should we do about unification of two Nan's?
%
%---------------------------------------------------------------------------%
:- module float.
:- interface.
:- type float.
/*****
The following operators will not be supported until we implement
predicate overloading. Use the builtin_float_lt etc. versions instead.
% 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.
% addition
:- func float + float = float.
:- mode in + in = uo is det.
% subtraction
:- func float - float = float.
:- mode in - in = uo is det.
% multiplication
:- func float * float = float.
:- mode in * in = uo is det.
% division
:- func float / float = float.
:- mode in / in = uo is det.
% unary plus
:- func + float = float.
:- mode + in = uo is det.
% unary minus
:- func - float = float.
:- mode - in = uo is det.
%---------------------------------------------------------------------------%
:- pred builtin_float_plus(float, float, float).
:- mode builtin_float_plus(in, in, uo) is det.
:- pred builtin_float_minus(float, float, float).
:- mode builtin_float_minus(in, in, uo) is det.
:- pred builtin_float_times(float, float, float).
:- mode builtin_float_times(in, in, uo) is det.
:- pred builtin_float_divide(float, float, float).
:- mode builtin_float_divide(in, in, uo) is det.
:- pred builtin_float_gt(float, float).
:- mode builtin_float_gt(in, in) is semidet.
:- pred builtin_float_lt(float, float).
:- mode builtin_float_lt(in, in) is semidet.
:- pred builtin_float_ge(float, float).
:- mode builtin_float_ge(in, in) is semidet.
:- pred builtin_float_le(float, float).
:- mode builtin_float_le(in, in) is semidet.
%---------------------------------------------------------------------------%
:- 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.
%---------------------------------------------------------------------------%
% System constants
% 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.
:- import_module int, require.
/*
these are builtins
X + Y = Z :- builtin_float_plus(X, Y, Z).
X - Y = Z :- builtin_float_minus(X, Y, Z).
X * Y = Z :- builtin_float_times(X, Y, Z).
X / Y = Z :- builtin_float_divide(X, Y, Z).
*/
/* these ought to be builtins */
+ X = 0.0 + X.
- X = 0.0 - X.
/*
these are builtins
float:(X < Y) :- builtin_float_lt(X, Y).
float:(X > Y) :- builtin_float_gt(X, Y).
float:(X =< Y) :- builtin_float_le(X, Y).
float:(X >= Y) :- builtin_float_ge(X, Y).
*/
/* All the builtin_float_* are builtins, which the compiler expands inline. */
%---------------------------------------------------------------------------%
float__abs(Num, Abs) :-
(
% (Num =< 0.0)
builtin_float_le(Num, 0.0)
->
Abs = - Num
;
Abs = Num
).
float__max(X, Y, Max) :-
(
% X >= Y
builtin_float_ge(X, Y)
->
Max = X
;
Max = Y
).
float__min(X, Y, Min) :-
(
% X =< Y
builtin_float_le(X, Y)
->
Min = X
;
Min = Y
).
%---------------------------------------------------------------------------%
% 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),
builtin_float_times(X, A2, Ans)
).
%---------------------------------------------------------------------------%
%
% System constants from <float.h>, implemented using the C interface
%
:- pragma(c_header_code, "
#include <float.h>
#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), "Max = MERCURY_FLOAT_MAX;").
% Minimum normalised floating-point number */
:- pragma(c_code, float__min(Min::out), "Min = MERCURY_FLOAT_MIN;").
% Smallest x such that x \= 1.0 + x
:- pragma(c_code, float__epsilon(Eps::out), "Eps = MERCURY_FLOAT_EPSILON;").
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%