root/third_party/libxslt/libexslt/math.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. exsltMathMin
  2. exsltMathMinFunction
  3. exsltMathMax
  4. exsltMathMaxFunction
  5. exsltMathHighest
  6. exsltMathHighestFunction
  7. exsltMathLowest
  8. exsltMathLowestFunction
  9. exsltMathConstant
  10. exsltMathConstantFunction
  11. exsltMathRandom
  12. exsltMathRandomFunction
  13. exsltMathAbs
  14. exsltMathAbsFunction
  15. exsltMathSqrt
  16. exsltMathSqrtFunction
  17. exsltMathPower
  18. exsltMathPowerFunction
  19. exsltMathLog
  20. exsltMathLogFunction
  21. exsltMathSin
  22. exsltMathSinFunction
  23. exsltMathCos
  24. exsltMathCosFunction
  25. exsltMathTan
  26. exsltMathTanFunction
  27. exsltMathAsin
  28. exsltMathAsinFunction
  29. exsltMathAcos
  30. exsltMathAcosFunction
  31. exsltMathAtan
  32. exsltMathAtanFunction
  33. exsltMathAtan2
  34. exsltMathAtan2Function
  35. exsltMathExp
  36. exsltMathExpFunction
  37. exsltMathRegister
  38. exsltMathXpathCtxtRegister

#define IN_LIBEXSLT
#include "libexslt/libexslt.h"

#if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)
#include <win32config.h>
#else
#include "config.h"
#endif

#include <libxml/tree.h>
#include <libxml/xpath.h>
#include <libxml/xpathInternals.h>

#include <libxslt/xsltconfig.h>
#include <libxslt/xsltutils.h>
#include <libxslt/xsltInternals.h>
#include <libxslt/extensions.h>

#ifdef HAVE_MATH_H
#include <math.h>
#endif

#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif

#include "exslt.h"

/**
 * exsltMathMin:
 * @ns:  a node-set
 *
 * Implements the EXSLT - Math min() function:
 *    number math:min (node-set)
 *
 * Returns the minimum value of the nodes passed as the argument, or
 *         xmlXPathNAN if @ns is NULL or empty or if one of the nodes
 *         turns into NaN.
 */
static double
exsltMathMin (xmlNodeSetPtr ns) {
    double ret, cur;
    int i;

    if ((ns == NULL) || (ns->nodeNr == 0))
        return(xmlXPathNAN);
    ret = xmlXPathCastNodeToNumber(ns->nodeTab[0]);
    if (xmlXPathIsNaN(ret))
        return(xmlXPathNAN);
    for (i = 1; i < ns->nodeNr; i++) {
        cur = xmlXPathCastNodeToNumber(ns->nodeTab[i]);
        if (xmlXPathIsNaN(cur))
            return(xmlXPathNAN);
        if (cur < ret)
            ret = cur;
    }
    return(ret);
}

/**
 * exsltMathMinFunction:
 * @ctxt:  an XPath parser context
 * @nargs:  the number of arguments
 *
 * Wraps #exsltMathMin for use by the XPath processor.
 */
static void
exsltMathMinFunction (xmlXPathParserContextPtr ctxt, int nargs) {
    xmlNodeSetPtr ns;
    double ret;
    void *user = NULL;

    if (nargs != 1) {
        xsltGenericError(xsltGenericErrorContext,
                         "math:min: invalid number of arguments\n");
        ctxt->error = XPATH_INVALID_ARITY;
        return;
    }
    /* We need to delay the freeing of value->user */
    if ((ctxt->value != NULL) && (ctxt->value->boolval != 0)) {
        user = ctxt->value->user;
        ctxt->value->boolval = 0;
        ctxt->value->user = NULL;
    }
    ns = xmlXPathPopNodeSet(ctxt);
    if (xmlXPathCheckError(ctxt))
        return;

    ret = exsltMathMin(ns);

    xmlXPathFreeNodeSet(ns);
    if (user != NULL)
        xmlFreeNodeList((xmlNodePtr)user);

    xmlXPathReturnNumber(ctxt, ret);
}

/**
 * exsltMathMax:
 * @ns:  a node-set
 *
 * Implements the EXSLT - Math max() function:
 *    number math:max (node-set)
 *
 * Returns the maximum value of the nodes passed as arguments, or
 *         xmlXPathNAN if @ns is NULL or empty or if one of the nodes
 *         turns into NaN.
 */
static double
exsltMathMax (xmlNodeSetPtr ns) {
    double ret, cur;
    int i;

    if ((ns == NULL) || (ns->nodeNr == 0))
        return(xmlXPathNAN);
    ret = xmlXPathCastNodeToNumber(ns->nodeTab[0]);
    if (xmlXPathIsNaN(ret))
        return(xmlXPathNAN);
    for (i = 1; i < ns->nodeNr; i++) {
        cur = xmlXPathCastNodeToNumber(ns->nodeTab[i]);
        if (xmlXPathIsNaN(cur))
            return(xmlXPathNAN);
        if (cur > ret)
            ret = cur;
    }
    return(ret);
}

