jaro_winkler 1.3.7 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7687918cbfcaa8ffb589f1d1383ac2e6611e235f
4
- data.tar.gz: e8129522a42193023a77593dddfe3917eafe3f68
3
+ metadata.gz: fe11a8c8be8cadef3f1f14f847c40a0a8e41268f
4
+ data.tar.gz: f509aaa81627917a4cf1017884f43b60dcd5483b
5
5
  SHA512:
6
- metadata.gz: be7befc2a7e5c5a2866ba7e4995bf99a0f9d75bfab3e01c806a1d39b10b0a27975f795f2330248e96e5673a8ce81d0ef01fa12a6d18f3f2cf73ff9de28764a60
7
- data.tar.gz: 3183fb3c534e1c1820ee16cd6a81bfcd35899ffc586e5ac064f5e4deace965d5507b83ca1d4a1fe3d8d30cc894da72eb998f1119ec3223a61c50c072d7e2029d
6
+ metadata.gz: 88fca6ab51c8a830de64e23b96f7efaaeeac01cd71735dd3820fc9e84e5de0027872014a8aef0278658d45455a7719a81601604929d17228fd6e8b6cb8fba919
7
+ data.tar.gz: ab7ee1020506ba6693e2b9878afddcb4a39bf7fb0be89b3958cfc5571f051b8295898cf050d517aa2c1951b23093517ce2d82d8d9c5544e816a4ac9e34c5bc6c
@@ -1,11 +1,11 @@
1
1
  unless RUBY_PLATFORM == 'java'
2
- require "mkmf"
2
+ require 'mkmf'
3
3
  $CFLAGS << ' -std=c99 '
4
- create_makefile("jaro_winkler/jaro_winkler")
4
+ create_makefile('jaro_winkler/jaro_winkler_ext')
5
5
  else
6
- dummy_makefile = open("Makefile", "wb")
6
+ dummy_makefile = open('Makefile', 'wb')
7
7
  dummy_makefile.puts '.PHONY: install'
8
8
  dummy_makefile.puts 'install:'
9
- dummy_makefile.puts "\t" + '@echo "Extensions not installed, falling back to pure Ruby version."'
9
+ dummy_makefile.puts "\t" + '@echo "C extension is not installed, fall back to pure Ruby version instead."'
10
10
  dummy_makefile.close
11
11
  end
@@ -6,19 +6,47 @@
6
6
  #include <stdlib.h>
7
7
  #include <ctype.h>
8
8
 
