[m-rev.] diff: add unchecked math operations

Julien Fischer juliensf at csse.unimelb.edu.au
Mon Mar 5 01:58:39 AEDT 2012


Branches: main

library/math.m:
 	Add unchecked versions of all the operations in this module
 	that don't already have them.

 	Delete the stuff in the header comment about
 	ML_OMIT_MATH_DOMAIN_CHECKS; with the unchecked versions
 	available recompiling the library to omit the domain
 	checks is no longer necessary.

NEWS:
 	Annonce the above additions.

Julien.

Index: NEWS
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/NEWS,v
retrieving revision 1.604
diff -u -r1.604 NEWS
--- NEWS	29 Feb 2012 01:19:18 -0000	1.604
+++ NEWS	4 Mar 2012 14:39:31 -0000
@@ -13,6 +13,9 @@
    pqueue.insert/4, pqueue.remove/4, stack.push/3, stack.push_list/3,
    stack.pop/3 and stack.det_pop/3.

+* We have added versions of the operations in the math module that omit the
+  domain checks.
+

  NEWS for Mercury 11.07.1
  ------------------------
Index: library/math.m
===================================================================
RCS file: /home/mercury/mercury1/repository/mercury/library/math.m,v
retrieving revision 1.62
diff -u -r1.62 math.m
--- library/math.m	30 Nov 2011 03:12:54 -0000	1.62
+++ library/math.m	4 Mar 2012 14:31:53 -0000
@@ -13,29 +13,16 @@
  % Higher mathematical operations.  (The basics are in float.m.)
  %
  % By default, domain errors are currently handled by throwing an exception.
+% For better performance, each operation in this module that can throw a domain
+% exception also has an unchecked version that omits the domain check.
  %
-% 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.
+% The unchecked operations are semantically safe, since the target 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 nuchecked operations  you only have the information that the
+% floating-point exception signal handler gives you.
  %
  %---------------------------------------------------------------------------%
  %---------------------------------------------------------------------------%
@@ -47,10 +34,6 @@
      % 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).

  %---------------------------------------------------------------------------%
@@ -101,10 +84,6 @@
      % Domain restriction: X >= 0
      %
  :- func math.sqrt(float) = float.
-
-    % As above, but the behaviour is undefined if the argument is less
-    % than zero.
-    %
  :- func math.unchecked_sqrt(float) = float.

  :- type math.quadratic_roots
@@ -129,6 +108,7 @@
      % Domain restriction: X >= 0 and (X = 0 implies Y > 0)
      %
  :- func math.pow(float, float) = float.
+:- func math.unchecked_pow(float, float) = float.

      % math.exp(X) = Exp is true if Exp is e raised to the power of X.
      %
@@ -139,24 +119,28 @@
      % Domain restriction: X > 0
      %
  :- func math.ln(float) = float.
+:- func math.unchecked_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.
+:- func math.unchecked_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.
+:- func math.unchecked_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.
+:- func math.unchecked_log(float, float) = float.

  %---------------------------------------------------------------------------%
  %
@@ -181,6 +165,7 @@
      % Domain restriction: X must be in the range [-1,1]
      %
  :- func math.asin(float) = float.
+:- func math.unchecked_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].
@@ -188,6 +173,7 @@
      % Domain restriction: X must be in the range [-1,1]
      %
  :- func math.acos(float) = float.
+:- func math.unchecked_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].
@@ -541,13 +527,11 @@
              Res = 0.0
          )
      ;
-        Res = math.pow_2(X, Y)
+        Res = math.unchecked_pow(X, Y)
      ).

