ATLAS Offline Software
Static Public Member Functions | List of all members
FloatingPointHelpers::IEEE754_like< mantiss, exp, tag > Class Template Reference

#include <FPHelpers.h>

Collaboration diagram for FloatingPointHelpers::IEEE754_like< mantiss, exp, tag >:

Static Public Member Functions

constexpr static unsigned int total_size_bits ()
 
constexpr static unsigned int mantissa_size_bits ()
 
constexpr static unsigned int exponent_size_bits ()
 
template<class T >
constexpr static T mantissa_mask ()
 
template<class T >
constexpr static T exponent_mask ()
 
template<class T >
constexpr static T sign_mask ()
 
template<class T >
constexpr static T full_mask ()
 
template<class T >
constexpr static T exponent_bias ()
 
template<class T >
constexpr static T max_exponent_with_bias ()
 
template<class T >
constexpr static bool is_infinite (const T pattern)
 
template<class T >
constexpr static bool is_NaN (const T pattern)
 
template<class T >
constexpr static T absolute_value (const T pattern)
 
template<class T >
constexpr static T to_total_ordering (const T pattern)
 
template<class T >
constexpr static T from_total_ordering (const T pattern)
 
template<class T >
constexpr static T positive_zero ()
 
template<class T >
constexpr static T negative_zero ()
 
template<class T >
constexpr static T positive_infinity ()
 
template<class T >
constexpr static T negative_infinity ()
 
template<class T >
constexpr static bool round_results (const bool is_negative, const bool is_odd, const bool is_nearer_to_up, const bool is_tied, RoundingModes rt)
 
template<class T >
constexpr static T add_patterns (const T a, const T b, const RoundingModes rt=RoundingModes::Default)
 The absolute value of must be greater than or equal than that of . More...
 
template<class T >
constexpr static T subtract_patterns (const T a, const T b, const RoundingModes rt=RoundingModes::Default)
 The absolute value of must be greater than or equal than that of . More...
 
template<class T >
constexpr static T add (const T a, const T b, const RoundingModes rt=RoundingModes::Default)
 
template<class T >
constexpr static T subtract (const T a, const T b, const RoundingModes rt=RoundingModes::Default)
 

Detailed Description

template<unsigned int mantiss, unsigned int exp, unsigned int tag = 1>
class FloatingPointHelpers::IEEE754_like< mantiss, exp, tag >

Specifies a floating point format like those described in IEEE-754, with an adjustable number of bits in the exponent and mantissa.

tag just allows differing floating point definitions with the same size, in case there are e. g. multiple implementations of native/faster operations available. Tag 0 is reserved for the default (i. e. non-native) implementation.

Definition at line 350 of file FPHelpers.h.

Member Function Documentation

◆ absolute_value()

template<unsigned int mantiss, unsigned int exp, unsigned int tag = 1>
template<class T >
constexpr static T FloatingPointHelpers::IEEE754_like< mantiss, exp, tag >::absolute_value ( const pattern)
inlinestaticconstexpr

Definition at line 435 of file FPHelpers.h.

436  {
437  return pattern & (~sign_mask<T>());
438  }

◆ add()

template<unsigned int mantiss, unsigned int exp, unsigned int tag = 1>
template<class T >
constexpr static T FloatingPointHelpers::IEEE754_like< mantiss, exp, tag >::add ( const a,
const b,
const RoundingModes  rt = RoundingModes::Default 
)
inlinestaticconstexpr
Warning
Branchy as everything, and thus quite inefficient. The addition/subtraction routines themselves could be branchless, but we must select between them...

Probably the overhead from all the operations makes it worth it?

Definition at line 631 of file FPHelpers.h.

632  {
633  const T abs_a = absolute_value<T>(a);
634  const T abs_b = absolute_value<T>(b);
635 
636  const bool sign_a = a & sign_mask<T>();
637  const bool sign_b = b & sign_mask<T>();
638 
639  if (abs_b == 0)
640  {
641  return a;
642  }
643  if (abs_a == 0)
644  {
645  return b;
646  }
647 
648  if (is_infinite<T>(a) && is_infinite<T>(b))
649  {
650  if (sign_a == sign_b)
651  {
652  return a;
653  }
654  else
655  {
656  return abs_a | (T(1) << (mantissa_size_bits() - 1));
657  //A "quiet" NaN in most platforms.
658  }
659  }
660  else if (is_NaN<T>(a))
661  {
662  return a;
663  }
664  else if (is_NaN<T>(b))
665  {
666  return b;
667  }
668 
669  if (sign_a == sign_b)
670  {
671  if (abs_a >= abs_b)
672  {
673  return add_patterns<T>(a, b, rt);
674  }
675  else
676  {
677  return add_patterns<T>(b, a, rt);
678  }
679  }
680  else
681  {
682  if (abs_a > abs_b)
683  {
684  return (sign_a * sign_mask<T>()) | subtract_patterns<T>(abs_a, abs_b, rt);
685  }
686  else if (abs_a == abs_b)
687  {
688  return 0;
689  }
690  else
691  {
692  return (sign_b * sign_mask<T>()) | subtract_patterns<T>(abs_b, abs_a, rt);
693  }
694  }
695  }

