« 2011年8月 | トップページ | 2011年10月 »

2011年9月

JAVAを用いた多倍長ライブラリ

BigDecimalで多倍長計算するライブラリです。

package jp.wshounen;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.ArrayList;

public class BigMath {
	private int precision;
	private MathContext context;
	private BigDecimal pi;
	private BigDecimal e;

	public BigMath(int precision) {
		this.precision = precision;
		context = new MathContext((int) Math.ceil(precision * 1.125),
				RoundingMode.HALF_EVEN);
		pi = null;
		e = null;
	}

	public BigDecimal round(BigDecimal in) {
		return in.round(new MathContext(precision, RoundingMode.HALF_EVEN));
	}

	public BigDecimal floor(BigDecimal in) {
		BigDecimal[] bi = in.divideAndRemainder(BigDecimal.ONE);
		if (bi[1].signum() == -1) {
			return bi[0].add(BigDecimal.ONE.negate());
		} else {
			return bi[0];
		}
	}

	public BigDecimal ceil(BigDecimal in) {
		BigDecimal[] bi = in.divideAndRemainder(BigDecimal.ONE);
		if (bi[1].signum() == 1) {
			return bi[0].add(BigDecimal.ONE);
		} else {
			return bi[0];
		}
	}

	public BigDecimal pi() {
		if (pi == null) {
			pi = atan(BigDecimal.ONE).multiply(new BigDecimal(4), context);
		}
		return pi;
	}

	public BigDecimal e() {
		if (e == null) {
			e = exp(BigDecimal.ONE);
		}
		return e;
	}

	public MathContext context() {
		return context;
	}

	public int precision() {
		return precision;
	}

	public BigDecimal asin(BigDecimal in) {
		int num = in.abs().compareTo(BigDecimal.ONE);
		if (num == 0) {
			return pi().divide(new BigDecimal(in.signum() * 2), context);
		} else if (num == -1) {
			BigDecimal bi = atan(in.divide(
					root(in.pow(2).negate().add(BigDecimal.ONE), 2).add(
							BigDecimal.ONE), context));
			return bi.add(bi, context);
		} else if (round(in.abs()).compareTo(BigDecimal.ONE) == 0) {
			return pi().divide(new BigDecimal(in.signum() * 2), context);
		} else {
			return null;
		}
	}

	public BigDecimal acos(BigDecimal in) {
		if (in.round(context).compareTo(BigDecimal.ONE) == 0) {
			return BigDecimal.ZERO;
		}
		BigDecimal bi = asin(in);
		if (bi == null) {
			return bi;
		} else {
			return pi().divide(new BigDecimal(2), context).add(bi.negate(),
					context);
		}
	}

	public BigDecimal atan(BigDecimal in) {
		int num = in.signum();
		if (num == 0) {
			return BigDecimal.ZERO;
		}
		BigDecimal bi = in.abs().round(context);
		BigDecimal res = BigDecimal.ZERO;
		BigDecimal perfive = new BigDecimal("0.2");
		if (bi.compareTo(perfive) == 1) {
			BigDecimal perfiveat = atan(perfive);
			while (bi.signum() == 1) {
				bi = bi.add(perfive.negate()).divide(
						bi.multiply(perfive).add(BigDecimal.ONE), context);
				res = res.add(perfiveat);
			}
		}
		if (num == -1) {
			bi = bi.negate();
			res = res.negate();
		}
		BigDecimal coef = bi.round(context);
		ArrayList<BigDecimal> temp = new ArrayList<BigDecimal>(0);
		temp.add(coef.add(res, context));
		bi = bi.pow(2).negate();
		do {
			num = temp.size();
			coef = coef.multiply(bi, context);
			temp.add(temp.get(num - 1).add(
					coef.divide(new BigDecimal(2 * num + 1), context), context));
		} while (temp.get(num).compareTo(temp.get(num - 1)) != 0);
		return temp.get(num);
	}

