예제 #1
0
파일: date.c 프로젝트: BigEd/wp34s
/*
 *  Convert Z = year, y = month, x = day to a valid date in X
 */
decNumber *dateFromYMD(decNumber *res, const decNumber *z, const decNumber *y, const decNumber *x) {
	if (decNumberIsSpecial(x) || decNumberIsSpecial(y) || decNumberIsSpecial(z))
		return set_NaN(res);
	else {
		return build_date(res, dn_to_int(z), dn_to_int(y), dn_to_int(x));
	}
}
예제 #2
0
파일: agm.c 프로젝트: BigEd/wp34s
void cmplxAGM(decNumber *rx, decNumber *ry,
		const decNumber *a, const decNumber *b,
		const decNumber *c, const decNumber *d) {
	decNumber x1, x2, y1, y2, t1, t2, u1, u2;
	int n;

	if (decNumberIsSpecial(a) || decNumberIsSpecial(b) ||
			decNumberIsSpecial(c) || decNumberIsSpecial(d)) {
			goto nan;
	}
	cmplxCopy(&x1, &x2, a, b);
	cmplxCopy(&y1, &y2, c, d);
	for (n=0; n<1000; n++) {
		cmplxSubtract(&t1, &t2, &x1, &x2, &y1, &y2);
		cmplxR(&u1, &t1, &t2);
		dn_compare(&u2, &u1, &const_1e_32);
		if (decNumberIsNegative(&u2)) {
			cmplxCopy(rx, ry, &x1, &x2);
			return;
		}

		cmplxAdd(&t1, &t2, &x1, &x2, &y1, &y2);
		cmplxDiv2(&u1, &u2, &t1, &t2);

		cmplxMultiply(&t1, &t2, &x1, &x2, &y1, &y2);
		cmplxSqrt(&y1, &y2, &t1, &t2);

		cmplxCopy(&x1, &x2, &u1, &u2);
	}
nan:	cmplx_NaN(rx, ry);
}
예제 #3
0
파일: agm.c 프로젝트: BigEd/wp34s
decNumber *decNumberAGM(decNumber *res, const decNumber *x, const decNumber *y) {
	int n;
	decNumber a, g, t, u;

	if (decNumberIsNegative(x) || decNumberIsNegative(y))
		goto nan;
	if (decNumberIsSpecial(x) || decNumberIsSpecial(y)) {
		if (decNumberIsNaN(x) || decNumberIsNaN(y))
			goto nan;
		if (dn_eq0(x) || dn_eq0(y))
			goto nan;
		return set_inf(res);
	}
	decNumberCopy(&a, x);
	decNumberCopy(&g, y);
	for (n=0; n<1000; n++) {
		if (relative_error(&a, &g, &const_1e_32))
			return decNumberCopy(res, &a);

		dn_add(&t, &a, &g);
		dn_div2(&u, &t);

		dn_multiply(&t, &a, &g);
		if (dn_eq0(&t))
			return decNumberZero(res);
		dn_sqrt(&g, &t);
		decNumberCopy(&a, &u);
	}
nan:	return set_NaN(res);
}
예제 #4
0
파일: date.c 프로젝트: BigEd/wp34s
/* Return the day of the week
 */
