xnd 0.2.0dev3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING.md +42 -0
  3. data/Gemfile +3 -0
  4. data/History.md +0 -0
  5. data/README.md +7 -0
  6. data/Rakefile +135 -0
  7. data/ext/ruby_xnd/extconf.rb +70 -0
  8. data/ext/ruby_xnd/float_pack_unpack.c +277 -0
  9. data/ext/ruby_xnd/float_pack_unpack.h +39 -0
  10. data/ext/ruby_xnd/gc_guard.c +36 -0
  11. data/ext/ruby_xnd/gc_guard.h +12 -0
  12. data/ext/ruby_xnd/include/xnd.h +449 -0
  13. data/ext/ruby_xnd/lib/libxnd.a +0 -0
  14. data/ext/ruby_xnd/lib/libxnd.so +1 -0
  15. data/ext/ruby_xnd/lib/libxnd.so.0 +1 -0
  16. data/ext/ruby_xnd/lib/libxnd.so.0.2.0dev3 +0 -0
  17. data/ext/ruby_xnd/memory_block_object.c +32 -0
  18. data/ext/ruby_xnd/memory_block_object.h +33 -0
  19. data/ext/ruby_xnd/ruby_xnd.c +1953 -0
  20. data/ext/ruby_xnd/ruby_xnd.h +61 -0
  21. data/ext/ruby_xnd/ruby_xnd_internal.h +85 -0
  22. data/ext/ruby_xnd/util.h +170 -0
  23. data/ext/ruby_xnd/xnd/AUTHORS.txt +5 -0
  24. data/ext/ruby_xnd/xnd/INSTALL.txt +134 -0
  25. data/ext/ruby_xnd/xnd/LICENSE.txt +29 -0
  26. data/ext/ruby_xnd/xnd/MANIFEST.in +3 -0
  27. data/ext/ruby_xnd/xnd/Makefile.in +80 -0
  28. data/ext/ruby_xnd/xnd/README.rst +44 -0
  29. data/ext/ruby_xnd/xnd/config.guess +1530 -0
  30. data/ext/ruby_xnd/xnd/config.h.in +22 -0
  31. data/ext/ruby_xnd/xnd/config.sub +1782 -0
  32. data/ext/ruby_xnd/xnd/configure +4867 -0
  33. data/ext/ruby_xnd/xnd/configure.ac +164 -0
  34. data/ext/ruby_xnd/xnd/doc/Makefile +14 -0
  35. data/ext/ruby_xnd/xnd/doc/_static/copybutton.js +66 -0
  36. data/ext/ruby_xnd/xnd/doc/conf.py +26 -0
  37. data/ext/ruby_xnd/xnd/doc/index.rst +44 -0
  38. data/ext/ruby_xnd/xnd/doc/libxnd/data-structures.rst +186 -0
  39. data/ext/ruby_xnd/xnd/doc/libxnd/functions.rst +148 -0
  40. data/ext/ruby_xnd/xnd/doc/libxnd/index.rst +25 -0
  41. data/ext/ruby_xnd/xnd/doc/releases/index.rst +34 -0
  42. data/ext/ruby_xnd/xnd/doc/xnd/align-pack.rst +96 -0
  43. data/ext/ruby_xnd/xnd/doc/xnd/buffer-protocol.rst +42 -0
  44. data/ext/ruby_xnd/xnd/doc/xnd/index.rst +30 -0
  45. data/ext/ruby_xnd/xnd/doc/xnd/quickstart.rst +62 -0
  46. data/ext/ruby_xnd/xnd/doc/xnd/types.rst +674 -0
  47. data/ext/ruby_xnd/xnd/install-sh +527 -0
  48. data/ext/ruby_xnd/xnd/libxnd/Makefile.in +102 -0
  49. data/ext/ruby_xnd/xnd/libxnd/Makefile.vc +112 -0
  50. data/ext/ruby_xnd/xnd/libxnd/bitmaps.c +345 -0
  51. data/ext/ruby_xnd/xnd/libxnd/contrib.h +313 -0
  52. data/ext/ruby_xnd/xnd/libxnd/copy.c +944 -0
  53. data/ext/ruby_xnd/xnd/libxnd/equal.c +1216 -0
  54. data/ext/ruby_xnd/xnd/libxnd/inline.h +154 -0
  55. data/ext/ruby_xnd/xnd/libxnd/overflow.h +147 -0
  56. data/ext/ruby_xnd/xnd/libxnd/split.c +286 -0
  57. data/ext/ruby_xnd/xnd/libxnd/tests/Makefile.in +39 -0
  58. data/ext/ruby_xnd/xnd/libxnd/tests/Makefile.vc +44 -0
  59. data/ext/ruby_xnd/xnd/libxnd/tests/README.txt +2 -0
  60. data/ext/ruby_xnd/xnd/libxnd/tests/runtest.c +101 -0
  61. data/ext/ruby_xnd/xnd/libxnd/tests/test.h +48 -0
  62. data/ext/ruby_xnd/xnd/libxnd/tests/test_fixed.c +108 -0
  63. data/ext/ruby_xnd/xnd/libxnd/xnd.c +1304 -0
  64. data/ext/ruby_xnd/xnd/libxnd/xnd.h +449 -0
  65. data/ext/ruby_xnd/xnd/python/test_xnd.py +3144 -0
  66. data/ext/ruby_xnd/xnd/python/xnd/__init__.py +290 -0
  67. data/ext/ruby_xnd/xnd/python/xnd/_xnd.c +2822 -0
  68. data/ext/ruby_xnd/xnd/python/xnd/contrib/pretty.py +850 -0
  69. data/ext/ruby_xnd/xnd/python/xnd/docstrings.h +129 -0
  70. data/ext/ruby_xnd/xnd/python/xnd/pyxnd.h +200 -0
  71. data/ext/ruby_xnd/xnd/python/xnd/util.h +182 -0
  72. data/ext/ruby_xnd/xnd/python/xnd_randvalue.py +1121 -0
  73. data/ext/ruby_xnd/xnd/python/xnd_support.py +106 -0
  74. data/ext/ruby_xnd/xnd/setup.py +303 -0
  75. data/ext/ruby_xnd/xnd/vcbuild/INSTALL.txt +42 -0
  76. data/ext/ruby_xnd/xnd/vcbuild/runtest32.bat +16 -0
  77. data/ext/ruby_xnd/xnd/vcbuild/runtest64.bat +14 -0
  78. data/ext/ruby_xnd/xnd/vcbuild/vcbuild32.bat +29 -0
  79. data/ext/ruby_xnd/xnd/vcbuild/vcbuild64.bat +29 -0
  80. data/ext/ruby_xnd/xnd/vcbuild/vcclean.bat +13 -0
  81. data/ext/ruby_xnd/xnd/vcbuild/vcdistclean.bat +14 -0
  82. data/lib/ruby_xnd.so +0 -0
  83. data/lib/xnd.rb +306 -0
  84. data/lib/xnd/monkeys.rb +29 -0
  85. data/lib/xnd/version.rb +6 -0
  86. data/spec/debug_spec.rb +9 -0
  87. data/spec/gc_guard_spec.rb +10 -0
  88. data/spec/leakcheck.rb +9 -0
  89. data/spec/spec_helper.rb +877 -0
  90. data/spec/type_inference_spec.rb +81 -0
  91. data/spec/xnd_spec.rb +2921 -0
  92. data/xnd.gemspec +47 -0
  93. metadata +215 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ffef6659002865013b6d317fc2ac6bb681fc08a3