	public BigDecimal root(BigDecimal in, int index) {
		int num = in.signum();
		if (num == 0) {
			return BigDecimal.ZERO;
		} else if (num == -1) {
			return null;
		} else if (index <= 0) {
			return null;
		} else if (in.compareTo(BigDecimal.ONE) == 0 || index == 1) {
			return in.round(context);
		}
		BigDecimal bi = in.round(context);
		int i = index * 1;
		int j;
		do {
			j = 2;
			while (i % j != 0 && i > j * j) {
				j++;
			}
			if (i == j * j) {
				j = i;
			} else if (i % j == 0) {
				i = i / j;
			} else {
				j = i;
			}
			if (j > 5) {
				bi = pow(bi, BigDecimal.ONE.divide(new BigDecimal(j), context));
			} else {
				ArrayList<BigDecimal> temp = new ArrayList<BigDecimal>(0);
				temp.add(bi);
				do {
					num = temp.size();
					temp.add(temp
							.get(num - 1)
							.pow(j)
							.multiply(new BigDecimal(j - 1))
							.add(bi)
							.divide(temp.get(num - 1).pow(j - 1)
									.multiply(new BigDecimal(j)), context));
				} while (temp.get(num).compareTo(temp.get(num - 1)) != 0);
				bi = temp.get(num);
			}
		} while (i > j);
		return bi;
	}

	public BigDecimal log(BigDecimal in) {
		if (in.signum() < 1) {
			return null;
		}
		int num = in.compareTo(BigDecimal.ONE);
		BigDecimal coef, bi, res;
		if (num == 0) {
			return BigDecimal.ZERO;
		} else if (num == -1) {
			bi = in.round(context);
			coef = BigDecimal.ONE.negate();
		} else {
			bi = BigDecimal.ONE.divide(in, context);
			coef = BigDecimal.ONE;
		}
		res = BigDecimal.ZERO;
		do {
			bi = bi.multiply(e(), context);
			res = res.add(BigDecimal.ONE);
		} while (bi.compareTo(BigDecimal.ONE) == -1);
		if (bi.pow(5).compareTo(e()) == 1) {
			bi = root(bi, 5);
			coef = coef.multiply(new BigDecimal(5));
		}
		if (num == -1) {
			res = res.negate();
		}
		bi = BigDecimal.ONE.negate().add(BigDecimal.ONE.divide(bi, context));
		coef = coef.multiply(bi, context);
		ArrayList<BigDecimal> temp = new ArrayList<BigDecimal>(0);
		temp.add(coef.add(res, context));
		bi = bi.negate();
		do {
			num = temp.size();
			coef = coef.multiply(bi, context);
			temp.add(temp.get(num - 1).add(
					coef.divide(new BigDecimal(num + 1), context), context));
		} while (temp.get(num).compareTo(temp.get(num - 1)) != 0);
		return temp.get(num);
	}

	public BigDecimal sin(BigDecimal in) {
		BigDecimal[] bi = in.divideAndRemainder(pi(), context);
		bi[1] = bi[1].divide(new BigDecimal(3), context);
		ArrayList<BigDecimal> temp = new ArrayList<BigDecimal>(0);
		if (bi[0].abs().remainder(new BigDecimal(2), context)
				.compareTo(BigDecimal.ONE) == 0) {
			temp.add(bi[1].negate(context));
		} else {
			temp.add(bi[1].round(context));
		}
		BigDecimal coef = temp.get(0);
		bi[1] = bi[1].pow(2);
		int num;
		do {
			num = temp.size();
			coef = coef.multiply(bi[1]).divide(
					new BigDecimal(-2 * num * (2 * num + 1)), context);
			temp.add(temp.get(num - 1).add(coef, context));
		} while (temp.get(num).compareTo(temp.get(num - 1)) != 0);
		bi[1] = temp.get(num).pow(3).negate().multiply(new BigDecimal(4))
				.add(temp.get(num).multiply(new BigDecimal(3)), context);
		num = bi[1].signum();
		return bi[1].add(new BigDecimal(-num), context).add(
				new BigDecimal(num), context);
	}

	public BigDecimal cos(BigDecimal in) {
		BigDecimal[] bi = in.divideAndRemainder(pi(), context);
		bi[1] = bi[1].divide(new BigDecimal(3), context).pow(2);
		ArrayList<BigDecimal> temp = new ArrayList<BigDecimal>(0);
		if (bi[0].abs().remainder(new BigDecimal(2), context)
				.compareTo(BigDecimal.ONE) == 0) {
			temp.add(BigDecimal.ONE.negate());
		} else {
			temp.add(BigDecimal.ONE);
		}
		BigDecimal coef = temp.get(0);
		int num;
		do {
			num = temp.size();
			coef = coef.multiply(bi[1]).divide(
					new BigDecimal(-2 * num * (2 * num - 1)), context);
			temp.add(temp.get(num - 1).add(coef, context));
		} while (temp.get(num).compareTo(temp.get(num - 1)) != 0);
		bi[1] = temp
				.get(num)
				.pow(3)
				.multiply(new BigDecimal(4))
				.add(temp.get(num).negate().multiply(new BigDecimal(3)),
						context);
		num = bi[1].signum();
		return bi[1].add(new BigDecimal(-num), context).add(
				new BigDecimal(num), context);
	}

