github.com/igggame/nebulas-go@v2.1.0+incompatible/nbre/common/math/softfloat.hpp (about)

     1  /*
     2   * Copyright (C) 2017 ETH Zurich, University of Bologna
     3   * All rights reserved.
     4   *
     5   *
     6   * Bug fixes and contributions will eventually be released under the
     7   * SolderPad open hardware license in the context of the PULP platform
     8   * (http://www.pulp-platform.org), under the copyright of ETH Zurich and the
     9   * University of Bologna.
    10   *
    11   * -------
    12   *
    13   * C++ wrapper for the SoftFloat library.
    14   * Defines the following classes:
    15   *  - float8
    16   *  - float16
    17   *  - float32
    18   *  - float64
    19   *  - extFloat80
    20   *  - float128
    21   * Includes overloaded operators for:
    22   *  - casts
    23   *  - arithmetic operators
    24   *  - relational operators
    25   *  - compound assignments
    26   *
    27   * -------
    28   *
    29   * Author: Stefan Mach
    30   * Email:  smach@iis.ee.ethz.ch
    31   * Date:   2017-05-19 09:51:34
    32   * Last Modified by:   Xuepeng Fan
    33   * Last Modified time: 2018-11-20
    34   */
    35  
    36  #pragma once
    37  #include "softfloat.h"
    38  
    39  /*----------------------------------------------------------------------------
    40  |  _______                   _       _
    41  | |__   __|                 | |     | |
    42  |    | | ___ _ __ ___  _ __ | | __ _| |_ ___  ___
    43  |    | |/ _ \ '_ ` _ \| '_ \| |/ _` | __/ _ \/ __|
    44  |    | |  __/ | | | | | |_) | | (_| | ||  __/\__ \
    45  |    |_|\___|_| |_| |_| .__/|_|\__,_|\__\___||___/
    46  |                     | |
    47  |                     |_|
    48  *----------------------------------------------------------------------------*/
    49  /*----------------------------------------------------------------------------
    50  | Function Templates
    51  *----------------------------------------------------------------------------*/
    52  template <typename From, typename To> static inline To softfloat_cast(const From &);
    53  template <typename T> static inline T softfloat_roundToInt(const T &);
    54  template <typename T> static inline T softfloat_add(const T &, const T &);
    55  template <typename T> static inline T softfloat_sub(const T &, const T &);
    56  template <typename T> static inline T softfloat_mul(const T &, const T &);
    57  template <typename T> static inline T softfloat_mulAdd(const T &, const T &, const T &);
    58  template <typename T> static inline T softfloat_div(const T &, const T &);
    59  template <typename T> static inline T softfloat_rem(const T &, const T &);
    60  template <typename T> static inline T softfloat_sqrt(const T &);
    61  template <typename T> static inline bool softfloat_eq(const T &, const T &);
    62  template <typename T> static inline bool softfloat_le(const T &, const T &);
    63  template <typename T> static inline bool softfloat_lt(const T &, const T &);
    64  template <typename T> static inline bool softfloat_isSignalingNaN(const T &);
    65  
    66  /*----------------------------------------------------------------------------
    67  | Class Template
    68  *----------------------------------------------------------------------------*/
    69  template <typename T> class softfloat;
    70  
    71  
    72  /*----------------------------------------------------------------------------
    73  |  ______                    _____        __ _       _ _   _
    74  | |  ____|                  |  __ \      / _(_)     (_) | (_)
    75  | | |__ _   _ _ __   ___    | |  | | ___| |_ _ _ __  _| |_ _  ___  _ __  ___
    76  | |  __| | | | '_ \ / __|   | |  | |/ _ \  _| | '_ \| | __| |/ _ \| '_ \/ __|
    77  | | |  | |_| | | | | (__ _  | |__| |  __/ | | | | | | | |_| | (_) | | | \__ \
    78  | |_|   \__,_|_| |_|\___(_) |_____/ \___|_| |_|_| |_|_|\__|_|\___/|_| |_|___/
    79  |
    80  *----------------------------------------------------------------------------*/
    81  /*----------------------------------------------------------------------------
    82  |  __                                  __ _
    83  | /   _  _ _|_ _     o __ _|_   ---   |_ |_)
    84  | \__(_|_>  |__>     | | | |_         |  |
    85  |
    86  *----------------------------------------------------------------------------*/
    87  
    88  
    89  /*----------------------------------------------------------------------------
    90  | From ui32
    91  *----------------------------------------------------------------------------*/
    92  
    93  template <> float16_t softfloat_cast<uint32_t, float16_t>(const uint32_t &v) {
    94      return ui32_to_f16(v);
    95  }
    96  
    97  template <> float32_t softfloat_cast<uint32_t, float32_t>(const uint32_t &v) {
    98      return ui32_to_f32(v);
    99  }
   100  
   101  template <> float64_t softfloat_cast<uint32_t, float64_t>(const uint32_t &v) {
   102      return ui32_to_f64(v);
   103  }
   104  
   105  template <> extFloat80_t softfloat_cast<uint32_t, extFloat80_t>(const uint32_t &v) {
   106      extFloat80_t tmp;
   107      ui32_to_extF80M(v, &tmp);
   108      return tmp;
   109  }
   110  
   111  template <> float128_t softfloat_cast<uint32_t, float128_t>(const uint32_t &v) {
   112      float128_t tmp;
   113      ui32_to_f128M(v, &tmp);
   114      return tmp;
   115  }
   116  
   117  /*----------------------------------------------------------------------------
   118  | From ui64
   119  *----------------------------------------------------------------------------*/
   120  
   121  template <> float16_t softfloat_cast<uint64_t, float16_t>(const uint64_t &v) {
   122      return ui64_to_f16(v);
   123  }
   124  
   125  template <> float32_t softfloat_cast<uint64_t, float32_t>(const uint64_t &v) {
   126      return ui64_to_f32(v);
   127  }
   128  
   129  template <> float64_t softfloat_cast<uint64_t, float64_t>(const uint64_t &v) {
   130      return ui64_to_f64(v);
   131  }
   132  
   133  template <> extFloat80_t softfloat_cast<uint64_t, extFloat80_t>(const uint64_t &v) {
   134      extFloat80_t tmp;
   135      ui64_to_extF80M(v, &tmp);
   136      return tmp;
   137  }
   138  
   139  template <> float128_t softfloat_cast<uint64_t, float128_t>(const uint64_t &v) {
   140      float128_t tmp;
   141      ui64_to_f128M(v, &tmp);
   142      return tmp;
   143  }
   144  
   145  /*----------------------------------------------------------------------------
   146  | From i32
   147  *----------------------------------------------------------------------------*/
   148  
   149  template <> float16_t softfloat_cast<int32_t, float16_t>(const int32_t &v) {
   150      return i32_to_f16(v);
   151  }
   152  
   153  template <> float32_t softfloat_cast<int32_t, float32_t>(const int32_t &v) {
   154      return i32_to_f32(v);
   155  }
   156  
   157  template <> float64_t softfloat_cast<int32_t, float64_t>(const int32_t &v) {
   158      return i32_to_f64(v);
   159  }
   160  
   161  template <> extFloat80_t softfloat_cast<int32_t, extFloat80_t>(const int32_t &v) {
   162      extFloat80_t tmp;
   163      i32_to_extF80M(v, &tmp);
   164      return tmp;
   165  }
   166  
   167  template <> float128_t softfloat_cast<int32_t, float128_t>(const int32_t &v) {
   168      float128_t tmp;
   169      i32_to_f128M(v, &tmp);
   170      return tmp;
   171  }
   172  
   173  /*----------------------------------------------------------------------------
   174  | From i64
   175  *----------------------------------------------------------------------------*/
   176  
   177  template <> float16_t softfloat_cast<int64_t, float16_t>(const int64_t &v) {
   178      return i64_to_f16(v);
   179  }
   180  
   181  template <> float32_t softfloat_cast<int64_t, float32_t>(const int64_t &v) {
   182      return i64_to_f32(v);
   183  }
   184  
   185  template <> float64_t softfloat_cast<int64_t, float64_t>(const int64_t &v) {
   186      return i64_to_f64(v);
   187  }
   188  
   189  template <> extFloat80_t softfloat_cast<int64_t, extFloat80_t>(const int64_t &v) {
   190      extFloat80_t tmp;
   191      i64_to_extF80M(v, &tmp);
   192      return tmp;
   193  }
   194  
   195  template <> float128_t softfloat_cast<int64_t, float128_t>(const int64_t &v) {
   196      float128_t tmp;
   197      i64_to_f128M(v, &tmp);
   198      return tmp;
   199  }
   200  
   201  /*----------------------------------------------------------------------------
   202  |  __                __ _           __ _
   203  | /   _  _ _|_ _    |_ |_)   ---   |_ |_)
   204  | \__(_|_>  |__>    |  |           |  |
   205  |
   206  *----------------------------------------------------------------------------*/
   207  
   208  /*----------------------------------------------------------------------------
   209  | From float
   210  *----------------------------------------------------------------------------*/
   211  
   212  template <> float16_t softfloat_cast<float, float16_t>(const float &v) {
   213      float32_t result;
   214      const uint32_t *value = reinterpret_cast<const uint32_t *>(&v);
   215      result.v = *value;
   216      return f32_to_f16(result);
   217  }
   218  
   219  template <> float32_t softfloat_cast<float, float32_t>(const float &v) {
   220      float32_t result;
   221      const uint32_t *value = reinterpret_cast<const uint32_t *>(&v);
   222      result.v = *value;
   223      return result;
   224  }
   225  
   226  template <> float64_t softfloat_cast<float, float64_t>(const float &v) {
   227      float32_t result;
   228      const uint32_t *value = reinterpret_cast<const uint32_t *>(&v);
   229      result.v = *value;
   230      return f32_to_f64(result);
   231  }
   232  
   233  template <> extFloat80_t softfloat_cast<float, extFloat80_t>(const float &v) {
   234      float32_t result;
   235      const uint32_t *value = reinterpret_cast<const uint32_t *>(&v);
   236      result.v = *value;
   237      extFloat80_t tmp;
   238      f32_to_extF80M(result, &tmp);
   239      return tmp;
   240  }
   241  
   242  template <> float128_t softfloat_cast<float, float128_t>(const float &v) {
   243      float32_t result;
   244      const uint32_t *value = reinterpret_cast<const uint32_t *>(&v);
   245      result.v = *value;
   246      float128_t tmp;
   247      f32_to_f128M(result, &tmp);
   248      return tmp;
   249  }
   250  
   251  /*----------------------------------------------------------------------------
   252  | From double
   253  *----------------------------------------------------------------------------*/
   254  
   255  template <> float16_t softfloat_cast<double, float16_t>(const double &v) {
   256      float64_t result;
   257      const uint64_t *value = reinterpret_cast<const uint64_t *>(&v);
   258      result.v = *value;
   259      return f64_to_f16(result);
   260  }
   261  
   262  template <> float32_t softfloat_cast<double, float32_t>(const double &v) {
   263      float64_t result;
   264      const uint64_t *value = reinterpret_cast<const uint64_t *>(&v);
   265      result.v = *value;
   266      return f64_to_f32(result);
   267  }
   268  
   269  template <> float64_t softfloat_cast<double, float64_t>(const double &v) {
   270      float64_t result;
   271      const uint64_t *value = reinterpret_cast<const uint64_t *>(&v);
   272      result.v = *value;
   273      return result;
   274  }
   275  
   276  template <> extFloat80_t softfloat_cast<double, extFloat80_t>(const double &v) {
   277      float64_t result;
   278      const uint64_t *value = reinterpret_cast<const uint64_t *>(&v);
   279      result.v = *value;
   280      extFloat80_t tmp;
   281      f64_to_extF80M(result, &tmp);
   282      return tmp;
   283  }
   284  
   285  template <> float128_t softfloat_cast<double, float128_t>(const double &v) {
   286      float64_t result;
   287      const uint64_t *value = reinterpret_cast<const uint64_t *>(&v);
   288      result.v = *value;
   289      float128_t tmp;
   290      f64_to_f128M(result, &tmp);
   291      return tmp;
   292  }
   293  
   294  /*----------------------------------------------------------------------------
   295  | From long double
   296  *----------------------------------------------------------------------------*/
   297  
   298  template <> float16_t softfloat_cast<long double, float16_t>(const long double &v) {
   299      float128_t result;
   300      const uint64_t *value = reinterpret_cast<const uint64_t *>(&v);
   301      result.v[0] = value[0];
   302      result.v[1] = value[1];
   303      return f128M_to_f16(&result);
   304  }
   305  
   306  template <> float32_t softfloat_cast<long double, float32_t>(const long double &v) {
   307      float128_t result;
   308      const uint64_t *value = reinterpret_cast<const uint64_t *>(&v);
   309      result.v[0] = value[0];
   310      result.v[1] = value[1];
   311      return f128M_to_f32(&result);
   312  }
   313  
   314  template <> float64_t softfloat_cast<long double, float64_t>(const long double &v) {
   315      float128_t result;
   316      const uint64_t *value = reinterpret_cast<const uint64_t *>(&v);
   317      result.v[0] = value[0];
   318      result.v[1] = value[1];
   319      return f128M_to_f64(&result);
   320  }
   321  
   322  template <> extFloat80_t softfloat_cast<long double, extFloat80_t>(const long double &v) {
   323      float128_t result;
   324      const uint64_t *value = reinterpret_cast<const uint64_t *>(&v);
   325      result.v[0] = value[0];
   326      result.v[1] = value[1];
   327      extFloat80_t tmp;
   328      f128M_to_extF80M(&result, &tmp);
   329      return tmp;
   330  }
   331  
   332  template <> float128_t softfloat_cast<long double, float128_t>(const long double &v) {
   333      float128_t result;
   334      const uint64_t *value = reinterpret_cast<const uint64_t *>(&v);
   335      result.v[0] = value[0];
   336      result.v[1] = value[1];
   337      return result;
   338  }
   339  
   340  
   341  /*----------------------------------------------------------------------------
   342  | From f16
   343  *----------------------------------------------------------------------------*/
   344  
   345  template <> float16_t softfloat_cast<float16_t, float16_t>(const float16_t &v) {
   346      return v;
   347  }
   348  
   349  template <> float32_t softfloat_cast<float16_t, float32_t>(const float16_t &v) {
   350      return f16_to_f32(v);
   351  }
   352  
   353  template <> float64_t softfloat_cast<float16_t, float64_t>(const float16_t &v) {
   354      return f16_to_f64(v);
   355  }
   356  
   357  template <> extFloat80_t softfloat_cast<float16_t, extFloat80_t>(const float16_t &v) {
   358      extFloat80_t tmp;
   359      f16_to_extF80M(v, &tmp);
   360      return tmp;
   361  }
   362  
   363  template <> float128_t softfloat_cast<float16_t, float128_t>(const float16_t &v) {
   364      float128_t tmp;
   365      f16_to_f128M(v, &tmp);
   366      return tmp;
   367  }
   368  
   369  /*----------------------------------------------------------------------------
   370  | From f32
   371  *----------------------------------------------------------------------------*/
   372  
   373  template <> float16_t softfloat_cast<float32_t, float16_t>(const float32_t &v) {
   374      return f32_to_f16(v);
   375  }
   376  
   377  template <> float32_t softfloat_cast<float32_t, float32_t>(const float32_t &v) {
   378      return v;
   379  }
   380  
   381  template <> float64_t softfloat_cast<float32_t, float64_t>(const float32_t &v) {
   382      return f32_to_f64(v);
   383  }
   384  
   385  template <> extFloat80_t softfloat_cast<float32_t, extFloat80_t>(const float32_t &v) {
   386      extFloat80_t tmp;
   387      f32_to_extF80M(v, &tmp);
   388      return tmp;
   389  }
   390  
   391  template <> float128_t softfloat_cast<float32_t, float128_t>(const float32_t &v) {
   392      float128_t tmp;
   393      f32_to_f128M(v, &tmp);
   394      return tmp;
   395  }
   396  
   397  /*----------------------------------------------------------------------------
   398  | From f64
   399  *----------------------------------------------------------------------------*/
   400  
   401  template <> float16_t softfloat_cast<float64_t, float16_t>(const float64_t &v) {
   402      return f64_to_f16(v);
   403  }
   404  
   405  template <> float32_t softfloat_cast<float64_t, float32_t>(const float64_t &v) {
   406      return f64_to_f32(v);
   407  }
   408  
   409  template <> float64_t softfloat_cast<float64_t, float64_t>(const float64_t &v) {
   410      return v;
   411  }
   412  
   413  template <> extFloat80_t softfloat_cast<float64_t, extFloat80_t>(const float64_t &v) {
   414      extFloat80_t tmp;
   415      f64_to_extF80M(v, &tmp);
   416      return tmp;
   417  }
   418  
   419  template <> float128_t softfloat_cast<float64_t, float128_t>(const float64_t &v) {
   420      float128_t tmp;
   421      f64_to_f128M(v, &tmp);
   422      return tmp;
   423  }
   424  
   425  /*----------------------------------------------------------------------------
   426  | From extF80
   427  *----------------------------------------------------------------------------*/
   428  
   429  template <> float16_t softfloat_cast<extFloat80_t, float16_t>(const extFloat80_t &v) {
   430      return extF80M_to_f16(&v);
   431  }
   432  
   433  template <> float32_t softfloat_cast<extFloat80_t, float32_t>(const extFloat80_t &v) {
   434      return extF80M_to_f32(&v);
   435  }
   436  
   437  template <> float64_t softfloat_cast<extFloat80_t, float64_t>(const extFloat80_t &v) {
   438      return extF80M_to_f64(&v);
   439  }
   440  
   441  template <> extFloat80_t softfloat_cast<extFloat80_t, extFloat80_t>(const extFloat80_t &v) {
   442      return v;
   443  }
   444  
   445  template <> float128_t softfloat_cast<extFloat80_t, float128_t>(const extFloat80_t &v) {
   446      float128_t tmp;
   447      extF80M_to_f128M(&v, &tmp);
   448      return tmp;
   449  }
   450  
   451  /*----------------------------------------------------------------------------
   452  | From f128
   453  *----------------------------------------------------------------------------*/
   454  
   455  template <> float16_t softfloat_cast<float128_t, float16_t>(const float128_t &v) {
   456      return f128M_to_f16(&v);
   457  }
   458  
   459  template <> float32_t softfloat_cast<float128_t, float32_t>(const float128_t &v) {
   460      return f128M_to_f32(&v);
   461  }
   462  
   463  template <> float64_t softfloat_cast<float128_t, float64_t>(const float128_t &v) {
   464      return f128M_to_f64(&v);
   465  }
   466  
   467  template <> extFloat80_t softfloat_cast<float128_t, extFloat80_t>(const float128_t &v) {
   468      extFloat80_t tmp;
   469      f128M_to_extF80M(&v, &tmp);
   470      return tmp;
   471  }
   472  
   473  template <> float128_t softfloat_cast<float128_t, float128_t>(const float128_t &v) {
   474      return v;
   475  }
   476  
   477  /*----------------------------------------------------------------------------
   478  |  __                __ _
   479  | /   _  _ _|_ _    |_ |_)   ---    o __ _|_
   480  | \__(_|_>  |__>    |  |            | | | |_
   481  |
   482  | The template specializations here use round towards 0 as their default mode!
   483  *----------------------------------------------------------------------------*/
   484  
   485  /*----------------------------------------------------------------------------
   486  | From f16
   487  *----------------------------------------------------------------------------*/
   488  template <> uint32_t softfloat_cast<float16_t, uint32_t>(const float16_t &v) {
   489      return f16_to_ui32_r_minMag(v, true);
   490  }
   491  
   492  template <> uint64_t softfloat_cast<float16_t, uint64_t>(const float16_t &v) {
   493      return f16_to_ui64_r_minMag(v, true);
   494  }
   495  
   496  template <> int32_t softfloat_cast<float16_t, int32_t>(const float16_t &v) {
   497      return f16_to_i32_r_minMag(v, true);
   498  }
   499  
   500  template <> int64_t softfloat_cast<float16_t, int64_t>(const float16_t &v) {
   501      return f16_to_i64_r_minMag(v, true);
   502  }
   503  
   504  /*----------------------------------------------------------------------------
   505  | From f32
   506  *----------------------------------------------------------------------------*/
   507  template <> uint32_t softfloat_cast<float32_t, uint32_t>(const float32_t &v) {
   508      return f32_to_ui32_r_minMag(v, true);
   509  }
   510  
   511  template <> uint64_t softfloat_cast<float32_t, uint64_t>(const float32_t &v) {
   512      return f32_to_ui64_r_minMag(v, true);
   513  }
   514  
   515  template <> int32_t softfloat_cast<float32_t, int32_t>(const float32_t &v) {
   516      return f32_to_i32_r_minMag(v, true);
   517  }
   518  
   519  template <> int64_t softfloat_cast<float32_t, int64_t>(const float32_t &v) {
   520      return f32_to_i64_r_minMag(v, true);
   521  }
   522  
   523  /*----------------------------------------------------------------------------
   524  | From f64
   525  *----------------------------------------------------------------------------*/
   526  template <> uint32_t softfloat_cast<float64_t, uint32_t>(const float64_t &v) {
   527      return f64_to_ui32_r_minMag(v, true);
   528  }
   529  
   530  template <> uint64_t softfloat_cast<float64_t, uint64_t>(const float64_t &v) {
   531      return f64_to_ui64_r_minMag(v, true);
   532  }
   533  
   534  template <> int32_t softfloat_cast<float64_t, int32_t>(const float64_t &v) {
   535      return f64_to_i32_r_minMag(v, true);
   536  }
   537  
   538  template <> int64_t softfloat_cast<float64_t, int64_t>(const float64_t &v) {
   539      return f64_to_i64_r_minMag(v, true);
   540  }
   541  
   542  /*----------------------------------------------------------------------------
   543  | From ext80
   544  *----------------------------------------------------------------------------*/
   545  template <> uint32_t softfloat_cast<extFloat80_t, uint32_t>(const extFloat80_t &v) {
   546      return extF80M_to_ui32_r_minMag(&v, true);
   547  }
   548  
   549  template <> uint64_t softfloat_cast<extFloat80_t, uint64_t>(const extFloat80_t &v) {
   550      return extF80M_to_ui64_r_minMag(&v, true);
   551  }
   552  
   553  template <> int32_t softfloat_cast<extFloat80_t, int32_t>(const extFloat80_t &v) {
   554      return extF80M_to_i32_r_minMag(&v, true);
   555  }
   556  
   557  template <> int64_t softfloat_cast<extFloat80_t, int64_t>(const extFloat80_t &v) {
   558      return extF80M_to_i64_r_minMag(&v, true);
   559  }
   560  
   561  /*----------------------------------------------------------------------------
   562  | From f128
   563  *----------------------------------------------------------------------------*/
   564  template <> uint32_t softfloat_cast<float128_t, uint32_t>(const float128_t &v) {
   565      return f128M_to_ui32_r_minMag(&v, true);
   566  }
   567  
   568  template <> uint64_t softfloat_cast<float128_t, uint64_t>(const float128_t &v) {
   569      return f128M_to_ui64_r_minMag(&v, true);
   570  }
   571  
   572  template <> int32_t softfloat_cast<float128_t, int32_t>(const float128_t &v) {
   573      return f128M_to_i32_r_minMag(&v, true);
   574  }
   575  
   576  template <> int64_t softfloat_cast<float128_t, int64_t>(const float128_t &v) {
   577      return f128M_to_i64_r_minMag(&v, true);
   578  }
   579  
   580  /*----------------------------------------------------------------------------
   581  |  _
   582  | |_) _    __  _|   _|_ _     o __ _|_
   583  | | \(_)|_|| |(_|    |_(_)    | | | |_
   584  |
   585  | These template specializations use the global rounding mode for rounding!
   586  *----------------------------------------------------------------------------*/
   587  
   588  template <> float16_t softfloat_roundToInt(const float16_t &v) {
   589      return f16_roundToInt(v, softfloat_roundingMode, true);
   590  }
   591  
   592  template <> float32_t softfloat_roundToInt(const float32_t &v) {
   593      return f32_roundToInt(v, softfloat_roundingMode, true);
   594  }
   595  
   596  template <> float64_t softfloat_roundToInt(const float64_t &v) {
   597      return f64_roundToInt(v, softfloat_roundingMode, true);
   598  }
   599  
   600  template <> extFloat80_t softfloat_roundToInt(const extFloat80_t &v) {
   601      extFloat80_t tmp;
   602      extF80M_roundToInt(&v, softfloat_roundingMode, true, &tmp);
   603      return tmp;
   604  }
   605  
   606  template <> float128_t softfloat_roundToInt(const float128_t &v) {
   607      float128_t tmp;
   608      f128M_roundToInt(&v, softfloat_roundingMode, true, &tmp);
   609      return tmp;
   610  }
   611  
   612  /*----------------------------------------------------------------------------
   613  |  _
   614  | |_| _| _| o _|_ o  _ __
   615  | | |(_|(_| |  |_ | (_)| |
   616  |
   617  *----------------------------------------------------------------------------*/
   618  
   619  template <> float16_t softfloat_add(const float16_t &a, const float16_t &b) {
   620      return f16_add(a,b);
   621  }
   622  
   623  template <> float32_t softfloat_add(const float32_t &a, const float32_t &b) {
   624      return f32_add(a,b);
   625  }
   626  
   627  template <> float64_t softfloat_add(const float64_t &a, const float64_t &b) {
   628      return f64_add(a,b);
   629  }
   630  
   631  template <> extFloat80_t softfloat_add(const extFloat80_t &a, const extFloat80_t &b) {
   632      extFloat80_t tmp;
   633      extF80M_add(&a,&b,&tmp);
   634      return tmp;
   635  }
   636  
   637  template <> float128_t softfloat_add(const float128_t &a, const float128_t &b) {
   638      float128_t tmp;
   639      f128M_add(&a,&b,&tmp);
   640      return tmp;
   641  }
   642  
   643  /*----------------------------------------------------------------------------
   644  |  __
   645  | (_    |_ _|_ __ _  _ _|_ o  _ __
   646  | __)|_||_) |_ | (_|(_  |_ | (_)| |
   647  |
   648  *----------------------------------------------------------------------------*/
   649  
   650  template <> float16_t softfloat_sub(const float16_t &a, const float16_t &b) {
   651      return f16_sub(a,b);
   652  }
   653  
   654  template <> float32_t softfloat_sub(const float32_t &a, const float32_t &b) {
   655      return f32_sub(a,b);
   656  }
   657  
   658  template <> float64_t softfloat_sub(const float64_t &a, const float64_t &b) {
   659      return f64_sub(a,b);
   660  }
   661  
   662  template <> extFloat80_t softfloat_sub(const extFloat80_t &a, const extFloat80_t &b) {
   663      extFloat80_t tmp;
   664      extF80M_sub(&a,&b,&tmp);
   665      return tmp;
   666  }
   667  
   668  template <> float128_t softfloat_sub(const float128_t &a, const float128_t &b) {
   669      float128_t tmp;
   670      f128M_sub(&a,&b,&tmp);
   671      return tmp;
   672  }
   673  
   674  /*----------------------------------------------------------------------------
   675  |                 _
   676  | |V|    | _|_ o |_) |  o  _  _ _|_ o  _ __
   677  | | ||_| |  |_ | |   |  | (_ (_| |_ | (_)| |
   678  |
   679  *----------------------------------------------------------------------------*/
   680  template <> float16_t softfloat_mul(const float16_t &a, const float16_t &b) {
   681      return f16_mul(a,b);
   682  }
   683  
   684  template <> float32_t softfloat_mul(const float32_t &a, const float32_t &b) {
   685      return f32_mul(a,b);
   686  }
   687  
   688  template <> float64_t softfloat_mul(const float64_t &a, const float64_t &b) {
   689      return f64_mul(a,b);
   690  }
   691  
   692  template <> extFloat80_t softfloat_mul(const extFloat80_t &a, const extFloat80_t &b) {
   693      extFloat80_t tmp;
   694      extF80M_mul(&a,&b,&tmp);
   695      return tmp;
   696  }
   697  
   698  template <> float128_t softfloat_mul(const float128_t &a, const float128_t &b) {
   699      float128_t tmp;
   700      f128M_mul(&a,&b,&tmp);
   701      return tmp;
   702  }
   703  
   704  /*----------------------------------------------------------------------------
   705  |  __                               _           _
   706  | |_     _  _  _|   |V|    | _|_ o |_) |  \/---|_| _| _|
   707  | |  |_|_> (/_(_|   | ||_| |  |_ | |   |  /    | |(_|(_|
   708  |
   709  *----------------------------------------------------------------------------*/
   710  template <> float16_t softfloat_mulAdd(const float16_t &a, const float16_t &b, const float16_t &c) {
   711      return f16_mulAdd(a,b,c);
   712  }
   713  
   714  template <> float32_t softfloat_mulAdd(const float32_t &a, const float32_t &b, const float32_t &c) {
   715      return f32_mulAdd(a,b,c);
   716  }
   717  
   718  template <> float64_t softfloat_mulAdd(const float64_t &a, const float64_t &b, const float64_t &c) {
   719      return f64_mulAdd(a,b,c);
   720  }
   721  
   722  template <> extFloat80_t softfloat_mulAdd(const extFloat80_t &a, const extFloat80_t &b, const extFloat80_t &c) {
   723      return softfloat_add(softfloat_mul(a,b),c); /* Compounded */
   724  }
   725  
   726  template <> float128_t softfloat_mulAdd(const float128_t &a, const float128_t &b, const float128_t &c) {
   727      float128_t tmp;
   728      f128M_mulAdd(&a,&b,&c,&tmp);
   729      return tmp;
   730  }
   731  
   732  /*----------------------------------------------------------------------------
   733  |  _
   734  | | \ o     o  _  o  _ __
   735  | |_/ | \_/ | _>  | (_)| |
   736  |
   737  *----------------------------------------------------------------------------*/
   738  template <> float16_t softfloat_div(const float16_t &a, const float16_t &b) {
   739      return f16_div(a,b);
   740  }
   741  
   742  template <> float32_t softfloat_div(const float32_t &a, const float32_t &b) {
   743      return f32_div(a,b);
   744  }
   745  
   746  template <> float64_t softfloat_div(const float64_t &a, const float64_t &b) {
   747      return f64_div(a,b);
   748  }
   749  
   750  template <> extFloat80_t softfloat_div(const extFloat80_t &a, const extFloat80_t &b) {
   751      extFloat80_t tmp;
   752      extF80M_div(&a,&b,&tmp);
   753      return tmp;
   754  }
   755  
   756  template <> float128_t softfloat_div(const float128_t &a, const float128_t &b) {
   757      float128_t tmp;
   758      f128M_div(&a,&b,&tmp);
   759      return tmp;
   760  }
   761  
   762  /*----------------------------------------------------------------------------
   763  |  _
   764  | |_) _ __  _  o __  _| _  __
   765  | | \(/_|||(_| | | |(_|(/_ |
   766  |
   767  *----------------------------------------------------------------------------*/
   768  template <> float16_t softfloat_rem(const float16_t &a, const float16_t &b) {
   769      return f16_rem(a,b);
   770  }
   771  
   772  template <> float32_t softfloat_rem(const float32_t &a, const float32_t &b) {
   773      return f32_rem(a,b);
   774  }
   775  
   776  template <> float64_t softfloat_rem(const float64_t &a, const float64_t &b) {
   777      return f64_rem(a,b);
   778  }
   779  
   780  template <> extFloat80_t softfloat_rem(const extFloat80_t &a, const extFloat80_t &b) {
   781      extFloat80_t tmp;
   782      extF80M_rem(&a,&b,&tmp);
   783      return tmp;
   784  }
   785  
   786  template <> float128_t softfloat_rem(const float128_t &a, const float128_t &b) {
   787      float128_t tmp;
   788      f128M_rem(&a,&b,&tmp);
   789      return tmp;
   790  }
   791  
   792  /*----------------------------------------------------------------------------
   793  |  __ _                 _
   794  | (_ (_|    _  __ _    |_) _  _ _|_
   795  | __)  ||_|(_| | (/_   | \(_)(_) |_
   796  |
   797  *----------------------------------------------------------------------------*/
   798  template <> float16_t softfloat_sqrt(const float16_t &a) {
   799      return f16_sqrt(a);
   800  }
   801  
   802  template <> float32_t softfloat_sqrt(const float32_t &a) {
   803      return f32_sqrt(a);
   804  }
   805  
   806  template <> float64_t softfloat_sqrt(const float64_t &a) {
   807      return f64_sqrt(a);
   808  }
   809  
   810  template <> extFloat80_t softfloat_sqrt(const extFloat80_t &a) {
   811      extFloat80_t tmp;
   812      extF80M_sqrt(&a,&tmp);
   813      return tmp;
   814  }
   815  
   816  template <> float128_t softfloat_sqrt(const float128_t &a) {
   817      float128_t tmp;
   818      f128M_sqrt(&a,&tmp);
   819      return tmp;
   820  }
   821  
   822  /*----------------------------------------------------------------------------
   823  |  __ _
   824  | |_ (_|    _  |  o _|_ \/
   825  | |__  ||_|(_| |  |  |_ /
   826  |
   827  | These template specializations use signaling comparisons!
   828  *----------------------------------------------------------------------------*/
   829  template <> bool softfloat_eq(const float16_t &a, const float16_t &b) {
   830      return f16_eq_signaling(a,b);
   831  }
   832  
   833  template <> bool softfloat_eq(const float32_t &a, const float32_t &b) {
   834      return f32_eq_signaling(a,b);
   835  }
   836  
   837  template <> bool softfloat_eq(const float64_t &a, const float64_t &b) {
   838      return f64_eq_signaling(a,b);
   839  }
   840  
   841  template <> bool softfloat_eq(const extFloat80_t &a, const extFloat80_t &b) {
   842       return extF80M_eq_signaling(&a,&b);
   843  }
   844  
   845  template <> bool softfloat_eq(const float128_t &a, const float128_t &b) {
   846       return f128M_eq_signaling(&a,&b);
   847  }
   848  
   849  /*----------------------------------------------------------------------------
   850  |                ___             _        __ _             ___
   851  | |   _  _  _ --- | |_  _ __ ---/ \ __---|_ (_|    _  | --- |  _
   852  | |__(/__> _>     | | |(_|| |   \_/ |    |__  ||_|(_| |     | (_)
   853  |
   854  | These template specializations use signaling comparisons!
   855  *----------------------------------------------------------------------------*/
   856  template <> bool softfloat_le(const float16_t &a, const float16_t &b) {
   857      return f16_le(a,b);
   858  }
   859  
   860  template <> bool softfloat_le(const float32_t &a, const float32_t &b) {
   861      return f32_le(a,b);
   862  }
   863  
   864  template <> bool softfloat_le(const float64_t &a, const float64_t &b) {
   865      return f64_le(a,b);
   866  }
   867  
   868  template <> bool softfloat_le(const extFloat80_t &a, const extFloat80_t &b) {
   869       return extF80M_le(&a,&b);
   870  }
   871  
   872  template <> bool softfloat_le(const float128_t &a, const float128_t &b) {
   873       return f128M_le(&a,&b);
   874  }
   875  
   876  /*----------------------------------------------------------------------------
   877  |                ___
   878  | |   _  _  _ --- | |_  _ __
   879  | |__(/__> _>     | | |(_|| |
   880  |
   881  | These template specializations use signaling comparisons!
   882  *----------------------------------------------------------------------------*/
   883  template <> bool softfloat_lt(const float16_t &a, const float16_t &b) {
   884      return f16_lt(a,b);
   885  }
   886  
   887  template <> bool softfloat_lt(const float32_t &a, const float32_t &b) {
   888      return f32_lt(a,b);
   889  }
   890  
   891  template <> bool softfloat_lt(const float64_t &a, const float64_t &b) {
   892      return f64_lt(a,b);
   893  }
   894  
   895  template <> bool softfloat_lt(const extFloat80_t &a, const extFloat80_t &b) {
   896       return extF80M_lt(&a,&b);
   897  }
   898  
   899  template <> bool softfloat_lt(const float128_t &a, const float128_t &b) {
   900       return f128M_le(&a,&b);
   901  }
   902  
   903  /*----------------------------------------------------------------------------
   904  | ___       __    _                 _
   905  |  |  _    (_  o (_|__  _  |  o __ (_|   |\| _ |\|
   906  | _|__>    __) | __|| |(_| |  | | |__|   | |(_|| |
   907  |
   908  *----------------------------------------------------------------------------*/
   909  template <> bool softfloat_isSignalingNaN(const float16_t &a) {
   910      return f16_isSignalingNaN(a);
   911  }
   912  
   913  template <> bool softfloat_isSignalingNaN(const float32_t &a) {
   914      return f32_isSignalingNaN(a);
   915  }
   916  
   917  template <> bool softfloat_isSignalingNaN(const float64_t &a) {
   918      return f64_isSignalingNaN(a);
   919  }
   920  
   921  template <> bool softfloat_isSignalingNaN(const extFloat80_t &a) {
   922       return extF80M_isSignalingNaN(&a);
   923  }
   924  
   925  template <> bool softfloat_isSignalingNaN(const float128_t &a) {
   926       return f128M_isSignalingNaN(&a);
   927  }
   928  
   929  
   930  /*----------------------------------------------------------------------------
   931  |   _____ _                 _____        __ _       _ _   _
   932  |  / ____| |               |  __ \      / _(_)     (_) | (_)
   933  | | |    | | __ _ ___ ___  | |  | | ___| |_ _ _ __  _| |_ _  ___  _ __
   934  | | |    | |/ _` / __/ __| | |  | |/ _ \  _| | '_ \| | __| |/ _ \| '_ \
   935  | | |____| | (_| \__ \__ \ | |__| |  __/ | | | | | | | |_| | (_) | | | |
   936  |  \_____|_|\__,_|___/___/ |_____/ \___|_| |_|_| |_|_|\__|_|\___/|_| |_|
   937  |
   938  *----------------------------------------------------------------------------*/
   939  
   940  #include <iostream>
   941  
   942  template<typename TU>
   943  struct redirect_is_signed{
   944    constexpr static bool value = std::is_same<TU, long>::value || std::is_same<TU, long long>::value
   945      || std::is_same<TU, short>::value || std::is_same<TU, int>::value;
   946  };
   947  
   948  template<typename TU>
   949  struct redirect_is_unsigned{
   950    constexpr static bool value = std::is_same<TU, unsigned long>::value || std::is_same<TU, unsigned long long>::value
   951      || std::is_same<TU, unsigned short>::value || std::is_same<TU, unsigned int>::value;
   952  };
   953  
   954  template<typename TU, bool needs_redirect = redirect_is_signed<TU>::value || redirect_is_unsigned<TU>::value >
   955  struct infer_type_helper{};
   956  template<typename TU>
   957  struct infer_type_helper<TU, false>{
   958    typedef TU type;
   959  };
   960  
   961  template <size_t L> struct sized_int_type{};
   962  template <> struct sized_int_type<2>{
   963    typedef int16_t type;
   964  };
   965  template <> struct sized_int_type<4>{
   966    typedef int32_t type;
   967  };
   968  template <> struct sized_int_type<8>{
   969    typedef int64_t type;
   970  };
   971  
   972  template <size_t L> struct sized_uint_type{};
   973  template <> struct sized_uint_type<2>{
   974    typedef uint16_t type;
   975  };
   976  template <> struct sized_uint_type<4>{
   977    typedef uint32_t type;
   978  };
   979  template <> struct sized_uint_type<8>{
   980    typedef uint64_t type;
   981  };
   982  
   983  template <typename TU>
   984  struct infer_type_helper<TU, true>{
   985    typedef typename std::conditional_t<redirect_is_signed<TU>::value,
   986            typename sized_int_type<sizeof(TU)>::type,
   987            typename sized_uint_type<sizeof(TU)>::type> type ;
   988  };
   989  template <typename T> class softfloat {
   990    public:
   991      typedef T value_type;
   992  protected:
   993      T v;
   994  
   995  public:
   996      // Empty constructor --> initialize to positive zero.
   997      inline softfloat () {
   998          v = softfloat_cast<uint32_t,T>(0);
   999      }
  1000  
  1001      // Constructor from wrapped type T
  1002      inline softfloat (const T &v) : v(v) {}
  1003  
  1004      // Constructor from softfloat types
  1005      template <typename U> inline softfloat (const softfloat<U> &w) {
  1006          v = softfloat_cast<U,T>(w);
  1007      }
  1008  
  1009      // Constructor from castable type
  1010      template <typename U> inline softfloat (const U &w) {
  1011          typedef typename infer_type_helper<U>::type TU;
  1012          v = softfloat_cast<TU,T>(w);
  1013      }
  1014  
  1015      inline softfloat<T> round_to_int(){
  1016        return softfloat(softfloat_roundToInt(v));
  1017      }
  1018      inline softfloat<T> integer_val(){
  1019        auto prev = softfloat_roundingMode;
  1020        softfloat_roundingMode = softfloat_round_min;
  1021        auto t = softfloat(softfloat_roundToInt(v));
  1022        softfloat_roundingMode = prev;
  1023        return t;
  1024      }
  1025      inline softfloat<T> decimal_val(){
  1026        return *this - integer_val();
  1027      }
  1028  
  1029  
  1030  
  1031      /*------------------------------------------------------------------------
  1032      | OPERATOR OVERLOADS: CASTS
  1033      *------------------------------------------------------------------------*/
  1034  
  1035      // Cast to the wrapped types --> can implicitly use softfloat object with
  1036      // <float>_ functions from C package.
  1037      inline operator T() const {
  1038          return v;
  1039      }
  1040  
  1041      inline explicit operator float() const {
  1042        uint32_t temp = softfloat_cast<T, float32_t>(v).v;
  1043        float *result = reinterpret_cast<float *>(&temp);
  1044        return *result;
  1045      }
  1046  
  1047      inline explicit operator double() const {
  1048        uint64_t temp = softfloat_cast<T, float64_t>(v).v;
  1049        double *result = reinterpret_cast<double *>(&temp);
  1050        return *result;
  1051      }
  1052  
  1053      inline explicit operator long double() const {
  1054        extFloat80_t temp = softfloat_cast<T, extFloat80_t >(v);
  1055        long double *result = reinterpret_cast<long double *>(&temp);
  1056        return *result;
  1057      }
  1058  
  1059  
  1060      /*------------------------------------------------------------------------
  1061      | OPERATOR OVERLOADS: Arithmetics
  1062      *------------------------------------------------------------------------*/
  1063  
  1064  
  1065      /* UNARY MINUS (-) */
  1066      inline softfloat operator-() const
  1067      {
  1068          return softfloat_sub(softfloat_cast<uint32_t,T>(0), v);
  1069      }
  1070  
  1071      /* UNARY PLUS (+) */
  1072      inline softfloat operator+() const
  1073      {
  1074          return softfloat(*this);
  1075      }
  1076  
  1077      /* ADD (+) */
  1078      friend inline softfloat operator+(const softfloat &a, const softfloat &b)
  1079      {
  1080          return softfloat_add(a.v,b.v);
  1081      }
  1082  
  1083      /* SUBTRACT (-) */
  1084      friend inline softfloat operator-(const softfloat &a, const softfloat &b)
  1085      {
  1086          return softfloat_sub(a.v,b.v);
  1087      }
  1088  
  1089      /* MULTIPLY (*) */
  1090      friend inline softfloat operator*(const softfloat &a, const softfloat &b)
  1091      {
  1092          return softfloat_mul(a.v,b.v);
  1093      }
  1094  
  1095      /* DIVIDE (/) */
  1096      friend inline softfloat operator/(const softfloat &a, const softfloat &b)
  1097      {
  1098          return softfloat_div(a.v,b.v);
  1099      }
  1100  
  1101      /*------------------------------------------------------------------------
  1102      | OPERATOR OVERLOADS: Relational operators
  1103      *------------------------------------------------------------------------*/
  1104  
  1105      /* EQUALITY (==) */
  1106      inline bool operator==(const softfloat &b) const {
  1107          return softfloat_eq(v,b.v);
  1108      }
  1109  
  1110      /* INEQUALITY (!=) */
  1111      inline bool operator!=(const softfloat &b) const {
  1112          return !(softfloat_eq(v,b.v));
  1113      }
  1114  
  1115      /* GREATER-THAN (>) */
  1116      inline bool operator>(const softfloat &b) const {
  1117          return !(softfloat_le(v,b.v));
  1118      }
  1119  
  1120      /* LESS-THAN (<) */
  1121      inline bool operator<(const softfloat &b) const {
  1122          return softfloat_lt(v,b.v);
  1123      }
  1124  
  1125      /* GREATER-THAN-OR-EQUAL-TO (>=) */
  1126      inline bool operator>=(const softfloat &b) const {
  1127          return !(softfloat_lt(v,b.v));
  1128      }
  1129  
  1130      /* LESS-THAN-OR-EQUAL-TO (<=) */
  1131      inline bool operator<=(const softfloat &b) const {
  1132          return softfloat_le(v,b.v);
  1133      }
  1134  
  1135      /*------------------------------------------------------------------------
  1136      | OPERATOR OVERLOADS: Compound assignment operators (no bitwise ops)
  1137      *------------------------------------------------------------------------*/
  1138      inline softfloat &operator+=(const softfloat &b) {
  1139          return *this = *this + b;
  1140      }
  1141  
  1142      inline softfloat &operator-=(const softfloat &b) {
  1143          return *this = *this - b;
  1144      }
  1145  
  1146      inline softfloat &operator*=(const softfloat &b) {
  1147          return *this = *this * b;
  1148      }
  1149  
  1150      inline softfloat &operator/=(const softfloat &b) {
  1151          return *this = *this / b;
  1152      }
  1153  
  1154      /*------------------------------------------------------------------------
  1155      | OPERATOR OVERLOADS: IO streams operators
  1156      *------------------------------------------------------------------------*/
  1157      friend std::ostream& operator<<(std::ostream& os, const softfloat& obj)
  1158      {
  1159        static_assert(sizeof(long double) == 16, "long double is too short");
  1160        auto t = softfloat_cast<T, float64_t>(obj.v);
  1161        os << *(double*)(&t);
  1162        return os;
  1163      }
  1164  
  1165      friend std::istream& operator>>(std::istream& is, softfloat& obj)
  1166      {
  1167        static_assert(sizeof(long double) == 16, "long double is too short");
  1168        float64_t t;
  1169        is >> *(double*)(&t);
  1170        obj.v = softfloat_cast<float64_t, T>(t);
  1171        return is;
  1172      }
  1173  };
  1174  
  1175  
  1176  
  1177  /*----------------------------------------------------------------------------
  1178  |  _______                   _       __
  1179  | |__   __|                 | |     / _|
  1180  |    | |_   _ _ __   ___  __| | ___| |_ ___
  1181  |    | | | | | '_ \ / _ \/ _` |/ _ \  _/ __|
  1182  |    | | |_| | |_) |  __/ (_| |  __/ | \__ \
  1183  |    |_|\__, | .__/ \___|\__,_|\___|_| |___/
  1184  |        __/ | |
  1185  |       |___/|_|
  1186  *----------------------------------------------------------------------------*/
  1187  
  1188  typedef softfloat<float16_t>    float16;
  1189  typedef softfloat<float32_t>    float32;
  1190  typedef softfloat<float64_t>    float64;
  1191  typedef softfloat<extFloat80_t> extFloat80;
  1192  typedef softfloat<float128_t>   float128;
  1193