From 5f87bfcf8f4c562ebb42bacb9b75b2ceb05b431f Mon Sep 17 00:00:00 2001 From: Joe Newton <> Date: Sat, 29 Feb 2020 00:34:25 -0500 Subject: [PATCH 1/7] Improved code coverage and did slight restructuring of the project/sources --- Half.xcodeproj/project.pbxproj | 50 ++++++---- Package.swift | 4 +- {Info => Plists}/Half-Info.plist | 0 {Info => Plists}/HalfTests-Info.plist | 0 README.md | 3 +- Sources/CHalf/include/half.h | 130 +++++++++++--------------- Sources/CHalf/src/half.c | 56 +++++++++++ Sources/Half/Half.swift | 11 ++- Tests/CHalfTests/CHalfTests.swift | 129 +++++++++++++++++++++++++ Tests/HalfTests/HalfTests.swift | 13 ++- 10 files changed, 299 insertions(+), 97 deletions(-) rename {Info => Plists}/Half-Info.plist (100%) rename {Info => Plists}/HalfTests-Info.plist (100%) create mode 100644 Tests/CHalfTests/CHalfTests.swift diff --git a/Half.xcodeproj/project.pbxproj b/Half.xcodeproj/project.pbxproj index 896c2ec..3d0ef8f 100644 --- a/Half.xcodeproj/project.pbxproj +++ b/Half.xcodeproj/project.pbxproj @@ -25,6 +25,9 @@ DD94FBF923F3C5BB0041D4EC /* half.h in Headers */ = {isa = PBXBuildFile; fileRef = DDFEEC8423F0B6FF0096015C /* half.h */; settings = {ATTRIBUTES = (Public, ); }; }; DD94FBFA23F3C5BC0041D4EC /* half.h in Headers */ = {isa = PBXBuildFile; fileRef = DDFEEC8423F0B6FF0096015C /* half.h */; settings = {ATTRIBUTES = (Public, ); }; }; DD94FBFB23F3C5BD0041D4EC /* half.h in Headers */ = {isa = PBXBuildFile; fileRef = DDFEEC8423F0B6FF0096015C /* half.h */; settings = {ATTRIBUTES = (Public, ); }; }; + DDB8120323F587890079FEB5 /* CHalfTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB8120223F587890079FEB5 /* CHalfTests.swift */; }; + DDB8120423F587890079FEB5 /* CHalfTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB8120223F587890079FEB5 /* CHalfTests.swift */; }; + DDB8120523F587890079FEB5 /* CHalfTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDB8120223F587890079FEB5 /* CHalfTests.swift */; }; DDFEEC3D23EF13910096015C /* Half.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDFEEC3323EF13900096015C /* Half.framework */; }; DDFEEC4223EF13910096015C /* HalfTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = DDFEEC4123EF13910096015C /* HalfTests.swift */; }; DDFEECC723F2001A0096015C /* Half.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = DDFEECBE23F2001A0096015C /* Half.framework */; }; @@ -88,11 +91,12 @@ /* Begin PBXFileReference section */ DD6F08D124008A7400749359 /* codecov.yml */ = {isa = PBXFileReference; lastKnownFileType = text.yaml; path = codecov.yml; 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 = "Info/Half-Info.plist"; sourceTree = ""; }; + DDFEEC3723EF13900096015C /* Half-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "Half-Info.plist"; path = "Plists/Half-Info.plist"; sourceTree = ""; }; DDFEEC3C23EF13910096015C /* HalfTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HalfTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; DDFEEC4123EF13910096015C /* HalfTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HalfTests.swift; sourceTree = ""; }; - DDFEEC4323EF13910096015C /* HalfTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "HalfTests-Info.plist"; path = "../../Info/HalfTests-Info.plist"; sourceTree = ""; }; + DDFEEC4323EF13910096015C /* HalfTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "HalfTests-Info.plist"; path = "Plists/HalfTests-Info.plist"; sourceTree = ""; }; DDFEEC8423F0B6FF0096015C /* half.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = half.h; sourceTree = ""; }; DDFEECAB23F1BA550096015C /* Half.podspec */ = {isa = PBXFileReference; lastKnownFileType = text; path = Half.podspec; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.ruby; }; DDFEECAC23F1BA550096015C /* Package.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Package.swift; sourceTree = SOURCE_ROOT; }; @@ -174,11 +178,20 @@ DD94FBF723F3C50E0041D4EC /* Tests */ = { isa = PBXGroup; children = ( + DDB1DF43240A279300C20FED /* CHalfTests */, DDFEEC4023EF13910096015C /* HalfTests */, ); path = Tests; sourceTree = ""; }; + DDB1DF43240A279300C20FED /* CHalfTests */ = { + isa = PBXGroup; + children = ( + DDB8120223F587890079FEB5 /* CHalfTests.swift */, + ); + path = CHalfTests; + sourceTree = ""; + }; DDFEEC2923EF13900096015C = { isa = PBXGroup; children = ( @@ -217,7 +230,6 @@ DDFEEC4123EF13910096015C /* HalfTests.swift */, DDFEED4D23F26F170096015C /* Half+CodingTests.swift */, DDFEED5123F2737B0096015C /* FunctionsTests.swift */, - DDFEEC4323EF13910096015C /* HalfTests-Info.plist */, ); path = HalfTests; sourceTree = ""; @@ -243,6 +255,7 @@ DDFEECB023F1BA6E0096015C /* ATTRIBUTIONS */, DDFEECB123F1BA730096015C /* LICENSE */, DDFEEC3723EF13900096015C /* Half-Info.plist */, + DDFEEC4323EF13910096015C /* HalfTests-Info.plist */, ); name = "Supporting Files"; sourceTree = ""; @@ -603,6 +616,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + DDB8120323F587890079FEB5 /* CHalfTests.swift in Sources */, DDFEED4E23F26F170096015C /* Half+CodingTests.swift in Sources */, DDFEED5223F2737B0096015C /* FunctionsTests.swift in Sources */, DDFEEC4223EF13910096015C /* HalfTests.swift in Sources */, @@ -624,6 +638,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + DDB8120423F587890079FEB5 /* CHalfTests.swift in Sources */, DDFEED4F23F26F170096015C /* Half+CodingTests.swift in Sources */, DDFEED5323F2737B0096015C /* FunctionsTests.swift in Sources */, DDFEED0A23F200FE0096015C /* HalfTests.swift in Sources */, @@ -645,6 +660,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + DDB8120523F587890079FEB5 /* CHalfTests.swift in Sources */, DDFEED5023F26F170096015C /* Half+CodingTests.swift in Sources */, DDFEED5423F2737B0096015C /* FunctionsTests.swift in Sources */, DDFEED0B23F200FF0096015C /* HalfTests.swift in Sources */, @@ -827,7 +843,7 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Info/Half-Info.plist"; + INFOPLIST_FILE = "Plists/Half-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -852,7 +868,7 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Info/Half-Info.plist"; + INFOPLIST_FILE = "Plists/Half-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -873,7 +889,7 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - INFOPLIST_FILE = "Info/HalfTests-Info.plist"; + INFOPLIST_FILE = "Plists/HalfTests-Info.plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -892,7 +908,7 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CLANG_ENABLE_MODULES = YES; CODE_SIGN_STYLE = Automatic; - INFOPLIST_FILE = "Info/HalfTests-Info.plist"; + INFOPLIST_FILE = "Plists/HalfTests-Info.plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -930,7 +946,7 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Info/Half-Info.plist"; + INFOPLIST_FILE = "Plists/Half-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -956,7 +972,7 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Info/Half-Info.plist"; + INFOPLIST_FILE = "Plists/Half-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -977,7 +993,7 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = "Info/HalfTests-Info.plist"; + INFOPLIST_FILE = "Plists/HalfTests-Info.plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", @@ -995,7 +1011,7 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; - INFOPLIST_FILE = "Info/HalfTests-Info.plist"; + INFOPLIST_FILE = "Plists/HalfTests-Info.plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/../Frameworks", @@ -1016,7 +1032,7 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Info/Half-Info.plist"; + INFOPLIST_FILE = "Plists/Half-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -1042,7 +1058,7 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Info/Half-Info.plist"; + INFOPLIST_FILE = "Plists/Half-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -1063,7 +1079,7 @@ buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; - INFOPLIST_FILE = "Info/HalfTests-Info.plist"; + INFOPLIST_FILE = "Plists/HalfTests-Info.plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1081,7 +1097,7 @@ buildSettings = { ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; CODE_SIGN_STYLE = Automatic; - INFOPLIST_FILE = "Info/HalfTests-Info.plist"; + INFOPLIST_FILE = "Plists/HalfTests-Info.plist"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -1104,7 +1120,7 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Info/Half-Info.plist"; + INFOPLIST_FILE = "Plists/Half-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", @@ -1131,7 +1147,7 @@ DYLIB_COMPATIBILITY_VERSION = 1; DYLIB_CURRENT_VERSION = 1; DYLIB_INSTALL_NAME_BASE = "@rpath"; - INFOPLIST_FILE = "Info/Half-Info.plist"; + INFOPLIST_FILE = "Plists/Half-Info.plist"; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", diff --git a/Package.swift b/Package.swift index 12aac3e..ea2b83c 100644 --- a/Package.swift +++ b/Package.swift @@ -12,11 +12,13 @@ let package = Package( ], products: [ - .library(name: "Half", type: .dynamic, targets: ["Half"]) + .library(name: "Half", targets: ["Half", "CHalf"]) ], targets: [ .target(name: "CHalf"), + .testTarget(name: "CHalfTests", dependencies: ["CHalf"]), + .target(name: "Half", dependencies: ["CHalf"]), .testTarget(name: "HalfTests", dependencies: ["Half"]) ], diff --git a/Info/Half-Info.plist b/Plists/Half-Info.plist similarity index 100% rename from Info/Half-Info.plist rename to Plists/Half-Info.plist diff --git a/Info/HalfTests-Info.plist b/Plists/HalfTests-Info.plist similarity index 100% rename from Info/HalfTests-Info.plist rename to Plists/HalfTests-Info.plist diff --git a/README.md b/README.md index 948280b..97f6c90 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,7 @@ Half [![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) +![Swift](https://github.com/SomeRandomiOSDev/HalfTest/workflows/Swift/badge.svg) **Half** is a lightweight framework containing a Swift implementation for a half-precision floating point type for iOS, macOS, tvOS, and watchOS. @@ -70,7 +71,7 @@ Joseph Newton, somerandomiosdev@gmail.com Credits -------- -**Half** is based heavily on the `Float`, `Double`, and `Float80` structures provided by Swift. See `ATTRIBUTIONS` for more details. +**Half** is based heavily on the implementations of the `Float`, `Double`, and `Float80` structures provided by Swift. See `ATTRIBUTIONS` for more details. License -------- diff --git a/Sources/CHalf/include/half.h b/Sources/CHalf/include/half.h index c8b4638..e5c34a5 100644 --- a/Sources/CHalf/include/half.h +++ b/Sources/CHalf/include/half.h @@ -10,13 +10,14 @@ #include #include -#include -#if __has_attribute(__always_inline__) -# define HALF_INLINE __attribute__((__always_inline__)) -#else -# define HALF_INLINE inline -#endif +#if !defined(EXTERN_C) +# if defined(__cplusplus) +# define EXTERN_C extern "C" +# else +# define EXTERN_C extern +# endif // #if defined(__cplusplus) +#endif // #if !defined(EXTERN_C) #if __has_attribute(__const__) # define HALF_CONST __attribute__((__const__)) @@ -24,13 +25,7 @@ # define HALF_CONST /* nothing */ #endif -#if __has_attribute(__nodebug__) -# define HALF_NODEBUG __attribute__((__nodebug__)) -#else -# define HALF_NODEBUG /* nothing */ -#endif - -#define HALF_FUNC HALF_INLINE HALF_CONST HALF_NODEBUG +#define HALF_FUNC HALF_CONST #define HALF_OFUNC HALF_FUNC __attribute__((__overloadable__)) typedef union { @@ -38,65 +33,54 @@ typedef union { __fp16 _fp; } __attribute__((packed)) half_t; -#define HALF_FROM_RAW(x) (half_t){ ._bits = (x) } -#define RAW_FROM_HALF(x) x._bits -#define HALF_FROM_FP16(x) (half_t){ ._fp = (x) } -#define FP16_FROM_HALF(x) x._fp - -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-function" - -static HALF_FUNC half_t _half_zero(void) { return HALF_FROM_FP16(0.0); } -static HALF_FUNC half_t _half_epsilon(void) { return HALF_FROM_FP16(0x1p-10); } -static HALF_FUNC half_t _half_pi(void) { return HALF_FROM_FP16(0x1.92p1); } -static HALF_FUNC half_t _half_nan(void) { return HALF_FROM_RAW(0x7E00); } - -static HALF_FUNC uint16_t _half_to_raw(const half_t val) { return RAW_FROM_HALF(val); } -static HALF_FUNC half_t _half_from_raw(const uint16_t val) { return HALF_FROM_RAW(val); } - -static HALF_OFUNC half_t _half_from(const double val) { const __fp16 fpval = (__fp16)val; return HALF_FROM_FP16(fpval); } -static HALF_OFUNC half_t _half_from(const float val) { const __fp16 fpval = (__fp16)val; return HALF_FROM_FP16(fpval); } -static HALF_OFUNC half_t _half_from(const long long val) { const __fp16 fpval = (__fp16)val; return HALF_FROM_FP16(fpval); } -static HALF_OFUNC half_t _half_from(const long val) { const __fp16 fpval = (__fp16)val; return HALF_FROM_FP16(fpval); } -static HALF_OFUNC half_t _half_from(const int val) { const __fp16 fpval = (__fp16)val; return HALF_FROM_FP16(fpval); } -static HALF_OFUNC half_t _half_from(const short val) { const __fp16 fpval = (__fp16)val; return HALF_FROM_FP16(fpval); } -static HALF_OFUNC half_t _half_from(const char val) { const __fp16 fpval = (__fp16)val; return HALF_FROM_FP16(fpval); } -static HALF_OFUNC half_t _half_from(const unsigned long long val) { const __fp16 fpval = (__fp16)val; return HALF_FROM_FP16(fpval); } -static HALF_OFUNC half_t _half_from(const unsigned long val) { const __fp16 fpval = (__fp16)val; return HALF_FROM_FP16(fpval); } -static HALF_OFUNC half_t _half_from(const unsigned int val) { const __fp16 fpval = (__fp16)val; return HALF_FROM_FP16(fpval); } -static HALF_OFUNC half_t _half_from(const unsigned short val) { const __fp16 fpval = (__fp16)val; return HALF_FROM_FP16(fpval); } -static HALF_OFUNC half_t _half_from(const unsigned char val) { const __fp16 fpval = (__fp16)val; return HALF_FROM_FP16(fpval); } - -static HALF_FUNC double _half_to_double(const half_t val) { return (double)FP16_FROM_HALF(val); } -static HALF_FUNC float _half_to_float(const half_t val) { return (float)FP16_FROM_HALF(val); } -static HALF_FUNC long long _half_to_longlong(const half_t val) { return (long long)FP16_FROM_HALF(val); } -static HALF_FUNC long _half_to_long(const half_t val) { return (long)FP16_FROM_HALF(val); } -static HALF_FUNC int _half_to_int(const half_t val) { return (int)FP16_FROM_HALF(val); } -static HALF_FUNC short _half_to_short(const half_t val) { return (short)FP16_FROM_HALF(val); } -static HALF_FUNC char _half_to_char(const half_t val) { return (char)FP16_FROM_HALF(val); } -static HALF_FUNC unsigned long long _half_to_ulonglong(const half_t val) { return (unsigned long long)FP16_FROM_HALF(val); } -static HALF_FUNC unsigned long _half_to_ulong(const half_t val) { return (unsigned long)FP16_FROM_HALF(val); } -static HALF_FUNC unsigned int _half_to_uint(const half_t val) { return (unsigned int)FP16_FROM_HALF(val); } -static HALF_FUNC unsigned short _half_to_ushort(const half_t val) { return (unsigned short)FP16_FROM_HALF(val); } -static HALF_FUNC unsigned char _half_to_uchar(const half_t val) { return (unsigned char)FP16_FROM_HALF(val); } - -static HALF_FUNC half_t _half_add(const half_t lhs, const half_t rhs) { return HALF_FROM_FP16(FP16_FROM_HALF(lhs) + FP16_FROM_HALF(rhs)); } -static HALF_FUNC half_t _half_sub(const half_t lhs, const half_t rhs) { return HALF_FROM_FP16(FP16_FROM_HALF(lhs) - FP16_FROM_HALF(rhs)); } -static HALF_FUNC half_t _half_mul(const half_t lhs, const half_t rhs) { return HALF_FROM_FP16(FP16_FROM_HALF(lhs) * FP16_FROM_HALF(rhs)); } -static HALF_FUNC half_t _half_div(const half_t lhs, const half_t rhs) { return HALF_FROM_FP16(FP16_FROM_HALF(lhs) / FP16_FROM_HALF(rhs)); } - -static HALF_FUNC half_t _half_neg(const half_t val) { return HALF_FROM_FP16(0.0 - FP16_FROM_HALF(val)); } -static HALF_FUNC half_t _half_abs(const half_t val) { return HALF_FROM_RAW(RAW_FROM_HALF(val) & 0x7FFF); } // clear sign bit -static HALF_FUNC half_t _half_sqrt(const half_t val) { return _half_from(sqrt((float)FP16_FROM_HALF(val))); } - -static HALF_FUNC half_t _half_fma(const half_t val, const half_t lhs, const half_t rhs) { return HALF_FROM_FP16(FP16_FROM_HALF(val) + (FP16_FROM_HALF(lhs) * FP16_FROM_HALF(rhs))); } - -static HALF_FUNC bool _half_equal(const half_t lhs, const half_t rhs) { return FP16_FROM_HALF(lhs) == FP16_FROM_HALF(rhs); } -static HALF_FUNC bool _half_lt(const half_t lhs, const half_t rhs) { return FP16_FROM_HALF(lhs) < FP16_FROM_HALF(rhs); } -static HALF_FUNC bool _half_gt(const half_t lhs, const half_t rhs) { return FP16_FROM_HALF(lhs) > FP16_FROM_HALF(rhs); } -static HALF_FUNC bool _half_lte(const half_t lhs, const half_t rhs) { return FP16_FROM_HALF(lhs) <= FP16_FROM_HALF(rhs); } -static HALF_FUNC bool _half_gte(const half_t lhs, const half_t rhs) { return FP16_FROM_HALF(lhs) >= FP16_FROM_HALF(rhs); } - -#pragma clang diagnostic pop +EXTERN_C HALF_FUNC half_t _half_zero(void); +EXTERN_C HALF_FUNC half_t _half_epsilon(void); +EXTERN_C HALF_FUNC half_t _half_pi(void); +EXTERN_C HALF_FUNC half_t _half_nan(void); + +EXTERN_C HALF_FUNC uint16_t _half_to_raw(const half_t); +EXTERN_C HALF_FUNC half_t _half_from_raw(const uint16_t); + +EXTERN_C HALF_OFUNC half_t _half_from(const double); +EXTERN_C HALF_OFUNC half_t _half_from(const float); +EXTERN_C HALF_OFUNC half_t _half_from(const long long); +EXTERN_C HALF_OFUNC half_t _half_from(const long); +EXTERN_C HALF_OFUNC half_t _half_from(const int); +EXTERN_C HALF_OFUNC half_t _half_from(const short); +EXTERN_C HALF_OFUNC half_t _half_from(const char); +EXTERN_C HALF_OFUNC half_t _half_from(const unsigned long long); +EXTERN_C HALF_OFUNC half_t _half_from(const unsigned long); +EXTERN_C HALF_OFUNC half_t _half_from(const unsigned int); +EXTERN_C HALF_OFUNC half_t _half_from(const unsigned short); +EXTERN_C HALF_OFUNC half_t _half_from(const unsigned char); + +EXTERN_C HALF_FUNC double _half_to_double(const half_t); +EXTERN_C HALF_FUNC float _half_to_float(const half_t); +EXTERN_C HALF_FUNC long long _half_to_longlong(const half_t); +EXTERN_C HALF_FUNC long _half_to_long(const half_t); +EXTERN_C HALF_FUNC int _half_to_int(const half_t); +EXTERN_C HALF_FUNC short _half_to_short(const half_t); +EXTERN_C HALF_FUNC char _half_to_char(const half_t); +EXTERN_C HALF_FUNC unsigned long long _half_to_ulonglong(const half_t); +EXTERN_C HALF_FUNC unsigned long _half_to_ulong(const half_t); +EXTERN_C HALF_FUNC unsigned int _half_to_uint(const half_t); +EXTERN_C HALF_FUNC unsigned short _half_to_ushort(const half_t); +EXTERN_C HALF_FUNC unsigned char _half_to_uchar(const half_t); + +EXTERN_C HALF_FUNC half_t _half_add(const half_t, const half_t); +EXTERN_C HALF_FUNC half_t _half_sub(const half_t, const half_t); +EXTERN_C HALF_FUNC half_t _half_mul(const half_t, const half_t); +EXTERN_C HALF_FUNC half_t _half_div(const half_t, const half_t); +EXTERN_C HALF_FUNC half_t _half_fma(const half_t, const half_t, const half_t); + +EXTERN_C HALF_FUNC half_t _half_neg(const half_t); +EXTERN_C HALF_FUNC half_t _half_abs(const half_t); +EXTERN_C HALF_FUNC half_t _half_sqrt(const half_t); + +EXTERN_C HALF_FUNC bool _half_equal(const half_t, const half_t); +EXTERN_C HALF_FUNC bool _half_lt(const half_t, const half_t); +EXTERN_C HALF_FUNC bool _half_gt(const half_t, const half_t); +EXTERN_C HALF_FUNC bool _half_lte(const half_t, const half_t); +EXTERN_C HALF_FUNC bool _half_gte(const half_t, const half_t); #endif /* half_h */ diff --git a/Sources/CHalf/src/half.c b/Sources/CHalf/src/half.c index 2f20069..412bd5e 100644 --- a/Sources/CHalf/src/half.c +++ b/Sources/CHalf/src/half.c @@ -6,3 +6,59 @@ // #include "half.h" +#include + +#define HALF_FROM_RAW(x) (half_t){ ._bits = (x) } +#define RAW_FROM_HALF(x) x._bits +#define HALF_FROM_FP16(x) (half_t){ ._fp = (x) } +#define FP16_FROM_HALF(x) x._fp + +HALF_FUNC half_t _half_zero(void) { return HALF_FROM_FP16(0.0); } +HALF_FUNC half_t _half_epsilon(void) { return HALF_FROM_FP16(0x1p-10); } +HALF_FUNC half_t _half_pi(void) { return HALF_FROM_FP16(0x1.92p1); } +HALF_FUNC half_t _half_nan(void) { return HALF_FROM_RAW(0x7E00); } + +HALF_FUNC uint16_t _half_to_raw(const half_t val) { return RAW_FROM_HALF(val); } +HALF_FUNC half_t _half_from_raw(const uint16_t val) { return HALF_FROM_RAW(val); } + +HALF_OFUNC half_t _half_from(const double val) { const __fp16 fpval = (__fp16)val; return HALF_FROM_FP16(fpval); } +HALF_OFUNC half_t _half_from(const float val) { const __fp16 fpval = (__fp16)val; return HALF_FROM_FP16(fpval); } +HALF_OFUNC half_t _half_from(const long long val) { const __fp16 fpval = (__fp16)val; return HALF_FROM_FP16(fpval); } +HALF_OFUNC half_t _half_from(const long val) { const __fp16 fpval = (__fp16)val; return HALF_FROM_FP16(fpval); } +HALF_OFUNC half_t _half_from(const int val) { const __fp16 fpval = (__fp16)val; return HALF_FROM_FP16(fpval); } +HALF_OFUNC half_t _half_from(const short val) { const __fp16 fpval = (__fp16)val; return HALF_FROM_FP16(fpval); } +HALF_OFUNC half_t _half_from(const char val) { const __fp16 fpval = (__fp16)val; return HALF_FROM_FP16(fpval); } +HALF_OFUNC half_t _half_from(const unsigned long long val) { const __fp16 fpval = (__fp16)val; return HALF_FROM_FP16(fpval); } +HALF_OFUNC half_t _half_from(const unsigned long val) { const __fp16 fpval = (__fp16)val; return HALF_FROM_FP16(fpval); } +HALF_OFUNC half_t _half_from(const unsigned int val) { const __fp16 fpval = (__fp16)val; return HALF_FROM_FP16(fpval); } +HALF_OFUNC half_t _half_from(const unsigned short val) { const __fp16 fpval = (__fp16)val; return HALF_FROM_FP16(fpval); } +HALF_OFUNC half_t _half_from(const unsigned char val) { const __fp16 fpval = (__fp16)val; return HALF_FROM_FP16(fpval); } + +HALF_FUNC double _half_to_double(const half_t val) { return (double)FP16_FROM_HALF(val); } +HALF_FUNC float _half_to_float(const half_t val) { return (float)FP16_FROM_HALF(val); } +HALF_FUNC long long _half_to_longlong(const half_t val) { return (long long)FP16_FROM_HALF(val); } +HALF_FUNC long _half_to_long(const half_t val) { return (long)FP16_FROM_HALF(val); } +HALF_FUNC int _half_to_int(const half_t val) { return (int)FP16_FROM_HALF(val); } +HALF_FUNC short _half_to_short(const half_t val) { return (short)FP16_FROM_HALF(val); } +HALF_FUNC char _half_to_char(const half_t val) { return (char)FP16_FROM_HALF(val); } +HALF_FUNC unsigned long long _half_to_ulonglong(const half_t val) { return (unsigned long long)FP16_FROM_HALF(val); } +HALF_FUNC unsigned long _half_to_ulong(const half_t val) { return (unsigned long)FP16_FROM_HALF(val); } +HALF_FUNC unsigned int _half_to_uint(const half_t val) { return (unsigned int)FP16_FROM_HALF(val); } +HALF_FUNC unsigned short _half_to_ushort(const half_t val) { return (unsigned short)FP16_FROM_HALF(val); } +HALF_FUNC unsigned char _half_to_uchar(const half_t val) { return (unsigned char)FP16_FROM_HALF(val); } + +HALF_FUNC half_t _half_add(const half_t lhs, const half_t rhs) { return HALF_FROM_FP16(FP16_FROM_HALF(lhs) + FP16_FROM_HALF(rhs)); } +HALF_FUNC half_t _half_sub(const half_t lhs, const half_t rhs) { return HALF_FROM_FP16(FP16_FROM_HALF(lhs) - FP16_FROM_HALF(rhs)); } +HALF_FUNC half_t _half_mul(const half_t lhs, const half_t rhs) { return HALF_FROM_FP16(FP16_FROM_HALF(lhs) * FP16_FROM_HALF(rhs)); } +HALF_FUNC half_t _half_div(const half_t lhs, const half_t rhs) { return HALF_FROM_FP16(FP16_FROM_HALF(lhs) / FP16_FROM_HALF(rhs)); } +HALF_FUNC half_t _half_fma(const half_t val, const half_t lhs, const half_t rhs) { return HALF_FROM_FP16(FP16_FROM_HALF(val) + (FP16_FROM_HALF(lhs) * FP16_FROM_HALF(rhs))); } + +HALF_FUNC half_t _half_neg(const half_t val) { return HALF_FROM_FP16(0.0 - FP16_FROM_HALF(val)); } +HALF_FUNC half_t _half_abs(const half_t val) { return HALF_FROM_RAW(RAW_FROM_HALF(val) & 0x7FFF); } // clear sign bit +HALF_FUNC half_t _half_sqrt(const half_t val) { return _half_from(sqrt((float)FP16_FROM_HALF(val))); } + +HALF_FUNC bool _half_equal(const half_t lhs, const half_t rhs) { return FP16_FROM_HALF(lhs) == FP16_FROM_HALF(rhs); } +HALF_FUNC bool _half_lt(const half_t lhs, const half_t rhs) { return FP16_FROM_HALF(lhs) < FP16_FROM_HALF(rhs); } +HALF_FUNC bool _half_gt(const half_t lhs, const half_t rhs) { return FP16_FROM_HALF(lhs) > FP16_FROM_HALF(rhs); } +HALF_FUNC bool _half_lte(const half_t lhs, const half_t rhs) { return FP16_FROM_HALF(lhs) <= FP16_FROM_HALF(rhs); } +HALF_FUNC bool _half_gte(const half_t lhs, const half_t rhs) { return FP16_FROM_HALF(lhs) >= FP16_FROM_HALF(rhs); } diff --git a/Sources/Half/Half.swift b/Sources/Half/Half.swift index b95a06e..60af76e 100644 --- a/Sources/Half/Half.swift +++ b/Sources/Half/Half.swift @@ -249,7 +249,7 @@ extension Half: BinaryFloatingPoint { #if !arch(arm) if isSubnormal { let bitPattern = (self * 0x1p10).bitPattern & (-Half.infinity).bitPattern - return Half(bitPattern: bitPattern) * 0x1p-10 + return Half(bitPattern: bitPattern) * .ulpOfOne } #endif @@ -446,10 +446,10 @@ extension Half: FloatingPoint { guard isFinite else { return .nan } if isNormal { let bitPattern = self.bitPattern & Half.infinity.bitPattern - return Half(bitPattern: bitPattern) * 0x1p-10 + return Half(bitPattern: bitPattern) * .ulpOfOne } - return .leastNormalMagnitude * 0x1p-10 + return .leastNormalMagnitude * .ulpOfOne } // @@ -493,6 +493,11 @@ extension Half: FloatingPoint { return Half(nan: 0, signaling: true) } + @inlinable + public static var ulpOfOne: Half { + return Half(_half_epsilon()) + } + // @_transparent diff --git a/Tests/CHalfTests/CHalfTests.swift b/Tests/CHalfTests/CHalfTests.swift new file mode 100644 index 0000000..6124ab1 --- /dev/null +++ b/Tests/CHalfTests/CHalfTests.swift @@ -0,0 +1,129 @@ +// +// CHalfTests.swift +// Half +// +// Copyright © 2020 SomeRandomiOSDev. All rights reserved. +// + +#if SWIFT_PACKAGE +@testable import CHalf +#endif +@testable import Half +import XCTest + +class TestCHalf: XCTestCase { + + // MARK: Test Methods + + func testConstructorFunctions() { + var half = Half(_half_zero()) + XCTAssertEqual(half, 0.0) + + half = Half(_half_epsilon()) + XCTAssertEqual(half, .ulpOfOne) + + half = Half(_half_pi()) + XCTAssertEqual(half, .pi) + + half = Half(_half_nan()) + XCTAssertTrue(half.isNaN) + XCTAssertFalse(half.isSignalingNaN) + } + + func testConvertingToFromRawValue() { + let raw: UInt16 = 0x749A + let half = Half(_half_from_raw(raw)) + + XCTAssertEqual(Half(bitPattern: raw), half) + XCTAssertEqual(half.bitPattern, raw) + XCTAssertEqual(raw, _half_to_raw(half._value)) + } + + func testConvertToFromPrimitiveValues() { + XCTAssertEqual(Half(_half_from(Double(-1.0))), -1.0) + XCTAssertEqual(Half(_half_from(Float(-1.0))), -1.0) + XCTAssertEqual(Half(_half_from(CLongLong(-2))), -2.0) + XCTAssertEqual(Half(_half_from(CLong(-2))), -2.0) + XCTAssertEqual(Half(_half_from(CInt(-2))), -2.0) + XCTAssertEqual(Half(_half_from(CShort(-2))), -2.0) + XCTAssertEqual(Half(_half_from(CChar(-2))), -2.0) + XCTAssertEqual(Half(_half_from(CUnsignedLongLong(3))), 3.0) + XCTAssertEqual(Half(_half_from(CUnsignedLong(3))), 3.0) + XCTAssertEqual(Half(_half_from(CUnsignedInt(3))), 3.0) + XCTAssertEqual(Half(_half_from(CUnsignedShort(3))), 3.0) + XCTAssertEqual(Half(_half_from(CUnsignedChar(3))), 3.0) + + XCTAssertEqual(_half_to_double(Half(-1.0)._value), -1.0) + XCTAssertEqual(_half_to_float(Half(-1.0)._value), -1.0) + XCTAssertEqual(_half_to_longlong(Half(-2.0)._value), -2) + XCTAssertEqual(_half_to_long(Half(-2.0)._value), -2) + XCTAssertEqual(_half_to_int(Half(-2.0)._value), -2) + XCTAssertEqual(_half_to_short(Half(-2.0)._value), -2) + XCTAssertEqual(_half_to_char(Half(-2.0)._value), -2) + XCTAssertEqual(_half_to_ulonglong(Half(3.0)._value), 3) + XCTAssertEqual(_half_to_ulong(Half(3.0)._value), 3) + XCTAssertEqual(_half_to_uint(Half(3.0)._value), 3) + XCTAssertEqual(_half_to_ushort(Half(3.0)._value), 3) + XCTAssertEqual(_half_to_uchar(Half(3.0)._value), 3) + } + + func testArithmeticFunctions() { + let lhs = Half(10.0) + let rhs = Half(2.5) + let value = Half(6.7) + + XCTAssertEqual(Half(_half_add(lhs._value, rhs._value)), 12.5) + XCTAssertEqual(Half(_half_add(lhs._value, rhs._value)), lhs + rhs) + + XCTAssertEqual(Half(_half_sub(lhs._value, rhs._value)), 7.5) + XCTAssertEqual(Half(_half_sub(lhs._value, rhs._value)), lhs - rhs) + + XCTAssertEqual(Half(_half_mul(lhs._value, rhs._value)), 25.0) + XCTAssertEqual(Half(_half_mul(lhs._value, rhs._value)), lhs * rhs) + + XCTAssertEqual(Half(_half_div(lhs._value, rhs._value)), 4.0) + XCTAssertEqual(Half(_half_div(lhs._value, rhs._value)), lhs / rhs) + + XCTAssertEqual(Half(_half_fma(value._value, lhs._value, rhs._value)), 31.7) + XCTAssertEqual(Half(_half_fma(value._value, lhs._value, rhs._value)), value.addingProduct(lhs, rhs)) + } + + func testMiscellaneousFunctions() { + let half = Half(-9.0) + + XCTAssertEqual(Half(_half_neg(half._value)), 9.0) + XCTAssertEqual(Half(_half_neg(half._value)), -half) + + XCTAssertEqual(Half(_half_abs(half._value)), 9.0) + XCTAssertEqual(Half(_half_abs(half._value)), half.magnitude) + XCTAssertEqual(Half(_half_abs(half._value)), abs(half)) + + XCTAssertEqual(Half(_half_sqrt(abs(half)._value)), 3.0) + XCTAssertEqual(Half(_half_sqrt(abs(half)._value)), abs(half).squareRoot()) + XCTAssertEqual(Half(_half_sqrt(abs(half)._value)), sqrt(abs(half))) + } + + func testLogicFunctions() { + let value1 = Half(4.9) + let value2 = Half(6.7) + let value3 = Half(4.9) + + XCTAssertFalse(_half_equal(value1._value, value2._value)) + XCTAssertTrue(_half_lt(value1._value, value2._value)) + XCTAssertFalse(_half_gt(value1._value, value2._value)) + XCTAssertTrue(_half_lte(value1._value, value2._value)) + XCTAssertFalse(_half_gte(value1._value, value2._value)) + + XCTAssertFalse(_half_equal(value2._value, value3._value)) + XCTAssertFalse(_half_lt(value2._value, value3._value)) + XCTAssertTrue(_half_gt(value2._value, value3._value)) + XCTAssertFalse(_half_lte(value2._value, value3._value)) + XCTAssertTrue(_half_gte(value2._value, value3._value)) + + XCTAssertTrue(_half_equal(value3._value, value1._value)) + XCTAssertFalse(_half_lt(value3._value, value1._value)) + XCTAssertFalse(_half_gt(value3._value, value1._value)) + XCTAssertTrue(_half_lte(value3._value, value1._value)) + XCTAssertTrue(_half_gte(value3._value, value1._value)) + } +} diff --git a/Tests/HalfTests/HalfTests.swift b/Tests/HalfTests/HalfTests.swift index b45061b..8bb0915 100644 --- a/Tests/HalfTests/HalfTests.swift +++ b/Tests/HalfTests/HalfTests.swift @@ -5,10 +5,13 @@ // Copyright © 2020 SomeRandomiOSDev. All rights reserved. // -import CoreGraphics.CGBase @testable import Half import XCTest +#if canImport(CoreGraphics) +import CoreGraphics.CGBase +#endif // #if canImport(CoreGraphics) + class HalfTests: XCTestCase { // MARK: Test Methods @@ -54,22 +57,28 @@ class HalfTests: XCTestCase { func testConvertFromOtherFloatTypes() { let float: Float = 3.14 let double: Double = 3.14 +#if canImport(CoreGraphics) let cgfloat: CGFloat = 3.14 +#endif // #if canImport(CoreGraphics) #if !(os(Windows) || os(Android)) && (arch(i386) || arch(x86_64)) let float80: Float80 = 3.14 #endif let half1 = Half(float) let half2 = Half(double) +#if canImport(CoreGraphics) let half3 = Half(cgfloat) +#endif // #if canImport(CoreGraphics) #if !(os(Windows) || os(Android)) && (arch(i386) || arch(x86_64)) let half4 = Half(float80) #endif XCTAssertEqual(half1, half2) +#if canImport(CoreGraphics) XCTAssertEqual(half2, half3) +#endif // #if canImport(CoreGraphics) #if !(os(Windows) || os(Android)) && (arch(i386) || arch(x86_64)) - XCTAssertEqual(half3, half4) + XCTAssertEqual(half2, half4) #endif binaryFloatingPoint(Double(1.0)) { XCTAssertEqual($0, $1) } From 7360e1111b0d15e72c6ca2ccd4bd47f3b9a3d9f4 Mon Sep 17 00:00:00 2001 From: Joe Newton <> Date: Sat, 29 Feb 2020 01:00:13 -0500 Subject: [PATCH 2/7] 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 3/7] 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 4/7] 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 5/7] 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 6/7] 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 From 1a3288d07c7ef20003464f4a24daf6a4d5c3ba44 Mon Sep 17 00:00:00 2001 From: Joe Newton <> Date: Sat, 29 Feb 2020 01:47:17 -0500 Subject: [PATCH 7/7] Incremented the podspec version --- Half.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Half.podspec b/Half.podspec index fd7d57f..9c4ddec 100644 --- a/Half.podspec +++ b/Half.podspec @@ -1,7 +1,7 @@ Pod::Spec.new do |s| s.name = "Half" - s.version = "1.0.2" + s.version = "1.1.0" s.summary = "Swift Half-Precision Floating Point" s.description = <<-DESC A lightweight framework containing a Swift implementation for a half-precision floating point type for iOS, macOS, tvOS, and watchOS.