[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

[xsl] XSLT for math computations (Was: Re: [xsl] when to use xslt)


Subject: [xsl] XSLT for math computations (Was: Re: [xsl] when to use xslt)
From: Dimtre Novatchev <dnovatchev@xxxxxxxxx>
Date: Sat, 15 Jan 2005 13:21:22 +1100

> But Mark made the distinction, that it is not useful to use
> XSLT for rather complex computations, in his example
> calculating prime numbers. Though as a contrast, Dimitre
> posted an example, where XSLT is used for a rather complex
> computation, which runs fast and successful. So the question
> whether XSLT should be used for mathematical problems or
> stuff like this is not fully clear yet. (For me, at least :))

Fundamentally wrong and incorrect question !

Not only one shouldn't be forbidden to use whatever tool they
themselves have selected.

The prime number problem is not at all an isolated example.

FXSL provides pure XSLT implementation of some most fundamental math
function groups such as:

  - exponential/logarithmic: exp(), ln(). log(), log2(), log10(),
sqrt(), pow(), ... etc.

  - trigonometric: sin(), cos(), tan(), cot(), secans(), cosecans()

  - inverse-trigonometric: the above with the prefix "arc"

  - Hyperbolic-trigonometric: the trigonometric fns with the prefix "h"

  - Finding the root of any equation of the form f(x) = 0, where f()
is a continuos function of one real argument -- using the
Newton-Raphston method and the binary search method.

  - Random number generator functions that produce a sequence of
random numbers in a given interval and/or with a given distribution

  - some statistical functions

  - etc.

See this at:

   http://fxsl.sourceforge.net/articles/xslCalculator/The%20FXSL%20Calculator.html
and
   http://fxsl.sourceforge.net/articles/Random/Casting%20the%20Dice%20with%20FXSL-htm.htm


The other, factual reason is that using XSLT for math computations is
simple, compact, elegant and fun.

For example, to get the sequence:

N^10, N = 1 to 10

one simply writes this one-line expression:

             f:map(f:flip(f:pow(),10), 1 to 10)

To get the sum of the tenth powers of all numbers from 1 to 10, one
writes this one-liner:

     sum(f:map(f:flip(f:pow(),10), 1 to 10))


To get the tenth root of the above, this one-liner is used:

   f:pow(sum(f:map(f:flip(f:pow(),10), 1 to 10)), 0.1)


Here's the full result of a transformation. The expressions to the
left of the "=" sign are the XPath expressions that are actually used
in the transformation:



f:pow(2,5) = 32.000000498873234
-----------------------------------------------
f:flip(f:pow(), 2, 5) = 25.000000210097642
-----------------------------------------------
f:map(f:flip(f:pow(),2), 1 to 10) = 
1
4.00000002487061
8.999999997225032
16.0000000654391
25.000000210097642
36.00000008032039
49.00000001473974
64.00000003117357
81.00000012870524
99.99999981533682
-----------------------------------------------
f:map(f:flip(f:pow(),10), 1 to 10) = 
1
1024.000031977348
59048.99991721205
1.0485760215547918E6
9.765625412399698E6
6.046617668837886E7
2.8247524947463E8
1.0737418267311203E9
3.486784428898773E9
9.999999907930431E9
-----------------------------------------------
sum(f:map(f:flip(f:pow(),10), 1 to 10)) = 
1.4914341865157238E10
-----------------------------------------------
f:pow(sum(f:map(f:flip(f:pow(),10), 1 to 10)), 0.1) = 
10.407835264401298
-----------------------------------------------
f:log(2,4) = 0.5000000015112621
-----------------------------------------------
f:flip(f:log(), 2, 4) = 1.9999999939549515
-----------------------------------------------
f:map(f:flip(f:log(),2), 2 to 10) = 
1
1.584962493378093
1.9999999939549515
2.321928090518739
2.58496249071745
2.807354909651913
2.9999999868509244
3.169924988315051
3.3219280785926495

The time it took to produce these results on my PC was: 469 milliseconds

The results are self-explanatory and it is very easy to learn how to
compose arbitrary expressions using the basic math functions and
operators of FXSL and XPath 2.0.

The combining "glue" is functional composition and using
currying/partial application.

Note also, that as of present all (most important) XPath 2.0 functions
and operators can be used as higher-order functions, by using a
convenient FXSL wrapper with the same name.

For example, to produce the sequence:

   2*N, N = 1 to 10

the following XPath expression can be used:

   f:map(f:mult(2), 1 to 10)


In this expression f:mult() is(a wrapper of) the op:numeric-multiply
operator as defined in

      http://www.w3.org/TR/xpath-functions/#func-numeric-multiply

f:mult(2) is the partial application of f:mult() with 2 as the first
argument. It is itself a function that takes one argument and returns
it multiplied by 2.

FXSL provides such wrappers for all (most important) XPath 2.0
functions and operators.

One final example. The following one-liner returns a sequence of
numeric values approximating sqrt(2) with precision ranging from 0 to
13 digits after the decimal point:

    f:map(f:round-half-to-even(f:sqrt(2, 0.000001)), 0 to 13)

and the result is:

1
1.4
1.41
1.414
1.4142
1.41421
1.414214
1.4142136
1.41421356
1.414213562
1.4142135624
1.41421356237
1.414213562375
1.4142135623747


Hope this post makes it possible to be more clear about the usefulness
of XSLT in math computations. It should certainly dispell the myth of
XSLT being "slow" in these.


Cheers,

Dimitre Novatchev


> Fittingly, Michael emphasized in his post, that the
> argument, XSLT is slow, is not accurate for straightforward
> transformations any more, often the time for parsing the
> input and serializing the output is neglected.


Current Thread
Keywords