static int dateExtract(decNumber *res, const decNumber *x, int *y, int *m, int *d) {
	if (decNumberIsSpecial(x) || extract_date(x, y, m, d)) {
		set_NaN(res);
		return 0;
	}
	return 1;
}
예제 #5
0
bool DecimalDecNumber::toDecimalComponents(const DecimalDecNumber &val, int64& significand, int32& exponent)
{
	DecimalDecNumber valCopy = val;
	valCopy.m_context.digits = 18; // maximum number of digits which can be represented by int64 significand

	// Check if decimal is NaN or infinite - we can't represent these as components
	if (decNumberIsSpecial( &valCopy.m_value ))
	{
		exponent = 0;
		significand = 0;
		return false;
	}

	// Minimize the size of the number the significand needs to represent
	decNumberReduce( &valCopy.m_value, &valCopy.m_value, &valCopy.m_context );

	exponent = valCopy.m_value.exponent;

	decNumber numExponent;
	decNumberFromInt32( &numExponent, -valCopy.m_value.exponent );
	decNumberScaleB( &valCopy.m_value, &valCopy.m_value, &numExponent, &valCopy.m_context );

	if (::sscanf(valCopy.toString(0).c_str(), "%lld", &significand) != 1)
	{
		exponent = 0;
		significand = 0;
		return false;
	}

	return true;
}
예제 #6
0
파일: date.c 프로젝트: BigEd/wp34s
decNumber *dateFromJ(decNumber *res, const decNumber *x) {
	if (decNumberIsSpecial(x) || dn_lt0(x))
		set_NaN(res);
	else {
		const int j = dn_to_int(x);
		int y, m, d;

		JDN2(j, &y, &m, &d);
		return build_date(res, y, m, d);
	}
	return res;
}
예제 #7
0
파일: date.c 프로젝트: BigEd/wp34s
/* Conversion routines from Julian days to and from dates
 */
decNumber *dateToJ(decNumber *res, const decNumber *x) {
	if (decNumberIsSpecial(x))
err:		set_NaN(res);
	else {
		int y, m, d;

		if (extract_date(x, &y, &m, &d))
			goto err;
		int_to_dn(res, JDN(y, m, d));
	}
	return res;
}
예제 #8
0
파일: date.c 프로젝트: BigEd/wp34s
void date_alphamonth(enum nilop op) {
	decNumber x;
	int y, m, d;
	static const char mons[12*3] = "JANFEBMARAPRMAYJUNJULAUGSEPOCTNOVDEC";

	getX(&x);
	if (decNumberIsSpecial(&x) || extract_date(&x, &y, &m, &d))
		err(ERR_BAD_DATE);
	else {
		copy3(&(mons[3*m - 3]));
	}
}
예제 #9
0
파일: date.c 프로젝트: BigEd/wp34s
void date_alphaday(enum nilop op) {
	decNumber x;
	int y, m, d, dow;

	getX(&x);
	if (decNumberIsSpecial(&x) || extract_date(&x, &y, &m, &d))
		err(ERR_BAD_DATE);
	else {
		dow = day_of_week(y, m, d, NULL);
		copy3(&("MONTUEWEDTHUFRISATSUN"[3*(dow-1)]));
	}
}
예제 #10
0
파일: date.c 프로젝트: BigEd/wp34s
/* Given an argument on the stack, attempt to determine the year.
 * If the argument is a plain integer, it is the year.
 * Otherwise, decode it according to the current date mode and
 * return the year.
 */
