Merge pull request #506 from andrewcsmith/patch-2
[supercollider.git] / SCClassLibrary / Common / Math / Integer.sc
blob9c18243c5984585abff1e8dad70e98560a83e7b6
1 Integer : SimpleNumber {
2         isInteger { ^true }
4         hash { ^this.asFloat.hash }
6         + { arg aNumber, adverb; _AddInt; ^aNumber.performBinaryOpOnSimpleNumber('+', this, adverb) }
7         - { arg aNumber, adverb; _SubInt; ^aNumber.performBinaryOpOnSimpleNumber('-', this, adverb) }
8         * { arg aNumber, adverb; _MulInt; ^aNumber.performBinaryOpOnSimpleNumber('*', this, adverb) }
10         clip { arg lo, hi; _ClipInt; ^this.primitiveFailed }
11         wrap { arg lo, hi; _WrapInt; ^this.primitiveFailed }
12         fold { arg lo, hi; _FoldInt; ^this.primitiveFailed }
14         even { ^(this & 1) == 0 }
15         odd { ^(this & 1) == 1 }
17         xrand { arg exclude=0;
18                 ^(exclude + (this - 1).rand + 1) % this;
19         }
20         xrand2 { arg exclude=0;
21                 var res;
22                 res = (2 * this).rand - this;
23                 if (res == exclude, { ^this },{ ^res });
24         }
25         degreeToKey { arg scale, stepsPerOctave = 12;
26                 ^scale.performDegreeToKey(this, stepsPerOctave)
27         }
29         // iteration
30         do { arg function;
31                 // iterates function from 0 to this-1
32                 // special byte codes inserted by compiler for this method
33                 var i = 0;
34                 while ({ i < this }, { function.value(i, i); i = i + 1; });
35         }
36         // override 'do'
37         generate { arg function; function.value(this) }
39         collectAs { arg function, class;
40                 var res = (class ? Array).new(this);
41                 this.do {|i| res.add(function.value(i)) }
42                 ^res;
43         }
45         collect { arg function;
46                 ^this.collectAs(function, Array)
47         }
49         reverseDo { arg function;
50                 // iterates function from 0 to this-1
51                 // special byte codes inserted by compiler for this method
52                 var i=0, j=0;
53                 i = this - 1;
54                 while ({ i >= 0 }, { function.value(i, j); i = i - 1; j = j + 1; });
55         }
56         for { arg endval, function;
57                 // iterates function from this to endval (inclusive)
58                 // special byte codes inserted by compiler for this method
59                 var i, j=0, stepval=1;
60                 i = this;
61                 while ({ i <= endval }, { function.value(i, j); i = i + 1; j = j + 1; });
62         }
63         forBy { arg endval, stepval, function;
64                 // iterates function from this to endval (inclusive) by step
65                 // special byte codes inserted by compiler for this method
66                 var i, j=0;
67                 i = this;
68                 while ({ i <= endval }, { function.value(i, j); i = i + stepval; j = j + 1; });
69         }
71         to { arg hi, step=1;
72                 ^Interval.new(this, hi, step)
73         }
75         // conversions to Char
76         asAscii {
77                 // must be 0 <= this <= 255
78                 _AsAscii
79                 ^this.primitiveFailed
80         }
81         asUnicode { ^this }
82         asDigit {
83                 // must be 0 <= this <= 35
84                 _AsDigit
85                 ^this.primitiveFailed
86         }
87         asBinaryDigits { arg numDigits = 8;
88                 var array;
89                 array = Array.new(numDigits);
90                 numDigits.do({ arg i;
91                         array.addFirst(this >> i & 1)
92                 });
93                 ^array
94         }
95         asDigits { arg base=10, numDigits;
96                 var array, num = this;
97                 numDigits = numDigits ?? { (this.log / base.log + 1e-10).asInteger + 1 };
98                 array = Array.new(numDigits);
99                 numDigits.do {
100                         array = array.addFirst(num % base);
101                         num = num div: base
102                 }
103                 ^array
104         }
106         nextPowerOfTwo { _NextPowerOfTwo }
107         isPowerOfTwo { _IsPowerOfTwo }
108         leadingZeroes { _CLZ }
109         trailingZeroes { _CTZ }
110         numBits { _NumBits }
111         log2Ceil { _Log2Ceil }
112         grayCode { _BinaryGrayCode }
113         setBit { arg bitNumber, bool = true; _SetBit ^this.primitiveFailed }
115         nthPrime { _NthPrime }
116         prevPrime { _PrevPrime }
117         nextPrime { _NextPrime }
118         indexOfPrime { _IndexOfPrime }
120         isPrime {
121                 _IsPrime
122                 /*
123                 var sqrtThis;
124                 if ( this <= 2, {
125                         if (this == 2, { ^true }, { ^false });
126                 });
127                 sqrtThis = this.sqrt.asInteger;
128                 256.do({ arg i; var p;
129                         p = i.nthPrime;
130                         if (this % p == 0, { ^false });
131                         if (p >= sqrtThis, { ^true });
132                 });
133                 ^nil
134                 */
135         }
137         // exit the program and return the result code to unix shell
138         exit { _Exit }
140         asStringToBase { | base=10, width=8 |
141                 var rest = this, string, mask;
142                 if (base.inclusivelyBetween(2, 36).not) {
143                         base = clip(base, 2, 36);
144                         warn(thisMethod + ": base not between 2 and 36");
145                 };
146                 string = String.newClear(width);
147                 if (base.isPowerOfTwo) {
148                         mask = base - 1;
149                         base = base.trailingZeroes;
150                         width.do { | i |
151                                 string.put(width-i-1, (rest & mask).asDigit);
152                                 rest = rest >> base;
153                         };
154                 } {
155                         width.do { | i |
156                                 string.put(width-i-1, (rest mod: base).asDigit);
157                                 rest = rest div: base;
158                         };
159                 };
160                 ^string
161         }
163         asBinaryString { | width=8 |
164                 ^this.asStringToBase(2, width)
165         }
167         asHexString { | width=8 |
168                 ^this.asStringToBase(16, width)
169         }
171         asIPString {
172             ^((this >> 24) & 255).asString ++ "." ++
173                 ((this >> 16) & 255).asString ++ "." ++
174                 ((this >> 8) & 255).asString ++ "." ++
175                 (this & 255).asString
176         }
178         archiveAsCompileString { ^true }
180         geom { arg start, grow;
181                 ^Array.geom(this, start, grow);
182         }
183         fib { arg a=0.0, b=1.0;
184                 ^Array.fib(this, a, b);
185         }
187         factors {
188                 var num, array, prime;
189                 if(this <= 1) { ^[] }; // no prime factors exist below the first prime
190                 num = this.abs;
191                 // there are 6542 16 bit primes from 2 to 65521
192                 6542.do {|i|
193                         prime = i.nthPrime;
194                         while { (num mod: prime) == 0 }{
195                                 array = array.add(prime);
196                                 num = num div: prime;
197                                 if (num == 1) {^array}
198                         };
199                         if (prime.squared > num) {
200                                 array = array.add(num);
201                                 ^array
202                         };
203                 };
204                 // because Integer is 32 bit, and we have tested all 16 bit primes,
205                 // any remaining number must be a prime.
206                 array = array.add(num);
207                 ^array
208         }
210         pidRunning { _PidRunning; ^this.primitiveFailed }
212         factorial {
213                 ^#[1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600]
214                         @ this.max(0)
215                         ?? { Error("integer resolution too low for this factorial:" + this).throw };
216                 /*var   product = 1;
217                 if(this <= 1) { ^1 } {
218                         this.do { |x| product = product * (x+1) };
219                         ^product
220                 }*/
221         }
223                 // support for modifiers keys
224         isCaps { ^this & 65536 == 65536}
225         isShift { ^this & 131072 == 131072 }
226         isCtrl { ^this & 262144 == 262144 }
227         isAlt { ^this & 524288 == 524288 }
228         isCmd { ^this & 1048576 == 1048576 }
229         isNumPad { ^this & 2097152 == 2097152 }
230         isHelp { ^this & 4194304 == 4194304 }
231         isFun { ^this & 8388608 == 8388608 }