/*#io Number ioDoc( docCopyright("Steve Dekorte", 2002) docLicense("BSD revised") docObject("Number") docInclude("_ioCode/Number.io") docDescription("A container for a double (a 64bit floating point number on most platforms).") docCategory("Core") */ #define _GNU_SOURCE // for round #include "IoNumber.h" #include "IoObject.h" #include "IoState.h" #include "IoSeq.h" #include "IoSeq.h" #include "IoDate.h" #include "IoState.h" #include #include #include #include #if defined(_BSD_PPC_SETJMP_H_) #include #else #include #endif #if defined(__SYMBIAN32__) /* TODO: Fix symbian constants */ #define FLT_MAX 0.0 #define FLT_MIN 0.0 #else #include #endif #ifdef _MSC_VER #define isnan _isnan float round(float a) { return floor(a+0.5f); } #endif #define NIVAR(self) CNUMBER(self) IoNumber *IoNumber_numberForDouble_canUse_(IoNumber *self, double n, IoNumber *other) { if (NIVAR(self) == n) return self; if (NIVAR(other) == n) return other; return IONUMBER(n); } IoTag *IoNumber_tag(void *state) { IoTag *tag = IoTag_newWithName_("Number"); tag->state = state; tag->cloneFunc = (TagCloneFunc *)IoNumber_rawClone; tag->freeFunc = (TagFreeFunc *)IoNumber_free; tag->compareFunc = (TagCompareFunc *)IoNumber_compare; tag->writeToStoreOnStreamFunc = (TagWriteToStoreOnStreamFunc *)IoNumber_writeToStore_stream_; tag->readFromStoreOnStreamFunc = (TagReadFromStoreOnStreamFunc *)IoNumber_readFromStore_stream_; assert(sizeof(double) <= sizeof(void *)*2); /*printf("Number tag = %p\n", (void *)tag);*/ return tag; } void IoNumber_writeToStore_stream_(IoNumber *self, IoStore *store, BStream *stream) { BStream_writeTaggedDouble_(stream, NIVAR(self)); } void *IoNumber_readFromStore_stream_(IoNumber *self, IoStore *store, BStream *stream) { NIVAR(self) = BStream_readTaggedDouble(stream); return self; } // #define IONUMBER_IS_MUTABLE IoNumber *IoNumber_proto(void *state) { IoMethodTable methodTable[] = { {"asNumber", IoNumber_asNumber}, {"add", IoNumber_add_}, {"+", IoNumber_add_}, {"-", IoNumber_subtract}, {"*", IoNumber_multiply}, {"/", IoNumber_divide}, //{"print", IoNumber_printNumber}, //{"linePrint", IoNumber_linePrint}, {"asString", IoNumber_asString}, {"asBuffer", IoNumber_asBuffer}, {"asCharacter", IoNumber_asCharacter}, {"asUint32Buffer", IoNumber_asUint32Buffer}, //{"asDate", IoNumber_asDate}, {"abs", IoNumber_abs}, {"acos", IoNumber_acos}, {"asin", IoNumber_asin}, {"atan", IoNumber_atan}, {"atan2", IoNumber_atan2}, {"ceil", IoNumber_ceil}, {"cos", IoNumber_cos}, // {"deg", IoNumber_deg} {"exp", IoNumber_exp}, {"factorial", IoNumber_factorial}, {"floor", IoNumber_floor}, {"log", IoNumber_log}, {"log10", IoNumber_log10}, {"max", IoNumber_max}, {"min", IoNumber_min}, {"%", IoNumber_mod}, {"mod", IoNumber_mod}, //{"^", IoNumber_pow}, {"**", IoNumber_pow}, {"pow", IoNumber_pow}, {"round", IoNumber_round}, {"sin", IoNumber_sin}, {"sqrt", IoNumber_sqrt}, {"squared", IoNumber_squared}, {"cubed", IoNumber_cubed}, {"tan", IoNumber_tan}, {"toggle", IoNumber_toggle}, // logic operations {"&", IoNumber_bitwiseAnd}, {"^", IoNumber_bitwiseXor}, {"|", IoNumber_bitwiseOr}, {"bitwiseAnd", IoNumber_bitwiseAnd}, {"bitwiseOr", IoNumber_bitwiseOr}, {"bitwiseXor", IoNumber_bitwiseXor}, {"bitwiseComplement", IoNumber_bitwiseComplement}, {"shiftLeft", IoNumber_bitShiftLeft}, {"shiftRight", IoNumber_bitShiftRight}, // even and odd {"isEven", IoNumber_isEven}, {"isOdd", IoNumber_isOdd}, // character operations {"isAlphaNumeric", IoNumber_isAlphaNumeric}, {"isLetter", IoNumber_isLetter}, {"isControlCharacter", IoNumber_isControlCharacter}, {"isDigit", IoNumber_isDigit}, {"isGraph", IoNumber_isGraph}, {"isLowercase", IoNumber_isLowercase}, {"isUppercase", IoNumber_isUppercase}, {"isPrint", IoNumber_isPrint}, {"isPunctuation", IoNumber_isPunctuation}, {"isSpace", IoNumber_isSpace}, {"isHexDigit", IoNumber_isHexDigit}, {"Lowercase", IoNumber_Lowercase}, {"upperCase", IoNumber_upperCase}, {"asLowercase", IoNumber_Lowercase}, {"asUppercase", IoNumber_upperCase}, {"between", IoNumber_between}, {"clip", IoNumber_clip}, {"negate", IoNumber_negate}, {"at", IoNumber_at}, {"integerMax", IoNumber_integerMax}, {"integerMin", IoNumber_integerMin}, {"longMax", IoNumber_longMax}, {"longMin", IoNumber_longMin}, {"shortMax", IoNumber_shortMax}, {"shortMin", IoNumber_shortMin}, {"unsignedLongMax", IoNumber_unsignedLongMax}, {"unsignedIntMax", IoNumber_unsignedIntMax}, {"floatMax", IoNumber_floatMax}, {"floatMin", IoNumber_floatMin}, {"isNan", IoNumber_isNan}, {"repeatTimes", IoNumber_repeat}, {"repeat", IoNumber_repeat}, {NULL, NULL}, }; IoObject *self = IoObject_new(state); self->tag = IoNumber_tag(state); NIVAR(self) = 0; IoState_registerProtoWithFunc_((IoState *)state, self, IoNumber_proto); IoObject_addMethodTable_(self, methodTable); return self; } IoNumber *IoNumber_rawClone(IoNumber *proto) { IoObject *self = IoObject_rawClonePrimitive(proto); NIVAR(self) = NIVAR(proto); return self; } IoNumber *IoNumber_newWithDouble_(void *state, double n) { IoNumber *proto = IoState_protoWithInitFunction_((IoState *)state, IoNumber_proto); IoNumber *self = IOCLONE(proto); // since Numbers have no refs, we can avoid IOCLONE NIVAR(self) = n; return self; } IoNumber *IoNumber_newCopyOf_(IoNumber *self) { return IONUMBER(NIVAR(self)); } void IoNumber_copyFrom_(IoNumber *self, IoNumber *number) { NIVAR(self) = NIVAR(number); } void IoNumber_free(IoNumber *self) { /* need this so Object won't try to free IoObject_dataPointer(self) */ } int IoNumber_asInt(IoNumber *self) { return (int)(NIVAR(self)); } long IoNumber_asLong(IoNumber *self) { return (long)(NIVAR(self)); } float IoNumber_asFloat(IoNumber *self) { return (float)NIVAR(self); } double IoNumber_asDouble(IoNumber *self) { return (double)NIVAR(self); } int IoNumber_compare(IoNumber *self, IoNumber *v) { if (ISNUMBER(v)) { if (NIVAR(self) == NIVAR(v)) { return 0; } return (NIVAR(self) > NIVAR(v)) ? 1 : -1; } return ((ptrdiff_t)self->tag) - ((ptrdiff_t)v->tag); } void IoNumber_Double_intoCString_(double n, char *s, size_t maxSize) { if (n == (int)n) { snprintf(s, maxSize, "%d", (int)n); } else if (n > INT_MAX) { snprintf(s, maxSize, "%e", n); } else { int l; snprintf(s, maxSize, "%f", n); // remove the trailing zeros ex: 10.00 -> 10 l = strlen(s) - 1; while (l > 0) { if (s[l] == '0') { s[l] = 0; l--; continue; } if (s[l] == '.') { s[l] = 0; l--; break; } break; } } } void IoNumber_print(IoNumber *self) { double d = NIVAR(self); char s[128]; IoNumber_Double_intoCString_(d, s, 127); IoState_print_(IOSTATE, "%s", s); } // ----------------------------------------------------------- #ifdef _WIN32 #include #else #include #endif //IoObject *IoNumber_htonl(IoNumber *self, IoObject *locals, IoMessage *m) //{ // /*#io // docSlot("htonl", // "Returns a new number with the first 4 bytes of the receiver switched from //host to network byte order.") // */ // // IoNumber *num = IONUMBER(0); // IoObject_setDataUint32_(num, htonl(IoObject_dataUint32(self))); // return num; //} //IoObject *IoNumber_ntohl(IoNumber *self, IoObject *locals, IoMessage *m) //{ // /*#io // docSlot("ntohl", // "Returns a new number with the first 4 bytes of the receiver switched from //network to host byte order.") // */ // // IoNumber *num = IONUMBER(0); // IoObject_setDataUint32_(num, ntohl(IoObject_dataUint32(self))); // return num; //} // ----------------------------------------------------------- IoObject *IoNumber_asNumber(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("asNumber", "Returns self.") */ return self; } IoObject *IoNumber_add_(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("+(aNumber)", "Returns a new number that is the sum of the receiver and aNumber.") */ IoNumber *other = IoMessage_locals_numberArgAt_(m, locals, 0); return IONUMBER(NIVAR(self) + NIVAR(other)); } IoObject *IoNumber_subtract(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("-(aNumber)", "Returns a new number that is the difference of the receiver and aNumber.") */ IoNumber *other = IoMessage_locals_numberArgAt_(m, locals, 0); return IONUMBER(NIVAR(self) - NIVAR(other)); } IoObject *IoNumber_divide(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("/(aNumber)", "Returns a new number with the value of the receiver diveded by aNumber.") */ IoNumber *other = IoMessage_locals_numberArgAt_(m, locals, 0); return IONUMBER(NIVAR(self) / NIVAR(other)); } IoObject *IoNumber_multiply(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("*(aNumber)", "Returns a new number that is the product of the receiver and aNumber.") */ IoNumber *other = IoMessage_locals_numberArgAt_(m, locals, 0); return IONUMBER(NIVAR(self) * NIVAR(other)); } IoObject *IoNumber_printNumber(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("print", "Prints the number.") */ char s[24]; memset(s, 0, 24); IoNumber_Double_intoCString_(NIVAR(self), s, 24); IoState_print_((IoState *)IOSTATE, s); return self; } IoObject *IoNumber_linePrint(IoNumber *self, IoObject *locals, IoMessage *m) { /* docSlot("linePrint", "Prints the Number and a new line character.") */ IoNumber_printNumber(self, locals, m); IoState_print_((IoState *)IOSTATE, "\n"); return self; } IoObject *IoNumber_justAsString(IoNumber *self, IoObject *locals, IoMessage *m) { IoSymbol *string; int size = 1000; char *s = (char *)malloc(size); memset(s, 0, size); IoNumber_Double_intoCString_(NIVAR(self), s, 1000); string = IoState_symbolWithCString_((IoState *)IOSTATE, s); free(s); return string; } IoObject *IoNumber_asCharacter(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("asCharacter", "Returns a String containing a single character whose value is the ascii value of the first byte of the receiver.") */ char s[2]; s[0] = (char)NIVAR(self); s[1] = 0; return IoState_symbolWithCString_length_((IoState *)IOSTATE, s, 1); } IoObject *IoNumber_asUint32Buffer(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("asUint32Buffer", "Returns a Sequence containing a 4 byte representation of the uint32 value of the receiver.") */ uint32_t i = (int)NIVAR(self); return IoSeq_newWithData_length_(IOSTATE, (unsigned char *)&i, sizeof(uint32_t)); } IoObject *IoNumber_asBuffer(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("asBuffer(optionalNumberOfBytes)", "Returns a Buffer containing a the number of bytes specified by optionalNumberOfBytes (up to the size of a double on the platform) of the reciever. If no optionalNumberOfBytes is specified, it is assumed to be the number of bytes in a double on the host platform.") */ IoNumber *byteCount = IoMessage_locals_valueArgAt_(m, locals, 0); int bc = sizeof(double); if (!ISNIL(byteCount)) { bc = NIVAR(byteCount); } return IoSeq_newWithData_length_(IOSTATE, (unsigned char *)&(NIVAR(self)), bc); } IoObject *IoNumber_asString(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("asString(optionalIntegerDigits, optionalFactionDigits)", """Returns a string representation of the receiver. For example:
1234.5678 asString(0, 2)
would return:
$1234.56
""") */ if (IoMessage_argCount(m) >= 1) { int whole = IoMessage_locals_intArgAt_(m, locals, 0); int part = 6; char s[32]; if (IoMessage_argCount(m) >= 2) { part = abs(IoMessage_locals_intArgAt_(m, locals, 1)); } part = abs(part); whole = abs(whole); if (whole > 15) whole = 15; if (part > 15) part = 15; if (whole && part) { snprintf(s, 32, "%*.*f", whole, part, NIVAR(self)); } else if (whole) { snprintf(s, 32, "%*d", whole, (int) NIVAR(self)); } else if (part) { snprintf(s, 32, "%.*f", part, NIVAR(self)); } else { snprintf(s, 32, "%d", (int) NIVAR(self)); } return IOSYMBOL(s); } return IoNumber_justAsString(self, locals, m); } /* IoObject *IoNumber_asDate(IoNumber *self, IoObject *locals, IoMessage *m) { return IoDate_newWithNumber_((IoState *)IOSTATE, NIVAR(self)); } */ IoObject *IoNumber_abs(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("abs", "Returns a number with the absolute value of the receiver.") */ return (NIVAR(self) < 0) ? (IoObject *)IONUMBER(-NIVAR(self)) : (IoObject *)self; } IoObject *IoNumber_acos(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("acos", "Returns a number with the arc cosine of the receiver.") */ return IONUMBER(acos(NIVAR(self))); } IoObject *IoNumber_asin(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("asin", "Returns a number with the arc sine of the receiver.") */ return IONUMBER(asin(NIVAR(self))); } IoObject *IoNumber_atan(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("atan", "Returns a number with the arc tangent of the receiver.") */ return IONUMBER(atan(NIVAR(self))); } IoObject *IoNumber_atan2(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("atan2(aNumber)", "Returns a number with the arc tangent of y/x where y is the receiver and x is aNumber.") */ IoNumber *other = IoMessage_locals_numberArgAt_(m, locals, 0); return IONUMBER(atan2(NIVAR(self), NIVAR(other))); } IoObject *IoNumber_ceil(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("ceil", "Returns the a number with the receiver's value rounded up to the nearest integer if it's fractional component is greater than 0.") */ return IONUMBER(ceil(NIVAR(self))); } IoObject *IoNumber_cos(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("cos", "Returns the cosine of the receiver.") */ return IONUMBER(cos(NIVAR(self))); } /* IoObject *IoNumber_deg(IoNumber *self, IoObject *locals, IoMessage *m) { return IONUMBER(deg(NIVAR(self))); } */ IoObject *IoNumber_exp(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("exp", "Returns e to the power of the receiver.") */ return IONUMBER(exp(NIVAR(self))); } IoObject *IoNumber_factorial(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("factorial", "Returns the factorial of the receiver.") */ int n = NIVAR(self); double v = 1; while (n) { v *= n; n--; } return IONUMBER(v); } IoObject *IoNumber_floor(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("floor", "Returns the a number with the receiver's value rounded down to the nearest integer if it's fractional component is not 0.") */ return IONUMBER(floor(NIVAR(self))); } IoObject *IoNumber_log(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("log", "Returns the natural logarithm of the receiver.") */ return IONUMBER(log(NIVAR(self))); } IoObject *IoNumber_log10(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("log10", "Returns the base 10 logarithm of the receiver.") */ return IONUMBER(log10(NIVAR(self))); } IoObject *IoNumber_max(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("max(aNumber)", "Returns the greater of the receiver and aNumber.") */ IoNumber *other = IoMessage_locals_numberArgAt_(m, locals, 0); return (NIVAR(self) > NIVAR(other)) ? (IoObject *)self :(IoObject *)other; } IoObject *IoNumber_min(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("min(aNumber)", "Returns the lesser of the receiver and aNumber.") */ IoNumber *other = IoMessage_locals_numberArgAt_(m, locals, 0); return (NIVAR(self) < NIVAR(other)) ? (IoObject *)self : (IoObject *)other; } IoObject *IoNumber_mod(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("%(aNumber)", "Returns the receiver modulus aNumber.") */ IoNumber *other = IoMessage_locals_numberArgAt_(m, locals, 0); return IONUMBER(fmod(NIVAR(self), NIVAR(other))); } /* IoObject *IoNumber_modf(IoNumber *self, IoObject *locals, IoMessage *m) { IoNumber *other = IoMessage_locals_numberArgAt_(m, locals, 0); if (NIVAR(self) < NIVAR(other)); return self; return other; } IoObject *IoNumber_rad(IoNumber *self, IoObject *locals, IoMessage *m) */ IoObject *IoNumber_pow(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("pow(aNumber)", "Returns the value of the receiver to the aNumber power.") */ /*#io docSlot("**(aNumber)", "Same as pow(aNumber).") */ IoNumber *other = IoMessage_locals_numberArgAt_(m, locals, 0); return IONUMBER(pow(NIVAR(self), NIVAR(other))); } IoObject *IoNumber_round(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("round", "Returns the a number with the receiver's value rounded up to the nearest integer if it's fraction component is >= .5.") */ return IONUMBER(round(NIVAR(self))); } IoObject *IoNumber_sin(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("sin", "Returns the sine of the receiver.") */ return IONUMBER(sin(NIVAR(self))); } IoObject *IoNumber_sqrt(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("sqrt", "Returns the square root of the receiver.") */ return IONUMBER(sqrt(NIVAR(self))); } IoObject *IoNumber_squared(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("sqrt", "Returns the square root of the receiver.") */ double v = NIVAR(self); return IONUMBER(v * v); } IoObject *IoNumber_cubed(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("cubed", "Returns the cube of the receiver.") */ double v = NIVAR(self); return IONUMBER(v * v * v); } IoObject *IoNumber_tan(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("tan", "Returns the tangent of the receiver.") */ return IONUMBER(tan(NIVAR(self))); } /* IoObject *IoNumber_frexp(IoNumber *self, IoObject *locals, IoMessage *m) { return IONUMBER( frexp(NIVAR(self)) ); } IoObject *IoNumber_ldexp(IoNumber *self, IoObject *locals, IoMessage *m) { return IONUMBER( ldexp(NIVAR(self)) ); } */ IoObject *IoNumber_toggle(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("toggle", "Returns 1 if the receiver is 0. Returns 0 otherwise.") */ return (NIVAR(self))? (IoObject *)IONUMBER(0) : (IoObject *)IONUMBER(1); } /* --- bitwise operations ---------------------------------------- */ IoObject *IoNumber_bitwiseAnd(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("&(aNumber)", "Returns a new number with the bitwise AND of the receiver and aNumber.") */ long other = IoMessage_locals_longArgAt_(m, locals, 0); return IONUMBER(((long)NIVAR(self) & other)); } IoObject *IoNumber_bitwiseOr(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("|(aNumber)", "Returns a new number with the bitwise OR of the receiver and aNumber.") */ long other = IoMessage_locals_longArgAt_(m, locals, 0); long n = NIVAR(self); long r = n | other; return IONUMBER(r); } IoObject *IoNumber_bitwiseXor(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("bitwiseXor(aNumber)", "Returns a new number with the bitwise XOR of the receiver and aNumber.") */ long other = IoMessage_locals_longArgAt_(m, locals, 0); long r = (double)((long)NIVAR(self) ^ other); return IONUMBER(r); } IoObject *IoNumber_bitwiseComplement(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("bitwiseComplement", "Returns a new number with the bitwise complement of the receiver. (Turns the 0 bits of become 1s and the 1 bits become 0s. )") */ long r = (double)(~(long)NIVAR(self)); return IONUMBER(r); } IoObject *IoNumber_bitShiftLeft(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("shiftLeft(aNumber)", "Shifts the bits of the receiver left by the number of places specified by aNumber.") */ long other = IoMessage_locals_longArgAt_(m, locals, 0); long r = (double)((long)NIVAR(self) << other); return IONUMBER(r); } IoObject *IoNumber_bitShiftRight(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("shiftRight(aNumber)", "Shifts the bits of the receiver right by the number of places specified by aNumber.") */ long other = IoMessage_locals_longArgAt_(m, locals, 0); long r = (double)((long)NIVAR(self) >> (long)other); return IONUMBER(r); } // even and odd ------------------------------ IoObject *IoNumber_isEven(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("isEven", "Returns self if integer form of the receiver is even. Otherwise returns Nil.") */ int n = NIVAR(self); return IOBOOL(self, 0 == (n & 0x01)); } IoObject *IoNumber_isOdd(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("isOdd", "Returns self if integer form of the receiver is even. Otherwise returns Nil.") */ int n = NIVAR(self); return IOBOOL(self, 0x01 == (n & 0x01)); } // character operations --------------------------------- IoObject *IoNumber_isAlphaNumeric(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("isAlphaNumeric", "Returns self if the receiver is an alphanumeric character value. Otherwise returns Nil.") */ return IOBOOL(self, isalnum((int)NIVAR(self))); } IoObject *IoNumber_isLetter(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("isLetter", "eturns self if the receiver is an alphanetic character value. Otherwise returns Nil.") */ return IOBOOL(self, isalpha((int)NIVAR(self))); } IoObject *IoNumber_isControlCharacter(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("isControlCharacter", "Returns self if the receiver is an control character value. Otherwise returns Nil.") */ return IOBOOL(self, iscntrl((int)NIVAR(self))); } IoObject *IoNumber_isDigit(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("isDigit", "Returns self if the receiver is an numeric digit character value. Otherwise returns Nil.") */ return IOBOOL(self, isdigit((int)NIVAR(self))); } IoObject *IoNumber_isGraph(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("isGraph", "Returns self if the receiver is a printing character value except space. Otherwise returns Nil.") */ return IOBOOL(self, isgraph((int)NIVAR(self))); } IoObject *IoNumber_isLowercase(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("isLowercase", "Returns self if the receiver is an lower case character value. Otherwise returns Nil.") */ return IOBOOL(self, islower((int)NIVAR(self))); } IoObject *IoNumber_isUppercase(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("isUppercase", "Returns self if the receiver is an upper case character value. Otherwise returns Nil.") */ return IOBOOL(self, isupper((int)NIVAR(self))); } IoObject *IoNumber_isPrint(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("isPrint", "Returns self if the receiver is an printing character value, including space. Otherwise returns Nil.") */ return IOBOOL(self, isprint((int)NIVAR(self))); } IoObject *IoNumber_isPunctuation(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("isPunctuation", "Returns self if the receiver is an printing character value, except space letter or digit. Otherwise returns Nil.") */ return IOBOOL(self, ispunct((int)NIVAR(self))); } IoObject *IoNumber_isSpace(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("isSpace", "Returns self if the receiver is a space, formfeed, newline carriage return, tab or vertical tab character value. Otherwise returns Nil.") */ return IOBOOL(self, isspace((int)NIVAR(self))); } IoObject *IoNumber_isHexDigit(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("isHexDigit", "Returns self if the receiver is hexidecimal digit character value. Otherwise returns Nil.") */ return IOBOOL(self, isxdigit((int)NIVAR(self))); } // case --------------------------------- IoObject *IoNumber_Lowercase(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("Lowercase", "Returns a new Number containing a lower case version of the receiver.") */ int r = tolower((int)NIVAR(self)); return IONUMBER(r); } IoObject *IoNumber_upperCase(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("upperCase", "Returns a new Number containing a upper case version of the receiver.") */ int r = toupper((int)NIVAR(self)); return IONUMBER(r); } IoObject *IoNumber_between(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("between(aNumber1, aNumber2)", "Returns the receiver if the receiver's value is between or equal to aNumber1 and aNumber2, otherwise returns nil.") */ double a = IoMessage_locals_doubleArgAt_(m, locals, 0); double b = IoMessage_locals_doubleArgAt_(m, locals, 1); double n = NIVAR(self); return IOBOOL(self, ((n >= a) && (n <= b)) || (n <= a && (n >= b))); } IoObject *IoNumber_clip(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("clip(aNumber1, aNumber2)", "Returns self if the receiver is between aNumber1 and aNumber2. Returns aNumber1 if it is less than aNumber1. Returns aNumber2 if it is greater than aNumber2.") */ double a = IoMessage_locals_doubleArgAt_(m, locals, 0); double b = IoMessage_locals_doubleArgAt_(m, locals, 1); double n = NIVAR(self); if (n < a) n = a; if (n > b) n = b; return IONUMBER(n); } IoObject *IoNumber_negate(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("negate", "Returns new number that is negated version of the receiver.") */ return IONUMBER(-NIVAR(self)); } IoObject *IoNumber_at(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("at(bitIndexNumber)", "Returns a new Number containing 1 if the receiver cast to a long has it's bit set to 1 at bitIndexNumber. Otherwise returns 0.") */ int i = IoMessage_locals_intArgAt_(m, locals, 0); long l = (long)NIVAR(self); IOASSERT((i >= 0) && (i < sizeof(double)*8), "index out of bit bounds"); l = l >> i; l = l & 0x1; return IONUMBER(l); } // limits ------------------------------------ IoObject *IoNumber_integerMax(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("integerMax", "Returns the maximum integer value.") */ return IONUMBER(INT_MAX); } IoObject *IoNumber_integerMin(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("integerMin", "Returns the minimum integer value.") */ return IONUMBER(INT_MIN); } IoObject *IoNumber_longMax(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("longMax", "Returns the maximum long value.") */ return IONUMBER(LONG_MAX); } IoObject *IoNumber_longMin(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("longMin", "Returns the minimum long value.") */ return IONUMBER(LONG_MIN); } IoObject *IoNumber_shortMax(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("shortMax", "Returns the maximum short value.") */ return IONUMBER(SHRT_MAX); } IoObject *IoNumber_shortMin(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("shortMin", "Returns the minimum short value.") */ return IONUMBER(SHRT_MIN); } IoObject *IoNumber_unsignedLongMax(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("unsignedLongMax", "Returns the maximum unsigned long value.") */ return IONUMBER(ULONG_MAX); } IoObject *IoNumber_unsignedIntMax(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("unsignedIntMax", "Returns the maximum unsigned int value.") */ return IONUMBER(UINT_MAX); } IoObject *IoNumber_unsignedShortMax(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("unsignedShortMax", "Returns the minimum unsigned int value.") */ return IONUMBER(USHRT_MAX); } IoObject *IoNumber_floatMax(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("floatMax", "Returns the maximum float value.") */ return IONUMBER(FLT_MAX); } IoObject *IoNumber_floatMin(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("floatMin", "Returns the minimum float value.") */ return IONUMBER(FLT_MIN); } IoObject *IoNumber_doubleMax(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("floatMax", "Returns the maximum double precision float value.") */ return IONUMBER(DBL_MAX); } IoObject *IoNumber_doubleMin(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("doubleMin", "Returns the minimum double precision float value.") */ return IONUMBER(DBL_MIN); } IoObject *IoNumber_isNan(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("isNan", "Returns true if the receiver is not a number. Otherwise returns false.") */ return IOBOOL(self, isnan(CNUMBER(self))); } // looping --------------------------------------------- IoObject *IoNumber_repeat(IoNumber *self, IoObject *locals, IoMessage *m) { /*#io docSlot("repeatTimes(optionalIndex, expression)", "Evaluates message a number of times that corresponds to the receivers integer value. This is significantly faster than a for() or while() loop.") */ IoMessage_assertArgCount_receiver_(m, 1, self); { IoState *state = IOSTATE; IoSymbol *indexSlotName; IoMessage *doMessage; double i, max = CNUMBER(self); IoObject *result = IONIL(self); if(IoMessage_argCount(m) > 1) { indexSlotName = IoMessage_name(IoMessage_rawArgAt_(m, 0)); doMessage = IoMessage_rawArgAt_(m, 1); } else { indexSlotName = 0; doMessage = IoMessage_rawArgAt_(m, 0); } IoState_pushRetainPool(state); for (i = 0; i < max; i ++) { /* if (result != locals && result != self) { IoState_immediatelyFreeIfUnreferenced_(state, result); } */ IoState_clearTopPool(state); if (indexSlotName) { IoObject_setSlot_to_(locals, indexSlotName, IONUMBER(i)); } result = IoMessage_locals_performOn_(doMessage, locals, locals); if (IoState_handleStatus(IOSTATE)) { goto done; } } done: IoState_popRetainPoolExceptFor_(IOSTATE, result); return result; } }