◆ add_patterns()

template<unsigned int mantiss, unsigned int exp, unsigned int tag = 1>
template<class T >
constexpr static T FloatingPointHelpers::IEEE754_like< mantiss, exp, tag >::add_patterns ( const a,
const b,
const RoundingModes  rt = RoundingModes::Default 
)
inlinestaticconstexpr

The absolute value of must be greater than or equal than that of .

We also don't handle zero, NaN or infinities here.

Definition at line 512 of file FPHelpers.h.

513  {
514  using namespace OperatorsHelper;
515 
516  constexpr unsigned int extra_bits = 2;
517  //One sign and at least one exponent bit, we're safe!
518 
519  constexpr T first_not_mantissa_bit = T(1) << mantissa_size_bits();
520 
521  const T exp_a = (a & exponent_mask<T>()) >> mantissa_size_bits();
522  const T exp_b = (b & exponent_mask<T>()) >> mantissa_size_bits();
523 
524  const bool a_denormal = (exp_a != 0);
525  const bool b_denormal = (exp_b != 0);
526 
527  const bool use_second = (exp_a - exp_b) <= mantissa_size_bits() + 1 + extra_bits;
528  const bool is_negative = a & sign_mask<T>();
529 
530  const T mantiss_a = ((a & mantissa_mask<T>()) | (first_not_mantissa_bit * a_denormal)) << extra_bits;
531  const T mantiss_b = ((b & mantissa_mask<T>()) | (first_not_mantissa_bit * b_denormal)) << extra_bits;
532  //To account for the overflow and rounding.
533 
534  T mantiss_ret = mantiss_a;
535 
536  mantiss_ret += safe_rshift(mantiss_b, exp_a - exp_b);
537 
538  mantiss_ret |= !!(safe_lshift(mantiss_b, exp_a - exp_b) & mantissa_mask<T>()) * use_second;
539 
540  const unsigned int leading_zeros = LeadingZerosPortability::count_leading_zeros<T>(mantiss_ret);
541  constexpr unsigned int desired_number_of_zeros = sizeof(T) * CHAR_BIT - mantissa_size_bits() - 1 - extra_bits;
542  const unsigned int shift_amount = clamped_sub(desired_number_of_zeros, leading_zeros);
543 
544  const T last_bit_mask = T(1) << (shift_amount + extra_bits);
545  const T last_discarded_bit_mask = last_bit_mask >> 1;
546  const T round_mask = (last_bit_mask - 1) * !!(last_bit_mask);
547  const bool round_up = (mantiss_ret & round_mask) > last_discarded_bit_mask;
548  const bool tied = last_discarded_bit_mask && ((mantiss_ret & round_mask) == last_discarded_bit_mask);
549 
550  bool round_bit = round_results<T>(is_negative, (mantiss_ret & last_bit_mask), round_up, tied, rt) && !!last_bit_mask;
551 
552  mantiss_ret = safe_rshift(mantiss_ret, shift_amount + extra_bits);
553 
554  mantiss_ret += round_bit * (shift_amount + extra_bits <= sizeof(T) * CHAR_BIT);
555 
556  const T exponent_ret = exp_a + shift_amount + (exp_a == 0 && mantiss_ret > mantissa_mask<T>());
557 
558  mantiss_ret &= mantissa_mask<T>();
559 
560  mantiss_ret &= ~( ( exponent_ret > max_exponent_with_bias<T>() ) * mantissa_mask<T>() );
561  //If we somehow summed up to infinity,
562  //unset the remaining bits.
563 
564  return (is_negative * sign_mask<T>()) | (exponent_ret << mantissa_size_bits()) | mantiss_ret;
565  }

◆ exponent_bias()

template<unsigned int mantiss, unsigned int exp, unsigned int tag = 1>
template<class T >
constexpr static T FloatingPointHelpers::IEEE754_like< mantiss, exp, tag >::exponent_bias ( )
inlinestaticconstexpr