	public BigDecimal tan(BigDecimal in) {
		BigDecimal bi = cos(in);
		if (bi.add(BigDecimal.ONE, context).compareTo(BigDecimal.ONE) == 0) {
			return null;
		} else {
			return sin(in).divide(bi, context);
		}
	}

	public BigDecimal exp(BigDecimal in) {
		int num = in.signum();
		BigDecimal coef = BigDecimal.ONE;
		BigDecimal bi;
		if (num == 0) {
			return BigDecimal.ONE;
		} else if (num == 1) {
			bi = in.negate(context);
		} else {
			bi = in.round(context);
		}
		if (in.abs().round(context).compareTo(BigDecimal.ONE) != 0) {
			while (bi.signum() == -1) {
				bi = bi.add(BigDecimal.ONE);
				coef = coef.multiply(e(), context);
			}
		}
		if (num == 1) {
			bi = bi.negate();
		} else {
			coef = BigDecimal.ONE.divide(coef, context);
		}
		ArrayList<BigDecimal> temp = new ArrayList<BigDecimal>(0);
		temp.add(coef.round(context));
		do {
			num = temp.size();
			coef = coef.multiply(bi).divide(new BigDecimal(num), context);
			temp.add(temp.get(num - 1).add(coef, context));
		} while (temp.get(num).compareTo(temp.get(num - 1)) != 0);
		return temp.get(num);
	}

	public BigDecimal pow(BigDecimal in, BigDecimal index) {
		BigDecimal bi = log(in);
		if (bi == null) {
			return null;
		} else {
			return exp(bi.multiply(index));
		}
	}
}

暦計算用の20桁精度の定数付きライブラリです。

package jp.wshounen;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.ArrayList;

public class DEMath {
	public final static MathContext context = new MathContext(24,
			RoundingMode.HALF_EVEN);
	public static final int precision = 20;
	public static final BigDecimal au = new BigDecimal(149597870691l)
			.scaleByPowerOfTen(-3);
	public static final BigDecimal emrat = new BigDecimal(8130056)
			.scaleByPowerOfTen(-5);
	public static final BigDecimal clight = new BigDecimal(2997922458l)
			.scaleByPowerOfTen(-4);
	public static final BigDecimal jultimeOfJ2000 = new BigDecimal(2451545);
	public static final BigDecimal equatorialRadius = new BigDecimal(6378137)
			.scaleByPowerOfTen(-3);
	public static final BigDecimal polarRadius = new BigDecimal(6356752)
			.scaleByPowerOfTen(-3);
	public static final BigDecimal solarRadius = new BigDecimal(695989245)
			.scaleByPowerOfTen(-3);
	public static final BigDecimal lunarRadius = new BigDecimal(17380908)
			.scaleByPowerOfTen(-4);
	public static final BigDecimal PI = atan(BigDecimal.ONE).multiply(
			new BigDecimal(4), context);
	public static final BigDecimal E = exp(BigDecimal.ONE);
	public static final BigDecimal[][] icrfRot = rotAB(
			rotAB(rotX(arcsecToRad(new BigDecimal(-68192).scaleByPowerOfTen(-7))),
					rotY(arcsecToRad(new BigDecimal(-166170)
							.scaleByPowerOfTen(-7)))),
			rotZ(arcsecToRad(new BigDecimal(146).scaleByPowerOfTen(-4))));
	public static final BigDecimal obliquityArcsecOfJ2000 = new BigDecimal(
			84381406).scaleByPowerOfTen(-3);

	public static BigDecimal round(final BigDecimal in, final int precision) {
		return in.round(new MathContext(precision, RoundingMode.HALF_EVEN));
	}

	public static long divideToFloor(final long value, final long divisor) {
		long remainder = value % divisor;
		return ((remainder < 0 && divisor > 0) || (remainder > 0 && divisor < 0)) ? (value - remainder)
				/ divisor - 1
				: (value - remainder) / divisor;
	}

