1 /*
2     SuperCollider real time audio synthesis system
3     Copyright (c) 2002 James McCartney. All rights reserved.
4     http://www.audiosynth.com
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program; if not, write to the Free Software
18     Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301  USA
19 */
20 /*
21 
22 Primitives for some bit operations.
23 
24 */
25 
26 #include "PyrPrimitive.h"
27 #include "VMGlobals.h"
28 #include "clz.h"
29 
30 
31 int prNumBits(VMGlobals* g, int numArgsPushed);
prNumBits(VMGlobals * g,int numArgsPushed)32 int prNumBits(VMGlobals* g, int numArgsPushed) {
33     PyrSlot* a = g->sp;
34     SetRaw(a, NUMBITS(slotRawInt(a)));
35     return errNone;
36 }
37 
38 int prLog2Ceil(VMGlobals* g, int numArgsPushed);
prLog2Ceil(VMGlobals * g,int numArgsPushed)39 int prLog2Ceil(VMGlobals* g, int numArgsPushed) {
40     PyrSlot* a = g->sp;
41     SetRaw(a, LOG2CEIL(slotRawInt(a)));
42     return errNone;
43 }
44 
45 int prCLZ(VMGlobals* g, int numArgsPushed);
prCLZ(VMGlobals * g,int numArgsPushed)46 int prCLZ(VMGlobals* g, int numArgsPushed) {
47     PyrSlot* a = g->sp;
48     SetRaw(a, CLZ(slotRawInt(a)));
49     return errNone;
50 }
51 
52 int prCTZ(VMGlobals* g, int numArgsPushed);
prCTZ(VMGlobals * g,int numArgsPushed)53 int prCTZ(VMGlobals* g, int numArgsPushed) {
54     PyrSlot* a = g->sp;
55     SetRaw(a, CTZ(slotRawInt(a)));
56     return errNone;
57 }
58 
59 int prNextPowerOfTwo(VMGlobals* g, int numArgsPushed);
prNextPowerOfTwo(VMGlobals * g,int numArgsPushed)60 int prNextPowerOfTwo(VMGlobals* g, int numArgsPushed) {
61     PyrSlot* a;
62 
63     a = g->sp;
64 
65     SetRaw(a, NEXTPOWEROFTWO(slotRawInt(a)));
66     return errNone;
67 }
68 
69 int prIsPowerOfTwo(VMGlobals* g, int numArgsPushed);
prIsPowerOfTwo(VMGlobals * g,int numArgsPushed)70 int prIsPowerOfTwo(VMGlobals* g, int numArgsPushed) {
71     PyrSlot* a = g->sp;
72     SetBool(a, ISPOWEROFTWO(slotRawInt(a)));
73     return errNone;
74 }
75 
76 int prBinaryGrayCode(VMGlobals* g, int numArgsPushed);
prBinaryGrayCode(VMGlobals * g,int numArgsPushed)77 int prBinaryGrayCode(VMGlobals* g, int numArgsPushed) {
78     PyrSlot* a;
79 
80     a = g->sp;
81     SetRaw(a, GRAYCODE(slotRawInt(a)));
82     return errNone;
83 }
84 
85 int prSetBit(VMGlobals* g, int numArgsPushed);
prSetBit(VMGlobals * g,int numArgsPushed)86 int prSetBit(VMGlobals* g, int numArgsPushed) {
87     PyrSlot* a = g->sp - 2;
88     PyrSlot* b = g->sp - 1;
89     PyrSlot* c = g->sp;
90 
91     int32 bit, mask;
92     int err = slotIntVal(b, &bit);
93     if (err)
94         return err;
95     bit = bit & 31;
96     mask = 1L << bit;
97     if (IsFalse(c)) {
98         SetRaw(a, slotRawInt(a) & ~mask);
99     } else {
100         SetRaw(a, slotRawInt(a) | mask);
101     }
102     return errNone;
103 }
104 
105 int prHammingDistance(VMGlobals* g, int numArgsPushed);
prHammingDistance(VMGlobals * g,int numArgsPushed)106 int prHammingDistance(VMGlobals* g, int numArgsPushed) {
107     PyrSlot* a = g->sp - 1;
108     PyrSlot* b = g->sp;
109 
110     if (NotInt(a) || NotInt(b))
111         return errWrongType;
112 
113     int aInt = slotRawInt(a);
114     int bInt = slotRawInt(b);
115 
116     int count = 0, mask = 1;
117     for (int i = 0; i < 32; i++) {
118         if ((aInt & mask) != (bInt & mask))
119             count = count + 1;
120         mask = mask << 1;
121     }
122     SetRaw(a, count);
123 
124     return errNone;
125 }
126 
127 void initBitPrimitives();
initBitPrimitives()128 void initBitPrimitives() {
129     int base, index = 0;
130 
131     base = nextPrimitiveIndex();
132 
133     definePrimitive(base, index++, "_NextPowerOfTwo", prNextPowerOfTwo, 1, 0);
134     definePrimitive(base, index++, "_IsPowerOfTwo", prIsPowerOfTwo, 1, 0);
135     definePrimitive(base, index++, "_CLZ", prCLZ, 1, 0);
136     definePrimitive(base, index++, "_CTZ", prCTZ, 1, 0);
137     definePrimitive(base, index++, "_NumBits", prNumBits, 1, 0);
138     definePrimitive(base, index++, "_Log2Ceil", prLog2Ceil, 1, 0);
139     definePrimitive(base, index++, "_SetBit", prSetBit, 3, 0);
140     definePrimitive(base, index++, "_BinaryGrayCode", prBinaryGrayCode, 1, 0);
141     definePrimitive(base, index++, "_HammingDistance", prHammingDistance, 2, 0);
142 }
143 
144 
145 #if _SC_PLUGINS_
146 
147 #    include "SCPlugin.h"
148 
149 // export the function that SC will call to load the plug in.
150 #    pragma export on
151 extern "C" {
152 SCPlugIn* loadPlugIn(void);
153 }
154 #    pragma export off
155 
156 
157 // define plug in object
158 class APlugIn : public SCPlugIn {
159 public:
160     APlugIn();
161     virtual ~APlugIn();
162 
163     virtual void AboutToCompile();
164 };
165 
APlugIn()166 APlugIn::APlugIn() {
167     // constructor for plug in
168 }
169 
~APlugIn()170 APlugIn::~APlugIn() {
171     // destructor for plug in
172 }
173 
AboutToCompile()174 void APlugIn::AboutToCompile() {
175     // this is called each time the class library is compiled.
176     initBitPrimitives();
177 }
178 
179 // This function is called when the plug in is loaded into SC.
180 // It returns an instance of APlugIn.
loadPlugIn()181 SCPlugIn* loadPlugIn() { return new APlugIn(); }
182 
183 #endif
184