9
- double jaro_winkler_distance(char* short_str, int short_str_len, char* long_str, int long_str_len, LibJaroOption *opt){
9
+ #define SWAP(x, y) do{ __typeof__(x) SWAP = x; x = y; y = SWAP; }while(0)
10
+
11
+ double jaro_distance_from_codes(unsigned long long *codes1, int len1, unsigned long long *codes2, int len2, LibJaroOption *opt);
12
+ double jaro_winkler_distance_from_codes(unsigned long long *codes1, int len1, unsigned long long *codes2, int len2, LibJaroOption *opt);
13
+
14
+ double jaro_distance(char* short_str, int short_str_len, char* long_str, int long_str_len, LibJaroOption *opt){
10
15
  if(!short_str_len || !long_str_len) return 0.0;
11
16
 
12
- if(short_str_len > long_str_len){
13
- SWAP(short_str, long_str);
14
- SWAP(short_str_len, long_str_len);
15
- }
17
+ unsigned long long *short_codes, *long_codes;
18
+ int short_codes_len, long_codes_len;
19
+ string_to_codes(short_str, short_str_len, &short_codes, &short_codes_len);
20
+ string_to_codes(long_str, long_str_len, &long_codes, &long_codes_len);
21
+
22
+ double ret = jaro_distance_from_codes(short_codes, short_codes_len, long_codes, long_codes_len, opt);
23
+
24
+ free(short_codes); free(long_codes);
25
+ return ret;
26
+ }
27
+
28
+ double jaro_winkler_distance(char* short_str, int short_str_len, char* long_str, int long_str_len, LibJaroOption *opt){
29
+ if(!short_str_len || !long_str_len) return 0.0;
16
30
 
17
31
  unsigned long long *short_codes, *long_codes;
18
32
  int short_codes_len, long_codes_len;
19
33
  string_to_codes(short_str, short_str_len, &short_codes, &short_codes_len);
20
34
  string_to_codes(long_str, long_str_len, &long_codes, &long_codes_len);
21
35
 
36
+ double ret = jaro_winkler_distance_from_codes(short_codes, short_codes_len, long_codes, long_codes_len, opt);
37
+
38
+ free(short_codes); free(long_codes);
39
+ return ret;
40
+ }
41
+
42
+ double jaro_distance_from_codes(unsigned long long* short_codes, int short_codes_len, unsigned long long* long_codes, int long_codes_len, LibJaroOption *opt){
43
+ if(!short_codes_len || !long_codes_len) return 0.0;
44
+
45
+ if(short_codes_len > long_codes_len){
46
+ SWAP(short_codes, long_codes);
47
+ SWAP(short_codes_len, long_codes_len);
48
+ }
49
+
22
50
  if(opt->ignore_case){
23
51
  for(int i = 0; i < short_codes_len; i++) short_codes[i] = tolower(short_codes[i]);
24
52
  for(int i = 0; i < long_codes_len; i++) long_codes[i] = tolower(long_codes[i]);
@@ -27,10 +55,10 @@ double jaro_winkler_distance(char* short_str, int short_str_len, char* long_str,
27
55
  int window_size = long_codes_len/2 - 1;
28
56
  if(window_size < 0) window_size = 0;
29
57
 
30
- char short_codes_flag[short_str_len];
31
- char long_codes_flag[long_str_len];
32
- memset(short_codes_flag, 0, short_str_len);
33
- memset(long_codes_flag, 0, long_str_len);
58
+ char short_codes_flag[short_codes_len];
59
+ char long_codes_flag[long_codes_len];
60
+ memset(short_codes_flag, 0, short_codes_len);
61
+ memset(long_codes_flag, 0, long_codes_len);
34
62
 
35
63
  // count number of matching characters
36
64
  int match_count = 0;
@@ -46,10 +74,8 @@ double jaro_winkler_distance(char* short_str, int short_str_len, char* long_str,
46
74
  }
47
75
  }
48
76
  }
49
- if(!match_count){
50
- free(short_codes); free(long_codes);
51
- return 0.0;
52
- }
77
+
78
+ if(!match_count) return 0.0;
53
79
 
54
80
  // count number of transpositions
55
81
  int transposition_count = 0, j = 0, k = 0;
@@ -77,27 +103,20 @@ double jaro_winkler_distance(char* short_str, int short_str_len, char* long_str,
77
103
  break;
78
104
  }
79
105
 
80
- // jaro distance
81
- double jaro_distance;
82
106
  double m = (double)match_count;
83
107
  double t = (double)(transposition_count/2);
84
108
  if(opt->adj_table) m = similar_count/10.0 + m;
85
- jaro_distance = (m/short_codes_len + m/long_codes_len + (m-t)/m) / 3;
109
+ return (m/short_codes_len + m/long_codes_len + (m-t)/m) / 3;
110
+ }
86
111
 
87
- // jaro winkler distance
88
- if(!opt){
89
- static LibJaroOption default_opt = {.weight = DEFAULT_WEIGHT, .threshold = DEFAULT_THRESHOLD};
90
- opt = &default_opt;
91
- }
92
- if(jaro_distance < opt->threshold){
93
- free(short_codes); free(long_codes);
94
- return jaro_distance;
95
- }
112
+ double jaro_winkler_distance_from_codes(unsigned long long* short_codes, int short_codes_len, unsigned long long* long_codes, int long_codes_len, LibJaroOption *opt){
113
+ double jaro_distance = jaro_distance_from_codes(short_codes, short_codes_len, long_codes, long_codes_len, opt);
114
+
115
+ if(jaro_distance < opt->threshold) return jaro_distance;
96
116
  else{
97
117
  int prefix = 0;
98
118
  int max_4 = short_codes_len > 4 ? 4 : short_codes_len;
99
119
  for(prefix = 0; prefix < max_4 && short_codes[prefix] == long_codes[prefix]; prefix++);
100
- free(short_codes); free(long_codes);
101
120
  return jaro_distance + prefix*opt->weight*(1-jaro_distance);
102
121
  }
103
122
  }
@@ -1,7 +1,6 @@
1
1
  #ifndef LIBJARO_JARO_H
2
2
  #define LIBJARO_JARO_H
3
3
 
4
- #define SWAP(x, y) do{ __typeof__(x) SWAP = x; x = y; y = SWAP; }while(0)
5
4
  #define DEFAULT_WEIGHT 0.1
6
5
  #define DEFAULT_THRESHOLD 0.7
7
6
 
@@ -10,6 +9,9 @@ typedef struct LibJaroOption{
10
9
  char ignore_case, adj_table;
11
10
  } LibJaroOption;
12
11
 
12
+
13
+ static const LibJaroOption DEFAULT_OPT = {.weight = DEFAULT_WEIGHT, .threshold = DEFAULT_THRESHOLD, .ignore_case = 0, .adj_table = 0};
14
+ double jaro_distance(char *str1, int len1, char *str2, int len2, LibJaroOption *opt);
13
15
  double jaro_winkler_distance(char *str1, int len1, char *str2, int len2, LibJaroOption *opt);
14
16
 
15
17
  #endif
@@ -1,28 +1,45 @@
1
1
  #include "ruby.h"
2
2
  #include "jaro.h"
3
3
 
4
- VALUE rb_mJaroWinkler;
5
- VALUE distance(int argc, VALUE *argv, VALUE self);
4
+ VALUE rb_mJaroWinkler,
5
+ rb_eError,
6
+ rb_eInvalidWeightError;
6
7
 
7
- void Init_jaro_winkler(void){
8
+ VALUE rb_jaro_winkler_distance(int argc, VALUE *argv, VALUE self);
9
+ VALUE rb_jaro_distance(int argc, VALUE *argv, VALUE self);
10
+ VALUE distance(int argc, VALUE *argv, VALUE self, double (*distance_fn)(char *str1, int len1, char *str2, int len2, LibJaroOption *opt));
11
+
12
+ void Init_jaro_winkler_ext(void){
8
13
  rb_mJaroWinkler = rb_define_module("JaroWinkler");
9
- rb_define_module_function(rb_mJaroWinkler, "c_distance", distance, -1);
14
+ rb_eError = rb_define_class_under(rb_mJaroWinkler, "Error", rb_eRuntimeError);
15
+ rb_eInvalidWeightError = rb_define_class_under(rb_mJaroWinkler, "InvalidWeightError", rb_eError);
16
+ rb_define_module_function(rb_mJaroWinkler, "distance", rb_jaro_winkler_distance, -1);
17
+ rb_define_module_function(rb_mJaroWinkler, "jaro_distance", rb_jaro_distance, -1);
10
18
  }
11
19
 
12
- VALUE distance(int argc, VALUE *argv, VALUE self){
20
+
21
+ VALUE distance(int argc, VALUE *argv, VALUE self, double (*distance_fn)(char *str1, int len1, char *str2, int len2, LibJaroOption *opt)){
13
22
  VALUE s1, s2, opt;
14
23
  rb_scan_args(argc, argv, "2:", &s1, &s2, &opt);
15
- LibJaroOption c_opt = {.weight = DEFAULT_WEIGHT, .threshold = DEFAULT_THRESHOLD, .ignore_case = 0, .adj_table = 0};
24
+ LibJaroOption c_opt = DEFAULT_OPT;
16
25
  if(TYPE(opt) == T_HASH){
17
26
  VALUE weight = rb_hash_aref(opt, ID2SYM(rb_intern("weight"))),
18
27
  threshold = rb_hash_aref(opt, ID2SYM(rb_intern("threshold"))),
19
28
  ignore_case = rb_hash_aref(opt, ID2SYM(rb_intern("ignore_case"))),
20
29
  adj_table = rb_hash_aref(opt, ID2SYM(rb_intern("adj_table")));
21
30
  if(!NIL_P(weight)) c_opt.weight = NUM2DBL(weight);
22
- if(c_opt.weight > 0.25) rb_raise(rb_eRuntimeError, "Scaling factor should not exceed 0.25, otherwise the distance can become larger than 1.");
31
+ if(c_opt.weight > 0.25) rb_raise(rb_eInvalidWeightError, "Scaling factor should not exceed 0.25, otherwise the distance can become larger than 1.");
23
32
  if(!NIL_P(threshold)) c_opt.threshold = NUM2DBL(threshold);
24
33
  if(!NIL_P(ignore_case)) c_opt.ignore_case = (TYPE(ignore_case) == T_FALSE || NIL_P(ignore_case)) ? 0 : 1;
25
34
  if(!NIL_P(adj_table)) c_opt.adj_table = (TYPE(adj_table) == T_FALSE || NIL_P(adj_table)) ? 0 : 1;
26
35
  }
27
- return rb_float_new(jaro_winkler_distance(StringValuePtr(s1), RSTRING_LEN(s1), StringValuePtr(s2), RSTRING_LEN(s2), &c_opt));
36
+ return rb_float_new((*distance_fn)(StringValuePtr(s1), RSTRING_LEN(s1), StringValuePtr(s2), RSTRING_LEN(s2), &c_opt));
37
+ }
38
+
39
+ VALUE rb_jaro_distance(int argc, VALUE *argv, VALUE self){
40
+ return distance(argc, argv, self, jaro_distance);
41
+ }
42
+
43
+ VALUE rb_jaro_winkler_distance(int argc, VALUE *argv, VALUE self){
44
+ return distance(argc, argv, self, jaro_winkler_distance);
28
45
  }
@@ -1,76 +1,9 @@
1
- require 'jaro_winkler/fallback'
2
- require 'jaro_winkler/adjusting_table'
3
- require 'jaro_winkler/jaro_winkler.so' unless JaroWinkler.fallback?
4
- module JaroWinkler
5
- module_function
6
- def jaro_distance s1, s2, options = {}
7
- options[:adj_table]
8
- length1, length2 = s1.length, s2.length
9
- # Guarantee the length order
10
- if s1.length > s2.length
11
- s1, s2 = s2, s1
12
- length1, length2 = length2, length1
13
- end
14
- window_size = (length2 / 2) - 1
15
- window_size = 0 if window_size < 0
16
- matches = 0.0
17
- sim_matches = 0.0
18
- transpositions = 0
19
- previous_index = -1
20
- max_index = length2 - 1
21
- s1.chars.each_with_index do |c1, i|
22
- left = i - window_size
23
- right = i + window_size
24
- left = 0 if left < 0
25
- right = max_index if right > max_index
26
- matched = false
27
- sim_matched = false
28
- found = false
29
- s2[left..right].chars.each_with_index do |c2, j|
30
- if c1 == c2
31
- matched = true
32
- s2_index = left + j
33
- if !found && s2_index > previous_index
34
- previous_index = s2_index
35
- found = true
36
- end
37
- elsif options[:adj_table] && DEFAULT_ADJ_TABLE[c1][c2]
38
- sim_matched = true
39
- end
40
- end
41
- if matched
42
- matches += 1
43
- transpositions += 1 unless found
44
- elsif sim_matched # not matched but similarly matched
45
- sim_matches += 3
46
- end
47
- end
48
- # Don't divide transpositions by 2 since it's been counted directly by above code.
49
- similarity = matches
50
- similarity += sim_matches / 10 if options[:adj_table]
51
- matches == 0 ? 0 : (similarity / length1 + similarity / length2 + (matches - transpositions) / matches) / 3.0
52
- end
1
+ require 'jaro_winkler/version'
53
2
 
54
- def r_distance s1, s2, options = {}
55
- options = {weight: 0.1, threshold: 0.7, ignore_case: false, adj_table: false}.merge options
56
- weight, threshold, ignore_case = options[:weight], options[:threshold], options[:ignore_case]
57
- raise 'Scaling factor should not exceed 0.25, otherwise the distance can become larger than 1' if weight > 0.25
58
- s1, s2 = s1.upcase, s2.upcase if ignore_case
59
- distance = jaro_distance(s1, s2, options)
60
- prefix = 0
61
- max_length = [4, s1.length, s2.length].min
62
- s1[0, max_length].chars.each_with_index do |c1, i|
63
- c1 == s2[i] ? prefix += 1 : break
64
- end
65
- distance < threshold ? distance : distance + ((prefix * weight) * (1 - distance))
66
- end
67
-
68
- if JaroWinkler.fallback?
69
- alias :distance :r_distance
70
- alias :c_distance :r_distance
71
- module_function :distance, :c_distance
72
- else
73
- alias :distance :c_distance
74
- module_function :distance
75
- end
76
- end
3
+ case RUBY_PLATFORM
4
+ when 'java'
5
+ require 'jaro_winkler/jaro_winkler_pure'
6
+ else
7
+ require 'jaro_winkler/jaro_winkler_ext'
8
+ end
9
+
@@ -0,0 +1,125 @@
1
+ require 'jaro_winkler/adjusting_table'
2
+ module JaroWinkler
3
+ class Error < RuntimeError; end
4
+ class InvalidWeightError < Error; end
5
+
6
+ DEFAULT_WEIGHT = 0.1
7
+ DEFAULT_THRESHOLD = 0.7
8
+ DEFAULT_OPTIONS = {
9
+ jaro: {adj_table: false, ignore_case: false},
10
+ jaro_winkler: {weight: DEFAULT_WEIGHT, threshold: DEFAULT_THRESHOLD}
11
+ }
12
+
13
+ module_function
14
+
15
+ def distance str1, str2, options={}
16
+ _distance str1.codepoints.to_a, str2.codepoints.to_a, options
17
+ end
18
+
19
+ def jaro_distance str1, str2, options={}
20
+ _jaro_distance str1.codepoints.to_a, str2.codepoints.to_a, options
21
+ end
22
+
23
+ def _distance codes1, codes2, options={}
24
+ options = DEFAULT_OPTIONS[:jaro_winkler].merge options
25
+ raise InvalidWeightError if options[:weight] > 0.25
26
+ jaro_distance = _jaro_distance(codes1, codes2, options);
27
+
28
+ if jaro_distance < options[:threshold]
29
+ jaro_distance
30
+ else
31
+ codes1, codes2 = codes2, codes1 if codes1.length > codes2.length
32
+ len1, len2 = codes1.length, codes2.length
33
+ max_4 = len1 > 4 ? 4 : len1
34
+ prefix = 0
35
+ while prefix < max_4 && codes1[prefix] == codes2[prefix]
36
+ prefix += 1
37
+ end
38
+ jaro_distance + prefix * options[:weight] * (1 - jaro_distance)
39
+ end
40
+ end
41
+
42
+ def _jaro_distance codes1, codes2, options={}
43
+ options = DEFAULT_OPTIONS[:jaro].merge options
44
+
45
+ codes1, codes2 = codes2, codes1 if codes1.length > codes2.length
46
+ len1, len2 = codes1.length, codes2.length
47
+ return 0.0 if len1 == 0 || len2 == 0
48
+
49
+ if options[:ignore_case]
50
+ codes1.map!{ |c| c >= 97 && c <= 122 ? c -= 32 : c }
51
+ codes2.map!{ |c| c >= 97 && c <= 122 ? c -= 32 : c }
52
+ end
53
+
54
+ window = len2/2 - 1
55
+ window = 0 if(window < 0)
56
+ flags1, flags2 = 0, 0
57
+
58
+ # // count number of matching characters
59
+ match_count = 0;
60
+ i = 0
61
+ while i < len1
62
+ left = (i >= window) ? i - window : 0
63
+ right = (i + window <= len2 - 1) ? (i + window) : (len2 - 1)
64
+ right = len2 - 1 if right > len2 - 1
65
+ j = left
66
+ while j <= right
67
+ if flags2[j] == 0 && codes1[i] == codes2[j]
68
+ flags1 |= (1 << i)
69
+ flags2 |= (1 << j)
70
+ match_count += 1
71
+ break
72
+ end
73
+ j +=1
74
+ end
75
+ i += 1
76
+ end
77
+
78
+ return 0.0 if match_count == 0
79
+
80
+ # // count number of transpositions
81
+ transposition_count = j = k = 0
82
+ i = 0
83
+ while i < len1
84
+ if flags1[i] == 1
85
+ j = k
86
+ while j < len2
87
+ if flags2[j] == 1
88
+ k = j + 1;
89
+ break;
90
+ end
91
+ j += 1
92
+ end
93
+ transposition_count += 1 if codes1[i] != codes2[j]
94
+ end
95
+ i += 1
96
+ end
97
+
98
+ # // count similarities in nonmatched characters
99
+ similar_count = 0
100
+ if options[:adj_table] && len1 > match_count
101
+ i = 0
102
+ while i < len1
103
+ if flags1[i] == 0
104
+ j = 0
105
+ while j < len2
106
+ if flags2[j] == 0
107
+ if DEFAULT_ADJ_TABLE[codes1[i].chr(Encoding::UTF_8)][codes2[j].chr(Encoding::UTF_8)]
108
+ similar_count += 3
109
+ break
110
+ end
111
+ end
112
+ j += 1
113
+ end
114
+ end
115
+ i += 1
116
+ end
117
+ end
118
+
119
+ m = match_count.to_f
120
+ t = transposition_count/2
121
+ m = similar_count/10.0 + m if options[:adj_table]
122
+ (m/len1 + m/len2 + (m-t)/m) / 3
123
+ end
124
+
125
+ end
@@ -1,3 +1,3 @@
1
1
  module JaroWinkler
2
- VERSION = "1.3.7"
2
+ VERSION = '1.4.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jaro_winkler
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.7
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jian Weihang
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-09-28 00:00:00.000000000 Z
11
+ date: 2015-12-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -53,49 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: rspec
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: fuzzy-string-match
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: hotwater
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
- - !ruby/object:Gem::Dependency
98
- name: amatch
56
+ name: minitest
99
57
  requirement: !ruby/object:Gem::Requirement
100
58
  requirements:
101
59
  - - ">="
@@ -128,7 +86,7 @@ files:
128
86
  - ext/jaro_winkler/murmur_hash2.c
129
87
  - lib/jaro_winkler.rb
130
88
  - lib/jaro_winkler/adjusting_table.rb
131
- - lib/jaro_winkler/fallback.rb
89
+ - lib/jaro_winkler/jaro_winkler_pure.rb
132
90
  - lib/jaro_winkler/version.rb
133
91
  homepage: https://github.com/tonytonyjan/jaro_winkler
134
92
  licenses:
@@ -150,7 +108,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
150
108
  version: '0'
151
109
  requirements: []
152
110
  rubyforge_project:
153
- rubygems_version: 2.4.5.1
111
+ rubygems_version: 2.5.1
154
112
  signing_key:
155
113
  specification_version: 4
156
114
  summary: Ruby & C implementation of Jaro-Winkler distance algorithm which both support
@@ -1,6 +0,0 @@
1
- module JaroWinkler
2
- module_function
3
- def fallback?
4
- RUBY_PLATFORM == 'java'
5
- end
6
- end