yard 0.6.1 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of yard might be problematic. Click here for more details.
- data/ChangeLog +356 -0
- data/README.md +27 -5
- data/docs/GettingStarted.md +45 -6
- data/docs/Tags.md +16 -5
- data/docs/WhatsNew.md +60 -2
- data/lib/yard.rb +16 -37
- data/lib/yard/autoload.rb +5 -0
- data/lib/yard/cli/command.rb +18 -6
- data/lib/yard/cli/command_parser.rb +1 -0
- data/lib/yard/cli/config.rb +113 -0
- data/lib/yard/cli/gems.rb +16 -7
- data/lib/yard/cli/server.rb +30 -8
- data/lib/yard/cli/stats.rb +1 -1
- data/lib/yard/cli/yardoc.rb +16 -1
- data/lib/yard/code_objects/base.rb +7 -2
- data/lib/yard/code_objects/class_object.rb +1 -0
- data/lib/yard/code_objects/method_object.rb +1 -0
- data/lib/yard/code_objects/proxy.rb +8 -2
- data/lib/yard/config.rb +225 -0
- data/lib/yard/handlers/base.rb +29 -2
- data/lib/yard/handlers/processor.rb +1 -1
- data/lib/yard/handlers/ruby/class_handler.rb +6 -1
- data/lib/yard/handlers/ruby/constant_handler.rb +13 -15
- data/lib/yard/handlers/ruby/exception_handler.rb +1 -1
- data/lib/yard/handlers/ruby/extend_handler.rb +3 -0
- data/lib/yard/handlers/ruby/legacy/class_condition_handler.rb +1 -0
- data/lib/yard/handlers/ruby/legacy/class_handler.rb +7 -1
- data/lib/yard/handlers/ruby/legacy/constant_handler.rb +8 -10
- data/lib/yard/handlers/ruby/legacy/exception_handler.rb +1 -1
- data/lib/yard/handlers/ruby/legacy/extend_handler.rb +3 -0
- data/lib/yard/handlers/ruby/legacy/method_handler.rb +1 -0
- data/lib/yard/handlers/ruby/legacy/mixin_handler.rb +13 -2
- data/lib/yard/handlers/ruby/method_handler.rb +1 -0
- data/lib/yard/handlers/ruby/mixin_handler.rb +14 -4
- data/lib/yard/handlers/ruby/struct_handler_methods.rb +10 -1
- data/lib/yard/handlers/ruby/visibility_handler.rb +1 -1
- data/lib/yard/parser/c_parser.rb +26 -11
- data/lib/yard/parser/ruby/legacy/statement_list.rb +26 -9
- data/lib/yard/parser/source_parser.rb +5 -2
- data/lib/yard/serializers/yardoc_serializer.rb +2 -2
- data/lib/yard/server.rb +11 -0
- data/lib/yard/server/commands/frames_command.rb +1 -1
- data/lib/yard/server/commands/library_command.rb +22 -13
- data/lib/yard/server/commands/library_index_command.rb +1 -0
- data/lib/yard/server/commands/search_command.rb +2 -0
- data/lib/yard/server/commands/static_file_command.rb +6 -1
- data/lib/yard/server/templates/doc_server/processing/html/processing.erb +3 -3
- data/lib/yard/templates/helpers/html_helper.rb +1 -1
- data/lib/yard/templates/helpers/markup_helper.rb +13 -12
- data/lib/yard/verifier.rb +3 -1
- data/spec/cli/config_spec.rb +72 -0
- data/spec/cli/gems_spec.rb +81 -0
- data/spec/cli/server_spec.rb +35 -5
- data/spec/cli/stats_spec.rb +15 -0
- data/spec/cli/yardoc_spec.rb +39 -1
- data/spec/code_objects/base_spec.rb +2 -0
- data/spec/code_objects/method_object_spec.rb +5 -0
- data/spec/code_objects/proxy_spec.rb +20 -5
- data/spec/config_spec.rb +165 -0
- data/spec/handlers/alias_handler_spec.rb +7 -0
- data/spec/handlers/base_spec.rb +64 -0
- data/spec/handlers/class_condition_handler_spec.rb +13 -8
- data/spec/handlers/class_handler_spec.rb +54 -46
- data/spec/handlers/constant_handler_spec.rb +13 -0
- data/spec/handlers/examples/alias_handler_001.rb.txt +2 -0
- data/spec/handlers/examples/class_handler_001.rb.txt +12 -1
- data/spec/handlers/examples/constant_handler_001.rb.txt +6 -0
- data/spec/handlers/examples/exception_handler_001.rb.txt +8 -0
- data/spec/handlers/examples/method_handler_001.rb.txt +6 -0
- data/spec/handlers/examples/visibility_handler_001.rb.txt +3 -0
- data/spec/handlers/exception_handler_spec.rb +5 -0
- data/spec/handlers/extend_handler_spec.rb +4 -0
- data/spec/handlers/method_handler_spec.rb +5 -0
- data/spec/handlers/mixin_handler_spec.rb +10 -0
- data/spec/handlers/visibility_handler_spec.rb +4 -0
- data/spec/parser/base_spec.rb +1 -1
- data/spec/parser/c_parser_spec.rb +39 -1
- data/spec/parser/examples/override.c.txt +424 -0
- data/spec/parser/ruby/legacy/statement_list_spec.rb +11 -0
- data/spec/parser/source_parser_spec.rb +33 -1
- data/spec/server/commands/static_file_command_spec.rb +20 -3
- data/spec/server_spec.rb +10 -0
- data/spec/templates/examples/method001.html +33 -3
- data/spec/templates/examples/method001.txt +8 -1
- data/spec/templates/helpers/markup_helper_spec.rb +21 -26
- data/spec/templates/method_spec.rb +3 -1
- data/spec/verifier_spec.rb +5 -0
- data/templates/default/fulldoc/html/css/style.css +4 -1
- data/templates/default/fulldoc/html/js/app.js +1 -1
- data/templates/default/tags/html/option.erb +1 -3
- data/templates/default/tags/setup.rb +18 -15
- metadata +11 -4
- data/spec/yard_spec.rb +0 -55
@@ -8,6 +8,10 @@ describe "YARD::Handlers::Ruby::#{RUBY18 ? "Legacy::" : ""}ClassConditionHandler
|
|
8
8
|
names.each {|name| Registry.at("A##{name}not").should be_nil }
|
9
9
|
end
|
10
10
|
|
11
|
+
def no_undoc_error(code)
|
12
|
+
lambda { StubbedSourceParser.parse_string(code) }.should_not raise_error
|
13
|
+
end
|
14
|
+
|
11
15
|
it "should parse all unless blocks for complex conditions" do
|
12
16
|
verify_method :g
|
13
17
|
end
|
@@ -45,13 +49,14 @@ describe "YARD::Handlers::Ruby::#{RUBY18 ? "Legacy::" : ""}ClassConditionHandler
|
|
45
49
|
end
|
46
50
|
|
47
51
|
it "should not fail on complex conditions" do
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
52
|
+
log.should_not_receive(:warn)
|
53
|
+
log.should_not_receive(:error)
|
54
|
+
no_undoc_error "if defined?(A) && defined?(B); puts 'hi' end"
|
55
|
+
no_undoc_error(<<-eof)
|
56
|
+
(<<-TEST) unless defined?(ABCD_MODEL_TEST)
|
57
|
+
'String'
|
58
|
+
TEST
|
59
|
+
eof
|
60
|
+
no_undoc_error "if caller.none? { |l| l =~ %r{lib/rails/generators\\.rb:(\\d+):in `lookup!'$} }; end"
|
56
61
|
end
|
57
62
|
end
|
@@ -21,7 +21,7 @@ describe "YARD::Handlers::Ruby::#{RUBY18 ? "Legacy::" : ""}ClassHandler" do
|
|
21
21
|
end
|
22
22
|
|
23
23
|
it "should interpret class << ClassName as a class level block in ClassName's namespace" do
|
24
|
-
P("A::B::C
|
24
|
+
P("A::B::C.Hello").should be_instance_of(CodeObjects::MethodObject)
|
25
25
|
end
|
26
26
|
|
27
27
|
it "should make visibility public when parsing a block" do
|
@@ -174,64 +174,72 @@ describe "YARD::Handlers::Ruby::#{RUBY18 ? "Legacy::" : ""}ClassHandler" do
|
|
174
174
|
obj.tag(:param).types.should == ["IO"]
|
175
175
|
end
|
176
176
|
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
177
|
+
["SemiDoccedStruct", "NotAStruct"].each do |struct|
|
178
|
+
describe("Attributes on a " + (struct == "NotAStruct" ? "class" : "struct")) do
|
179
|
+
it "defines both readers and writers when @attr is used on Structs" do
|
180
|
+
obj = Registry.at(struct)
|
181
|
+
attrs = obj.attributes[:instance]
|
182
|
+
attrs[:first][:read].should_not be_nil
|
183
|
+
attrs[:first][:write].should_not be_nil
|
184
|
+
end
|
183
185
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
186
|
+
it "defines only a reader when only @attr_reader is used on Structs" do
|
187
|
+
obj = Registry.at(struct)
|
188
|
+
attrs = obj.attributes[:instance]
|
189
|
+
attrs[:second][:read].should_not be_nil
|
190
|
+
attrs[:second][:write].should be_nil
|
191
|
+
end
|
190
192
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
193
|
+
it "defines only a writer when only @attr_writer is used on Structs" do
|
194
|
+
obj = Registry.at(struct)
|
195
|
+
attrs = obj.attributes[:instance]
|
196
|
+
attrs[:third][:read].should be_nil
|
197
|
+
attrs[:third][:write].should_not be_nil
|
198
|
+
end
|
197
199
|
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
200
|
+
it "defines a reader with correct return types when @attr_reader is used on Structs" do
|
201
|
+
obj = Registry.at("#{struct}#second")
|
202
|
+
obj.tag(:return).types.should == ["Fixnum"]
|
203
|
+
end
|
202
204
|
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
205
|
+
it "defines a writer with correct parameter types when @attr_writer is used on Structs" do
|
206
|
+
obj = Registry.at("#{struct}#third=")
|
207
|
+
obj.tag(:param).types.should == ["Array"]
|
208
|
+
end
|
207
209
|
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
210
|
+
it "defines a reader and a writer when both @attr_reader and @attr_writer are used" do
|
211
|
+
obj = Registry.at(struct)
|
212
|
+
attrs = obj.attributes[:instance]
|
213
|
+
attrs[:fourth][:read].should_not be_nil
|
214
|
+
attrs[:fourth][:write].should_not be_nil
|
215
|
+
end
|
214
216
|
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
217
|
+
it "uses @attr_reader for the getter when both @attr_reader and @attr_writer are given" do
|
218
|
+
obj = Registry.at("#{struct}#fourth")
|
219
|
+
obj.tag(:return).types.should == ["#read"]
|
220
|
+
end
|
219
221
|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
222
|
+
it "uses @attr_writer for the setter when both @attr_reader and @attr_writer are given" do
|
223
|
+
obj = Registry.at("#{struct}#fourth=")
|
224
|
+
obj.tag(:param).types.should == ["IO"]
|
225
|
+
end
|
224
226
|
|
225
|
-
|
226
|
-
|
227
|
-
|
227
|
+
it "extracts text from @attr_reader" do
|
228
|
+
Registry.at("#{struct}#fourth").docstring.should == "returns a proc that reads"
|
229
|
+
end
|
228
230
|
|
229
|
-
|
230
|
-
|
231
|
+
it "extracts text from @attr_writer" do
|
232
|
+
Registry.at("#{struct}#fourth=").docstring.should == "sets the proc that writes stuff"
|
233
|
+
end
|
234
|
+
end
|
231
235
|
end
|
232
236
|
|
233
237
|
it "should inherit from a regular struct" do
|
234
238
|
Registry.at('RegularStruct').superclass.should == P(:Struct)
|
235
239
|
Registry.at('RegularStruct2').superclass.should == P(:Struct)
|
236
240
|
end
|
241
|
+
|
242
|
+
it "should handle inheritance from 'self'" do
|
243
|
+
Registry.at('Outer1::Inner1').superclass.should == Registry.at('Outer1')
|
244
|
+
end
|
237
245
|
end
|
@@ -45,6 +45,19 @@ describe "YARD::Handlers::Ruby::#{RUBY18 ? "Legacy::" : ""}ConstantHandler" do
|
|
45
45
|
obj.attributes[:instance].should be_empty
|
46
46
|
end
|
47
47
|
|
48
|
+
it "should maintain docstrings on structs defined via constants" do
|
49
|
+
obj = Registry.at("DocstringStruct")
|
50
|
+
obj.should_not be_nil
|
51
|
+
obj.docstring.should == "A crazy struct."
|
52
|
+
obj.attributes[:instance].should_not be_empty
|
53
|
+
a1 = Registry.at("DocstringStruct#bar")
|
54
|
+
a2 = Registry.at("DocstringStruct#baz")
|
55
|
+
a1.docstring.should == "An attr"
|
56
|
+
a1.tag(:return).types.should == ["String"]
|
57
|
+
a2.docstring.should == "Another attr"
|
58
|
+
a2.tag(:return).types.should == ["Number"]
|
59
|
+
end
|
60
|
+
|
48
61
|
it "should raise undocumentable error in 1.9 parser for Struct.new assignment to non-const" do
|
49
62
|
undoc_error "nonconst = Struct.new"
|
50
63
|
end if RUBY19
|
@@ -105,4 +105,15 @@ end
|
|
105
105
|
# @attr_reader [#read] fourth returns a proc that reads
|
106
106
|
# @attr_writer [IO] fourth sets the proc that writes stuff
|
107
107
|
class SemiDoccedStruct < Struct.new(:first, :second, :third, :fourth)
|
108
|
-
end
|
108
|
+
end
|
109
|
+
|
110
|
+
# @attr [String] first the first entry
|
111
|
+
# @attr_reader [Fixnum] second this only has a reader
|
112
|
+
# @attr_writer [Array] third this only has a writer
|
113
|
+
# @attr_reader [#read] fourth returns a proc that reads
|
114
|
+
# @attr_writer [IO] fourth sets the proc that writes stuff
|
115
|
+
class NotAStruct; end
|
116
|
+
|
117
|
+
class Outer1
|
118
|
+
class Inner1 < self; end
|
119
|
+
end
|
@@ -17,3 +17,9 @@ end
|
|
17
17
|
MyClass = Struct.new(:a, :b, :c)
|
18
18
|
NotMyClass = Struct.new("NotMyClass2", :b, :c)
|
19
19
|
MyEmptyStruct = Struct.new
|
20
|
+
|
21
|
+
# A crazy struct.
|
22
|
+
#
|
23
|
+
# @attr [String] bar An attr
|
24
|
+
# @attr [Number] baz Another attr
|
25
|
+
DocstringStruct = Struct.new(:bar, :baz)
|
@@ -36,4 +36,9 @@ describe "YARD::Handlers::Ruby::#{RUBY18 ? "Legacy::" : ""}ExceptionHandler" do
|
|
36
36
|
it "should ignore any raise calls on a receiver" do
|
37
37
|
P('Testing#mymethod9').tag(:raise).should be_nil
|
38
38
|
end
|
39
|
+
|
40
|
+
it "should handle raise expressions that are method calls" do
|
41
|
+
P('Testing#mymethod10').tag(:raise).should be_nil
|
42
|
+
P('Testing#mymethod11').tag(:raise).should be_nil
|
43
|
+
end
|
39
44
|
end
|
@@ -16,4 +16,8 @@ describe "YARD::Handlers::Ruby::#{RUBY18 ? "Legacy::" : ""}ExtendHandler" do
|
|
16
16
|
it "should extend module with correct namespace" do
|
17
17
|
Registry.at('Q::R::S').class_mixins.first.path.should == 'A'
|
18
18
|
end
|
19
|
+
|
20
|
+
it "should not allow extending self if object is a class" do
|
21
|
+
undoc_error "class Foo; extend self; end"
|
22
|
+
end
|
19
23
|
end
|
@@ -127,4 +127,9 @@ describe "YARD::Handlers::Ruby::#{RUBY18 ? "Legacy::" : ""}MethodHandler" do
|
|
127
127
|
undoc_error "error = Foo; def error.at(foo) end"
|
128
128
|
Registry.at('error').should be_nil
|
129
129
|
end
|
130
|
+
|
131
|
+
it "should allow class method to be defined on constant reference object" do
|
132
|
+
Registry.at('Foo.meth_on_const').should_not be_nil
|
133
|
+
Registry.at('Foo.meth2_on_const').should_not be_nil
|
134
|
+
end
|
130
135
|
end
|
@@ -37,4 +37,14 @@ describe "YARD::Handlers::Ruby::#{RUBY18 ? "Legacy::" : ""}MixinHandler" do
|
|
37
37
|
P("ABC::DEF::FOO").mixins.should == [P("ABC::FOO")]
|
38
38
|
P("ABC::DEF::BAR").mixins.should == [P("ABC::BAR")]
|
39
39
|
end
|
40
|
+
|
41
|
+
it "should raise undocumentable error if argument is variable" do
|
42
|
+
undoc_error "module X; include invalid; end"
|
43
|
+
Registry.at('X').mixins.should == []
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should parse all other arguments before erroring out on undocumentable error" do
|
47
|
+
undoc_error "module X; include invalid, Y; end"
|
48
|
+
Registry.at('X').mixins.should == [P('Y')]
|
49
|
+
end
|
40
50
|
end
|
@@ -27,4 +27,8 @@ describe "YARD::Handlers::Ruby::#{RUBY18 ? "Legacy::" : ""}VisibilityHandler" do
|
|
27
27
|
Registry.at('Testing#argument').should be_nil
|
28
28
|
Registry.at('Testing#method_call').should be_nil
|
29
29
|
end
|
30
|
+
|
31
|
+
it "should handle constants passed in as symbols" do
|
32
|
+
Registry.at('Testing#Foo').visibility.should == :private
|
33
|
+
end
|
30
34
|
end
|
data/spec/parser/base_spec.rb
CHANGED
@@ -7,7 +7,7 @@ describe YARD::Parser::Base do
|
|
7
7
|
end
|
8
8
|
|
9
9
|
it "should take 2 arguments" do
|
10
|
-
lambda { Parser::Base.new }.should raise_error(ArgumentError, /wrong number of arguments/)
|
10
|
+
lambda { Parser::Base.new }.should raise_error(ArgumentError, /wrong (number|#) of arguments/)
|
11
11
|
end
|
12
12
|
|
13
13
|
it "should raise NotImplementedError on #initialize" do
|
@@ -5,6 +5,9 @@ describe YARD::Parser::CParser do
|
|
5
5
|
before(:all) do
|
6
6
|
file = File.join(File.dirname(__FILE__), 'examples', 'array.c.txt')
|
7
7
|
@parser = Parser::CParser.new(IO.read(file)).parse
|
8
|
+
|
9
|
+
override_file = File.join(File.dirname(__FILE__), 'examples', 'override.c.txt')
|
10
|
+
@override_parser = Parser::CParser.new(IO.read(override_file)).parse
|
8
11
|
end
|
9
12
|
|
10
13
|
describe '#parse' do
|
@@ -20,4 +23,39 @@ describe YARD::Parser::CParser do
|
|
20
23
|
obj.tags(:overload).size.should > 1
|
21
24
|
end
|
22
25
|
end
|
23
|
-
|
26
|
+
|
27
|
+
describe '#find_override_comment' do
|
28
|
+
it "should parse GMP::Z class" do
|
29
|
+
z = YARD::Registry.at('GMP::Z')
|
30
|
+
z.should_not be_nil
|
31
|
+
z.docstring.should_not be_blank
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should parse GMP::Z methods w/ bodies" do
|
35
|
+
add = YARD::Registry.at('GMP::Z#+')
|
36
|
+
add.docstring.should_not be_blank
|
37
|
+
add.source.should_not be_nil
|
38
|
+
add.source.should_not be_empty
|
39
|
+
|
40
|
+
add_self = YARD::Registry.at('GMP::Z#+')
|
41
|
+
add_self.docstring.should_not be_blank
|
42
|
+
add_self.source.should_not be_nil
|
43
|
+
add_self.source.should_not be_empty
|
44
|
+
|
45
|
+
sqrtrem = YARD::Registry.at('GMP::Z#+')
|
46
|
+
sqrtrem.docstring.should_not be_blank
|
47
|
+
sqrtrem.source.should_not be_nil
|
48
|
+
sqrtrem.source.should_not be_empty
|
49
|
+
end
|
50
|
+
|
51
|
+
it "should parse GMP::Z methods w/o bodies" do
|
52
|
+
neg = YARD::Registry.at('GMP::Z#neg')
|
53
|
+
neg.docstring.should_not be_blank
|
54
|
+
neg.source.should be_nil
|
55
|
+
|
56
|
+
neg_self = YARD::Registry.at('GMP::Z#neg')
|
57
|
+
neg_self.docstring.should_not be_blank
|
58
|
+
neg_self.source.should be_nil
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end if CONTINUATIONS_SUPPORTED
|
@@ -0,0 +1,424 @@
|
|
1
|
+
#include <gmpz.h>
|
2
|
+
#include <gmpq.h>
|
3
|
+
#include <gmpf.h>
|
4
|
+
|
5
|
+
/*
|
6
|
+
* Document-class: GMP::Z
|
7
|
+
*
|
8
|
+
* GMP Multiple Precision Integer.
|
9
|
+
*
|
10
|
+
* Instances of this class can store variables of the type mpz_t. This class
|
11
|
+
* also contains many methods that act as the functions for mpz_t variables,
|
12
|
+
* as well as a few methods that attempt to make this library more Ruby-ish.
|
13
|
+
*/
|
14
|
+
|
15
|
+
/**********************************************************************
|
16
|
+
* Macros *
|
17
|
+
**********************************************************************/
|
18
|
+
|
19
|
+
/*
|
20
|
+
* DEFUN_INT2INT defines two functions. The first takes a GMP::Z as
|
21
|
+
* self, calls mpz_fname on the contained mpz_t, whose arguments are
|
22
|
+
* exactly (0) the return argument and (1) self. The second is the same
|
23
|
+
* destructive method.
|
24
|
+
*/
|
25
|
+
#define DEFUN_INT2INT(fname,mpz_fname) \
|
26
|
+
static VALUE r_gmpz_##fname(VALUE self) \
|
27
|
+
{ \
|
28
|
+
MP_INT *self_val, *res_val; \
|
29
|
+
VALUE res; \
|
30
|
+
mpz_get_struct(self, self_val); \
|
31
|
+
mpz_make_struct_init(res, res_val); \
|
32
|
+
mpz_fname(res_val, self_val); \
|
33
|
+
return res; \
|
34
|
+
} \
|
35
|
+
\
|
36
|
+
static VALUE r_gmpz_##fname##_self(VALUE self) \
|
37
|
+
{ \
|
38
|
+
MP_INT *self_val; \
|
39
|
+
mpz_get_struct(self, self_val); \
|
40
|
+
mpz_fname(self_val, self_val); \
|
41
|
+
return self; \
|
42
|
+
}
|
43
|
+
|
44
|
+
|
45
|
+
/**********************************************************************
|
46
|
+
* Integer Arithmetic *
|
47
|
+
**********************************************************************/
|
48
|
+
|
49
|
+
/*
|
50
|
+
* call-seq:
|
51
|
+
* a + b
|
52
|
+
*
|
53
|
+
* Adds _a_ to _b_. _b_ must be an instance of one of:
|
54
|
+
* * GMP::Z
|
55
|
+
* * Fixnum
|
56
|
+
* * GMP::Q
|
57
|
+
* * GMP::F
|
58
|
+
* * Bignum
|
59
|
+
*/
|
60
|
+
VALUE r_gmpz_add(VALUE self, VALUE arg)
|
61
|
+
{
|
62
|
+
MP_INT *self_val, *arg_val, *res_val;
|
63
|
+
VALUE res;
|
64
|
+
|
65
|
+
mpz_get_struct(self,self_val);
|
66
|
+
|
67
|
+
if (GMPZ_P(arg)) {
|
68
|
+
mpz_get_struct(arg,arg_val);
|
69
|
+
mpz_make_struct_init(res, res_val);
|
70
|
+
mpz_add(res_val, self_val, arg_val);
|
71
|
+
} else if (FIXNUM_P(arg)) {
|
72
|
+
mpz_make_struct_init(res, res_val);
|
73
|
+
if (FIX2NUM(arg) > 0)
|
74
|
+
mpz_add_ui(res_val, self_val, FIX2NUM(arg));
|
75
|
+
else
|
76
|
+
mpz_sub_ui(res_val, self_val, -FIX2NUM(arg));
|
77
|
+
} else if (GMPQ_P(arg)) {
|
78
|
+
return r_gmpq_add(arg, self);
|
79
|
+
} else if (GMPF_P(arg)) {
|
80
|
+
#ifndef MPFR
|
81
|
+
return r_gmpf_add(arg, self);
|
82
|
+
#else
|
83
|
+
return rb_funcall(arg, rb_intern("+"), 1, self);
|
84
|
+
#endif
|
85
|
+
} else if (BIGNUM_P(arg)) {
|
86
|
+
mpz_make_struct_init(res, res_val);
|
87
|
+
mpz_init(res_val);
|
88
|
+
mpz_set_bignum(res_val, arg);
|
89
|
+
mpz_add(res_val, res_val, self_val);
|
90
|
+
} else {
|
91
|
+
typeerror(ZQFXB);
|
92
|
+
}
|
93
|
+
return res;
|
94
|
+
}
|
95
|
+
|
96
|
+
/*
|
97
|
+
* call-seq:
|
98
|
+
* a.add!(_b_)
|
99
|
+
*
|
100
|
+
* Adds _a_ to _b_ in-place, setting _a_ to the sum. _b_ must be an instance of one of:
|
101
|
+
* * GMP::Z
|
102
|
+
* * Fixnum
|
103
|
+
* * GMP::Q
|
104
|
+
* * GMP::F
|
105
|
+
* * Bignum
|
106
|
+
*/
|
107
|
+
VALUE r_gmpz_add_self(VALUE self, VALUE arg)
|
108
|
+
{
|
109
|
+
MP_INT *self_val, *arg_val;
|
110
|
+
|
111
|
+
mpz_get_struct(self,self_val);
|
112
|
+
|
113
|
+
if (GMPZ_P(arg)) {
|
114
|
+
mpz_get_struct(arg,arg_val);
|
115
|
+
mpz_add(self_val, self_val, arg_val);
|
116
|
+
} else if (FIXNUM_P(arg)) {
|
117
|
+
if (FIX2NUM(arg) > 0)
|
118
|
+
mpz_add_ui(self_val, self_val, FIX2NUM(arg));
|
119
|
+
else
|
120
|
+
mpz_sub_ui(self_val, self_val, -FIX2NUM(arg));
|
121
|
+
} else if (BIGNUM_P(arg)) {
|
122
|
+
mpz_temp_from_bignum(arg_val, arg);
|
123
|
+
mpz_add(self_val, self_val, arg_val);
|
124
|
+
mpz_temp_free(arg_val);
|
125
|
+
} else {
|
126
|
+
typeerror(ZXB);
|
127
|
+
}
|
128
|
+
return Qnil;
|
129
|
+
}
|
130
|
+
|
131
|
+
/*
|
132
|
+
* call-seq:
|
133
|
+
* a - b
|
134
|
+
*
|
135
|
+
* Subtracts _b_ from _a_. _b_ must be an instance of one of:
|
136
|
+
* * GMP::Z
|
137
|
+
* * Fixnum
|
138
|
+
* * GMP::Q
|
139
|
+
* * GMP::F
|
140
|
+
* * Bignum
|
141
|
+
*/
|
142
|
+
VALUE r_gmpz_sub(VALUE self, VALUE arg)
|
143
|
+
{
|
144
|
+
MP_RAT *res_val_q, *arg_val_q;
|
145
|
+
MP_INT *self_val, *arg_val, *res_val;
|
146
|
+
MP_FLOAT *arg_val_f, *res_val_f;
|
147
|
+
VALUE res;
|
148
|
+
unsigned long prec;
|
149
|
+
|
150
|
+
mpz_get_struct(self,self_val);
|
151
|
+
|
152
|
+
if (GMPZ_P(arg)) {
|
153
|
+
mpz_make_struct_init(res, res_val);
|
154
|
+
mpz_get_struct(arg,arg_val);
|
155
|
+
mpz_sub (res_val, self_val, arg_val);
|
156
|
+
} else if (FIXNUM_P(arg)) {
|
157
|
+
mpz_make_struct_init(res, res_val);
|
158
|
+
if (FIX2NUM(arg) > 0)
|
159
|
+
mpz_sub_ui (res_val, self_val, FIX2NUM(arg));
|
160
|
+
else
|
161
|
+
mpz_add_ui (res_val, self_val, -FIX2NUM(arg));
|
162
|
+
} else if (GMPQ_P(arg)) {
|
163
|
+
mpq_make_struct_init(res, res_val_q);
|
164
|
+
mpq_get_struct(arg,arg_val_q);
|
165
|
+
mpz_set (mpq_denref(res_val_q), mpq_denref(arg_val_q));
|
166
|
+
mpz_mul (mpq_numref(res_val_q), mpq_denref(arg_val_q), self_val);
|
167
|
+
mpz_sub (mpq_numref(res_val_q), mpq_numref(res_val_q), mpq_numref(arg_val_q));
|
168
|
+
} else if (GMPF_P(arg)) {
|
169
|
+
mpf_get_struct_prec (arg, arg_val_f, prec);
|
170
|
+
mpf_make_struct_init(res, res_val_f, prec);
|
171
|
+
mpf_set_z (res_val_f, self_val);
|
172
|
+
mpf_sub (res_val_f, res_val_f, arg_val_f);
|
173
|
+
} else if (BIGNUM_P(arg)) {
|
174
|
+
mpz_make_struct_init(res, res_val);
|
175
|
+
mpz_set_bignum (res_val, arg);
|
176
|
+
mpz_sub (res_val, self_val, res_val);
|
177
|
+
} else {
|
178
|
+
typeerror (ZQFXB);
|
179
|
+
}
|
180
|
+
return res;
|
181
|
+
}
|
182
|
+
|
183
|
+
/*
|
184
|
+
* call-seq:
|
185
|
+
* a.sub!(b)
|
186
|
+
*
|
187
|
+
* Subtracts _b_ from _a_ in-place, setting _a_ to the difference. _b_ must be an
|
188
|
+
* instance of one of:
|
189
|
+
* * GMP::Z
|
190
|
+
* * Fixnum
|
191
|
+
* * GMP::Q
|
192
|
+
* * GMP::F
|
193
|
+
* * Bignum
|
194
|
+
*/
|
195
|
+
VALUE r_gmpz_sub_self(VALUE self, VALUE arg)
|
196
|
+
{
|
197
|
+
MP_INT *self_val, *arg_val;
|
198
|
+
|
199
|
+
mpz_get_struct(self,self_val);
|
200
|
+
|
201
|
+
if (GMPZ_P(arg)) {
|
202
|
+
mpz_get_struct(arg, arg_val);
|
203
|
+
mpz_sub (self_val, self_val, arg_val);
|
204
|
+
} else if (FIXNUM_P(arg)) {
|
205
|
+
if (FIX2NUM(arg) > 0)
|
206
|
+
mpz_sub_ui (self_val, self_val, FIX2NUM(arg));
|
207
|
+
else
|
208
|
+
mpz_add_ui (self_val, self_val, -FIX2NUM(arg));
|
209
|
+
} else if (BIGNUM_P(arg)) {
|
210
|
+
mpz_temp_from_bignum(arg_val, arg);
|
211
|
+
mpz_sub (self_val, self_val, arg_val);
|
212
|
+
mpz_temp_free (arg_val);
|
213
|
+
} else {
|
214
|
+
typeerror (ZXB);
|
215
|
+
}
|
216
|
+
return Qnil;
|
217
|
+
}
|
218
|
+
|
219
|
+
/*
|
220
|
+
* call-seq:
|
221
|
+
* a * b
|
222
|
+
*
|
223
|
+
* Multiplies _a_ with _b_. _a_ must be an instance of one of
|
224
|
+
* * GMP::Z
|
225
|
+
* * Fixnum
|
226
|
+
* * GMP::Q
|
227
|
+
* * GMP::F
|
228
|
+
* * Bignum
|
229
|
+
*/
|
230
|
+
VALUE r_gmpz_mul(VALUE self, VALUE arg)
|
231
|
+
{
|
232
|
+
MP_INT *self_val, *arg_val, *res_val;
|
233
|
+
VALUE res;
|
234
|
+
|
235
|
+
mpz_get_struct(self,self_val);
|
236
|
+
|
237
|
+
if (GMPZ_P(arg)) {
|
238
|
+
mpz_make_struct_init(res, res_val);
|
239
|
+
mpz_get_struct(arg,arg_val);
|
240
|
+
mpz_mul(res_val, self_val, arg_val);
|
241
|
+
} else if (FIXNUM_P(arg)) {
|
242
|
+
mpz_make_struct_init(res, res_val);
|
243
|
+
mpz_mul_si(res_val, self_val, FIX2NUM(arg));
|
244
|
+
} else if (GMPQ_P(arg)) {
|
245
|
+
return r_gmpq_mul(arg, self);
|
246
|
+
} else if (GMPF_P(arg)) {
|
247
|
+
#ifndef MPFR
|
248
|
+
return r_gmpf_mul(arg, self);
|
249
|
+
#else
|
250
|
+
return rb_funcall(arg, rb_intern("*"), 1, self);
|
251
|
+
#endif
|
252
|
+
} else if (BIGNUM_P(arg)) {
|
253
|
+
mpz_make_struct_init(res, res_val);
|
254
|
+
mpz_set_bignum(res_val, arg);
|
255
|
+
mpz_mul(res_val, res_val, self_val);
|
256
|
+
} else {
|
257
|
+
typeerror(ZQFXB);
|
258
|
+
}
|
259
|
+
return res;
|
260
|
+
}
|
261
|
+
|
262
|
+
/*
|
263
|
+
* call-seq:
|
264
|
+
* a.addmul!(b, c)
|
265
|
+
*
|
266
|
+
* @since 0.4.17
|
267
|
+
*
|
268
|
+
* Sets _a_ to _a_ plus _b_ times _c_. _b_ and _c_ must each be an instance of one of
|
269
|
+
* * GMP::Z
|
270
|
+
* * Fixnum
|
271
|
+
* * Bignum
|
272
|
+
*/
|
273
|
+
VALUE r_gmpz_addmul_self(VALUE self, VALUE b, VALUE c)
|
274
|
+
{
|
275
|
+
MP_INT *self_val, *b_val, *c_val;
|
276
|
+
int free_b_val = 0;
|
277
|
+
|
278
|
+
if (GMPZ_P(b)) {
|
279
|
+
mpz_get_struct(b, b_val);
|
280
|
+
} else if (FIXNUM_P(b)) {
|
281
|
+
mpz_temp_alloc(b_val);
|
282
|
+
mpz_init_set_si(b_val, FIX2NUM(b));
|
283
|
+
free_b_val = 1;
|
284
|
+
} else if (BIGNUM_P(b)) {
|
285
|
+
mpz_temp_from_bignum(b_val, b);
|
286
|
+
free_b_val = 1;
|
287
|
+
} else {
|
288
|
+
typeerror_as(ZXB, "addend");
|
289
|
+
}
|
290
|
+
mpz_get_struct(self, self_val);
|
291
|
+
|
292
|
+
if (GMPZ_P(c)) {
|
293
|
+
mpz_get_struct(c, c_val);
|
294
|
+
mpz_addmul(self_val, b_val, c_val);
|
295
|
+
} else if (FIXNUM_P(c)) {
|
296
|
+
if (FIX2NUM(c) < 0)
|
297
|
+
{
|
298
|
+
if (free_b_val) { mpz_temp_free(b_val); }
|
299
|
+
rb_raise(rb_eRangeError, "multiplicand (Fixnum) must be nonnegative");
|
300
|
+
}
|
301
|
+
mpz_addmul_ui(self_val, b_val, FIX2NUM(c));
|
302
|
+
} else if (BIGNUM_P(c)) {
|
303
|
+
mpz_temp_from_bignum(c_val, c);
|
304
|
+
mpz_addmul(self_val, b_val, c_val);
|
305
|
+
mpz_temp_free(c_val);
|
306
|
+
} else {
|
307
|
+
if (free_b_val)
|
308
|
+
mpz_temp_free(b_val);
|
309
|
+
typeerror_as(ZXB, "multiplicand");
|
310
|
+
}
|
311
|
+
if (free_b_val)
|
312
|
+
mpz_temp_free(b_val);
|
313
|
+
return self;
|
314
|
+
}
|
315
|
+
|
316
|
+
/*
|
317
|
+
* Document-method: neg
|
318
|
+
*
|
319
|
+
* call-seq:
|
320
|
+
* a.neg
|
321
|
+
* -a
|
322
|
+
*
|
323
|
+
* Returns -_a_.
|
324
|
+
*/
|
325
|
+
/*
|
326
|
+
* Document-method: neg!
|
327
|
+
*
|
328
|
+
* call-seq:
|
329
|
+
* a.neg!
|
330
|
+
*
|
331
|
+
* Sets _a_ to -_a_.
|
332
|
+
*/
|
333
|
+
DEFUN_INT2INT(neg, mpz_neg)
|
334
|
+
/*
|
335
|
+
* Document-method: abs
|
336
|
+
*
|
337
|
+
* call-seq:
|
338
|
+
* a.abs
|
339
|
+
*
|
340
|
+
* Returns the absolute value of _a_.
|
341
|
+
*/
|
342
|
+
/*
|
343
|
+
* Document-method: abs!
|
344
|
+
*
|
345
|
+
* call-seq:
|
346
|
+
* a.abs!
|
347
|
+
*
|
348
|
+
* Sets _a_ to its absolute value.
|
349
|
+
*/
|
350
|
+
DEFUN_INT2INT(abs, mpz_abs)
|
351
|
+
|
352
|
+
|
353
|
+
/**********************************************************************
|
354
|
+
* Integer Roots *
|
355
|
+
**********************************************************************/
|
356
|
+
|
357
|
+
/*
|
358
|
+
* Document-method: sqrt
|
359
|
+
*
|
360
|
+
* call-seq:
|
361
|
+
* a.sqrt
|
362
|
+
*
|
363
|
+
* Returns the truncated integer part of the square root of _a_.
|
364
|
+
*/
|
365
|
+
/*
|
366
|
+
* Document-method: sqrt!
|
367
|
+
*
|
368
|
+
* call-seq:
|
369
|
+
* a.sqrt!
|
370
|
+
*
|
371
|
+
* Sets _a_ to the truncated integer part of its square root.
|
372
|
+
*/
|
373
|
+
DEFUN_INT2INT(sqrt, mpz_sqrt)
|
374
|
+
|
375
|
+
/*
|
376
|
+
* call-seq:
|
377
|
+
* a.sqrtrem #=> s, r
|
378
|
+
*
|
379
|
+
* Returns the truncated integer part of the square root of _a_ as _s_ and the remainder
|
380
|
+
* <i>a - s * s</i> as _r_, which will be zero if _a_ is a perfect square.
|
381
|
+
*/
|
382
|
+
static VALUE r_gmpz_sqrtrem(VALUE self)
|
383
|
+
{
|
384
|
+
MP_INT *self_val, *sqrt_val, *rem_val;
|
385
|
+
VALUE sqrt, rem;
|
386
|
+
|
387
|
+
mpz_get_struct(self, self_val);
|
388
|
+
mpz_make_struct_init(sqrt, sqrt_val);
|
389
|
+
mpz_make_struct_init(rem, rem_val);
|
390
|
+
mpz_sqrtrem(sqrt_val, rem_val, self_val);
|
391
|
+
return rb_assoc_new(sqrt, rem);
|
392
|
+
}
|
393
|
+
|
394
|
+
|
395
|
+
/**********************************************************************
|
396
|
+
* Init function *
|
397
|
+
**********************************************************************/
|
398
|
+
|
399
|
+
void init_gmpz()
|
400
|
+
{
|
401
|
+
mGMP = rb_define_module("GMP");
|
402
|
+
rb_define_module_function(mGMP, "Z", r_gmpmod_z, -1);
|
403
|
+
|
404
|
+
cGMP_Z = rb_define_class_under(mGMP, "Z", rb_cInteger);
|
405
|
+
|
406
|
+
// Integer Arithmetic
|
407
|
+
rb_define_method(cGMP_Z, "+", r_gmpz_add, 1);
|
408
|
+
rb_define_method(cGMP_Z, "add!", r_gmpz_add_self, 1);
|
409
|
+
rb_define_method(cGMP_Z, "-", r_gmpz_sub, 1);
|
410
|
+
rb_define_method(cGMP_Z, "sub!", r_gmpz_sub_self, 1);
|
411
|
+
rb_define_method(cGMP_Z, "*", r_gmpz_mul, 1);
|
412
|
+
rb_define_method(cGMP_Z, "addmul!", r_gmpz_addmul_self, 2);
|
413
|
+
rb_define_method(cGMP_Z, "neg", r_gmpz_neg, 0);
|
414
|
+
rb_define_method(cGMP_Z, "neg!", r_gmpz_neg_self, 0);
|
415
|
+
rb_define_method(cGMP_Z, "-@", r_gmpz_neg, 0);
|
416
|
+
rb_define_method(cGMP_Z, "abs", r_gmpz_abs, 0);
|
417
|
+
rb_define_method(cGMP_Z, "abs!", r_gmpz_abs_self, 0);
|
418
|
+
|
419
|
+
// Integer Roots
|
420
|
+
rb_define_method(cGMP_Z, "root", r_gmpz_root, 1);
|
421
|
+
rb_define_method(cGMP_Z, "sqrt", r_gmpz_sqrt, 0);
|
422
|
+
rb_define_method(cGMP_Z, "sqrt!", r_gmpz_sqrt_self, 0);
|
423
|
+
rb_define_method(cGMP_Z, "sqrtrem", r_gmpz_sqrtrem, 0);
|
424
|
+
}
|