master xplshn/aruu / cmd / posix / awk / math.c
  1/* ***************************************************************
  2 * copyright (c) lucent technologies 1997
  3 * all rights reserved
  4 *
  5 * permission to use, copy, modify, and distribute this software and
  6 * its documentation for any purpose and without fee is hereby
  7 * granted, provided that the above copyright notice appear in all
  8 * copies and that both that the copyright notice and this
  9 * permission notice and warranty disclaimer appear in supporting
 10 * documentation, and that the name lucent technologies or any of
 11 * its entities not be used in advertising or publicity pertaining
 12 * to distribution of the software without specific, written prior
 13 * permission
 14 *
 15 * LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 16 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 17 * IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
 18 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
 19 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
 20 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 21 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
 22 * THIS SOFTWARE
 23 * ************************************************************** */
 24
 25#ifdef __GNUC__
 26#pragma GCC diagnostic ignored "-Wunknown-pragmas"
 27#endif
 28#pragma STDC FENV_ACCESS ON
 29
 30#include <errno.h>
 31#include <fenv.h>
 32#include <math.h>
 33#include <stdio.h>
 34
 35#include "awk.h"
 36
 37#ifndef FE_DIVBYZERO
 38#define FE_DIVBYZERO 0
 39#endif
 40
 41#ifndef FE_INVALID
 42#define FE_INVALID 0
 43#endif
 44
 45#ifndef FE_OVERFLOW
 46#define FE_OVERFLOW 0
 47#endif
 48
 49#ifndef FE_UNDERFLOW
 50#define FE_UNDERFLOW 0
 51#endif
 52
 53#define errclear()                                                                                 \
 54  do {                                                                                             \
 55    errno = 0;                                                                                     \
 56    feclearexcept(FE_ALL_EXCEPT);                                                                  \
 57  } while (0)
 58
 59static double
 60errcheck(double x, const char *s)
 61{
 62  if (errno == EDOM || fetestexcept(FE_INVALID)) {
 63    errno = 0;
 64    WARNING("%s argument out of domain", s);
 65    x = 1;
 66  } else if (errno == ERANGE || fetestexcept(FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW)) {
 67    errno = 0;
 68    WARNING("%s result out of range", s);
 69    x = 1;
 70  }
 71
 72  return x;
 73}
 74
 75double
 76exp_errcheck(double x)
 77{
 78  errclear();
 79  return errcheck(exp(x), "exp");
 80}
 81
 82double
 83log_errcheck(double x)
 84{
 85  errclear();
 86  return errcheck(log(x), "log");
 87}
 88
 89double
 90pow_errcheck(double x, double y)
 91{
 92  errclear();
 93  return errcheck(pow(x, y), "pow");
 94}
 95
 96double
 97sqrt_errcheck(double x)
 98{
 99  errclear();
100  return errcheck(sqrt(x), "sqrt");
101}