1
2 //metadoc Number category Core
3 //metadoc Number copyright Steve Dekorte 2002
4 //metadoc Number license BSD revised
5 /*metadoc Number description
6 A container for a double (a 64bit floating point number on most platforms).
7 */
8
9 #ifdef _MSC_VER
10 #define _USE_MATH_DEFINES
11 #endif
12
13 #include "IoNumber.h"
14 #include "IoObject.h"
15 #include "IoState.h"
16 #include "IoSeq.h"
17 #include "IoSeq.h"
18 #include "IoDate.h"
19 #include "IoState.h"
20
21 #include <ctype.h>
22 #include <assert.h>
23
24 #include <setjmp.h>
25 #if defined(_BSD_PPC_SETJMP_H_)
26 #include <machine/limits.h>
27 #else
28 #include <limits.h>
29 #endif
30
31 #if defined(__SYMBIAN32__)
32 /* TODO: Fix symbian constants */
33 #define FLT_MAX 0.0
34 #define FLT_MIN 0.0
35 #else
36 #include <float.h>
37 #endif
38
39 #ifndef log2
log2(double n)40 double log2(double n)
41 {
42 return log(n) / log(2);
43 }
44 #endif
45
46 #ifdef __FreeBSD__
47 #define log2(x) (log(x) / M_LN2)
48 #endif
49
50 #define DATA(self) CNUMBER(self)
51
52 static const char *protoId = "Number";
53
IoNumber_numberForDouble_canUse_(IoNumber * self,double n,IoNumber * other)54 IoNumber *IoNumber_numberForDouble_canUse_(IoNumber *self, double n, IoNumber *other)
55 {
56 if (DATA(self) == n) return self;
57 if (DATA(other) == n) return other;
58 return IONUMBER(n);
59 }
60
IoNumber_newTag(void * state)61 IoTag *IoNumber_newTag(void *state)
62 {
63 IoTag *tag = IoTag_newWithName_(protoId);
64 IoTag_state_(tag, state);
65 IoTag_cloneFunc_(tag, (IoTagCloneFunc *)IoNumber_rawClone);
66 IoTag_freeFunc_(tag, (IoTagFreeFunc *)IoNumber_free);
67 IoTag_compareFunc_(tag, (IoTagCompareFunc *)IoNumber_compare);
68 //IoTag_writeToStreamFunc_(tag, (IoTagWriteToStreamFunc *)IoNumber_writeToStream_);
69 //IoTag_readFromStreamFunc_(tag, (IoTagReadFromStreamFunc *)IoNumber_readFromStream_);
70 assert(sizeof(double) <= sizeof(void *)*2);
71 /*printf("Number tag = %p\n", (void *)tag);*/
72 return tag;
73 }
74
75 /*
76 void IoNumber_writeToStream_(IoNumber *self, BStream *stream)
77 {
78 BStream_writeTaggedDouble_(stream, DATA(self));
79 }
80
81 void *IoNumber_readFromStream_(IoNumber *self, BStream *stream)
82 {
83 DATA(self) = BStream_readTaggedDouble(stream);
84 return self;
85 }
86 */
87
88 // #define IONUMBER_IS_MUTABLE
89
IoNumber_proto(void * state)90 IoNumber *IoNumber_proto(void *state)
91 {
92 IoMethodTable methodTable[] = {
93 {"asNumber", IoNumber_asNumber},
94 {"+", IoNumber_add_},
95 {"-", IoNumber_subtract},
96 {"*", IoNumber_multiply},
97 {"/", IoNumber_divide},
98 //{"print", IoNumber_printNumber},
99
100 {"asString", IoNumber_asString},
101 {"asBuffer", IoNumber_asBuffer},
102 {"asCharacter", IoNumber_asCharacter},
103 {"asUint32Buffer", IoNumber_asUint32Buffer},
104 //{"asDate", IoNumber_asDate},
105
106 {"abs", IoNumber_abs},
107 {"acos", IoNumber_acos},
108 {"asin", IoNumber_asin},
109 {"atan", IoNumber_atan},
110 {"atan2", IoNumber_atan2},
111 {"ceil", IoNumber_ceil},
112 {"cos", IoNumber_cos},
113 // {"deg", IoNumber_deg}
114 {"exp", IoNumber_exp},
115 {"factorial", IoNumber_factorial},
116 {"floor", IoNumber_floor},
117 {"log", IoNumber_log},
118 {"log2", IoNumber_log2},
119 {"log10", IoNumber_log10},
120 {"max", IoNumber_max},
121 {"min", IoNumber_min},
122 {"%", IoNumber_mod},
123 {"mod", IoNumber_mod},
124 {"**", IoNumber_pow},
125 {"pow", IoNumber_pow},
126 {"round", IoNumber_round},
127 {"roundDown", IoNumber_roundDown},
128 {"sin", IoNumber_sin},
129 {"sqrt", IoNumber_sqrt},
130 {"squared", IoNumber_squared},
131 {"cubed", IoNumber_cubed},
132 {"tan", IoNumber_tan},
133 {"toggle", IoNumber_toggle},
134
135 // logic operations
136
137 {"&", IoNumber_bitwiseAnd},
138 {"|", IoNumber_bitwiseOr},
139 {"^", IoNumber_bitwiseXor},
140 {"<<", IoNumber_bitShiftLeft},
141 {">>", IoNumber_bitShiftRight},
142
143 {"bitwiseAnd", IoNumber_bitwiseAnd},
144 {"bitwiseOr", IoNumber_bitwiseOr},
145 {"bitwiseXor", IoNumber_bitwiseXor},
146 {"bitwiseComplement", IoNumber_bitwiseComplement},
147 {"shiftLeft", IoNumber_bitShiftLeft},
148 {"shiftRight", IoNumber_bitShiftRight},
149
150 // even and odd
151
152 {"isEven", IoNumber_isEven},
153 {"isOdd", IoNumber_isOdd},
154
155 // character operations
156
157 {"isAlphaNumeric", IoNumber_isAlphaNumeric},
158 {"isLetter", IoNumber_isLetter},
159 {"isControlCharacter", IoNumber_isControlCharacter},
160 {"isDigit", IoNumber_isDigit},
161 {"isGraph", IoNumber_isGraph},
162 {"isLowercase", IoNumber_isLowercase},
163 {"isUppercase", IoNumber_isUppercase},
164 {"isPrint", IoNumber_isPrint},
165 {"isPunctuation", IoNumber_isPunctuation},
166 {"isSpace", IoNumber_isSpace},
167 {"isHexDigit", IoNumber_isHexDigit},
168
169 {"asLowercase", IoNumber_asLowercase},
170 {"asUppercase", IoNumber_asUppercase},
171
172 {"between", IoNumber_between},
173 {"clip", IoNumber_clip},
174 {"negate", IoNumber_negate},
175 {"at", IoNumber_at},
176
177 {"integerMax", IoNumber_integerMax},
178 {"integerMin", IoNumber_integerMin},
179 {"longMax", IoNumber_longMax},
180 {"longMin", IoNumber_longMin},
181 {"shortMax", IoNumber_shortMax},
182 {"shortMin", IoNumber_shortMin},
183 {"unsignedLongMax", IoNumber_unsignedLongMax},
184 {"unsignedIntMax", IoNumber_unsignedIntMax},
185 {"floatMax", IoNumber_floatMax},
186 {"floatMin", IoNumber_floatMin},
187 {"isNan", IoNumber_isNan},
188
189 {"repeat", IoNumber_repeat},
190
191 {NULL, NULL},
192 };
193
194 IoObject *self = IoObject_new(state);
195
196 IoObject_tag_(self, IoNumber_newTag(state));
197 DATA(self) = 0;
198 IoState_registerProtoWithId_((IoState *)state, self, protoId);
199
200 IoObject_addMethodTable_(self, methodTable);
201 return self;
202 }
203
IoNumber_rawClone(IoNumber * proto)204 IoNumber *IoNumber_rawClone(IoNumber *proto)
205 {
206 IoObject *self = IoObject_rawClonePrimitive(proto);
207 DATA(self) = DATA(proto);
208 return self;
209 }
210
IoNumber_newWithDouble_(void * state,double n)211 IoNumber *IoNumber_newWithDouble_(void *state, double n)
212 {
213 // Normalize NAN, since there are positive and negative NANs
214 if (isnan(n))
215 {
216 n = NAN;
217 }
218 IoNumber *proto = IoState_protoWithId_((IoState *)state, protoId);
219 IoNumber *self = IOCLONE(proto); // since Numbers have no refs, we can avoid IOCLONE
220 DATA(self) = n;
221 return self;
222 }
223
IoNumber_newCopyOf_(IoNumber * self)224 IoNumber *IoNumber_newCopyOf_(IoNumber *self)
225 {
226 return IONUMBER(DATA(self));
227 }
228
IoNumber_copyFrom_(IoNumber * self,IoNumber * number)229 void IoNumber_copyFrom_(IoNumber *self, IoNumber *number)
230 {
231 DATA(self) = DATA(number);
232 }
233
IoNumber_free(IoNumber * self)234 void IoNumber_free(IoNumber *self)
235 {
236 /* need this so Object won't try to io_free IoObject_dataPointer(self) */
237 }
238
IoNumber_asStackUArray(IoNumber * self)239 UArray IoNumber_asStackUArray(IoNumber *self)
240 {
241 UArray a = UArray_stackAllocedEmptyUArray();
242 a.size = 1;
243
244 if (sizeof(double) == 4)
245 {
246 a.itemType = CTYPE_float32_t;
247 a.itemSize = 4;
248 }
249 else
250 {
251 a.itemType = CTYPE_float64_t;
252 a.itemSize = 8;
253 }
254
255 a.data = (uint8_t *)(&DATA(self));
256 return a;
257 }
258
IoNumber_asInt(IoNumber * self)259 int IoNumber_asInt(IoNumber *self)
260 {
261 return (int)(DATA(self));
262 }
263
IoNumber_asLong(IoNumber * self)264 long IoNumber_asLong(IoNumber *self)
265 {
266 return (long)(DATA(self));
267 }
268
IoNumber_asFloat(IoNumber * self)269 float IoNumber_asFloat(IoNumber *self)
270 {
271 return (float)DATA(self);
272 }
273
IoNumber_asDouble(IoNumber * self)274 double IoNumber_asDouble(IoNumber *self)
275 {
276 return (double)DATA(self);
277 }
278
IoNumber_compare(IoNumber * self,IoNumber * v)279 int IoNumber_compare(IoNumber *self, IoNumber *v)
280 {
281 if (ISNUMBER(v))
282 {
283 if (DATA(self) == DATA(v))
284 {
285 return 0;
286 }
287 return (DATA(self) > DATA(v)) ? 1 : -1;
288 }
289 return IoObject_defaultCompare(self, v);
290 }
291
IoNumber_Double_intoCString_(double n,char * s,size_t maxSize)292 void IoNumber_Double_intoCString_(double n, char *s, size_t maxSize)
293 {
294 if (n == (int)n)
295 {
296 snprintf(s, maxSize, "%d", (int)n);
297 }
298 else if (n > INT_MAX)
299 {
300 snprintf(s, maxSize, "%e", n);
301 }
302 else
303 {
304 long l;
305
306 snprintf(s, maxSize, "%.16f", n);
307
308 // remove the trailing zeros ex: 10.00 -> 10
309
310 l = (long)strlen(s) - 1;
311
312 while (l > 0)
313 {
314 if (s[l] == '0') { s[l] = 0; l--; continue; }
315 if (s[l] == '.') { s[l] = 0; l--; break; }
316 break;
317 }
318 }
319 }
320
IoNumber_print(IoNumber * self)321 void IoNumber_print(IoNumber *self)
322 {
323 double d = DATA(self);
324 char s[128];
325
326 IoNumber_Double_intoCString_(d, s, 127);
327 IoState_print_(IOSTATE, "%s", s);
328 }
329
330 // -----------------------------------------------------------
331
332 #ifdef _WIN32
333 #include <winsock2.h>
334 #else
335 #include <arpa/inet.h>
336 #endif
337
338 //IO_METHOD(IoNumber, htonl)
339 //{
340 // /* doc htonl
341 // Returns a new number with the first 4 bytes of the receiver switched from
342 //host to network byte order.
343 // */
344 //
345 // IoNumber *num = IONUMBER(0);
346 // IoObject_setDataUint32_(num, htonl(IoObject_dataUint32(self)));
347 // return num;
348 //}
349
350 //IO_METHOD(IoNumber, ntohl)
351 //{
352 // /* doc ntohl
353 //Returns a new number with the first 4 bytes of the receiver switched from
354 //network to host byte order.
355 // */
356 //
357 // IoNumber *num = IONUMBER(0);
358 // IoObject_setDataUint32_(num, ntohl(IoObject_dataUint32(self)));
359 // return num;
360 //}
361
362 // -----------------------------------------------------------
363
IO_METHOD(IoNumber,asNumber)364 IO_METHOD(IoNumber, asNumber)
365 {
366 /*doc Number asNumber
367 Returns self.
368 */
369
370 return self;
371 }
372
IO_METHOD(IoNumber,add_)373 IO_METHOD(IoNumber, add_)
374 {
375 /*doc Number +(aNumber)
376 Returns a new number that is the sum of the receiver and aNumber.
377 */
378
379 IoNumber *other = IoMessage_locals_numberArgAt_(m, locals, 0);
380 return IONUMBER(DATA(self) + DATA(other));
381 }
382
383
IO_METHOD(IoNumber,subtract)384 IO_METHOD(IoNumber, subtract)
385 {
386 /*doc Number -(aNumber)
387 Returns a new number that is the difference of the receiver and aNumber.
388 */
389
390 IoNumber *other = IoMessage_locals_numberArgAt_(m, locals, 0);
391 return IONUMBER(DATA(self) - DATA(other));
392 }
393
IO_METHOD(IoNumber,divide)394 IO_METHOD(IoNumber, divide)
395 {
396 /*doc Number /(aNumber)
397 Returns a new number with the value of the receiver divided by aNumber.
398 */
399
400 IoNumber *other = IoMessage_locals_numberArgAt_(m, locals, 0);
401 return IONUMBER(DATA(self) / DATA(other));
402 }
403
IO_METHOD(IoNumber,multiply)404 IO_METHOD(IoNumber, multiply)
405 {
406 /*doc Number *(aNumber)
407 Returns a new number that is the product of the receiver and aNumber.
408 */
409
410 IoNumber *other = IoMessage_locals_numberArgAt_(m, locals, 0);
411 return IONUMBER(DATA(self) * DATA(other));
412 }
413
IoNumber_asAllocedCString(IoNumber * self)414 char *IoNumber_asAllocedCString(IoNumber *self)
415 {
416 int size = 1024;
417 char *s = (char *)io_calloc(1, size);
418 memset(s, 0, size);
419 IoNumber_Double_intoCString_(DATA(self), s, size - 1);
420 return s;
421 }
422
IO_METHOD(IoNumber,printNumber)423 IO_METHOD(IoNumber, printNumber)
424 {
425 /*doc Number print
426 Prints the number.
427 */
428
429 char *s = IoNumber_asAllocedCString(self);
430 IoState_print_((IoState *)IOSTATE, s);
431 io_free(s);
432 return self;
433 }
434
IO_METHOD(IoNumber,justAsString)435 IO_METHOD(IoNumber, justAsString)
436 {
437 IoSymbol *string;
438 char *s = IoNumber_asAllocedCString(self);
439 string = IoSeq_newWithCString_((IoState *)IOSTATE, s);
440 io_free(s);
441 return string;
442 }
443
countBytes(long ld)444 static int countBytes(long ld)
445 {
446 int n = 1;
447 for (;;)
448 {
449 ld >>= 8;
450 if (ld == 0)
451 {
452 return n;
453 }
454 n++;
455 }
456 }
457
IO_METHOD(IoNumber,asCharacter)458 IO_METHOD(IoNumber, asCharacter)
459 {
460 /*doc Number asCharacter
461 Returns a String containing a single character whose
462 value is the value of the first byte of the receiver.
463 Returns nil if the number has no valid UCS mapping.
464 */
465
466 double d =DATA(self);
467 long ld = d;
468
469 if (d < 0 || d != ld)
470 {
471 return IONIL(self);
472 }
473 else
474 {
475 uint32_t i = io_uint32InBigEndian((uint32_t)d);
476 int bytes = countBytes(ld);
477 IoSeq *s;
478
479 if (bytes == 0)
480 {
481 bytes = 1;
482 }
483
484 if (bytes == 3)
485 {
486 bytes = 4;
487 }
488
489 if (bytes > 4)
490 {
491 // no valid UCS encoding for this value
492 return IONIL(self);
493 }
494
495 s = IoSeq_newWithData_length_(IOSTATE, (unsigned char *)&i, bytes);
496
497 {
498 UArray *u = IoSeq_rawUArray(s);
499 int e = CENCODING_ASCII;
500
501 switch (bytes)
502 {
503 case 1: e = CENCODING_ASCII; break;
504 case 2: e = CENCODING_UCS2; break;
505 case 4: e = CENCODING_UCS4; break;
506 }
507
508 UArray_setEncoding_(u, e);
509 }
510
511 return s;
512 }
513 }
514
IO_METHOD(IoNumber,asUint32Buffer)515 IO_METHOD(IoNumber, asUint32Buffer)
516 {
517 /*doc Number asUint32Buffer
518 Returns a Sequence containing a 4 byte representation of the uint32 value of the receiver.
519 */
520
521 uint32_t i = (int)DATA(self);
522 return IoSeq_newWithData_length_(IOSTATE, (unsigned char *)&i, sizeof(uint32_t));
523 }
524
IO_METHOD(IoNumber,asBuffer)525 IO_METHOD(IoNumber, asBuffer)
526 {
527 /*doc Number asBuffer(optionalNumberOfBytes)
528 Returns a Buffer containing a the number of bytes specified by
529 optionalNumberOfBytes (up to the size of a double on the platform) of the receiver.
530 If no optionalNumberOfBytes is specified, it is assumed to be the number of bytes
531 in a double on the host platform.
532 */
533 IoNumber *byteCount = IoMessage_locals_valueArgAt_(m, locals, 0);
534 int bc = sizeof(double);
535
536 if (!ISNIL(byteCount))
537 {
538 bc = DATA(byteCount);
539 }
540 return IoSeq_newWithData_length_(IOSTATE, (unsigned char *)&(DATA(self)), bc);
541 }
542
IO_METHOD(IoNumber,asString)543 IO_METHOD(IoNumber, asString)
544 {
545 /*doc Number asString(optionalIntegerDigits, optionalFactionDigits)
546 Returns a string representation of the receiver. For example:
547 <pre>
548 1234.5678 asString(0, 2)
549 </pre>
550 would return:
551 <pre>
552 1234.57
553 </pre>
554 */
555
556 if (IoMessage_argCount(m) >= 1)
557 {
558 int whole = IoMessage_locals_intArgAt_(m, locals, 0);
559 int part = 6;
560 char *s;
561 size_t length;
562 IoObject *n;
563
564
565 if (IoMessage_argCount(m) >= 2)
566 {
567 part = abs(IoMessage_locals_intArgAt_(m, locals, 1));
568 }
569
570 part = abs(part);
571 whole = abs(whole);
572
573 // If whole == 0, printf might need an arbitary size string. Instead of
574 // second guessing the size, pick a really big size: 1024.
575 length = 1024;
576 s = io_calloc(1, length);
577
578 snprintf(s, length, "%*.*f", whole, part, DATA(self));
579
580 n = IOSEQ((unsigned char *)s, (size_t)strlen(s));
581
582 io_free(s);
583
584 return n;
585 }
586
587 return IoNumber_justAsString(self, locals, m);
588 }
589
590 /*
591 IO_METHOD(IoNumber, asDate)
592 {
593 return IoDate_newWithNumber_((IoState *)IOSTATE, DATA(self));
594 }
595 */
596
IO_METHOD(IoNumber,abs)597 IO_METHOD(IoNumber, abs)
598 {
599 /*doc Number abs
600 Returns a number with the absolute value of the receiver.
601 */
602
603 return (DATA(self) < 0) ? (IoObject *)IONUMBER(-DATA(self)) : (IoObject *)self;
604 }
605
IO_METHOD(IoNumber,acos)606 IO_METHOD(IoNumber, acos)
607 {
608 /*doc Number acos
609 Returns a number with the arc cosine of the receiver.
610 */
611
612 return IONUMBER(acos(DATA(self)));
613 }
614
IO_METHOD(IoNumber,asin)615 IO_METHOD(IoNumber, asin)
616 {
617 /*doc Number asin
618 Returns a number with the arc sine of the receiver.
619 */
620
621 return IONUMBER(asin(DATA(self)));
622 }
623
IO_METHOD(IoNumber,atan)624 IO_METHOD(IoNumber, atan)
625 {
626 /*doc Number atan
627 Returns a number with the arc tangent of the receiver.
628 */
629
630 return IONUMBER(atan(DATA(self)));
631 }
632
IO_METHOD(IoNumber,atan2)633 IO_METHOD(IoNumber, atan2)
634 {
635 /*doc Number atan2(aNumber)
636 Returns a number with the arc tangent of y/x where y is the receiver and x is aNumber.
637 */
638
639 IoNumber *other = IoMessage_locals_numberArgAt_(m, locals, 0);
640 return IONUMBER(atan2(DATA(self), DATA(other)));
641 }
642
IO_METHOD(IoNumber,ceil)643 IO_METHOD(IoNumber, ceil)
644 {
645 /*doc Number ceil
646 Returns the a number with the receiver's value rounded up to
647 the nearest integer if its fractional component is greater than 0.
648 */
649
650 return IONUMBER(ceil(DATA(self)));
651 }
652
IO_METHOD(IoNumber,cos)653 IO_METHOD(IoNumber, cos)
654 {
655 /*doc Number cos
656 Returns the cosine of the receiver.
657 */
658
659 return IONUMBER(cos(DATA(self)));
660 }
661
662 /*
663 IO_METHOD(IoNumber, deg)
664 {
665 return IONUMBER(deg(DATA(self)));
666 }
667 */
668
IO_METHOD(IoNumber,exp)669 IO_METHOD(IoNumber, exp)
670 {
671 /*doc Number exp
672 Returns e to the power of the receiver.
673 */
674
675 return IONUMBER(exp(DATA(self)));
676 }
677
IO_METHOD(IoNumber,factorial)678 IO_METHOD(IoNumber, factorial)
679 {
680 /*doc Number factorial
681 Returns the factorial of the receiver.
682 */
683
684 int n = DATA(self);
685 double v = 1;
686 while (n)
687 {
688 v *= n;
689 n--;
690 }
691 return IONUMBER(v);
692 }
693
IO_METHOD(IoNumber,floor)694 IO_METHOD(IoNumber, floor)
695 {
696 /*doc Number floor
697 Returns a number with the receiver's value rounded
698 down to the nearest integer if its fractional component is not 0.
699 */
700
701 return IONUMBER(floor(DATA(self)));
702 }
703
IO_METHOD(IoNumber,log)704 IO_METHOD(IoNumber, log)
705 {
706 /*doc Number log
707 Returns the logarithm of the receiver. The base
708 is taken as the value of the first argument or the constant e if
709 the first argument is omitted.
710 */
711
712 float base;
713 if(IoMessage_argCount(m) > 0){
714 base = DATA(IoMessage_locals_numberArgAt_(m, locals, 0));
715 }
716 else{
717 base = (float)M_E;
718 }
719 return IONUMBER(log(DATA(self)) / log(base));
720 }
721
IO_METHOD(IoNumber,log2)722 IO_METHOD(IoNumber, log2)
723 {
724 /*doc Number log2
725 Returns the base 2 logarithm of the receiver.
726 */
727
728 return IONUMBER(log2(DATA(self)));
729 }
730
IO_METHOD(IoNumber,log10)731 IO_METHOD(IoNumber, log10)
732 {
733 /*doc Number log10
734 Returns the base 10 logarithm of the receiver.
735 */
736
737 return IONUMBER(log10(DATA(self)));
738 }
739
IO_METHOD(IoNumber,max)740 IO_METHOD(IoNumber, max)
741 {
742 /*doc Number max(aNumber)
743 Returns the greater of the receiver and aNumber.
744 */
745
746 IoNumber *other = IoMessage_locals_numberArgAt_(m, locals, 0);
747 return (DATA(self) > DATA(other)) ? (IoObject *)self :(IoObject *)other;
748 }
749
IO_METHOD(IoNumber,min)750 IO_METHOD(IoNumber, min)
751 {
752 /*doc Number min(aNumber)
753 Returns the lesser of the receiver and aNumber.
754 */
755
756 IoNumber *other = IoMessage_locals_numberArgAt_(m, locals, 0);
757 return (DATA(self) < DATA(other)) ? (IoObject *)self : (IoObject *)other;
758 }
759
IO_METHOD(IoNumber,mod)760 IO_METHOD(IoNumber, mod)
761 {
762 /*doc Number %(aNumber)
763 Returns the receiver modulus aNumber.
764 */
765
766 /*doc Number mod(aNumber)
767 Returns the receiver modulus aNumber.
768 */
769
770 IoNumber *other = IoMessage_locals_numberArgAt_(m, locals, 0);
771 return IONUMBER(fmod(DATA(self), DATA(other)));
772 }
773
774 /*
775 IO_METHOD(IoNumber, modf)
776 {
777 IoNumber *other = IoMessage_locals_numberArgAt_(m, locals, 0);
778 if (DATA(self) < DATA(other)); return self;
779 return other;
780 }
781
782 IO_METHOD(IoNumber, rad)
783 */
784
IO_METHOD(IoNumber,pow)785 IO_METHOD(IoNumber, pow)
786 {
787 /*doc Number pow(aNumber)
788 Returns the value of the receiver to the aNumber power.
789 */
790
791 /*doc Number **(aNumber)
792 Same as pow(aNumber).
793 */
794
795 IoNumber *other = IoMessage_locals_numberArgAt_(m, locals, 0);
796 return IONUMBER(pow(DATA(self), DATA(other)));
797 }
798
IO_METHOD(IoNumber,round)799 IO_METHOD(IoNumber, round)
800 {
801 /*doc Number round
802 Returns a number with the receiver's value rounded up to
803 the nearest integer if its fraction component is >= .5 or rounded up to the nearest integer otherwise.
804 */
805
806 double x = DATA(self);
807 if (x < 0.0)
808 return IONUMBER(ceil(x - 0.5));
809 else
810 return IONUMBER(floor(x + 0.5));
811 }
812
IO_METHOD(IoNumber,roundDown)813 IO_METHOD(IoNumber, roundDown)
814 {
815 /*doc Number roundDown
816 Returns a number with the receiver's value rounded down to
817 the nearest integer if its fraction component is <= .5 or rounded up the the nearest integer otherwise.
818 */
819
820 return IONUMBER(floor(DATA(self) + 0.5));
821 }
822
IO_METHOD(IoNumber,sin)823 IO_METHOD(IoNumber, sin)
824 {
825 /*doc Number sin
826 Returns the sine of the receiver.
827 */
828
829 return IONUMBER(sin(DATA(self)));
830 }
831
IO_METHOD(IoNumber,sqrt)832 IO_METHOD(IoNumber, sqrt)
833 {
834 /*doc Number sqrt
835 Returns the square root of the receiver.
836 */
837
838 return IONUMBER(sqrt(DATA(self)));
839 }
840
IO_METHOD(IoNumber,squared)841 IO_METHOD(IoNumber, squared)
842 {
843 /*doc Number squared
844 Returns the square of the receiver.
845 */
846
847 double v = DATA(self);
848 return IONUMBER(v * v);
849 }
850
IO_METHOD(IoNumber,cubed)851 IO_METHOD(IoNumber, cubed)
852 {
853 /*doc Number cubed
854 Returns the cube of the receiver.
855 */
856
857 double v = DATA(self);
858 return IONUMBER(v * v * v);
859 }
860
861
IO_METHOD(IoNumber,tan)862 IO_METHOD(IoNumber, tan)
863 {
864 /*doc Number tan
865 Returns the tangent of the receiver.
866 */
867
868 return IONUMBER(tan(DATA(self)));
869 }
870
871 /*
872 IO_METHOD(IoNumber, frexp)
873 {
874 return IONUMBER( frexp(DATA(self)) );
875 }
876
877 IO_METHOD(IoNumber, ldexp)
878 {
879 return IONUMBER( ldexp(DATA(self)) );
880 }
881 */
882
IO_METHOD(IoNumber,toggle)883 IO_METHOD(IoNumber, toggle)
884 {
885 /*doc Number toggle
886 Returns 1 if the receiver is 0. Returns 0 otherwise.
887 */
888
889 return (DATA(self))? (IoObject *)IONUMBER(0) : (IoObject *)IONUMBER(1);
890 }
891
892 /* --- bitwise operations ---------------------------------------- */
893
IO_METHOD(IoNumber,bitwiseAnd)894 IO_METHOD(IoNumber, bitwiseAnd)
895 {
896 /*doc Number &(aNumber)
897 Returns a new number with the bitwise AND of the receiver and aNumber.
898 */
899
900 /*doc Number bitwiseAnd(aNumber)
901 Returns a new number with the bitwise AND of the receiver and aNumber.
902 */
903
904 long other = IoMessage_locals_longArgAt_(m, locals, 0);
905 return IONUMBER(((long)DATA(self) & other));
906 }
907
IO_METHOD(IoNumber,bitwiseOr)908 IO_METHOD(IoNumber, bitwiseOr)
909 {
910 /*doc Number |(aNumber)
911 Returns a new number with the bitwise OR of the receiver and aNumber.
912 */
913
914 /*doc Number bitwiseOr(aNumber)
915 Returns a new number with the bitwise AND of the receiver and aNumber.
916 */
917
918 long other = IoMessage_locals_longArgAt_(m, locals, 0);
919 long n = DATA(self);
920 long r = n | other;
921 return IONUMBER(r);
922 }
923
IO_METHOD(IoNumber,bitwiseXor)924 IO_METHOD(IoNumber, bitwiseXor)
925 {
926 /*doc Number bitwiseXor(aNumber)
927 Returns a new number with the bitwise XOR of the receiver and aNumber.
928 */
929
930 /*doc Number ^(aNumber)
931 Returns the bitwise xor with the receiver (both numbers are converted to longs for the operation).
932 */
933
934 long other = IoMessage_locals_longArgAt_(m, locals, 0);
935 long r = (double)((long)DATA(self) ^ other);
936 return IONUMBER(r);
937 }
938
IO_METHOD(IoNumber,bitwiseComplement)939 IO_METHOD(IoNumber, bitwiseComplement)
940 {
941 /*doc Number bitwiseComplement
942 Returns a new number with the bitwise complement of the
943 receiver. (The 0 bits become 1s and the 1 bits become 0s. )
944 */
945
946 long r = (double)(~(long)DATA(self));
947 return IONUMBER(r);
948 }
949
IO_METHOD(IoNumber,bitShiftLeft)950 IO_METHOD(IoNumber, bitShiftLeft)
951 {
952 /*doc Number <<(aNumber)
953 Shifts the bits of the receiver left by the number of places specified by aNumber.
954 */
955
956 long other = IoMessage_locals_longArgAt_(m, locals, 0);
957 long r = (double)((long)DATA(self) << other);
958 return IONUMBER(r);
959 }
960
IO_METHOD(IoNumber,bitShiftRight)961 IO_METHOD(IoNumber, bitShiftRight)
962 {
963 /*doc Number >>(aNumber)
964 Shifts the bits of the receiver right by the number of places specified by aNumber.
965 */
966
967 long other = IoMessage_locals_longArgAt_(m, locals, 0);
968 long r = (double)((long)DATA(self) >> (long)other);
969 return IONUMBER(r);
970 }
971
972 // even and odd ------------------------------
973
IO_METHOD(IoNumber,isEven)974 IO_METHOD(IoNumber, isEven)
975 {
976 /*doc Number isEven
977 Returns true if
978 integer form of the receiver is even
979 , false otherwise.
980 */
981
982 int n = DATA(self);
983 return IOBOOL(self, 0 == (n & 0x01));
984 }
985
IO_METHOD(IoNumber,isOdd)986 IO_METHOD(IoNumber, isOdd)
987 {
988 /*doc Number isOdd
989 Returns true if
990 integer form of the receiver is odd
991 , false otherwise.
992 */
993
994 int n = DATA(self);
995 return IOBOOL(self, 0x01 == (n & 0x01));
996 }
997
998 // character operations ---------------------------------
999
IO_METHOD(IoNumber,isAlphaNumeric)1000 IO_METHOD(IoNumber, isAlphaNumeric)
1001 {
1002 /*doc Number isAlphaNumeric
1003 Returns true if
1004 receiver is an alphanumeric character value
1005 , false otherwise.
1006 */
1007
1008 return IOBOOL(self, isalnum((int)DATA(self)));
1009 }
1010
IO_METHOD(IoNumber,isLetter)1011 IO_METHOD(IoNumber, isLetter)
1012 {
1013 /*doc Number isLetter
1014 Returns true if
1015 receiver is a letter character value
1016 , false otherwise.
1017 */
1018
1019 return IOBOOL(self, isalpha((int)DATA(self)));
1020 }
1021
IO_METHOD(IoNumber,isControlCharacter)1022 IO_METHOD(IoNumber, isControlCharacter)
1023 {
1024 /*doc Number isControlCharacter
1025 Returns true if
1026 receiver is a control character value
1027 , false otherwise.
1028 */
1029
1030 return IOBOOL(self, iscntrl((int)DATA(self)));
1031 }
1032
IO_METHOD(IoNumber,isDigit)1033 IO_METHOD(IoNumber, isDigit)
1034 {
1035 /*doc Number isDigit
1036 Returns true if
1037 receiver is a numeric digit value
1038 , false otherwise.
1039 */
1040
1041 return IOBOOL(self, isdigit((int)DATA(self)));
1042 }
1043
IO_METHOD(IoNumber,isGraph)1044 IO_METHOD(IoNumber, isGraph)
1045 {
1046 /*doc Number isGraph
1047 Returns true if
1048 the receiver is a printing character value except space
1049 , false otherwise.
1050 */
1051
1052 return IOBOOL(self, isgraph((int)DATA(self)));
1053 }
1054
IO_METHOD(IoNumber,isLowercase)1055 IO_METHOD(IoNumber, isLowercase)
1056 {
1057 /*doc Number isLowercase
1058 Returns true if
1059 the receiver is a lowercase character value
1060 , false otherwise.
1061 */
1062
1063 return IOBOOL(self, islower((int)DATA(self)));
1064 }
1065
IO_METHOD(IoNumber,isUppercase)1066 IO_METHOD(IoNumber, isUppercase)
1067 {
1068 /*doc Number isUppercase
1069 Returns true if
1070 the receiver is a uppercase character value
1071 , false otherwise.
1072 */
1073
1074 return IOBOOL(self, isupper((int)DATA(self)));
1075 }
1076
IO_METHOD(IoNumber,isPrint)1077 IO_METHOD(IoNumber, isPrint)
1078 {
1079 /*doc Number isPrint
1080 Returns true if
1081 the receiver is a printing character value, including space
1082 , false otherwise.
1083 */
1084
1085 return IOBOOL(self, isprint((int)DATA(self)));
1086 }
1087
IO_METHOD(IoNumber,isPunctuation)1088 IO_METHOD(IoNumber, isPunctuation)
1089 {
1090 /*doc Number isPunctuation
1091 Returns true if
1092 the receiver is a punctuation character value
1093 , false otherwise.
1094
1095 */
1096
1097 return IOBOOL(self, ispunct((int)DATA(self)));
1098 }
1099
IO_METHOD(IoNumber,isSpace)1100 IO_METHOD(IoNumber, isSpace)
1101 {
1102 /*doc Number isSpace
1103 Returns true if
1104 the receiver is a space, formfeed, newline carriage return, tab or vertical tab character value
1105 , false otherwise.
1106 */
1107
1108 return IOBOOL(self, isspace((int)DATA(self)));
1109 }
1110
IO_METHOD(IoNumber,isHexDigit)1111 IO_METHOD(IoNumber, isHexDigit)
1112 {
1113 /*doc Number isHexDigit
1114 Returns true if
1115 the receiver is a hexadecimal character value
1116 , false otherwise.
1117 */
1118
1119 return IOBOOL(self, isxdigit((int)DATA(self)));
1120 }
1121
1122 // case ---------------------------------
1123
IO_METHOD(IoNumber,asLowercase)1124 IO_METHOD(IoNumber, asLowercase)
1125 {
1126 /*doc Number asLowercase
1127 Returns a new Number containing a lower case version of the receiver.
1128 */
1129
1130 int r = tolower((int)DATA(self));
1131 return IONUMBER(r);
1132 }
1133
IO_METHOD(IoNumber,asUppercase)1134 IO_METHOD(IoNumber, asUppercase)
1135 {
1136 /*doc Number asUppercase
1137 Returns a new Number containing a upper case version of the receiver.
1138 */
1139
1140 int r = toupper((int)DATA(self));
1141 return IONUMBER(r);
1142 }
1143
IO_METHOD(IoNumber,between)1144 IO_METHOD(IoNumber, between)
1145 {
1146 /*doc Number between(aNumber1, aNumber2)
1147 Returns true if the receiver's value is between or
1148 equal to aNumber1 and aNumber2, otherwise returns false.
1149 */
1150
1151 double a = IoMessage_locals_doubleArgAt_(m, locals, 0);
1152 double b = IoMessage_locals_doubleArgAt_(m, locals, 1);
1153 double n = DATA(self);
1154
1155 return IOBOOL(self, ((n >= a) && (n <= b)) || (n <= a && (n >= b)));
1156 }
1157
IO_METHOD(IoNumber,clip)1158 IO_METHOD(IoNumber, clip)
1159 {
1160 /*doc Number clip(aNumber1, aNumber2)
1161 Returns self if the receiver is between aNumber1 and aNumber2.
1162 Returns aNumber1 if it is less than aNumber1. Returns aNumber2 if it is greater than aNumber2.
1163 */
1164
1165 double a = IoMessage_locals_doubleArgAt_(m, locals, 0);
1166 double b = IoMessage_locals_doubleArgAt_(m, locals, 1);
1167 double n = DATA(self);
1168
1169 if (n < a) n = a;
1170 if (n > b) n = b;
1171
1172 return IONUMBER(n);
1173 }
1174
IO_METHOD(IoNumber,negate)1175 IO_METHOD(IoNumber, negate)
1176 {
1177 /*doc Number negate
1178 Returns new number that is negated version of the receiver.
1179 */
1180
1181 return IONUMBER(-DATA(self));
1182 }
1183
IO_METHOD(IoNumber,at)1184 IO_METHOD(IoNumber, at)
1185 {
1186 /*doc Number at(bitIndexNumber)
1187 Returns a new Number containing 1 if the receiver cast to a long
1188 has its bit set to 1 at bitIndexNumber. Otherwise returns 0.
1189 */
1190
1191 int i = IoMessage_locals_intArgAt_(m, locals, 0);
1192 long l = (long)DATA(self);
1193
1194 IOASSERT((i >= 0) && (i < sizeof(double)*8), "index out of bit bounds");
1195
1196 l = l >> i;
1197 l = l & 0x1;
1198 return IONUMBER(l);
1199 }
1200
1201 // limits ------------------------------------
1202
IO_METHOD(IoNumber,integerMax)1203 IO_METHOD(IoNumber, integerMax)
1204 {
1205 /*doc Number integerMax
1206 Returns the maximum integer value.
1207 */
1208
1209 return IONUMBER(INT_MAX);
1210 }
1211
IO_METHOD(IoNumber,integerMin)1212 IO_METHOD(IoNumber, integerMin)
1213 {
1214 /*doc Number integerMin
1215 Returns the minimum integer value.
1216 */
1217
1218 return IONUMBER(INT_MIN);
1219 }
1220
1221
IO_METHOD(IoNumber,longMax)1222 IO_METHOD(IoNumber, longMax)
1223 {
1224 /*doc Number longMax
1225 Returns the maximum long value.
1226 */
1227
1228 return IONUMBER(LONG_MAX);
1229 }
1230
IO_METHOD(IoNumber,longMin)1231 IO_METHOD(IoNumber, longMin)
1232 {
1233 /*doc Number longMin
1234 Returns the minimum long value.
1235 */
1236
1237 return IONUMBER(LONG_MIN);
1238 }
1239
1240
IO_METHOD(IoNumber,shortMax)1241 IO_METHOD(IoNumber, shortMax)
1242 {
1243 /*doc Number shortMax
1244 Returns the maximum short value.
1245 */
1246
1247 return IONUMBER(SHRT_MAX);
1248 }
1249
IO_METHOD(IoNumber,shortMin)1250 IO_METHOD(IoNumber, shortMin)
1251 {
1252 /*doc Number shortMin
1253 Returns the minimum short value.
1254 */
1255
1256 return IONUMBER(SHRT_MIN);
1257 }
1258
IO_METHOD(IoNumber,unsignedLongMax)1259 IO_METHOD(IoNumber, unsignedLongMax)
1260 {
1261 /*doc Number unsignedLongMax
1262 Returns the maximum unsigned long value.
1263 */
1264
1265 return IONUMBER(ULONG_MAX);
1266 }
1267
IO_METHOD(IoNumber,unsignedIntMax)1268 IO_METHOD(IoNumber, unsignedIntMax)
1269 {
1270 /*doc Number unsignedIntMax
1271 Returns the maximum unsigned int value.
1272 */
1273
1274 return IONUMBER(UINT_MAX);
1275 }
1276
IO_METHOD(IoNumber,unsignedShortMax)1277 IO_METHOD(IoNumber, unsignedShortMax)
1278 {
1279 /*doc Number unsignedShortMax
1280 Returns the minimum unsigned int value.
1281 */
1282
1283 return IONUMBER(USHRT_MAX);
1284 }
1285
IO_METHOD(IoNumber,floatMax)1286 IO_METHOD(IoNumber, floatMax)
1287 {
1288 /*doc Number floatMax
1289 Returns the maximum float value.
1290 */
1291
1292 return IONUMBER(FLT_MAX);
1293 }
1294
IO_METHOD(IoNumber,floatMin)1295 IO_METHOD(IoNumber, floatMin)
1296 {
1297 /*doc Number floatMin
1298 Returns the minimum float value.
1299 */
1300
1301 return IONUMBER(FLT_MIN);
1302 }
1303
IO_METHOD(IoNumber,doubleMax)1304 IO_METHOD(IoNumber, doubleMax)
1305 {
1306 /*doc Number floatMax
1307 Returns the maximum double precision float value.
1308 */
1309
1310 return IONUMBER(DBL_MAX);
1311 }
1312
IO_METHOD(IoNumber,doubleMin)1313 IO_METHOD(IoNumber, doubleMin)
1314 {
1315 /*doc Number doubleMin
1316 Returns the minimum double precision float value.
1317 */
1318
1319 return IONUMBER(DBL_MIN);
1320 }
1321
IO_METHOD(IoNumber,isNan)1322 IO_METHOD(IoNumber, isNan)
1323 {
1324 /*doc Number isNan
1325 Returns true if the receiver is not a number. Otherwise returns false.
1326 */
1327
1328 return IOBOOL(self, isnan(CNUMBER(self)));
1329 }
1330
1331 // looping ---------------------------------------------
1332
IO_METHOD(IoNumber,repeat)1333 IO_METHOD(IoNumber, repeat)
1334 {
1335 /*doc Number repeat(optionalIndex, expression)
1336 Evaluates message a number of times that corresponds to the receivers
1337 integer value. This is significantly faster than a for() or while() loop.
1338 */
1339
1340 IoMessage_assertArgCount_receiver_(m, 1, self);
1341
1342 {
1343 IoState *state = IOSTATE;
1344 IoSymbol *indexSlotName;
1345 IoMessage *doMessage;
1346 double i, max = CNUMBER(self);
1347 IoObject *result = IONIL(self);
1348
1349 if(IoMessage_argCount(m) > 1)
1350 {
1351 indexSlotName = IoMessage_name(IoMessage_rawArgAt_(m, 0));
1352 doMessage = IoMessage_rawArgAt_(m, 1);
1353 }
1354 else
1355 {
1356 indexSlotName = 0;
1357 doMessage = IoMessage_rawArgAt_(m, 0);
1358 }
1359
1360 IoState_pushRetainPool(state);
1361
1362 for (i = 0; i < max; i ++)
1363 {
1364 /*
1365 if (result != locals && result != self)
1366 {
1367 IoState_immediatelyFreeIfUnreferenced_(state, result);
1368 }
1369 */
1370
1371 IoState_clearTopPool(state);
1372
1373 if (indexSlotName)
1374 {
1375 IoObject_setSlot_to_(locals, indexSlotName, IONUMBER(i));
1376 }
1377
1378 result = IoMessage_locals_performOn_(doMessage, locals, locals);
1379
1380 if (IoState_handleStatus(IOSTATE))
1381 {
1382 break;
1383 }
1384 }
1385
1386 IoState_popRetainPoolExceptFor_(IOSTATE, result);
1387 return result;
1388 }
1389 }
1390
1391