/**
 * exsltMathMaxFunction:
 * @ctxt:  an XPath parser context
 * @nargs:  the number of arguments
 *
 * Wraps #exsltMathMax for use by the XPath processor.
 */
static void
exsltMathMaxFunction (xmlXPathParserContextPtr ctxt, int nargs) {
    xmlNodeSetPtr ns;
    double ret;
    void *user = NULL;

    if (nargs != 1) {
        xmlXPathSetArityError(ctxt);
        return;
    }

    /* We need to delay the freeing of value->user */
    if ((ctxt->value != NULL) && (ctxt->value->boolval != 0)) {
        user = ctxt->value->user;
        ctxt->value->boolval = 0;
        ctxt->value->user = 0;
    }
    ns = xmlXPathPopNodeSet(ctxt);
    if (xmlXPathCheckError(ctxt))
        return;

    ret = exsltMathMax(ns);

    xmlXPathFreeNodeSet(ns);

    if (user != NULL)
        xmlFreeNodeList((xmlNodePtr)user);
    xmlXPathReturnNumber(ctxt, ret);
}

/**
 * exsltMathHighest:
 * @ns:  a node-set
 *
 * Implements the EXSLT - Math highest() function:
 *    node-set math:highest (node-set)
 *
 * Returns the nodes in the node-set whose value is the maximum value
 *         for the node-set.
 */
static xmlNodeSetPtr
exsltMathHighest (xmlNodeSetPtr ns) {
    xmlNodeSetPtr ret = xmlXPathNodeSetCreate(NULL);
    double max, cur;
    int i;

    if ((ns == NULL) || (ns->nodeNr == 0))
        return(ret);

    max = xmlXPathCastNodeToNumber(ns->nodeTab[0]);
    if (xmlXPathIsNaN(max))
        return(ret);
    else
        xmlXPathNodeSetAddUnique(ret, ns->nodeTab[0]);

    for (i = 1; i < ns->nodeNr; i++) {
        cur = xmlXPathCastNodeToNumber(ns->nodeTab[i]);
        if (xmlXPathIsNaN(cur)) {
            xmlXPathEmptyNodeSet(ret);
            return(ret);
        }
        if (cur < max)
            continue;
        if (cur > max) {
            max = cur;
            xmlXPathEmptyNodeSet(ret);
            xmlXPathNodeSetAddUnique(ret, ns->nodeTab[i]);
            continue;
        }
        xmlXPathNodeSetAddUnique(ret, ns->nodeTab[i]);
    }
    return(ret);
}

/**
 * exsltMathHighestFunction:
 * @ctxt:  an XPath parser context
 * @nargs:  the number of arguments
 *
 * Wraps #exsltMathHighest for use by the XPath processor
 */
static void
exsltMathHighestFunction (xmlXPathParserContextPtr ctxt, int nargs) {
    xmlNodeSetPtr ns, ret;
    void *user = NULL;

    if (nargs != 1) {
        xmlXPathSetArityError(ctxt);
        return;
    }

    /* We need to delay the freeing of value->user */
    if ((ctxt->value != NULL) && ctxt->value->boolval != 0) {
        user = ctxt->value->user;
        ctxt->value->boolval = 0;
        ctxt->value->user = NULL;
    }
    ns = xmlXPathPopNodeSet(ctxt);
    if (xmlXPathCheckError(ctxt))
        return;

    ret = exsltMathHighest(ns);

    xmlXPathFreeNodeSet(ns);
    if (user != NULL)
        xmlFreeNodeList((xmlNodePtr)user);

    xmlXPathReturnNodeSet(ctxt, ret);
}

/**
 * exsltMathLowest:
 * @ns:  a node-set
 *
 * Implements the EXSLT - Math lowest() function
 *    node-set math:lowest (node-set)
 *
 * Returns the nodes in the node-set whose value is the minimum value
 *         for the node-set.
 */