	public static BigDecimal round(final BigDecimal in) {
		return in.setScale(0, RoundingMode.HALF_EVEN);
		// BigDecimal[] bi = in.divideAndRemainder(BigDecimal.ONE);
		// int num = bi[1].add(bi[1]).abs().compareTo(BigDecimal.ONE);
		// if (num == 1
		// || (num == 0 && bi[0].remainder(new BigDecimal(2)).signum() != 0)) {
		// return bi[0].add(new BigDecimal(bi[1].signum()));
		// } else {
		// return bi[0];
		// }
	}

	public static BigDecimal arcsecToRad(final BigDecimal arcsec) {
		return arcsec.multiply(PI).divide(new BigDecimal(648000), context);
	}

	public static BigDecimal radToArcsec(final BigDecimal rad) {
		return rad.multiply(new BigDecimal(648000)).divide(PI, context);
	}

	public static BigDecimal floor(final BigDecimal in) {
		return in.setScale(0, RoundingMode.FLOOR);
		// BigDecimal[] bi = in.divideAndRemainder(BigDecimal.ONE);
		// if (bi[1].signum() == -1) {
		// return bi[0].add(BigDecimal.ONE.negate());
		// } else {
		// return bi[0];
		// }
	}

	public static BigDecimal ceil(final BigDecimal in) {
		return in.setScale(0, RoundingMode.CEILING);
		// BigDecimal[] bi = in.divideAndRemainder(BigDecimal.ONE);
		// if (bi[1].signum() == 1) {
		// return bi[0].add(BigDecimal.ONE);
		// } else {
		// return bi[0];
		// }
	}

	public static BigDecimal asin(final BigDecimal in) {
		int num = in.abs().compareTo(BigDecimal.ONE);
		if (num == 0) {
			return PI.divide(new BigDecimal(in.signum() * 2), context);
		} else if (num == -1) {
			BigDecimal bi = atan(in.divide(
					root(in.pow(2).negate().add(BigDecimal.ONE), 2).add(
							BigDecimal.ONE), context));
			return bi.add(bi, context);
		} else if (round(in.abs(), 20).compareTo(BigDecimal.ONE) == 0) {
			return PI.divide(new BigDecimal(in.signum() * 2), context);
		} else {
			return null;
		}
	}

	public static BigDecimal acos(final BigDecimal in) {
		if (in.round(context).compareTo(BigDecimal.ONE) == 0) {
			return BigDecimal.ZERO;
		}
		BigDecimal bi = asin(in);
		if (bi == null) {
			return bi;
		} else {
			return PI.divide(new BigDecimal(2), context).add(bi.negate(),
					context);
		}
	}

	public static BigDecimal atan(final BigDecimal in) {
		int num = in.signum();
		if (num == 0) {
			return BigDecimal.ZERO;
		}
		BigDecimal bi = in.abs().round(context);
		BigDecimal res = BigDecimal.ZERO;
		BigDecimal perfive = new BigDecimal(2).scaleByPowerOfTen(-1);
		if (bi.compareTo(perfive) == 1) {
			BigDecimal perfiveat = atan(perfive);
			while (bi.signum() == 1) {
				bi = bi.add(perfive.negate()).divide(
						bi.multiply(perfive).add(BigDecimal.ONE), context);
				res = res.add(perfiveat);
			}
		}
		if (num == -1) {
			bi = bi.negate();
			res = res.negate();
		}
		BigDecimal coef = bi.round(context);
		ArrayList<BigDecimal> temp = new ArrayList<BigDecimal>(0);
		temp.add(coef.add(res, context));
		bi = bi.pow(2).negate();
		do {
			num = temp.size();
			coef = coef.multiply(bi, context);
			temp.add(temp.get(num - 1).add(
					coef.divide(new BigDecimal(2 * num + 1), context), context));
		} while (temp.get(num).compareTo(temp.get(num - 1)) != 0);
		return temp.get(num);
	}

