xnd 0.2.0dev3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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