Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* MIT License
*
* Copyright (c) 2002-2023 Mikko Tommila
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package org.apfloat;
import org.apfloat.ApfloatMath.ApfloatHolder;
/**
* Helper class for computing the Euler gamma using binary splitting and the Brent-McMillan formula.
*
* @since 1.11.0
* @version 1.11.0
* @author Mikko Tommila
*/
class EulerHelper
{
// See http://www.numberworld.org/y-cruncher/internals/binary-splitting-library.html#eulergamma_bm_ab
// See https://www.ginac.de/CLN/binsplit.pdf
private EulerHelper(Apfloat n2, long precision, int radix)
throws ApfloatRuntimeException
{
this.n2 = n2;
this.precision = precision;
this.radix = radix;
}
public static Apfloat euler(long precision, int radix)
throws ApfloatRuntimeException
{
ApfloatHolder Q = new ApfloatHolder(),
R = new ApfloatHolder(),
S = new ApfloatHolder(),
U = new ApfloatHolder();
long workingPrecision = ApfloatHelper.extendPrecision(precision),
n = ApfloatHelper.extendPrecision((long) (precision * Math.log(radix) / 4)),
terms = (long) (ALPHA * n);
Apfloat nn = new Apfloat(n, workingPrecision, radix),
n2 = nn.multiply(nn);
new EulerHelper(n2, workingPrecision, radix).euler(0, terms, null, Q, R, S, null, U, null);
return U.getApfloat().divide(Q.getApfloat().multiply(R.getApfloat().add(S.getApfloat()))).subtract(ApfloatMath.log(nn)).precision(precision);
}
private void euler(long a, long b, ApfloatHolder P, ApfloatHolder Q, ApfloatHolder R, ApfloatHolder S, ApfloatHolder T, ApfloatHolder U, ApfloatHolder V)
throws ApfloatRuntimeException
{
assert (a < b);
if (b - a == 1)
{
Apfloat bb = new Apfloat(b, this.precision, this.radix);
Apfloat b2 = bb.multiply(bb);
if (P != null)
{
P.setApfloat(new Apfloat(1, this.precision, this.radix));
}
Q.setApfloat(bb);
R.setApfloat(this.n2);
S.setApfloat(b2);
if (T != null)
{
T.setApfloat(this.n2);
}
U.setApfloat(this.n2);
if (V != null)
{
V.setApfloat(b2.multiply(bb));
}
}
else
{
long m = a + b >>> 1;
ApfloatHolder LP = new ApfloatHolder(),
LQ = new ApfloatHolder(),
LR = new ApfloatHolder(),
LS = new ApfloatHolder(),
LT = new ApfloatHolder(),
LU = new ApfloatHolder(),
LV = new ApfloatHolder(),
RP = new ApfloatHolder(),
RQ = new ApfloatHolder(),
RR = new ApfloatHolder(),
RS = new ApfloatHolder(),
RT = new ApfloatHolder(),
RU = new ApfloatHolder(),
RV = new ApfloatHolder();
euler(a, m, LP, LQ, LR, LS, LT, LU, V != null ? LV : null);
euler(m, b, P != null ? RP : null, RQ, RR, RS, T != null ? RT : null, RU, RV);
if (P != null)
{
P.setApfloat(LP.getApfloat().multiply(RQ.getApfloat()).add(LQ.getApfloat().multiply(RP.getApfloat())));
}
Q.setApfloat(LQ.getApfloat().multiply(RQ.getApfloat()));
R.setApfloat(LR.getApfloat().multiply(RS.getApfloat()).add(LT.getApfloat().multiply(RR.getApfloat())));
S.setApfloat(LS.getApfloat().multiply(RS.getApfloat()));
if (T != null)
{
T.setApfloat(LT.getApfloat().multiply(RT.getApfloat()));
}
U.setApfloat(LU.getApfloat().multiply(RV.getApfloat()).add(LP.getApfloat().multiply(LT.getApfloat()).multiply(RQ.getApfloat()).multiply(RR.getApfloat())).add(LQ.getApfloat().multiply(LT.getApfloat()).multiply(RU.getApfloat())));
if (V != null)
{
V.setApfloat(LV.getApfloat().multiply(RV.getApfloat()));
}
}
}
private static final double ALPHA = 3.5911214766686221; // 1 / W(1 / e)
private final Apfloat n2;
private final long precision;
private final int radix;
}