hitokage 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.travis.yml +4 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +21 -0
  6. data/README.md +89 -0
  7. data/Rakefile +19 -0
  8. data/bin/console +14 -0
  9. data/bin/setup +8 -0
  10. data/ext/hitokage_ext/double-conversion/AUTHORS +14 -0
  11. data/ext/hitokage_ext/double-conversion/COPYING +26 -0
  12. data/ext/hitokage_ext/double-conversion/LICENSE +26 -0
  13. data/ext/hitokage_ext/double-conversion/README +54 -0
  14. data/ext/hitokage_ext/double-conversion/bignum-dtoa.cc +641 -0
  15. data/ext/hitokage_ext/double-conversion/bignum-dtoa.h +84 -0
  16. data/ext/hitokage_ext/double-conversion/bignum.cc +766 -0
  17. data/ext/hitokage_ext/double-conversion/bignum.h +144 -0
  18. data/ext/hitokage_ext/double-conversion/cached-powers.cc +175 -0
  19. data/ext/hitokage_ext/double-conversion/cached-powers.h +64 -0
  20. data/ext/hitokage_ext/double-conversion/diy-fp.cc +57 -0
  21. data/ext/hitokage_ext/double-conversion/diy-fp.h +118 -0
  22. data/ext/hitokage_ext/double-conversion/double-conversion.cc +982 -0
  23. data/ext/hitokage_ext/double-conversion/double-conversion.h +543 -0
  24. data/ext/hitokage_ext/double-conversion/fast-dtoa.cc +665 -0
  25. data/ext/hitokage_ext/double-conversion/fast-dtoa.h +88 -0
  26. data/ext/hitokage_ext/double-conversion/fixed-dtoa.cc +404 -0
  27. data/ext/hitokage_ext/double-conversion/fixed-dtoa.h +56 -0
  28. data/ext/hitokage_ext/double-conversion/ieee.h +402 -0
  29. data/ext/hitokage_ext/double-conversion/strtod.cc +555 -0
  30. data/ext/hitokage_ext/double-conversion/strtod.h +45 -0
  31. data/ext/hitokage_ext/double-conversion/utils.h +341 -0
  32. data/ext/hitokage_ext/extconf.rb +10 -0
  33. data/ext/hitokage_ext/hitokage_ext.cc +26 -0
  34. data/hitokage.gemspec +26 -0
  35. data/lib/hitokage.rb +5 -0
  36. data/lib/hitokage/replace_float_to_s.rb +6 -0
  37. data/lib/hitokage/version.rb +3 -0
  38. metadata +136 -0
