0

To follow up a question I asked already and kind of solved as far as I got the answer to my question despite the fact a new problem was borne from the solved one which is this:

The problem in using the Complex API is that it doesn't recognise the shape method from the NMatrix API:

So when I run the following spec code on my compiled C extension:

  it "Creates a new FFTW.r2c object and takes an a 1D NMatrix as its argument" do
    n = NMatrix.new([4], [3.10, 1.73, 1.04, 2.83])

    r = FFTW.Z(n)
    i = FFTW.Z(FFTW.r2c_one(r))
    #expect(fftw).to eq(fftw)
  end

There is an error because shape belongs to the nmatrix class.

 FFTW Creates a new FFTW.r2c object and takes an a 1D NMatrix as its argument
     Failure/Error: i = FFTW.Z(FFTW.r2c_one(r))
     NoMethodError:
       undefined method `shape' for NMatrix:Class
     # ./spec/fftw_spec.rb:26:in `r2c_one'
     # ./spec/fftw_spec.rb:26:in `block (2 levels) in <top (required)>'

Shape is called from the nmatrix class so I can understand why this has happened but not figure out how to get round it.

The result of

  it "Creates a new FFTW.r2c object and takes an a 1D NMatrix as its argument" do
    n = NMatrix.new([4], [3.10, 1.73, 1.04, 2.83])

    fftw = FFTW.Z(n)
    expect(fftw).to eq(fftw)
  end

is

/home/magpie/.rvm/rubies/ruby-2.1.2/bin/ruby -I/home/magpie/.rvm/gems/ruby-2.1.2/gems/rspec-core-3.0.4/lib:/home/magpie/.rvm/gems/ruby-2.1.2/gems/rspec-support-3.0.4/lib -S /home/magpie/.rvm/gems/ruby-2.1.2/gems/rspec-core-3.0.4/exe/rspec ./spec/fftw_spec.rb
./lib/fftw/fftw.so found!

FFTW
  creates an NMatrix object
  Fills dense with individual assignments
  Creates a new FFTW.r2c object and takes an a 1D NMatrix as its argument

Finished in 0.00091 seconds (files took 0.07199 seconds to load)
3 examples, 0 failures
Community
  • 1
  • 1
Magpie
  • 607
  • 2
  • 7
  • 26
  • This doesn't seem to match the spec in your source `fftw_spec.rb`. Is there a reason for that? – acsmith Aug 25 '14 at 17:58
  • @acsmith I'm wanting to fix it before I push it is all. – Magpie Aug 25 '14 at 18:05
  • 1
    Oh, got it. Well it looks to me like your `#Z` method is returning the actual `Class` `NMatrix`, rather than an instance of `NMatrix`, which is why you're getting the undefined method (as `#shape` is defined as an instance method). Can you `pp` the result of `FFTW.Z(n)`? – acsmith Aug 25 '14 at 18:21
  • so I should use `rb_define_method` instead of `rb_define_singleton_method` to define Z in the Init_fftw method @acsmith ? – Magpie Aug 25 '14 at 18:34
  • @acsmith what do you mean `pp` the result? I've added what I think you were asking for in the question let me know if I need to revise it. – Magpie Aug 25 '14 at 18:35
  • Oh, sorry, I meant to just print the result of the `#Z` call. `pp` is just a gem that NMatrix uses to make printed matrices look pretty. (It stands for pretty print.) – acsmith Aug 25 '14 at 18:46
  • @acsmith does my edit to the question make sense? When I add on ` fftw = FFTW.Z(n) FFTW.r2c_one(fftw)` I still get that same shape error though. I've split it up into methods now in the C – Magpie Aug 25 '14 at 18:53

1 Answers1

2

I think the issue is this chunk of code in fftw.cpp

lines 51-56:

static VALUE
fftw_shape(VALUE self)
{
  // shape is a ruby array, e.g. [2, 2] for a 2x2 matrix
  return rb_funcall(cNMatrix, rb_intern("shape"), 0);
}

You're trying to call shape on the NMatrix class here. rb_funcall works like this:

rb_funcall(object_to_invoke_method, method_to_invoke, number_of_args, ...)

The problem is that you have cNMatrix in the first argument position, so it's trying to send the shape method to the NMatrix class rather than to the object. So you really want to be calling it on the nmatrix object like:

static VALUE
fftw_shape(VALUE self, VALUE nmatrix)
{
  // shape is a ruby array, e.g. [2, 2] for a 2x2 matrix
  return rb_funcall(nmatrix, rb_intern("shape"), 0);
}

and on line 82:

VALUE shape = fftw_shape(self, nmatrix);

Does that help? I think that the only issue is that you're calling shape on the class, but something else might crop up.

acsmith
  • 1,466
  • 11
  • 16
  • Yeah I've just change that back because i only implemented it to try and see if it solved the problem. Unfortunately it doesn't solve the problem to call an instance not the class nmatrix on shape either way. Here's the latest ext https://github.com/thisMagpie/fftw/blob/master/ext/fftw/fftw.cpp – Magpie Aug 25 '14 at 19:34
  • Well, I don't know what specific error you're getting with this, but I think the problem is at https://github.com/thisMagpie/fftw/blob/8261f2807cd4420e4fc16b704e83f28484b2077a/spec/fftw_spec.rb#L54. You're trying to get the shape off an NMatrix but you're not actually passing it one. It seems like you actually want to be storing some shape information on your FFTW object instead, but I may be misunderstanding. – Translunar Aug 28 '14 at 15:19
  • @mohawkjohn, I had thought that at first but the spec it was failing on was not calling shape in ruby but every single instance of r2c_one (It was maddening). As an exercise I might try to have a go at this answer by interpreting the logic in andrew's patch (which solved this problem) and see if he can verify that it makes sense. That'd be quite handy to have done, I think. – Magpie Aug 30 '14 at 02:22