Definition at line 405 of file FPHelpers.h.

406  {
407  static_assert(sizeof(T) * CHAR_BIT >= (mantiss + exp + 1),
408  "The type must be large enough to hold the bit representation of the floating point." );
409  return (T(1) << (exp - 1)) - 1;
410  }

◆ exponent_mask()

template<unsigned int mantiss, unsigned int exp, unsigned int tag = 1>
template<class T >
constexpr static T FloatingPointHelpers::IEEE754_like< mantiss, exp, tag >::exponent_mask ( )
inlinestaticconstexpr

Definition at line 380 of file FPHelpers.h.

381  {
382  static_assert(sizeof(T) * CHAR_BIT >= (mantiss + exp + 1),
383  "The type must be large enough to hold the bit representation of the floating point." );
384 
385  T ret = (T(1) << exp) - 1;
386  return ret << mantiss;
387  }

◆ exponent_size_bits()

template<unsigned int mantiss, unsigned int exp, unsigned int tag = 1>
constexpr static unsigned int FloatingPointHelpers::IEEE754_like< mantiss, exp, tag >::exponent_size_bits ( )
inlinestaticconstexpr

Definition at line 365 of file FPHelpers.h.

366  {
367  return exp;
368  }

◆ from_total_ordering()

template<unsigned int mantiss, unsigned int exp, unsigned int tag = 1>
template<class T >
constexpr static T FloatingPointHelpers::IEEE754_like< mantiss, exp, tag >::from_total_ordering ( const pattern)
inlinestaticconstexpr
Warning
Even though +0 and -0 should technically compare equal, we will convert between them too so the operation becomes fully reversible.

Definition at line 454 of file FPHelpers.h.

455  {
456  const T xor_mask = (!(pattern & sign_mask<T>()) * full_mask<T>()) | sign_mask<T>();
457  return pattern ^ xor_mask;
458  }

◆ full_mask()

template<unsigned int mantiss, unsigned int exp, unsigned int tag = 1>
template<class T >
constexpr static T FloatingPointHelpers::IEEE754_like< mantiss, exp, tag >::full_mask ( )
inlinestaticconstexpr

Definition at line 399 of file FPHelpers.h.

400  {
401  return mantissa_mask<T>() | exponent_mask<T>() | sign_mask<T>();
402  }

◆ is_infinite()

template<unsigned int mantiss, unsigned int exp, unsigned int tag = 1>
template<class T >
constexpr static bool FloatingPointHelpers::IEEE754_like< mantiss, exp, tag >::is_infinite ( const pattern)
inlinestaticconstexpr

Definition at line 421 of file FPHelpers.h.

422  {
423  return (pattern & (~sign_mask<T>())) == exponent_mask<T>();
424  }

◆ is_NaN()

template<unsigned int mantiss, unsigned int exp, unsigned int tag = 1>
template<class T >
constexpr static bool FloatingPointHelpers::IEEE754_like< mantiss, exp, tag >::is_NaN ( const pattern)
inlinestaticconstexpr

Definition at line 427 of file FPHelpers.h.

428  {
429  return (pattern & (~sign_mask<T>())) > exponent_mask<T>();
430  //If it also has bits in the mantissa, it's greater than the mask.
431  //Last bit is sign, so signedness of T is of no concern.
432  }

◆ mantissa_mask()

template<unsigned int mantiss, unsigned int exp, unsigned int tag = 1>
template<class T >
constexpr static T FloatingPointHelpers::IEEE754_like< mantiss, exp, tag >::mantissa_mask ( )
inlinestaticconstexpr

Definition at line 371 of file FPHelpers.h.

372  {
373  static_assert(sizeof(T) * CHAR_BIT >= (mantiss + exp + 1),
374  "The type must be large enough to hold the bit representation of the floating point." );
375  T ret = (T(1) << mantiss) - 1;
376  return ret;
377  }

◆ mantissa_size_bits()

template<unsigned int mantiss, unsigned int exp, unsigned int tag = 1>
constexpr static unsigned int FloatingPointHelpers::IEEE754_like< mantiss, exp, tag >::mantissa_size_bits ( )
inlinestaticconstexpr

Definition at line 360 of file FPHelpers.h.

361  {
362  return mantiss;
363  }

◆ max_exponent_with_bias()

template<unsigned int mantiss, unsigned int exp, unsigned int tag = 1>
template<class T >
constexpr static T FloatingPointHelpers::IEEE754_like< mantiss, exp, tag >::max_exponent_with_bias ( )
inlinestaticconstexpr