-:- func math.pow_2(float, float) = float.
-
  :- pragma foreign_proc("C",
-    math.pow_2(X::in, Y::in) = (Res::out),
+    math.unchecked_pow(X::in, Y::in) = (Res::out),
      [will_not_call_mercury, promise_pure, thread_safe, will_not_modify_trail,
          does_not_affect_liveness],
  "
@@ -555,21 +539,21 @@
  ").

  :- pragma foreign_proc("C#",
-    math.pow_2(X::in, Y::in) = (Res::out),
+    math.unchecked_pow(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),
+    math.unchecked_pow(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),
+    math.unchecked_pow(X::in, Y::in) = (Res::out),
      [thread_safe, promise_pure],
  "
      Res = math:pow(X, Y)
@@ -605,32 +589,30 @@
      ( math_domain_checks, X =< 0.0 ->
          throw(domain_error("math.ln"))
      ;
-        Log = math.ln_2(X)
+        Log = math.unchecked_ln(X)
      ).

-:- func math.ln_2(float) = float.
-
  :- pragma foreign_proc("C",
-    math.ln_2(X::in) = (Log::out),
+    math.unchecked_ln(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),
+    math.unchecked_ln(X::in) = (Log::out),
      [thread_safe, promise_pure],
  "
      Log = System.Math.Log(X);
  ").
  :- pragma foreign_proc("Java",
-    math.ln_2(X::in) = (Log::out),
+    math.unchecked_ln(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),
+    math.unchecked_ln(X::in) = (Log::out),
      [thread_safe, promise_pure],
  "
      Log = math:log(X)
@@ -640,62 +622,58 @@
      ( math_domain_checks, X =< 0.0 ->
          throw(domain_error("math.log10"))
      ;
-        Log = math.log10_2(X)
+        Log = math.unchecked_log10(X)
      ).

-:- func math.log10_2(float) = float.
-
  :- pragma foreign_proc("C",
-    math.log10_2(X::in) = (Log10::out),
+    math.unchecked_log10(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),
+    math.unchecked_log10(X::in) = (Log10::out),
      [thread_safe, promise_pure],
  "
      Log10 = System.Math.Log10(X);
  ").
  :- pragma foreign_proc("Erlang",
-    math.log10_2(X::in) = (Log10::out),
+    math.unchecked_log10(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.unchecked_log10(X) = math.unchecked_ln(X) / math.unchecked_ln(10.0).

  math.log2(X) = Log :-
      ( math_domain_checks, X =< 0.0 ->
          throw(domain_error("math.log2"))
      ;
-        Log = math.log2_2(X)
+        Log = math.unchecked_log2(X)
      ).

-:- func math.log2_2(float) = float.
-
  :- pragma foreign_proc("C",
-    math.log2_2(X::in) = (Log2::out),
+    math.unchecked_log2(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),
+    math.unchecked_log2(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),
+    math.unchecked_log2(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.unchecked_log2(X) = math.unchecked_ln(X) / math.unchecked_ln(2.0).

  math.log(B, X) = Log :-
      (
@@ -707,27 +685,25 @@
      ->
          throw(domain_error("math.log"))
      ;
-        Log = math.log_2(B, X)
+        Log = math.unchecked_log(B, X)
      ).

-:- func math.log_2(float, float) = float.
-
  :- pragma foreign_proc("C",
-    math.log_2(B::in, X::in) = (Log::out),
+    math.unchecked_log(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),
+    math.unchecked_log(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).
+math.unchecked_log(B, X) = math.unchecked_ln(X) / math.unchecked_ln(B).

  :- pragma foreign_proc("C",
      math.sin(X::in) = (Sin::out),
@@ -816,32 +792,30 @@
      ->
          throw(domain_error("math.asin"))
      ;
-        ASin = math.asin_2(X)
+        ASin = math.unchecked_asin(X)
      ).

-:- func math.asin_2(float) = float.
-
  :- pragma foreign_proc("C",
-    math.asin_2(X::in) = (ASin::out),
+    math.unchecked_asin(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),
+    math.unchecked_asin(X::in) = (ASin::out),
      [thread_safe, promise_pure],
  "
      ASin = System.Math.Asin(X);
  ").
  :- pragma foreign_proc("Java",
-    math.asin_2(X::in) = (ASin::out),
+    math.unchecked_asin(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),
+    math.unchecked_asin(X::in) = (ASin::out),
      [thread_safe, promise_pure],
  "
      ASin = math:asin(X)
@@ -856,38 +830,35 @@
      ->
          throw(domain_error("math.acos"))
      ;
-        ACos = math.acos_2(X)
+        ACos = math.unchecked_acos(X)
      ).

-:- func math.acos_2(float) = float.
-
  :- pragma foreign_proc("C",
-    math.acos_2(X::in) = (ACos::out),
+    math.unchecked_acos(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),
+    math.unchecked_acos(X::in) = (ACos::out),
      [thread_safe, promise_pure],
  "
      ACos = System.Math.Acos(X);
  ").
  :- pragma foreign_proc("Java",
-    math.acos_2(X::in) = (ACos::out),
+    math.unchecked_acos(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),
+    math.unchecked_acos(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,

--------------------------------------------------------------------------
mercury-reviews mailing list
Post messages to:       mercury-reviews at csse.unimelb.edu.au
Administrative Queries: owner-mercury-reviews at csse.unimelb.edu.au
Subscriptions:          mercury-reviews-request at csse.unimelb.edu.au
--------------------------------------------------------------------------



More information about the reviews mailing list