	public static BigDecimal root(final BigDecimal in, final int index) {
		int num = in.signum();
		if (num == 0) {
			return BigDecimal.ZERO;
		} else if (num == -1) {
			return null;
		} else if (index <= 0) {
			return null;
		} else if (in.compareTo(BigDecimal.ONE) == 0 || index == 1) {
			return in.round(context);
		}
		BigDecimal bi = in.round(context);
		int i = index;
		int j = 2;
		boolean b = true;
		while (i >= j && b) {
			while (i % j != 0 && i > j * j) {
				j++;
			}
			if (i % j == 0) {
				i /= j;
			} else {
				j = i;
				b = false;
			}
			if (j > 5) {
				bi = pow(bi, BigDecimal.ONE.divide(new BigDecimal(j), context));
			} else {
				ArrayList<BigDecimal> temp = new ArrayList<BigDecimal>(0);
				temp.add(bi);
				do {
					num = temp.size();
					temp.add(temp
							.get(num - 1)
							.pow(j)
							.multiply(new BigDecimal(j - 1))
							.add(bi)
							.divide(temp.get(num - 1).pow(j - 1)
									.multiply(new BigDecimal(j)), context));
				} while (temp.get(num).compareTo(temp.get(num - 1)) != 0);
				bi = temp.get(num);
			}
		}
		return bi;
	}

	public static BigDecimal log(final BigDecimal in) {
		if (in.signum() < 1) {
			return null;
		}
		int num = in.compareTo(BigDecimal.ONE);
		BigDecimal coef, bi, res;
		if (num == 0) {
			return BigDecimal.ZERO;
		} else if (num == -1) {
			bi = in.round(context);
			coef = BigDecimal.ONE.negate();
		} else {
			bi = BigDecimal.ONE.divide(in, context);
			coef = BigDecimal.ONE;
		}
		res = BigDecimal.ZERO;
		do {
			bi = bi.multiply(E, context);
			res = res.add(BigDecimal.ONE);
		} while (bi.compareTo(BigDecimal.ONE) == -1);
		if (bi.pow(5).compareTo(E) == 1) {
			bi = root(bi, 5);
			coef = coef.multiply(new BigDecimal(5));
		}
		if (num == -1) {
			res = res.negate();
		}
		bi = BigDecimal.ONE.negate().add(BigDecimal.ONE.divide(bi, context));
		coef = coef.multiply(bi, context);
		ArrayList<BigDecimal> temp = new ArrayList<BigDecimal>(0);
		temp.add(coef.add(res, context));
		bi = bi.negate();
		do {
			num = temp.size();
			coef = coef.multiply(bi, context);
			temp.add(temp.get(num - 1).add(
					coef.divide(new BigDecimal(num + 1), context), context));
		} while (temp.get(num).compareTo(temp.get(num - 1)) != 0);
		return temp.get(num);
	}

	public static BigDecimal sin(final BigDecimal in) {
		BigDecimal[] bi = in.divideAndRemainder(PI, context);
		bi[1] = bi[1].divide(new BigDecimal(3), context);
		ArrayList<BigDecimal> temp = new ArrayList<BigDecimal>(0);
		if (bi[0].abs().remainder(new BigDecimal(2), context)
				.compareTo(BigDecimal.ONE) == 0) {
			temp.add(bi[1].negate(context));
		} else {
			temp.add(bi[1].round(context));
		}
		BigDecimal coef = temp.get(0);
		bi[1] = bi[1].pow(2);
		int num;
		do {
			num = temp.size();
			coef = coef.multiply(bi[1]).divide(
					new BigDecimal(-2 * num * (2 * num + 1)), context);
			temp.add(temp.get(num - 1).add(coef, context));
		} while (temp.get(num).compareTo(temp.get(num - 1)) != 0);
		bi[1] = temp.get(num).pow(3).negate().multiply(new BigDecimal(4))
				.add(temp.get(num).multiply(new BigDecimal(3)), context);
		num = bi[1].signum();
		return bi[1].add(new BigDecimal(-num), context).add(
				new BigDecimal(num), context);
	}

	public static BigDecimal cos(final BigDecimal in) {
		BigDecimal[] bi = in.divideAndRemainder(PI, context);
		bi[1] = bi[1].divide(new BigDecimal(3), context).pow(2);
		ArrayList<BigDecimal> temp = new ArrayList<BigDecimal>(0);
		if (bi[0].abs().remainder(new BigDecimal(2), context)
				.compareTo(BigDecimal.ONE) == 0) {
			temp.add(BigDecimal.ONE.negate());
		} else {
			temp.add(BigDecimal.ONE);
		}
		BigDecimal coef = temp.get(0);
		int num;
		do {
			num = temp.size();
			coef = coef.multiply(bi[1]).divide(
					new BigDecimal(-2 * num * (2 * num - 1)), context);
			temp.add(temp.get(num - 1).add(coef, context));
		} while (temp.get(num).compareTo(temp.get(num - 1)) != 0);
		bi[1] = temp
				.get(num)
				.pow(3)
				.multiply(new BigDecimal(4))
				.add(temp.get(num).negate().multiply(new BigDecimal(3)),
						context);
		num = bi[1].signum();
		return bi[1].add(new BigDecimal(-num), context).add(
				new BigDecimal(num), context);
	}

