Skip to content

Commit bfc40dc

Browse files
Move the floating point code to cborinternal_p.h
... 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 <[email protected]>
1 parent 8894366 commit bfc40dc

File tree

5 files changed

+107
-70
lines changed

5 files changed

+107
-70
lines changed

.travis.yml

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ matrix:
1515
- QMAKESPEC=linux-g++
1616
- EVAL="CC=gcc-7 && CXX=g++-7"
1717
- CFLAGS="-Os"
18+
- LDFLAGS="-Wl,--no-undefined -lm"
1819
- QMAKEFLAGS="-config release"
1920
- os: linux
2021
addons:
@@ -29,9 +30,23 @@ matrix:
2930
- EVAL="CC=clang-5.0 && CXX=clang++"
3031
- PATH=$PATH:/usr/local/clang/bin
3132
- CFLAGS="-Oz"
33+
- LDFLAGS="-Wl,--no-undefined -lm"
3234
- QMAKEFLAGS="-config release"
3335
- MAKEFLAGS=-s
3436
- TESTARGS=-silent
37+
- os: linux
38+
env:
39+
- QMAKESPEC=linux-gcc-freestanding
40+
- EVAL="CXX=false"
41+
- CFLAGS="-ffreestanding -Os"
42+
- LDFLAGS="-Wl,--no-undefined -lm"
43+
- os: linux
44+
env:
45+
- QMAKESPEC=linux-gcc-no-math
46+
- EVAL="CXX=false && touch src/math.h src/float.h"
47+
- CFLAGS="-ffreestanding -DCBOR_NO_FLOATING_POINT -Os"
48+
- LDFLAGS="-Wl,--no-undefined"
49+
- LDLIBS=""
3550
- os: osx
3651
env:
3752
- QMAKESPEC=macx-clang
@@ -57,10 +72,12 @@ script:
5772
- make -s clean
5873
- make -k
5974
CFLAGS="$CFLAGS -O0 -g"
60-
- make
75+
LDFLAGS="$LDFLAGS" ${LDLIBS+LDLIBS="$LDLIBS"}
76+
- grep -q freestanding-pass .config || make
6177
QMAKEFLAGS="$QMAKEFLAGS QMAKE_CXX=$CXX"
6278
tests/Makefile
63-
- (cd tests && make check -k
79+
- grep -q freestanding-pass .config ||
80+
(cd tests && make check -k
6481
TESTRUNNER=`which valgrind 2>/dev/null`)
6582
- make -s clean
6683
- ./scripts/update-docs.sh

src/cborinternal_p.h

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,75 @@
2727

2828
#include "compilersupport_p.h"
2929

30+
#ifndef CBOR_NO_FLOATING_POINT
31+
# include <float.h>
32+
# include <math.h>
33+
#else
34+
# ifndef CBOR_NO_HALF_FLOAT_TYPE
35+
# define CBOR_NO_HALF_FLOAT_TYPE 1
36+
# endif
37+
#endif
38+
39+
#ifndef CBOR_NO_HALF_FLOAT_TYPE
40+
# ifdef __F16C__
41+
# include <immintrin.h>
42+
static inline unsigned short encode_half(double val)
43+
{
44+
return _cvtss_sh((float)val, 3);
45+
}
46+
static inline double decode_half(unsigned short half)
47+
{
48+
return _cvtsh_ss(half);
49+
}
50+
# else
51+
/* software implementation of float-to-fp16 conversions */
52+
static inline unsigned short encode_half(double val)
53+
{
54+
uint64_t v;
55+
int sign, exp, mant;
56+
memcpy(&v, &val, sizeof(v));
57+
sign = v >> 63 << 15;
58+
exp = (v >> 52) & 0x7ff;
59+
mant = v << 12 >> 12 >> (53-11); /* keep only the 11 most significant bits of the mantissa */
60+
exp -= 1023;
61+
if (exp == 1024) {
62+
/* infinity or NaN */
63+
exp = 16;
64+
mant >>= 1;
65+
} else if (exp >= 16) {
66+
/* overflow, as largest number */
67+
exp = 15;
68+
mant = 1023;
69+
} else if (exp >= -14) {
70+
/* regular normal */
71+
} else if (exp >= -24) {
72+
/* subnormal */
73+
mant |= 1024;
74+
mant >>= -(exp + 14);
75+
exp = -15;
76+
} else {
77+
/* underflow, make zero */
78+
return 0;
79+
}
80+
81+
/* safe cast here as bit operations above guarantee not to overflow */
82+
return (unsigned short)(sign | ((exp + 15) << 10) | mant);
83+
}
84+
85+
/* this function was copied & adapted from RFC 7049 Appendix D */
86+
static inline double decode_half(unsigned short half)
87+
{
88+
int exp = (half >> 10) & 0x1f;
89+
int mant = half & 0x3ff;
90+
double val;
91+
if (exp == 0) val = ldexp(mant, -24);
92+
else if (exp != 31) val = ldexp(mant + 1024, exp - 25);
93+
else val = mant == 0 ? INFINITY : NAN;
94+
return half & 0x8000 ? -val : val;
95+
}
96+
# endif
97+
#endif /* CBOR_NO_HALF_FLOAT_TYPE */
98+
3099
#ifndef CBOR_INTERNAL_API
31100
# define CBOR_INTERNAL_API
32101
#endif

src/cborpretty.c

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/****************************************************************************
22
**
3-
** Copyright (C) 2017 Intel Corporation
3+
** Copyright (C) 2018 Intel Corporation
44
**
55
** Permission is hereby granted, free of charge, to any person obtaining a copy
66
** of this software and associated documentation files (the "Software"), to deal
@@ -36,11 +36,6 @@
3636
#include <inttypes.h>
3737
#include <string.h>
3838

39-
#ifndef CBOR_NO_FLOATING_POINT
40-
# include <float.h>
41-
# include <math.h>
42-
#endif
43-
4439
/**
4540
* \defgroup CborPretty Converting CBOR to text
4641
* \brief Group of functions used to convert CBOR to text form.
@@ -149,6 +144,7 @@
149144
* \value CborPrettyDefaultFlags Default conversion flags.
150145
*/
151146

147+
#ifndef CBOR_NO_FLOATING_POINT
152148
static inline bool convertToUint64(double v, uint64_t *absolute)
153149
{
154150
double supremum;
@@ -179,6 +175,7 @@ static inline bool convertToUint64(double v, uint64_t *absolute)
179175
*absolute = v;
180176
return *absolute == v;
181177
}
178+
#endif
182179

183180
static void printRecursionLimit(CborStreamFunction stream, void *out)
184181
{

src/cbortojson.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/****************************************************************************
22
**
3-
** Copyright (C) 2016 Intel Corporation
3+
** Copyright (C) 2018 Intel Corporation
44
**
55
** Permission is hereby granted, free of charge, to any person obtaining a copy
66
** of this software and associated documentation files (the "Software"), to deal
@@ -32,11 +32,10 @@
3232

3333
#include "cbor.h"
3434
#include "cborjson.h"
35+
#include "cborinternal_p.h"
3536
#include "compilersupport_p.h"
3637

37-
#include <float.h>
3838
#include <inttypes.h>
39-
#include <math.h>
4039
#include <stdio.h>
4140
#include <stdlib.h>
4241
#include <string.h>
@@ -595,6 +594,7 @@ static CborError value_to_json(FILE *out, CborValue *it, int flags, CborType typ
595594
break;
596595
}
597596

597+
#ifndef CBOR_NO_FLOATING_POINT
598598
case CborDoubleType: {
599599
double val;
600600
if (false) {
@@ -606,9 +606,15 @@ static CborError value_to_json(FILE *out, CborValue *it, int flags, CborType typ
606606
} else if (false) {
607607
uint16_t f16;
608608
case CborHalfFloatType:
609+
# ifndef CBOR_NO_HALF_FLOAT_TYPE
609610
status->flags = TypeWasNotNative;
610611
cbor_value_get_half_float(it, &f16);
611612
val = decode_half(f16);
613+
# else
614+
(void)f16;
615+
err = CborErrorUnsupportedType;
616+
break;
617+
# endif
612618
} else {
613619
cbor_value_get_double(it, &val);
614620
}
@@ -634,6 +640,13 @@ static CborError value_to_json(FILE *out, CborValue *it, int flags, CborType typ
634640
}
635641
break;
636642
}
643+
#else
644+
case CborDoubleType:
645+
case CborFloatType:
646+
case CborHalfFloatType:
647+
err = CborErrorUnsupportedType;
648+
break;
649+
#endif /* !CBOR_NO_FLOATING_POINT */
637650

638651
case CborInvalidType:
639652
return CborErrorUnknownType;

src/compilersupport_p.h

Lines changed: 0 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,6 @@
3636
#ifndef assert
3737
# include <assert.h>
3838
#endif
39-
#include <float.h>
40-
#include <math.h>
4139
#include <stddef.h>
4240
#include <stdint.h>
4341
#include <string.h>
@@ -46,10 +44,6 @@
4644
# include <stdbool.h>
4745
#endif
4846

49-
#ifdef __F16C__
50-
# include <immintrin.h>
51-
#endif
52-
5347
#if __STDC_VERSION__ >= 201112L || __cplusplus >= 201103L || __cpp_static_assert >= 200410
5448
# define cbor_static_assert(x) static_assert(x, #x)
5549
#elif !defined(__cplusplus) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406) && (__STDC_VERSION__ > 199901L)
@@ -207,58 +201,5 @@ static inline bool add_check_overflow(size_t v1, size_t v2, size_t *r)
207201
#endif
208202
}
209203

210-
static inline unsigned short encode_half(double val)
211-
{
212-
#ifdef __F16C__
213-
return _cvtss_sh((float)val, 3);
214-
#else
215-
uint64_t v;
216-
int sign, exp, mant;
217-
memcpy(&v, &val, sizeof(v));
218-
sign = v >> 63 << 15;
219-
exp = (v >> 52) & 0x7ff;
220-
mant = v << 12 >> 12 >> (53-11); /* keep only the 11 most significant bits of the mantissa */
221-
exp -= 1023;
222-
if (exp == 1024) {
223-
/* infinity or NaN */
224-
exp = 16;
225-
mant >>= 1;
226-
} else if (exp >= 16) {
227-
/* overflow, as largest number */
228-
exp = 15;
229-
mant = 1023;
230-
} else if (exp >= -14) {
231-
/* regular normal */
232-
} else if (exp >= -24) {
233-
/* subnormal */
234-
mant |= 1024;
235-
mant >>= -(exp + 14);
236-
exp = -15;
237-
} else {
238-
/* underflow, make zero */
239-
return 0;
240-
}
241-
242-
/* safe cast here as bit operations above guarantee not to overflow */
243-
return (unsigned short)(sign | ((exp + 15) << 10) | mant);
244-
#endif
245-
}
246-
247-
/* this function was copied & adapted from RFC 7049 Appendix D */
248-
static inline double decode_half(unsigned short half)
249-
{
250-
#ifdef __F16C__
251-
return _cvtsh_ss(half);
252-
#else
253-
int exp = (half >> 10) & 0x1f;
254-
int mant = half & 0x3ff;
255-
double val;
256-
if (exp == 0) val = ldexp(mant, -24);
257-
else if (exp != 31) val = ldexp(mant + 1024, exp - 25);
258-
else val = mant == 0 ? INFINITY : NAN;
259-
return half & 0x8000 ? -val : val;
260-
#endif
261-
}
262-
263204
#endif /* COMPILERSUPPORT_H */
264205

0 commit comments

Comments
 (0)