/// special functions coded for Yacas by Serge Winitzki: Gamma, Zeta, Bernoulli, LambertW

/// coded by Jonathan Leto: PolyLog, Dirichlet*, Digamma, Bessel*, Erf*, Fresnel*, Beta,
///			    CatalanConstNum, Sinc, Beta, DawsonIntegral

/////////////////////////////////////////////////
/// Euler's Gamma function
/////////////////////////////////////////////////

/// User visible functions: Gamma(x), LnGamma(x)

5 # Gamma(Infinity)	<-- Infinity;

10 # Gamma(_n)_(IsInteger(n) And n<=0) <-- Infinity;
10 # LnGamma(_n)_(IsInteger(n) And n<=0) <-- Infinity;

20 # Gamma(n_IsRationalOrNumber)_(IsPositiveInteger(n) Or FloatIsInt(2*n)) <-- (Round(2*n)/2-1)!;
20 # LnGamma(n_IsRationalOrNumber)_(IsPositiveInteger(n) Or FloatIsInt(2*n)) <-- Ln((Round(2*n)/2-1)!);

30 # Gamma(x_IsConstant)_(InNumericMode()) <-- Internal'GammaNum(N(Eval(x)));
30 # LnGamma(x_IsConstant)_(InNumericMode()) <-- Internal'LnGammaNum(N(Eval(x)));

/////////////////////////////////////////////////
/// Riemann's Zeta function
/////////////////////////////////////////////////

/// identities for exact values of Zeta

10 # Zeta(1) <-- Infinity;
10 # Zeta(0) <-- -1/2;	// let's save time
10 # Zeta(3)_InNumericMode() <-- Zeta3();	// special case
10 # Zeta(n_IsEven)_(n>0) <-- Pi^n*(2^(n-1)/n! *Abs(Bernoulli(n)));
10 # Zeta(n_IsInteger)_(n<0) <-- -Bernoulli(-n+1)/(-n+1);
11 # Zeta(n_IsInfinity) <-- 1;

/// compute numeric value
20 # Zeta(s_IsConstant)_(InNumericMode()) <-- Internal'ZetaNum(N(Eval(s)));

/////////////////////////////////////////////////
/// Bernoulli numbers and polynomials
/////////////////////////////////////////////////

/// Bernoulli(n): interface to Bernoulli numbers
10 # Bernoulli(0) <-- 1;
10 # Bernoulli(1) <-- -1/2;
15 # Bernoulli(n_IsInteger)_(n<0) <-- Undefined;
30 # Bernoulli(n_IsOdd) <-- 0;

/// numerical computations of Bernulli numbers use two different methods, one good for small numbers and one good only for very large numbers (using Zeta function)
20 # Bernoulli(n_IsEven)_(n<=Bernoulli1Threshold()) <-- Internal'BernoulliArray(n)[n+1];
20 # Bernoulli(n_IsEven)_(n>Bernoulli1Threshold()) <-- Bernoulli1(n);

LocalSymbols(bernoulli1Threshold) [
  /// Bernoulli1Threshold could in principle be set by the user
  If(Not IsBound(bernoulli1Threshold), bernoulli1Threshold := 20);

  Bernoulli1Threshold() := bernoulli1Threshold;
  SetBernoulli1Threshold(threshold) := [ bernoulli1Threshold := threshold;];

] ; // LocalSymbols(bernoulli1Threshold)

/// Bernoulli polynomials of degree n in variable x
Bernoulli(n_IsInteger, _x) <-- [
	Local(B, i, result);
	B := Internal'BernoulliArray(n);
	result := B[1];
	For(i:=n-1, i>=0, i--) [
		result := result * x + B[n-i+1]*Bin(n,i);
	];
	result;
];

/////////////////////////////////////////////////
/// Bessel and related functions
/////////////////////////////////////////////////

10 # BesselJ(0,0) 	<-- 1;
10 # BesselI(0,0)	<-- 1;
10 # BesselJ(_n,0)_(n>0) <-- 0;
10 # BesselI(_n,0)_(n>0) <-- 0;
10 # BesselJ(_n,0)_(n<0 And IsInteger(n)) <-- 0;
10 # BesselI(_n,0)_(n<0 And IsInteger(n)) <-- 0;
10 # BesselJ(_n,0)_(n<0 And Not IsInteger(n)) <-- Infinity;