@@ -0,0 +1,45 @@
1
+ // Copyright 2010 the V8 project authors. All rights reserved.
2
+ // Redistribution and use in source and binary forms, with or without
3
+ // modification, are permitted provided that the following conditions are
4
+ // met:
5
+ //
6
+ // * Redistributions of source code must retain the above copyright
7
+ // notice, this list of conditions and the following disclaimer.
8
+ // * Redistributions in binary form must reproduce the above
9
+ // copyright notice, this list of conditions and the following
10
+ // disclaimer in the documentation and/or other materials provided
11
+ // with the distribution.
12
+ // * Neither the name of Google Inc. nor the names of its
13
+ // contributors may be used to endorse or promote products derived
14
+ // from this software without specific prior written permission.
15
+ //
16
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
+ // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
+ // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
+ // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
+ // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
+ // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
+ // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
+ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
+ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+
28
+ #ifndef DOUBLE_CONVERSION_STRTOD_H_
29
+ #define DOUBLE_CONVERSION_STRTOD_H_
30
+
31
+ #include "utils.h"
32
+
33
+ namespace double_conversion {
34
+
35
+ // The buffer must only contain digits in the range [0-9]. It must not
36
+ // contain a dot or a sign. It must not start with '0', and must not be empty.
37
+ double Strtod(Vector<const char> buffer, int exponent);
38
+
39
+ // The buffer must only contain digits in the range [0-9]. It must not
40
+ // contain a dot or a sign. It must not start with '0', and must not be empty.
41
+ float Strtof(Vector<const char> buffer, int exponent);
42
+
43
+ } // namespace double_conversion
44
+
45
+ #endif // DOUBLE_CONVERSION_STRTOD_H_
@@ -0,0 +1,341 @@
1
+ // Copyright 2010 the V8 project authors. All rights reserved.
2
+ // Redistribution and use in source and binary forms, with or without
3
+ // modification, are permitted provided that the following conditions are
4
+ // met:
5
+ //
6
+ // * Redistributions of source code must retain the above copyright
7
+ // notice, this list of conditions and the following disclaimer.
8
+ // * Redistributions in binary form must reproduce the above
9
+ // copyright notice, this list of conditions and the following
10
+ // disclaimer in the documentation and/or other materials provided
11
+ // with the distribution.
12
+ // * Neither the name of Google Inc. nor the names of its
13
+ // contributors may be used to endorse or promote products derived
14
+ // from this software without specific prior written permission.
15
+ //
16
+ // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17
+ // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18
+ // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19
+ // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20
+ // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21
+ // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22
+ // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23
+ // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24
+ // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25
+ // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26
+ // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
+
28
+ #ifndef DOUBLE_CONVERSION_UTILS_H_
29
+ #define DOUBLE_CONVERSION_UTILS_H_
30
+
31
+ #include <stdlib.h>
32
+ #include <string.h>
33
+
34
+ #include <assert.h>
35
+ #ifndef ASSERT
36
+ #define ASSERT(condition) \
37
+ assert(condition);
38
+ #endif
39
+ #ifndef UNIMPLEMENTED
40
+ #define UNIMPLEMENTED() (abort())
41
+ #endif
42
+ #ifndef DOUBLE_CONVERSION_NO_RETURN
43
+ #ifdef _MSC_VER
44
+ #define DOUBLE_CONVERSION_NO_RETURN __declspec(noreturn)
45
+ #else
46
+ #define DOUBLE_CONVERSION_NO_RETURN __attribute__((noreturn))
47
+ #endif
48
+ #endif
49
+ #ifndef UNREACHABLE
50
+ #ifdef _MSC_VER
51
+ void DOUBLE_CONVERSION_NO_RETURN abort_noreturn();
52
+ inline void abort_noreturn() { abort(); }
53
+ #define UNREACHABLE() (abort_noreturn())
54
+ #else
55
+ #define UNREACHABLE() (abort())
56
+ #endif
57
+ #endif
58
+
59
+
60
+ // Double operations detection based on target architecture.
61
+ // Linux uses a 80bit wide floating point stack on x86. This induces double
62
+ // rounding, which in turn leads to wrong results.
63
+ // An easy way to test if the floating-point operations are correct is to
64
+ // evaluate: 89255.0/1e22. If the floating-point stack is 64 bits wide then
65
+ // the result is equal to 89255e-22.
66
+ // The best way to test this, is to create a division-function and to compare
67
+ // the output of the division with the expected result. (Inlining must be
68
+ // disabled.)
69
+ // On Linux,x86 89255e-22 != Div_double(89255.0/1e22)
70
+ #if defined(_M_X64) || defined(__x86_64__) || \
71
+ defined(__ARMEL__) || defined(__avr32__) || \
72
+ defined(__hppa__) || defined(__ia64__) || \
73
+ defined(__mips__) || \
74
+ defined(__powerpc__) || defined(__ppc__) || defined(__ppc64__) || \
75
+ defined(_POWER) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || \
76
+ defined(__sparc__) || defined(__sparc) || defined(__s390__) || \
77
+ defined(__SH4__) || defined(__alpha__) || \
78
+ defined(_MIPS_ARCH_MIPS32R2) || \
79
+ defined(__AARCH64EL__) || defined(__aarch64__)
80
+ #define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
81
+ #elif defined(__mc68000__)
82
+ #undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS
83
+ #elif defined(_M_IX86) || defined(__i386__) || defined(__i386)
84
+ #if defined(_WIN32)
85
+ // Windows uses a 64bit wide floating point stack.
86
+ #define DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS 1
87
+ #else
88
+ #undef DOUBLE_CONVERSION_CORRECT_DOUBLE_OPERATIONS
89
+ #endif // _WIN32
90
+ #else
91
+ #error Target architecture was not detected as supported by Double-Conversion.
92
+ #endif
93
+
94
+ #if defined(__GNUC__)
95
+ #define DOUBLE_CONVERSION_UNUSED __attribute__((unused))
96
+ #else
97
+ #define DOUBLE_CONVERSION_UNUSED
98
+ #endif
99
+
100
+ #if defined(_WIN32) && !defined(__MINGW32__)
101
+
102
+ typedef signed char int8_t;
103
+ typedef unsigned char uint8_t;
104
+ typedef short int16_t; // NOLINT
105
+ typedef unsigned short uint16_t; // NOLINT
106
+ typedef int int32_t;
107
+ typedef unsigned int uint32_t;
108
+ typedef __int64 int64_t;
109
+ typedef unsigned __int64 uint64_t;
110
+ // intptr_t and friends are defined in crtdefs.h through stdio.h.
111
+
112
+ #else
113
+
114
+ #include <stdint.h>
115
+
116
+ #endif
117
+
118
+ typedef uint16_t uc16;
119
+
120
+ // The following macro works on both 32 and 64-bit platforms.
121
+ // Usage: instead of writing 0x1234567890123456
122
+ // write UINT64_2PART_C(0x12345678,90123456);
123
+ #define UINT64_2PART_C(a, b) (((static_cast<uint64_t>(a) << 32) + 0x##b##u))
124
+
125
+
126
+ // The expression ARRAY_SIZE(a) is a compile-time constant of type
127
+ // size_t which represents the number of elements of the given
128
+ // array. You should only use ARRAY_SIZE on statically allocated
129
+ // arrays.
130
+ #ifndef ARRAY_SIZE
131
+ #define ARRAY_SIZE(a) \
132
+ ((sizeof(a) / sizeof(*(a))) / \
133
+ static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
134
+ #endif
135
+
136
+ // A macro to disallow the evil copy constructor and operator= functions
137
+ // This should be used in the private: declarations for a class
138
+ #ifndef DISALLOW_COPY_AND_ASSIGN
139
+ #define DISALLOW_COPY_AND_ASSIGN(TypeName) \
140
+ TypeName(const TypeName&); \
141
+ void operator=(const TypeName&)
142
+ #endif
143
+
144
+ // A macro to disallow all the implicit constructors, namely the
145
+ // default constructor, copy constructor and operator= functions.
146
+ //
147
+ // This should be used in the private: declarations for a class
148
+ // that wants to prevent anyone from instantiating it. This is
149
+ // especially useful for classes containing only static methods.
150
+ #ifndef DISALLOW_IMPLICIT_CONSTRUCTORS
151
+ #define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \
152
+ TypeName(); \
153
+ DISALLOW_COPY_AND_ASSIGN(TypeName)
154
+ #endif
155
+
156
+ namespace double_conversion {
157
+
158
+ static const int kCharSize = sizeof(char);
159
+
160
+ // Returns the maximum of the two parameters.
161
+ template <typename T>
162
+ static T Max(T a, T b) {
163
+ return a < b ? b : a;
164
+ }
165
+
166
+
167
+ // Returns the minimum of the two parameters.
168
+ template <typename T>
169
+ static T Min(T a, T b) {
170
+ return a < b ? a : b;
171
+ }
172
+
173
+
174
+ inline int StrLength(const char* string) {
175
+ size_t length = strlen(string);
176
+ ASSERT(length == static_cast<size_t>(static_cast<int>(length)));
177
+ return static_cast<int>(length);
178
+ }
179
+
180
+ // This is a simplified version of V8's Vector class.
181
+ template <typename T>
182
+ class Vector {
183
+ public:
184
+ Vector() : start_(NULL), length_(0) {}
185
+ Vector(T* data, int len) : start_(data), length_(len) {
186
+ ASSERT(len == 0 || (len > 0 && data != NULL));
187
+ }
188
+
189
+ // Returns a vector using the same backing storage as this one,
190
+ // spanning from and including 'from', to but not including 'to'.
191
+ Vector<T> SubVector(int from, int to) {
192
+ ASSERT(to <= length_);
193
+ ASSERT(from < to);
194
+ ASSERT(0 <= from);
195
+ return Vector<T>(start() + from, to - from);
196
+ }
197
+
198
+ // Returns the length of the vector.
199
+ int length() const { return length_; }
200
+
201
+ // Returns whether or not the vector is empty.
202
+ bool is_empty() const { return length_ == 0; }
203
+
204
+ // Returns the pointer to the start of the data in the vector.
205
+ T* start() const { return start_; }
206
+
207
+ // Access individual vector elements - checks bounds in debug mode.
208
+ T& operator[](int index) const {
209
+ ASSERT(0 <= index && index < length_);
210
+ return start_[index];
211
+ }
212
+
213
+ T& first() { return start_[0]; }
214
+
215
+ T& last() { return start_[length_ - 1]; }
216
+
217
+ private:
218
+ T* start_;
219
+ int length_;
220
+ };
221
+
222
+
223
+ // Helper class for building result strings in a character buffer. The
224
+ // purpose of the class is to use safe operations that checks the
225
+ // buffer bounds on all operations in debug mode.
226
+ class StringBuilder {
227
+ public:
228
+ StringBuilder(char* buffer, int buffer_size)
229
+ : buffer_(buffer, buffer_size), position_(0) { }
230
+
231
+ ~StringBuilder() { if (!is_finalized()) Finalize(); }
232
+
233
+ int size() const { return buffer_.length(); }
234
+
235
+ // Get the current position in the builder.
236
+ int position() const {
237
+ ASSERT(!is_finalized());
238
+ return position_;
239
+ }
240
+
241
+ // Reset the position.
242
+ void Reset() { position_ = 0; }
243
+
244
+ // Add a single character to the builder. It is not allowed to add
245
+ // 0-characters; use the Finalize() method to terminate the string
246
+ // instead.
247
+ void AddCharacter(char c) {
248
+ ASSERT(c != '\0');
249
+ ASSERT(!is_finalized() && position_ < buffer_.length());
250
+ buffer_[position_++] = c;
251
+ }
252
+
253
+ // Add an entire string to the builder. Uses strlen() internally to
254
+ // compute the length of the input string.
255
+ void AddString(const char* s) {
256
+ AddSubstring(s, StrLength(s));
257
+ }
258
+
259
+ // Add the first 'n' characters of the given string 's' to the
260
+ // builder. The input string must have enough characters.
261
+ void AddSubstring(const char* s, int n) {
262
+ ASSERT(!is_finalized() && position_ + n < buffer_.length());
263
+ ASSERT(static_cast<size_t>(n) <= strlen(s));
264
+ memmove(&buffer_[position_], s, n * kCharSize);
265
+ position_ += n;
266
+ }
267
+
268
+
269
+ // Add character padding to the builder. If count is non-positive,
270
+ // nothing is added to the builder.
271
+ void AddPadding(char c, int count) {
272
+ for (int i = 0; i < count; i++) {
273
+ AddCharacter(c);
274
+ }
275
+ }
276
+
277
+ // Finalize the string by 0-terminating it and returning the buffer.
278
+ char* Finalize() {
279
+ ASSERT(!is_finalized() && position_ < buffer_.length());
280
+ buffer_[position_] = '\0';
281
+ // Make sure nobody managed to add a 0-character to the
282
+ // buffer while building the string.
283
+ ASSERT(strlen(buffer_.start()) == static_cast<size_t>(position_));
284
+ position_ = -1;
285
+ ASSERT(is_finalized());
286
+ return buffer_.start();
287
+ }
288
+
289
+ private:
290
+ Vector<char> buffer_;
291
+ int position_;
292
+
293
+ bool is_finalized() const { return position_ < 0; }
294
+
295
+ DISALLOW_IMPLICIT_CONSTRUCTORS(StringBuilder);
296
+ };
297
+
298
+ // The type-based aliasing rule allows the compiler to assume that pointers of
299
+ // different types (for some definition of different) never alias each other.
300
+ // Thus the following code does not work:
301
+ //
302
+ // float f = foo();
303
+ // int fbits = *(int*)(&f);
304
+ //
305
+ // The compiler 'knows' that the int pointer can't refer to f since the types
306
+ // don't match, so the compiler may cache f in a register, leaving random data
307
+ // in fbits. Using C++ style casts makes no difference, however a pointer to
308
+ // char data is assumed to alias any other pointer. This is the 'memcpy
309
+ // exception'.
310
+ //
311
+ // Bit_cast uses the memcpy exception to move the bits from a variable of one
312
+ // type of a variable of another type. Of course the end result is likely to
313
+ // be implementation dependent. Most compilers (gcc-4.2 and MSVC 2005)
314
+ // will completely optimize BitCast away.
315
+ //
316
+ // There is an additional use for BitCast.
317
+ // Recent gccs will warn when they see casts that may result in breakage due to
318
+ // the type-based aliasing rule. If you have checked that there is no breakage
319
+ // you can use BitCast to cast one pointer type to another. This confuses gcc
320
+ // enough that it can no longer see that you have cast one pointer type to
321
+ // another thus avoiding the warning.
322
+ template <class Dest, class Source>
323
+ inline Dest BitCast(const Source& source) {
324
+ // Compile time assertion: sizeof(Dest) == sizeof(Source)
325
+ // A compile error here means your Dest and Source have different sizes.
326
+ DOUBLE_CONVERSION_UNUSED
327
+ typedef char VerifySizesAreEqual[sizeof(Dest) == sizeof(Source) ? 1 : -1];
328
+
329
+ Dest dest;
330
+ memmove(&dest, &source, sizeof(dest));
331
+ return dest;
332
+ }
333
+
334
+ template <class Dest, class Source>
335
+ inline Dest BitCast(Source* source) {
336
+ return BitCast<Dest>(reinterpret_cast<uintptr_t>(source));
337
+ }
338
+
339
+ } // namespace double_conversion
340
+
341
+ #endif // DOUBLE_CONVERSION_UTILS_H_
@@ -0,0 +1,10 @@
1
+ require "mkmf"
2
+
3
+ abort "should compile C++" unless have_library "stdc++"
4
+
5
+ $objs = ["hitokage_ext.o"]
6
+ Dir.glob(File.join(__dir__, "./double-conversion/*.cc")).each do |path|
7
+ $objs << path.gsub(/\.cc$/, '.o')
8
+ end
9
+
10
+ create_makefile "hitokage/hitokage_ext"
@@ -0,0 +1,26 @@
1
+ #include <ruby.h>
2
+ #include "double-conversion/double-conversion.h"
3
+
4
+ using namespace double_conversion;
5
+
6
+ static int flags = DoubleToStringConverter::EMIT_TRAILING_DECIMAL_POINT | DoubleToStringConverter::EMIT_TRAILING_ZERO_AFTER_POINT | DoubleToStringConverter::EMIT_POSITIVE_EXPONENT_SIGN;
7
+ static double_conversion::DoubleToStringConverter converter(flags, "Infinity", "NaN", 'e', -4, 15, 6, 0);
8
+ static char buffer[256];
9
+ static double_conversion::StringBuilder builder(buffer, sizeof(buffer));
10
+
11
+ static VALUE hitokage_to_s(VALUE self) {
12
+ double value = RFLOAT_VALUE(self);
13
+
14
+ builder.Reset();
15
+ bool result = converter.ToShortest(value, &builder);
16
+ if (result) {
17
+ return rb_str_new(buffer, builder.position());
18
+ } else {
19
+ return Qnil;
20
+ }
21
+ }
22
+
23
+ extern "C" void Init_hitokage_ext() {
24
+ rb_define_method(rb_cFloat, "hitokage_to_s", RUBY_METHOD_FUNC(hitokage_to_s), 0);
25
+ }
26
+
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'hitokage/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "hitokage"
8
+ spec.version = Hitokage::VERSION
9
+ spec.authors = ["Soutaro Matsumoto"]
10
+ spec.email = ["matsumoto@soutaro.com"]
11
+
12
+ spec.summary = %q{Yet another float to string conversion, a bit faster than Float#to_s}
13
+ spec.description = %q{Yet another float to string conversion}
14
+ spec.homepage = "https://github.com/soutaro/hitokage"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
18
+ spec.bindir = "exe"
19
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
+ spec.require_paths = ["lib"]
21
+
22
+ spec.add_development_dependency "bundler", "~> 1.11"
23
+ spec.add_development_dependency "rake", "~> 10.0"
24
+ spec.add_development_dependency "minitest", "~> 5.0"
25
+ spec.add_development_dependency "rake-compiler", "~> 0.9.7"
26
+ end