static xmlNodeSetPtr
exsltMathLowest (xmlNodeSetPtr ns) {
    xmlNodeSetPtr ret = xmlXPathNodeSetCreate(NULL);
    double min, cur;
    int i;

    if ((ns == NULL) || (ns->nodeNr == 0))
        return(ret);

    min = xmlXPathCastNodeToNumber(ns->nodeTab[0]);
    if (xmlXPathIsNaN(min))
        return(ret);
    else
        xmlXPathNodeSetAddUnique(ret, ns->nodeTab[0]);

    for (i = 1; i < ns->nodeNr; i++) {
        cur = xmlXPathCastNodeToNumber(ns->nodeTab[i]);
        if (xmlXPathIsNaN(cur)) {
            xmlXPathEmptyNodeSet(ret);
            return(ret);
        }
        if (cur > min)
            continue;
        if (cur < min) {
            min = cur;
            xmlXPathEmptyNodeSet(ret);
            xmlXPathNodeSetAddUnique(ret, ns->nodeTab[i]);
            continue;
        }
        xmlXPathNodeSetAddUnique(ret, ns->nodeTab[i]);
    }
    return(ret);
}

/**
 * exsltMathLowestFunction:
 * @ctxt:  an XPath parser context
 * @nargs:  the number of arguments
 *
 * Wraps #exsltMathLowest for use by the XPath processor
 */
static void
exsltMathLowestFunction (xmlXPathParserContextPtr ctxt, int nargs) {
    xmlNodeSetPtr ns, ret;
    void *user = NULL;
    

    if (nargs != 1) {
        xmlXPathSetArityError(ctxt);
        return;
    }

    /* We need to delay the freeing of value->user */
    if ((ctxt->value != NULL) && (ctxt->value->boolval != 0)) {
        user = ctxt->value->user;
        ctxt->value->boolval = 0;
        ctxt->value->user = NULL;
    }
    ns = xmlXPathPopNodeSet(ctxt);
    if (xmlXPathCheckError(ctxt))
        return;

    ret = exsltMathLowest(ns);

    xmlXPathFreeNodeSet(ns);
    if (user != NULL)
        xmlFreeNodeList((xmlNodePtr)user);

    xmlXPathReturnNodeSet(ctxt, ret);
}

/* math other functions */

/* constant values */
#define EXSLT_PI        (const xmlChar *) \
                        "3.1415926535897932384626433832795028841971693993751"
#define EXSLT_E         (const xmlChar *) \
                        "2.71828182845904523536028747135266249775724709369996"
#define EXSLT_SQRRT2    (const xmlChar *) \
                        "1.41421356237309504880168872420969807856967187537694"
#define EXSLT_LN2       (const xmlChar *) \
                        "0.69314718055994530941723212145817656807550013436025"
#define EXSLT_LN10      (const xmlChar *) \
                        "2.30258509299404568402"
#define EXSLT_LOG2E     (const xmlChar *) \
                        "1.4426950408889634074"
#define EXSLT_SQRT1_2   (const xmlChar *) \
                        "0.70710678118654752440"

/**
 * exsltMathConstant
 * @name: string
 * @precision:  number
 *
 * Implements the EXSLT - Math constant function:
 *     number math:constant(string, number)
 *
 * Returns a number value of the given constant with the given precision or
 * xmlXPathNAN if name is unknown.
 * The constants are PI, E, SQRRT2, LN2, LN10, LOG2E, and SQRT1_2
 */
static double
exsltMathConstant (xmlChar *name, double precision) {
    xmlChar *str;
    double ret;

    if ((name == NULL) || (xmlXPathIsNaN(precision)) || (precision < 1.0)) {
        return xmlXPathNAN;
    }

    if (xmlStrEqual(name, BAD_CAST "PI")) {
        int len = xmlStrlen(EXSLT_PI);

        if (precision <= len)
            len = (int)precision;
        
        str = xmlStrsub(EXSLT_PI, 0, len);

    } else if (xmlStrEqual(name, BAD_CAST "E")) {
        int len = xmlStrlen(EXSLT_E);

        if (precision <= len)
            len = (int)precision;
        
        str = xmlStrsub(EXSLT_E, 0, len);

    } else if (xmlStrEqual(name, BAD_CAST "SQRRT2")) {
        int len = xmlStrlen(EXSLT_SQRRT2);

        if (precision <= len)
            len = (int)precision;
        
        str = xmlStrsub(EXSLT_SQRRT2, 0, len);

    } else if (xmlStrEqual(name, BAD_CAST "LN2")) {
        int len = xmlStrlen(EXSLT_LN2);

        if (precision <= len)
            len = (int)precision;
        
        str = xmlStrsub(EXSLT_LN2, 0, len);

    } else if (xmlStrEqual(name, BAD_CAST "LN10")) {
        int len = xmlStrlen(EXSLT_LN10);

        if (precision <= len)
            len = (int)precision;
        
        str = xmlStrsub(EXSLT_LN10, 0, len);

    } else if (xmlStrEqual(name, BAD_CAST "LOG2E")) {
        int len = xmlStrlen(EXSLT_LOG2E);

        if (precision <= len)
            len = (int)precision;
        
        str = xmlStrsub(EXSLT_LOG2E, 0, len);

    } else if (xmlStrEqual(name, BAD_CAST "SQRT1_2")) {
        int len = xmlStrlen(EXSLT_SQRT1_2);

        if (precision <= len)
            len = (int)precision;
        
        str = xmlStrsub(EXSLT_SQRT1_2, 0, len);

    } else {
        str = NULL;
    }
    if (str == NULL)
        return xmlXPathNAN;
    ret = xmlXPathCastStringToNumber(str);
    xmlFree(str);
    return ret;
}

