package abstrasy.libraries.math;
import abstrasy.Bivalence;
import abstrasy.Node;
import abstrasy.SELF;
import abstrasy.externals.AExtCachable;
import abstrasy.externals.AExtClonable;
import abstrasy.externals.AExtTools;
import abstrasy.interpreter.InterpreterException;
import abstrasy.interpreter.ORef;
import abstrasy.interpreter.StdErrors;
import abstrasy.libraries.math.rjm.BigDecimalMath;
import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
/**
* Abstrasy Interpreter
*
* Copyright : Copyright (c) 2006-2012, Luc Bruninx.
*
* Concédée sous licence EUPL, version 1.1 uniquement (la «Licence»).
*
* Vous ne pouvez utiliser la présente oeuvre que conformément à la Licence.
* Vous pouvez obtenir une copie de la Licence à l’adresse suivante:
*
* http://www.osor.eu/eupl
*
* Sauf obligation légale ou contractuelle écrite, le logiciel distribué sous
* la Licence est distribué "en l’état", SANS GARANTIES OU CONDITIONS QUELLES
* QU’ELLES SOIENT, expresses ou implicites.
*
* Consultez la Licence pour les autorisations et les restrictions
* linguistiques spécifiques relevant de la Licence.
*
*
* @author Luc Bruninx
* @version 1.0
*/
public class External_Context extends AExtTools implements AExtClonable,
AExtCachable {
public External_Context() {
}
/*
* Configuration de base : 34/ROUND_HALF_EVEN (IEEE 754R Decimal128).
* =====================
*
* Attention, malgré la conformité du contexte initial, la précision augmente dynamiquement pour
* préserver la partie entière des nombres. Sur ce point, le contexte n'est pas compatible avec
* l'IEEE 754E Decimal128.
*
*/
static final private int DEFAULT_PRECISION = 34;
static final private int DEFAULT_ROUND = BigDecimal.ROUND_HALF_EVEN;
static final private MathContext DEFAULT_CONTEXT = new MathContext(DEFAULT_PRECISION, RoundingMode.valueOf(DEFAULT_ROUND));
static MathContext context = DEFAULT_CONTEXT;
/*
* Constantes exportées...
*/
public static Node external_RMODE_CEILING() {
return new Node(BigDecimal.ROUND_CEILING);
}
public static Node external_RMODE_FLOOR() {
return new Node(BigDecimal.ROUND_FLOOR);
}
public static Node external_RMODE_HALF_UP() {
return new Node(BigDecimal.ROUND_HALF_UP);
}
public static Node external_RMODE_HALF_DOWN() {
return new Node(BigDecimal.ROUND_HALF_DOWN);
}
public static Node external_RMODE_HALF_EVEN() {
return new Node(BigDecimal.ROUND_HALF_EVEN);
}
public static Node external_RMODE_UP() {
return new Node(BigDecimal.ROUND_UP);
}
public static Node external_RMODE_DOWN() {
return new Node(BigDecimal.ROUND_DOWN);
}
/**
* méthode interne: détermine le code RMODE selon l'objet RoundingMode.
* @param rm le RoundingMode.
* @return int le code de RMODE de BigDecimal.
* @throws InterpreterException
*/
public static int RMODEof(RoundingMode rm) throws InterpreterException {
if (rm == RoundingMode.CEILING)
return BigDecimal.ROUND_CEILING;
if (rm == RoundingMode.FLOOR)
return BigDecimal.ROUND_FLOOR;
if (rm == RoundingMode.HALF_UP)
return BigDecimal.ROUND_HALF_UP;
if (rm == RoundingMode.HALF_DOWN)
return BigDecimal.ROUND_HALF_DOWN;
if (rm == RoundingMode.HALF_EVEN)
return BigDecimal.ROUND_HALF_EVEN;
if (rm == RoundingMode.UP)
return BigDecimal.ROUND_UP;
if (rm == RoundingMode.DOWN)
return BigDecimal.ROUND_DOWN;
throw new InterpreterException(StdErrors.Internal_error);
}
//-------------------------------------------------------------------------
public Node external_mutator_set_default_precision(Node startAt) throws Exception {
startAt.isGoodArgsCnt(2);
SELF.require_SELF_mutable();
context = new MathContext((int) startAt.getSubNode(1, Node.TYPE_NUMBER).getNumber(), context.getRoundingMode());
return null;
}
public Node external_get_default_precision(Node startAt) throws Exception {
startAt.isGoodArgsCnt(1);
return new Node(context.getPrecision());
}
public Node external_mutator_reset_default_precision(Node startAt) throws Exception {
startAt.isGoodArgsCnt(1);
SELF.require_SELF_mutable();
context = new MathContext(DEFAULT_PRECISION, context.getRoundingMode());
;
return null;
}
//--------------------------------------------------------------------------
public Node external_mutator_set_default_RMODE(Node startAt) throws Exception {
startAt.isGoodArgsCnt(2);
SELF.require_SELF_mutable();
context = new MathContext(context.getPrecision(), RoundingMode.valueOf((int) startAt.getSubNode(1, Node.TYPE_NUMBER).getNumber()));
return null;
}
public Node external_get_default_RMODE(Node startAt) throws Exception {
startAt.isGoodArgsCnt(1);
return new Node(RMODEof(context.getRoundingMode()));
}
public Node external_mutator_reset_default_RMODE(Node startAt) throws Exception {
startAt.isGoodArgsCnt(1);
SELF.require_SELF_mutable();
context = new MathContext(context.getPrecision(), RoundingMode.valueOf(DEFAULT_ROUND));
return null;
}
//
//---------------------------------------------------------------------------
//
/**
* Retourne la valeur de la constante NAPIER (E) avec éventuellement une précision explicite.
*
* (:napier) -> E avec la précision par défaut
* (:napier n) -> E avec la précision de n décimales.
*
* @param startAt
* @return Node:Decimal
* @throws Exception
*/
public Node external_napier(Node startAt) throws Exception {
switch (startAt.size()) {
case 1:
return Node.createExternal(new External_Decimal(BigDecimalMath.exp(context), context));
case 2:
MathContext nmc = new MathContext((int) startAt.getSubNode(1, Node.TYPE_NUMBER).getNumber(), context.getRoundingMode());
return Node.createExternal(new External_Decimal(BigDecimalMath.exp(nmc), nmc));
default:
startAt.isGoodArgsCnt(1, 2);
}
return null;
}
/**
* Retourne la valeur de la constante PI avec éventuellement une précision explicite.
*
* (:pi) -> PI avec la précision par défaut
* (:pi n) -> PI avec la précision de n décimales.
*
* @param startAt
* @return Node:Decimal
* @throws Exception
*/
public Node external_pi(Node startAt) throws Exception {
switch (startAt.size()) {
case 1:
return Node.createExternal(new External_Decimal(BigDecimalMath.pi(context), context));
case 2:
MathContext nmc = new MathContext((int) startAt.getSubNode(1, Node.TYPE_NUMBER).getNumber(), context.getRoundingMode());
return Node.createExternal(new External_Decimal(BigDecimalMath.pi(nmc), nmc));
default:
startAt.isGoodArgsCnt(1, 2);
}
return null;
}
/**
* Retourne la valeur de la constante EULER (Gamma) avec éventuellement une précision explicite.
*
* (:euler) -> Gamma avec la précision par défaut
* (:euler n) -> Gamma avec la précision de n décimales.
*
* @param startAt
* @return Node:Decimal
* @throws Exception
*/
public Node external_euler(Node startAt) throws Exception {
switch (startAt.size()) {
case 1:
return Node.createExternal(new External_Decimal(BigDecimalMath.exp(context), context));
case 2:
MathContext nmc = new MathContext((int) startAt.getSubNode(1, Node.TYPE_NUMBER).getNumber(), context.getRoundingMode());
return Node.createExternal(new External_Decimal(BigDecimalMath.gamma(nmc), nmc));
default:
startAt.isGoodArgsCnt(1, 2);
}
return null;
}
//
//-----------------------------------------------------------------------------
//
@Override
public Object clone_my_self(Bivalence bival) {
return this; //singleton
}
/*
* ----------------------------------------------------------------------------
*
* Optimisation par cache d'instanciantion (mars 2012) rev 1.0-6321.0
*
* ----------------------------------------------------------------------------
*/
private static ORef _optim_symbols_cache_ = new ORef();
@Override
public Object getSymbolsCache() {
return _optim_symbols_cache_.getRef();
}
@Override
public void setSymbolsCache(Object cache) {
_optim_symbols_cache_.setRef(cache);
}
}