	public static BigDecimal tan(final BigDecimal in) {
		BigDecimal bi = cos(in);
		if (bi.add(BigDecimal.ONE, context).compareTo(BigDecimal.ONE) == 0) {
			return null;
		} else {
			return sin(in).divide(bi, context);
		}
	}

	public static BigDecimal exp(final BigDecimal in) {
		int num = in.signum();
		BigDecimal coef = BigDecimal.ONE;
		BigDecimal bi;
		if (num == 0) {
			return BigDecimal.ONE;
		} else if (num == 1) {
			bi = in.negate(context);
		} else {
			bi = in.round(context);
		}
		if (in.abs().round(context).compareTo(BigDecimal.ONE) != 0) {
			while (bi.signum() == -1) {
				bi = bi.add(BigDecimal.ONE);
				coef = coef.multiply(E, context);
			}
		}
		if (num == 1) {
			bi = bi.negate();
		} else {
			coef = BigDecimal.ONE.divide(coef, context);
		}
		ArrayList<BigDecimal> temp = new ArrayList<BigDecimal>(0);
		temp.add(coef.round(context));
		do {
			num = temp.size();
			coef = coef.multiply(bi).divide(new BigDecimal(num), context);
			temp.add(temp.get(num - 1).add(coef, context));
		} while (temp.get(num).compareTo(temp.get(num - 1)) != 0);
		return temp.get(num);
	}

	public static BigDecimal pow(final BigDecimal in, final BigDecimal index) {
		BigDecimal bi = log(in);
		if (bi == null) {
			return null;
		} else {
			return exp(bi.multiply(index));
		}
	}

	/**
	 * Matrix of rotation Y to Z. R1(-rad).
	 */
	public static BigDecimal[][] rotX(final BigDecimal rad) {
		BigDecimal Cos = cos(rad);
		BigDecimal Sin = sin(rad);
		return new BigDecimal[][] {
				{ BigDecimal.ONE, BigDecimal.ZERO, BigDecimal.ZERO },
				{ BigDecimal.ZERO, Cos, Sin },
				{ BigDecimal.ZERO, Sin.negate(), Cos } };
	}

	/**
	 * Matrix of rotation X to Z. R2(rad).
	 */
	public static BigDecimal[][] rotY(final BigDecimal rad) {
		BigDecimal Cos = cos(rad);
		BigDecimal Sin = sin(rad);
		return new BigDecimal[][] { { Cos, BigDecimal.ZERO, Sin },
				{ BigDecimal.ZERO, BigDecimal.ONE, BigDecimal.ZERO },
				{ Sin.negate(), BigDecimal.ZERO, Cos } };
	}

	/**
	 * Matrix of rotation X to Y. R3(-rad).
	 */
	public static BigDecimal[][] rotZ(final BigDecimal rad) {
		BigDecimal Cos = cos(rad);
		BigDecimal Sin = sin(rad);
		return new BigDecimal[][] { { Cos, Sin, BigDecimal.ZERO },
				{ Sin.negate(), Cos, BigDecimal.ZERO },
				{ BigDecimal.ZERO, BigDecimal.ZERO, BigDecimal.ONE } };
	}

	/**
	 * Rotation (1,0,0) to A[0] = (x,y,z). Rotation (0,1,0) to A[1] = (x,y,z).
	 * Rotation (0,0,1) to A[2] = (x,y,z). Ar = rotA(A,r).
	 */
	public static BigDecimal[] rotA(final BigDecimal[][] A,
			final BigDecimal[] star) {
		BigDecimal[] res = new BigDecimal[] { BigDecimal.ZERO, BigDecimal.ZERO,
				BigDecimal.ZERO };
		for (int i = 0; i < 3; i++)
			for (int j = 0; j < 3; j++)
				res[i] = res[i].add(star[j].multiply(A[j][i]));
		return res;
	}

