Coverage Report

Created: 2023-12-14 10:34

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