summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--builtin.c31
-rw-r--r--config/m4/check-math-func.m44
-rw-r--r--configure.ac32
-rw-r--r--libm.h147
4 files changed, 206 insertions, 8 deletions
diff --git a/builtin.c b/builtin.c
index f99ce092..9d4fff1c 100644
--- a/builtin.c
+++ b/builtin.c
@@ -1,4 +1,5 @@
#define _BSD_SOURCE
+#define _GNU_SOURCE
#define _XOPEN_SOURCE
#include <sys/time.h>
#include <stdlib.h>
@@ -90,7 +91,23 @@ static jv f_ ## name(jq_state *jq, jv input) { \
jv_free(input); \
return ret; \
}
+#define LIBM_DD_NO(name)
+
+#define LIBM_DDD(name) \
+static jv f_ ## name(jq_state *jq, jv input, jv a, jv b) { \
+ if (jv_get_kind(a) != JV_KIND_NUMBER || jv_get_kind(b) != JV_KIND_NUMBER) \
+ return type_error(input, "number required"); \
+ jv_free(input); \
+ jv ret = jv_number(name(jv_number_value(a), jv_number_value(b))); \
+ jv_free(a); \
+ jv_free(b); \
+ return ret; \
+}
+#define LIBM_DDD_NO(name)
#include "libm.h"
+#undef LIBM_DDD_NO
+#undef LIBM_DD_NO
+#undef LIBM_DDD
#undef LIBM_DD
static jv f_negate(jq_state *jq, jv input) {
@@ -1201,6 +1218,11 @@ static jv f_current_line(jq_state *jq) {
#define LIBM_DD(name) \
{(cfunction_ptr)f_ ## name, "_" #name, 1},
+#define LIBM_DD_NO(name)
+
+#define LIBM_DDD(name) \
+ {(cfunction_ptr)f_ ## name, "_" #name, 3},
+#define LIBM_DD_NO(name)
static const struct cfunction function_list[] = {
#include "libm.h"
@@ -1268,6 +1290,9 @@ static const struct cfunction function_list[] = {
{(cfunction_ptr)f_current_filename, "input_filename", 1},
{(cfunction_ptr)f_current_line, "input_line_number", 1},
};
+#undef LIBM_DDD_NO
+#undef LIBM_DD_NO
+#undef LIBM_DDD
#undef LIBM_DD
struct bytecoded_builtin { const char* name; block code; };
@@ -1312,6 +1337,9 @@ static block bind_bytecoded_builtins(block b) {
}
#define LIBM_DD(name) "def " #name ": _" #name ";",
+#define LIBM_DDD(name) "def " #name "(a;b): _" #name "(a;b);",
+#define LIBM_DD_NO(name) "def " #name ": \"Error: " #name "() not found at build time\"|error;",
+#define LIBM_DDD_NO(name) "def " #name "(a;b): \"Error: " #name "() not found at build time\"|error;",
static const char* const jq_builtins[] = {
"def error: error(.);",
@@ -1591,6 +1619,9 @@ static const char* const jq_builtins[] = {
" end"
" end;",
};
+#undef LIBM_DDD_NO
+#undef LIBM_DD_NO
+#undef LIBM_DDD
#undef LIBM_DD
diff --git a/config/m4/check-math-func.m4 b/config/m4/check-math-func.m4
new file mode 100644
index 00000000..ce632726
--- /dev/null
+++ b/config/m4/check-math-func.m4
@@ -0,0 +1,4 @@
+dnl AC_FIND_FUNC(func, arguments)
+AC_DEFUN([AC_CHECK_MATH_FUNC], [
+ AC_FIND_FUNC_NO_LIBS([$1], [m], [#include <math.h>], [$2])
+])
diff --git a/configure.ac b/configure.ac
index 16544295..7b59029f 100644
--- a/configure.ac
+++ b/configure.ac
@@ -162,6 +162,38 @@ if test $enable_pthread_tls = yes; then
AC_FIND_FUNC([atexit], [pthread], [#include <stdlib.h>], [NULL])
fi
+dnl libm math.h functions
+AC_CHECK_MATH_FUNC(acos, [.5])
+AC_CHECK_MATH_FUNC(acosh, [.5])
+AC_CHECK_MATH_FUNC(asin, [.5])
+AC_CHECK_MATH_FUNC(asinh, [.5])
+AC_CHECK_MATH_FUNC(atan, [.5])
+AC_CHECK_MATH_FUNC(atanh, [.5])
+AC_CHECK_MATH_FUNC(cbrt, [.5])
+AC_CHECK_MATH_FUNC(cos, [.5])
+AC_CHECK_MATH_FUNC(cosh, [.5])
+AC_CHECK_MATH_FUNC(exp2, [.5])
+AC_CHECK_MATH_FUNC(exp, [.5])
+AC_CHECK_MATH_FUNC(floor, [.5])
+AC_CHECK_MATH_FUNC(j0, [.5])
+AC_CHECK_MATH_FUNC(j1, [.5])
+AC_CHECK_MATH_FUNC(log10, [.5])
+AC_CHECK_MATH_FUNC(log2, [.5])
+AC_CHECK_MATH_FUNC(log, [.5])
+AC_CHECK_MATH_FUNC(sin, [.5])
+AC_CHECK_MATH_FUNC(sinh, [.5])
+AC_CHECK_MATH_FUNC(sqrt, [.5])
+AC_CHECK_MATH_FUNC(tan, [.5])
+AC_CHECK_MATH_FUNC(tanh, [.5])
+AC_CHECK_MATH_FUNC(tgamma, [.5])
+AC_CHECK_MATH_FUNC(y0, [.5])
+AC_CHECK_MATH_FUNC(y1, [.5])
+AC_CHECK_MATH_FUNC(pow, [2,2])
+AC_CHECK_MATH_FUNC(pow10, [2])
+AC_CHECK_MATH_FUNC(atan2, [.5,.5])
+AC_CHECK_MATH_FUNC(hypot, [.5,.5])
+AC_CHECK_MATH_FUNC(remainder, [3,2])
+
dnl Thread local storage
have___thread=no
AC_MSG_CHECKING(for thread-local storage)
diff --git a/libm.h b/libm.h
index f8c52bef..9b1fae9f 100644
--- a/libm.h
+++ b/libm.h
@@ -1,34 +1,165 @@
+#ifdef HAVE_ACOS
LIBM_DD(acos)
+#else
+LIBM_DD_NO(acos)
+#endif
+#ifdef HAVE_ACOSH
LIBM_DD(acosh)
+#else
+LIBM_DD_NO(acosh)
+#endif
+#ifdef HAVE_ASIN
LIBM_DD(asin)
+#else
+LIBM_DD_NO(asin)
+#endif
+#ifdef HAVE_ASINH
LIBM_DD(asinh)
+#else
+LIBM_DD_NO(asinh)
+#endif
+#ifdef HAVE_ATAN
LIBM_DD(atan)
+#else
+LIBM_DD_NO(atan)
+#endif
+#ifdef HAVE_ATANH
LIBM_DD(atanh)
+#else
+LIBM_DD_NO(atanh)
+#endif
+#ifdef HAVE_CBRT
LIBM_DD(cbrt)
+#else
+LIBM_DD_NO(cbrt)
+#endif
+#ifdef HAVE_COS
LIBM_DD(cos)
+#else
+LIBM_DD_NO(cos)
+#endif
+#ifdef HAVE_COSH
LIBM_DD(cosh)
+#else
+LIBM_DD_NO(cosh)
+#endif
+#ifdef HAVE_EXP2
LIBM_DD(exp2)
+#else
+LIBM_DD_NO(exp2)
+#endif
+#ifdef HAVE_EXP
LIBM_DD(exp)
+#else
+LIBM_DD_NO(exp)
+#endif
+#ifdef HAVE_FLOOR
LIBM_DD(floor)
+#else
+LIBM_DD_NO(floor)
+#endif
+#ifdef HAVE_J0
LIBM_DD(j0)
+#else
+LIBM_DD_NO(j0)
+#endif
+#ifdef HAVE_J1
LIBM_DD(j1)
+#else
+LIBM_DD_NO(j1)
+#endif
+#ifdef HAVE_LOG10
LIBM_DD(log10)
+#else
+LIBM_DD_NO(log10)
+#endif
+#ifdef HAVE_LOG2
LIBM_DD(log2)
+#else
+LIBM_DD_NO(log2)
+#endif
+#ifdef HAVE_LOG
LIBM_DD(log)
+#else
+LIBM_DD_NO(log)
+#endif
+#ifdef HAVE_SIN
LIBM_DD(sin)
+#else
+LIBM_DD_NO(sin)
+#endif
+#ifdef HAVE_SINH
LIBM_DD(sinh)
+#else
+LIBM_DD_NO(sinh)
+#endif
+#ifdef HAVE_SQRT
LIBM_DD(sqrt)
+#else
+LIBM_DD_NO(sqrt)
+#endif
+#ifdef HAVE_TAN
LIBM_DD(tan)
+#else
+LIBM_DD_NO(tan)
+#endif
+#ifdef HAVE_TANH
LIBM_DD(tanh)
+#else
+LIBM_DD_NO(tanh)
+#endif
+#ifdef HAVE_TGAMMA
LIBM_DD(tgamma)
+#else
+LIBM_DD_NO(tgamma)
+#endif
+#ifdef HAVE_Y0
LIBM_DD(y0)
+#else
+LIBM_DD_NO(y0)
+#endif
+#ifdef HAVE_Y1
LIBM_DD(y1)
-/* LIBM_DID(jn) */
-/* LIBM_DID(yn) */
-/* LIBM_DDD(pow) */
-/* LIBM_DDD(atan2) */
-/* LIBM_DDD(hypot) */
-/* LIBM_DDD(remainder) */
-/* LIBM_DDI(scalbn) */
-/* LIBM_DDIP(lgamma_r) */
+#else
+LIBM_DD_NO(y1)
+#endif
+#ifdef HAVE_POW
+LIBM_DDD(pow)
+#else
+LIBM_DDD_NO(pow)
+#endif
+#ifdef HAVE_POW10
+LIBM_DD(pow10)
+#else
+LIBM_DD_NO(pow10)
+#endif
+#ifdef HAVE_JN
+LIBM_DID(jn)
+#endif
+#ifdef HAVE_YN
+LIBM_DID(yn)
+#endif
+#ifdef HAVE_ATAN2
+LIBM_DDD(atan2)
+#else
+LIBM_DDD_NO(atan2)
+#endif
+#ifdef HAVE_HYPOT
+LIBM_DDD(hypot)
+#else
+LIBM_DDD_NO(hypot)
+#endif
+#ifdef HAVE_REMAINDER
+LIBM_DDD(remainder)
+#else
+LIBM_DDD_NO(remainder)
+#endif
+#if 0
+#ifdef HAVE_SCALBN
+LIBM_DDI(scalbn)
+#endif
+#ifdef HAVE_LGAMMA_R
+LIBM_DDIP(lgamma_r)
+#endif
+#endif