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