bit-twiddle 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 6c88090274260692eb69445316299a13b3b63b89
4
- data.tar.gz: d5b7938cfeb8c8de999b052f4c08b59038f97bcf
2
+ SHA256:
3
+ metadata.gz: ea6d4c9db54e566dc5c8a45e8ab95a41fec390f45358092351967501a4248d9c
4
+ data.tar.gz: f25c14b7aaba7912a12e77e79f1ad4542d6f13d8ac36c2ef85a3f9bc83589908
5
5
  SHA512:
6
- metadata.gz: 4b13792ba786af66d85c982aab50165cdeabd8569f3927e9508732190f8cf3e9f2598d7ebbce2bfb68eb8f6de4c0af3f11cb627d9882802acbf2d03aa58ee73a
7
- data.tar.gz: f4e55b16fe4753d66ddf7e87b3d25692c6e8d5ed0331e6f2eee36122c3f35baba50194638532ac4cf0c5bbfa89452886fc522afdba3ed2421e55d16d61b2e7f3
6
+ metadata.gz: 276b6e1717614ef408cc52275612aa78cc3ef17fcb46d77771ff433d0cb6f26f976b30efcb97a9c1fabedd6fbeafa850edbce322e475db512d6d902d9adaefc2
7
+ data.tar.gz: ce967635d56d3b9425e6036a242cb87da2995a261b703b6c6024776df02a5c1dd30e68d74cc12c28bbbea7672cdd3851eb10af497b302e4ca4306f1fbc2653d2
data/LICENSE CHANGED
@@ -1,3 +1,3 @@
1
1
  The program code in the 'bit-twiddle' repository (currently available at https://github.com/alexdowad/bit-twiddle) has been placed in the public domain by its author. You can do anything you want with it, anything at all. You can copy it, sell it, buy it, lease it, rent it out, put it in pawn, or use it as a down payment on a new truck. You can sing it out in the shower, or on a crowded bus. You can even inscribe it on a silk flag, and plant it on Kilimanjaro's snow-covered slopes. The possibilities are endless!
2
2
 
3
- If you need a specific license, then make a copy of the code, solemnly declare that the copy belongs to you, and license it to yourself under any terms you desire.
3
+ If 'public domain' isn't what you like, then you can use this code under a CC0 (creative commons) license. Still no good? Drop the author a note and we'll see how to fix you up.
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
- #Fast bitwise operations for Ruby
1
+ Fast bitwise operations for Ruby
2
+ ================================
2
3
 
3
- Ruby has built-in implementations of the "workhorses" of bit manipulation: bitwise AND, OR, NOT, and XOR operations and bit shifts. This library adds more bitwise operations, which may be useful in implementing some algorithms. All the added operations are implemented in optimized C code (so this is MRI-only). All operations on integers are implemented for both `Fixnum`s and `Bignum`s.
4
+ Ruby has built-in implementations of the "workhorses" of bit manipulation: bitwise AND, OR, NOT, and XOR operations and bit shifts. This library adds more bitwise operations, which may be useful in implementing some algorithms. All the added operations are implemented in optimized C code (so this is MRI-only).
4
5
 
5
6
  Install this goodness with:
6
7
 
@@ -22,8 +23,6 @@ require "bit-twiddle/core_ext"
22
23
 
23
24
  In many cases, `bit-twiddle` operations explicitly work on the low 8, 16, 32, or 64 bits of an integer. (For example, it defines `#bitreverse8`, `#bitreverse16`, `#bitreverse32`, and `#bitreverse64` methods.) If an integer's bit width is larger than the number of bits operated on, the higher-end bits are passed through unchanged.
24
25
 
25
- All methods automatically convert between `Fixnum` and `Bignum` as is most appropriate to represent their result.
26
-
27
26
  ## Examples
28
27
 
29
28
  ### Population count
@@ -0,0 +1,266 @@
1
+
2
+ SHELL = /bin/sh
3
+
4
+ # V=0 quiet, V=1 verbose. other values don't work.
5
+ V = 0
6
+ Q1 = $(V:1=)
7
+ Q = $(Q1:0=@)
8
+ ECHO1 = $(V:1=@ :)
9
+ ECHO = $(ECHO1:0=@ echo)
10
+ NULLCMD = :
11
+
12
+ #### Start of system configuration section. ####
13
+
14
+ srcdir = .
15
+ topdir = /home/alex/.rbenv/versions/2.7.2/include/ruby-2.7.0
16
+ hdrdir = $(topdir)
17
+ arch_hdrdir = /home/alex/.rbenv/versions/2.7.2/include/ruby-2.7.0/x86_64-linux
18
+ PATH_SEPARATOR = :
19
+ VPATH = $(srcdir):$(arch_hdrdir)/ruby:$(hdrdir)/ruby
20
+ prefix = $(DESTDIR)/home/alex/.rbenv/versions/2.7.2
21
+ rubysitearchprefix = $(rubylibprefix)/$(sitearch)
22
+ rubyarchprefix = $(rubylibprefix)/$(arch)
23
+ rubylibprefix = $(libdir)/$(RUBY_BASE_NAME)
24
+ exec_prefix = $(prefix)
25
+ vendorarchhdrdir = $(vendorhdrdir)/$(sitearch)
26
+ sitearchhdrdir = $(sitehdrdir)/$(sitearch)
27
+ rubyarchhdrdir = $(rubyhdrdir)/$(arch)
28
+ vendorhdrdir = $(rubyhdrdir)/vendor_ruby
29
+ sitehdrdir = $(rubyhdrdir)/site_ruby
30
+ rubyhdrdir = $(includedir)/$(RUBY_VERSION_NAME)
31
+ vendorarchdir = $(vendorlibdir)/$(sitearch)
32
+ vendorlibdir = $(vendordir)/$(ruby_version)
33
+ vendordir = $(rubylibprefix)/vendor_ruby
34
+ sitearchdir = $(sitelibdir)/$(sitearch)
35
+ sitelibdir = $(sitedir)/$(ruby_version)
36
+ sitedir = $(rubylibprefix)/site_ruby
37
+ rubyarchdir = $(rubylibdir)/$(arch)
38
+ rubylibdir = $(rubylibprefix)/$(ruby_version)
39
+ sitearchincludedir = $(includedir)/$(sitearch)
40
+ archincludedir = $(includedir)/$(arch)
41
+ sitearchlibdir = $(libdir)/$(sitearch)
42
+ archlibdir = $(libdir)/$(arch)
43
+ ridir = $(datarootdir)/$(RI_BASE_NAME)
44
+ mandir = $(datarootdir)/man
45
+ localedir = $(datarootdir)/locale
46
+ libdir = $(exec_prefix)/lib
47
+ psdir = $(docdir)
48
+ pdfdir = $(docdir)
49
+ dvidir = $(docdir)
50
+ htmldir = $(docdir)
51
+ infodir = $(datarootdir)/info
52
+ docdir = $(datarootdir)/doc/$(PACKAGE)
53
+ oldincludedir = $(DESTDIR)/usr/include
54
+ includedir = $(prefix)/include
55
+ runstatedir = $(localstatedir)/run
56
+ localstatedir = $(prefix)/var
57
+ sharedstatedir = $(prefix)/com
58
+ sysconfdir = $(prefix)/etc
59
+ datadir = $(datarootdir)
60
+ datarootdir = $(prefix)/share
61
+ libexecdir = $(exec_prefix)/libexec
62
+ sbindir = $(exec_prefix)/sbin
63
+ bindir = $(exec_prefix)/bin
64
+ archdir = $(rubyarchdir)
65
+
66
+
67
+ CC_WRAPPER =
68
+ CC = gcc
69
+ CXX = g++
70
+ LIBRUBY = $(LIBRUBY_SO)
71
+ LIBRUBY_A = lib$(RUBY_SO_NAME)-static.a
72
+ LIBRUBYARG_SHARED = -Wl,-rpath,$(libdir) -L$(libdir) -l$(RUBY_SO_NAME)
73
+ LIBRUBYARG_STATIC = -Wl,-rpath,$(libdir) -L$(libdir) -l$(RUBY_SO_NAME)-static $(MAINLIBS)
74
+ empty =
75
+ OUTFLAG = -o $(empty)
76
+ COUTFLAG = -o $(empty)
77
+ CSRCFLAG = $(empty)
78
+
79
+ RUBY_EXTCONF_H =
80
+ cflags = $(optflags) $(debugflags) $(warnflags)
81
+ cxxflags =
82
+ optflags = -O3
83
+ debugflags = -ggdb3
84
+ warnflags = -Wall -Wextra -Wdeprecated-declarations -Wduplicated-cond -Wimplicit-function-declaration -Wimplicit-int -Wmisleading-indentation -Wpointer-arith -Wwrite-strings -Wimplicit-fallthrough=0 -Wmissing-noreturn -Wno-cast-function-type -Wno-constant-logical-operand -Wno-long-long -Wno-missing-field-initializers -Wno-overlength-strings -Wno-packed-bitfield-compat -Wno-parentheses-equality -Wno-self-assign -Wno-tautological-compare -Wno-unused-parameter -Wno-unused-value -Wsuggest-attribute=format -Wsuggest-attribute=noreturn -Wunused-variable
85
+ cppflags =
86
+ CCDLFLAGS = -fPIC
87
+ CFLAGS = $(CCDLFLAGS) $(cflags) -fPIC -Wall -Wno-unknown-warning-option -Wno-unknown-attributes -Wno-ignored-attributes -Werror -O3 -march=native -mtune=native -std=c99 -I./ruby23 $(ARCH_FLAG)
88
+ INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir)/ruby/backward -I$(hdrdir) -I$(srcdir)
89
+ DEFS =
90
+ CPPFLAGS = -DSIZEOF_SHORT=2 -DSIZEOF_INT=4 -DSIZEOF_LONG=8 -DSIZEOF_LONG_LONG=8 -DHAVE_TYPE_ULONG -DRSHIFT_IS_ARITH=1 -DHAVE_BSWAP16=1 -I/home/alex/.rbenv/versions/2.7.2/include $(DEFS) $(cppflags)
91
+ CXXFLAGS = $(CCDLFLAGS) -g -O2 $(ARCH_FLAG)
92
+ ldflags = -L. -L/home/alex/.rbenv/versions/2.7.2/lib -fstack-protector-strong -rdynamic -Wl,-export-dynamic
93
+ dldflags = -L/home/alex/.rbenv/versions/2.7.2/lib -Wl,--compress-debug-sections=zlib
94
+ ARCH_FLAG =
95
+ DLDFLAGS = $(ldflags) $(dldflags) $(ARCH_FLAG)
96
+ LDSHARED = $(CC) -shared
97
+ LDSHAREDXX = $(CXX) -shared
98
+ AR = ar
99
+ EXEEXT =
100
+
101
+ RUBY_INSTALL_NAME = $(RUBY_BASE_NAME)
102
+ RUBY_SO_NAME = ruby
103
+ RUBYW_INSTALL_NAME =
104
+ RUBY_VERSION_NAME = $(RUBY_BASE_NAME)-$(ruby_version)
105
+ RUBYW_BASE_NAME = rubyw
106
+ RUBY_BASE_NAME = ruby
107
+
108
+ arch = x86_64-linux
109
+ sitearch = $(arch)
110
+ ruby_version = 2.7.0
111
+ ruby = $(bindir)/$(RUBY_BASE_NAME)
112
+ RUBY = $(ruby)
113
+ ruby_headers = $(hdrdir)/ruby.h $(hdrdir)/ruby/backward.h $(hdrdir)/ruby/ruby.h $(hdrdir)/ruby/defines.h $(hdrdir)/ruby/missing.h $(hdrdir)/ruby/intern.h $(hdrdir)/ruby/st.h $(hdrdir)/ruby/subst.h $(arch_hdrdir)/ruby/config.h
114
+
115
+ RM = rm -f
116
+ RM_RF = $(RUBY) -run -e rm -- -rf
117
+ RMDIRS = rmdir --ignore-fail-on-non-empty -p
118
+ MAKEDIRS = /bin/mkdir -p
119
+ INSTALL = /usr/bin/install -c
120
+ INSTALL_PROG = $(INSTALL) -m 0755
121
+ INSTALL_DATA = $(INSTALL) -m 644
122
+ COPY = cp
123
+ TOUCH = exit >
124
+
125
+ #### End of system configuration section. ####
126
+
127
+ preload =
128
+ libpath = . $(libdir)
129
+ LIBPATH = -L. -L$(libdir) -Wl,-rpath,$(libdir)
130
+ DEFFILE =
131
+
132
+ CLEANFILES = mkmf.log
133
+ DISTCLEANFILES =
134
+ DISTCLEANDIRS =
135
+
136
+ extout =
137
+ extout_prefix =
138
+ target_prefix =
139
+ LOCAL_LIBS =
140
+ LIBS = $(LIBRUBYARG_SHARED) -lm -lc
141
+ ORIG_SRCS = bit_twiddle.c
142
+ SRCS = $(ORIG_SRCS)
143
+ OBJS = bit_twiddle.o
144
+ HDRS =
145
+ LOCAL_HDRS =
146
+ TARGET = bit_twiddle
147
+ TARGET_NAME = bit_twiddle
148
+ TARGET_ENTRY = Init_$(TARGET_NAME)
149
+ DLLIB = $(TARGET).so
150
+ EXTSTATIC =
151
+ STATIC_LIB =
152
+
153
+ TIMESTAMP_DIR = .
154
+ BINDIR = $(bindir)
155
+ RUBYCOMMONDIR = $(sitedir)$(target_prefix)
156
+ RUBYLIBDIR = $(sitelibdir)$(target_prefix)
157
+ RUBYARCHDIR = $(sitearchdir)$(target_prefix)
158
+ HDRDIR = $(rubyhdrdir)/ruby$(target_prefix)
159
+ ARCHHDRDIR = $(rubyhdrdir)/$(arch)/ruby$(target_prefix)
160
+ TARGET_SO_DIR =
161
+ TARGET_SO = $(TARGET_SO_DIR)$(DLLIB)
162
+ CLEANLIBS = $(TARGET_SO)
163
+ CLEANOBJS = *.o *.bak
164
+
165
+ all: $(DLLIB)
166
+ static: $(STATIC_LIB)
167
+ .PHONY: all install static install-so install-rb
168
+ .PHONY: clean clean-so clean-static clean-rb
169
+
170
+ clean-static::
171
+ clean-rb-default::
172
+ clean-rb::
173
+ clean-so::
174
+ clean: clean-so clean-static clean-rb-default clean-rb
175
+ -$(Q)$(RM) $(CLEANLIBS) $(CLEANOBJS) $(CLEANFILES) .*.time
176
+
177
+ distclean-rb-default::
178
+ distclean-rb::
179
+ distclean-so::
180
+ distclean-static::
181
+ distclean: clean distclean-so distclean-static distclean-rb-default distclean-rb
182
+ -$(Q)$(RM) Makefile $(RUBY_EXTCONF_H) conftest.* mkmf.log
183
+ -$(Q)$(RM) core ruby$(EXEEXT) *~ $(DISTCLEANFILES)
184
+ -$(Q)$(RMDIRS) $(DISTCLEANDIRS) 2> /dev/null || true
185
+
186
+ realclean: distclean
187
+ install: install-so install-rb
188
+
189
+ install-so: $(DLLIB) $(TIMESTAMP_DIR)/.sitearchdir.time
190
+ $(INSTALL_PROG) $(DLLIB) $(RUBYARCHDIR)
191
+ clean-static::
192
+ -$(Q)$(RM) $(STATIC_LIB)
193
+ install-rb: pre-install-rb do-install-rb install-rb-default
194
+ install-rb-default: pre-install-rb-default do-install-rb-default
195
+ pre-install-rb: Makefile
196
+ pre-install-rb-default: Makefile
197
+ do-install-rb:
198
+ do-install-rb-default:
199
+ pre-install-rb-default:
200
+ @$(NULLCMD)
201
+ $(TIMESTAMP_DIR)/.sitearchdir.time:
202
+ $(Q) $(MAKEDIRS) $(@D) $(RUBYARCHDIR)
203
+ $(Q) $(TOUCH) $@
204
+
205
+ site-install: site-install-so site-install-rb
206
+ site-install-so: install-so
207
+ site-install-rb: install-rb
208
+
209
+ .SUFFIXES: .c .m .cc .mm .cxx .cpp .o .S
210
+
211
+ .cc.o:
212
+ $(ECHO) compiling $(<)
213
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<
214
+
215
+ .cc.S:
216
+ $(ECHO) translating $(<)
217
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$<
218
+
219
+ .mm.o:
220
+ $(ECHO) compiling $(<)
221
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<
222
+
223
+ .mm.S:
224
+ $(ECHO) translating $(<)
225
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$<
226
+
227
+ .cxx.o:
228
+ $(ECHO) compiling $(<)
229
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<
230
+
231
+ .cxx.S:
232
+ $(ECHO) translating $(<)
233
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$<
234
+
235
+ .cpp.o:
236
+ $(ECHO) compiling $(<)
237
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<
238
+
239
+ .cpp.S:
240
+ $(ECHO) translating $(<)
241
+ $(Q) $(CXX) $(INCFLAGS) $(CPPFLAGS) $(CXXFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$<
242
+
243
+ .c.o:
244
+ $(ECHO) compiling $(<)
245
+ $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<
246
+
247
+ .c.S:
248
+ $(ECHO) translating $(<)
249
+ $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$<
250
+
251
+ .m.o:
252
+ $(ECHO) compiling $(<)
253
+ $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -c $(CSRCFLAG)$<
254
+
255
+ .m.S:
256
+ $(ECHO) translating $(<)
257
+ $(Q) $(CC) $(INCFLAGS) $(CPPFLAGS) $(CFLAGS) $(COUTFLAG)$@ -S $(CSRCFLAG)$<
258
+
259
+ $(TARGET_SO): $(OBJS) Makefile
260
+ $(ECHO) linking shared-object $(DLLIB)
261
+ -$(Q)$(RM) $(@)
262
+ $(Q) $(LDSHARED) -o $@ $(OBJS) $(LIBPATH) $(DLDFLAGS) $(LOCAL_LIBS) $(LIBS)
263
+
264
+
265
+
266
+ $(OBJS): $(HDRS) $(ruby_headers)
@@ -0,0 +1,1879 @@
1
+ /* Fast C implementation of additional bitwise operations for Ruby
2
+ * Hand-crafted with ♥ by Alex Dowad, using ONLY the finest 1s and 0s */
3
+
4
+ #include <ruby.h>
5
+ #include "bt_bignum.h"
6
+
7
+ #ifndef HAVE_TYPE_ULONG
8
+ typedef unsigned long ulong;
9
+ #endif
10
+ #ifndef HAVE_TYPE_UCHAR
11
+ typedef unsigned char uchar;
12
+ #endif
13
+
14
+ #define fix_zero LONG2FIX(0L)
15
+ #define BIGNUM_P(x) RB_TYPE_P((x), T_BIGNUM)
16
+
17
+ #if SIZEOF_BDIGIT == SIZEOF_LONG
18
+
19
+ #define popcount_bdigit __builtin_popcountl
20
+ #define ffs_bdigit __builtin_ffsl
21
+ #define clz_bdigit __builtin_clzl
22
+
23
+ #elif SIZEOF_BDIGIT == SIZEOF_INT
24
+
25
+ #define popcount_bdigit __builtin_popcount
26
+ #define ffs_bdigit __builtin_ffs
27
+ #define clz_bdigit __builtin_clz
28
+
29
+ #else
30
+ #error "What is the size of a Ruby Bignum digit on this platform???"
31
+ #endif
32
+
33
+ #if SIZEOF_BDIGIT < 4
34
+ #error "Sorry, Integer#bswap32 and Integer#arith_rshift32 will not work if sizeof(BDIGIT) < 4. Please report this error."
35
+ #elif SIZEOF_BDIGIT > 8
36
+ #error "Sorry, several methods will not work if sizeof(BDIGIT) > 8. Please report this error."
37
+ #elif SIZEOF_LONG > 8
38
+ #error "Sorry, Integer#arith_rshift64 will not work if sizeof(long) > 8. Please report this error."
39
+ #endif
40
+
41
+ #if HAVE_BSWAP16 == 0
42
+ /* stupid bug in GCC 4.7 */
43
+ static inline uint16_t __builtin_bswap16(uint16_t value)
44
+ {
45
+ return (value >> 8) | (value << 8);
46
+ }
47
+ #endif
48
+
49
+ static int
50
+ bnum_greater(VALUE bnum, BDIGIT value)
51
+ {
52
+ BDIGIT *digits = RBIGNUM_DIGITS(bnum);
53
+ size_t len = RBIGNUM_LEN(bnum);
54
+ if (*digits > value)
55
+ return 1;
56
+ while (--len)
57
+ if (*++digits > 0)
58
+ return 1;
59
+ return 0;
60
+ }
61
+
62
+ static long
63
+ value_to_shiftdist(VALUE shiftdist, unsigned int bits)
64
+ {
65
+ for (;;) {
66
+ if (FIXNUM_P(shiftdist)) {
67
+ return FIX2LONG(shiftdist);
68
+ } else if (BIGNUM_P(shiftdist)) {
69
+ long sdist;
70
+ if (bnum_greater(shiftdist, bits-1))
71
+ sdist = bits;
72
+ else
73
+ sdist = *RBIGNUM_DIGITS(shiftdist);
74
+ if (RBIGNUM_NEGATIVE_P(shiftdist))
75
+ sdist = -sdist;
76
+ return sdist;
77
+ } else {
78
+ shiftdist = rb_to_int(shiftdist);
79
+ }
80
+ }
81
+ }
82
+
83
+ /* 'mask' is 0x7 for 8, 0xF for 16, 0x1F for 32, 0x3F for 64
84
+ * return value is always positive! */
85
+ static ulong
86
+ value_to_rotdist(VALUE rotdist, long bits, long mask)
87
+ {
88
+ for (;;) {
89
+ long rdist;
90
+ if (FIXNUM_P(rotdist)) {
91
+ rdist = FIX2LONG(rotdist) % bits;
92
+ if (rdist < 0)
93
+ rdist += bits;
94
+ return (ulong)rdist;
95
+ } else if (BIGNUM_P(rotdist)) {
96
+ rdist = *RBIGNUM_DIGITS(rotdist) & mask;
97
+ if (RBIGNUM_NEGATIVE_P(rotdist))
98
+ rdist = bits - rdist;
99
+ return (ulong)rdist;
100
+ } else {
101
+ rotdist = rb_to_int(rotdist);
102
+ }
103
+ }
104
+ }
105
+
106
+ static void
107
+ store_64_into_bnum(VALUE bnum, uint64_t int64)
108
+ {
109
+ BDIGIT *dest = RBIGNUM_DIGITS(bnum);
110
+ size_t len = RBIGNUM_LEN(bnum);
111
+
112
+ #if (SIZEOF_BDIGIT == 8)
113
+ *dest = int64;
114
+ #else
115
+ if (len > 1) {
116
+ *dest = (uint32_t)int64;
117
+ *(dest+1) = (uint32_t)(int64 >> 32);
118
+ } else if ((int64 & (0xFFFFFFFFULL << 32)) == 0) {
119
+ /* the high 4 bytes are zero anyways */
120
+ *dest = (uint32_t)int64;
121
+ } else {
122
+ rb_big_resize(bnum, 2);
123
+ dest = RBIGNUM_DIGITS(bnum); /* may have moved */
124
+ *dest = (uint32_t)int64;
125
+ *(dest+1) = (uint32_t)(int64 >> 32);
126
+ }
127
+ #endif
128
+ }
129
+
130
+ static uint64_t
131
+ load_64_from_bignum(VALUE bnum)
132
+ {
133
+ BDIGIT *src = RBIGNUM_DIGITS(bnum);
134
+ size_t len = RBIGNUM_LEN(bnum);
135
+ uint64_t result = *src;
136
+
137
+ if (SIZEOF_BDIGIT == 4 && len > 1)
138
+ result += ((uint64_t)*(src+1)) << 32;
139
+
140
+ return result;
141
+ }
142
+
143
+ static VALUE
144
+ modify_lo8_in_bignum(VALUE bnum, uint8_t lo8)
145
+ {
146
+ VALUE result;
147
+
148
+ if (lo8 == (uint8_t)*RBIGNUM_DIGITS(bnum))
149
+ return bnum;
150
+
151
+ result = rb_big_clone(bnum);
152
+ *RBIGNUM_DIGITS(result) = (*RBIGNUM_DIGITS(bnum) & ~0xFFL) | lo8;
153
+ return result;
154
+ }
155
+
156
+ static VALUE
157
+ modify_lo16_in_bignum(VALUE bnum, uint16_t lo16)
158
+ {
159
+ VALUE result;
160
+
161
+ if (lo16 == (uint16_t)*RBIGNUM_DIGITS(bnum))
162
+ return bnum;
163
+
164
+ result = rb_big_clone(bnum);
165
+ *RBIGNUM_DIGITS(result) = (*RBIGNUM_DIGITS(bnum) & ~0xFFFFL) | lo16;
166
+ return result;
167
+ }
168
+
169
+ static VALUE
170
+ modify_lo32_in_bignum(VALUE bnum, uint32_t lo32)
171
+ {
172
+ BDIGIT value;
173
+ VALUE result;
174
+
175
+ if (lo32 == (uint32_t)*RBIGNUM_DIGITS(bnum))
176
+ return bnum;
177
+
178
+ if (SIZEOF_BDIGIT == 4)
179
+ value = lo32;
180
+ else
181
+ value = (*RBIGNUM_DIGITS(bnum) & ~0xFFFFFFFFL) | lo32;
182
+
183
+ #if SIZEOF_LONG == 4
184
+ /* if a 'long' is only 4 bytes, a 32-bit number could be promoted to Bignum
185
+ * then modifying the low 32 bits could make it fixable again */
186
+ if (RBIGNUM_LEN(bnum) == 1 && FIXABLE(value))
187
+ return LONG2FIX(value);
188
+ #endif
189
+
190
+ result = rb_big_clone(bnum);
191
+ *RBIGNUM_DIGITS(result) = value;
192
+ return result;
193
+ }
194
+
195
+ static VALUE
196
+ modify_lo64_in_bignum(VALUE bnum, uint64_t lo64)
197
+ {
198
+ VALUE result;
199
+
200
+ if (RBIGNUM_LEN(bnum) <= (8/SIZEOF_BDIGIT)) {
201
+ if (RBIGNUM_POSITIVE_P(bnum)) {
202
+ if (POSFIXABLE(lo64))
203
+ return LONG2FIX((long)lo64);
204
+ } else if (lo64 <= -FIXNUM_MIN) {
205
+ return LONG2FIX(-(long)lo64);
206
+ }
207
+ }
208
+
209
+ result = rb_big_clone(bnum);
210
+ store_64_into_bnum(result, lo64);
211
+ return result;
212
+ }
213
+
214
+ /* Now start defining implementations of actual Ruby methods
215
+ * First two helper macros: */
216
+ #define def_int_method(name) \
217
+ static VALUE int_ ## name(VALUE integer) { \
218
+ if (FIXNUM_P(integer)) \
219
+ return fnum_ ## name(integer); \
220
+ else \
221
+ return bnum_ ## name(integer); \
222
+ }
223
+ #define def_int_method_with_arg(name) \
224
+ static VALUE int_ ## name(VALUE integer, VALUE arg) { \
225
+ if (FIXNUM_P(integer)) \
226
+ return fnum_ ## name(integer, arg); \
227
+ else \
228
+ return bnum_ ## name(integer, arg); \
229
+ }
230
+
231
+ static VALUE
232
+ fnum_popcount(VALUE fnum)
233
+ {
234
+ long value = FIX2LONG(fnum);
235
+ if (value < 0)
236
+ rb_raise(rb_eRangeError, "can't take popcount of a negative number");
237
+ return LONG2FIX(__builtin_popcountl((ulong)value));
238
+ }
239
+
240
+ static VALUE
241
+ bnum_popcount(VALUE bnum)
242
+ {
243
+ BDIGIT *digits = RBIGNUM_DIGITS(bnum);
244
+ size_t length = RBIGNUM_LEN(bnum);
245
+ long bits = 0;
246
+
247
+ if (RBIGNUM_NEGATIVE_P(bnum))
248
+ rb_raise(rb_eRangeError, "can't take popcount of a negative number");
249
+
250
+ while (length--) {
251
+ bits += popcount_bdigit(*digits);
252
+ digits++;
253
+ }
254
+
255
+ return LONG2FIX(bits);
256
+ }
257
+
258
+ /* Document-method: Integer#popcount
259
+ * Return the number of 1 bits in this integer.
260
+ *
261
+ * If the receiver is negative, raise `RangeError`.
262
+ *
263
+ * @example
264
+ * 7.popcount # => 3
265
+ * 255.popcount # => 8
266
+ * @return [Integer]
267
+ */
268
+ def_int_method(popcount);
269
+
270
+ /* Return the number of 1 bits in all the bytes of this `String`.
271
+ * @example
272
+ * "abc".popcount # => 10
273
+ * @return [Integer]
274
+ */
275
+ static VALUE
276
+ str_popcount(VALUE str)
277
+ {
278
+ uchar *p = (uchar*)RSTRING_PTR(str);
279
+ long length = RSTRING_LEN(str);
280
+ long bits = 0;
281
+
282
+ /* This could be made faster by processing 4/8 bytes at a time */
283
+
284
+ while (length--)
285
+ bits += __builtin_popcount(*p++);
286
+
287
+ return LONG2FIX(bits);
288
+ }
289
+
290
+ static VALUE
291
+ fnum_lo_bit(VALUE fnum)
292
+ {
293
+ /* We raise an error on a negative number because the internal representation
294
+ * used for negative numbers is different between Fixnum and Bignum, so the
295
+ * results would not be consistent (running a program on a different computer,
296
+ * or with a Ruby interpreter compiled by a different compiler, could yield
297
+ * different results.)
298
+ * The alternative would be to _pretend_ that both Fixnums/Bignums use 2's
299
+ * complement notation and compute the answer accordingly.
300
+ * I don't think it's worth the trouble! */
301
+ long value = FIX2LONG(fnum);
302
+ if (value < 0)
303
+ rb_raise(rb_eRangeError, "can't find lowest 1 bit in a negative number");
304
+ return LONG2FIX(__builtin_ffsl(value));
305
+ }
306
+
307
+ static VALUE
308
+ bnum_lo_bit(VALUE bnum)
309
+ {
310
+ BDIGIT *digit = RBIGNUM_DIGITS(bnum);
311
+ long bits = 0;
312
+
313
+ if (RBIGNUM_NEGATIVE_P(bnum))
314
+ rb_raise(rb_eRangeError, "can't find lowest 1 bit in a negative number");
315
+
316
+ while (!*digit) {
317
+ digit++;
318
+ bits += (sizeof(BDIGIT) * 8);
319
+ }
320
+
321
+ bits += ffs_bdigit(*digit);
322
+ return LONG2FIX(bits);
323
+ }
324
+
325
+ /* Document-method: Integer#lo_bit
326
+ * Return the index of the lowest 1 bit, where the least-significant bit is index 1.
327
+ * If the receiver is 0, return 0.
328
+ *
329
+ * If the receiver is negative, raise `RangeError`.
330
+ *
331
+ * @example
332
+ * 1.lo_bit # => 1
333
+ * 128.lo_bit # => 8
334
+ * @return [Integer]
335
+ */
336
+ def_int_method(lo_bit);
337
+
338
+ static VALUE
339
+ fnum_hi_bit(VALUE fnum)
340
+ {
341
+ long value = FIX2LONG(fnum);
342
+ if (value == 0)
343
+ return fix_zero;
344
+ else if (value < 0)
345
+ rb_raise(rb_eRangeError, "can't find highest 1 bit in a negative number");
346
+ return LONG2FIX((sizeof(long) * 8) - __builtin_clzl(value));
347
+ }
348
+
349
+ static VALUE
350
+ bnum_hi_bit(VALUE bnum)
351
+ {
352
+ BDIGIT *digit = RBIGNUM_DIGITS(bnum) + (RBIGNUM_LEN(bnum)-1);
353
+ ulong bits = (sizeof(BDIGIT) * 8) * RBIGNUM_LEN(bnum);
354
+
355
+ if (RBIGNUM_NEGATIVE_P(bnum))
356
+ rb_raise(rb_eRangeError, "can't find highest 1 bit in a negative number");
357
+
358
+ while (!*digit) {
359
+ digit--;
360
+ bits -= (sizeof(BDIGIT) * 8);
361
+ }
362
+
363
+ bits -= clz_bdigit(*digit);
364
+ return LONG2FIX(bits);
365
+ }
366
+
367
+ /* Document-method: Integer#hi_bit
368
+ * Return the index of the highest 1 bit, where the least-significant bit is index 1.
369
+ * If the receiver is 0, return 0.
370
+ *
371
+ * If the receiver is negative, raise `RangeError`.
372
+ *
373
+ * @example
374
+ * 1.hi_bit # => 1
375
+ * 255.hi_bit # => 8
376
+ * @return [Integer]
377
+ */
378
+ def_int_method(hi_bit);
379
+
380
+ static VALUE
381
+ fnum_bswap16(VALUE fnum)
382
+ {
383
+ long value = FIX2LONG(fnum);
384
+ if (value < 0)
385
+ rb_raise(rb_eRangeError, "can't swap bytes in a negative number");
386
+ return LONG2FIX(((ulong)value & ~0xFFFFUL) | __builtin_bswap16((uint16_t)value));
387
+ }
388
+
389
+ static VALUE
390
+ bnum_bswap16(VALUE bnum)
391
+ {
392
+ if (RBIGNUM_POSITIVE_P(bnum))
393
+ return modify_lo16_in_bignum(bnum, __builtin_bswap16((uint16_t)*RBIGNUM_DIGITS(bnum)));
394
+ else
395
+ rb_raise(rb_eRangeError, "can't swap bytes in a negative number");
396
+ }
397
+
398
+ /* Document-method: Integer#bswap16
399
+ * Reverse the least-significant and second least-significant bytes of this integer.
400
+ *
401
+ * If the receiver is negative, raise `RangeError`.
402
+ *
403
+ * @example
404
+ * 0xFF00.bswap16 # => 255
405
+ * 0x00FF.bswap16 # => 65280
406
+ * @return [Integer]
407
+ */
408
+ def_int_method(bswap16);
409
+
410
+ static VALUE
411
+ fnum_bswap32(VALUE fnum)
412
+ {
413
+ long value = FIX2LONG(fnum);
414
+ if (value < 0)
415
+ rb_raise(rb_eRangeError, "can't swap bytes in a negative number");
416
+
417
+ if (SIZEOF_LONG == 4)
418
+ /* the size of a Fixnum is always the same as 'long'
419
+ * and the C standard guarantees 'long' is at least 32 bits
420
+ * but a couple bits are used for tagging, so the usable precision could
421
+ * be less than 32 bits...
422
+ * That is why we have to use a '2NUM' function, not '2FIX' */
423
+ return ULONG2NUM(__builtin_bswap32(FIX2LONG(fnum)));
424
+ else
425
+ return LONG2FIX(((ulong)value & ~0xFFFFFFFFUL) | __builtin_bswap32((uint32_t)value));
426
+ }
427
+
428
+ static VALUE
429
+ bnum_bswap32(VALUE bnum)
430
+ {
431
+ if (RBIGNUM_POSITIVE_P(bnum))
432
+ return modify_lo32_in_bignum(bnum, __builtin_bswap32(*RBIGNUM_DIGITS(bnum)));
433
+ else
434
+ rb_raise(rb_eRangeError, "can't swap bytes in a negative number");
435
+ }
436
+
437
+ /* Document-method: Integer#bswap32
438
+ * Reverse the least-significant 4 bytes of this integer.
439
+ *
440
+ * Does not reverse bits within each byte. This can be used to swap endianness
441
+ * of a 32-bit integer. If the receiver is negative, raise `RangeError`.
442
+ *
443
+ * @example
444
+ * 0xaabbccdd.bswap32.to_s(16) # => "ddccbbaa"
445
+ *
446
+ * @return [Integer]
447
+ */
448
+ def_int_method(bswap32);
449
+
450
+ static VALUE
451
+ fnum_bswap64(VALUE fnum)
452
+ {
453
+ long value = FIX2LONG(fnum);
454
+ if (value < 0)
455
+ rb_raise(rb_eRangeError, "can't swap bytes in a negative number");
456
+ return ULL2NUM(__builtin_bswap64((uint64_t)value));
457
+ }
458
+
459
+ static VALUE
460
+ bnum_bswap64(VALUE bnum)
461
+ {
462
+ if (RBIGNUM_POSITIVE_P(bnum))
463
+ return modify_lo64_in_bignum(bnum, __builtin_bswap64(load_64_from_bignum(bnum)));
464
+ else
465
+ rb_raise(rb_eRangeError, "can't swap bytes in a negative number");
466
+ }
467
+
468
+ /* Document-method: Integer#bswap64
469
+ * Reverse the least-significant 8 bytes of this integer.
470
+ *
471
+ * Does not reverse bits within each byte. This can be used to swap endianness
472
+ * of a 64-bit integer. If the receiver is negative, raise `RangeError`.
473
+ *
474
+ * @example
475
+ * 0xaabbccdd.bswap64.to_s(16) # => "ddccbbaa00000000"
476
+ *
477
+ * @return [Integer]
478
+ */
479
+ def_int_method(bswap64);
480
+
481
+ #define def_rot_helpers(bits) \
482
+ static inline uint##bits##_t rrot##bits(uint##bits##_t value, VALUE rotdist) { \
483
+ ulong rotd = value_to_rotdist(rotdist, bits, bits-1); \
484
+ return (value >> rotd) | (value << (-rotd & (bits-1))); \
485
+ } \
486
+ static inline uint##bits##_t lrot##bits(uint##bits##_t value, VALUE rotdist) { \
487
+ ulong rotd = value_to_rotdist(rotdist, bits, bits-1); \
488
+ return (value << rotd) | (value >> (-rotd & (bits-1))); \
489
+ }
490
+
491
+ def_rot_helpers(8);
492
+ def_rot_helpers(16);
493
+ def_rot_helpers(32);
494
+ def_rot_helpers(64);
495
+
496
+ static VALUE
497
+ fnum_rrot8(VALUE fnum, VALUE rotdist)
498
+ {
499
+ long value = FIX2LONG(fnum);
500
+ return LONG2FIX(((ulong)value & ~0xFFUL) | rrot8((uint8_t)value, rotdist));
501
+ }
502
+
503
+ static VALUE
504
+ bnum_rrot8(VALUE bnum, VALUE rotdist)
505
+ {
506
+ return modify_lo8_in_bignum(bnum, rrot8((uint8_t)*RBIGNUM_DIGITS(bnum), rotdist));
507
+ }
508
+
509
+ /* Document-method: Integer#rrot8
510
+ * Right-rotation ("circular shift") of the low 8 bits in this integer.
511
+ *
512
+ * If the rotate distance is negative, the bit rotation will be to the left
513
+ * instead.
514
+ *
515
+ * @example
516
+ * 0b01110001.rrot8(1).to_s(2) # => "10111000"
517
+ * 0b01110001.rrot8(3).to_s(2) # => "101110"
518
+ *
519
+ * @param rotdist [Integer] Number of bit positions to rotate by
520
+ * @return [Integer]
521
+ */
522
+ def_int_method_with_arg(rrot8);
523
+
524
+ static VALUE
525
+ fnum_rrot16(VALUE fnum, VALUE rotdist)
526
+ {
527
+ long value = FIX2LONG(fnum);
528
+ return LONG2FIX(((ulong)value & ~0xFFFFUL) | rrot16((uint16_t)value, rotdist));
529
+ }
530
+
531
+ static VALUE
532
+ bnum_rrot16(VALUE bnum, VALUE rotdist)
533
+ {
534
+ return modify_lo16_in_bignum(bnum, rrot16((uint16_t)*RBIGNUM_DIGITS(bnum), rotdist));
535
+ }
536
+
537
+ /* Document-method: Integer#rrot16
538
+ * Right-rotation ("circular shift") of the low 16 bits in this integer.
539
+ *
540
+ * If the rotate distance is negative, the bit rotation will be to the left
541
+ * instead.
542
+ *
543
+ * @example
544
+ * 0b0111000101110001.rrot16(1).to_s(2) # => "1011100010111000"
545
+ * 0b0111000101110001.rrot16(3).to_s(2) # => "10111000101110"
546
+ *
547
+ * @param rotdist [Integer] Number of bit positions to rotate by
548
+ * @return [Integer]
549
+ */
550
+ def_int_method_with_arg(rrot16);
551
+
552
+ static VALUE
553
+ fnum_rrot32(VALUE fnum, VALUE rotdist)
554
+ {
555
+ long value = FIX2LONG(fnum);
556
+ if (SIZEOF_LONG == 8)
557
+ return LONG2FIX(((ulong)value & ~0xFFFFFFFFUL) | rrot32((uint32_t)value, rotdist));
558
+ else
559
+ return ULONG2NUM(rrot32((uint32_t)value, rotdist));
560
+ }
561
+
562
+ static VALUE
563
+ bnum_rrot32(VALUE bnum, VALUE rotdist)
564
+ {
565
+ return modify_lo32_in_bignum(bnum, rrot32((uint32_t)*RBIGNUM_DIGITS(bnum), rotdist));
566
+ }
567
+
568
+ /* Document-method: Integer#rrot32
569
+ * Right-rotation ("circular shift") of the low 32 bits in this integer.
570
+ *
571
+ * If the rotate distance is negative, the bit rotation will be to the left
572
+ * instead.
573
+ *
574
+ * @example
575
+ * 0xaabbccdd.rrot32(4).to_s(16) # => "daabbccd"
576
+ *
577
+ * @param rotdist [Integer] Number of bit positions to rotate by
578
+ * @return [Integer]
579
+ */
580
+ def_int_method_with_arg(rrot32);
581
+
582
+ static VALUE
583
+ fnum_rrot64(VALUE fnum, VALUE rotdist)
584
+ {
585
+ return ULL2NUM(rrot64(FIX2ULONG(fnum), rotdist));
586
+ }
587
+
588
+ static VALUE
589
+ bnum_rrot64(VALUE bnum, VALUE rotdist)
590
+ {
591
+ return modify_lo64_in_bignum(bnum, rrot64(load_64_from_bignum(bnum), rotdist));
592
+ }
593
+
594
+ /* Document-method: Integer#rrot64
595
+ * Right-rotation ("circular shift") of the low 64 bits in this integer.
596
+ *
597
+ * If the rotate distance is negative, the bit rotation will be to the left
598
+ * instead.
599
+ *
600
+ * @example
601
+ * 0x11223344aabbccdd.rrot64(4).to_s(16) # => "d11223344aabbccd"
602
+ *
603
+ * @param rotdist [Integer] Number of bit positions to rotate by
604
+ * @return [Integer]
605
+ */
606
+ def_int_method_with_arg(rrot64);
607
+
608
+ static VALUE
609
+ fnum_lrot8(VALUE fnum, VALUE rotdist)
610
+ {
611
+ long value = FIX2LONG(fnum);
612
+ return LONG2FIX(((ulong)value & ~0xFFUL) | lrot8((uint8_t)value, rotdist));
613
+ }
614
+
615
+ static VALUE
616
+ bnum_lrot8(VALUE bnum, VALUE rotdist)
617
+ {
618
+ return modify_lo8_in_bignum(bnum, lrot8((uint8_t)*RBIGNUM_DIGITS(bnum), rotdist));
619
+ }
620
+
621
+ /* Document-method: Integer#lrot8
622
+ * Left-rotation ("circular shift") of the low 8 bits in this integer.
623
+ *
624
+ * If the rotate distance is negative, the bit rotation will be to the right
625
+ * instead.
626
+ *
627
+ * @example
628
+ * 0b01110001.lrot8(1).to_s(2) # => "11100010"
629
+ * 0b01110001.lrot8(3).to_s(2) # => "10001011"
630
+ *
631
+ * @param rotdist [Integer] Number of bit positions to rotate by
632
+ * @return [Integer]
633
+ */
634
+ def_int_method_with_arg(lrot8);
635
+
636
+ static VALUE
637
+ fnum_lrot16(VALUE fnum, VALUE rotdist)
638
+ {
639
+ long value = FIX2LONG(fnum);
640
+ return LONG2FIX(((ulong)value & ~0xFFFFUL) | lrot16((uint16_t)value, rotdist));
641
+ }
642
+
643
+ static VALUE
644
+ bnum_lrot16(VALUE bnum, VALUE rotdist)
645
+ {
646
+ return modify_lo16_in_bignum(bnum, lrot16((uint16_t)*RBIGNUM_DIGITS(bnum), rotdist));
647
+ }
648
+
649
+ /* Document-method: Integer#lrot16
650
+ * Left-rotation ("circular shift") of the low 16 bits in this integer.
651
+ *
652
+ * If the rotate distance is negative, the bit rotation will be to the right
653
+ * instead.
654
+ *
655
+ * @example
656
+ * 0b0111000101110001.lrot16(1).to_s(2) # => "1110001011100010"
657
+ * 0b0111000101110001.lrot16(3).to_s(2) # => "1000101110001011"
658
+ *
659
+ * @param rotdist [Integer] Number of bit positions to rotate by
660
+ * @return [Integer]
661
+ */
662
+ def_int_method_with_arg(lrot16);
663
+
664
+ static VALUE
665
+ fnum_lrot32(VALUE fnum, VALUE rotdist)
666
+ {
667
+ long value = FIX2LONG(fnum);
668
+ return LONG2FIX(((ulong)value & ~0xFFFFFFFFUL) | lrot32((uint32_t)value, rotdist));
669
+ }
670
+
671
+ static VALUE
672
+ bnum_lrot32(VALUE bnum, VALUE rotdist)
673
+ {
674
+ return modify_lo32_in_bignum(bnum, lrot32((uint32_t)*RBIGNUM_DIGITS(bnum), rotdist));
675
+ }
676
+
677
+ /* Document-method: Integer#lrot32
678
+ * Left-rotation ("circular shift") of the low 32 bits in this integer.
679
+ *
680
+ * If the rotate distance is negative, the bit rotation will be to the right
681
+ * instead.
682
+ *
683
+ * @example
684
+ * 0xaabbccdd.lrot32(4).to_s(16) # => "abbccdda"
685
+ *
686
+ * @param rotdist [Integer] Number of bit positions to rotate by
687
+ * @return [Integer]
688
+ */
689
+ def_int_method_with_arg(lrot32);
690
+
691
+ static VALUE
692
+ fnum_lrot64(VALUE fnum, VALUE rotdist)
693
+ {
694
+ return ULL2NUM(lrot64(FIX2ULONG(fnum), rotdist));
695
+ }
696
+
697
+ static VALUE
698
+ bnum_lrot64(VALUE bnum, VALUE rotdist)
699
+ {
700
+ return modify_lo64_in_bignum(bnum, lrot64(load_64_from_bignum(bnum), rotdist));
701
+ }
702
+
703
+ /* Document-method: Integer#lrot64
704
+ * Left-rotation ("circular shift") of the low 64 bits in this integer.
705
+ *
706
+ * If the rotate distance is negative, the bit rotation will be to the right
707
+ * instead.
708
+ *
709
+ * @example
710
+ * 0x11223344aabbccdd.lrot64(4).to_s(16) # => "1223344aabbccdd1"
711
+ *
712
+ * @param rotdist [Integer] Number of bit positions to rotate by
713
+ * @return [Integer]
714
+ */
715
+ def_int_method_with_arg(lrot64);
716
+
717
+ #define def_shift_helpers(bits) \
718
+ static uint##bits##_t lshift##bits(uint##bits##_t value, VALUE shiftdist) { \
719
+ long sdist = value_to_shiftdist(shiftdist, bits); \
720
+ if (sdist >= bits || sdist <= -bits) return 0; \
721
+ else if (sdist < 0) return value >> ((uint)-sdist); \
722
+ else return value << (uint)sdist; \
723
+ } \
724
+ static uint##bits##_t rshift##bits(uint##bits##_t value, VALUE shiftdist) { \
725
+ long sdist = value_to_shiftdist(shiftdist, bits); \
726
+ if (sdist >= bits || sdist <= -bits) return 0; \
727
+ else if (sdist < 0) return value << ((uint)-sdist); \
728
+ else return value >> (uint)sdist; \
729
+ } \
730
+ static uint##bits##_t arith_rshift##bits(uint##bits##_t value, VALUE shiftdist) { \
731
+ long sdist = value_to_shiftdist(shiftdist, bits); \
732
+ if (sdist >= bits) { \
733
+ if ((((uint##bits##_t)1 << (bits - 1)) & value) != 0) \
734
+ return ~0; \
735
+ else \
736
+ return 0; \
737
+ } else if (sdist <= -bits) { \
738
+ return 0; \
739
+ } else if (sdist < 0) { \
740
+ return value << ((uint)-sdist); \
741
+ } else if (RSHIFT_IS_ARITH) { \
742
+ return (int##bits##_t)value >> (int)sdist; \
743
+ } else if ((((uint##bits##_t)1 << (bits - 1)) & value) != 0) { \
744
+ return (value >> sdist) | ~(((uint##bits##_t)~0) >> sdist); \
745
+ } else { \
746
+ return value >> sdist; \
747
+ } \
748
+ }
749
+
750
+ def_shift_helpers(8);
751
+ def_shift_helpers(16);
752
+ def_shift_helpers(32);
753
+ def_shift_helpers(64);
754
+
755
+ static VALUE
756
+ fnum_lshift8(VALUE fnum, VALUE shiftdist)
757
+ {
758
+ long value = FIX2LONG(fnum);
759
+ if (shiftdist == fix_zero)
760
+ return fnum;
761
+ else
762
+ return LONG2FIX(((ulong)value & ~0xFFUL) | lshift8((uint8_t)value, shiftdist));
763
+ }
764
+
765
+ static VALUE
766
+ bnum_lshift8(VALUE bnum, VALUE shiftdist)
767
+ {
768
+ if (shiftdist == fix_zero)
769
+ return bnum;
770
+ else
771
+ return modify_lo8_in_bignum(bnum, lshift8((uint8_t)*RBIGNUM_DIGITS(bnum), shiftdist));
772
+ }
773
+
774
+ /* Document-method: Integer#lshift8
775
+ * Left-shift of the low 8 bits in this integer.
776
+ *
777
+ * If the shift distance is negative, a right shift will be performed instead.
778
+ * The vacated bit positions will be filled with 0 bits. If shift distance is
779
+ * more than 7 or less than -7, the low 8 bits will all be zeroed.
780
+ *
781
+ * @example
782
+ * 0x11223344.lshift8(1).to_s(16) # => "11223388"
783
+ * 0x11223344.lshift8(2).to_s(16) # => "11223310"
784
+ *
785
+ * @param shiftdist [Integer] Number of bit positions to shift by
786
+ * @return [Integer]
787
+ */
788
+ def_int_method_with_arg(lshift8);
789
+
790
+ static VALUE
791
+ fnum_lshift16(VALUE fnum, VALUE shiftdist)
792
+ {
793
+ long value = FIX2LONG(fnum);
794
+ if (shiftdist == fix_zero)
795
+ return fnum;
796
+ else
797
+ return LONG2FIX(((ulong)value & ~0xFFFFUL) | lshift16((uint16_t)value, shiftdist));
798
+ }
799
+
800
+ static VALUE
801
+ bnum_lshift16(VALUE bnum, VALUE shiftdist)
802
+ {
803
+ if (shiftdist == fix_zero)
804
+ return bnum;
805
+ else
806
+ return modify_lo16_in_bignum(bnum, lshift16((uint16_t)*RBIGNUM_DIGITS(bnum), shiftdist));
807
+ }
808
+
809
+ /* Document-method: Integer#lshift16
810
+ * Left-shift of the low 16 bits in this integer.
811
+ *
812
+ * If the shift distance is negative, a right shift will be performed instead.
813
+ * The vacated bit positions will be filled with 0 bits. If shift distance is
814
+ * more than 15 or less than -15, the low 16 bits will all be zeroed.
815
+ *
816
+ * @example
817
+ * 0x11223344.lshift16(1).to_s(16) # => "11226688"
818
+ * 0x11223344.lshift16(2).to_s(16) # => "1122cd10"
819
+ *
820
+ * @param shiftdist [Integer] Number of bit positions to shift by
821
+ * @return [Integer]
822
+ */
823
+ def_int_method_with_arg(lshift16);
824
+
825
+ static VALUE
826
+ fnum_lshift32(VALUE fnum, VALUE shiftdist)
827
+ {
828
+ long value = FIX2LONG(fnum);
829
+ if (shiftdist == fix_zero)
830
+ return fnum;
831
+ else
832
+ return LONG2FIX(((ulong)value & ~0xFFFFFFFFUL) | lshift32((uint32_t)value, shiftdist));
833
+ }
834
+
835
+ static VALUE
836
+ bnum_lshift32(VALUE bnum, VALUE shiftdist)
837
+ {
838
+ if (shiftdist == fix_zero)
839
+ return bnum;
840
+ else
841
+ return modify_lo32_in_bignum(bnum, lshift32((uint32_t)*RBIGNUM_DIGITS(bnum), shiftdist));
842
+ }
843
+
844
+ /* Document-method: Integer#lshift32
845
+ * Left-shift of the low 32 bits in this integer.
846
+ *
847
+ * If the shift distance is negative, a right shift will be performed instead.
848
+ * The vacated bit positions will be filled with 0 bits. If shift distance is
849
+ * more than 31 or less than -31, the low 32 bits will all be zeroed.
850
+ *
851
+ * @example
852
+ * 0x11223344.lshift32(1).to_s(16) # => "22446688"
853
+ * 0x11223344.lshift32(2).to_s(16) # => "4488cd10"
854
+ *
855
+ * @param shiftdist [Integer] Number of bit positions to shift by
856
+ * @return [Integer]
857
+ */
858
+ def_int_method_with_arg(lshift32);
859
+
860
+ static VALUE
861
+ fnum_lshift64(VALUE fnum, VALUE shiftdist)
862
+ {
863
+ long sdist = value_to_shiftdist(shiftdist, 64);
864
+
865
+ if (sdist == 0)
866
+ return fnum;
867
+ else if (sdist >= 64 || sdist <= -64)
868
+ return fix_zero;
869
+ else if (sdist < 0)
870
+ return LONG2FIX(FIX2ULONG(fnum) >> ((ulong)-sdist));
871
+ else
872
+ return ULL2NUM(FIX2ULONG(fnum) << ((ulong)sdist));
873
+ }
874
+
875
+ static VALUE
876
+ bnum_lshift64(VALUE bnum, VALUE shiftdist)
877
+ {
878
+ if (shiftdist == fix_zero)
879
+ return bnum;
880
+ else
881
+ return modify_lo64_in_bignum(bnum, lshift64(load_64_from_bignum(bnum), shiftdist));
882
+ }
883
+
884
+ /* Document-method: Integer#lshift64
885
+ * Left-shift of the low 64 bits in this integer.
886
+ *
887
+ * If the shift distance is negative, a right shift will be performed instead.
888
+ * The vacated bit positions will be filled with 0 bits. If shift distance is
889
+ * more than 63 or less than -63, the low 64 bits will all be zeroed.
890
+ *
891
+ * @example
892
+ * 0x1122334411223344.lshift64(1).to_s(16) # => "2244668822446688"
893
+ * 0x1122334411223344.lshift64(2).to_s(16) # => "4488cd104488cd10"
894
+ *
895
+ * @param shiftdist [Integer] Number of bit positions to shift by
896
+ * @return [Integer]
897
+ */
898
+ def_int_method_with_arg(lshift64);
899
+
900
+ static VALUE
901
+ fnum_rshift8(VALUE fnum, VALUE shiftdist)
902
+ {
903
+ long value = FIX2LONG(fnum);
904
+ if (shiftdist == fix_zero)
905
+ return fnum;
906
+ else
907
+ return LONG2FIX(((ulong)value & ~0xFFUL) | rshift8((uint8_t)value, shiftdist));
908
+ }
909
+
910
+ static VALUE
911
+ bnum_rshift8(VALUE bnum, VALUE shiftdist)
912
+ {
913
+ if (shiftdist == fix_zero)
914
+ return bnum;
915
+ else
916
+ return modify_lo8_in_bignum(bnum, rshift8((uint8_t)*RBIGNUM_DIGITS(bnum), shiftdist));
917
+ }
918
+
919
+ /* Document-method: Integer#rshift8
920
+ * Right-shift of the low 8 bits in this integer.
921
+ *
922
+ * If the shift distance is negative, a left shift will be performed instead.
923
+ * The vacated bit positions will be filled with 0 bits. If shift distance is
924
+ * more than 7 or less than -7, the low 8 bits will all be zeroed.
925
+ *
926
+ * @example
927
+ * 0x11223344.rshift8(1).to_s(16) # => "11223322"
928
+ * 0x11223344.rshift8(2).to_s(16) # => "11223311"
929
+ *
930
+ * @param shiftdist [Integer] Number of bit positions to shift by
931
+ * @return [Integer]
932
+ */
933
+ def_int_method_with_arg(rshift8);
934
+
935
+ static VALUE
936
+ fnum_rshift16(VALUE fnum, VALUE shiftdist)
937
+ {
938
+ long value = FIX2LONG(fnum);
939
+ if (shiftdist == fix_zero)
940
+ return fnum;
941
+ else
942
+ return LONG2FIX(((ulong)value & ~0xFFFFUL) | rshift16((uint16_t)value, shiftdist));
943
+ }
944
+
945
+ static VALUE
946
+ bnum_rshift16(VALUE bnum, VALUE shiftdist)
947
+ {
948
+ if (shiftdist == fix_zero)
949
+ return bnum;
950
+ else
951
+ return modify_lo16_in_bignum(bnum, rshift16((uint16_t)*RBIGNUM_DIGITS(bnum), shiftdist));
952
+ }
953
+
954
+ /* Document-method: Integer#rshift16
955
+ * Right-shift of the low 16 bits in this integer.
956
+ *
957
+ * If the shift distance is negative, a left shift will be performed instead.
958
+ * The vacated bit positions will be filled with 0 bits. If shift distance is
959
+ * more than 15 or less than -15, the low 16 bits will all be zeroed.
960
+ *
961
+ * @example
962
+ * 0x11223344.rshift16(1).to_s(16) # => "112219a2"
963
+ * 0x11223344.rshift16(2).to_s(16) # => "11220cd1"
964
+ *
965
+ * @param shiftdist [Integer] Number of bit positions to shift by
966
+ * @return [Integer]
967
+ */
968
+ def_int_method_with_arg(rshift16);
969
+
970
+ static VALUE
971
+ fnum_rshift32(VALUE fnum, VALUE shiftdist)
972
+ {
973
+ long value = FIX2LONG(fnum);
974
+ if (shiftdist == fix_zero)
975
+ return fnum;
976
+ else
977
+ return LONG2FIX(((ulong)value & ~0xFFFFFFFFUL) | rshift32((uint32_t)value, shiftdist));
978
+ }
979
+
980
+ static VALUE
981
+ bnum_rshift32(VALUE bnum, VALUE shiftdist)
982
+ {
983
+ if (shiftdist == fix_zero)
984
+ return bnum;
985
+ else
986
+ return modify_lo32_in_bignum(bnum, rshift32(*RBIGNUM_DIGITS(bnum), shiftdist));
987
+ }
988
+
989
+ /* Document-method: Integer#rshift32
990
+ * Right-shift of the low 32 bits in this integer.
991
+ *
992
+ * If the shift distance is negative, a left shift will be performed instead.
993
+ * The vacated bit positions will be filled with 0 bits. If shift distance is
994
+ * more than 31 or less than -31, the low 32 bits will all be zeroed.
995
+ *
996
+ * @example
997
+ * 0x11223344.rshift32(1).to_s(16) # => "89119a2"
998
+ * 0x11223344.rshift32(2).to_s(16) # => "4488cd1"
999
+ *
1000
+ * @param shiftdist [Integer] Number of bit positions to shift by
1001
+ * @return [Integer]
1002
+ */
1003
+ def_int_method_with_arg(rshift32);
1004
+
1005
+ static VALUE
1006
+ fnum_rshift64(VALUE fnum, VALUE shiftdist)
1007
+ {
1008
+ long sdist = value_to_shiftdist(shiftdist, 64);
1009
+
1010
+ if (sdist == 0)
1011
+ return fnum;
1012
+ else if (sdist >= 64 || sdist <= -64)
1013
+ return fix_zero;
1014
+ else if (sdist < 0)
1015
+ return ULL2NUM(FIX2ULONG(fnum) << ((ulong)-sdist));
1016
+ else
1017
+ return LONG2FIX(FIX2ULONG(fnum) >> ((ulong)sdist));
1018
+ }
1019
+
1020
+ static VALUE
1021
+ bnum_rshift64(VALUE bnum, VALUE shiftdist)
1022
+ {
1023
+ if (shiftdist == fix_zero)
1024
+ return bnum;
1025
+ else
1026
+ return modify_lo64_in_bignum(bnum, rshift64(load_64_from_bignum(bnum), shiftdist));
1027
+ }
1028
+
1029
+ /* Document-method: Integer#rshift64
1030
+ * Right-shift of the low 64 bits in this integer.
1031
+ *
1032
+ * If the shift distance is negative, a left shift will be performed instead.
1033
+ * The vacated bit positions will be filled with 0 bits. If shift distance is
1034
+ * more than 63 or less than -63, the low 64 bits will all be zeroed.
1035
+ *
1036
+ * @example
1037
+ * 0x1122334411223344.rshift64(1).to_s(16) # => "89119a2089119a2"
1038
+ * 0x1122334411223344.rshift64(2).to_s(16) # => "4488cd104488cd1"
1039
+ *
1040
+ * @param shiftdist [Integer] Number of bit positions to shift by
1041
+ * @return [Integer]
1042
+ */
1043
+ def_int_method_with_arg(rshift64);
1044
+
1045
+ static VALUE
1046
+ fnum_arith_rshift8(VALUE fnum, VALUE shiftdist)
1047
+ {
1048
+ long value = FIX2LONG(fnum);
1049
+ if (shiftdist == fix_zero)
1050
+ return fnum;
1051
+ else
1052
+ return LONG2FIX(((ulong)value & ~0xFFUL) | arith_rshift8((uint8_t)value, shiftdist));
1053
+ }
1054
+
1055
+ static VALUE
1056
+ bnum_arith_rshift8(VALUE bnum, VALUE shiftdist)
1057
+ {
1058
+ if (shiftdist == fix_zero)
1059
+ return bnum;
1060
+ else
1061
+ return modify_lo8_in_bignum(bnum, arith_rshift8((uint8_t)*RBIGNUM_DIGITS(bnum), shiftdist));
1062
+ }
1063
+
1064
+ /* Document-method: Integer#arith_rshift8
1065
+ * Arithmetic right-shift of the low 8 bits in this integer.
1066
+ *
1067
+ * If bit 8 is a 1, the vacated bit positions will be filled with 1s. Otherwise,
1068
+ * they will be filled with 0s. Or, if the shift distance is negative, a left shift
1069
+ * will be performed instead, and the vacated bit positions will be filled with 0s.
1070
+ *
1071
+ * @example
1072
+ * 0xaabbccdd.arith_rshift8(1).to_s(16) # => "aabbccee"
1073
+ * 0xaabbccdd.arith_rshift8(2).to_s(16) # => "aabbccf7"
1074
+ *
1075
+ * @param shiftdist [Integer] Number of bit positions to shift by
1076
+ * @return [Integer]
1077
+ */
1078
+ def_int_method_with_arg(arith_rshift8);
1079
+
1080
+ static VALUE
1081
+ fnum_arith_rshift16(VALUE fnum, VALUE shiftdist)
1082
+ {
1083
+ long value = FIX2LONG(fnum);
1084
+ if (shiftdist == fix_zero)
1085
+ return fnum;
1086
+ else
1087
+ return LONG2FIX(((ulong)value & ~0xFFFFUL) | arith_rshift16((uint16_t)value, shiftdist));
1088
+ }
1089
+
1090
+ static VALUE
1091
+ bnum_arith_rshift16(VALUE bnum, VALUE shiftdist)
1092
+ {
1093
+ if (shiftdist == fix_zero)
1094
+ return bnum;
1095
+ else
1096
+ return modify_lo16_in_bignum(bnum, arith_rshift16((uint16_t)*RBIGNUM_DIGITS(bnum), shiftdist));
1097
+ }
1098
+
1099
+ /* Document-method: Integer#arith_rshift16
1100
+ * Arithmetic right-shift of the low 16 bits in this integer.
1101
+ *
1102
+ * If bit 16 is a 1, the vacated bit positions will be filled with 1s. Otherwise,
1103
+ * they will be filled with 0s. Or, if the shift distance is negative, a left shift
1104
+ * will be performed instead, and the vacated bit positions will be filled with 0s.
1105
+ *
1106
+ * @example
1107
+ * 0xaabbccdd.arith_rshift16(1).to_s(16) # => "aabbe66e"
1108
+ * 0xaabbccdd.arith_rshift16(2).to_s(16) # => "aabbf337"
1109
+ *
1110
+ * @param shiftdist [Integer] Number of bit positions to shift by
1111
+ * @return [Integer]
1112
+ */
1113
+ def_int_method_with_arg(arith_rshift16);
1114
+
1115
+ static VALUE
1116
+ fnum_arith_rshift32(VALUE fnum, VALUE shiftdist)
1117
+ {
1118
+ long value = FIX2LONG(fnum);
1119
+ if (shiftdist == fix_zero)
1120
+ return fnum;
1121
+ else
1122
+ return LONG2FIX(((ulong)value & ~0xFFFFFFFFUL) | arith_rshift32((uint32_t)value, shiftdist));
1123
+ }
1124
+
1125
+ static VALUE
1126
+ bnum_arith_rshift32(VALUE bnum, VALUE shiftdist)
1127
+ {
1128
+ if (shiftdist == fix_zero)
1129
+ return bnum;
1130
+ else
1131
+ return modify_lo32_in_bignum(bnum, arith_rshift32(*RBIGNUM_DIGITS(bnum), shiftdist));
1132
+ }
1133
+
1134
+ /* Document-method: Integer#arith_rshift32
1135
+ * Arithmetic right-shift of the low 32 bits in this integer.
1136
+ *
1137
+ * If bit 32 is a 1, the vacated bit positions will be filled with 1s. Otherwise,
1138
+ * they will be filled with 0s. Or, if the shift distance is negative, a left shift
1139
+ * will be performed instead, and the vacated bit positions will be filled with 0s.
1140
+ *
1141
+ * @example
1142
+ * 0xaabbccddaabbccdd.arith_rshift32(1).to_s(16) # => "d55de66e"
1143
+ * 0xaabbccddaabbccdd.arith_rshift32(2).to_s(16) # => "eaaef337"
1144
+ *
1145
+ * @param shiftdist [Integer] Number of bit positions to shift by
1146
+ * @return [Integer]
1147
+ */
1148
+ def_int_method_with_arg(arith_rshift32);
1149
+
1150
+ static VALUE
1151
+ fnum_arith_rshift64(VALUE fnum, VALUE shiftdist)
1152
+ {
1153
+ if (shiftdist == fix_zero)
1154
+ return fnum;
1155
+ else
1156
+ return ULONG2NUM(arith_rshift64((uint64_t)FIX2LONG(fnum), shiftdist));
1157
+ }
1158
+
1159
+ static VALUE
1160
+ bnum_arith_rshift64(VALUE bnum, VALUE shiftdist)
1161
+ {
1162
+ if (shiftdist == fix_zero)
1163
+ return bnum;
1164
+ else
1165
+ return modify_lo64_in_bignum(bnum, arith_rshift64(load_64_from_bignum(bnum), shiftdist));
1166
+ }
1167
+
1168
+ /* Document-method: Integer#arith_rshift64
1169
+ * Arithmetic right-shift of the low 64 bits in this integer.
1170
+ *
1171
+ * If bit 64 is a 1, the vacated bit positions will be filled with 1s. Otherwise,
1172
+ * they will be filled with 0s. Or, if the shift distance is negative, a left shift
1173
+ * will be performed instead, and the vacated bit positions will be filled with 0s.
1174
+ *
1175
+ * @example
1176
+ * 0xaabbccddaabbccdd.arith_rshift64(1).to_s(16) # => "d55de66ed55de66e"
1177
+ * 0xaabbccddaabbccdd.arith_rshift64(2).to_s(16) # => "eaaef3376aaef337"
1178
+ *
1179
+ * @param shiftdist [Integer] Number of bit positions to shift by
1180
+ * @return [Integer]
1181
+ */
1182
+ def_int_method_with_arg(arith_rshift64);
1183
+
1184
+ static const uint8_t bitreverse_table[] =
1185
+ {
1186
+ 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
1187
+ 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
1188
+ 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
1189
+ 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
1190
+ 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
1191
+ 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
1192
+ 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
1193
+ 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
1194
+ 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
1195
+ 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
1196
+ 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
1197
+ 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
1198
+ 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
1199
+ 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
1200
+ 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
1201
+ 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
1202
+ };
1203
+
1204
+ static inline uint8_t reverse8(uint8_t value)
1205
+ {
1206
+ if (SIZEOF_LONG == 8)
1207
+ /* 64-bit CPU
1208
+ * Thanks to the Bit Twiddling Hacks page:
1209
+ * http://graphics.stanford.edu/~seander/bithacks.html */
1210
+ return (uint8_t)((value * 0x0202020202UL & 0x010884422010UL) % 1023);
1211
+ else
1212
+ /* 32-bit CPU */
1213
+ return bitreverse_table[value];
1214
+ }
1215
+
1216
+ static inline uint16_t reverse16(uint16_t value)
1217
+ {
1218
+ return (uint16_t)(bitreverse_table[value & 0xFF] << 8) | bitreverse_table[value >> 8];
1219
+ }
1220
+
1221
+ static inline uint32_t reverse32(uint32_t value)
1222
+ {
1223
+ return ((uint32_t)reverse16((uint16_t)value) << 16) | reverse16(value >> 16);
1224
+ }
1225
+
1226
+ static inline uint64_t reverse64(uint64_t value)
1227
+ {
1228
+ return ((uint64_t)reverse32((uint32_t)value) << 32) | reverse32(value >> 32);
1229
+ }
1230
+
1231
+ static VALUE
1232
+ fnum_bitreverse8(VALUE fnum)
1233
+ {
1234
+ long value = FIX2LONG(fnum);
1235
+ if (value < 0)
1236
+ rb_raise(rb_eRangeError, "can't reverse bits in a negative number");
1237
+ return LONG2FIX((value & ~0xFFL) | reverse8((uint8_t)value));
1238
+ }
1239
+
1240
+ static VALUE
1241
+ bnum_bitreverse8(VALUE bnum)
1242
+ {
1243
+ if (RBIGNUM_NEGATIVE_P(bnum))
1244
+ rb_raise(rb_eRangeError, "can't reverse bits in a negative number");
1245
+ return modify_lo8_in_bignum(bnum, reverse8((uint8_t)*RBIGNUM_DIGITS(bnum)));
1246
+ }
1247
+
1248
+ /* Document-method: Integer#bitreverse8
1249
+ * Reverse the low 8 bits in this integer.
1250
+ *
1251
+ * If the receiver is negative, raise `RangeError`.
1252
+ *
1253
+ * @example
1254
+ * 0b01101011.bitreverse8.to_s(2) # => "11010110"
1255
+ *
1256
+ * @return [Integer]
1257
+ */
1258
+ def_int_method(bitreverse8);
1259
+
1260
+ static VALUE
1261
+ fnum_bitreverse16(VALUE fnum)
1262
+ {
1263
+ long value = FIX2LONG(fnum);
1264
+ if (value < 0)
1265
+ rb_raise(rb_eRangeError, "can't reverse bits in a negative number");
1266
+ return LONG2FIX((value & ~0xFFFFL) | reverse16((uint16_t)value));
1267
+ }
1268
+
1269
+ static VALUE
1270
+ bnum_bitreverse16(VALUE bnum)
1271
+ {
1272
+ if (RBIGNUM_NEGATIVE_P(bnum))
1273
+ rb_raise(rb_eRangeError, "can't reverse bits in a negative number");
1274
+ return modify_lo16_in_bignum(bnum, reverse16((uint16_t)*RBIGNUM_DIGITS(bnum)));
1275
+ }
1276
+
1277
+ /* Document-method: Integer#bitreverse16
1278
+ * Reverse the low 16 bits in this integer.
1279
+ *
1280
+ * If the receiver is negative, raise `RangeError`.
1281
+ *
1282
+ * @example
1283
+ * 0b0110101100001011.bitreverse16.to_s(2) # => "1101000011010110"
1284
+ *
1285
+ * @return [Integer]
1286
+ */
1287
+ def_int_method(bitreverse16);
1288
+
1289
+ static VALUE
1290
+ fnum_bitreverse32(VALUE fnum)
1291
+ {
1292
+ long value = FIX2LONG(fnum);
1293
+ uint32_t lo32 = (uint32_t)value;
1294
+ if (value < 0)
1295
+ rb_raise(rb_eRangeError, "can't reverse bits in a negative number");
1296
+ else if (SIZEOF_LONG == 4)
1297
+ return ULONG2NUM(reverse32(lo32));
1298
+ else
1299
+ return LONG2FIX((value & ~0xFFFFFFFFL) | reverse32(lo32));
1300
+ }
1301
+
1302
+ static VALUE
1303
+ bnum_bitreverse32(VALUE bnum)
1304
+ {
1305
+ if (RBIGNUM_NEGATIVE_P(bnum))
1306
+ rb_raise(rb_eRangeError, "can't reverse bits in a negative number");
1307
+ return modify_lo32_in_bignum(bnum, reverse32(*RBIGNUM_DIGITS(bnum)));
1308
+ }
1309
+
1310
+ /* Document-method: Integer#bitreverse32
1311
+ * Reverse the low 32 bits in this integer.
1312
+ *
1313
+ * If the receiver is negative, raise `RangeError`.
1314
+ *
1315
+ * @example
1316
+ * 0x12341234.bitreverse32.to_s(16) # => "2c482c48"
1317
+ *
1318
+ * @return [Integer]
1319
+ */
1320
+ def_int_method(bitreverse32);
1321
+
1322
+ static VALUE
1323
+ fnum_bitreverse64(VALUE fnum)
1324
+ {
1325
+ long value = FIX2LONG(fnum);
1326
+ if (value < 0)
1327
+ rb_raise(rb_eRangeError, "can't reverse bits in a negative number");
1328
+ return ULL2NUM(reverse64((uint64_t)value));
1329
+ }
1330
+
1331
+ static VALUE
1332
+ bnum_bitreverse64(VALUE bnum)
1333
+ {
1334
+ if (RBIGNUM_NEGATIVE_P(bnum))
1335
+ rb_raise(rb_eRangeError, "can't reverse bits in a negative number");
1336
+ return modify_lo64_in_bignum(bnum, reverse64(load_64_from_bignum(bnum)));
1337
+ }
1338
+
1339
+ /* Document-method: Integer#bitreverse64
1340
+ * Reverse the low 64 bits in this integer.
1341
+ *
1342
+ * If the receiver is negative, raise `RangeError`.
1343
+ *
1344
+ * @example
1345
+ * 0xabcd1234abcd1234.bitreverse64.to_s(16) # => "2c48b3d52c48b3d5"
1346
+ *
1347
+ * @return [Integer]
1348
+ */
1349
+ def_int_method(bitreverse64);
1350
+
1351
+ /* Document-class: Integer
1352
+ * Ruby's good old Integer.
1353
+ *
1354
+ * `require "bit-twiddle/core_ext"` before trying to use any of the below methods.
1355
+ */
1356
+ /* Document-class: String
1357
+ * Ruby's good old String.
1358
+ *
1359
+ * `require "bit-twiddle/core_ext"` before trying to use any of the below methods.
1360
+ */
1361
+
1362
+ /* Add all `bit-twiddle` methods directly to `Integer`. */
1363
+ static void init_core_extensions()
1364
+ {
1365
+ rb_define_method(rb_cInteger, "popcount", int_popcount, 0);
1366
+ rb_define_method(rb_cString, "popcount", str_popcount, 0);
1367
+
1368
+ rb_define_method(rb_cInteger, "lo_bit", int_lo_bit, 0);
1369
+ rb_define_method(rb_cInteger, "hi_bit", int_hi_bit, 0);
1370
+
1371
+ rb_define_method(rb_cInteger, "bswap16", int_bswap16, 0);
1372
+ rb_define_method(rb_cInteger, "bswap32", int_bswap32, 0);
1373
+ rb_define_method(rb_cInteger, "bswap64", int_bswap64, 0);
1374
+
1375
+ rb_define_method(rb_cInteger, "rrot8", int_rrot8, 1);
1376
+ rb_define_method(rb_cInteger, "rrot16", int_rrot16, 1);
1377
+ rb_define_method(rb_cInteger, "rrot32", int_rrot32, 1);
1378
+ rb_define_method(rb_cInteger, "rrot64", int_rrot64, 1);
1379
+
1380
+ rb_define_method(rb_cInteger, "lrot8", int_lrot8, 1);
1381
+ rb_define_method(rb_cInteger, "lrot16", int_lrot16, 1);
1382
+ rb_define_method(rb_cInteger, "lrot32", int_lrot32, 1);
1383
+ rb_define_method(rb_cInteger, "lrot64", int_lrot64, 1);
1384
+
1385
+ rb_define_method(rb_cInteger, "lshift8", int_lshift8, 1);
1386
+ rb_define_method(rb_cInteger, "lshift16", int_lshift16, 1);
1387
+ rb_define_method(rb_cInteger, "lshift32", int_lshift32, 1);
1388
+ rb_define_method(rb_cInteger, "lshift64", int_lshift64, 1);
1389
+
1390
+ rb_define_method(rb_cInteger, "rshift8", int_rshift8, 1);
1391
+ rb_define_method(rb_cInteger, "rshift16", int_rshift16, 1);
1392
+ rb_define_method(rb_cInteger, "rshift32", int_rshift32, 1);
1393
+ rb_define_method(rb_cInteger, "rshift64", int_rshift64, 1);
1394
+
1395
+ rb_define_method(rb_cInteger, "arith_rshift8", int_arith_rshift8, 1);
1396
+ rb_define_method(rb_cInteger, "arith_rshift16", int_arith_rshift16, 1);
1397
+ rb_define_method(rb_cInteger, "arith_rshift32", int_arith_rshift32, 1);
1398
+ rb_define_method(rb_cInteger, "arith_rshift64", int_arith_rshift64, 1);
1399
+
1400
+ rb_define_method(rb_cInteger, "bitreverse8", int_bitreverse8, 0);
1401
+ rb_define_method(rb_cInteger, "bitreverse16", int_bitreverse16, 0);
1402
+ rb_define_method(rb_cInteger, "bitreverse32", int_bitreverse32, 0);
1403
+ rb_define_method(rb_cInteger, "bitreverse64", int_bitreverse64, 0);
1404
+ }
1405
+
1406
+ static VALUE
1407
+ bt_add_core_extensions(VALUE self)
1408
+ {
1409
+ /* this is so Yardoc can find method definitions */
1410
+ init_core_extensions();
1411
+ return Qnil;
1412
+ }
1413
+
1414
+ /* Wrapper functions are used for methods on BitTwiddle module */
1415
+ #define def_wrapper(name) \
1416
+ static VALUE bt_ ## name(VALUE self, VALUE num) \
1417
+ { \
1418
+ retry: \
1419
+ switch (TYPE(num)) { \
1420
+ case T_FIXNUM: return fnum_ ## name(num); \
1421
+ case T_BIGNUM: return bnum_ ## name(num); \
1422
+ default: num = rb_to_int(num); goto retry; \
1423
+ } \
1424
+ }
1425
+ #define def_wrapper_with_arg(name) \
1426
+ static VALUE bt_ ## name(VALUE self, VALUE num, VALUE arg) \
1427
+ { \
1428
+ retry: \
1429
+ switch (TYPE(num)) { \
1430
+ case T_FIXNUM: return fnum_ ## name(num, arg); \
1431
+ case T_BIGNUM: return bnum_ ## name(num, arg); \
1432
+ default: num = rb_to_int(num); goto retry; \
1433
+ } \
1434
+ }
1435
+
1436
+ def_wrapper(popcount);
1437
+ def_wrapper(lo_bit);
1438
+ def_wrapper(hi_bit);
1439
+ def_wrapper(bswap16);
1440
+ def_wrapper(bswap32);
1441
+ def_wrapper(bswap64);
1442
+ def_wrapper_with_arg(lrot8);
1443
+ def_wrapper_with_arg(lrot16);
1444
+ def_wrapper_with_arg(lrot32);
1445
+ def_wrapper_with_arg(lrot64);
1446
+ def_wrapper_with_arg(rrot8);
1447
+ def_wrapper_with_arg(rrot16);
1448
+ def_wrapper_with_arg(rrot32);
1449
+ def_wrapper_with_arg(rrot64);
1450
+ def_wrapper_with_arg(lshift8);
1451
+ def_wrapper_with_arg(lshift16);
1452
+ def_wrapper_with_arg(lshift32);
1453
+ def_wrapper_with_arg(lshift64);
1454
+ def_wrapper_with_arg(rshift8);
1455
+ def_wrapper_with_arg(rshift16);
1456
+ def_wrapper_with_arg(rshift32);
1457
+ def_wrapper_with_arg(rshift64);
1458
+ def_wrapper_with_arg(arith_rshift8);
1459
+ def_wrapper_with_arg(arith_rshift16);
1460
+ def_wrapper_with_arg(arith_rshift32);
1461
+ def_wrapper_with_arg(arith_rshift64);
1462
+ def_wrapper(bitreverse8);
1463
+ def_wrapper(bitreverse16);
1464
+ def_wrapper(bitreverse32);
1465
+ def_wrapper(bitreverse64);
1466
+
1467
+ void Init_bit_twiddle(void)
1468
+ {
1469
+ VALUE rb_mBitTwiddle = rb_define_module("BitTwiddle");
1470
+
1471
+ rb_define_singleton_method(rb_mBitTwiddle, "add_core_extensions", bt_add_core_extensions, 0);
1472
+
1473
+ /* Return the number of 1 bits in `int`.
1474
+ * @example
1475
+ * BitTwiddle.popcount(7) # => 3
1476
+ * BitTwiddle.popcount(255) # => 8
1477
+ *
1478
+ * If `int` is negative, raise `RangeError`.
1479
+ *
1480
+ * @param int [Integer] The integer to operate on
1481
+ * @return [Integer]
1482
+ */
1483
+ rb_define_singleton_method(rb_mBitTwiddle, "popcount", bt_popcount, 1);
1484
+ /* Return the index of the lowest 1 bit, where the least-significant bit is index 1.
1485
+ * If this integer is 0, return 0.
1486
+ * @example
1487
+ * BitTwiddle.lo_bit(1) # => 1
1488
+ * BitTwiddle.lo_bit(128) # => 8
1489
+ *
1490
+ * If `int` is negative, raise `RangeError`.
1491
+ *
1492
+ * @param int [Integer] The integer to operate on
1493
+ * @return [Integer]
1494
+ */
1495
+ rb_define_singleton_method(rb_mBitTwiddle, "lo_bit", bt_lo_bit, 1);
1496
+ /* Return the index of the highest 1 bit, where the least-significant bit is index 1.
1497
+ * If `int` is 0, return 0.
1498
+ * @example
1499
+ * BitTwiddle.hi_bit(1) # => 1
1500
+ * BitTwiddle.hi_bit(255) # => 8
1501
+ *
1502
+ * If `int` is negative, raise `RangeError`.
1503
+ *
1504
+ * @param int [Integer] The integer to operate on
1505
+ * @return [Integer]
1506
+ */
1507
+ rb_define_singleton_method(rb_mBitTwiddle, "hi_bit", bt_hi_bit, 1);
1508
+ /* Reverse the least-significant and second least-significant bytes of `int`.
1509
+ * @example
1510
+ * BitTwiddle.bswap16(0xFF00) # => 255
1511
+ * BitTwiddle.bswap16(0x00FF) # => 65280
1512
+ *
1513
+ * If `int` is negative, raise `RangeError`.
1514
+ *
1515
+ * @param int [Integer] The integer to operate on
1516
+ * @return [Integer]
1517
+ */
1518
+ rb_define_singleton_method(rb_mBitTwiddle, "bswap16", bt_bswap16, 1);
1519
+ /* Reverse the least-significant 4 bytes of `int`.
1520
+ *
1521
+ * Does not reverse bits within each byte. This can be used to swap endianness
1522
+ * of a 32-bit integer.
1523
+ *
1524
+ * @example
1525
+ * BitTwiddle.bswap32(0xaabbccdd).to_s(16) # => "ddccbbaa"
1526
+ *
1527
+ * If `int` is negative, raise `RangeError`.
1528
+ *
1529
+ * @param int [Integer] The integer to operate on
1530
+ * @return [Integer]
1531
+ */
1532
+ rb_define_singleton_method(rb_mBitTwiddle, "bswap32", bt_bswap32, 1);
1533
+ /* Reverse the least-significant 8 bytes of `int`.
1534
+ *
1535
+ * Does not reverse bits within each byte. This can be used to swap endianness
1536
+ * of a 64-bit integer.
1537
+ *
1538
+ * @example
1539
+ * BitTwiddle.bswap64(0xaabbccdd).to_s(16) # => "ddccbbaa00000000"
1540
+ *
1541
+ * If `int` is negative, raise `RangeError`.
1542
+ *
1543
+ * @param int [Integer] The integer to operate on
1544
+ * @return [Integer]
1545
+ */
1546
+ rb_define_singleton_method(rb_mBitTwiddle, "bswap64", bt_bswap64, 1);
1547
+ /* Left-rotation ("circular shift") of the low 8 bits in `int`.
1548
+ *
1549
+ * If the rotate distance is negative, the bit rotation will be to the right
1550
+ * instead.
1551
+ *
1552
+ * @example
1553
+ * BitTwiddle.lrot8(0b01110001, 1).to_s(2) # => "11100010"
1554
+ * BitTwiddle.lrot8(0b01110001, 3).to_s(2) # => "10001011"
1555
+ *
1556
+ * @param int [Integer] The integer to operate on
1557
+ * @param rotdist [Integer] Number of bit positions to rotate by
1558
+ * @return [Integer]
1559
+ */
1560
+ rb_define_singleton_method(rb_mBitTwiddle, "lrot8", bt_lrot8, 2);
1561
+ /* Left-rotation ("circular shift") of the low 16 bits in `int`.
1562
+ *
1563
+ * If the rotate distance is negative, the bit rotation will be to the right
1564
+ * instead.
1565
+ *
1566
+ * @example
1567
+ * BitTwiddle.lrot16(0b0111000101110001, 1).to_s(2) # => "1110001011100010"
1568
+ * BitTwiddle.lrot16(0b0111000101110001, 3).to_s(2) # => "1000101110001011"
1569
+ *
1570
+ * @param int [Integer] The integer to operate on
1571
+ * @param rotdist [Integer] Number of bit positions to rotate by
1572
+ * @return [Integer]
1573
+ */
1574
+ rb_define_singleton_method(rb_mBitTwiddle, "lrot16", bt_lrot16, 2);
1575
+ /* Left-rotation ("circular shift") of the low 32 bits in `int`.
1576
+ *
1577
+ * If the rotate distance is negative, the bit rotation will be to the right
1578
+ * instead.
1579
+ *
1580
+ * @example
1581
+ * BitTwiddle.lrot32(0xaabbccdd, 4).to_s(16) # => "abbccdda"
1582
+ *
1583
+ * @param int [Integer] The integer to operate on
1584
+ * @param rotdist [Integer] Number of bit positions to rotate by
1585
+ * @return [Integer]
1586
+ */
1587
+ rb_define_singleton_method(rb_mBitTwiddle, "lrot32", bt_lrot32, 2);
1588
+ /* Left-rotation ("circular shift") of the low 64 bits in `int`.
1589
+ *
1590
+ * If the rotate distance is negative, the bit rotation will be to the right
1591
+ * instead.
1592
+ *
1593
+ * @example
1594
+ * BitTwiddle.lrot64(0x11223344aabbccdd, 4).to_s(16) # => "1223344aabbccdd1"
1595
+ *
1596
+ * @param int [Integer] The integer to operate on
1597
+ * @param rotdist [Integer] Number of bit positions to rotate by
1598
+ * @return [Integer]
1599
+ */
1600
+ rb_define_singleton_method(rb_mBitTwiddle, "lrot64", bt_lrot64, 2);
1601
+ /* Right-rotation ("circular shift") of the low 8 bits in `int`.
1602
+ *
1603
+ * If the rotate distance is negative, the bit rotation will be to the left
1604
+ * instead.
1605
+ *
1606
+ * @example
1607
+ * BitTwiddle.rrot8(0b01110001, 1).to_s(2) # => "10111000"
1608
+ * BitTwiddle.rrot8(0b01110001, 3).to_s(2) # => "101110"
1609
+ *
1610
+ * @param int [Integer] The integer to operate on
1611
+ * @param rotdist [Integer] Number of bit positions to rotate by
1612
+ * @return [Integer]
1613
+ */
1614
+ rb_define_singleton_method(rb_mBitTwiddle, "rrot8", bt_rrot8, 2);
1615
+ /* Right-rotation ("circular shift") of the low 16 bits in `int`.
1616
+ *
1617
+ * If the rotate distance is negative, the bit rotation will be to the left
1618
+ * instead.
1619
+ *
1620
+ * @example
1621
+ * BitTwiddle.rrot16(0b0111000101110001, 1).to_s(2) # => "1011100010111000"
1622
+ * BitTwiddle.rrot16(0b0111000101110001, 3).to_s(2) # => "10111000101110"
1623
+ *
1624
+ * @param int [Integer] The integer to operate on
1625
+ * @param rotdist [Integer] Number of bit positions to rotate by
1626
+ * @return [Integer]
1627
+ */
1628
+ rb_define_singleton_method(rb_mBitTwiddle, "rrot16", bt_rrot16, 2);
1629
+ /* Right-rotation ("circular shift") of the low 32 bits in `int`.
1630
+ *
1631
+ * If the rotate distance is negative, the bit rotation will be to the left
1632
+ * instead.
1633
+ *
1634
+ * @example
1635
+ * BitTwiddle.rrot32(0xaabbccdd, 4).to_s(16) # => "daabbccd"
1636
+ *
1637
+ * @param int [Integer] The integer to operate on
1638
+ * @param rotdist [Integer] Number of bit positions to rotate by
1639
+ * @return [Integer]
1640
+ */
1641
+ rb_define_singleton_method(rb_mBitTwiddle, "rrot32", bt_rrot32, 2);
1642
+ /* Right-rotation ("circular shift") of the low 64 bits in `int`.
1643
+ *
1644
+ * If the rotate distance is negative, the bit rotation will be to the left
1645
+ * instead.
1646
+ *
1647
+ * @example
1648
+ * BitTwiddle.rrot64(0x11223344aabbccdd, 4).to_s(16) # => "d11223344aabbccd"
1649
+ *
1650
+ * @param int [Integer] The integer to operate on
1651
+ * @param rotdist [Integer] Number of bit positions to rotate by
1652
+ * @return [Integer]
1653
+ */
1654
+ rb_define_singleton_method(rb_mBitTwiddle, "rrot64", bt_rrot64, 2);
1655
+ /* Left-shift of the low 8 bits in `int`.
1656
+ *
1657
+ * If the shift distance is negative, a right shift will be performed instead.
1658
+ * The vacated bit positions will be filled with 0 bits. If shift distance is
1659
+ * more than 7 or less than -7, the low 8 bits will all be zeroed.
1660
+ *
1661
+ * @example
1662
+ * BitTwiddle.lshift8(0x11223344, 1).to_s(16) # => "11223388"
1663
+ * BitTwiddle.lshift8(0x11223344, 2).to_s(16) # => "11223310"
1664
+ *
1665
+ * @param int [Integer] The integer to operate on
1666
+ * @param shiftdist [Integer] Number of bit positions to shift by
1667
+ * @return [Integer]
1668
+ */
1669
+ rb_define_singleton_method(rb_mBitTwiddle, "lshift8", bt_lshift8, 2);
1670
+ /* Left-shift of the low 16 bits in `int`.
1671
+ *
1672
+ * If the shift distance is negative, a right shift will be performed instead.
1673
+ * The vacated bit positions will be filled with 0 bits. If shift distance is
1674
+ * more than 15 or less than -15, the low 16 bits will all be zeroed.
1675
+ *
1676
+ * @example
1677
+ * BitTwiddle.lshift16(0x11223344, 1).to_s(16) # => "11226688"
1678
+ * BitTwiddle.lshift16(0x11223344, 2).to_s(16) # => "1122cd10"
1679
+ *
1680
+ * @param int [Integer] The integer to operate on
1681
+ * @param shiftdist [Integer] Number of bit positions to shift by
1682
+ * @return [Integer]
1683
+ */
1684
+ rb_define_singleton_method(rb_mBitTwiddle, "lshift16", bt_lshift16, 2);
1685
+ /* Left-shift of the low 32 bits in `int`.
1686
+ *
1687
+ * If the shift distance is negative, a right shift will be performed instead.
1688
+ * The vacated bit positions will be filled with 0 bits. If shift distance is
1689
+ * more than 31 or less than -31, the low 32 bits will all be zeroed.
1690
+ *
1691
+ * @example
1692
+ * BitTwiddle.lshift32(0x11223344, 1).to_s(16) # => "22446688"
1693
+ * BitTwiddle.lshift32(0x11223344, 2).to_s(16) # => "4488cd10"
1694
+ *
1695
+ * @param int [Integer] The integer to operate on
1696
+ * @param shiftdist [Integer] Number of bit positions to shift by
1697
+ * @return [Integer]
1698
+ */
1699
+ rb_define_singleton_method(rb_mBitTwiddle, "lshift32", bt_lshift32, 2);
1700
+ /* Left-shift of the low 64 bits in `int`.
1701
+ *
1702
+ * If the shift distance is negative, a right shift will be performed instead.
1703
+ * The vacated bit positions will be filled with 0 bits. If shift distance is
1704
+ * more than 63 or less than -63, the low 64 bits will all be zeroed.
1705
+ *
1706
+ * @example
1707
+ * BitTwiddle.lshift64(0x1122334411223344, 1).to_s(16) # => "2244668822446688"
1708
+ * BitTwiddle.lshift64(0x1122334411223344, 2).to_s(16) # => "4488cd104488cd10"
1709
+ *
1710
+ * @param int [Integer] The integer to operate on
1711
+ * @param shiftdist [Integer] Number of bit positions to shift by
1712
+ * @return [Integer]
1713
+ */
1714
+ rb_define_singleton_method(rb_mBitTwiddle, "lshift64", bt_lshift64, 2);
1715
+ /* Right-shift of the low 8 bits in `int`.
1716
+ *
1717
+ * If the shift distance is negative, a left shift will be performed instead.
1718
+ * The vacated bit positions will be filled with 0 bits. If shift distance is
1719
+ * more than 7 or less than -7, the low 8 bits will all be zeroed.
1720
+ *
1721
+ * @example
1722
+ * BitTwiddle.rshift8(0x11223344, 1).to_s(16) # => "11223322"
1723
+ * BitTwiddle.rshift8(0x11223344, 2).to_s(16) # => "11223311"
1724
+ *
1725
+ * @param int [Integer] The integer to operate on
1726
+ * @param shiftdist [Integer] Number of bit positions to shift by
1727
+ * @return [Integer]
1728
+ */
1729
+ rb_define_singleton_method(rb_mBitTwiddle, "rshift8", bt_rshift8, 2);
1730
+ /* Right-shift of the low 16 bits in `int`.
1731
+ *
1732
+ * If the shift distance is negative, a left shift will be performed instead.
1733
+ * The vacated bit positions will be filled with 0 bits. If shift distance is
1734
+ * more than 15 or less than -15, the low 16 bits will all be zeroed.
1735
+ *
1736
+ * @example
1737
+ * BitTwiddle.rshift16(0x11223344, 1).to_s(16) # => "112219a2"
1738
+ * BitTwiddle.rshift16(0x11223344, 2).to_s(16) # => "11220cd1"
1739
+ *
1740
+ * @param int [Integer] The integer to operate on
1741
+ * @param shiftdist [Integer] Number of bit positions to shift by
1742
+ * @return [Integer]
1743
+ */
1744
+ rb_define_singleton_method(rb_mBitTwiddle, "rshift16", bt_rshift16, 2);
1745
+ /* Right-shift of the low 32 bits in `int`.
1746
+ *
1747
+ * If the shift distance is negative, a left shift will be performed instead.
1748
+ * The vacated bit positions will be filled with 0 bits. If shift distance is
1749
+ * more than 31 or less than -31, the low 32 bits will all be zeroed.
1750
+ *
1751
+ * @example
1752
+ * BitTwiddle.rshift32(0x11223344, 1).to_s(16) # => "89119a2"
1753
+ * BitTwiddle.rshift32(0x11223344, 2).to_s(16) # => "4488cd1"
1754
+ *
1755
+ * @param int [Integer] The integer to operate on
1756
+ * @param shiftdist [Integer] Number of bit positions to shift by
1757
+ * @return [Integer]
1758
+ */
1759
+ rb_define_singleton_method(rb_mBitTwiddle, "rshift32", bt_rshift32, 2);
1760
+ /* Arithmetic right-shift of the low 64 bits in `int`.
1761
+ *
1762
+ * If bit 64 is a 1, the vacated bit positions will be filled with 1s. Otherwise,
1763
+ * they will be filled with 0s. Or, if the shift distance is negative, a left shift
1764
+ * will be performed instead, and the vacated bit positions will be filled with 0s.
1765
+ *
1766
+ * @example
1767
+ * BitTwiddle.arith_rshift64(0xaabbccddaabbccdd, 1).to_s(16) # => "d55de66ed55de66e"
1768
+ * BitTwiddle.arith_rshift64(0xaabbccddaabbccdd, 2).to_s(16) # => "eaaef3376aaef337"
1769
+ *
1770
+ * @param int [Integer] The integer to operate on
1771
+ * @param shiftdist [Integer] Number of bit positions to shift by
1772
+ * @return [Integer]
1773
+ */
1774
+ rb_define_singleton_method(rb_mBitTwiddle, "rshift64", bt_rshift64, 2);
1775
+ /* Arithmetic right-shift of the low 8 bits in `int`.
1776
+ *
1777
+ * If bit 8 is a 1, the vacated bit positions will be filled with 1s. Otherwise,
1778
+ * they will be filled with 0s. Or, if the shift distance is negative, a left shift
1779
+ * will be performed instead, and the vacated bit positions will be filled with 0s.
1780
+ *
1781
+ * @example
1782
+ * BitTwiddle.arith_rshift8(0xaabbccdd, 1).to_s(16) # => "aabbccee"
1783
+ * BitTwiddle.arith_rshift8(0xaabbccdd, 2).to_s(16) # => "aabbccf7"
1784
+ *
1785
+ * @param int [Integer] The integer to operate on
1786
+ * @param shiftdist [Integer] Number of bit positions to shift by
1787
+ * @return [Integer]
1788
+ */
1789
+ rb_define_singleton_method(rb_mBitTwiddle, "arith_rshift8", bt_arith_rshift8, 2);
1790
+ /* Arithmetic right-shift of the low 16 bits in `int`.
1791
+ *
1792
+ * If bit 16 is a 1, the vacated bit positions will be filled with 1s. Otherwise,
1793
+ * they will be filled with 0s. Or, if the shift distance is negative, a left shift
1794
+ * will be performed instead, and the vacated bit positions will be filled with 0s.
1795
+ *
1796
+ * @example
1797
+ * BitTwiddle.arith_rshift16(0xaabbccdd, 1).to_s(16) # => "aabbe66e"
1798
+ * BitTwiddle.arith_rshift16(0xaabbccdd, 2).to_s(16) # => "aabbf337"
1799
+ *
1800
+ * @param int [Integer] The integer to operate on
1801
+ * @param shiftdist [Integer] Number of bit positions to shift by
1802
+ * @return [Integer]
1803
+ */
1804
+ rb_define_singleton_method(rb_mBitTwiddle, "arith_rshift16", bt_arith_rshift16, 2);
1805
+ /* Arithmetic right-shift of the low 32 bits in `int`.
1806
+ *
1807
+ * If bit 32 is a 1, the vacated bit positions will be filled with 1s. Otherwise,
1808
+ * they will be filled with 0s. Or, if the shift distance is negative, a left shift
1809
+ * will be performed instead, and the vacated bit positions will be filled with 0s.
1810
+ *
1811
+ * @example
1812
+ * BitTwiddle.arith_rshift32(0xaabbccddaabbccdd, 1).to_s(16) # => "d55de66e"
1813
+ * BitTwiddle.arith_rshift32(0xaabbccddaabbccdd, 2).to_s(16) # => "eaaef337"
1814
+ *
1815
+ * @param int [Integer] The integer to operate on
1816
+ * @param shiftdist [Integer] Number of bit positions to shift by
1817
+ * @return [Integer]
1818
+ */
1819
+ rb_define_singleton_method(rb_mBitTwiddle, "arith_rshift32", bt_arith_rshift32, 2);
1820
+ /* Arithmetic right-shift of the low 64 bits in `int`.
1821
+ *
1822
+ * If bit 64 is a 1, the vacated bit positions will be filled with 1s. Otherwise,
1823
+ * they will be filled with 0s. Or, if the shift distance is negative, a left shift
1824
+ * will be performed instead, and the vacated bit positions will be filled with 0s.
1825
+ *
1826
+ * @example
1827
+ * BitTwiddle.arith_rshift64(0xaabbccddaabbccdd, 1).to_s(16) # => "d55de66ed55de66e"
1828
+ * BitTwiddle.arith_rshift64(0xaabbccddaabbccdd, 2).to_s(16) # => "eaaef3376aaef337"
1829
+ *
1830
+ * @param int [Integer] The integer to operate on
1831
+ * @param shiftdist [Integer] Number of bit positions to shift by
1832
+ * @return [Integer]
1833
+ */
1834
+ rb_define_singleton_method(rb_mBitTwiddle, "arith_rshift64", bt_arith_rshift64, 2);
1835
+ /* Reverse the low 8 bits in `int`.
1836
+ *
1837
+ * @example
1838
+ * BitTwiddle.bitreverse8(0b01101011).to_s(2) # => "11010110"
1839
+ *
1840
+ * If `int` is negative, raise `RangeError`.
1841
+ *
1842
+ * @param int [Integer] The integer to operate on
1843
+ * @return [Integer]
1844
+ */
1845
+ rb_define_singleton_method(rb_mBitTwiddle, "bitreverse8", bt_bitreverse8, 1);
1846
+ /* Reverse the low 16 bits in `int`.
1847
+ *
1848
+ * @example
1849
+ * BitTwiddle.bitreverse16(0b0110101100001011).to_s(2) # => "1101000011010110"
1850
+ *
1851
+ * If `int` is negative, raise `RangeError`.
1852
+ *
1853
+ * @param int [Integer] The integer to operate on
1854
+ * @return [Integer]
1855
+ */
1856
+ rb_define_singleton_method(rb_mBitTwiddle, "bitreverse16", bt_bitreverse16, 1);
1857
+ /* Reverse the low 32 bits in `int`.
1858
+ *
1859
+ * @example
1860
+ * BitTwiddle.bitreverse32(0x12341234).to_s(16) # => "2c482c48"
1861
+ *
1862
+ * If `int` is negative, raise `RangeError`.
1863
+ *
1864
+ * @param int [Integer] The integer to operate on
1865
+ * @return [Integer]
1866
+ */
1867
+ rb_define_singleton_method(rb_mBitTwiddle, "bitreverse32", bt_bitreverse32, 1);
1868
+ /* Reverse the low 64 bits in `int`.
1869
+ *
1870
+ * @example
1871
+ * BitTwiddle.bitreverse64(0xabcd1234abcd1234).to_s(16) # => "2c48b3d52c48b3d5"
1872
+ *
1873
+ * If `int` is negative, raise `RangeError`.
1874
+ *
1875
+ * @param int [Integer] The integer to operate on
1876
+ * @return [Integer]
1877
+ */
1878
+ rb_define_singleton_method(rb_mBitTwiddle, "bitreverse64", bt_bitreverse64, 1);
1879
+ }