txInteger fxToInteger(txMachine* the, txSlot* theSlot) { #if mxOptimize if (XS_INTEGER_KIND == theSlot->kind) return theSlot->value.integer; // this is the case over 90% of the time, so avoid the switch #endif again: switch (theSlot->kind) { case XS_UNDEFINED_KIND: case XS_NULL_KIND: theSlot->kind = XS_INTEGER_KIND; theSlot->value.integer = 0; break; case XS_BOOLEAN_KIND: theSlot->kind = XS_INTEGER_KIND; if (theSlot->value.boolean == 0) theSlot->value.integer = 0; else theSlot->value.integer = 1; break; case XS_INTEGER_KIND: break; case XS_NUMBER_KIND: theSlot->kind = XS_INTEGER_KIND; switch (c_fpclassify(theSlot->value.number)) { case C_FP_INFINITE: case C_FP_NAN: case C_FP_ZERO: theSlot->value.integer = 0; break; default: { #define MODULO 4294967296.0 txNumber aNumber = c_fmod(c_trunc(theSlot->value.number), MODULO); if (aNumber >= MODULO / 2) aNumber -= MODULO; else if (aNumber < -MODULO / 2) aNumber += MODULO; theSlot->value.integer = (txInteger)aNumber; } break; } break; case XS_STRING_KIND: case XS_STRING_X_KIND: theSlot->kind = XS_NUMBER_KIND; theSlot->value.number = fxStringToNumber(the->dtoa, theSlot->value.string, 1); goto again; case XS_SYMBOL_KIND: mxTypeError("Cannot coerce symbol to integer"); break; case XS_REFERENCE_KIND: fxToPrimitive(the, theSlot, XS_NUMBER_HINT); goto again; default: mxTypeError("Cannot coerce to integer"); break; } return theSlot->value.integer; }
txIndex fxArgToArrayLimit(txMachine* the, txInteger argi) { if (mxArgc > argi) { txNumber i = c_trunc(fxToNumber(the, mxArgv(argi))); if (c_isnan(i)) i = 0; else if (i < 0) i = 0; else if (i > XS_MAX_INDEX) i = XS_MAX_INDEX; return (txIndex)i; } return XS_MAX_INDEX; }
void fx_Number_isInteger(txMachine* the) { int fpclass; txSlot* slot = (mxArgc < 1) ? C_NULL : fxCheckNumber(the, mxArgv(0)); mxResult->kind = XS_BOOLEAN_KIND; mxResult->value.boolean = 0; if (slot) { fpclass = c_fpclassify(slot->value.number); if ((fpclass != FP_NAN) && (fpclass != FP_INFINITE)) { txNumber check = c_trunc(slot->value.number); if (slot->value.number == check) mxResult->value.boolean = 1; } } }
txIndex fxArgToIndex(txMachine* the, txInteger argi, txIndex index, txIndex length) { if (mxArgc > argi) { txNumber c = length; txNumber i = c_trunc(fxToNumber(the, mxArgv(argi))); if (c_isnan(i)) i = 0; if (i < 0) { i = c + i; if (i < 0) i = 0; } else if (i > c) i = c; index = (txIndex)i; } return index; }
void fx_Date_prototype_setTime(txMachine* the) { txSlot* slot = fxCheckDate(the, mxThis); if (!slot) mxTypeError("this is no date"); if (mxArgc < 1) slot->value.number = C_NAN; else { txNumber number = fxToNumber(the, mxArgv(0)); int fpclass = c_fpclassify(number); if (fpclass != FP_NAN) { if (c_fabs(number) > 8.64e15) number = C_NAN; else number = c_trunc(number); } slot->value.number = number; } mxResult->value.number = slot->value.number; mxResult->kind = XS_NUMBER_KIND; }
void fx_Date_prototype_set_aux(txMachine* the, txTimeDescription* td, txSlot* slot) { c_time_t time; txNumber number; td->tm.tm_isdst = -1; time = c_mktime(&(td->tm)); if (time == -1) number = C_NAN; else { number = (time * 1000.0) + td->ms; if (c_fpclassify(number) != FP_NAN) { if (c_fabs(number) > 8.64e15) number = C_NAN; else number = c_trunc(number); } } mxResult->value.number = number; mxResult->kind = XS_NUMBER_KIND; slot->value.number = number; }
txUnsigned fxToUnsigned(txMachine* the, txSlot* theSlot) { txUnsigned result; again: switch (theSlot->kind) { case XS_UNDEFINED_KIND: case XS_NULL_KIND: theSlot->kind = XS_INTEGER_KIND; result = theSlot->value.integer = 0; break; case XS_BOOLEAN_KIND: theSlot->kind = XS_INTEGER_KIND; if (theSlot->value.boolean == 0) result = theSlot->value.integer = 0; else result = theSlot->value.integer = 1; break; case XS_INTEGER_KIND: if (theSlot->value.integer >= 0) return (txUnsigned)theSlot->value.integer; theSlot->kind = XS_NUMBER_KIND; theSlot->value.number = theSlot->value.integer; // continue case XS_NUMBER_KIND: theSlot->kind = XS_INTEGER_KIND; switch (c_fpclassify(theSlot->value.number)) { case C_FP_INFINITE: case C_FP_NAN: case C_FP_ZERO: result = theSlot->value.integer = 0; break; default: { #define MODULO 4294967296.0 txNumber aNumber = c_fmod(c_trunc(theSlot->value.number), MODULO); if (aNumber < 0) aNumber += MODULO; result = (txUnsigned)aNumber; if (((txInteger)result) >= 0) { theSlot->kind = XS_INTEGER_KIND; theSlot->value.integer = (txInteger)result; } else { theSlot->kind = XS_NUMBER_KIND; theSlot->value.number = aNumber; } } break; } break; case XS_STRING_KIND: case XS_STRING_X_KIND: theSlot->kind = XS_NUMBER_KIND; theSlot->value.number = fxStringToNumber(the->dtoa, theSlot->value.string, 1); goto again; case XS_SYMBOL_KIND: result = 0; mxTypeError("Cannot coerce symbol to unsigned"); break; case XS_REFERENCE_KIND: fxToPrimitive(the, theSlot, XS_NUMBER_HINT); goto again; default: result = 0; mxTypeError("Cannot coerce to unsigned"); break; } return result; }