lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


2014-04-04 15:08 GMT+02:00 Roberto Ierusalimschy <roberto@inf.puc-rio.br>:

> Is there any good logic in having sinh but not asinh, isnormal, isinf,
> feraiseexcept, expm1, log1p, hypot, cbrt, scalbn, and dozens more?
> All of them are useful, but we must always keep in mind the bloating rule.

There is no logic in having sinh but not asinh. Therefore Lua should
provide asinh, acosh and atanh. These functions are the staple of
any first-year calculus student and are called "elementary" in books
about mathematical functions.

expm1 and log1p are debatable, but those sophisticated enough to
know that they exist can look up the pre-C99 workarounds. log1p
is needed to implement the inverse hyperbolics, but I won't push for
exposing at the Lua level.

To assist the team, here are the functions ready-coded in C89.
These versions have been in use (by me only, AFAIK, although
they are on my GitHub site in a package that I have not advertised)
for more than a year.

Dirk Laurie

/* Numerically stable versions of the inverse hyperbolics due to
   W. Kahan. Those can be replaced by C builtins when the C99
   standard is met, removing the need for math_log1p. */
static lua_Number math_log1p (lua_Number x) {
  lua_Number u=1+x;
  if (u==1) return x;
  return log(u)*x/(u-1);
}

static int math_circ0 (lua_State *L) {
  lua_Number x=luaL_checknumber(L, 1);
  lua_pushnumber(L, sqrt(1-x*x));
  return 1;
}

static int math_circ4 (lua_State *L) {
  lua_Number x=luaL_checknumber(L, 1);
  lua_pushnumber(L, sqrt(1+x*x));
  return 1;
}

static int math_circ_4 (lua_State *L) {
  lua_Number x=luaL_checknumber(L, 1);
  lua_pushnumber(L, sqrt(x*x-1));
  return 1;
}

static int math_acosh (lua_State *L) {
  lua_Number x=luaL_checknumber(L, 1);
  lua_pushnumber(L, log(x+sqrt(x*x-1)));
  return 1;
}

static int math_asinh (lua_State *L) {
  lua_Number x=luaL_checknumber(L, 1);
  lua_Number s=fabs(x);
  s=math_log1p(s*(1+s/(sqrt(1+x*x)+1)));
  if (x<0) s=-s;
  lua_pushnumber(L,s);
  return 1;
}

static int math_atanh (lua_State *L) {
  lua_Number x=luaL_checknumber(L, 1);
  lua_Number s=fabs(x);
  s=math_log1p(2*s/(1-s))/2;
  if (x<0) s=-s;
  lua_pushnumber(L,s);
  return 1;
}