/**
 * exsltMathConstantFunction:
 * @ctxt:  an XPath parser context
 * @nargs:  the number of arguments
 *
 * Wraps #exsltMathConstant for use by the XPath processor.
 */
static void
exsltMathConstantFunction (xmlXPathParserContextPtr ctxt, int nargs) {
    double   ret;
    xmlChar *name;

    if (nargs != 2) {
        xmlXPathSetArityError(ctxt);
        return;
    }
    ret = xmlXPathPopNumber(ctxt);
    if (xmlXPathCheckError(ctxt))
        return;

    name = xmlXPathPopString(ctxt);
    if (xmlXPathCheckError(ctxt))
        return;

    ret = exsltMathConstant(name, ret);
    if (name != NULL)
        xmlFree(name);

    xmlXPathReturnNumber(ctxt, ret);
}

#if defined(HAVE_STDLIB_H) && defined(RAND_MAX)

/**
 * exsltMathRandom:
 *
 * Implements the EXSLT - Math random() function:
 *    number math:random ()
 *
 * Returns a random number between 0 and 1 inclusive.
 */
static double
exsltMathRandom (void) {
    double ret;
    int num;

    num = rand();
    ret = (double)num / (double)RAND_MAX;
    return(ret);
}

/**
 * exsltMathRandomFunction:
 * @ctxt:  an XPath parser context
 * @nargs:  the number of arguments
 *
 * Wraps #exsltMathRandom for use by the XPath processor.
 */
static void
exsltMathRandomFunction (xmlXPathParserContextPtr ctxt, int nargs) {
    double ret;

    if (nargs != 0) {
        xmlXPathSetArityError(ctxt);
        return;
    }

    ret = exsltMathRandom();

    xmlXPathReturnNumber(ctxt, ret);
}

#endif /* defined(HAVE_STDLIB_H) && defined(RAND_MAX) */

#if HAVE_MATH_H

/**
 * exsltMathAbs:
 * @num:  a double
 *
 * Implements the EXSLT - Math abs() function:
 *    number math:abs (number)
 *
 * Returns the absolute value of the argument, or xmlXPathNAN if @num is Nan.
 */
static double
exsltMathAbs (double num) {
    double ret;

    if (xmlXPathIsNaN(num))
        return(xmlXPathNAN);
    ret = fabs(num);
    return(ret);
}

/**
 * exsltMathAbsFunction:
 * @ctxt:  an XPath parser context
 * @nargs:  the number of arguments
 *
 * Wraps #exsltMathAbs for use by the XPath processor.
 */
static void
exsltMathAbsFunction (xmlXPathParserContextPtr ctxt, int nargs) {
    double ret;

    if (nargs != 1) {
        xmlXPathSetArityError(ctxt);
        return;
    }
    ret = xmlXPathPopNumber(ctxt);
    if (xmlXPathCheckError(ctxt))
        return;

    ret = exsltMathAbs(ret);

    xmlXPathReturnNumber(ctxt, ret);
}

/**
 * exsltMathSqrt:
 * @num:  a double
 *
 * Implements the EXSLT - Math sqrt() function:
 *    number math:sqrt (number)
 *
 * Returns the square root of the argument, or xmlXPathNAN if @num is Nan.
 */
static double
exsltMathSqrt (double num) {
    double ret;

    if (xmlXPathIsNaN(num))
        return(xmlXPathNAN);
    ret = sqrt(num);
    return(ret);
}

/**
 * exsltMathSqrtFunction:
 * @ctxt:  an XPath parser context
 * @nargs:  the number of arguments
 *
 * Wraps #exsltMathSqrt for use by the XPath processor.
 */
static void
exsltMathSqrtFunction (xmlXPathParserContextPtr ctxt, int nargs) {
    double ret;

    if (nargs != 1) {
        xmlXPathSetArityError(ctxt);
        return;
    }
    ret = xmlXPathPopNumber(ctxt);
    if (xmlXPathCheckError(ctxt))
        return;

    ret = exsltMathSqrt(ret);

    xmlXPathReturnNumber(ctxt, ret);
}

/**
 * exsltMathPower:
 * @base:  a double
 * @power:  a double
 *
 * Implements the EXSLT - Math power() function:
 *    number math:power (number, number)
 *
 * Returns the power base and power arguments, or xmlXPathNAN
 * if either @base or @power is Nan.
 */
