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.
- 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
|