// The following should be ComplexInfinity, if/when that is implemented
10 # BesselI(_n,0)_(n<0 And Not IsInteger(n)) <-- Infinity;

10 # BesselJ(0,Infinity)<-- 0;
20 # BesselJ(1/2,_x)	<-- Sqrt(2/(x*Pi))*Sin(x);
20 # BesselI(1/2,_x)	<-- Sqrt(2/(x*Pi))*Sinh(x);
20 # BesselJ(-1/2,_x)	<-- Sqrt(2/(x*Pi))*Cos(x);
20 # BesselJ(3/2,_x)	<-- Sqrt(2/(x*Pi))*(Sin(x)/x - Cos(x));

20 # BesselI(3/2,_x)    <-- Sqrt(2/(x*Pi))*(Cosh(x) - Sinh(x)/x);

20 # BesselJ(-3/2,_x)	<-- Sqrt(2/(x*Pi))*(Cos(x)/x + Sin(x));

20 # BesselJ(5/2,_x)	<-- Sqrt(2/(x*Pi))*((3/x^2 - 1)*Sin(x) - 3*Cos(x)/x );
20 # BesselI(5/2,_x)    <-- Sqrt(2/(x*Pi))*((3/x^2 + 1)*Sinh(x) - 3*Cosh(x)/x );

20 # BesselJ(-5/2,_x)      <-- Sqrt(2/(x*Pi))*( (3/x^2 -1)*Cos(x) + 3*Sin(x)/x );


// Forward recursion, works great, but really slow when n << x
30 # BesselJ(_n,_x)_(IsConstant(x) And IsInteger(n) And N(Abs(x) > 2*Gamma(n))) <-- N((2*(n+1)/x)*BesselJ(n+1,x) - BesselJ(n+2,x));

30 # BesselJ(_n,_z)_(n<0 And IsInteger(n) ) <-- (-1)^n*BesselJ(-n,z);
30 # BesselI(_n,_z)_(n<0 And IsInteger(n) ) <-- BesselI(-n,z);


// When I put "And InNumericMode()" on the next rule, I lose precision. Why ?
// Also, if I move the the "_IsComplex" to the end with "IsComplex(x)" 
// I lose precision.

//40 # BesselJ(_n,x_IsComplex)_(Abs(x)<= 2*Gamma(n) )  <-- N(BesselNsmall(n,x,0));
//40 # BesselI(_n,x_IsComplex)_(Abs(x)<= 2*Gamma(n) )  <-- N(BesselNsmall(n,x,1));
40 # BesselJ(_n,x_IsComplex)_(N(Abs(x)<= 2*Gamma(n)) )  <-- 
[
ApproxInfSum((-1)^k*(x/2)^(2*k+c[1])/(k! * Gamma(k+c[1]+1) ),0,x,{n} );
];

40 # BesselI(_n,x_IsComplex)_(IsConstant(x) And Abs(x)<= 2*Gamma(n) )  <--
[
ApproxInfSum((x/2)^(2*k+c[1])/(k! * Gamma(k+c[1]+1) ),0,x,{n} );
];


// This is buggy
40 # BesselY(_n,x_IsComplex)_(Abs(x)<= 2*Gamma(n) )  <-- N((Cos(n*Pi)*BesselJ(n,x) - BesselJ(-n,x))/Sin(Pi*n));

50 # BesselJ(0,x_IsComplex)_(InNumericMode()) <-- N(BesselJN0(x));

//50 # BesselJ(_n_IsPositiveNumber,_z_IsComplex) <-- BesselJN(n,z);


// Ex:
// Bessel of order n:
// ApproxInfSum((-1)^k*(x/2)^(2*k+c[1])/(k! * Gamma(k+c[1]+1) ),1,x,{n} );

Function("ApproxInfSum",{expr,start,x})[
	ApproxInfSum(expr,start,x,{0});
];

