POSIX math: implement lround().
authorJarkko Hietaniemi <jhi@iki.fi>
Mon, 8 Sep 2014 14:56:52 +0000 (10:56 -0400)
committerJarkko Hietaniemi <jhi@iki.fi>
Mon, 8 Sep 2014 15:53:10 +0000 (11:53 -0400)
Somehow had missed this so far, but probably because in Perl terms
it is very similar to round(), and very similar to rint().

The API variations are fascinating: round(), roundl(), lround(), lroundl(),
llround(), llroundl().

ext/B/t/concise-xs.t
ext/POSIX/POSIX.xs
ext/POSIX/lib/POSIX.pod

index 2a62781..2cad249 100644 (file)
@@ -201,9 +201,9 @@ my $testpkgs = {
                         hypot ilogb isfinite isgreater isgreaterequal
                         isinf isless islessequal islessgreater isnan
                         isnormal isunordered j0 j1 jn lgamma log1p
-                        log2 logb lrint nan nearbyint nextafter nexttoward
-                        remainder remquo rint round scalbn signbit
-                        sinh tanh tgamma trunc y0 y1 yn/,
+                        log2 logb lrint lround nan nearbyint nextafter
+                        nexttoward remainder remquo rint round scalbn
+                        signbit sinh tanh tgamma trunc y0 y1 yn/,
 
                       ],
               perl => [qw/ import croak AUTOLOAD /,
index 5a32d74..f2f7e40 100644 (file)
    acosh asinh atanh cbrt copysign erf erfc exp2 expm1 fdim fma fmax
    fmin fpclassify hypot ilogb isfinite isgreater isgreaterequal isinf
    isless islessequal islessgreater isnan isnormal isunordered lgamma
-   log1p log2 logb lrint nan nearbyint nextafter nexttoward remainder
+   log1p log2 logb lrint lround nan nearbyint nextafter nexttoward remainder
    remquo rint round scalbn signbit tgamma trunc
 
    See:
 #    else
 #      define c99_lrint        lrintl
 #    endif
+#    if defined(USE_64_BIT_INT) && QUADKIND == QUAD_IS_LONG_LONG
+#      define c99_lround       llroundl
+#    else
+#      define c99_lround       lroundl
+#    endif
 #    define c99_nan    nanl
 #    define c99_nearbyint      nearbyintl
 #    define c99_nextafter      nextafterl
 #    else
 #      define c99_lrint        lrint
 #    endif
+#    if defined(USE_64_BIT_INT) && QUADKIND == QUAD_IS_LONG_LONG
+#      define c99_lround       llround
+#    else
+#      define c99_lround       lround
+#    endif
 #    define c99_nan    nan
 #    define c99_nearbyint      nearbyint
 #    define c99_nextafter      nextafter
  * but on IA64 (Integrity) these do exist, and even on
  * recent enough HP-UX (cc) releases. */
 #  if defined(__hpux) && (defined(__hppa) || defined(_PA_RISC))
+/* lowest known release, could be lower */
 #    if defined(__HP_cc) && __HP_cc >= 111120
 #      undef c99_fma
 #      undef c99_nexttoward
 #      undef c99_fmin
 #      undef c99_fpclassify /* hpux 10.20 has fpclassify but different api */
 #      undef c99_lrint
+#      undef c99_lround
 #      undef c99_nan
 #      undef c99_nearbyint
 #      undef c99_nexttoward
 #    undef c99_isinf
 #    undef c99_isunordered
 #    undef c99_lrint
+#    undef c99_lround
 #    undef c99_nearbyint
 #    undef c99_nexttoward
 #    undef c99_remquo
 
 /* XXX Regarding C99 math.h, VMS seems to be missing these:
 
-  nan nearbyint round scalbn llrint
+  lround nan nearbyint round scalbn llrint
  */
 
 #ifdef __VMS
+#    undef c99_lround
 #    undef c99_nan
 #    undef c99_nearbyint
 #    undef c99_round
 #  undef c99_log1p
 #  undef c99_log2
 #  undef c99_lrint
+#  undef c99_lround
 #  undef c99_remquo
 #  undef c99_rint
 #  undef c99_signbit
@@ -741,6 +756,14 @@ static IV my_lrint(NV x)
 #  endif
 #endif
 
+#ifndef c99_lround
+static IV my_lround(NV x)
+{
+  return (IV)return MY_ROUND_NEAREST(x);
+}
+#  define c99_lround my_lround
+#endif
+
 /* XXX remainder */
 
 /* XXX remquo */
@@ -2099,7 +2122,8 @@ fpclassify(x)
        isnan = 4
        isnormal = 5
        lrint = 6
-        signbit = 7
+       lround = 7
+        signbit = 8
     CODE:
        RETVAL = -1;
        switch (ix) {
@@ -2141,6 +2165,13 @@ fpclassify(x)
 #endif
            break;
        case 7:
+#ifdef c99_lround
+           RETVAL = c99_lround(x);
+#else
+           not_here("lround");
+#endif
+           break;
+       case 8:
        default:
 #ifdef Perl_signbit
            RETVAL = Perl_signbit(x);
index 945cfaf..8dba5eb 100644 (file)
@@ -1087,6 +1087,12 @@ or upward (toward positive infinity) [C99].
 
 For the rounding mode, see L</fegetround> and L</fesetround>.
 
+=item C<lround>
+
+Like L</round>, but as integer, as opposed to floating point [C99].
+
+See also L</ceil>, L</floor>, L</trunc>.
+
 =item C<malloc>
 
 C<malloc()> is C-specific.  Perl does memory management transparently.
@@ -1393,9 +1399,10 @@ for removing (empty) directories, see L<perlfunc/rmdir>.
 
 =item C<round>
 
-Returns the integer nearest to the argument [C99].
+Returns the integer (but still as floating point) nearest to the
+argument [C99].
 
-See also L</ceil>, L</floor>, L</trunc>.
+See also L</ceil>, L</floor>, L</lround>, L</trunc>.
 
 =item C<scalbn>