static int find_year(const decNumber *x, int *year) {
	int y;

	if (decNumberIsSpecial(x))
		return -1;
	if (is_int(x)) {
		y = dn_to_int(x);
		if (check_date(y, 1, 1))
			return -1;
	} else if (extract_date(x, &y, NULL, NULL))
		return -1;
	*year = y;
	return 0;
}
예제 #11
0
// -------------------------------------
//      comparison function.   Returns
//         Not Comparable :  -2
//                      < :  -1
//                     == :   0
//                      > :  +1
int32_t DigitList::compare(const DigitList &other) {
    decNumber   result;
    int32_t     savedDigits = fContext.digits;
    fContext.digits = 1;
    uprv_decNumberCompare(&result, this->fDecNumber, other.fDecNumber, &fContext);
    fContext.digits = savedDigits;
    if (decNumberIsZero(&result)) {
        return 0;
    } else if (decNumberIsSpecial(&result)) {
        return -2;
    } else if (result.bits & DECNEG) {
        return -1;
    } else {
        return 1;
    }
}
예제 #12
0
void convertToIntX<int64>(const decNumber* pDecNum, decContext* pContext, int64& result)
{
	static const uint64 s_arrPowerOfTen[19] = {
			1, 10, 100, 1000, 10000, 100000, 1000000,
			10000000, 100000000, 1000000000, 10000000000ULL,
			100000000000ULL, 1000000000000ULL, 10000000000000ULL,
			100000000000000ULL, 1000000000000000ULL, 10000000000000000ULL,
			100000000000000000ULL, 1000000000000000000ULL };

	if (decNumberIsSpecial(pDecNum))
	{
		char sNumber[1024];
		throw("Attempt to get an integer from invalid number");
	}
	else if (pDecNum->exponent != 0)
	{
		char sNumber[1024];
		// FTHROW(InvalidArgumentException, "Unsupported exponent %d, only zero exponent is supported, number %s", pDecNum->exponent, decNumberToString(pDecNum, sNumber));
		throw("Unsupported exponent , only zero exponent is supported, number ");
	}
	else if (pDecNum->digits > (int)(sizeof(s_arrPowerOfTen)/sizeof(*s_arrPowerOfTen)))
	{
		char sNumber[1024];
		// FTHROW(InvalidArgumentException, "Overflow during conversion, number of digits is %d, number %s", pDecNum->digits, decNumberToString(pDecNum, sNumber));
		throw("Overflow during conversion, number of digits is number ");
	}
	const decNumberUnit* pDigit = pDecNum->lsu;
	uint64 nUnsignedResult = 0;
	const bool isNegative = decNumberIsNegative(pDecNum);
	const uint64 nMaxValue = isNegative ? -std::numeric_limits<int64>::min() : std::numeric_limits<int64>::max();

	for (int i = 0; i < pDecNum->digits; ++pDigit, i += DECDPUN)
	{
			const uint64 nPrev = nUnsignedResult;														// to be able to check on 'overflow'
			nUnsignedResult += *pDigit * s_arrPowerOfTen[i];
			if ((nUnsignedResult < nPrev) || (nUnsignedResult > nMaxValue))
			{
				char sNumber[1024];
				throw("Overflow during conversion, step");
				// FTHROW(InvalidArgumentException, "Overflow during conversion, step %d (%llu, %llu, %llu), number %s",
				// 		i, nUnsignedResult, nPrev, nMaxValue, decNumberToString(pDecNum, sNumber));
			}
	}
	result = isNegative ? -((int64)nUnsignedResult) : (int64)nUnsignedResult;
}
예제 #13
0
/**
 * Return true if the number represented by this object can fit into
 * a long.
 */
UBool
DigitList::fitsIntoInt64(UBool ignoreNegativeZero) /*const*/
{
    if (decNumberIsSpecial(this->fDecNumber)) {
        // NaN or Infinity.  Does not fit in int32.
        return FALSE;
    }
    uprv_decNumberTrim(this->fDecNumber);
    if (fDecNumber->exponent < 0) {
        // Number contains fraction digits.
        return FALSE;
    }
    if (decNumberIsZero(this->fDecNumber) && !ignoreNegativeZero &&
        (fDecNumber->bits & DECNEG) != 0) {
        // Negative Zero, not ingored.  Cannot represent as a long.
        return FALSE;
    }
    if (getUpperExponent() < 19) {
        // The number is 18 or fewer digits.
        // The max and min int64 are 19 digts, so this number fits.
        // This is the common case.
        return TRUE;
    }

    // TODO:  Should cache these constants; construction is relatively costly.
    //        But not of huge consequence; they're only needed for 19 digit ints.
    UErrorCode status = U_ZERO_ERROR;
    DigitList min64; min64.set("-9223372036854775808", status);
    if (this->compare(min64) < 0) {
        return FALSE;
    }
    DigitList max64; max64.set("9223372036854775807", status);
    if (this->compare(max64) > 0) {
        return FALSE;
    }
    if (U_FAILURE(status)) {
        return FALSE;
    }
    return true;
}