Method: Flt::FormatBase.define

Defined in:
lib/float-formats/classes.rb

.define(params = {}) {|_self| ... } ⇒ Object

Common parameters for all floating-point formats:

:bias_mode

This defines how the significand is interpreted:

  • :fractional_significand The radix point is before the most significant digit of the significand (including a hidden bit if there’s one).

  • :scientific_significand The radix point is after the most significant digit of the significand (including a hidden bit if there’s one).

  • :integral_significand The significand is assumed to be an integer, i.e. the radix point is after the least significant digit.

:bias

Defines the exponent encoding method to be excess notation and defines the bias.

:endianness

Defines the byte endianness. One of:

  • :little_endian Least significant bytes come first. (Intel etc.)

  • :big_endian (Network order): most significant bytes come first. (Motorola, SPARC,…)

  • :little_big_endian (Middle endian) Each pair of bytes (16-bit word) has the bytes in little endian order, but the words are stored in big endian order (we assume the number of bytes is even). (PDP-11).

Yields:

  • (_self)

Yield Parameters:



357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
# File 'lib/float-formats/classes.rb', line 357

def self.define(params={})
  @parameters = params

  @normalized = params[:normalized]
  @normalized = true if @normalized.nil?
  @fields_handler = params[:fields_handler]

  @exponent_radix = params[:exponent_radix] || radix

  @zero_encoded_exp = params[:zero_encoded_exp] || 0
  @min_encoded_exp = params[:min_encoded_exp] || 0
  @denormal_encoded_exp = params[:denormal_encoded_exp]
  @gradual_underflow = params[:gradual_underflow] || (@denormal_encoded_exp ? true : false)
  if @gradual_underflow
    @denormal_encoded_exp = 0 if !@denormal_encoded_exp
    if @denormal_encoded_exp>=@min_encoded_exp
      @min_encoded_exp = @denormal_encoded_exp
      # originally, we incremented min_encoded_exp here unconditionally, but
      # now we don't if there's no hidden bit
      # (we assume the minimum exponent can be used for normalized and denormalized numbers)
      # because of this, IEEE_EXTENDED & 128 formats now specify min_encoded_exp: 1 in it's definitions
      @min_encoded_exp += 1 if @hidden_bit
    end
  end
  # Note that if there's a hidden bit and no gradual underflow, the minimum encoded exponent will only
  # be used for zero unless a parameter :min_encoded_exp (=0) is passed. In this case all numbers with
  # minimun exponent and nonzero encoded significand will have a 1-valued hidden bit. Otherwise
  # the only valid encoded significand with minimun encoded exponent is 0.
  # In case of gradual underflow, the minimum exponent implies a hidden bit value of 0
  @min_encoded_exp += 1 if @min_encoded_exp==@zero_encoded_exp && (@hidden_bit && params[:min_encoded_exp].nil?)

  @infinite_encoded_exp = params[:infinite_encoded_exp]
  @nan_encoded_exp = params[:nan_encoded_exp]

  @infinity = params[:infinity] || (@infinite_encoded_exp ? true : false)
  @max_encoded_exp = params[:max_encoded_exp] || @exponent_radix**@fields[:exponent]-1 # maximum regular exponent, encoded
  if @infinity
    @infinite_encoded_exp = @nan_encoded_exp || @max_encoded_exp if !@infinite_encoded_exp
    @max_encoded_exp = @infinite_encoded_exp - 1 if @infinite_encoded_exp.kind_of?(Integer) && @infinite_encoded_exp<=@max_encoded_exp
  end
  @nan = params[:nan] || (@nan_encoded_exp ? true : false)
  if @nan
    @nan_encoded_exp = @infinite_encoded_exp || @max_encoded_exp if !@nan_encoded_exp
    @max_encoded_exp = @nan_encoded_exp - 1 if @nan_encoded_exp.kind_of?(Integer) && @nan_encoded_exp<=@max_encoded_exp
  end

  @exponent_mode = params[:exponent_mode]
  if @exponent_mode.nil?
    if params[:bias]
      @exponent_mode = :excess
    else
      @exponent_mode = :radix_complement
    end
  end
  @exponent_digits = @fields[:exponent]

  if @exponent_mode==:excess
    @bias = params[:bias] || (@exponent_radix**(@fields[:exponent]-1)-1)
    @bias_mode = params[:bias_mode] || :scientific_significand
    @min_exp = params[:min_exp]
    @max_exp = params[:max_exp]
    case @bias_mode
      when :integral_significand
        @integral_bias = @bias
        @fractional_bias = @integral_bias-@significand_digits
        @scientific_bias = @fractional_bias+1
      when :fractional_significand
        @fractional_bias = @bias
        @integral_bias = @fractional_bias+@significand_digits
        @scientific_bias = @fractional_bias+1
        @min_exp -= @significand_digits if @min_exp
        @max_exp -= @significand_digits if @max_exp
      when :scientific_significand
        @scientific_bias = @bias
        @fractional_bias = @scientific_bias-1
        @integral_bias = @fractional_bias+@significand_digits
        @min_exp -= @significand_digits-1 if @min_exp
        @max_exp -= @significand_digits-1 if @max_exp
    end
  else
    #@bias_mode = :scientific_significand
    @min_exp = params[:min_exp] || (-(@exponent_radix**@exponent_digits)/2 + 1)
    @max_exp = params[:max_exp] || ((@exponent_radix**@exponent_digits)/2 - 1)
  end
  @endianness = params[:endianness] || :little_endian

  @min_exp = @min_encoded_exp - @integral_bias if @min_exp.nil?
  @max_exp = @max_encoded_exp - @integral_bias if @max_exp.nil?

  if @exponent_mode==:excess
    @integral_max_exp = @max_exp
    @integral_min_exp = @min_exp
    @fractional_max_exp = @max_exp+@significand_digits
    @fractional_min_exp = @min_exp+@significand_digits
    @scientific_max_exp = @max_exp+@significand_digits-1
    @scientific_min_exp = @min_exp+@significand_digits-1
  else
    @integral_max_exp = @max_exp - (@significand_digits-1)
    @integral_min_exp = @min_exp - (@significand_digits-1)
    @fractional_max_exp = @max_exp+1
    @fractional_min_exp = @min_exp+1
    @scientific_max_exp = @max_exp
    @scientific_min_exp = @min_exp
  end

  @round = params[:round] # || :half_even

  @neg_mode = params[:neg_mode] || :sign_magnitude

  yield self if block_given?

end