/// FIXME this has a roundoff problem when InNumericMode()=True
// Summation must be on k
Function("ApproxInfSum",{expr,start,x,c})
[
        Local(term,result,k);
        Local(prec,eps,tmp);
        prec:=Builtin'Precision'Get();
//        Builtin'Precision'Set(Ceil(1.2*prec)); // this is a guess
        Builtin'Precision'Set(prec+2); // this is a guess
//        eps:=5*10^(-prec);
        eps:=10^(-prec);
//Echo(expr);
//Echo("     eps = ",N(Eval(eps)));

        term:=1;
        k:=start;
        result:=0;
        While( N(Abs(term) >= eps) )[
                term:=N(Eval(expr));
		//Echo({"term is ",term});
                k:=k+1;
		result:=result+term;

        ];
		If(InVerboseMode(), Echo("ApproxInfSum: Info: using ", k, " terms of the series"));
        Builtin'Precision'Set(prec);
        // This should not round, only truncate
        // some outputs will be off by one in the last digit

//Echo("lastterm = ",N(Eval(term)));

//Echo("r1",result);
//Echo("r2",RoundTo(result,prec));
//Echo("r3",N((result/10)*10));

  result;
];

/////////////////////////////////////////////////
/// Error and complementary error functions
/////////////////////////////////////////////////

10 # Erf(0)		<-- 0;
//10 # Erfc(0)		<-- 1;
10 # Erf(Infinity)	<-- 1;
10 # Erf(Undefined) <-- Undefined;
//10 # Erfc(Infinity)	<-- 0;
10 # Erf(x_IsNumber)_(x<0)	<-- -Erf(-x);
//40 # Erf(x_IsNumber)_(Abs(x) <= 1 )  <-- N(2/Sqrt(Pi)*ApproxInfSum((-1)^k*x^(2*k+1)/((2*k+1)*k!),0,x));

