Files
mercury/library/math.m
Peter Wang 8fb83bcfb1 Fix incorrect result type on new_buffer_2.
Estimated hours taken: 0.2
Branches: main

library/bit_buffer.m:
	Fix incorrect result type on new_buffer_2.

library/math.m:
	Fix Erlang implementation of math.round/1.

library/profiling_builtin.m:
library/table_builtin.m:
	Add Erlang stubs for :- external procedures for deep profiling and
	tabling.
2007-05-31 03:03:37 +00:00

1017 lines
27 KiB
Mathematica

%---------------------------------------------------------------------------%
% vim: ft=mercury ts=4 sw=4 et wm=0 tw=0
%---------------------------------------------------------------------------%
% Copyright (C) 1995-2007 The 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: math.m.
% Main author: bromage.
% Stability: high.
%
% Higher mathematical operations. (The basics are in float.m.)
%
% By default, domain errors are currently handled by throwing an exception.
%
% For better performance, it is possible to disable the Mercury domain
% checking by compiling with `--intermodule-optimization' and the C macro
% symbol `ML_OMIT_MATH_DOMAIN_CHECKS' defined, e.g. by using
% `MCFLAGS=--intermodule-optimization' and
% `MGNUCFLAGS=-DML_OMIT_MATH_DOMAIN_CHECKS' in your Mmakefile,
% or by compiling with the command
% `mmc --intermodule-optimization --cflags -DML_OMIT_MATH_DOMAIN_CHECKS'.
%
% For maximum performance, all Mercury domain checking can be disabled by
% recompiling this module using `MGNUCFLAGS=-DML_OMIT_MATH_DOMAIN_CHECKS'
% or `mmc --cflags -DML_OMIT_MATH_DOMAIN_CHECKS' as above. You can
% either recompile the entire library, or just copy `math.m' to your
% application's source directory and link with it directly instead of as
% part of the library.
%
% Note that the above performance improvements are semantically safe,
% since the C math library and/or floating point hardware perform these
% checks for you. The benefit of having the Mercury library perform the
% checks instead is that Mercury will tell you in which function or
% predicate the error occurred, as well as giving you a stack trace if
% that is enabled; with the checks disabled you only have the information
% that the floating-point exception signal handler gives you.
%
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- module math.
:- interface.
% A domain error exception, indicates that the inputs to a function
% were outside the domain of the function. The string indicates
% where the error occurred.
%
% It is possible to switch domain checking off, in which case,
% depending on the backend, a domain error may cause a program
% abort.
%
:- type domain_error ---> domain_error(string).
%---------------------------------------------------------------------------%
%
% Mathematical constants
%
% Pythagoras' number.
%
:- func math.pi = float.
% Base of natural logarithms.
%
:- func math.e = float.
%---------------------------------------------------------------------------%
%
% "Next integer" operations
%
% math.ceiling(X) = Ceil is true if Ceil is the smallest integer
% not less than X.
%
:- func math.ceiling(float) = float.
% math.floor(X) = Floor is true if Floor is the largest integer
% not greater than X.
%
:- func math.floor(float) = float.
% math.round(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.
%
:- func math.round(float) = float.
% math.truncate(X) = Trunc is true if Trunc is the integer closest to X
% such that |Trunc| =< |X|.
%
:- func math.truncate(float) = float.
%---------------------------------------------------------------------------%
%
% Polynomial roots
%
% math.sqrt(X) = Sqrt is true if Sqrt is the positive square root of X.
%
% Domain restriction: X >= 0
%
:- func math.sqrt(float) = float.
:- type math.quadratic_roots
---> no_roots
; one_root(float)
; two_roots(float, float).
% math.solve_quadratic(A, B, C) = Roots is true if Roots are
% the solutions to the equation Ax^2 + Bx + C.
%
% Domain restriction: A \= 0
%
:- func math.solve_quadratic(float, float, float) = quadratic_roots.
%---------------------------------------------------------------------------%
%
% Power/logarithm operations
%
% math.pow(X, Y) = Res is true if Res is X raised to the power of Y.
%
% Domain restriction: X >= 0 and (X = 0 implies Y > 0)
%
:- func math.pow(float, float) = float.
% math.exp(X) = Exp is true if Exp is e raised to the power of X.
%
:- func math.exp(float) = float.
% math.ln(X) = Log is true if Log is the natural logarithm of X.
%
% Domain restriction: X > 0
%
:- func math.ln(float) = float.
% math.log10(X) = Log is true if Log is the logarithm to base 10 of X.
%
% Domain restriction: X > 0
%
:- func math.log10(float) = float.
% math.log2(X) = Log is true if Log is the logarithm to base 2 of X.
%
% Domain restriction: X > 0
%
:- func math.log2(float) = float.
% math.log(B, X) = Log is true if Log is the logarithm to base B of X.
%
% Domain restriction: X > 0 and B > 0 and B \= 1
%
:- func math.log(float, float) = float.
%---------------------------------------------------------------------------%
%
% Trigonometric operations
%
% math.sin(X) = Sin is true if Sin is the sine of X.
%
:- func math.sin(float) = float.
% math.cos(X) = Cos is true if Cos is the cosine of X.
%
:- func math.cos(float) = float.
% math.tan(X) = Tan is true if Tan is the tangent of X.
%
:- func math.tan(float) = float.
% math.asin(X) = ASin is true if ASin is the inverse sine of X,
% where ASin is in the range [-pi/2,pi/2].
%
% Domain restriction: X must be in the range [-1,1]
%
:- func math.asin(float) = float.
% math.acos(X) = ACos is true if ACos is the inverse cosine of X,
% where ACos is in the range [0, pi].
%
% Domain restriction: X must be in the range [-1,1]
%
:- func math.acos(float) = float.
% math.atan(X) = ATan is true if ATan is the inverse tangent of X,
% where ATan is in the range [-pi/2,pi/2].
%
:- func math.atan(float) = float.
% math.atan2(Y, X) = ATan is true if ATan is the inverse tangent of Y/X,
% where ATan is in the range [-pi,pi].
%
:- func math.atan2(float, float) = float.
%---------------------------------------------------------------------------%
%
% Hyperbolic functions
%
% math.sinh(X) = Sinh is true if Sinh is the hyperbolic sine of X.
%
:- func math.sinh(float) = float.
% math.cosh(X) = Cosh is true if Cosh is the hyperbolic cosine of X.
%
:- func math.cosh(float) = float.
% math.tanh(X) = Tanh is true if Tanh is the hyperbolic tangent of X.
%
:- func math.tanh(float) = float.
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%
:- implementation.
:- import_module exception.
:- import_module float.
% These operations are mostly implemented using the C interface.
:- pragma foreign_decl("C", "
#include <math.h>
/*
** Mathematical constants.
**
** The maximum number of significant decimal digits which
** can be packed into an IEEE-754 extended precision
** floating point number is 18. Therefore 20 significant
** decimal digits for these constants should be plenty.
*/
#define ML_FLOAT_E 2.7182818284590452354
#define ML_FLOAT_PI 3.1415926535897932384
#define ML_FLOAT_LN2 0.69314718055994530941
"). % end pragma foreign_decl
:- pragma foreign_code("C#", "
// This is not defined in the .NET Frameworks.
// For pi and e we use the constants defined in System.Math.
public static double ML_FLOAT_LN2 = 0.69314718055994530941;
").
:- pragma foreign_code("Java", "
// As for .NET, java does not have a built-in ln2
private static final double ML_FLOAT_LN2 = 0.69314718055994530941;
").
:- pred math_domain_checks is semidet.
:- pragma foreign_proc("C",
math_domain_checks,
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
does_not_affect_liveness],
"
#ifdef ML_OMIT_MATH_DOMAIN_CHECKS
SUCCESS_INDICATOR = MR_FALSE;
#else
SUCCESS_INDICATOR = MR_TRUE;
#endif
").
:- pragma foreign_proc("C#",
math_domain_checks,
[thread_safe, promise_pure],
"
#if ML_OMIT_MATH_DOMAIN_CHECKS
SUCCESS_INDICATOR = false;
#else
SUCCESS_INDICATOR = true;
#endif
").
:- pragma foreign_proc("Java",
math_domain_checks,
[thread_safe, promise_pure],
"
succeeded = true;
").
:- pragma foreign_proc("Erlang",
math_domain_checks,
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
does_not_affect_liveness],
"
SUCCESS_INDICATOR = true
").
%
% Mathematical constants from math.m
%
% Pythagoras' number
:- pragma foreign_proc("C",
math.pi = (Pi::out),
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
does_not_affect_liveness],
"
Pi = ML_FLOAT_PI;
").
:- pragma foreign_proc("C#",
math.pi = (Pi::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Pi = System.Math.PI;
").
:- pragma foreign_proc("Java",
math.pi = (Pi::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Pi = java.lang.Math.PI;
").
:- pragma foreign_proc("Erlang",
math.pi = (Pi::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Pi = math:pi()
").
% This version is only used for back-ends for which there is no
% matching foreign_proc version. We define this with sufficient
% digits that if the underlying implementation's
% floating point parsing routines are good, it should
% to be accurate enough for 128-bit IEEE float.
math.pi = 3.1415926535897932384626433832795029.
% Base of natural logarithms
:- pragma foreign_proc("C",
math.e = (E::out),
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
does_not_affect_liveness],
"
E = ML_FLOAT_E;
").
:- pragma foreign_proc("C#",
math.e = (E::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
E = System.Math.E;
").
:- pragma foreign_proc("Java",
math.e = (E::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
E = java.lang.Math.E;
").
% This version is only used for back-ends for which there is no
% matching foreign_proc version. We define this with sufficient
% digits that if the underlying implementation's
% floating point parsing routines are good, it should
% to be accurate enough for 128-bit IEEE float.
math.e = 2.7182818284590452353602874713526625.
:- pragma foreign_proc("C",
math.ceiling(Num::in) = (Ceil::out),
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
does_not_affect_liveness],
"
Ceil = ceil(Num);
").
:- pragma foreign_proc("C#",
math.ceiling(Num::in) = (Ceil::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Ceil = System.Math.Ceiling(Num);
").
:- pragma foreign_proc("Java",
math.ceiling(Num::in) = (Ceil::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Ceil = java.lang.Math.ceil(Num);
").
:- pragma foreign_proc("Erlang",
math.ceiling(Num::in) = (Ceil::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
T = erlang:trunc(Num),
case (Num - T) > 0 of
true ->
Ceil = float(T + 1);
false ->
Ceil = float(T)
end
").
:- pragma foreign_proc("C",
math.floor(Num::in) = (Floor::out),
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
does_not_affect_liveness],
"
Floor = floor(Num);
").
:- pragma foreign_proc("C#",
math.floor(Num::in) = (Floor::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Floor = System.Math.Floor(Num);
").
:- pragma foreign_proc("Java",
math.floor(Num::in) = (Floor::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Floor = java.lang.Math.floor(Num);
").
:- pragma foreign_proc("Erlang",
math.floor(Num::in) = (Floor::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
T = erlang:trunc(Num),
case (Num - T) < 0 of
true ->
Floor = float(T - 1);
false ->
Floor = float(T)
end
").
:- pragma foreign_proc("C",
math.round(Num::in) = (Rounded::out),
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
does_not_affect_liveness],
"
Rounded = floor(Num+0.5);
").
:- pragma foreign_proc("C#",
math.round(Num::in) = (Rounded::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
// XXX the semantics of System.Math.Round() are not the same as ours.
// Unfortunately they are better (round to nearest even number).
Rounded = System.Math.Floor(Num+0.5);
").
:- pragma foreign_proc("Java",
math.round(Num::in) = (Rounded::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Rounded = java.lang.Math.round(Num);
").
:- pragma foreign_proc("Java",
math.round(Num::in) = (Rounded::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Rounded = java.lang.Math.round(Num);
").
:- pragma foreign_proc("Erlang",
math.round(Num::in) = (Rounded::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Rounded = float(round(Num))
").
math.round(Num) = math.floor(Num + 0.5).
math.truncate(X) = (X < 0.0 -> math.ceiling(X) ; math.floor(X)).
math.sqrt(X) = SquareRoot :-
( math_domain_checks, X < 0.0 ->
throw(domain_error("math.sqrt"))
;
SquareRoot = math.sqrt_2(X)
).
:- func math.sqrt_2(float) = float.
:- pragma foreign_proc("C",
math.sqrt_2(X::in) = (SquareRoot::out),
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
does_not_affect_liveness],
"
SquareRoot = sqrt(X);
").
:- pragma foreign_proc("C#",
math.sqrt_2(X::in) = (SquareRoot::out),
[thread_safe, promise_pure],
"
SquareRoot = System.Math.Sqrt(X);
").
:- pragma foreign_proc("Java",
math.sqrt_2(X::in) = (SquareRoot::out),
[thread_safe, promise_pure],
"
SquareRoot = java.lang.Math.sqrt(X);
").
:- pragma foreign_proc("Erlang",
math.sqrt_2(X::in) = (SquareRoot::out),
[thread_safe, promise_pure],
"
SquareRoot = math:sqrt(X)
").
% This version is only used for back-ends for which there is no
% matching foreign_proc version.
math.sqrt_2(X) = math.exp(math.ln(X) / 2.0).
math.solve_quadratic(A, B, C) = Roots :-
% This implementation is designed to minimise numerical errors;
% it is adapted from "Numerical recipes in C".
DSquared = B * B - 4.0 * A * C,
compare(CmpD, DSquared, 0.0),
(
CmpD = (<),
Roots = no_roots
;
CmpD = (=),
Root = -0.5 * B / A,
Roots = one_root(Root)
;
CmpD = (>),
D = sqrt(DSquared),
compare(CmpB, B, 0.0),
(
CmpB = (<),
Q = -0.5 * (B - D),
Root1 = Q / A,
Root2 = C / Q
;
CmpB = (=),
Root1 = -0.5 * D / A,
Root2 = -Root1
;
CmpB = (>),
Q = -0.5 * (B + D),
Root1 = Q / A,
Root2 = C / Q
),
Roots = two_roots(Root1, Root2)
).
math.pow(X, Y) = Res :-
( math_domain_checks, X < 0.0 ->
throw(domain_error("math.pow"))
; X = 0.0 ->
( Y =< 0.0 ->
throw(domain_error("math.pow"))
;
Res = 0.0
)
;
Res = math.pow_2(X, Y)
).
:- func math.pow_2(float, float) = float.
:- pragma foreign_proc("C",
math.pow_2(X::in, Y::in) = (Res::out),
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
does_not_affect_liveness],
"
Res = pow(X, Y);
").
:- pragma foreign_proc("C#",
math.pow_2(X::in, Y::in) = (Res::out),
[thread_safe, promise_pure],
"
Res = System.Math.Pow(X, Y);
").
:- pragma foreign_proc("Java",
math.pow_2(X::in, Y::in) = (Res::out),
[thread_safe, promise_pure],
"
Res = java.lang.Math.pow(X, Y);
").
:- pragma foreign_proc("Erlang",
math.pow_2(X::in, Y::in) = (Res::out),
[thread_safe, promise_pure],
"
Res = math:pow(X, Y)
").
:- pragma foreign_proc("C",
math.exp(X::in) = (Exp::out),
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
does_not_affect_liveness],
"
Exp = exp(X);
").
:- pragma foreign_proc("C#",
math.exp(X::in) = (Exp::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Exp = System.Math.Exp(X);
").
:- pragma foreign_proc("Java",
math.exp(X::in) = (Exp::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Exp = java.lang.Math.exp(X);
").
:- pragma foreign_proc("Erlang",
math.exp(X::in) = (Exp::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Exp = math:exp(X)
").
math.ln(X) = Log :-
( math_domain_checks, X =< 0.0 ->
throw(domain_error("math.ln"))
;
Log = math.ln_2(X)
).
:- func math.ln_2(float) = float.
:- pragma foreign_proc("C",
math.ln_2(X::in) = (Log::out),
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
does_not_affect_liveness],
"
Log = log(X);
").
:- pragma foreign_proc("C#",
math.ln_2(X::in) = (Log::out),
[thread_safe, promise_pure],
"
Log = System.Math.Log(X);
").
:- pragma foreign_proc("Java",
math.ln_2(X::in) = (Log::out),
[thread_safe, promise_pure],
"
Log = java.lang.Math.log(X);
").
:- pragma foreign_proc("Erlang",
math.ln_2(X::in) = (Log::out),
[thread_safe, promise_pure],
"
Log = math:log(X)
").
math.log10(X) = Log :-
( math_domain_checks, X =< 0.0 ->
throw(domain_error("math.log10"))
;
Log = math.log10_2(X)
).
:- func math.log10_2(float) = float.
:- pragma foreign_proc("C",
math.log10_2(X::in) = (Log10::out),
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
does_not_affect_liveness],
"
Log10 = log10(X);
").
:- pragma foreign_proc("C#",
math.log10_2(X::in) = (Log10::out),
[thread_safe, promise_pure],
"
Log10 = System.Math.Log10(X);
").
:- pragma foreign_proc("Erlang",
math.log10_2(X::in) = (Log10::out),
[thread_safe, promise_pure],
"
Log10 = math:log10(X)
").
% Java doesn't have a built-in log10, so default to mercury here.
math.log10_2(X) = math.ln_2(X) / math.ln_2(10.0).
math.log2(X) = Log :-
( math_domain_checks, X =< 0.0 ->
throw(domain_error("math.log2"))
;
Log = math.log2_2(X)
).
:- func math.log2_2(float) = float.
:- pragma foreign_proc("C",
math.log2_2(X::in) = (Log2::out),
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
does_not_affect_liveness],
"
Log2 = log(X) / ML_FLOAT_LN2;
").
:- pragma foreign_proc("C#",
math.log2_2(X::in) = (Log2::out),
[thread_safe, promise_pure],
"
Log2 = System.Math.Log(X) / ML_FLOAT_LN2;
").
:- pragma foreign_proc("Java",
math.log2_2(X::in) = (Log2::out),
[thread_safe, promise_pure],
"
Log2 = java.lang.Math.log(X) / ML_FLOAT_LN2;
").
math.log2_2(X) = math.ln_2(X) / math.ln_2(2.0).
math.log(B, X) = Log :-
(
math_domain_checks,
( X =< 0.0
; B =< 0.0
; B = 1.0
)
->
throw(domain_error("math.log"))
;
Log = math.log_2(B, X)
).
:- func math.log_2(float, float) = float.
:- pragma foreign_proc("C",
math.log_2(B::in, X::in) = (Log::out),
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
does_not_affect_liveness],
"
Log = log(X) / log(B);
").
:- pragma foreign_proc("C#",
math.log_2(B::in, X::in) = (Log::out),
[thread_safe, promise_pure],
"
Log = System.Math.Log(X, B);
").
% Java implementation will default to mercury here.
% Erlang implementation will default to mercury here.
math.log_2(B, X) = math.ln_2(X) / math.ln_2(B).
:- pragma foreign_proc("C",
math.sin(X::in) = (Sin::out),
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
does_not_affect_liveness],
"
Sin = sin(X);
").
:- pragma foreign_proc("C#",
math.sin(X::in) = (Sin::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Sin = System.Math.Sin(X);
").
:- pragma foreign_proc("Java",
math.sin(X::in) = (Sin::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Sin = java.lang.Math.sin(X);
").
:- pragma foreign_proc("Erlang",
math.sin(X::in) = (Sin::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Sin = math:sin(X)
").
:- pragma foreign_proc("C",
math.cos(X::in) = (Cos::out),
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
does_not_affect_liveness],
"
Cos = cos(X);
").
:- pragma foreign_proc("C#",
math.cos(X::in) = (Cos::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Cos = System.Math.Cos(X);
").
:- pragma foreign_proc("Java",
math.cos(X::in) = (Cos::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Cos = java.lang.Math.cos(X);
").
:- pragma foreign_proc("Erlang",
math.cos(X::in) = (Cos::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Cos = math:cos(X)
").
:- pragma foreign_proc("C",
math.tan(X::in) = (Tan::out),
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
does_not_affect_liveness],
"
Tan = tan(X);
").
:- pragma foreign_proc("C#",
math.tan(X::in) = (Tan::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Tan = System.Math.Tan(X);
").
:- pragma foreign_proc("Java",
math.tan(X::in) = (Tan::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Tan = java.lang.Math.tan(X);
").
:- pragma foreign_proc("Erlang",
math.tan(X::in) = (Tan::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Tan = math:tan(X)
").
math.asin(X) = ASin :-
(
math_domain_checks,
( X < -1.0
; X > 1.0
)
->
throw(domain_error("math.asin"))
;
ASin = math.asin_2(X)
).
:- func math.asin_2(float) = float.
:- pragma foreign_proc("C",
math.asin_2(X::in) = (ASin::out),
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
does_not_affect_liveness],
"
ASin = asin(X);
").
:- pragma foreign_proc("C#",
math.asin_2(X::in) = (ASin::out),
[thread_safe, promise_pure],
"
ASin = System.Math.Asin(X);
").
:- pragma foreign_proc("Java",
math.asin_2(X::in) = (ASin::out),
[thread_safe, promise_pure],
"
ASin = java.lang.Math.asin(X);
").
:- pragma foreign_proc("Erlang",
math.asin_2(X::in) = (ASin::out),
[thread_safe, promise_pure],
"
ASin = math:asin(X)
").
math.acos(X) = ACos :-
(
math_domain_checks,
( X < -1.0
; X > 1.0
)
->
throw(domain_error("math.acos"))
;
ACos = math.acos_2(X)
).
:- func math.acos_2(float) = float.
:- pragma foreign_proc("C",
math.acos_2(X::in) = (ACos::out),
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
does_not_affect_liveness],
"
ACos = acos(X);
").
:- pragma foreign_proc("C#",
math.acos_2(X::in) = (ACos::out),
[thread_safe, promise_pure],
"
ACos = System.Math.Acos(X);
").
:- pragma foreign_proc("Java",
math.acos_2(X::in) = (ACos::out),
[thread_safe, promise_pure],
"
ACos = java.lang.Math.acos(X);
").
:- pragma foreign_proc("Erlang",
math.acos_2(X::in) = (ACos::out),
[thread_safe, promise_pure],
"
ACos = math:acos(X)
").
:- pragma foreign_proc("C",
math.atan(X::in) = (ATan::out),
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
does_not_affect_liveness],
"
ATan = atan(X);
").
:- pragma foreign_proc("C#",
math.atan(X::in) = (ATan::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
ATan = System.Math.Atan(X);
").
:- pragma foreign_proc("Java",
math.atan(X::in) = (ATan::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
ATan = java.lang.Math.atan(X);
").
:- pragma foreign_proc("Erlang",
math.atan(X::in) = (ATan::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
ATan = math:atan(X)
").
:- pragma foreign_proc("C",
math.atan2(Y::in, X::in) = (ATan2::out),
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
does_not_affect_liveness],
"
ATan2 = atan2(Y, X);
").
:- pragma foreign_proc("C#",
math.atan2(Y::in, X::in) = (ATan2::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
ATan2 = System.Math.Atan2(Y, X);
").
:- pragma foreign_proc("Java",
math.atan2(Y::in, X::in) = (ATan2::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
ATan2 = java.lang.Math.atan2(Y, X);
").
:- pragma foreign_proc("Erlang",
math.atan2(Y::in, X::in) = (ATan2::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
ATan2 = math:atan2(Y, X)
").
:- pragma foreign_proc("C",
math.sinh(X::in) = (Sinh::out),
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
does_not_affect_liveness],
"
Sinh = sinh(X);
").
:- pragma foreign_proc("C#",
math.sinh(X::in) = (Sinh::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Sinh = System.Math.Sinh(X);
").
:- pragma foreign_proc("Erlang",
math.sinh(X::in) = (Sinh::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Sinh = math:sinh(X)
").
% Java doesn't have any hyperbolic functions built in.
math.sinh(X) = Sinh :-
Sinh = (exp(X)-exp(-X)) / 2.0.
:- pragma foreign_proc("C",
math.cosh(X::in) = (Cosh::out),
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
does_not_affect_liveness],
"
Cosh = cosh(X);
").
:- pragma foreign_proc("C#",
math.cosh(X::in) = (Cosh::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Cosh = System.Math.Cosh(X);
").
:- pragma foreign_proc("Erlang",
math.cosh(X::in) = (Cosh::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Cosh = math:cosh(X)
").
% Java doesn't have any hyperbolic functions built in.
math.cosh(X) = Cosh :-
Cosh = (exp(X)+exp(-X)) / 2.0.
:- pragma foreign_proc("C",
math.tanh(X::in) = (Tanh::out),
[will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
does_not_affect_liveness],
"
Tanh = tanh(X);
").
:- pragma foreign_proc("C#",
math.tanh(X::in) = (Tanh::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Tanh = System.Math.Tanh(X);
").
:- pragma foreign_proc("Erlang",
math.tanh(X::in) = (Tanh::out),
[will_not_call_mercury, promise_pure, thread_safe],
"
Tanh = math:tanh(X)
").
% Java doesn't have any hyperbolic functions built in.
math.tanh(X) = Tanh :-
Tanh = (exp(X)-exp(-X)) / (exp(X)+exp(-X)).
%---------------------------------------------------------------------------%
%---------------------------------------------------------------------------%