xnd 0.2.0dev3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CONTRIBUTING.md +42 -0
- data/Gemfile +3 -0
- data/History.md +0 -0
- data/README.md +7 -0
- data/Rakefile +135 -0
- data/ext/ruby_xnd/extconf.rb +70 -0
- data/ext/ruby_xnd/float_pack_unpack.c +277 -0
- data/ext/ruby_xnd/float_pack_unpack.h +39 -0
- data/ext/ruby_xnd/gc_guard.c +36 -0
- data/ext/ruby_xnd/gc_guard.h +12 -0
- data/ext/ruby_xnd/include/xnd.h +449 -0
- data/ext/ruby_xnd/lib/libxnd.a +0 -0
- data/ext/ruby_xnd/lib/libxnd.so +1 -0
- data/ext/ruby_xnd/lib/libxnd.so.0 +1 -0
- data/ext/ruby_xnd/lib/libxnd.so.0.2.0dev3 +0 -0
- data/ext/ruby_xnd/memory_block_object.c +32 -0
- data/ext/ruby_xnd/memory_block_object.h +33 -0
- data/ext/ruby_xnd/ruby_xnd.c +1953 -0
- data/ext/ruby_xnd/ruby_xnd.h +61 -0
- data/ext/ruby_xnd/ruby_xnd_internal.h +85 -0
- data/ext/ruby_xnd/util.h +170 -0
- data/ext/ruby_xnd/xnd/AUTHORS.txt +5 -0
- data/ext/ruby_xnd/xnd/INSTALL.txt +134 -0
- data/ext/ruby_xnd/xnd/LICENSE.txt +29 -0
- data/ext/ruby_xnd/xnd/MANIFEST.in +3 -0
- data/ext/ruby_xnd/xnd/Makefile.in +80 -0
- data/ext/ruby_xnd/xnd/README.rst +44 -0
- data/ext/ruby_xnd/xnd/config.guess +1530 -0
- data/ext/ruby_xnd/xnd/config.h.in +22 -0
- data/ext/ruby_xnd/xnd/config.sub +1782 -0
- data/ext/ruby_xnd/xnd/configure +4867 -0
- data/ext/ruby_xnd/xnd/configure.ac +164 -0
- data/ext/ruby_xnd/xnd/doc/Makefile +14 -0
- data/ext/ruby_xnd/xnd/doc/_static/copybutton.js +66 -0
- data/ext/ruby_xnd/xnd/doc/conf.py +26 -0
- data/ext/ruby_xnd/xnd/doc/index.rst +44 -0
- data/ext/ruby_xnd/xnd/doc/libxnd/data-structures.rst +186 -0
- data/ext/ruby_xnd/xnd/doc/libxnd/functions.rst +148 -0
- data/ext/ruby_xnd/xnd/doc/libxnd/index.rst +25 -0
- data/ext/ruby_xnd/xnd/doc/releases/index.rst +34 -0
- data/ext/ruby_xnd/xnd/doc/xnd/align-pack.rst +96 -0
- data/ext/ruby_xnd/xnd/doc/xnd/buffer-protocol.rst +42 -0
- data/ext/ruby_xnd/xnd/doc/xnd/index.rst +30 -0
- data/ext/ruby_xnd/xnd/doc/xnd/quickstart.rst +62 -0
- data/ext/ruby_xnd/xnd/doc/xnd/types.rst +674 -0
- data/ext/ruby_xnd/xnd/install-sh +527 -0
- data/ext/ruby_xnd/xnd/libxnd/Makefile.in +102 -0
- data/ext/ruby_xnd/xnd/libxnd/Makefile.vc +112 -0
- data/ext/ruby_xnd/xnd/libxnd/bitmaps.c +345 -0
- data/ext/ruby_xnd/xnd/libxnd/contrib.h +313 -0
- data/ext/ruby_xnd/xnd/libxnd/copy.c +944 -0
- data/ext/ruby_xnd/xnd/libxnd/equal.c +1216 -0
- data/ext/ruby_xnd/xnd/libxnd/inline.h +154 -0
- data/ext/ruby_xnd/xnd/libxnd/overflow.h +147 -0
- data/ext/ruby_xnd/xnd/libxnd/split.c +286 -0
- data/ext/ruby_xnd/xnd/libxnd/tests/Makefile.in +39 -0
- data/ext/ruby_xnd/xnd/libxnd/tests/Makefile.vc +44 -0
- data/ext/ruby_xnd/xnd/libxnd/tests/README.txt +2 -0
- data/ext/ruby_xnd/xnd/libxnd/tests/runtest.c +101 -0
- data/ext/ruby_xnd/xnd/libxnd/tests/test.h +48 -0
- data/ext/ruby_xnd/xnd/libxnd/tests/test_fixed.c +108 -0
- data/ext/ruby_xnd/xnd/libxnd/xnd.c +1304 -0
- data/ext/ruby_xnd/xnd/libxnd/xnd.h +449 -0
- data/ext/ruby_xnd/xnd/python/test_xnd.py +3144 -0
- data/ext/ruby_xnd/xnd/python/xnd/__init__.py +290 -0
- data/ext/ruby_xnd/xnd/python/xnd/_xnd.c +2822 -0
- data/ext/ruby_xnd/xnd/python/xnd/contrib/pretty.py +850 -0
- data/ext/ruby_xnd/xnd/python/xnd/docstrings.h +129 -0
- data/ext/ruby_xnd/xnd/python/xnd/pyxnd.h +200 -0
- data/ext/ruby_xnd/xnd/python/xnd/util.h +182 -0
- data/ext/ruby_xnd/xnd/python/xnd_randvalue.py +1121 -0
- data/ext/ruby_xnd/xnd/python/xnd_support.py +106 -0
- data/ext/ruby_xnd/xnd/setup.py +303 -0
- data/ext/ruby_xnd/xnd/vcbuild/INSTALL.txt +42 -0
- data/ext/ruby_xnd/xnd/vcbuild/runtest32.bat +16 -0
- data/ext/ruby_xnd/xnd/vcbuild/runtest64.bat +14 -0
- data/ext/ruby_xnd/xnd/vcbuild/vcbuild32.bat +29 -0
- data/ext/ruby_xnd/xnd/vcbuild/vcbuild64.bat +29 -0
- data/ext/ruby_xnd/xnd/vcbuild/vcclean.bat +13 -0
- data/ext/ruby_xnd/xnd/vcbuild/vcdistclean.bat +14 -0
- data/lib/ruby_xnd.so +0 -0
- data/lib/xnd.rb +306 -0
- data/lib/xnd/monkeys.rb +29 -0
- data/lib/xnd/version.rb +6 -0
- data/spec/debug_spec.rb +9 -0
- data/spec/gc_guard_spec.rb +10 -0
- data/spec/leakcheck.rb +9 -0
- data/spec/spec_helper.rb +877 -0
- data/spec/type_inference_spec.rb +81 -0
- data/spec/xnd_spec.rb +2921 -0
- data/xnd.gemspec +47 -0
- metadata +215 -0
checksums.yaml
ADDED
@@ -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
|
data/CONTRIBUTING.md
ADDED
@@ -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
data/History.md
ADDED
File without changes
|
data/README.md
ADDED
data/Rakefile
ADDED
@@ -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
|