	/**
	 * AB = (rotA(A,B[0]),rotA(A,B[1]),rotA(A,B[2])).
	 */
	public static BigDecimal[][] rotAB(final BigDecimal[][] A,
			final BigDecimal[][] B) {
		return new BigDecimal[][] { rotA(A, B[0]), rotA(A, B[1]), rotA(A, B[2]) };
	}

	public static BigDecimal[] getApproximation(final BigDecimal[] y,
			final BigDecimal unit) {
		if (y == null || y.length == 0) {
			return null;
		} else if (y.length == 1) {
			return new BigDecimal[] { y[0].plus() };
		} else if (unit == null || unit.signum() == 0) {
			return new BigDecimal[] { y[(y.length + 1) / 2].plus() };
		}
		BigDecimal[] res = new BigDecimal[y.length];
		for (int i = 0; i < y.length; i++) {
			res[i] = BigDecimal.ZERO;
		}
		for (int i = 0; i < y.length; i++) {
			ArrayList<BigDecimal> temp = new ArrayList<BigDecimal>(0);
			temp.add(y[i].plus());
			for (int j = 0; j < y.length; j++) {
				if (i != j) {
					BigDecimal dif = new BigDecimal(j - (y.length + 1) / 2)
							.multiply(unit);
					temp.add(0, temp.get(0).multiply(dif));
					for (int k = 1; k < temp.size() - 1; k++) {
						temp.set(k,
								temp.get(k + 1).multiply(dif).add(temp.get(k)));
					}
					dif = new BigDecimal(j - i).multiply(unit);
					for (int k = 0; k < temp.size(); k++) {
						temp.set(k, temp.get(k).divide(dif, DEMath.context));
					}
				}
			}
			for (int j = 0; j < y.length; j++) {
				res[j] = res[j].add(temp.get(j));
			}
		}
		return res;
	}

	public static BigDecimal approximationR(final BigDecimal[] coef,
			final BigDecimal x) {
		if (coef == null || coef.length == 0) {
			return BigDecimal.ZERO;
		} else if (x == null || x.signum() == 0) {
			return coef[0].plus();
		}
		BigDecimal y = coef[coef.length - 1].plus();
		for (int i = coef.length - 2; i >= 0; i--) {
			y = y.multiply(x).add(coef[i]);
		}
		return y;
	}

	public static BigDecimal approximationV(final BigDecimal[] coef,
			final BigDecimal x) {
		if (coef == null || coef.length <= 1) {
			return BigDecimal.ZERO;
		} else if (x == null || x.signum() == 0) {
			return coef[1].plus();
		}
		BigDecimal y = new BigDecimal(coef.length - 1)
				.multiply(coef[coef.length - 1]);
		for (int i = coef.length - 2; i >= 1; i--) {
			y = y.multiply(x).add(new BigDecimal(i).multiply(coef[i]));
		}
		return y;
	}
}

Macintoshで月影図1枚描くのに8分かかるので高速化の作業に入ります。だけどbyte配列の数を使わないといけないような計算はこの世に存在するのか?boolean配列の多倍長ライブラリもつくってみようかと思ったけどboolean配列だと無駄が多すぎて実装も大変なのでやめます。

このソースコードはMITライセンスですが万人に自由に使っていただくためJAVAを用いた多倍長計算の上記の機能の改良版について特許出願することを禁止いたします。

|

月影図を表示します

若くないと感じる時、それは計算の勘が鈍ったとき。最近数ヶ月使わなければすぐプログラミングのやり方を忘れて過去の作品が遺構になったりAndroidのプロジェクトが全部動かなくなったり。何事も日頃の行いがものを言いますね。

デイリーポータルZ

ブログネタ: 【賞品付き】もう若くないと感じた瞬間は?参加数

|

バスは街の探偵団

バスは毎日同じところを走っているけど、いろいろな客が乗ってくるから大変なこともある。最近はバス車内での犯罪に対応するためにいちはやく監視カメラなどを導入されていたりする。バスの管制官は実にいろいろな情報を発信していてきていて飽きない。車内で犯人と被害者が同乗する事もあるしいろいろな状況に対応するために日夜策士のような情報戦がされている。だから、真の地域の防犯の拠点はバスなどの公共交通機関なのだろう。

|

« 2011年8月 | トップページ | 2011年10月 »