class SassC::Script::Value::Number

def self.basically_equal?(num1, num2)

Returns:
  • (Boolean) -
def self.basically_equal?(num1, num2)
  (num1 - num2).abs < epsilon
end

def self.epsilon

The value for epsilon is one tenth of the current numeric precision.
numbers within an `epsilon` of each other are considered functionally equal.
Used in checking equality of floating point numbers. Any
def self.epsilon
  Thread.current[:sass_numeric_epsilon] ||= 1 / (precision_factor * 10)
end

def self.precision

def self.precision
  Thread.current[:sass_numeric_precision] || Thread.main[:sass_numeric_precision] || 10
end

def self.precision=(digits)

To set for all threads, be sure to set the precision on the main thread.
The numeric precision is stored as a thread local for thread safety reasons.
`3.1415926` will be printed as `3.142`.
For example, if this is `3`,
Sets the number of digits of precision
def self.precision=(digits)
  Thread.current[:sass_numeric_precision] = digits.round
  Thread.current[:sass_numeric_precision_factor] = nil
  Thread.current[:sass_numeric_epsilon] = nil
end

def self.precision_factor

it is derived from the `precision` method.
the precision factor used in numeric output
def self.precision_factor
  Thread.current[:sass_numeric_precision_factor] ||= 10.0**precision
end

def self.round(num)

Other tags:
    Private: -
def self.round(num)
  if num.is_a?(Float) && (num.infinite? || num.nan?)
    num
  elsif basically_equal?(num % 1, 0.0)
    num.round
  else
    ((num * precision_factor).round / precision_factor).to_f
  end
end

def basically_equal?(num1, num2)

Other tags:
    See: Sass::Script::Number.basically_equal? -

Other tags:
    Private: -
def basically_equal?(num1, num2)
  self.class.basically_equal?(num1, num2)
end

def coerce(num_units, den_units)

Raises:
  • (Sass::UnitConversionError) - if the given units are incompatible with the number's

Returns:
  • (Number) - The number with the new units

Parameters:
  • den_units (Array) -- The denominator units to coerce this number into.
  • num_units (Array) -- The numerator units to coerce this number into.
def coerce(num_units, den_units)
  Number.new(if unitless?
               value
             else
               value * coercion_factor(@numerator_units, num_units) /
                 coercion_factor(@denominator_units, den_units)
             end, num_units, den_units)
end

def coercion_factor(from_units, to_units)

def coercion_factor(from_units, to_units)
  # get a list of unmatched units
  from_units, to_units = sans_common_units(from_units, to_units)
  if from_units.size != to_units.size || !convertable?(from_units | to_units)
    raise Sass::UnitConversionError.new(
      "Incompatible units: '#{from_units.join('*')}' and '#{to_units.join('*')}'.")
  end
  from_units.zip(to_units).inject(1) {|m, p| m * conversion_factor(p[0], p[1])}
end

def comparable_to?(other)

Returns:
  • (Boolean) - Whether or not this number can be compared with the other.

Parameters:
  • other (Number) -- A number to decide if it can be compared with this number.
def comparable_to?(other)
  operate(other, :+)
  true
rescue Sass::UnitConversionError
  false
end

def compute_units(this, other, operation)

def compute_units(this, other, operation)
  case operation
  when :*
    [this.numerator_units + other.numerator_units,
     this.denominator_units + other.denominator_units]
  when :/
    [this.numerator_units + other.denominator_units,
     this.denominator_units + other.numerator_units]
  else
    [this.numerator_units, this.denominator_units]
  end
end

def conversion_factor(from_unit, to_unit)

def conversion_factor(from_unit, to_unit)
  CONVERSION_TABLE[from_unit][to_unit]
end

def convertable?(units)

def convertable?(units)
  units = Array(units).to_set
  return true if units.empty?
  return false unless (mutually_convertible = MUTUALLY_CONVERTIBLE[units.first])
  units.subset?(mutually_convertible)
end

def eql?(other)

numerator units, and denominator units.
Hash-equality must be transitive, so it just compares the exact value,
Hash-equality works differently than `==` equality for numbers.
def eql?(other)
  basically_equal?(value, other.value) && numerator_units == other.numerator_units &&
    denominator_units == other.denominator_units
end

def hash

def hash
  [value, numerator_units, denominator_units].hash
end

def initialize(value, numerator_units = NO_UNITS, denominator_units = NO_UNITS)

