mirror of
https://github.com/Mercury-Language/mercury.git
synced 2025-12-21 00:39:37 +00:00
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.)
239 lines
5.8 KiB
Mathematica
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;").
|
|
|
|
%---------------------------------------------------------------------------%
|
|
%---------------------------------------------------------------------------%
|