Definition at line 413 of file FPHelpers.h.

414  {
415  static_assert(sizeof(T) * CHAR_BIT >= (mantiss + exp + 1),
416  "The type must be large enough to hold the bit representation of the floating point." );
417  return exponent_bias<T>() * 2;
418  }

◆ negative_infinity()

template<unsigned int mantiss, unsigned int exp, unsigned int tag = 1>
template<class T >
constexpr static T FloatingPointHelpers::IEEE754_like< mantiss, exp, tag >::negative_infinity ( )
inlinestaticconstexpr

Definition at line 479 of file FPHelpers.h.

480  {
481  return sign_mask<T>() | exponent_mask<T>();
482  }

◆ negative_zero()

template<unsigned int mantiss, unsigned int exp, unsigned int tag = 1>
template<class T >
constexpr static T FloatingPointHelpers::IEEE754_like< mantiss, exp, tag >::negative_zero ( )
inlinestaticconstexpr

Definition at line 467 of file FPHelpers.h.

468  {
469  return sign_mask<T>();
470  }

◆ positive_infinity()

template<unsigned int mantiss, unsigned int exp, unsigned int tag = 1>
template<class T >
constexpr static T FloatingPointHelpers::IEEE754_like< mantiss, exp, tag >::positive_infinity ( )
inlinestaticconstexpr

Definition at line 473 of file FPHelpers.h.

474  {
475  return exponent_mask<T>();
476  }

◆ positive_zero()

template<unsigned int mantiss, unsigned int exp, unsigned int tag = 1>
template<class T >
constexpr static T FloatingPointHelpers::IEEE754_like< mantiss, exp, tag >::positive_zero ( )
inlinestaticconstexpr

Definition at line 461 of file FPHelpers.h.

462  {
463  return T(0);
464  }

◆ round_results()

template<unsigned int mantiss, unsigned int exp, unsigned int tag = 1>
template<class T >
constexpr static bool FloatingPointHelpers::IEEE754_like< mantiss, exp, tag >::round_results ( const bool  is_negative,
const bool  is_odd,
const bool  is_nearer_to_up,
const bool  is_tied,
RoundingModes  rt 
)
inlinestaticconstexpr

Definition at line 485 of file FPHelpers.h.

488  {
489  switch (rt)
490  {
492  return !is_negative;
494  return is_negative;
496  return 0;
497  //Truncate => do nothing
499  return is_nearer_to_up || (is_odd && is_tied);
501  return is_nearer_to_up || is_tied;
502  default:
503  return 0;
504  }
505  }

◆ sign_mask()

template<unsigned int mantiss, unsigned int exp, unsigned int tag = 1>
template<class T >
constexpr static T FloatingPointHelpers::IEEE754_like< mantiss, exp, tag >::sign_mask ( )
inlinestaticconstexpr

Definition at line 390 of file FPHelpers.h.

391  {
392  static_assert(sizeof(T) * CHAR_BIT >= (mantiss + exp + 1),
393  "The type must be large enough to hold the bit representation of the floating point." );
394  T ret = T(1) << (exp + mantiss);
395  return ret;
396  }

◆ subtract()

template<unsigned int mantiss, unsigned int exp, unsigned int tag = 1>
template<class T >
constexpr static T FloatingPointHelpers::IEEE754_like< mantiss, exp, tag >::subtract ( const a,
const b,
const RoundingModes  rt = RoundingModes::Default 
)
inlinestaticconstexpr

Definition at line 699 of file FPHelpers.h.

700  {
701  return add<T>(a, b ^ sign_mask<T>(), rt);
702  }

◆ subtract_patterns()

template<unsigned int mantiss, unsigned int exp, unsigned int tag = 1>
template<class T >
constexpr static T FloatingPointHelpers::IEEE754_like< mantiss, exp, tag >::subtract_patterns ( const a,
const b,
const RoundingModes  rt = RoundingModes::Default 
)
inlinestaticconstexpr

The absolute value of must be greater than or equal than that of .

We also don't handle zero, NaN or infinities here.

Definition at line 571 of file FPHelpers.h.

