Skip to content

Commit

Permalink
Move the floating point code to cborinternal_p.h
Browse files Browse the repository at this point in the history
... and put it behind #ifndef CBOR_NO_FLOATING_POINT.

The functions were not really compiler support, but are internal
functionality of TinyCBOR. This commit also puts both the <math.H> and
<float.h> headers behind an #if, so constrained systems without floating
point support won't enable it.

Signed-off-by: Thiago Macieira <thiago.macieira@intel.com>
  • Loading branch information
thiagomacieira committed Aug 14, 2018
1 parent 8894366 commit bfc40dc
Show file tree
Hide file tree
Showing 5 changed files with 107 additions and 70 deletions.
21 changes: 19 additions & 2 deletions .travis.yml
Expand Up @@ -15,6 +15,7 @@ matrix:
- QMAKESPEC=linux-g++
- EVAL="CC=gcc-7 && CXX=g++-7"
- CFLAGS="-Os"
- LDFLAGS="-Wl,--no-undefined -lm"
- QMAKEFLAGS="-config release"
- os: linux
addons:
Expand All @@ -29,9 +30,23 @@ matrix:
- EVAL="CC=clang-5.0 && CXX=clang++"
- PATH=$PATH:/usr/local/clang/bin
- CFLAGS="-Oz"
- LDFLAGS="-Wl,--no-undefined -lm"
- QMAKEFLAGS="-config release"
- MAKEFLAGS=-s
- TESTARGS=-silent
- os: linux
env:
- QMAKESPEC=linux-gcc-freestanding
- EVAL="CXX=false"
- CFLAGS="-ffreestanding -Os"
- LDFLAGS="-Wl,--no-undefined -lm"
- os: linux
env:
- QMAKESPEC=linux-gcc-no-math
- EVAL="CXX=false && touch src/math.h src/float.h"
- CFLAGS="-ffreestanding -DCBOR_NO_FLOATING_POINT -Os"
- LDFLAGS="-Wl,--no-undefined"
- LDLIBS=""
- os: osx
env:
- QMAKESPEC=macx-clang
Expand All @@ -57,10 +72,12 @@ script:
- make -s clean
- make -k
CFLAGS="$CFLAGS -O0 -g"
- make
LDFLAGS="$LDFLAGS" ${LDLIBS+LDLIBS="$LDLIBS"}
- grep -q freestanding-pass .config || make
QMAKEFLAGS="$QMAKEFLAGS QMAKE_CXX=$CXX"
tests/Makefile
- (cd tests && make check -k
- grep -q freestanding-pass .config ||
(cd tests && make check -k
TESTRUNNER=`which valgrind 2>/dev/null`)
- make -s clean
- ./scripts/update-docs.sh
69 changes: 69 additions & 0 deletions src/cborinternal_p.h
Expand Up @@ -27,6 +27,75 @@

#include "compilersupport_p.h"

#ifndef CBOR_NO_FLOATING_POINT
# include <float.h>
# include <math.h>
#else
# ifndef CBOR_NO_HALF_FLOAT_TYPE
# define CBOR_NO_HALF_FLOAT_TYPE 1
# endif
#endif

#ifndef CBOR_NO_HALF_FLOAT_TYPE
# ifdef __F16C__
# include <immintrin.h>
static inline unsigned short encode_half(double val)
{
return _cvtss_sh((float)val, 3);
}
static inline double decode_half(unsigned short half)
{
return _cvtsh_ss(half);
}
# else
/* software implementation of float-to-fp16 conversions */
static inline unsigned short encode_half(double val)
{
uint64_t v;
int sign, exp, mant;
memcpy(&v, &val, sizeof(v));
sign = v >> 63 << 15;
exp = (v >> 52) & 0x7ff;
mant = v << 12 >> 12 >> (53-11); /* keep only the 11 most significant bits of the mantissa */
exp -= 1023;
if (exp == 1024) {
/* infinity or NaN */
exp = 16;
mant >>= 1;
} else if (exp >= 16) {
/* overflow, as largest number */
exp = 15;
mant = 1023;
} else if (exp >= -14) {
/* regular normal */
} else if (exp >= -24) {
/* subnormal */
mant |= 1024;
mant >>= -(exp + 14);
exp = -15;
} else {
/* underflow, make zero */
return 0;
}

/* safe cast here as bit operations above guarantee not to overflow */
return (unsigned short)(sign | ((exp + 15) << 10) | mant);
}

/* this function was copied & adapted from RFC 7049 Appendix D */
static inline double decode_half(unsigned short half)
{
int exp = (half >> 10) & 0x1f;
int mant = half & 0x3ff;
double val;
if (exp == 0) val = ldexp(mant, -24);
else if (exp != 31) val = ldexp(mant + 1024, exp - 25);
else val = mant == 0 ? INFINITY : NAN;
return half & 0x8000 ? -val : val;
}
# endif
#endif /* CBOR_NO_HALF_FLOAT_TYPE */

#ifndef CBOR_INTERNAL_API
# define CBOR_INTERNAL_API
#endif
Expand Down
9 changes: 3 additions & 6 deletions src/cborpretty.c
@@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2017 Intel Corporation
** Copyright (C) 2018 Intel Corporation
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to deal
Expand Down Expand Up @@ -36,11 +36,6 @@
#include <inttypes.h>
#include <string.h>

#ifndef CBOR_NO_FLOATING_POINT
# include <float.h>
# include <math.h>
#endif

/**
* \defgroup CborPretty Converting CBOR to text
* \brief Group of functions used to convert CBOR to text form.
Expand Down Expand Up @@ -149,6 +144,7 @@
* \value CborPrettyDefaultFlags Default conversion flags.
*/

#ifndef CBOR_NO_FLOATING_POINT
static inline bool convertToUint64(double v, uint64_t *absolute)
{
double supremum;
Expand Down Expand Up @@ -179,6 +175,7 @@ static inline bool convertToUint64(double v, uint64_t *absolute)
*absolute = v;
return *absolute == v;
}
#endif

static void printRecursionLimit(CborStreamFunction stream, void *out)
{
Expand Down
19 changes: 16 additions & 3 deletions src/cbortojson.c
@@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 Intel Corporation
** Copyright (C) 2018 Intel Corporation
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to deal
Expand Down Expand Up @@ -32,11 +32,10 @@

#include "cbor.h"
#include "cborjson.h"
#include "cborinternal_p.h"
#include "compilersupport_p.h"

#include <float.h>
#include <inttypes.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Expand Down Expand Up @@ -595,6 +594,7 @@ static CborError value_to_json(FILE *out, CborValue *it, int flags, CborType typ
break;
}

#ifndef CBOR_NO_FLOATING_POINT
case CborDoubleType: {
double val;
if (false) {
Expand All @@ -606,9 +606,15 @@ static CborError value_to_json(FILE *out, CborValue *it, int flags, CborType typ
} else if (false) {
uint16_t f16;
case CborHalfFloatType:
# ifndef CBOR_NO_HALF_FLOAT_TYPE
status->flags = TypeWasNotNative;
cbor_value_get_half_float(it, &f16);
val = decode_half(f16);
# else
(void)f16;
err = CborErrorUnsupportedType;
break;
# endif
} else {
cbor_value_get_double(it, &val);
}
Expand All @@ -634,6 +640,13 @@ static CborError value_to_json(FILE *out, CborValue *it, int flags, CborType typ
}
break;
}
#else
case CborDoubleType:
case CborFloatType:
case CborHalfFloatType:
err = CborErrorUnsupportedType;
break;
#endif /* !CBOR_NO_FLOATING_POINT */

case CborInvalidType:
return CborErrorUnknownType;
Expand Down
59 changes: 0 additions & 59 deletions src/compilersupport_p.h
Expand Up @@ -36,8 +36,6 @@
#ifndef assert
# include <assert.h>
#endif
#include <float.h>
#include <math.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
Expand All @@ -46,10 +44,6 @@
# include <stdbool.h>
#endif

#ifdef __F16C__
# include <immintrin.h>
#endif

#if __STDC_VERSION__ >= 201112L || __cplusplus >= 201103L || __cpp_static_assert >= 200410
# define cbor_static_assert(x) static_assert(x, #x)
#elif !defined(__cplusplus) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406) && (__STDC_VERSION__ > 199901L)
Expand Down Expand Up @@ -207,58 +201,5 @@ static inline bool add_check_overflow(size_t v1, size_t v2, size_t *r)
#endif
}

static inline unsigned short encode_half(double val)
{
#ifdef __F16C__
return _cvtss_sh((float)val, 3);
#else
uint64_t v;
int sign, exp, mant;
memcpy(&v, &val, sizeof(v));
sign = v >> 63 << 15;
exp = (v >> 52) & 0x7ff;
mant = v << 12 >> 12 >> (53-11); /* keep only the 11 most significant bits of the mantissa */
exp -= 1023;
if (exp == 1024) {
/* infinity or NaN */
exp = 16;
mant >>= 1;
} else if (exp >= 16) {
/* overflow, as largest number */
exp = 15;
mant = 1023;
} else if (exp >= -14) {
/* regular normal */
} else if (exp >= -24) {
/* subnormal */
mant |= 1024;
mant >>= -(exp + 14);
exp = -15;
} else {
/* underflow, make zero */
return 0;
}

/* safe cast here as bit operations above guarantee not to overflow */
return (unsigned short)(sign | ((exp + 15) << 10) | mant);
#endif
}

/* this function was copied & adapted from RFC 7049 Appendix D */
static inline double decode_half(unsigned short half)
{
#ifdef __F16C__
return _cvtsh_ss(half);
#else
int exp = (half >> 10) & 0x1f;
int mant = half & 0x3ff;
double val;
if (exp == 0) val = ldexp(mant, -24);
else if (exp != 31) val = ldexp(mant + 1024, exp - 25);
else val = mant == 0 ? INFINITY : NAN;
return half & 0x8000 ? -val : val;
#endif
}

#endif /* COMPILERSUPPORT_H */

0 comments on commit bfc40dc

Please sign in to comment.