- add sources.
[platform/framework/web/crosswalk.git] / src / third_party / libxslt / libexslt / math.c
1 #define IN_LIBEXSLT
2 #include "libexslt/libexslt.h"
3
4 #if defined(WIN32) && !defined (__CYGWIN__) && (!__MINGW32__)
5 #include <win32config.h>
6 #else
7 #include "config.h"
8 #endif
9
10 #include <libxml/tree.h>
11 #include <libxml/xpath.h>
12 #include <libxml/xpathInternals.h>
13
14 #include <libxslt/xsltconfig.h>
15 #include <libxslt/xsltutils.h>
16 #include <libxslt/xsltInternals.h>
17 #include <libxslt/extensions.h>
18
19 #ifdef HAVE_MATH_H
20 #include <math.h>
21 #endif
22
23 #ifdef HAVE_STDLIB_H
24 #include <stdlib.h>
25 #endif
26
27 #include "exslt.h"
28
29 /**
30  * exsltMathMin:
31  * @ns:  a node-set
32  *
33  * Implements the EXSLT - Math min() function:
34  *    number math:min (node-set)
35  *
36  * Returns the minimum value of the nodes passed as the argument, or
37  *         xmlXPathNAN if @ns is NULL or empty or if one of the nodes
38  *         turns into NaN.
39  */
40 static double
41 exsltMathMin (xmlNodeSetPtr ns) {
42     double ret, cur;
43     int i;
44
45     if ((ns == NULL) || (ns->nodeNr == 0))
46         return(xmlXPathNAN);
47     ret = xmlXPathCastNodeToNumber(ns->nodeTab[0]);
48     if (xmlXPathIsNaN(ret))
49         return(xmlXPathNAN);
50     for (i = 1; i < ns->nodeNr; i++) {
51         cur = xmlXPathCastNodeToNumber(ns->nodeTab[i]);
52         if (xmlXPathIsNaN(cur))
53             return(xmlXPathNAN);
54         if (cur < ret)
55             ret = cur;
56     }
57     return(ret);
58 }
59
60 /**
61  * exsltMathMinFunction:
62  * @ctxt:  an XPath parser context
63  * @nargs:  the number of arguments
64  *
65  * Wraps #exsltMathMin for use by the XPath processor.
66  */
67 static void
68 exsltMathMinFunction (xmlXPathParserContextPtr ctxt, int nargs) {
69     xmlNodeSetPtr ns;
70     double ret;
71     void *user = NULL;
72
73     if (nargs != 1) {
74         xsltGenericError(xsltGenericErrorContext,
75                          "math:min: invalid number of arguments\n");
76         ctxt->error = XPATH_INVALID_ARITY;
77         return;
78     }
79     /* We need to delay the freeing of value->user */
80     if ((ctxt->value != NULL) && (ctxt->value->boolval != 0)) {
81         user = ctxt->value->user;
82         ctxt->value->boolval = 0;
83         ctxt->value->user = NULL;
84     }
85     ns = xmlXPathPopNodeSet(ctxt);
86     if (xmlXPathCheckError(ctxt))
87         return;
88
89     ret = exsltMathMin(ns);
90
91     xmlXPathFreeNodeSet(ns);
92     if (user != NULL)
93         xmlFreeNodeList((xmlNodePtr)user);
94
95     xmlXPathReturnNumber(ctxt, ret);
96 }
97
98 /**
99  * exsltMathMax:
100  * @ns:  a node-set
101  *
102  * Implements the EXSLT - Math max() function:
103  *    number math:max (node-set)
104  *
105  * Returns the maximum value of the nodes passed as arguments, or
106  *         xmlXPathNAN if @ns is NULL or empty or if one of the nodes
107  *         turns into NaN.
108  */
109 static double
110 exsltMathMax (xmlNodeSetPtr ns) {
111     double ret, cur;
112     int i;
113
114     if ((ns == NULL) || (ns->nodeNr == 0))
115         return(xmlXPathNAN);
116     ret = xmlXPathCastNodeToNumber(ns->nodeTab[0]);
117     if (xmlXPathIsNaN(ret))
118         return(xmlXPathNAN);
119     for (i = 1; i < ns->nodeNr; i++) {
120         cur = xmlXPathCastNodeToNumber(ns->nodeTab[i]);
121         if (xmlXPathIsNaN(cur))
122             return(xmlXPathNAN);
123         if (cur > ret)
124             ret = cur;
125     }
126     return(ret);
127 }
128
129 /**
130  * exsltMathMaxFunction:
131  * @ctxt:  an XPath parser context
132  * @nargs:  the number of arguments
133  *
134  * Wraps #exsltMathMax for use by the XPath processor.
135  */
136 static void
137 exsltMathMaxFunction (xmlXPathParserContextPtr ctxt, int nargs) {
138     xmlNodeSetPtr ns;
139     double ret;
140     void *user = NULL;
141
142     if (nargs != 1) {
143         xmlXPathSetArityError(ctxt);
144         return;
145     }
146
147     /* We need to delay the freeing of value->user */
148     if ((ctxt->value != NULL) && (ctxt->value->boolval != 0)) {
149         user = ctxt->value->user;
150         ctxt->value->boolval = 0;
151         ctxt->value->user = 0;
152     }
153     ns = xmlXPathPopNodeSet(ctxt);
154     if (xmlXPathCheckError(ctxt))
155         return;
156
157     ret = exsltMathMax(ns);
158
159     xmlXPathFreeNodeSet(ns);
160
161     if (user != NULL)
162         xmlFreeNodeList((xmlNodePtr)user);
163     xmlXPathReturnNumber(ctxt, ret);
164 }
165
166 /**
167  * exsltMathHighest:
168  * @ns:  a node-set
169  *
170  * Implements the EXSLT - Math highest() function:
171  *    node-set math:highest (node-set)
172  *
173  * Returns the nodes in the node-set whose value is the maximum value
174  *         for the node-set.
175  */
176 static xmlNodeSetPtr
177 exsltMathHighest (xmlNodeSetPtr ns) {
178     xmlNodeSetPtr ret = xmlXPathNodeSetCreate(NULL);
179     double max, cur;
180     int i;
181
182     if ((ns == NULL) || (ns->nodeNr == 0))
183         return(ret);
184
185     max = xmlXPathCastNodeToNumber(ns->nodeTab[0]);
186     if (xmlXPathIsNaN(max))
187         return(ret);
188     else
189         xmlXPathNodeSetAddUnique(ret, ns->nodeTab[0]);
190
191     for (i = 1; i < ns->nodeNr; i++) {
192         cur = xmlXPathCastNodeToNumber(ns->nodeTab[i]);
193         if (xmlXPathIsNaN(cur)) {
194             xmlXPathEmptyNodeSet(ret);
195             return(ret);
196         }
197         if (cur < max)
198             continue;
199         if (cur > max) {
200             max = cur;
201             xmlXPathEmptyNodeSet(ret);
202             xmlXPathNodeSetAddUnique(ret, ns->nodeTab[i]);
203             continue;
204         }
205         xmlXPathNodeSetAddUnique(ret, ns->nodeTab[i]);
206     }
207     return(ret);
208 }
209
210 /**
211  * exsltMathHighestFunction:
212  * @ctxt:  an XPath parser context
213  * @nargs:  the number of arguments
214  *
215  * Wraps #exsltMathHighest for use by the XPath processor
216  */
217 static void
218 exsltMathHighestFunction (xmlXPathParserContextPtr ctxt, int nargs) {
219     xmlNodeSetPtr ns, ret;
220     void *user = NULL;
221
222     if (nargs != 1) {
223         xmlXPathSetArityError(ctxt);
224         return;
225     }
226
227     /* We need to delay the freeing of value->user */
228     if ((ctxt->value != NULL) && ctxt->value->boolval != 0) {
229         user = ctxt->value->user;
230         ctxt->value->boolval = 0;
231         ctxt->value->user = NULL;
232     }
233     ns = xmlXPathPopNodeSet(ctxt);
234     if (xmlXPathCheckError(ctxt))
235         return;
236
237     ret = exsltMathHighest(ns);
238
239     xmlXPathFreeNodeSet(ns);
240     if (user != NULL)
241         xmlFreeNodeList((xmlNodePtr)user);
242
243     xmlXPathReturnNodeSet(ctxt, ret);
244 }
245
246 /**
247  * exsltMathLowest:
248  * @ns:  a node-set
249  *
250  * Implements the EXSLT - Math lowest() function
251  *    node-set math:lowest (node-set)
252  *
253  * Returns the nodes in the node-set whose value is the minimum value
254  *         for the node-set.
255  */
256 static xmlNodeSetPtr
257 exsltMathLowest (xmlNodeSetPtr ns) {
258     xmlNodeSetPtr ret = xmlXPathNodeSetCreate(NULL);
259     double min, cur;
260     int i;
261
262     if ((ns == NULL) || (ns->nodeNr == 0))
263         return(ret);
264
265     min = xmlXPathCastNodeToNumber(ns->nodeTab[0]);
266     if (xmlXPathIsNaN(min))
267         return(ret);
268     else
269         xmlXPathNodeSetAddUnique(ret, ns->nodeTab[0]);
270
271     for (i = 1; i < ns->nodeNr; i++) {
272         cur = xmlXPathCastNodeToNumber(ns->nodeTab[i]);
273         if (xmlXPathIsNaN(cur)) {
274             xmlXPathEmptyNodeSet(ret);
275             return(ret);
276         }
277         if (cur > min)
278             continue;
279         if (cur < min) {
280             min = cur;
281             xmlXPathEmptyNodeSet(ret);
282             xmlXPathNodeSetAddUnique(ret, ns->nodeTab[i]);
283             continue;
284         }
285         xmlXPathNodeSetAddUnique(ret, ns->nodeTab[i]);
286     }
287     return(ret);
288 }
289
290 /**
291  * exsltMathLowestFunction:
292  * @ctxt:  an XPath parser context
293  * @nargs:  the number of arguments
294  *
295  * Wraps #exsltMathLowest for use by the XPath processor
296  */
297 static void
298 exsltMathLowestFunction (xmlXPathParserContextPtr ctxt, int nargs) {
299     xmlNodeSetPtr ns, ret;
300     void *user = NULL;
301     
302
303     if (nargs != 1) {
304         xmlXPathSetArityError(ctxt);
305         return;
306     }
307
308     /* We need to delay the freeing of value->user */
309     if ((ctxt->value != NULL) && (ctxt->value->boolval != 0)) {
310         user = ctxt->value->user;
311         ctxt->value->boolval = 0;
312         ctxt->value->user = NULL;
313     }
314     ns = xmlXPathPopNodeSet(ctxt);
315     if (xmlXPathCheckError(ctxt))
316         return;
317
318     ret = exsltMathLowest(ns);
319
320     xmlXPathFreeNodeSet(ns);
321     if (user != NULL)
322         xmlFreeNodeList((xmlNodePtr)user);
323
324     xmlXPathReturnNodeSet(ctxt, ret);
325 }
326
327 /* math other functions */
328
329 /* constant values */
330 #define EXSLT_PI        (const xmlChar *) \
331                         "3.1415926535897932384626433832795028841971693993751"
332 #define EXSLT_E         (const xmlChar *) \
333                         "2.71828182845904523536028747135266249775724709369996"
334 #define EXSLT_SQRRT2    (const xmlChar *) \
335                         "1.41421356237309504880168872420969807856967187537694"
336 #define EXSLT_LN2       (const xmlChar *) \
337                         "0.69314718055994530941723212145817656807550013436025"
338 #define EXSLT_LN10      (const xmlChar *) \
339                         "2.30258509299404568402"
340 #define EXSLT_LOG2E     (const xmlChar *) \
341                         "1.4426950408889634074"
342 #define EXSLT_SQRT1_2   (const xmlChar *) \
343                         "0.70710678118654752440"
344
345 /**
346  * exsltMathConstant
347  * @name: string
348  * @precision:  number
349  *
350  * Implements the EXSLT - Math constant function:
351  *     number math:constant(string, number)
352  *
353  * Returns a number value of the given constant with the given precision or
354  * xmlXPathNAN if name is unknown.
355  * The constants are PI, E, SQRRT2, LN2, LN10, LOG2E, and SQRT1_2
356  */
357 static double
358 exsltMathConstant (xmlChar *name, double precision) {
359     xmlChar *str;
360     double ret;
361
362     if ((name == NULL) || (xmlXPathIsNaN(precision)) || (precision < 1.0)) {
363         return xmlXPathNAN;
364     }
365
366     if (xmlStrEqual(name, BAD_CAST "PI")) {
367         int len = xmlStrlen(EXSLT_PI);
368
369         if (precision <= len)
370             len = (int)precision;
371         
372         str = xmlStrsub(EXSLT_PI, 0, len);
373
374     } else if (xmlStrEqual(name, BAD_CAST "E")) {
375         int len = xmlStrlen(EXSLT_E);
376
377         if (precision <= len)
378             len = (int)precision;
379         
380         str = xmlStrsub(EXSLT_E, 0, len);
381
382     } else if (xmlStrEqual(name, BAD_CAST "SQRRT2")) {
383         int len = xmlStrlen(EXSLT_SQRRT2);
384
385         if (precision <= len)
386             len = (int)precision;
387         
388         str = xmlStrsub(EXSLT_SQRRT2, 0, len);
389
390     } else if (xmlStrEqual(name, BAD_CAST "LN2")) {
391         int len = xmlStrlen(EXSLT_LN2);
392
393         if (precision <= len)
394             len = (int)precision;
395         
396         str = xmlStrsub(EXSLT_LN2, 0, len);
397
398     } else if (xmlStrEqual(name, BAD_CAST "LN10")) {
399         int len = xmlStrlen(EXSLT_LN10);
400
401         if (precision <= len)
402             len = (int)precision;
403         
404         str = xmlStrsub(EXSLT_LN10, 0, len);
405
406     } else if (xmlStrEqual(name, BAD_CAST "LOG2E")) {
407         int len = xmlStrlen(EXSLT_LOG2E);
408
409         if (precision <= len)
410             len = (int)precision;
411         
412         str = xmlStrsub(EXSLT_LOG2E, 0, len);
413
414     } else if (xmlStrEqual(name, BAD_CAST "SQRT1_2")) {
415         int len = xmlStrlen(EXSLT_SQRT1_2);
416
417         if (precision <= len)
418             len = (int)precision;
419         
420         str = xmlStrsub(EXSLT_SQRT1_2, 0, len);
421
422     } else {
423         str = NULL;
424     }
425     if (str == NULL)
426         return xmlXPathNAN;
427     ret = xmlXPathCastStringToNumber(str);
428     xmlFree(str);
429     return ret;
430 }
431
432 /**
433  * exsltMathConstantFunction:
434  * @ctxt:  an XPath parser context
435  * @nargs:  the number of arguments
436  *
437  * Wraps #exsltMathConstant for use by the XPath processor.
438  */
439 static void
440 exsltMathConstantFunction (xmlXPathParserContextPtr ctxt, int nargs) {
441     double   ret;
442     xmlChar *name;
443
444     if (nargs != 2) {
445         xmlXPathSetArityError(ctxt);
446         return;
447     }
448     ret = xmlXPathPopNumber(ctxt);
449     if (xmlXPathCheckError(ctxt))
450         return;
451
452     name = xmlXPathPopString(ctxt);
453     if (xmlXPathCheckError(ctxt))
454         return;
455
456     ret = exsltMathConstant(name, ret);
457     if (name != NULL)
458         xmlFree(name);
459
460     xmlXPathReturnNumber(ctxt, ret);
461 }
462
463 #if defined(HAVE_STDLIB_H) && defined(RAND_MAX)
464
465 /**
466  * exsltMathRandom:
467  *
468  * Implements the EXSLT - Math random() function:
469  *    number math:random ()
470  *
471  * Returns a random number between 0 and 1 inclusive.
472  */
473 static double
474 exsltMathRandom (void) {
475     double ret;
476     int num;
477
478     num = rand();
479     ret = (double)num / (double)RAND_MAX;
480     return(ret);
481 }
482
483 /**
484  * exsltMathRandomFunction:
485  * @ctxt:  an XPath parser context
486  * @nargs:  the number of arguments
487  *
488  * Wraps #exsltMathRandom for use by the XPath processor.
489  */
490 static void
491 exsltMathRandomFunction (xmlXPathParserContextPtr ctxt, int nargs) {
492     double ret;
493
494     if (nargs != 0) {
495         xmlXPathSetArityError(ctxt);
496         return;
497     }
498
499     ret = exsltMathRandom();
500
501     xmlXPathReturnNumber(ctxt, ret);
502 }
503
504 #endif /* defined(HAVE_STDLIB_H) && defined(RAND_MAX) */
505
506 #if HAVE_MATH_H
507
508 /**
509  * exsltMathAbs:
510  * @num:  a double
511  *
512  * Implements the EXSLT - Math abs() function:
513  *    number math:abs (number)
514  *
515  * Returns the absolute value of the argument, or xmlXPathNAN if @num is Nan.
516  */
517 static double
518 exsltMathAbs (double num) {
519     double ret;
520
521     if (xmlXPathIsNaN(num))
522         return(xmlXPathNAN);
523     ret = fabs(num);
524     return(ret);
525 }
526
527 /**
528  * exsltMathAbsFunction:
529  * @ctxt:  an XPath parser context
530  * @nargs:  the number of arguments
531  *
532  * Wraps #exsltMathAbs for use by the XPath processor.
533  */
534 static void
535 exsltMathAbsFunction (xmlXPathParserContextPtr ctxt, int nargs) {
536     double ret;
537
538     if (nargs != 1) {
539         xmlXPathSetArityError(ctxt);
540         return;
541     }
542     ret = xmlXPathPopNumber(ctxt);
543     if (xmlXPathCheckError(ctxt))
544         return;
545
546     ret = exsltMathAbs(ret);
547
548     xmlXPathReturnNumber(ctxt, ret);
549 }
550
551 /**
552  * exsltMathSqrt:
553  * @num:  a double
554  *
555  * Implements the EXSLT - Math sqrt() function:
556  *    number math:sqrt (number)
557  *
558  * Returns the square root of the argument, or xmlXPathNAN if @num is Nan.
559  */
560 static double
561 exsltMathSqrt (double num) {
562     double ret;
563
564     if (xmlXPathIsNaN(num))
565         return(xmlXPathNAN);
566     ret = sqrt(num);
567     return(ret);
568 }
569
570 /**
571  * exsltMathSqrtFunction:
572  * @ctxt:  an XPath parser context
573  * @nargs:  the number of arguments
574  *
575  * Wraps #exsltMathSqrt for use by the XPath processor.
576  */
577 static void
578 exsltMathSqrtFunction (xmlXPathParserContextPtr ctxt, int nargs) {
579     double ret;
580
581     if (nargs != 1) {
582         xmlXPathSetArityError(ctxt);
583         return;
584     }
585     ret = xmlXPathPopNumber(ctxt);
586     if (xmlXPathCheckError(ctxt))
587         return;
588
589     ret = exsltMathSqrt(ret);
590
591     xmlXPathReturnNumber(ctxt, ret);
592 }
593
594 /**
595  * exsltMathPower:
596  * @base:  a double
597  * @power:  a double
598  *
599  * Implements the EXSLT - Math power() function:
600  *    number math:power (number, number)
601  *
602  * Returns the power base and power arguments, or xmlXPathNAN
603  * if either @base or @power is Nan.
604  */
605 static double
606 exsltMathPower (double base, double power) {
607     double ret;
608
609     if ((xmlXPathIsNaN(base) || xmlXPathIsNaN(power)))
610         return(xmlXPathNAN);
611     ret = pow(base, power);
612     return(ret);
613 }
614
615 /**
616  * exsltMathPower:
617  * @ctxt:  an XPath parser context
618  * @nargs:  the number of arguments
619  *
620  * Wraps #exsltMathPower for use by the XPath processor.
621  */
622 static void
623 exsltMathPowerFunction (xmlXPathParserContextPtr ctxt, int nargs) {
624     double ret, base;
625
626     if (nargs != 2) {
627         xmlXPathSetArityError(ctxt);
628         return;
629     }
630     ret = xmlXPathPopNumber(ctxt);
631     if (xmlXPathCheckError(ctxt))
632         return;
633
634     /* power */
635     base = xmlXPathPopNumber(ctxt);
636     if (xmlXPathCheckError(ctxt))
637         return;
638
639     ret = exsltMathPower(base, ret);
640
641     xmlXPathReturnNumber(ctxt, ret);
642 }
643
644 /**
645  * exsltMathLog:
646  * @num:  a double
647  *
648  * Implements the EXSLT - Math log() function:
649  *    number math:log (number)
650  *
651  * Returns the natural log of the argument, or xmlXPathNAN if @num is Nan.
652  */
653 static double
654 exsltMathLog (double num) {
655     double ret;
656
657     if (xmlXPathIsNaN(num))
658         return(xmlXPathNAN);
659     ret = log(num);
660     return(ret);
661 }
662
663 /**
664  * exsltMathLogFunction:
665  * @ctxt:  an XPath parser context
666  * @nargs:  the number of arguments
667  *
668  * Wraps #exsltMathLog for use by the XPath processor.
669  */
670 static void
671 exsltMathLogFunction (xmlXPathParserContextPtr ctxt, int nargs) {
672     double ret;
673
674     if (nargs != 1) {
675         xmlXPathSetArityError(ctxt);
676         return;
677     }
678     ret = xmlXPathPopNumber(ctxt);
679     if (xmlXPathCheckError(ctxt))
680         return;
681
682     ret = exsltMathLog(ret);
683
684     xmlXPathReturnNumber(ctxt, ret);
685 }
686
687 /**
688  * exsltMathSin:
689  * @num:  a double
690  *
691  * Implements the EXSLT - Math sin() function:
692  *    number math:sin (number)
693  *
694  * Returns the sine of the argument, or xmlXPathNAN if @num is Nan.
695  */
696 static double
697 exsltMathSin (double num) {
698     double ret;
699
700     if (xmlXPathIsNaN(num))
701         return(xmlXPathNAN);
702     ret = sin(num);
703     return(ret);
704 }
705
706 /**
707  * exsltMathSinFunction:
708  * @ctxt:  an XPath parser context
709  * @nargs:  the number of arguments
710  *
711  * Wraps #exsltMathSin for use by the XPath processor.
712  */
713 static void
714 exsltMathSinFunction (xmlXPathParserContextPtr ctxt, int nargs) {
715     double ret;
716
717     if (nargs != 1) {
718         xmlXPathSetArityError(ctxt);
719         return;
720     }
721     ret = xmlXPathPopNumber(ctxt);
722     if (xmlXPathCheckError(ctxt))
723         return;
724
725     ret = exsltMathSin(ret);
726
727     xmlXPathReturnNumber(ctxt, ret);
728 }
729
730 /**
731  * exsltMathCos:
732  * @num:  a double
733  *
734  * Implements the EXSLT - Math cos() function:
735  *    number math:cos (number)
736  *
737  * Returns the cosine of the argument, or xmlXPathNAN if @num is Nan.
738  */
739 static double
740 exsltMathCos (double num) {
741     double ret;
742
743     if (xmlXPathIsNaN(num))
744         return(xmlXPathNAN);
745     ret = cos(num);
746     return(ret);
747 }
748
749 /**
750  * exsltMathCosFunction:
751  * @ctxt:  an XPath parser context
752  * @nargs:  the number of arguments
753  *
754  * Wraps #exsltMathCos for use by the XPath processor.
755  */
756 static void
757 exsltMathCosFunction (xmlXPathParserContextPtr ctxt, int nargs) {
758     double ret;
759
760     if (nargs != 1) {
761         xmlXPathSetArityError(ctxt);
762         return;
763     }
764     ret = xmlXPathPopNumber(ctxt);
765     if (xmlXPathCheckError(ctxt))
766         return;
767
768     ret = exsltMathCos(ret);
769
770     xmlXPathReturnNumber(ctxt, ret);
771 }
772
773 /**
774  * exsltMathTan:
775  * @num:  a double
776  *
777  * Implements the EXSLT - Math tan() function:
778  *    number math:tan (number)
779  *
780  * Returns the tangent of the argument, or xmlXPathNAN if @num is Nan.
781  */
782 static double
783 exsltMathTan (double num) {
784     double ret;
785
786     if (xmlXPathIsNaN(num))
787         return(xmlXPathNAN);
788     ret = tan(num);
789     return(ret);
790 }
791
792 /**
793  * exsltMathTanFunction:
794  * @ctxt:  an XPath parser context
795  * @nargs:  the number of arguments
796  *
797  * Wraps #exsltMathTan for use by the XPath processor.
798  */
799 static void
800 exsltMathTanFunction (xmlXPathParserContextPtr ctxt, int nargs) {
801     double ret;
802
803     if (nargs != 1) {
804         xmlXPathSetArityError(ctxt);
805         return;
806     }
807     ret = xmlXPathPopNumber(ctxt);
808     if (xmlXPathCheckError(ctxt))
809         return;
810
811     ret = exsltMathTan(ret);
812
813     xmlXPathReturnNumber(ctxt, ret);
814 }
815
816 /**
817  * exsltMathAsin:
818  * @num:  a double
819  *
820  * Implements the EXSLT - Math asin() function:
821  *    number math:asin (number)
822  *
823  * Returns the arc sine of the argument, or xmlXPathNAN if @num is Nan.
824  */
825 static double
826 exsltMathAsin (double num) {
827     double ret;
828
829     if (xmlXPathIsNaN(num))
830         return(xmlXPathNAN);
831     ret = asin(num);
832     return(ret);
833 }
834
835 /**
836  * exsltMathAsinFunction:
837  * @ctxt:  an XPath parser context
838  * @nargs:  the number of arguments
839  *
840  * Wraps #exsltMathAsin for use by the XPath processor.
841  */
842 static void
843 exsltMathAsinFunction (xmlXPathParserContextPtr ctxt, int nargs) {
844     double ret;
845
846     if (nargs != 1) {
847         xmlXPathSetArityError(ctxt);
848         return;
849     }
850     ret = xmlXPathPopNumber(ctxt);
851     if (xmlXPathCheckError(ctxt))
852         return;
853
854     ret = exsltMathAsin(ret);
855
856     xmlXPathReturnNumber(ctxt, ret);
857 }
858
859 /**
860  * exsltMathAcos:
861  * @num:  a double
862  *
863  * Implements the EXSLT - Math acos() function:
864  *    number math:acos (number)
865  *
866  * Returns the arc cosine of the argument, or xmlXPathNAN if @num is Nan.
867  */
868 static double
869 exsltMathAcos (double num) {
870     double ret;
871
872     if (xmlXPathIsNaN(num))
873         return(xmlXPathNAN);
874     ret = acos(num);
875     return(ret);
876 }
877
878 /**
879  * exsltMathAcosFunction:
880  * @ctxt:  an XPath parser context
881  * @nargs:  the number of arguments
882  *
883  * Wraps #exsltMathAcos for use by the XPath processor.
884  */
885 static void
886 exsltMathAcosFunction (xmlXPathParserContextPtr ctxt, int nargs) {
887     double ret;
888
889     if (nargs != 1) {
890         xmlXPathSetArityError(ctxt);
891         return;
892     }
893     ret = xmlXPathPopNumber(ctxt);
894     if (xmlXPathCheckError(ctxt))
895         return;
896
897     ret = exsltMathAcos(ret);
898
899     xmlXPathReturnNumber(ctxt, ret);
900 }
901
902 /**
903  * exsltMathAtan:
904  * @num:  a double
905  *
906  * Implements the EXSLT - Math atan() function:
907  *    number math:atan (number)
908  *
909  * Returns the arc tangent of the argument, or xmlXPathNAN if @num is Nan.
910  */
911 static double
912 exsltMathAtan (double num) {
913     double ret;
914
915     if (xmlXPathIsNaN(num))
916         return(xmlXPathNAN);
917     ret = atan(num);
918     return(ret);
919 }
920
921 /**
922  * exsltMathAtanFunction:
923  * @ctxt:  an XPath parser context
924  * @nargs:  the number of arguments
925  *
926  * Wraps #exsltMathAtan for use by the XPath processor.
927  */
928 static void
929 exsltMathAtanFunction (xmlXPathParserContextPtr ctxt, int nargs) {
930     double ret;
931
932     if (nargs != 1) {
933         xmlXPathSetArityError(ctxt);
934         return;
935     }
936     ret = xmlXPathPopNumber(ctxt);
937     if (xmlXPathCheckError(ctxt))
938         return;
939
940     ret = exsltMathAtan(ret);
941
942     xmlXPathReturnNumber(ctxt, ret);
943 }
944
945 /**
946  * exsltMathAtan2:
947  * @y:  a double
948  * @x:  a double
949  *
950  * Implements the EXSLT - Math atan2() function:
951  *    number math:atan2 (number, number)
952  *
953  * Returns the arc tangent function of the y/x arguments, or xmlXPathNAN
954  * if either @y or @x is Nan.
955  */
956 static double
957 exsltMathAtan2 (double y, double x) {
958     double ret;
959
960     if ((xmlXPathIsNaN(y) || xmlXPathIsNaN(x)))
961         return(xmlXPathNAN);
962     ret = atan2(y, x);
963     return(ret);
964 }
965
966 /**
967  * exsltMathAtan2Function:
968  * @ctxt:  an XPath parser context
969  * @nargs:  the number of arguments
970  *
971  * Wraps #exsltMathAtan2 for use by the XPath processor.
972  */
973 static void
974 exsltMathAtan2Function (xmlXPathParserContextPtr ctxt, int nargs) {
975     double ret, x;
976
977     if (nargs != 2) {
978         xmlXPathSetArityError(ctxt);
979         return;
980     }
981     x = xmlXPathPopNumber(ctxt);
982     if (xmlXPathCheckError(ctxt))
983         return;
984
985     /* y */
986     ret = xmlXPathPopNumber(ctxt);
987     if (xmlXPathCheckError(ctxt))
988         return;
989
990     ret = exsltMathAtan2(ret, x);
991
992     xmlXPathReturnNumber(ctxt, ret);
993 }
994
995 /**
996  * exsltMathExp:
997  * @num:  a double
998  *
999  * Implements the EXSLT - Math exp() function:
1000  *    number math:exp (number)
1001  *
1002  * Returns the exponential function of the argument, or xmlXPathNAN if
1003  * @num is Nan.
1004  */
1005 static double
1006 exsltMathExp (double num) {
1007     double ret;
1008
1009     if (xmlXPathIsNaN(num))
1010         return(xmlXPathNAN);
1011     ret = exp(num);
1012     return(ret);
1013 }
1014
1015 /**
1016  * exsltMathExpFunction:
1017  * @ctxt:  an XPath parser context
1018  * @nargs:  the number of arguments
1019  *
1020  * Wraps #exsltMathExp for use by the XPath processor.
1021  */
1022 static void
1023 exsltMathExpFunction (xmlXPathParserContextPtr ctxt, int nargs) {
1024     double ret;
1025
1026     if (nargs != 1) {
1027         xmlXPathSetArityError(ctxt);
1028         return;
1029     }
1030     ret = xmlXPathPopNumber(ctxt);
1031     if (xmlXPathCheckError(ctxt))
1032         return;
1033
1034     ret = exsltMathExp(ret);
1035
1036     xmlXPathReturnNumber(ctxt, ret);
1037 }
1038
1039 #endif /* HAVE_MATH_H */
1040
1041 /**
1042  * exsltMathRegister:
1043  *
1044  * Registers the EXSLT - Math module
1045  */
1046
1047 void
1048 exsltMathRegister (void) {
1049     xsltRegisterExtModuleFunction ((const xmlChar *) "min",
1050                                    EXSLT_MATH_NAMESPACE,
1051                                    exsltMathMinFunction);
1052     xsltRegisterExtModuleFunction ((const xmlChar *) "max",
1053                                    EXSLT_MATH_NAMESPACE,
1054                                    exsltMathMaxFunction);
1055     xsltRegisterExtModuleFunction ((const xmlChar *) "highest",
1056                                    EXSLT_MATH_NAMESPACE,
1057                                    exsltMathHighestFunction);
1058     xsltRegisterExtModuleFunction ((const xmlChar *) "lowest",
1059                                    EXSLT_MATH_NAMESPACE,
1060                                    exsltMathLowestFunction);
1061     /* register other math functions */
1062     xsltRegisterExtModuleFunction ((const xmlChar *) "constant",
1063                                    EXSLT_MATH_NAMESPACE,
1064                                    exsltMathConstantFunction);
1065 #ifdef HAVE_STDLIB_H
1066     xsltRegisterExtModuleFunction ((const xmlChar *) "random",
1067                                    EXSLT_MATH_NAMESPACE,
1068                                    exsltMathRandomFunction);
1069 #endif
1070 #if HAVE_MATH_H
1071     xsltRegisterExtModuleFunction ((const xmlChar *) "abs",
1072                                    EXSLT_MATH_NAMESPACE,
1073                                    exsltMathAbsFunction);
1074     xsltRegisterExtModuleFunction ((const xmlChar *) "sqrt",
1075                                    EXSLT_MATH_NAMESPACE,
1076                                    exsltMathSqrtFunction);
1077     xsltRegisterExtModuleFunction ((const xmlChar *) "power",
1078                                    EXSLT_MATH_NAMESPACE,
1079                                    exsltMathPowerFunction);
1080     xsltRegisterExtModuleFunction ((const xmlChar *) "log",
1081                                    EXSLT_MATH_NAMESPACE,
1082                                    exsltMathLogFunction);
1083     xsltRegisterExtModuleFunction ((const xmlChar *) "sin",
1084                                    EXSLT_MATH_NAMESPACE,
1085                                    exsltMathSinFunction);
1086     xsltRegisterExtModuleFunction ((const xmlChar *) "cos",
1087                                    EXSLT_MATH_NAMESPACE,
1088                                    exsltMathCosFunction);
1089     xsltRegisterExtModuleFunction ((const xmlChar *) "tan",
1090                                    EXSLT_MATH_NAMESPACE,
1091                                    exsltMathTanFunction);
1092     xsltRegisterExtModuleFunction ((const xmlChar *) "asin",
1093                                    EXSLT_MATH_NAMESPACE,
1094                                    exsltMathAsinFunction);
1095     xsltRegisterExtModuleFunction ((const xmlChar *) "acos",
1096                                    EXSLT_MATH_NAMESPACE,
1097                                    exsltMathAcosFunction);
1098     xsltRegisterExtModuleFunction ((const xmlChar *) "atan",
1099                                    EXSLT_MATH_NAMESPACE,
1100                                    exsltMathAtanFunction);
1101     xsltRegisterExtModuleFunction ((const xmlChar *) "atan2",
1102                                    EXSLT_MATH_NAMESPACE,
1103                                    exsltMathAtan2Function);
1104     xsltRegisterExtModuleFunction ((const xmlChar *) "exp",
1105                                    EXSLT_MATH_NAMESPACE,
1106                                    exsltMathExpFunction);
1107 #endif
1108 }
1109
1110 /**
1111  * exsltMathXpathCtxtRegister:
1112  *
1113  * Registers the EXSLT - Math module for use outside XSLT
1114  */
1115 int
1116 exsltMathXpathCtxtRegister (xmlXPathContextPtr ctxt, const xmlChar *prefix)
1117 {
1118     if (ctxt
1119         && prefix
1120         && !xmlXPathRegisterNs(ctxt,
1121                                prefix,
1122                                (const xmlChar *) EXSLT_MATH_NAMESPACE)
1123         && !xmlXPathRegisterFuncNS(ctxt,
1124                                    (const xmlChar *) "min",
1125                                    (const xmlChar *) EXSLT_MATH_NAMESPACE,
1126                                    exsltMathMinFunction)
1127         && !xmlXPathRegisterFuncNS(ctxt,
1128                                    (const xmlChar *) "max",
1129                                    (const xmlChar *) EXSLT_MATH_NAMESPACE,
1130                                    exsltMathMaxFunction)
1131         && !xmlXPathRegisterFuncNS(ctxt,
1132                                    (const xmlChar *) "highest",
1133                                    (const xmlChar *) EXSLT_MATH_NAMESPACE,
1134                                    exsltMathHighestFunction)
1135         && !xmlXPathRegisterFuncNS(ctxt,
1136                                    (const xmlChar *) "lowest",
1137                                    (const xmlChar *) EXSLT_MATH_NAMESPACE,
1138                                    exsltMathLowestFunction)
1139 #ifdef HAVE_STDLIB_H
1140         && !xmlXPathRegisterFuncNS(ctxt,
1141                                    (const xmlChar *) "random",
1142                                    (const xmlChar *) EXSLT_MATH_NAMESPACE,
1143                                    exsltMathRandomFunction)
1144 #endif
1145 #if HAVE_MATH_H
1146         && !xmlXPathRegisterFuncNS(ctxt,
1147                                    (const xmlChar *) "abs",
1148                                    (const xmlChar *) EXSLT_MATH_NAMESPACE,
1149                                    exsltMathAbsFunction)
1150         && !xmlXPathRegisterFuncNS(ctxt,
1151                                    (const xmlChar *) "sqrt",
1152                                    (const xmlChar *) EXSLT_MATH_NAMESPACE,
1153                                    exsltMathSqrtFunction)
1154         && !xmlXPathRegisterFuncNS(ctxt,
1155                                    (const xmlChar *) "power",
1156                                    (const xmlChar *) EXSLT_MATH_NAMESPACE,
1157                                    exsltMathPowerFunction)
1158         && !xmlXPathRegisterFuncNS(ctxt,
1159                                    (const xmlChar *) "log",
1160                                    (const xmlChar *) EXSLT_MATH_NAMESPACE,
1161                                    exsltMathLogFunction)
1162         && !xmlXPathRegisterFuncNS(ctxt,
1163                                    (const xmlChar *) "sin",
1164                                    (const xmlChar *) EXSLT_MATH_NAMESPACE,
1165                                    exsltMathSinFunction)
1166         && !xmlXPathRegisterFuncNS(ctxt,
1167                                    (const xmlChar *) "cos",
1168                                    (const xmlChar *) EXSLT_MATH_NAMESPACE,
1169                                    exsltMathCosFunction)
1170         && !xmlXPathRegisterFuncNS(ctxt,
1171                                    (const xmlChar *) "tan",
1172                                    (const xmlChar *) EXSLT_MATH_NAMESPACE,
1173                                    exsltMathTanFunction)
1174         && !xmlXPathRegisterFuncNS(ctxt,
1175                                    (const xmlChar *) "asin",
1176                                    (const xmlChar *) EXSLT_MATH_NAMESPACE,
1177                                    exsltMathAsinFunction)
1178         && !xmlXPathRegisterFuncNS(ctxt,
1179                                    (const xmlChar *) "acos",
1180                                    (const xmlChar *) EXSLT_MATH_NAMESPACE,
1181                                    exsltMathAcosFunction)
1182         && !xmlXPathRegisterFuncNS(ctxt,
1183                                    (const xmlChar *) "atan",
1184                                    (const xmlChar *) EXSLT_MATH_NAMESPACE,
1185                                    exsltMathAtanFunction)
1186         && !xmlXPathRegisterFuncNS(ctxt,
1187                                    (const xmlChar *) "atan2",
1188                                    (const xmlChar *) EXSLT_MATH_NAMESPACE,
1189                                    exsltMathAtan2Function)
1190         && !xmlXPathRegisterFuncNS(ctxt,
1191                                    (const xmlChar *) "exp",
1192                                    (const xmlChar *) EXSLT_MATH_NAMESPACE,
1193                                    exsltMathExpFunction)
1194 #endif
1195         && !xmlXPathRegisterFuncNS(ctxt,
1196                                    (const xmlChar *) "constant",
1197                                    (const xmlChar *) EXSLT_MATH_NAMESPACE,
1198                                    exsltMathConstantFunction)) {
1199         return 0;
1200     }
1201     return -1;
1202 }