static double
exsltMathPower (double base, double power) {
    double ret;

    if ((xmlXPathIsNaN(base) || xmlXPathIsNaN(power)))
        return(xmlXPathNAN);
    ret = pow(base, power);
    return(ret);
}

/**
 * exsltMathPower:
 * @ctxt:  an XPath parser context
 * @nargs:  the number of arguments
 *
 * Wraps #exsltMathPower for use by the XPath processor.
 */
static void
exsltMathPowerFunction (xmlXPathParserContextPtr ctxt, int nargs) {
    double ret, base;

    if (nargs != 2) {
        xmlXPathSetArityError(ctxt);
        return;
    }
    ret = xmlXPathPopNumber(ctxt);
    if (xmlXPathCheckError(ctxt))
        return;

    /* power */
    base = xmlXPathPopNumber(ctxt);
    if (xmlXPathCheckError(ctxt))
        return;

    ret = exsltMathPower(base, ret);

    xmlXPathReturnNumber(ctxt, ret);
}

/**
 * exsltMathLog:
 * @num:  a double
 *
 * Implements the EXSLT - Math log() function:
 *    number math:log (number)
 *
 * Returns the natural log of the argument, or xmlXPathNAN if @num is Nan.
 */
static double
exsltMathLog (double num) {
    double ret;

    if (xmlXPathIsNaN(num))
        return(xmlXPathNAN);
    ret = log(num);
    return(ret);
}

/**
 * exsltMathLogFunction:
 * @ctxt:  an XPath parser context
 * @nargs:  the number of arguments
 *
 * Wraps #exsltMathLog for use by the XPath processor.
 */
static void
exsltMathLogFunction (xmlXPathParserContextPtr ctxt, int nargs) {
    double ret;

    if (nargs != 1) {
        xmlXPathSetArityError(ctxt);
        return;
    }
    ret = xmlXPathPopNumber(ctxt);
    if (xmlXPathCheckError(ctxt))
        return;

    ret = exsltMathLog(ret);

    xmlXPathReturnNumber(ctxt, ret);
}

/**
 * exsltMathSin:
 * @num:  a double
 *
 * Implements the EXSLT - Math sin() function:
 *    number math:sin (number)
 *
 * Returns the sine of the argument, or xmlXPathNAN if @num is Nan.
 */
static double
exsltMathSin (double num) {
    double ret;

    if (xmlXPathIsNaN(num))
        return(xmlXPathNAN);
    ret = sin(num);
    return(ret);
}

/**
 * exsltMathSinFunction:
 * @ctxt:  an XPath parser context
 * @nargs:  the number of arguments
 *
 * Wraps #exsltMathSin for use by the XPath processor.
 */
static void
exsltMathSinFunction (xmlXPathParserContextPtr ctxt, int nargs) {
    double ret;

    if (nargs != 1) {
        xmlXPathSetArityError(ctxt);
        return;
    }
    ret = xmlXPathPopNumber(ctxt);
    if (xmlXPathCheckError(ctxt))
        return;

    ret = exsltMathSin(ret);

    xmlXPathReturnNumber(ctxt, ret);
}

/**
 * exsltMathCos:
 * @num:  a double
 *
 * Implements the EXSLT - Math cos() function:
 *    number math:cos (number)
 *
 * Returns the cosine of the argument, or xmlXPathNAN if @num is Nan.
 */
static double
exsltMathCos (double num) {
    double ret;

    if (xmlXPathIsNaN(num))
        return(xmlXPathNAN);
    ret = cos(num);
    return(ret);
}

/**
 * exsltMathCosFunction:
 * @ctxt:  an XPath parser context
 * @nargs:  the number of arguments
 *
 * Wraps #exsltMathCos for use by the XPath processor.
 */
static void
exsltMathCosFunction (xmlXPathParserContextPtr ctxt, int nargs) {
    double ret;

    if (nargs != 1) {
        xmlXPathSetArityError(ctxt);
        return;
    }
    ret = xmlXPathPopNumber(ctxt);
    if (xmlXPathCheckError(ctxt))
        return;

    ret = exsltMathCos(ret);

    xmlXPathReturnNumber(ctxt, ret);
}

/**
 * exsltMathTan:
 * @num:  a double
 *
 * Implements the EXSLT - Math tan() function:
 *    number math:tan (number)
 *
 * Returns the tangent of the argument, or xmlXPathNAN if @num is Nan.
 */
static double
exsltMathTan (double num) {
    double ret;

    if (xmlXPathIsNaN(num))
        return(xmlXPathNAN);
    ret = tan(num);
    return(ret);
}

/**
 * exsltMathTanFunction:
 * @ctxt:  an XPath parser context
 * @nargs:  the number of arguments
 *
 * Wraps #exsltMathTan for use by the XPath processor.
 */