572  {
573  using namespace OperatorsHelper;
574 
575  constexpr unsigned int extra_bits = 2;
576  //One sign and at least one exponent bit, we're safe!
577 
578  constexpr T first_not_mantissa_bit = T(1) << mantissa_size_bits();
579 
580  const T exp_a = (a & exponent_mask<T>()) >> mantissa_size_bits();
581  const T exp_b = (b & exponent_mask<T>()) >> mantissa_size_bits();
582 
583  const bool use_second = (exp_a - exp_b) <= mantissa_size_bits() + 1 + extra_bits;
584  const bool is_negative = a & sign_mask<T>();
585 
586  const T mantiss_a = ((a & mantissa_mask<T>()) | (first_not_mantissa_bit * (exp_a != 0))) << extra_bits;
587  const T mantiss_b = ((b & mantissa_mask<T>()) | (first_not_mantissa_bit * (exp_b != 0))) << extra_bits;
588  //To account for the overflow and rounding.
589 
590  T mantiss_ret = mantiss_a;
591 
592  mantiss_ret -= safe_rshift(mantiss_b, exp_a - exp_b) * use_second;
593 
594  mantiss_ret |= !!(safe_lshift(-mantiss_b, exp_a - exp_b) & mantissa_mask<T>()) * use_second;
595 
596  const unsigned int leading_zeros = LeadingZerosPortability::count_leading_zeros<T>(mantiss_ret);
597  constexpr unsigned int desired_number_of_zeros = sizeof(T) * CHAR_BIT - mantissa_size_bits() - 1 - extra_bits;
598  const unsigned int shift_amount = clamped_sub(leading_zeros, desired_number_of_zeros);
599 
600  const T last_bit_mask = T(1) << extra_bits;
601  const T last_discarded_bit_mask = last_bit_mask >> 1;
602  const T round_mask = (last_bit_mask - 1) * !!(last_bit_mask);
603  const bool round_up = (mantiss_ret & round_mask) > last_discarded_bit_mask;
604  const bool tied = last_discarded_bit_mask && ((mantiss_ret & round_mask) == last_discarded_bit_mask);
605 
606  bool round_bit = round_results<T>(is_negative, (mantiss_ret & last_bit_mask), round_up, tied, rt) && !!last_bit_mask;
607 
608  mantiss_ret >>= extra_bits;
609 
610  mantiss_ret += round_bit;
611 
612  mantiss_ret = safe_lshift(mantiss_ret, shift_amount);
613 
614  const T exponent_ret = clamped_sub(exp_a, shift_amount);
615 
616  mantiss_ret = safe_rshift(mantiss_ret, clamped_sub(shift_amount, exp_a));
617 
618  mantiss_ret &= mantissa_mask<T>();
619 
620  return (is_negative * sign_mask<T>()) | (exponent_ret << mantissa_size_bits()) | mantiss_ret;
621  }

◆ to_total_ordering()

template<unsigned int mantiss, unsigned int exp, unsigned int tag = 1>
template<class T >
constexpr static T FloatingPointHelpers::IEEE754_like< mantiss, exp, tag >::to_total_ordering ( const pattern)
inlinestaticconstexpr
Warning
Even though +0 and -0 should technically compare equal, we will convert between them too so the operation becomes fully reversible.

Definition at line 444 of file FPHelpers.h.

445  {
446  const T xor_mask = (!!(pattern & sign_mask<T>()) * full_mask<T>()) | sign_mask<T>();
447  return pattern ^ xor_mask;
448  }

◆ total_size_bits()

template<unsigned int mantiss, unsigned int exp, unsigned int tag = 1>
constexpr static unsigned int FloatingPointHelpers::IEEE754_like< mantiss, exp, tag >::total_size_bits ( )
inlinestaticconstexpr

Definition at line 355 of file FPHelpers.h.

356  {
357  return mantiss + exp + 1;
358  }

The documentation for this class was generated from the following file:
mergePhysValFiles.pattern
pattern
Definition: DataQuality/DataQualityUtils/scripts/mergePhysValFiles.py:26
FloatingPointHelpers::RoundingModes::ToPlusInfinity
@ ToPlusInfinity
FloatingPointHelpers::IEEE754_like::mantissa_size_bits
constexpr static unsigned int mantissa_size_bits()
Definition: FPHelpers.h:360
drawFromPickle.exp
exp
Definition: drawFromPickle.py:36
FloatingPointHelpers::RoundingModes::ToNearestAwayFromZero
@ ToNearestAwayFromZero
FloatingPointHelpers::RoundingModes::ToNearestEven
@ ToNearestEven
ret
T ret(T t)
Definition: rootspy.cxx:260
FloatingPointHelpers::RoundingModes::ToMinusInfinity
@ ToMinusInfinity
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
FloatingPointHelpers::RoundingModes::ToZero
@ ToZero
a
TList * a
Definition: liststreamerinfos.cxx:10
TSU::T
unsigned long long T
Definition: L1TopoDataTypes.h:35