LocalSymbols(k)
[
	40 # Erf(_x)_(InNumericMode() And (IsNumber(x) Or IsComplex(x)) And Abs(x) <= 1) <-- 
[
  Local(prec);
  prec := Builtin'Precision'Get(); // N(...) modifies the precision
  2 / MathSqrt(Internal'Pi()) * x 
	* SumTaylorNum(x^2, 1, {{k}, -(2*k-1)/(2*k+1)/k},
	// the number of terms n must satisfy n*Ln(n/Exp(1))>10^prec 
//	Hold({{k}, [Echo(k); k;]}) @
		N(1+87/32*Exp(LambertW(prec*421/497)), 20)
	);

];

];	// LocalSymbols(k)

// asymptotic expansion, can be used only for low enough precision or large enough |x| (see predicates). Also works for complex x.
LocalSymbols(n'max, k)
[

	50 # Erf(_x)_(InNumericMode() And (IsNumber(x) Or IsComplex(x))
		And (
			[	// strongest condition: the exp(-x^2) asymptotic is already good
				n'max := 0;
				Re(x^2) > Builtin'Precision'Get()*3295/1431+0.121;
			]
			Or
			[	// next condition: the exp(-x^2) helps but we need a few terms of the series too
				n'max := N(Min((Builtin'Precision'Get()*3295/1431+0.121)/Internal'LnNum(Abs(x)), 2*Internal'LnNum(Abs(x))), 10);
				2*Abs(x)+Re(x^2) > Builtin'Precision'Get()*3295/1431+0.121;
			]
			Or
			[	// worst case: exp(-x^2) does not help and we need the full series
	// hack: save a value computed in the predicate to use in the body of rule
				n'max := N(({{k}, k+Internal'LnNum(k)} @ Builtin'Precision'Get()*3295/1431)/2 - 3/2, 10);
				Abs(x) > n'max+3/2;
			]
		)
	) <-- If(Re(x)!=0, Sign(Re(x)), 0) - Exp(-x^2)/x/MathSqrt(Internal'Pi())
	// the series is 1 - 1/2/x^2 + 1*3/2^2/x^4 - 1*3*5/2^3/x^6 + ...
	* SumTaylorNum(1/x^2, 1, {{k}, -(2*k-1)/2 }, Max(0, Floor(n'max)));

];	// LocalSymbols(n'max, k)

10 # Erfc(_x)		<-- 1 - Erf(x);
10 # Erfi(_x)		<-- -I*Erf(x*I);

/////////////////////////////////////////////////
/// Fresnel integrals
/////////////////////////////////////////////////

10 # FresnelSin(0)		<-- 0;
10 # FresnelSin(Infinity)	<-- 1/2;
10 # FresnelSin(x_IsNumber)_(x<0)	<-- -FresnelSin(x);
10 # FresnelCos(0)              <-- 0;
10 # FresnelCos(Infinity)       <-- 1/2;
10 # FresnelCos(x_IsNumber)_(x<0)       <-- -FresnelCos(x);

40 # FresnelSin(x_IsNumber)_(Abs(x) <= 1) <-- N(Sqrt(2/Pi)*ApproxInfSum((-1)^(k+1)*x^(2*k+1)/(k! * (2*k+1)),1,x));
40 # FresnelCos(x_IsNumber)_(Abs(x) <= 1) <-- N(Sqrt(2/Pi)*ApproxInfSum((-1)^(k+1)*x^(4*k-3)/((4*k-3) * (2*k-2)! ),1,x));

/////////////////////////////////////////////////
/// Lambert's $W$ function.
/////////////////////////////////////////////////

10 # LambertW(0) <-- 0;
10 # LambertW(Infinity) <-- Infinity;
10 # LambertW(Undefined) <-- Undefined;
10 # LambertW(-Infinity) <-- Infinity + I*Pi;
10 # LambertW(-Exp(-1)) <-- -1;
20 # LambertW(_x * Ln(_x)) <-- Ln(x);
20 # LambertW(Ln(_x) * _x) <-- Ln(x);

30 # LambertW(x_IsConstant) _ InNumericMode() <-- Internal'LambertWNum(Eval(x));

/* {Internal'LambertWNum} computes a numeric approximation of Lambert's $W$ function
to the current precision. It uses a Halley iteration
$$ W'=W-(W-x*Exp(-W))/(W+1-(W+2)/(W+1)*(W-x*Exp(-W))/2) $$.
The function has real values for real $x >= -Exp(-1)$. (This point is a logarithmic branching point.)
*/
10 # Internal'LambertWNum(x_IsNumber)_(x < -MathExp(-1)) <-- Undefined;
20 # Internal'LambertWNum(x_IsNumber) <--
[
	Local(W);
	NewtonNum(
	  `Hold(
	  {
	  {W},
	  [
	  	Local(a);
		a:=W- @x*MathExp(-W);
		W-a/(W+1-(W+2)/(W+1)*a/2.);
	  ]}),
	// initial approximation is the two-point global Pade:
	  If(
		x<0,
		x*MathExp(1) / (1+1 / (1 / MathSqrt(2*(x*MathExp(1)+1)) - 1 / MathSqrt(2) + 1/(MathExp(1)-1))),
		Internal'LnNum(1+x)*(1-Internal'LnNum(1+Internal'LnNum(1+x))/(2+Internal'LnNum(1+x)))
	  ),
	  10,	// initial approximation is good to about 3 digits
	  3	// 3rd order scheme
	);
];

10 # Beta(_n,_m)	<-- Gamma(m)*Gamma(n)/Gamma(m+n);
10 # DirichletEta(_z)	<-- (1-2/2^z)*Zeta(z);
10 # DirichletLambda(_z)<-- (1-1/2^z)*Zeta(z);
10 # Sinc(_x)		<-- If(x=0,1,Sin(x)/x);


////// Polylogarithm Function
// Note: currently, the numerics are only working for x \in [-1,1]

10 # PolyLog(_n,0)		<-- 0;
// this is nicer than -Ln(1/2)
10 # PolyLog(1,1/2)             <-- Ln(2);
10 # PolyLog(_n,1)		<-- Zeta(n);
10 # PolyLog(_n,_m)_(m= -1)	<-- DirichletEta(n);
10 # PolyLog(_n,_x)_(n< 0)	<-- (1/((1-x)^(-n+1)))*Sum(i,0,-n,Eulerian(-n,i)*x^(-n-i) );
//10 # PolyLog(_n,_x)_(n= -3)	<-- x*(x^2 + 4*x + 1)/(x-1)^4;
//10 # PolyLog(_n,_x)_(n= -2)	<-- x*(x+1)/(1-x)^3;
//10 # PolyLog(_n,_x)_(n= -1)	<-- x/(1-x)^2;
10 # PolyLog(0,_x)		<-- x/(1-x);
10 # PolyLog(1,_x)		<-- -Ln(1-x);
// special values
10 # PolyLog(2,1/2)		<-- (Pi^2 - 6*Ln(2)^2)/12;
10 # PolyLog(3,1/2)		<-- (4*Ln(2)^3 - 2*Pi^2*Ln(2)+21*Zeta(3))/24;
10 # PolyLog(2,2)		<-- Pi^2/4 - Pi*I*Ln(2);

20 # PolyLog(_n,_x)_(InNumericMode() And  x < -1 )  <-- [
	Local(prec,result);
	prec:=Builtin'Precision'Get();
	Builtin'Precision'Set(prec+5);
	Echo("Warning: PolyLog is only currently accurate for x in [-1,1]");
	result:= (-1)^(n-1)*PolyLog(n,1/x) - ((Ln(-x))^n)/n! - 
	Sum(r,1,Round(n/2), 
		2^(2*r-2)*Pi^(2*r)*Abs(Bernoulli(2*r))*Ln(-x)^(n-2*r)/( (2*r)! * (n - 2*r)! ) );
	Builtin'Precision'Set(prec);
	RoundTo(N(result),prec);
];
20 # PolyLog(_n,_x)_(InNumericMode() And x>= -1 And x < 0 ) <-- [
	// this makes the domain [-1,0) into [0,1],
	// so if the summation representation is used, it is monotone
        Local(prec,result);
        prec:=Builtin'Precision'Get();
        Builtin'Precision'Set(prec+5);

	result:=PolyLog(n,x^2)/2^(n-1) - PolyLog(n,-x) ;	
        Builtin'Precision'Set(prec);
        RoundTo(N(result),prec);

];
/* this is very slow at high precision
20 # PolyLog(_n,_x)_(InNumericMode() And x > 0 And x <= 1) <-- [
	Local(result,prec,term,k,eps);
	prec:=Builtin'Precision'Get();
  Builtin'Precision'Set(prec+5);
	eps:=10^(-prec);
	result:=0;
	// Sorry Serge, I was only getting 2 digits of precision with this
		// so why didn't you ask me? :) -- Serge
	//terms:=Floor(10 + N(prec*Ln(10)/Ln(prec) - 1));
	//Builtin'Precision'Set( prec + Floor(N(Ln(6*terms)/Ln(10))) );
	//result:=SumTaylorNum(x, {{k}, x^(k+1)/(k+1)^n }, terms );
	term:=1;
	For(k:=1,Abs(term)>eps,k++)[
		term:=N(x^k/k^n);
		result:=result+term;
	];
	Builtin'Precision'Set(prec);
	RoundTo(result,prec);
];
*/

20 # PolyLog(_n,_x)_(InNumericMode() And x > 0 And x < 1) <--
[	// use Taylor series x^(k+1)/(k+1)^n, converges for -1<x<1
	Local(prec, result, terms);
	prec:=Builtin'Precision'Get();
	Builtin'Precision'Set(15);	// to calculate the number of terms
	terms := Floor(-prec*Ln(10)/Ln(x));
	terms := Floor(-(prec*Ln(10)-(n-1)*Ln(terms))/Ln(x));
//	Echo("used", terms, "terms");
	If(terms < 4, terms := 4);
	Builtin'Precision'Set(prec+2*IntLog(prec,10)+5);
	result := x*SumTaylorNum(x, {{k}, 1/(k+1)^n}, terms);
	Builtin'Precision'Set(prec);
	RoundTo(result, prec);
];

// This is really slow for x <= 3
5  # DirichletBeta(1)		<-- Pi/4;
5  # DirichletBeta(2)		<-- Catalan;
5  # DirichletBeta(3)		<-- Pi^3/32;
6  # DirichletBeta(n_IsOdd)	<-- [
		Local(k);
		k:=(n-1)/2;
		(-1)^k*Euler(2*k)*(Pi/2)^(2*k+1)/(2*(2*k)!);
];


10 # DirichletBeta(x_IsRationalOrNumber)_(InNumericMode() And x>=1 ) <-- [
	Local(prec,eps,term,result,k);
	prec:=Builtin'Precision'Get();
  Builtin'Precision'Set(prec+3);
	eps:=10^(-prec);
	result:=0;
	term:=1;
	For(k:=0, Abs(term) > eps, k++ )[
		term:=(-1)^k/(2*k+1)^x;
		Echo("term is ",term);
		result:=result+term;
	];
	Builtin'Precision'Set(prec);
	RoundTo(result,prec);
];

/////////////////////////////////////////////////
/// Catalan's constant, various algorithms for comparison. (SW)
/////////////////////////////////////////////////

/* Brent-Fee's method based on Ramanujan's identity and Brent's trick.
 * Geometric convergence as 2^(-n). */
CatalanConstNum1() := 
[
  Local(prec,Aterm,Bterm,nterms,result,n);
  prec:=Builtin'Precision'Get();
	Builtin'Precision'Set(10);
	// estimate the number of terms from above
	nterms := 1+Floor(N((prec*Ln(10)+Ln(prec*Ln(10)/Ln(2)))/Ln(2)));
  Builtin'Precision'Set(prec+5);
	Aterm:=N(1/2);
  result:= Aterm;
  Bterm:=Aterm;
  For(n:=1, n<=nterms, n++ )
	[
/*
    Bterm := MultiplyNum(Bterm, n/(2*n+1));
    Aterm:= MathDivide(MultiplyNum(Aterm,n)+Bterm, 2*n+1);
/* this is faster: */
    Bterm:=MathDivide(MathMultiply(Bterm,n), 2*n+1); // Bterm = (k!)^2*2^(k-1)/(2*k+1)!
    Aterm:=MathDivide(MathMultiply(Aterm,n)+Bterm, 2*n+1); // Aterm = Bterm * Sum(k,0,n,1/(2*k+1))
/**/
    result := result + Aterm;
  ];
  Builtin'Precision'Set(prec);
  RoundTo(result,prec);	
];

/* Bailey 1997's method.
 * Geometric convergence as 4^(-n). */

CatalanConstNum() :=
[
	Local(prec, n, result);
	prec:=Builtin'Precision'Get();

	// number of terms
	n := 1+Div(prec*1068+642,643); // prec*Ln(10)/Ln(4)
	Builtin'Precision'Set(prec+2);	// 2 guard digits
	
	result := N(1/(2*n+1));
	While(n>0)
	[
/*
		result := MultiplyNum(result, n/(4*n+2))+N(1/(2*n-1));
/* this is faster: */
		result := MathDivide(MathMultiply(result, n), 4*n+2)+MathDivide(1,2*n-1);
/**/
		n := n-1;
	];
	result := MultiplyNum(result, 3/8) + N(Pi/8*Ln(2+Sqrt(3)));
	Builtin'Precision'Set(prec);
	RoundTo(result,prec);
];

/* Broadhurst's series.
 * Geometric convergence as 16^(-n). */

CatalanConstNum2() :=
[
	Local(prec, n, result1, result2);
	prec:=Builtin'Precision'Get();

	// first series
	// number of terms
	n := 1+Div(prec*534+642,643); // prec*Ln(10)/Ln(16)
	Builtin'Precision'Set(prec+2);	// 2 guard digits
	
	result1 := 0;
	While(n>=0)
	[
		result1 := MathDivide(result1, 16)+N(
			+1/(8*n+1)^2 -1/(8*n+2)^2 +1/2/(8*n+3)^2 -1/4/(8*n+5)^2 +1/4/(8*n+6)^2 -1/8/(8*n+7)^2 
		);
		n := n-1;
	];

	// second series
	// number of terms
	n := 1+Div(prec*178+642,643); // prec*Ln(10)/Ln(4096)
	Builtin'Precision'Set(prec+2);	// 2 guard digits
	
	result2 := 0;
	While(n>=0)
	[
		result2 := MathDivide(result2, 4096)+N(
			+1/(8*n+1)^2 +1/2/(8*n+2)^2 +1/8/(8*n+3)^2 -1/64/(8*n+5)^2 -1/128/(8*n+6)^2 -1/512/(8*n+7)^2 
		);
		n := n-1;
	];
	result1 := MultiplyNum(result1, 3/2) - MultiplyNum(result2, 1/4);
	Builtin'Precision'Set(prec);
	RoundTo(result1,prec);
];



10 # Digamma(_n)_(IsPositiveInteger(n)) <-- Sum(m,1,n-1,1/m) - gamma;
// needs Erf() that takes complex argument
/*
10 # DawsonIntegral(_x) <-- [
	Local(result,prec);
	prec:=Builtin'Precision'Get();
	Builtin'Precision'Set(prec+5);
	result:=N(I*Sqrt(Pi)*Exp(-x^2)*Erf(-I*x)/2);
	Builtin'Precision'Set(prec);
	RoundTo(result,prec);
];
*/
		