static void
exsltMathTanFunction (xmlXPathParserContextPtr ctxt, int nargs) {
    double ret;

    if (nargs != 1) {
        xmlXPathSetArityError(ctxt);
        return;
    }
    ret = xmlXPathPopNumber(ctxt);
    if (xmlXPathCheckError(ctxt))
        return;

    ret = exsltMathTan(ret);

    xmlXPathReturnNumber(ctxt, ret);
}

/**
 * exsltMathAsin:
 * @num:  a double
 *
 * Implements the EXSLT - Math asin() function:
 *    number math:asin (number)
 *
 * Returns the arc sine of the argument, or xmlXPathNAN if @num is Nan.
 */
static double
exsltMathAsin (double num) {
    double ret;

    if (xmlXPathIsNaN(num))
        return(xmlXPathNAN);
    ret = asin(num);
    return(ret);
}

/**
 * exsltMathAsinFunction:
 * @ctxt:  an XPath parser context
 * @nargs:  the number of arguments
 *
 * Wraps #exsltMathAsin for use by the XPath processor.
 */
static void
exsltMathAsinFunction (xmlXPathParserContextPtr ctxt, int nargs) {
    double ret;

    if (nargs != 1) {
        xmlXPathSetArityError(ctxt);
        return;
    }
    ret = xmlXPathPopNumber(ctxt);
    if (xmlXPathCheckError(ctxt))
        return;

    ret = exsltMathAsin(ret);

    xmlXPathReturnNumber(ctxt, ret);
}

/**
 * exsltMathAcos:
 * @num:  a double
 *
 * Implements the EXSLT - Math acos() function:
 *    number math:acos (number)
 *
 * Returns the arc cosine of the argument, or xmlXPathNAN if @num is Nan.
 */
static double
exsltMathAcos (double num) {
    double ret;

    if (xmlXPathIsNaN(num))
        return(xmlXPathNAN);
    ret = acos(num);
    return(ret);
}

/**
 * exsltMathAcosFunction:
 * @ctxt:  an XPath parser context
 * @nargs:  the number of arguments
 *
 * Wraps #exsltMathAcos for use by the XPath processor.
 */
static void
exsltMathAcosFunction (xmlXPathParserContextPtr ctxt, int nargs) {
    double ret;

    if (nargs != 1) {
        xmlXPathSetArityError(ctxt);
        return;
    }
    ret = xmlXPathPopNumber(ctxt);
    if (xmlXPathCheckError(ctxt))
        return;

    ret = exsltMathAcos(ret);

    xmlXPathReturnNumber(ctxt, ret);
}

/**
 * exsltMathAtan:
 * @num:  a double
 *
 * Implements the EXSLT - Math atan() function:
 *    number math:atan (number)
 *
 * Returns the arc tangent of the argument, or xmlXPathNAN if @num is Nan.
 */
static double
exsltMathAtan (double num) {
    double ret;

    if (xmlXPathIsNaN(num))
        return(xmlXPathNAN);
    ret = atan(num);
    return(ret);
}

/**
 * exsltMathAtanFunction:
 * @ctxt:  an XPath parser context
 * @nargs:  the number of arguments
 *
 * Wraps #exsltMathAtan for use by the XPath processor.
 */
static void
exsltMathAtanFunction (xmlXPathParserContextPtr ctxt, int nargs) {
    double ret;

    if (nargs != 1) {
        xmlXPathSetArityError(ctxt);
        return;
    }
    ret = xmlXPathPopNumber(ctxt);
    if (xmlXPathCheckError(ctxt))
        return;

    ret = exsltMathAtan(ret);

    xmlXPathReturnNumber(ctxt, ret);
}

/**
 * exsltMathAtan2:
 * @y:  a double
 * @x:  a double
 *
 * Implements the EXSLT - Math atan2() function:
 *    number math:atan2 (number, number)
 *
 * Returns the arc tangent function of the y/x arguments, or xmlXPathNAN
 * if either @y or @x is Nan.
 */
static double
exsltMathAtan2 (double y, double x) {
    double ret;

    if ((xmlXPathIsNaN(y) || xmlXPathIsNaN(x)))
        return(xmlXPathNAN);
    ret = atan2(y, x);
    return(ret);
}

/**
 * exsltMathAtan2Function:
 * @ctxt:  an XPath parser context
 * @nargs:  the number of arguments
 *
 * Wraps #exsltMathAtan2 for use by the XPath processor.
 */