4
+ data.tar.gz: 86f1b508eafa5c9aae610e2d83213b9d36e505cc
5
+ SHA512:
6
+ metadata.gz: 6829849586822ece90df0993fecd46c9fccac58de72998a2ca12b12b1626581d4b3ea303f583c142a75b7ad2b023b7b00b5d17c89609f3ce047f697c58b582c6
7
+ data.tar.gz: 206e74e6b6cc11941b16ea2d12e5bd8d1e1878364e927ed2ad6d6748239a400ab32457a5f0dae1c114419f86ede9bbecd07c52c700fb4897e30487f7279efaaf
@@ -0,0 +1,42 @@
1
+ # Developer notes
2
+
3
+ ## Using C APIs from other Ruby libraries
4
+
5
+ The xnd Ruby wrapper uses type definitions, macros and functions from the
6
+ libndtypes Ruby wrapper. For this purpose, it is important to make sure that
7
+ xnd can find the correct headers and shared object files during compile and
8
+ linking time.
9
+
10
+ This requires some modifications in both the ndtypes and xnd repos. ndtypes
11
+ must ensure that the relevant header files and shared object are exposed to
12
+ other Ruby gems.
13
+
14
+ ## structs in XND
15
+
16
+ The primary struct that contains data for the XND type is the following:
17
+ ```
18
+ typedef struct XndObject {
19
+ VALUE mblock; /* owner of the primary type and memory block */
20
+ VALUE type; /* owner of the current type. lives and dies with this obj. */
21
+ xnd_t xnd; /* typed view, does not own anything */
22
+ } XndObject;
23
+ ```
24
+ As the comments say, the `mblock` is an object of type `MemoryBlockObject` that
25
+ is never revealed to the user. It is shared between multiple instances of XND objects
26
+ and contains the primary type (i.e the type of the root object).
27
+
28
+ The `type` attribute is of type `NDT` and exists only on a per-object basis. It is specific
29
+ to the particular instance of `XndObject`. Therefore, whenever making a view, it is important
30
+ to store a reference to the `mblock` in the GC guard so that the memory that the view needs
31
+ to access for its data needs does not get GC'd in case the root object needs to be GC'd.
32
+
33
+ ## Infinite ranges
34
+
35
+ Ruby 2.6 will introduce infinite ranges using a prettier and less verbose syntax, but for now
36
+ we're stuck with using `Float::INFINITY` every time we want to specify an infinite range. This
37
+ can quickly get tedious to type. Therefore XND introduces the following syntax for infinite
38
+ ranges for references arrays:
39
+
40
+ * Full range (`0..Float::INFINITY`) : `INF`.
41
+ * Part range (`4..Float::INFINITY`) : `4..INF`.
42
+
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
3
+
File without changes
@@ -0,0 +1,7 @@
1
+ # Introduction
2
+
3
+ # Installation
4
+
5
+ # Usage
6
+
7
+ # Acknowledgments
@@ -0,0 +1,135 @@
1
+ require 'rake'
2
+ require 'rake/extensiontask'
3
+ require 'rspec/core/rake_task'
4
+ require 'bundler/gem_tasks'
5
+ require 'fileutils'
6
+ require 'xnd/version.rb'
7
+
8
+ gemspec = eval(IO.read("xnd.gemspec"))
9
+
10
+ ext_name = "ruby_xnd"
11
+ Rake::ExtensionTask.new(ext_name, gemspec) do |ext|
12
+ ext.ext_dir = "ext/#{ext_name}"
13
+ ext.source_pattern = "**/*.{c,h}"
14
+ end
15
+
16
+ def run *cmd
17
+ sh(cmd.join(" "))
18
+ end
19
+
20
+ task :console do
21
+ cmd = ['irb', "-r './lib/xnd.rb'"]
22
+ run(*cmd)
23
+ end
24
+
25
+ task :pry do
26
+ cmd = ['pry', "-r './lib/xnd.rb'"]
27
+ run(*cmd)
28
+ end
29
+
30
+ BASEDIR = Pathname( __FILE__ ).dirname.relative_path_from( Pathname.pwd )
31
+ SPECDIR = BASEDIR + 'spec'
32
+
33
+ VALGRIND_OPTIONS = [
34
+ "--tool=memcheck",
35
+ #"--leak-check=yes",
36
+ "--num-callers=15",
37
+ #"--error-limit=no",
38
+ "--partial-loads-ok=yes",
39
+ "--undef-value-errors=no" #,
40
+ #"--dsymutil=yes"
41
+ ]
42
+
43
+ CALLGRIND_OPTIONS = [
44
+ "--tool=callgrind",
45
+ "--dump-instr=yes",
46
+ "--simulate-cache=yes",
47
+ "--collect-jumps=yes"
48
+ ]
49
+
50
+ VALGRIND_MEMORYFILL_OPTIONS = [
51
+ "--freelist-vol=100000000",
52
+ "--malloc-fill=6D",
53
+ "--free-fill=66 ",
54
+ ]
55
+
56
+ GDB_OPTIONS = []
57
+
58
+ namespace :spec do
59
+ # partial-loads-ok and undef-value-errors necessary to ignore
60
+ # spurious (and eminently ignorable) warnings from the ruby
61
+ # interpreter
62
+
63
+ RSPEC_CMD = [ 'ruby', '-S', 'rspec', '-Ilib:ext', SPECDIR.to_s ]
64
+
65
+ desc "Run specs under GDB."
66
+ task :gdb => [ :compile ] do |task|
67
+ cmd = [ 'gdb' ] + GDB_OPTIONS
68
+ cmd += [ '--args' ]
69
+ cmd += RSPEC_CMD
70
+ run( *cmd )
71
+ end
72
+
73
+ desc "Run specs under cgdb."
74
+ task :cgdb => [ :compile ] do |task|
75
+ cmd = [ 'cgdb' ] + GDB_OPTIONS
76
+ cmd += [ '--args' ]
77
+ cmd += RSPEC_CMD
78
+ run( *cmd )
79
+ end
80
+
81
+ desc "Run specs under Valgrind."
82
+ task :valgrind => [ :compile ] do |task|
83
+ cmd = [ 'valgrind' ] + VALGRIND_OPTIONS
84
+ cmd += RSPEC_CMD
85
+ run( *cmd )
86
+ end
87
+
88
+ desc "Run specs under Callgrind."
89
+ task :callgrind => [ :compile ] do |task|
90
+ cmd = [ 'valgrind' ] + CALLGRIND_OPTIONS
91
+ cmd += RSPEC_CMD
92
+ run( *cmd )
93
+ end
94
+ end
95
+
96
+ LEAKCHECK_CMD = [ 'ruby', '-Ilib:ext', "#{SPECDIR}/leakcheck.rb" ]
97
+
98
+ desc "Run leakcheck script."
99
+ task :leakcheck => [ :compile ] do |task|
100
+ cmd = [ 'valgrind' ] + VALGRIND_OPTIONS
101
+ cmd += LEAKCHECK_CMD
102
+ run( *cmd )
103
+ end
104
+
105
+ task :clobber do |task|
106
+ [
107
+ "ext/#{ext_name}/include",
108
+ "ext/#{ext_name}/share",
109
+ "ext/#{ext_name}/lib",
110
+ ].each do |f|
111
+ puts "deleting folder #{f}..."
112
+ FileUtils.rm_rf(f)
113
+ end
114
+
115
+ Dir.chdir("ext/#{ext_name}/xnd/libxnd/") do
116
+ system("make clean")
117
+ end
118
+ end
119
+
120
+ task :develop do
121
+ ext_xnd = "ext/ruby_xnd/xnd"
122
+ puts "deleting previously created #{ext_xnd} directory..."
123
+ FileUtils.rm_rf(ext_xnd)
124
+ Dir.mkdir(ext_xnd)
125
+
126
+ puts "cloning xnd repo into ext/ folder..."
127
+ system("git clone https://github.com/plures/xnd #{ext_xnd}")
128
+
129
+ Dir.chdir(ext_xnd) do
130
+ system("git checkout #{RubyXND::COMMIT}")
131
+ end
132
+
133
+ puts "building gem with rake build..."
134
+ system("rake build")
135
+ end
@@ -0,0 +1,70 @@
1
+ require 'mkmf'
2
+
3
+ def windows?
4
+ (/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM) != nil
5
+ end
6
+
7
+ def mac?
8
+ (/darwin/ =~ RUBY_PLATFORM) != nil
9
+ end
10
+
11
+ def unix?
12
+ !windows?
13
+ end
14
+
15
+ # libndtypes config
16
+
17
+ ndtypes_version = ">= 0.2.0dev3"
18
+ ndtypes_spec = Gem::Specification.find_by_name("ndtypes", ndtypes_version)
19
+ ndtypes_extdir = File.join(ndtypes_spec.gem_dir, 'ext', 'ruby_ndtypes')
20
+ ndtypes_includedir = File.join(ndtypes_extdir, 'include')
21
+ ndtypes_libdir = File.join(ndtypes_extdir, 'lib')
22
+
23
+ find_header("ruby_ndtypes.h", ndtypes_includedir)
24
+ raise "cannot find ruby_ndtypes.h in path #{ndtypes_includedir}." unless have_header("ruby_ndtypes.h")
25
+
26
+ find_header("ndtypes.h", ndtypes_includedir)
27
+ find_library("ndtypes", nil, ndtypes_libdir)
28
+
29
+ dir_config("ndtypes", [ndtypes_includedir], [ndtypes_libdir])
30
+
31
+ # libxnd config
32
+
33
+ puts "compiling libxnd for your machine..."
34
+ Dir.chdir(File.join(File.dirname(__FILE__) + "/xnd")) do
35
+ if unix?
36
+ Dir.chdir("libxnd") do
37
+ Dir.mkdir(".objs") unless Dir.exists? ".objs"
38
+ end
39
+
40
+ system("./configure --prefix=#{File.expand_path("../")} --with-docs=no " +
41
+ "--with-includes=#{ndtypes_includedir}")
42
+ system("make")
43
+ system("make install")
44
+ elsif windows?
45
+ raise NotImplementedError, "need to specify build instructions for windows."
46
+ end
47
+ end
48
+
49
+ binaries = File.expand_path(File.join(File.dirname(__FILE__) + "/lib/"))
50
+ headers = File.expand_path(File.join(File.dirname(__FILE__) + "/include/"))
51
+
52
+ find_library("xnd", nil, binaries)
53
+ find_header("xnd.h", headers)
54
+
55
+ dir_config("xnd", [headers], [binaries])
56
+
57
+ $INSTALLFILES = [
58
+ ["ruby_xnd.h", "$(archdir)"],
59
+ ["xnd.h", "$(archdir)"]
60
+ ]
61
+
62
+ # for macOS
63
+ append_ldflags("-Wl,-rpath #{binaries}")
64
+
65
+ basenames = %w{float_pack_unpack gc_guard ruby_xnd}
66
+ $objs = basenames.map { |b| "#{b}.o" }
67
+ $srcs = basenames.map { |b| "#{b}.c" }
68
+
69
+ $CFLAGS += " -fPIC -g "
70
+ create_makefile("ruby_xnd/ruby_xnd")
@@ -0,0 +1,277 @@
1
+ /* BSD 3-Clause License
2
+ *
3
+ * Copyright (c) 2018, Quansight and Sameer Deshmukh
4
+ * All rights reserved.
5
+ *
6
+ * Redistribution and use in source and binary forms, with or without
7
+ * modification, are permitted provided that the following conditions are met:
8
+ *
9
+ * * Redistributions of source code must retain the above copyright notice, this
10
+ * list of conditions and the following disclaimer.
11
+ *
12
+ * * Redistributions in binary form must reproduce the above copyright notice,
13
+ * this list of conditions and the following disclaimer in the documentation
14
+ * and/or other materials provided with the distribution.
15
+ *
16
+ * * Neither the name of the copyright holder nor the names of its
17
+ * contributors may be used to endorse or promote products derived from
18
+ * this software without specific prior written permission.
19
+ *
20
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
+ */
31
+
32
+ /* Functions for packing and unpacking floats from char * arrays.
33
+
34
+ Author: Sameer Deshmukh (@v0dro)
35
+ */
36
+
37
+ #include "ruby_xnd_internal.h"
38
+
39
+ /* Pack a 32-bit float into a contiguous unsigned char* buffer.
40
+
41
+ Reference:
42
+ https://github.com/python/cpython/blob/master/Include/floatobject.h#L77
43
+
44
+ @param num The number to be packed.
45
+ @param ptr
46
+ @param le Le is a boolean argument. True if you want the string in
47
+ litte-endian format, false if you want it in big-endian format.
48
+
49
+ @return 0 if success. Raise ruby error if failure.
50
+ */
51
+ int
52
+ rb_xnd_pack_float32(double num, unsigned char* ptr, int le)
53
+ {
54
+ float y = (float)num;
55
+ int i, incr = 1;
56
+
57
+ if (isinf(y) && !isinf(num)) {
58
+ rb_raise(rb_eRangeError, "cannot fit value in 32-bit floating point number.");
59
+ }
60
+
61
+ unsigned char s[sizeof(float)];
62
+ memcpy(s, &y, sizeof(float));
63
+
64
+ #ifdef XND_DEBUG
65
+ if (!le) { // choose big-endian
66
+ ptr += 3;
67
+ incr = -1;
68
+ }
69
+ #else
70
+ if ((IEEE_LITTLE_ENDIAN_P && !le) || (IEEE_BIG_ENDIAN_P && le)) { // choose big-endian
71
+ ptr += 3;
72
+ incr = -1;
73
+ }
74
+ #endif
75
+
76
+ for (i = 0; i < sizeof(float); ++i) {
77
+ *ptr = s[i];
78
+ ptr += incr;
79
+ }
80
+
81
+ return 0;
82
+ }
83
+
84
+ /* Unpack a 32-bit float from a contiguos unsigned char* buffer.
85
+
86
+ @param ptr :
87
+ @param le Le is a boolean argument. True if you want the string in
88
+ litte-endian format, false if you want it in big-endian format.
89
+
90
+ @return unpacked number as a double.
91
+ */
92
+ int
93
+ rb_xnd_unpack_float32(float *x, unsigned char* ptr, int le)
94
+ {
95
+ #ifdef XND_DEBUG
96
+ if (!le) // big-endian
97
+ #else
98
+ if ((IEEE_LITTLE_ENDIAN_P && !le) || (IEEE_BIG_ENDIAN_P && le))// big-endian
99
+ #endif
100
+ {
101
+ char buf[4];
102
+ char *d = &buf[3];
103
+ int i;
104
+
105
+ for (i = 0; i < sizeof(float); ++i) {
106
+ *d-- = *ptr++;
107
+ }
108
+ memcpy(x, buf, sizeof(float));
109
+ }
110
+ else {
111
+ memcpy(x, ptr, sizeof(float));
112
+ }
113
+
114
+ return 0;
115
+ }
116
+
117
+ /* Pack 64 bit floating point number into an unsigned char array.
118
+
119
+ @param num
120
+ @param ptr
121
+ @param le
122
+ */
123
+ int
124
+ rb_xnd_pack_float64(double num, unsigned char *ptr, int le)
125
+ {
126
+ int i, incr = 1;
127
+
128
+ unsigned char s[sizeof(double)];
129
+ memcpy(s, &num, sizeof(double));
130
+
131
+ #ifdef XND_DEBUG
132
+ if (!le) { // choose big-endian
133
+ ptr += 7;
134
+ incr = -1;
135
+ }
136
+ #else
137
+ if ((IEEE_LITTLE_ENDIAN_P && !le) || (IEEE_BIG_ENDIAN_P && le)) { // choose big-endian
138
+ ptr += 7;
139
+ incr = -1;
140
+ }
141
+ #endif
142
+
143
+ for (i = 0; i < sizeof(double); ++i) {
144
+ *ptr = s[i];
145
+ ptr += incr;
146
+ }
147
+
148
+ return 0;
149
+ }
150
+
151
+ /* Unpack a 64-bit floating point number from an unsigned char array and return
152
+ the resulting number as a type double.
153
+ */
154
+ int
155
+ rb_xnd_unpack_float64(double *x, unsigned char *ptr, int le)
156
+ {
157
+ #ifdef XND_DEBUG
158
+ if (!le) { // big-endian
159
+ #else
160
+ if ((IEEE_LITTLE_ENDIAN_P && !le) || (IEEE_BIG_ENDIAN_P && le)) { // big-endian
161
+ #endif
162
+ char buf[sizeof(double)];
163
+ char *d = &buf[sizeof(double)-1];
164
+ int i;
165
+
166
+ for (i = 0; i < sizeof(double); ++i) {
167
+ *d-- = *ptr++;
168
+ }
169
+ memcpy(x, buf, sizeof(double));
170
+ }
171
+ else {
172
+ memcpy(x, ptr, sizeof(double));
173
+ }
174
+
175
+ return 0;
176
+ }
177
+
178
+ #ifdef XND_DEBUG
179
+ /* Functions for testing packing/unpacking functions.
180
+
181
+ In order to avoid the need for injecting the dependency of a C testing framework,
182
+ these are tests that work with the pack/unpack functions and are called in the
183
+ Init_ function if XND_DEBUG is defined.
184
+ */
185
+ void
186
+ test_pack_float32(void)
187
+ {
188
+ double num = 16448.0;
189
+ int i;
190
+ unsigned char ptr[4];
191
+
192
+ /* test big endian */
193
+ unsigned char ans_bige[4] = {0x46, 0x80, 0x80, 0x00};
194
+ rb_xnd_pack_float32(num, ptr, 0);
195
+ for (i = 0; i < 4; i++) {
196
+ assert(ans_bige[i] == ptr[i]);
197
+ }
198
+
199
+ /* test little endian */
200
+ unsigned char ans_lite[4] = {0, 0X80, 0X80, 0X46};
201
+ rb_xnd_pack_float32(num, ptr, 1);
202
+ for (i = 0; i < 4; i++) {
203
+ assert(ans_lite[i] == ptr[i]);
204
+ }
205
+ }
206
+
207
+ void test_unpack_float32(void)
208
+ {
209
+ float answer = 16448.0, result = 0.0;
210
+
211
+ /* test big endian */
212
+ unsigned char ptr_bige[4] = {0x46, 0x80, 0x80, 0x00};
213
+ rb_xnd_unpack_float32(&result, ptr_bige, 0);
214
+ assert(answer == result);
215
+
216
+ /* test little endian */
217
+ unsigned char ptr_lite[4] = {0, 0X80, 0X80, 0X46};
218
+ rb_xnd_unpack_float32(&result, ptr_lite, 1);
219
+ assert(answer == result);
220
+ }
221
+
222
+ void test_pack_float64(void)
223
+ {
224
+ double num = 16448.0;
225
+ int i;
226
+ unsigned char ptr[8];
227
+
228
+ /* test big endian. */
229
+ unsigned char ans_bige[8] = {0x40, 0xD0, 0x10, 0, 0, 0, 0, 0};
230
+ rb_xnd_pack_float64(num, ptr, 0);
231
+ for (i = 0; i < 8; i++) {
232
+ assert(ans_bige[i] == ptr[i]);
233
+ }
234
+
235
+ /* test little endian. */
236
+ unsigned char ans_lite[8] = {0, 0, 0, 0, 0, 0X10, 0XD0, 0X40};
237
+ rb_xnd_pack_float64(num, ptr, 1);
238
+ for (i = 0; i < 8; i++) {
239
+ assert(ans_lite[i] == ptr[i]);
240
+ }
241
+
242
+ double a = 1.0;
243
+ unsigned char ans_lite_a[8] = {0, 0, 0, 0, 0, 0, 0xF0, 0x3F};
244
+ rb_xnd_pack_float64(a, ptr, 1);
245
+ for (i = 0; i < 8; i++) {
246
+ assert(ans_lite_a[i] == ptr[i]);
247
+ }
248
+ }
249
+
250
+ void test_unpack_float64(void)
251
+ {
252
+ double answer = 16448.0, result = 0.0;
253
+
254
+ /* test big-endian */
255
+ unsigned char ptr_bige[8] = {0x40, 0xD0, 0x10, 0, 0, 0, 0, 0};
256
+ rb_xnd_unpack_float64(&result, ptr_bige, 0);
257
+ assert(answer == result);
258
+
259
+ /* test little-endian */
260
+ unsigned char ptr_lite[8] = {0, 0, 0, 0, 0, 0X10, 0XD0, 0X40};
261
+ rb_xnd_unpack_float64(&result, ptr_lite, 1);
262
+ assert(answer == result);
263
+
264
+ double a = 1.0;
265
+ unsigned char ans_lite_a[8] = {0, 0, 0, 0, 0, 0, 0xF0, 0x3F};
266
+ rb_xnd_unpack_float64(&result, ans_lite_a, 1);
267
+ assert(a == result);
268
+ }
269
+
270
+ void run_float_pack_unpack_tests(void)
271
+ {
272
+ test_pack_float32();
273
+ test_unpack_float32();
274
+ test_pack_float64();
275
+ test_unpack_float64();
276
+ }
277
+ #endif