From 7360e1111b0d15e72c6ca2ccd4bd47f3b9a3d9f4 Mon Sep 17 00:00:00 2001 From: Joe Newton <> Date: Sat, 29 Feb 2020 01:00:13 -0500 Subject: [PATCH 1/5] Added support for Linux --- .github/workflows/swift.yml | 28 ++- .swiftlint.yml | 5 + ATTRIBUTIONS | 317 +++++++++++++++++++++++++ Half.xcodeproj/project.pbxproj | 4 + README.md | 1 + Sources/CHalf/src/fp_extend.cpp | 107 +++++++++ Sources/CHalf/src/fp_trunc.cpp | 135 +++++++++++ Tests/CHalfTests/XCTestManifests.swift | 23 ++ Tests/HalfTests/XCTestManifests.swift | 65 +++++ Tests/LinuxMain.swift | 10 + 10 files changed, 687 insertions(+), 8 deletions(-) create mode 100644 Sources/CHalf/src/fp_extend.cpp create mode 100644 Sources/CHalf/src/fp_trunc.cpp create mode 100644 Tests/CHalfTests/XCTestManifests.swift create mode 100644 Tests/HalfTests/XCTestManifests.swift create mode 100644 Tests/LinuxMain.swift diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index 232b632..457b6ed 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -1,15 +1,27 @@ -name: Swift +name: Test -on: [push] +on: [push, pull_request] jobs: build: - - runs-on: macOS-latest - + strategy: + matrix: + os: [macOS-latest, ubuntu-latest] + swift: ["5.0"] + runs-on: ${{ matrix.os }} + env: + SWIFT_VERSION: ${{ matrix.swift }} + SWIFT_EXEC: .swiftenv/shims/swift steps: - uses: actions/checkout@v2 + - name: Install Swift + run: | + git clone https://github.com/kylef/swiftenv.git ~/.swiftenv + ~/.swiftenv/bin/swiftenv install $SWIFT_VERSION - name: Build - run: swift build -v - - name: Run Tests - run: swift test -v + run: | + ~/$SWIFT_EXEC --version + ~/$SWIFT_EXEC build -v + - name: Test + run: | + ~/$SWIFT_EXEC test -v diff --git a/.swiftlint.yml b/.swiftlint.yml index 6295eef..80ae263 100644 --- a/.swiftlint.yml +++ b/.swiftlint.yml @@ -57,6 +57,11 @@ opt_in_rules: reporter: "xcode" +excluded: + - Tests/LinuxMain.swift + - Tests/HalfTests/XCTestManifests.swift + - Tests/CHalfTests/XCTestManifests.swift + identifier_name: excluded: - pi diff --git a/ATTRIBUTIONS b/ATTRIBUTIONS index a0de46b..a217ce7 100644 --- a/ATTRIBUTIONS +++ b/ATTRIBUTIONS @@ -214,3 +214,320 @@ https://github.com/apple/swift portions of this Software are embedded into the binary product as a result, you may redistribute such product without providing attribution as would otherwise be required by Sections 4(a), 4(b) and 4(d) of the License. + + + +'fp_extend.cpp' and 'fp_func.cpp' are source files taken from a gist (https://gist.github.com/whchung/25875271922806e58ac21ad7d707e3cd) which was adapted from the LLVM compilter-rt project: + +https://github.com/llvm/llvm-project/compiler-rt +============================================================================== +The LLVM Project is under the Apache License v2.0 with LLVM Exceptions: +============================================================================== + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + + +---- LLVM Exceptions to the Apache 2.0 License ---- + +As an exception, if, as a result of your compiling your source code, portions +of this Software are embedded into an Object form of such source code, you +may redistribute such embedded portions in such Object form without complying +with the conditions of Sections 4(a), 4(b) and 4(d) of the License. + +In addition, if you combine or link compiled forms of this Software with +software that is licensed under the GPLv2 ("Combined Software") and if a +court of competent jurisdiction determines that the patent provision (Section +3), the indemnity provision (Section 9) or other Section of the License +conflicts with the conditions of the GPLv2, you may retroactively and +prospectively choose to deem waived or otherwise exclude such Section(s) of +the License, but only in their entirety and only with respect to the Combined +Software. + +============================================================================== +Software from third parties included in the LLVM Project: +============================================================================== +The LLVM Project contains third party software which is under different license +terms. All such code will be identified clearly using at least one of two +mechanisms: +1) It will be in a separate directory tree with its own `LICENSE.txt` or + `LICENSE` file at the top containing the specific license and restrictions + which apply to that software, or +2) It will contain specific license and restriction terms at the top of every + file. + +============================================================================== +Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy): +============================================================================== + +The compiler_rt library is dual licensed under both the University of Illinois +"BSD-Like" license and the MIT license. As a user of this code you may choose +to use it under either license. As a contributor, you agree to allow your code +to be used under both. + +Full text of the relevant licenses is included below. + +============================================================================== + +University of Illinois/NCSA +Open Source License + +Copyright (c) 2009-2019 by the contributors listed in CREDITS.TXT + +All rights reserved. + +Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE +SOFTWARE. + +============================================================================== + +Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/Half.xcodeproj/project.pbxproj b/Half.xcodeproj/project.pbxproj index 3d0ef8f..9a355b4 100644 --- a/Half.xcodeproj/project.pbxproj +++ b/Half.xcodeproj/project.pbxproj @@ -91,6 +91,8 @@ /* Begin PBXFileReference section */ DD6F08D124008A7400749359 /* codecov.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = codecov.yml; sourceTree = ""; }; + DDB1DF3F240A25D900C20FED /* fp_extend.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fp_extend.cpp; sourceTree = ""; }; + DDB1DF40240A25D900C20FED /* fp_trunc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = fp_trunc.cpp; sourceTree = ""; }; DDB8120223F587890079FEB5 /* CHalfTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CHalfTests.swift; sourceTree = ""; }; DDFEEC3323EF13900096015C /* Half.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Half.framework; sourceTree = BUILT_PRODUCTS_DIR; }; DDFEEC3723EF13900096015C /* Half-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "Half-Info.plist"; path = "Plists/Half-Info.plist"; sourceTree = ""; }; @@ -292,6 +294,8 @@ isa = PBXGroup; children = ( DDFEED8223F345690096015C /* half.c */, + DDB1DF3F240A25D900C20FED /* fp_extend.cpp */, + DDB1DF40240A25D900C20FED /* fp_trunc.cpp */, ); path = src; sourceTree = ""; diff --git a/README.md b/README.md index 97f6c90..5094011 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ Half [![CocoaPods Compatible](https://img.shields.io/cocoapods/v/Half.svg)](https://cocoapods.org/pods/Half) [![Carthage Compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage) [![Platform](https://img.shields.io/cocoapods/p/Half.svg)](https://cocoapods.org/pods/Half) +![Linux](https://img.shields.io/badge/platform-linux-lightgrey) [![Build](https://travis-ci.com/SomeRandomiOSDev/Half.svg?branch=master)](https://travis-ci.com/SomeRandomiOSDev/Half) [![Code Coverage](https://codecov.io/gh/SomeRandomiOSDev/Half/branch/master/graph/badge.svg)](https://codecov.io/gh/SomeRandomiOSDev/Half) [![Codacy](https://api.codacy.com/project/badge/Grade/8ad52c117e4a46d9aa4699d22fc0bf49)](https://app.codacy.com/app/SomeRandomiOSDev/Half?utm_source=github.com&utm_medium=referral&utm_content=SomeRandomiOSDev/Half&utm_campaign=Badge_Grade_Dashboard) diff --git a/Sources/CHalf/src/fp_extend.cpp b/Sources/CHalf/src/fp_extend.cpp new file mode 100644 index 0000000..2a105ac --- /dev/null +++ b/Sources/CHalf/src/fp_extend.cpp @@ -0,0 +1,107 @@ +#if defined(__linux__) +#include +#include + +typedef uint16_t src_t; +typedef uint16_t src_rep_t; +#define SRC_REP_C UINT16_C +static const int srcSigBits = 10; +#define src_rep_t_clz __builtin_clz + +typedef float dst_t; +typedef uint32_t dst_rep_t; +#define DST_REP_C UINT32_C +static const int dstSigBits = 23; + +// End of specialization parameters. Two helper routines for conversion to and +// from the representation of floating-point data as integer values follow. + +static __inline src_rep_t srcToRep(src_t x) { + const union { src_t f; src_rep_t i; } rep = {.f = x}; + return rep.i; +} + +static __inline dst_t dstFromRep(dst_rep_t x) { + const union { dst_t f; dst_rep_t i; } rep = {.i = x}; + return rep.f; +} +// End helper routines. Conversion implementation follows. + +static __inline dst_t __extendXfYf2__(src_t a) { + // Various constants whose values follow from the type parameters. + // Any reasonable optimizer will fold and propagate all of these. + const int srcBits = sizeof(src_t)*CHAR_BIT; + const int srcExpBits = srcBits - srcSigBits - 1; + const int srcInfExp = (1 << srcExpBits) - 1; + const int srcExpBias = srcInfExp >> 1; + + const src_rep_t srcMinNormal = SRC_REP_C(1) << srcSigBits; + const src_rep_t srcInfinity = (src_rep_t)srcInfExp << srcSigBits; + const src_rep_t srcSignMask = SRC_REP_C(1) << (srcSigBits + srcExpBits); + const src_rep_t srcAbsMask = srcSignMask - 1; + const src_rep_t srcQNaN = SRC_REP_C(1) << (srcSigBits - 1); + const src_rep_t srcNaNCode = srcQNaN - 1; + + const int dstBits = sizeof(dst_t)*CHAR_BIT; + const int dstExpBits = dstBits - dstSigBits - 1; + const int dstInfExp = (1 << dstExpBits) - 1; + const int dstExpBias = dstInfExp >> 1; + + const dst_rep_t dstMinNormal = DST_REP_C(1) << dstSigBits; + + // Break a into a sign and representation of the absolute value + const src_rep_t aRep = srcToRep(a); + const src_rep_t aAbs = aRep & srcAbsMask; + const src_rep_t sign = aRep & srcSignMask; + dst_rep_t absResult; + + // If sizeof(src_rep_t) < sizeof(int), the subtraction result is promoted + // to (signed) int. To avoid that, explicitly cast to src_rep_t. + if ((src_rep_t)(aAbs - srcMinNormal) < srcInfinity - srcMinNormal) { + // a is a normal number. + // Extend to the destination type by shifting the significand and + // exponent into the proper position and rebiasing the exponent. + absResult = (dst_rep_t)aAbs << (dstSigBits - srcSigBits); + absResult += (dst_rep_t)(dstExpBias - srcExpBias) << dstSigBits; + } + + else if (aAbs >= srcInfinity) { + // a is NaN or infinity. + // Conjure the result by beginning with infinity, then setting the qNaN + // bit (if needed) and right-aligning the rest of the trailing NaN + // payload field. + absResult = (dst_rep_t)dstInfExp << dstSigBits; + absResult |= (dst_rep_t)(aAbs & srcQNaN) << (dstSigBits - srcSigBits); + absResult |= (dst_rep_t)(aAbs & srcNaNCode) << (dstSigBits - srcSigBits); + } + + else if (aAbs) { + // a is denormal. + // renormalize the significand and clear the leading bit, then insert + // the correct adjusted exponent in the destination type. + const int scale = src_rep_t_clz(aAbs) - src_rep_t_clz(srcMinNormal); + absResult = (dst_rep_t)aAbs << (dstSigBits - srcSigBits + scale); + absResult ^= dstMinNormal; + const int resultExponent = dstExpBias - srcExpBias - scale + 1; + absResult |= (dst_rep_t)resultExponent << dstSigBits; + } + + else { + // a is zero. + absResult = 0; + } + + // Apply the signbit to (dst_t)abs(a). + const dst_rep_t result = absResult | (dst_rep_t)sign << (dstBits - srcBits); + return dstFromRep(result); +} +// Use a forwarding definition and noinline to implement a poor man's alias, +// as there isn't a good cross-platform way of defining one. +__attribute__((noinline)) float __extendhfsf2(uint16_t a) { + return __extendXfYf2__(a); +} + +extern "C" float __gnu_h2f_ieee(uint16_t a) { + return __extendhfsf2(a); +} +#endif // #if defined(__linux__) diff --git a/Sources/CHalf/src/fp_trunc.cpp b/Sources/CHalf/src/fp_trunc.cpp new file mode 100644 index 0000000..132b7b5 --- /dev/null +++ b/Sources/CHalf/src/fp_trunc.cpp @@ -0,0 +1,135 @@ +#if defined(__linux__) +#include +#include + +typedef float src_t; +typedef uint32_t src_rep_t; +#define SRC_REP_C UINT32_C +static const int srcSigBits = 23; + +typedef uint16_t dst_t; +typedef uint16_t dst_rep_t; +#define DST_REP_C UINT16_C +static const int dstSigBits = 10; + +// End of specialization parameters. Two helper routines for conversion to and +// from the representation of floating-point data as integer values follow. + +static __inline src_rep_t srcToRep(src_t x) { + const union { src_t f; src_rep_t i; } rep = {.f = x}; + return rep.i; +} + +static __inline dst_t dstFromRep(dst_rep_t x) { + const union { dst_t f; dst_rep_t i; } rep = {.i = x}; + return rep.f; +} + +static __inline dst_t __truncXfYf2__(src_t a) { + // Various constants whose values follow from the type parameters. + // Any reasonable optimizer will fold and propagate all of these. + const int srcBits = sizeof(src_t)*CHAR_BIT; + const int srcExpBits = srcBits - srcSigBits - 1; + const int srcInfExp = (1 << srcExpBits) - 1; + const int srcExpBias = srcInfExp >> 1; + + const src_rep_t srcMinNormal = SRC_REP_C(1) << srcSigBits; + const src_rep_t srcSignificandMask = srcMinNormal - 1; + const src_rep_t srcInfinity = (src_rep_t)srcInfExp << srcSigBits; + const src_rep_t srcSignMask = SRC_REP_C(1) << (srcSigBits + srcExpBits); + const src_rep_t srcAbsMask = srcSignMask - 1; + const src_rep_t roundMask = (SRC_REP_C(1) << (srcSigBits - dstSigBits)) - 1; + const src_rep_t halfway = SRC_REP_C(1) << (srcSigBits - dstSigBits - 1); + const src_rep_t srcQNaN = SRC_REP_C(1) << (srcSigBits - 1); + const src_rep_t srcNaNCode = srcQNaN - 1; + + const int dstBits = sizeof(dst_t)*CHAR_BIT; + const int dstExpBits = dstBits - dstSigBits - 1; + const int dstInfExp = (1 << dstExpBits) - 1; + const int dstExpBias = dstInfExp >> 1; + const int underflowExponent = srcExpBias + 1 - dstExpBias; + const int overflowExponent = srcExpBias + dstInfExp - dstExpBias; + const src_rep_t underflow = (src_rep_t)underflowExponent << srcSigBits; + const src_rep_t overflow = (src_rep_t)overflowExponent << srcSigBits; + + const dst_rep_t dstQNaN = DST_REP_C(1) << (dstSigBits - 1); + const dst_rep_t dstNaNCode = dstQNaN - 1; + + // Break a into a sign and representation of the absolute value + const src_rep_t aRep = srcToRep(a); + const src_rep_t aAbs = aRep & srcAbsMask; + const src_rep_t sign = aRep & srcSignMask; + dst_rep_t absResult; + + if (aAbs - underflow < aAbs - overflow) { + // The exponent of a is within the range of normal numbers in the + // destination format. We can convert by simply right-shifting with + // rounding and adjusting the exponent. + absResult = aAbs >> (srcSigBits - dstSigBits); + absResult -= (dst_rep_t)(srcExpBias - dstExpBias) << dstSigBits; + + const src_rep_t roundBits = aAbs & roundMask; + // Round to nearest + if (roundBits > halfway) + absResult++; + // Ties to even + else if (roundBits == halfway) + absResult += absResult & 1; + } + else if (aAbs > srcInfinity) { + // a is NaN. + // Conjure the result by beginning with infinity, setting the qNaN + // bit and inserting the (truncated) trailing NaN field. + absResult = (dst_rep_t)dstInfExp << dstSigBits; + absResult |= dstQNaN; + absResult |= ((aAbs & srcNaNCode) >> (srcSigBits - dstSigBits)) & dstNaNCode; + } + else if (aAbs >= overflow) { + // a overflows to infinity. + absResult = (dst_rep_t)dstInfExp << dstSigBits; + } + else { + // a underflows on conversion to the destination type or is an exact + // zero. The result may be a denormal or zero. Extract the exponent + // to get the shift amount for the denormalization. + const int aExp = aAbs >> srcSigBits; + const int shift = srcExpBias - dstExpBias - aExp + 1; + + const src_rep_t significand = (aRep & srcSignificandMask) | srcMinNormal; + + // Right shift by the denormalization amount with sticky. + if (shift > srcSigBits) { + absResult = 0; + } else { + const bool sticky = significand << (srcBits - shift); + src_rep_t denormalizedSignificand = significand >> shift | sticky; + absResult = denormalizedSignificand >> (srcSigBits - dstSigBits); + const src_rep_t roundBits = denormalizedSignificand & roundMask; + // Round to nearest + if (roundBits > halfway) + absResult++; + // Ties to even + else if (roundBits == halfway) + absResult += absResult & 1; + } + } + + // Apply the signbit to (dst_t)abs(a). + const dst_rep_t result = absResult | sign >> (srcBits - dstBits); + return dstFromRep(result); +} + +// Use a forwarding definition and noinline to implement a poor man's alias, +// as there isn't a good cross-platform way of defining one. +__attribute__((noinline)) uint16_t __truncsfhf2(float a) { + return __truncXfYf2__(a); +} + +extern "C" uint16_t __truncdfhf2(double a) { + return __truncsfhf2((double)a); +} + +extern "C" uint16_t __gnu_f2h_ieee(float a) { + return __truncsfhf2(a); +} +#endif // #if defined(__linux__) diff --git a/Tests/CHalfTests/XCTestManifests.swift b/Tests/CHalfTests/XCTestManifests.swift new file mode 100644 index 0000000..7cc1be4 --- /dev/null +++ b/Tests/CHalfTests/XCTestManifests.swift @@ -0,0 +1,23 @@ +#if !canImport(ObjectiveC) +import XCTest + +extension TestCHalf { + // DO NOT MODIFY: This is autogenerated, use: + // `swift test --generate-linuxmain` + // to regenerate. + static let __allTests__TestCHalf = [ + ("testArithmeticFunctions", testArithmeticFunctions), + ("testConstructorFunctions", testConstructorFunctions), + ("testConvertingToFromRawValue", testConvertingToFromRawValue), + ("testConvertToFromPrimitiveValues", testConvertToFromPrimitiveValues), + ("testLogicFunctions", testLogicFunctions), + ("testMiscellaneousFunctions", testMiscellaneousFunctions), + ] +} + +public func __allTests() -> [XCTestCaseEntry] { + return [ + testCase(TestCHalf.__allTests__TestCHalf), + ] +} +#endif diff --git a/Tests/HalfTests/XCTestManifests.swift b/Tests/HalfTests/XCTestManifests.swift new file mode 100644 index 0000000..43693f6 --- /dev/null +++ b/Tests/HalfTests/XCTestManifests.swift @@ -0,0 +1,65 @@ +#if !canImport(ObjectiveC) +import XCTest + +extension HalfCodingTests { + // DO NOT MODIFY: This is autogenerated, use: + // `swift test --generate-linuxmain` + // to regenerate. + static let __allTests__HalfCodingTests = [ + ("testEncodingDecoding", testEncodingDecoding), + ("testThrowingCases", testThrowingCases), + ] +} + +extension HalfTests { + // DO NOT MODIFY: This is autogenerated, use: + // `swift test --generate-linuxmain` + // to regenerate. + static let __allTests__HalfTests = [ + ("testAddProduct", testAddProduct), + ("testBasicComparisons", testBasicComparisons), + ("testBasicMathematicalFunctions", testBasicMathematicalFunctions), + ("testBasicValues", testBasicValues), + ("testBinade", testBinade), + ("testBitPattern", testBitPattern), + ("testCanonical", testCanonical), + ("testConvertFromIntTypes", testConvertFromIntTypes), + ("testConvertFromOtherFloatTypes", testConvertFromOtherFloatTypes), + ("testDescription", testDescription), + ("testExponent", testExponent), + ("testHashableProtocolMethods", testHashableProtocolMethods), + ("testLargestNumbers", testLargestNumbers), + ("testManualFloatingPointInitialization", testManualFloatingPointInitialization), + ("testNegativeHalfs", testNegativeHalfs), + ("testNonNumberValues", testNonNumberValues), + ("testOutputStreamable", testOutputStreamable), + ("testPi", testPi), + ("testRemainder", testRemainder), + ("testRounding", testRounding), + ("testSignificand", testSignificand), + ("testSignificandWidth", testSignificandWidth), + ("testSmallestNumbers", testSmallestNumbers), + ("testSquareRoot", testSquareRoot), + ("testStrideableProtocolMethods", testStrideableProtocolMethods), + ("testTruncatingRemainder", testTruncatingRemainder), + ("testULP", testULP), + ] +} + +extension TestFunctions { + // DO NOT MODIFY: This is autogenerated, use: + // `swift test --generate-linuxmain` + // to regenerate. + static let __allTests__TestFunctions = [ + ("testAllFunctions", testAllFunctions), + ] +} + +public func __allTests() -> [XCTestCaseEntry] { + return [ + testCase(HalfCodingTests.__allTests__HalfCodingTests), + testCase(HalfTests.__allTests__HalfTests), + testCase(TestFunctions.__allTests__TestFunctions), + ] +} +#endif diff --git a/Tests/LinuxMain.swift b/Tests/LinuxMain.swift new file mode 100644 index 0000000..e82f934 --- /dev/null +++ b/Tests/LinuxMain.swift @@ -0,0 +1,10 @@ +import XCTest + +import CHalfTests +import HalfTests + +var tests = [XCTestCaseEntry]() +tests += CHalfTests.__allTests() +tests += HalfTests.__allTests() + +XCTMain(tests) From e8c630778c2c7b2db2801f61684f104ff49ee444 Mon Sep 17 00:00:00 2001 From: Joe Newton <> Date: Sat, 29 Feb 2020 01:21:39 -0500 Subject: [PATCH 2/5] Dropped support declarations for unsupported Swift versions --- .github/workflows/swift.yml | 13 ++----------- Half.podspec | 2 +- Package.swift | 2 +- 3 files changed, 4 insertions(+), 13 deletions(-) diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index 457b6ed..493b8ec 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -7,21 +7,12 @@ jobs: strategy: matrix: os: [macOS-latest, ubuntu-latest] - swift: ["5.0"] runs-on: ${{ matrix.os }} - env: - SWIFT_VERSION: ${{ matrix.swift }} - SWIFT_EXEC: .swiftenv/shims/swift steps: - uses: actions/checkout@v2 - - name: Install Swift - run: | - git clone https://github.com/kylef/swiftenv.git ~/.swiftenv - ~/.swiftenv/bin/swiftenv install $SWIFT_VERSION - name: Build run: | - ~/$SWIFT_EXEC --version - ~/$SWIFT_EXEC build -v + swift build -v - name: Test run: | - ~/$SWIFT_EXEC test -v + swift test -v diff --git a/Half.podspec b/Half.podspec index 60972d4..fd7d57f 100644 --- a/Half.podspec +++ b/Half.podspec @@ -19,7 +19,7 @@ Pod::Spec.new do |s| s.source = { :git => "https://github.com/SomeRandomiOSDev/Half.git", :tag => s.version.to_s } s.source_files = 'Sources/**/*.{swift,h,c}' s.frameworks = 'Foundation' - s.swift_versions = ['4.0', '4.2', '5.0'] + s.swift_versions = ['5.0'] s.cocoapods_version = '>= 1.7.3' end diff --git a/Package.swift b/Package.swift index ea2b83c..918366d 100644 --- a/Package.swift +++ b/Package.swift @@ -23,5 +23,5 @@ let package = Package( .testTarget(name: "HalfTests", dependencies: ["Half"]) ], - swiftLanguageVersions: [.version("4"), .version("4.2"), .version("5")] + swiftLanguageVersions: [.version("5")] ) From 0c13569c7ad8f2be2284cc4aeaab89a341ef37a3 Mon Sep 17 00:00:00 2001 From: Joe Newton <> Date: Sat, 29 Feb 2020 01:26:54 -0500 Subject: [PATCH 3/5] Fixed broken Github workflow --- .github/workflows/swift.yml | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index 493b8ec..9c4ffcf 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -7,12 +7,21 @@ jobs: strategy: matrix: os: [macOS-latest, ubuntu-latest] + swift: ["5.1"] runs-on: ${{ matrix.os }} + env: + SWIFT_VERSION: ${{ matrix.swift }} + SWIFT_EXEC: .swiftenv/shims/swift steps: - uses: actions/checkout@v2 + - name: Install Swift + run: | + git clone https://github.com/kylef/swiftenv.git ~/.swiftenv + ~/.swiftenv/bin/swiftenv install $SWIFT_VERSION - name: Build run: | - swift build -v + ~/$SWIFT_EXEC --version + ~/$SWIFT_EXEC build -v - name: Test run: | - swift test -v + ~/$SWIFT_EXEC test -v From 9d3cd82d2ee9036e4b2156405427ee1a0ab6fb4b Mon Sep 17 00:00:00 2001 From: Joe Newton <47185726+SomeRandomiOSDev@users.noreply.github.com> Date: Sat, 29 Feb 2020 01:28:52 -0500 Subject: [PATCH 4/5] Update swift.yml --- .github/workflows/swift.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index 9c4ffcf..a083401 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -17,7 +17,7 @@ jobs: - name: Install Swift run: | git clone https://github.com/kylef/swiftenv.git ~/.swiftenv - ~/.swiftenv/bin/swiftenv install $SWIFT_VERSION + ~/.swiftenv/bin/swiftenv install $SWIFT_VERSION || true - name: Build run: | ~/$SWIFT_EXEC --version From 58e55997a854e66debe4837443a608383b69b6a0 Mon Sep 17 00:00:00 2001 From: Joe Newton <47185726+SomeRandomiOSDev@users.noreply.github.com> Date: Sat, 29 Feb 2020 01:36:58 -0500 Subject: [PATCH 5/5] Update swift.yml --- .github/workflows/swift.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/swift.yml b/.github/workflows/swift.yml index a083401..01ee3ed 100644 --- a/.github/workflows/swift.yml +++ b/.github/workflows/swift.yml @@ -17,7 +17,8 @@ jobs: - name: Install Swift run: | git clone https://github.com/kylef/swiftenv.git ~/.swiftenv - ~/.swiftenv/bin/swiftenv install $SWIFT_VERSION || true + ~/.swiftenv/bin/swiftenv install $SWIFT_VERSION --skip-existing + ~/.swiftenv/bin/swiftenv rehash - name: Build run: | ~/$SWIFT_EXEC --version