static void
exsltMathAtan2Function (xmlXPathParserContextPtr ctxt, int nargs) {
    double ret, x;

    if (nargs != 2) {
        xmlXPathSetArityError(ctxt);
        return;
    }
    x = xmlXPathPopNumber(ctxt);
    if (xmlXPathCheckError(ctxt))
        return;

    /* y */
    ret = xmlXPathPopNumber(ctxt);
    if (xmlXPathCheckError(ctxt))
        return;

    ret = exsltMathAtan2(ret, x);

    xmlXPathReturnNumber(ctxt, ret);
}

/**
 * exsltMathExp:
 * @num:  a double
 *
 * Implements the EXSLT - Math exp() function:
 *    number math:exp (number)
 *
 * Returns the exponential function of the argument, or xmlXPathNAN if
 * @num is Nan.
 */
static double
exsltMathExp (double num) {
    double ret;

    if (xmlXPathIsNaN(num))
        return(xmlXPathNAN);
    ret = exp(num);
    return(ret);
}

/**
 * exsltMathExpFunction:
 * @ctxt:  an XPath parser context
 * @nargs:  the number of arguments
 *
 * Wraps #exsltMathExp for use by the XPath processor.
 */
static void
exsltMathExpFunction (xmlXPathParserContextPtr ctxt, int nargs) {
    double ret;

    if (nargs != 1) {
        xmlXPathSetArityError(ctxt);
        return;
    }
    ret = xmlXPathPopNumber(ctxt);
    if (xmlXPathCheckError(ctxt))
        return;

    ret = exsltMathExp(ret);

    xmlXPathReturnNumber(ctxt, ret);
}

#endif /* HAVE_MATH_H */

/**
 * exsltMathRegister:
 *
 * Registers the EXSLT - Math module
 */

void
exsltMathRegister (void) {
    xsltRegisterExtModuleFunction ((const xmlChar *) "min",
                                   EXSLT_MATH_NAMESPACE,
                                   exsltMathMinFunction);
    xsltRegisterExtModuleFunction ((const xmlChar *) "max",
                                   EXSLT_MATH_NAMESPACE,
                                   exsltMathMaxFunction);
    xsltRegisterExtModuleFunction ((const xmlChar *) "highest",
                                   EXSLT_MATH_NAMESPACE,
                                   exsltMathHighestFunction);
    xsltRegisterExtModuleFunction ((const xmlChar *) "lowest",
                                   EXSLT_MATH_NAMESPACE,
                                   exsltMathLowestFunction);
    /* register other math functions */
    xsltRegisterExtModuleFunction ((const xmlChar *) "constant",
                                   EXSLT_MATH_NAMESPACE,
                                   exsltMathConstantFunction);
#ifdef HAVE_STDLIB_H
    xsltRegisterExtModuleFunction ((const xmlChar *) "random",
                                   EXSLT_MATH_NAMESPACE,
                                   exsltMathRandomFunction);
#endif
#if HAVE_MATH_H
    xsltRegisterExtModuleFunction ((const xmlChar *) "abs",
                                   EXSLT_MATH_NAMESPACE,
                                   exsltMathAbsFunction);
    xsltRegisterExtModuleFunction ((const xmlChar *) "sqrt",
                                   EXSLT_MATH_NAMESPACE,
                                   exsltMathSqrtFunction);
    xsltRegisterExtModuleFunction ((const xmlChar *) "power",
                                   EXSLT_MATH_NAMESPACE,
                                   exsltMathPowerFunction);
    xsltRegisterExtModuleFunction ((const xmlChar *) "log",
                                   EXSLT_MATH_NAMESPACE,
                                   exsltMathLogFunction);
    xsltRegisterExtModuleFunction ((const xmlChar *) "sin",
                                   EXSLT_MATH_NAMESPACE,
                                   exsltMathSinFunction);
    xsltRegisterExtModuleFunction ((const xmlChar *) "cos",
                                   EXSLT_MATH_NAMESPACE,
                                   exsltMathCosFunction);
    xsltRegisterExtModuleFunction ((const xmlChar *) "tan",
                                   EXSLT_MATH_NAMESPACE,
                                   exsltMathTanFunction);
    xsltRegisterExtModuleFunction ((const xmlChar *) "asin",
                                   EXSLT_MATH_NAMESPACE,
                                   exsltMathAsinFunction);
    xsltRegisterExtModuleFunction ((const xmlChar *) "acos",
                                   EXSLT_MATH_NAMESPACE,
                                   exsltMathAcosFunction);
    xsltRegisterExtModuleFunction ((const xmlChar *) "atan",
                                   EXSLT_MATH_NAMESPACE,
                                   exsltMathAtanFunction);
    xsltRegisterExtModuleFunction ((const xmlChar *) "atan2",
                                   EXSLT_MATH_NAMESPACE,
                                   exsltMathAtan2Function);
    xsltRegisterExtModuleFunction ((const xmlChar *) "exp",
                                   EXSLT_MATH_NAMESPACE,
                                   exsltMathExpFunction);
#endif
}