Parameters:
  • denominator_units (::String, Array<::String>) -- See \{#denominator\_units}
  • numerator_units (::String, Array<::String>) -- See \{#numerator\_units}
  • value (Numeric) -- The value of the number
def initialize(value, numerator_units = NO_UNITS, denominator_units = NO_UNITS)
  numerator_units = [numerator_units] if numerator_units.is_a?(::String)
  denominator_units = [denominator_units] if denominator_units.is_a?(::String)
  super(value)
  @numerator_units = numerator_units
  @denominator_units = denominator_units
  @options = nil
  normalize!
end

def inspect(opts = {})

Returns:
  • (String) - The representation
def inspect(opts = {})
  return original if original
  value = self.class.round(self.value)
  str = value.to_s
  # Ruby will occasionally print in scientific notation if the number is
  # small enough. That's technically valid CSS, but it's not well-supported
  # and confusing.
  str = ("%0.#{self.class.precision}f" % value).gsub(/0*$/, '') if str.include?('e')
  # Sometimes numeric formatting will result in a decimal number with a trailing zero (x.0)
  if str =~ /(.*)\.0$/
    str = $1
  end
  # We omit a leading zero before the decimal point in compressed mode.
  if @options && options[:style] == :compressed
    str.sub!(/^(-)?0\./, '\1.')
  end
  unitless? ? str : "#{str}#{unit_str}"
end

def int?

Returns:
  • (Boolean) - Whether or not this number is an integer.
def int?
  basically_equal?(value % 1, 0.0)
end

def is_unit?(unit)

Other tags:
    See: Number#unitless? - The unitless? method may be more readable.

Parameters:
  • unit (::String, nil) -- The unit the number should have or nil if the number
def is_unit?(unit)
  if unit
    denominator_units.size == 0 && numerator_units.size == 1 && numerator_units.first == unit
  else
    unitless?
  end
end

def legal_units?

Returns:
  • (Boolean) - Whether or not this number has units that can be represented in CSS
def legal_units?
  (@numerator_units.empty? || @numerator_units.size == 1) && @denominator_units.empty?
end

def normalize!

def normalize!
  return if unitless?
  @numerator_units, @denominator_units =
    sans_common_units(@numerator_units, @denominator_units)
  @denominator_units.each_with_index do |d, i|
    next unless convertable?(d) && (u = @numerator_units.find {|n| convertable?([n, d])})
    @value /= conversion_factor(d, u)
    @denominator_units.delete_at(i)
    @numerator_units.delete_at(@numerator_units.index(u))
  end
end

def operate(other, operation)

def operate(other, operation)
  this = self
  if OPERATIONS.include?(operation)
    if unitless?
      this = this.coerce(other.numerator_units, other.denominator_units)
    else
      other = other.coerce(@numerator_units, @denominator_units)
    end
  end
  # avoid integer division
  value = :/ == operation ? this.value.to_f : this.value
  result = value.send(operation, other.value)
  if result.is_a?(Numeric)
    Number.new(result, *compute_units(this, other, operation))
  else # Boolean op
    Bool.new(result)
  end
end

def sans_common_units(units1, units2)

def sans_common_units(units1, units2)
  units2 = units2.dup
  # Can't just use -, because we want px*px to coerce properly to px*mm
  units1 = units1.map do |u|
    j = units2.index(u)
    next u unless j
    units2.delete_at(j)
    nil
  end
  units1.compact!
  return units1, units2
end

def to_i

Raises:
  • (Sass::SyntaxError) - if the number isn't an integer

Returns:
  • (Integer) - The integer value of the number
def to_i
  super unless int?
  value.to_i
end

def to_s(opts = {})

Raises:
  • (Sass::SyntaxError) - if this number has units that can't be used in CSS

Returns:
  • (String) - The CSS representation of this number
def to_s(opts = {})
  return original if original
  raise Sass::SyntaxError.new("#{inspect} isn't a valid CSS value.") unless legal_units?
  inspect
end

def unit_str

Returns:
  • (String) - a string that represents the units in this number
def unit_str
  rv = @numerator_units.sort.join("*")
  if @denominator_units.any?
    rv << "/"
    rv << @denominator_units.sort.join("*")
  end
  rv
end

def unitless?

Returns:
  • (Boolean) - Whether or not this number has no units.
def unitless?
  @numerator_units.empty? && @denominator_units.empty?
end