Skip to content

Commit

Permalink
Removing merge conflicts
Browse files Browse the repository at this point in the history
  • Loading branch information
Arafatk committed Mar 1, 2016
1 parent 2bacd3f commit 42538bc
Show file tree
Hide file tree
Showing 13 changed files with 515 additions and 807 deletions.
50 changes: 20 additions & 30 deletions lib/nmatrix/enumerate.rb
Expand Up @@ -9,8 +9,8 @@
#
# == Copyright Information
#
# SciRuby is Copyright (c) 2010 - 2016, Ruby Science Foundation
# NMatrix is Copyright (c) 2012 - 2016, John Woods and the Ruby Science Foundation
# SciRuby is Copyright (c) 2010 - 2014, Ruby Science Foundation
# NMatrix is Copyright (c) 2012 - 2014, John Woods and the Ruby Science Foundation
#
# Please see LICENSE.txt for additional copyright notices.
#
Expand All @@ -35,10 +35,8 @@ class NMatrix
#
# Enumerate through the matrix. @see Enumerable#each
#
# For dense, this actually calls a specialized
# each iterator (in C). For yale and list, it relies upon
# #each_with_indices (which is about as fast as reasonably
# possible for C code).
# For dense, this actually calls a specialized each iterator (in C). For yale and list, it relies upon
# #each_with_indices (which is about as fast as reasonably possible for C code).
def each &bl
if self.stype == :dense
self.__dense_each__(&bl)
Expand Down Expand Up @@ -68,9 +66,8 @@ def each &bl
#
# Returns an NMatrix if a block is given. For an Array, use #flat_map
#
# Note that #map will always return an :object matrix,
# because it has no way of knowing
# how to handle operations on the different dtypes.
# Note that #map will always return an :object matrix, because it has no way of knowing
# how to handle operations on the different dtypes.
#
def map(&bl)
return enum_for(:map) unless block_given?
Expand All @@ -94,9 +91,8 @@ def map!
iterated = true
self[*i] = (yield e)
end
# HACK: if there's a single element in a non-dense matrix,
# it won't iterate and won't change the default value;
# this ensures that it does get changed.
#HACK: if there's a single element in a non-dense matrix, it won't iterate and
#won't change the default value; this ensures that it does get changed.
unless iterated then
self.each_with_indices do |e, *i|
self[*i] = (yield e)
Expand Down Expand Up @@ -159,8 +155,8 @@ def each_column(get_by=:reference)
#
# Iterate through each layer, referencing it as an NMatrix slice.
#
# Note: If you have a 3-dimensional matrix, the first dimension
# contains rows, the second contains columns, and the third contains layers.
# Note: If you have a 3-dimensional matrix, the first dimension contains rows,
# the second contains columns, and the third contains layers.
def each_layer(get_by=:reference)
return enum_for(:each_layer, get_by) unless block_given?
(0...self.shape[2]).each do |k|
Expand All @@ -174,12 +170,10 @@ def each_layer(get_by=:reference)
# call-seq:
# each_stored_with_index -> Enumerator
#
# Allow iteration across a vector NMatrix's stored values.
# See also @each_stored_with_indices
# Allow iteration across a vector NMatrix's stored values. See also @each_stored_with_indices
#
def each_stored_with_index(&block)
raise(NotImplementedError, "only works for
dim 2 vectors") unless self.dim <= 2
raise(NotImplementedError, "only works for dim 2 vectors") unless self.dim <= 2
return enum_for(:each_stored_with_index) unless block_given?

self.each_stored_with_indices do |v, i, j|
Expand Down Expand Up @@ -214,17 +208,15 @@ def each_stored_with_index(&block)
# (i.e. the usual parameter to Enumerable#reduce). Supply nil or do not
# supply this argument to have it follow the usual Enumerable#reduce
# behavior of using the first element as the initial value.
# @param [Symbol] dtype if non-nil/false, forces the accumulated
# result to have this dtype
# @return [NMatrix] an NMatrix with the same number of
# dimensions as thev input, but with the input dimension now having
# size 1. Each element is the result of the reduction
# at that position along the specified dimension.
# @param [Symbol] dtype if non-nil/false, forces the accumulated result to have this dtype
# @return [NMatrix] an NMatrix with the same number of dimensions as the
# input, but with the input dimension now having size 1. Each element
# is the result of the reduction at that position along the specified
# dimension.
#
def inject_rank(dimen=0, initial=nil, dtype=nil)

raise(RangeError, "requested dimension (#{dimen}) does
not exist (shape: #{shape})") if dimen > self.dim
raise(RangeError, "requested dimension (#{dimen}) does not exist (shape: #{shape})") if dimen > self.dim

return enum_for(:inject_rank, dimen, initial, dtype) unless block_given?

Expand All @@ -234,12 +226,10 @@ def inject_rank(dimen=0, initial=nil, dtype=nil)
first_as_acc = false

if initial then
acc = NMatrix.new(new_shape, initial, :dtype => dtype \
|| self.dtype, stype: self.stype)
acc = NMatrix.new(new_shape, initial, :dtype => dtype || self.dtype, stype: self.stype)
else
each_rank(dimen) do |sub_mat|
acc = (sub_mat.is_a?(NMatrix) and !dtype.nil? and \
dtype != self.dtype) ? sub_mat.cast(self.stype, dtype) : sub_mat
acc = (sub_mat.is_a?(NMatrix) and !dtype.nil? and dtype != self.dtype) ? sub_mat.cast(self.stype, dtype) : sub_mat
break
end
first_as_acc = true
Expand Down
107 changes: 45 additions & 62 deletions lib/nmatrix/fftw.rb
Expand Up @@ -9,8 +9,8 @@
#
# == Copyright Information
#
# SciRuby is Copyright (c) 2010 - 2016, Ruby Science Foundation
# NMatrix is Copyright (c) 2012 - 2016, John Woods and the Ruby Science Foundation
# SciRuby is Copyright (c) 2010 - 2014, Ruby Science Foundation
# NMatrix is Copyright (c) 2012 - 2014, John Woods and the Ruby Science Foundation
#
# Please see LICENSE.txt for additional copyright notices.
#
Expand Down Expand Up @@ -53,8 +53,7 @@ def fft
# Compute 2D FFT of a 2D matrix using FFTW default parameters.
# @return [NMatrix] NMatrix of dtype :complex128 containing computed values.
def fft2
raise ShapeError, "Shape must be 2 (is
#{self.shape})" if self.shape.size != 2
raise ShapeError, "Shape must be 2 (is #{self.shape})" if self.shape.size != 2
input = self.dtype == :complex128 ? self : self.cast(dtype: :complex128)
plan = NMatrix::FFTW::Plan.new(self.shape, dim: 2)
plan.set_input input
Expand Down Expand Up @@ -97,17 +96,15 @@ class Plan
# the input/output arrays are not overwritten during planning.
# * :measure - Equivalent to FFTW_MEASURE. Tells FFTW to find an optimized
# plan by actually computing several FFTs and measuring their execution
# time. Depending on your machine, this can take some time (often a few
# time. Depending on your machine, this can take some time (often a few
# seconds).
# * :patient - Equivalent to FFTW_PATIENT. Like FFTW_MEASURE,
# but considers a wider range of algorithms and
# often produces a “more optimal” plan
# (especially for large transforms), but at the expense
# of several times longer planning time (especially for
# large transforms).
# * :exhaustive - Equivalent to FFTW_EXHAUSTIVE. Like FFTW_PATIENT, but
# considers an even wider range of algorithms, including many that we
# think are unlikely to be fast, to produce the most optimal plan but
# * :patient - Equivalent to FFTW_PATIENT. Like FFTW_MEASURE, but considers
# a wider range of algorithms and often produces a “more optimal” plan
# (especially for large transforms), but at the expense of several times
# longer planning time (especially for large transforms).
# * :exhaustive - Equivalent to FFTW_EXHAUSTIVE. Like FFTW_PATIENT, but
# considers an even wider range of algorithms, including many that we
# think are unlikely to be fast, to produce the most optimal plan but
# with a substantially increased planning time.
#
# @see http://www.fftw.org/fftw3_doc/Planner-Flags.html#Planner-Flags
Expand All @@ -118,14 +115,13 @@ class Plan
patient: 32
}

# Hash holding numerical values of the direction in
# which a :complex_complextype FFT should be performed.
# Hash holding numerical values of the direction in which a :complex_complex
# type FFT should be performed.
#
# @see http://www.fftw.org/fftw3_doc/Complex-One_002dDimensional-DFTs.html#Complex-One_002dDimensional-DFTs
# (The fourth argument, sign, can be either FFTW_FORWARD (-1) or
# FFTW_BACKWARD (+1), and indicates the direction of the
# transform you are interested in; technically, it is the sign of the
# exponent in the transform)
# FFTW_BACKWARD (+1), and indicates the direction of the transform you are
# interested in; technically, it is the sign of the exponent in the transform)
FFT_DIRECTION_HASH = {
forward: -1,
backward: 1
Expand Down Expand Up @@ -185,55 +181,49 @@ class Plan
attr_reader :output

# @!attribute [r] real_real_kind
# @return [Symbol] Specifies the kind of real to real FFT being
# performed. This is a symbol from REAL_REAL_FFT_KINDS_HASH.
# Only valid when type of transform is of type :real_real.
# @return [Symbol] Specifies the kind of real to real FFT being performed.
# This is a symbol from REAL_REAL_FFT_KINDS_HASH. Only valid when type
# of transform is of type :real_real.
# @see REAL_REAL_FFT_KINDS_HASH
# @see http://www.fftw.org/fftw3_doc/Real_002dto_002dReal-Transform-Kinds.html#Real_002dto_002dReal-Transform-Kinds
attr_reader :real_real_kind

# Create a plan for a DFT. The FFTW library requires that you first create
# a plan for performing a DFT, so that FFTW can optimize its algorithms
# according to your computer's hardware and various user supplied options.
#
# @see http://www.fftw.org/doc/Using-Plans.html
#
# @see http://www.fftw.org/doc/Using-Plans.html
# For a comprehensive explanation of the FFTW planner.
# @param shape [Array, Fixnum] Specify the shape of the plan. For 1D
# fourier transforms this can be a single number specifying
# the length of the input. For multi-dimensional transforms, specify an
# Array containing the length of each dimension.
#
# fourier transforms this can be a single number specifying the length of
# the input. For multi-dimensional transforms, specify an Array containing
# the length of each dimension.
# @param [Hash] opts the options to create a message with.
# @option opts [Fixnum] :dim (1) The number of dimensions of the Fourier
# transform. If 'shape' has more numbers than :dim, the number of
# dimensions specified by :dim will be considered when
# making the plan.
# transform. If 'shape' has more numbers than :dim, the number of dimensions
# specified by :dim will be considered when making the plan.
# @option opts [Symbol] :type (:complex_complex) The type of transform to
# perform based on the input and output data desired. The default value
# indicates that a transform is being planned that uses complex numbers
# as input and generates complex numbers as output. Similarly you can
# use :complex_real, :real_complex or :real_real to specify the kind
# of input and output that you will be supplying to the plan.
# @see DATA_TYPE_HASH
# @option opts [Symbol, Array] :flags (:estimate) Specify one
# or more flags which denote the methodology that is used for
# deciding the algorithm used when planning the fourier transform.
# Use one or more of :estimate, :measure, :exhaustive and :patient.
# These flags map to the planner flags specified at
# http://www.fftw.org/fftw3_doc/Planner-Flags.html#Planner-Flags.
# @option opts [Symbol, Array] :flags (:estimate) Specify one or more flags
# which denote the methodology that is used for deciding the algorithm used
# when planning the fourier transform. Use one or more of :estimate, :measure,
# :exhaustive and :patient. These flags map to the planner flags specified
# at http://www.fftw.org/fftw3_doc/Planner-Flags.html#Planner-Flags.
# @see REAL_REAL_FFT_KINDS_HASH
# @option opts [Symbol] :direction (:forward) The direction of a DFT of
# type :complex_complex. Technically, it is the sign of the exponent in
# type :complex_complex. Technically, it is the sign of the exponent in
# the transform. :forward corresponds to -1 and :backward to +1.
# @see FFT_DIRECTION_HASH
# @option opts [Array] :real_real_kind When the type of transform is
# :real_real, specify the kind of transform
# that should be performed FOR EACH AXIS of input. The position
# of the symbol in the Array corresponds to the
# axis of the input. The number of elements in :real_real_kind
# must be equal to
# :dim. Can accept one of the inputs specified in
# REAL_REAL_FFT_KINDS_HASH.
# @option opts [Array] :real_real_kind When the type of transform is :real_real,
# specify the kind of transform that should be performed FOR EACH AXIS
# of input. The position of the symbol in the Array corresponds to the
# axis of the input. The number of elements in :real_real_kind must be equal to
# :dim. Can accept one of the inputs specified in REAL_REAL_FFT_KINDS_HASH.
# @see REAL_REAL_FFT_KINDS_HASH
# @see http://www.fftw.org/fftw3_doc/Real_002dto_002dReal-Transform-Kinds.html#Real_002dto_002dReal-Transform-Kinds
# @example Create a plan for a basic 1D FFT and execute it.
Expand Down Expand Up @@ -264,16 +254,13 @@ def initialize shape, opts={}
@flags = opts[:flags].is_a?(Array) ? opts[:flags] : [opts[:flags]]
@real_real_kind = opts[:real_real_kind]

raise ArgumentError, ":real_real_kind option must be
specified for :real_real type transforms" if
raise ArgumentError, ":real_real_kind option must be specified for :real_real type transforms" if
@real_real_kind.nil? and @type == :real_real

raise ArgumentError, "Specify kind of transform of
each axis of input." if
raise ArgumentError, "Specify kind of transform of each axis of input." if
@real_real_kind and @real_real_kind.size != @dim

raise ArgumentError, "dim (#{@dim}) cannot be more than
size of shape #{@shape.size}" if
raise ArgumentError, "dim (#{@dim}) cannot be more than size of shape #{@shape.size}" if
@dim > @shape.size

@plan_data = c_create_plan(@shape, @size, @dim,
Expand All @@ -291,14 +278,12 @@ def initialize shape, opts={}
# don't match.
def set_input ip
raise ArgumentError, "stype must be dense." if ip.stype != :dense
raise ArgumentError, "size of input (#{ip.size}) cannot
be greater than planned input size #{@size}" if
raise ArgumentError, "size of input (#{ip.size}) cannot be greater than planned input size #{@size}" if
ip.size != @size

case @type
when :complex_complex, :complex_real
raise ArgumentError, "dtype must be
complex128." if ip.dtype != :complex128
raise ArgumentError, "dtype must be complex128." if ip.dtype != :complex128
when :real_complex, :real_real
raise ArgumentError, "dtype must be float64." if ip.dtype != :float64
else
Expand Down Expand Up @@ -331,8 +316,8 @@ def execute
private

# Combine flags received from the user (Symbols) into their respective
# numeric equivalents and then 'OR' (|) all of them so the
# resulting number can be passed directly to the FFTW planner function.
# numeric equivalents and then 'OR' (|) all of them so the resulting number
# can be passed directly to the FFTW planner function.
def combine_flags flgs
temp = 0
flgs.each do |f|
Expand All @@ -349,11 +334,9 @@ def verify_opts opts
end
end

# Get the numerical equivalents of the kind of real-real
# FFT to be computed.
# Get the numerical equivalents of the kind of real-real FFT to be computed.
def encoded_rr_kind
return @real_real_kind.map { |e| REAL_REAL_FFT_KINDS_HASH[e] \
} if @real_real_kind
return @real_real_kind.map { |e| REAL_REAL_FFT_KINDS_HASH[e] } if @real_real_kind
end
end
end
Expand Down
22 changes: 8 additions & 14 deletions lib/nmatrix/homogeneous.rb
Expand Up @@ -9,8 +9,8 @@
#
# == Copyright Information
#
# SciRuby is Copyright (c) 2010 - 2016, Ruby Science Foundation
# NMatrix is Copyright (c) 2012 - 2016, John Woods and the Ruby Science Foundation
# SciRuby is Copyright (c) 2010 - 2014, Ruby Science Foundation
# NMatrix is Copyright (c) 2012 - 2014, John Woods and the Ruby Science Foundation
#
# Please see LICENSE.txt for additional copyright notices.
#
Expand Down Expand Up @@ -100,8 +100,7 @@ def z_rotation angle_in_radians, opts={}
# translation(translation, dtype: dtype) -> NMatrix
# translation(x, y, z, dtype: dtype) -> NMatrix
#
# Generate a 4x4 homogeneous transformation matrix
# representing a translation.
# Generate a 4x4 homogeneous transformation matrix representing a translation.
#
# * *Returns* :
# - A homogeneous transformation matrix consisting of a translation.
Expand All @@ -127,8 +126,7 @@ def z_rotation angle_in_radians, opts={}
#
def translation *args
xyz = args.shift if args.first.is_a?(NMatrix) || args.first.is_a?(Array)
default_dtype = xyz.respond_to?(:dtype) ? xyz.dtype \
: NMatrix.guess_dtype(xyz)
default_dtype = xyz.respond_to?(:dtype) ? xyz.dtype : NMatrix.guess_dtype(xyz)
opts = {dtype: default_dtype}
opts = opts.merge(args.pop) if args.size > 0 && args.last.is_a?(Hash)
xyz ||= args
Expand Down Expand Up @@ -159,10 +157,8 @@ def translation *args
# n.quaternion # => [1, 0, 0, 0]
#
def quaternion
raise(ShapeError, "Expected square
matrix") if self.shape[0] != self.shape[1]
raise(ShapeError, "Expected 3x3 rotation (or 4x4
homogeneous) matrix") if self.shape[0] > 4 || self.shape[0] < 3
raise(ShapeError, "Expected square matrix") if self.shape[0] != self.shape[1]
raise(ShapeError, "Expected 3x3 rotation (or 4x4 homogeneous) matrix") if self.shape[0] > 4 || self.shape[0] < 3

q = NMatrix.new([4], dtype: self.dtype == :float32 ? :float32: :float64)
rotation_trace = self[0,0] + self[1,1] + self[2,2]
Expand Down Expand Up @@ -217,8 +213,7 @@ def quaternion
# call-seq:
# angle_vector -> [angle, about_vector]
#
# Find the angle vector for a quaternion. Assumes the
# quaternion has unit length.
# Find the angle vector for a quaternion. Assumes the quaternion has unit length.
#
# Source: http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/
#
Expand All @@ -231,8 +226,7 @@ def quaternion
# q.angle_vector # => [1, 0, 0, 0]
#
def angle_vector
raise(ShapeError, "Expected length-4 vector or
matrix (quaternion)") if self.shape[0] != 4
raise(ShapeError, "Expected length-4 vector or matrix (quaternion)") if self.shape[0] != 4
raise("Expected unit quaternion") if self[0] > 1

xyz = NMatrix.new([3], dtype: self.dtype)
Expand Down

0 comments on commit 42538bc

Please sign in to comment.