/**
 * exsltMathXpathCtxtRegister:
 *
 * Registers the EXSLT - Math module for use outside XSLT
 */
int
exsltMathXpathCtxtRegister (xmlXPathContextPtr ctxt, const xmlChar *prefix)
{
    if (ctxt
        && prefix
        && !xmlXPathRegisterNs(ctxt,
                               prefix,
                               (const xmlChar *) EXSLT_MATH_NAMESPACE)
        && !xmlXPathRegisterFuncNS(ctxt,
                                   (const xmlChar *) "min",
                                   (const xmlChar *) EXSLT_MATH_NAMESPACE,
                                   exsltMathMinFunction)
        && !xmlXPathRegisterFuncNS(ctxt,
                                   (const xmlChar *) "max",
                                   (const xmlChar *) EXSLT_MATH_NAMESPACE,
                                   exsltMathMaxFunction)
        && !xmlXPathRegisterFuncNS(ctxt,
                                   (const xmlChar *) "highest",
                                   (const xmlChar *) EXSLT_MATH_NAMESPACE,
                                   exsltMathHighestFunction)
        && !xmlXPathRegisterFuncNS(ctxt,
                                   (const xmlChar *) "lowest",
                                   (const xmlChar *) EXSLT_MATH_NAMESPACE,
                                   exsltMathLowestFunction)
#ifdef HAVE_STDLIB_H
        && !xmlXPathRegisterFuncNS(ctxt,
                                   (const xmlChar *) "random",
                                   (const xmlChar *) EXSLT_MATH_NAMESPACE,
                                   exsltMathRandomFunction)
#endif
#if HAVE_MATH_H
        && !xmlXPathRegisterFuncNS(ctxt,
                                   (const xmlChar *) "abs",
                                   (const xmlChar *) EXSLT_MATH_NAMESPACE,
                                   exsltMathAbsFunction)
        && !xmlXPathRegisterFuncNS(ctxt,
                                   (const xmlChar *) "sqrt",
                                   (const xmlChar *) EXSLT_MATH_NAMESPACE,
                                   exsltMathSqrtFunction)
        && !xmlXPathRegisterFuncNS(ctxt,
                                   (const xmlChar *) "power",
                                   (const xmlChar *) EXSLT_MATH_NAMESPACE,
                                   exsltMathPowerFunction)
        && !xmlXPathRegisterFuncNS(ctxt,
                                   (const xmlChar *) "log",
                                   (const xmlChar *) EXSLT_MATH_NAMESPACE,
                                   exsltMathLogFunction)
        && !xmlXPathRegisterFuncNS(ctxt,
                                   (const xmlChar *) "sin",
                                   (const xmlChar *) EXSLT_MATH_NAMESPACE,
                                   exsltMathSinFunction)
        && !xmlXPathRegisterFuncNS(ctxt,
                                   (const xmlChar *) "cos",
                                   (const xmlChar *) EXSLT_MATH_NAMESPACE,
                                   exsltMathCosFunction)
        && !xmlXPathRegisterFuncNS(ctxt,
                                   (const xmlChar *) "tan",
                                   (const xmlChar *) EXSLT_MATH_NAMESPACE,
                                   exsltMathTanFunction)
        && !xmlXPathRegisterFuncNS(ctxt,
                                   (const xmlChar *) "asin",
                                   (const xmlChar *) EXSLT_MATH_NAMESPACE,
                                   exsltMathAsinFunction)
        && !xmlXPathRegisterFuncNS(ctxt,
                                   (const xmlChar *) "acos",
                                   (const xmlChar *) EXSLT_MATH_NAMESPACE,
                                   exsltMathAcosFunction)
        && !xmlXPathRegisterFuncNS(ctxt,
                                   (const xmlChar *) "atan",
                                   (const xmlChar *) EXSLT_MATH_NAMESPACE,
                                   exsltMathAtanFunction)
        && !xmlXPathRegisterFuncNS(ctxt,
                                   (const xmlChar *) "atan2",
                                   (const xmlChar *) EXSLT_MATH_NAMESPACE,
                                   exsltMathAtan2Function)
        && !xmlXPathRegisterFuncNS(ctxt,
                                   (const xmlChar *) "exp",
                                   (const xmlChar *) EXSLT_MATH_NAMESPACE,
                                   exsltMathExpFunction)
#endif
        && !xmlXPathRegisterFuncNS(ctxt,
                                   (const xmlChar *) "constant",
                                   (const xmlChar *) EXSLT_MATH_NAMESPACE,
                                   exsltMathConstantFunction)) {
        return 0;
    }
    return -1;
}

/* [<][>][^][v][top][bottom][index][help] */