Skip to content

Commit

Permalink
enhancement #149 implemented: access half-precision floating point da…
Browse files Browse the repository at this point in the history
…ta as single float

Motivation: half-precision floating point format is used to minimize storage
and traffic mostly.  Application level manipulates with single and double
precision usually. So, two routines added to public API to encode/decode given
single precision value in the half precision format

Signed-off-by: S.Phirsov
Signed-off-by: Thiago Macieira <[email protected]>
  • Loading branch information
phirsov authored and thiagomacieira committed Sep 3, 2021
1 parent cb37252 commit 814ec02
Show file tree
Hide file tree
Showing 10 changed files with 370 additions and 13 deletions.
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ TINYCBOR_FREESTANDING_SOURCES = \
src/cborerrorstrings.c \
src/cborencoder.c \
src/cborencoder_close_container_checked.c \
src/cborencoder_float.c \
src/cborparser.c \
src/cborparser_float.c \
src/cborpretty.c \
#
CBORDUMP_SOURCES = tools/cbordump/cbordump.c
Expand Down
4 changes: 4 additions & 0 deletions Makefile.nmake
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,21 @@ TINYCBOR_SOURCES = \
src\cborerrorstrings.c \
src\cborencoder.c \
src\cborencoder_close_container_checked.c \
src\cborencoder_float.c \
src\cborparser.c \
src\cborparser_dup_string.c \
src\cborparser_float.c \
src\cborpretty.c \
src\cborpretty_stdio.c \
src\cborvalidation.c
TINYCBOR_OBJS = \
src\cborerrorstrings.obj \
src\cborencoder.obj \
src\cborencoder_close_container_checked.obj \
src\cborencoder_float.obj \
src\cborparser.obj \
src\cborparser_dup_string.obj \
src\cborparser_float.obj \
src\cborpretty.obj \
src\cborpretty_stdio.obj \
src\cborvalidation.obj
Expand Down
3 changes: 3 additions & 0 deletions src/cbor.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,7 @@ CBOR_INLINE_API CborError cbor_encode_undefined(CborEncoder *encoder)

CBOR_INLINE_API CborError cbor_encode_half_float(CborEncoder *encoder, const void *value)
{ return cbor_encode_floating_point(encoder, CborHalfFloatType, value); }
CBOR_API CborError cbor_encode_float_as_half_float(CborEncoder *encoder, float value);
CBOR_INLINE_API CborError cbor_encode_float(CborEncoder *encoder, float value)
{ return cbor_encode_floating_point(encoder, CborFloatType, &value); }
CBOR_INLINE_API CborError cbor_encode_double(CborEncoder *encoder, double value)
Expand Down Expand Up @@ -493,7 +494,9 @@ CBOR_API CborError cbor_value_map_find_value(const CborValue *map, const char *s
/* Floating point */
CBOR_INLINE_API bool cbor_value_is_half_float(const CborValue *value)
{ return value->type == CborHalfFloatType; }
CBOR_PRIVATE_API uint16_t _cbor_value_get_half_float_helper(const CborValue *value);
CBOR_API CborError cbor_value_get_half_float(const CborValue *value, void *result);
CBOR_API CborError cbor_value_get_half_float_as_float(const CborValue *value, float *result);

CBOR_INLINE_API bool cbor_value_is_float(const CborValue *value)
{ return value->type == CborFloatType; }
Expand Down
18 changes: 15 additions & 3 deletions src/cborencoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -382,7 +382,7 @@ CborError cbor_encode_simple_value(CborEncoder *encoder, uint8_t value)
* This function is useful for code that needs to pass through floating point
* values but does not wish to have the actual floating-point code.
*
* \sa cbor_encode_half_float, cbor_encode_float, cbor_encode_double
* \sa cbor_encode_half_float, cbor_encode_float_as_half_float, cbor_encode_float, cbor_encode_double
*/
CborError cbor_encode_floating_point(CborEncoder *encoder, CborType fpType, const void *value)
{
Expand Down Expand Up @@ -589,13 +589,25 @@ CborError cbor_encoder_close_container(CborEncoder *parentEncoder, const CborEnc
* \sa cbor_encode_floating_point(), cbor_encode_float(), cbor_encode_double()
*/

/**
* \fn CborError cbor_encode_float_as_half_float(CborEncoder *encoder, float value)
*
* Convert the IEEE 754 single-precision (32-bit) floating point value \a value
* to the IEEE 754 half-precision (16-bit) floating point value and append it
* to the CBOR stream provided by \a encoder.
* The \a value should be in the range of the IEEE 754 half-precision floating point type,
* INFINITY, -INFINITY, or NAN, otherwise the behavior of this function is undefined.
*
* \sa cbor_encode_floating_point(), cbor_encode_float(), cbor_encode_double()
*/

/**
* \fn CborError cbor_encode_float(CborEncoder *encoder, float value)
*
* Appends the IEEE 754 single-precision (32-bit) floating point value \a value
* to the CBOR stream provided by \a encoder.
*
* \sa cbor_encode_floating_point(), cbor_encode_half_float(), cbor_encode_double()
* \sa cbor_encode_floating_point(), cbor_encode_half_float(), cbor_encode_float_as_half_float(), cbor_encode_double()
*/

/**
Expand All @@ -604,7 +616,7 @@ CborError cbor_encoder_close_container(CborEncoder *parentEncoder, const CborEnc
* Appends the IEEE 754 double-precision (64-bit) floating point value \a value
* to the CBOR stream provided by \a encoder.
*
* \sa cbor_encode_floating_point(), cbor_encode_half_float(), cbor_encode_float()
* \sa cbor_encode_floating_point(), cbor_encode_half_float(), cbor_encode_float_as_half_float(), cbor_encode_float()
*/

/**
Expand Down
42 changes: 42 additions & 0 deletions src/cborencoder_float.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/****************************************************************************
**
** Copyright (C) 2019 S.Phirsov
**
** 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.
**
****************************************************************************/

#define _BSD_SOURCE 1
#define _DEFAULT_SOURCE 1
#ifndef __STDC_LIMIT_MACROS
# define __STDC_LIMIT_MACROS 1
#endif

#include "cbor.h"

#include "cborinternal_p.h"

#ifndef CBOR_NO_HALF_FLOAT_TYPE
CborError cbor_encode_float_as_half_float(CborEncoder *encoder, float value)
{
uint16_t v = (uint16_t)encode_half(value);

return cbor_encode_floating_point(encoder, CborHalfFloatType, &v);
}
#endif
23 changes: 19 additions & 4 deletions src/cborparser.c
Original file line number Diff line number Diff line change
Expand Up @@ -1433,17 +1433,32 @@ CborError cbor_value_map_find_value(const CborValue *map, const char *string, Cb
* floating point, this function takes a \c{void *} as a parameter for the
* storage area, which must be at least 16 bits wide.
*
* \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_half_float(), cbor_value_get_float()
* \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_half_float(), cbor_value_get_half_float_as_float(), cbor_value_get_float()
*/
CborError cbor_value_get_half_float(const CborValue *value, void *result)
{
uint16_t v;
cbor_assert(cbor_value_is_half_float(value));

/* size has been computed already */
v = get16(value->ptr + 1);
v = _cbor_value_get_half_float_helper(value);
memcpy(result, &v, sizeof(v));

return CborNoError;
}

/** \internal
*
* Retrieves the CBOR half-precision floating point value binary
* representation as 16-bit unsigned integer.
* The result can be used as-is, e.g. to copy bitwise into the
* system-dependent half-precision floating point type, or it can be
* converted to the C language standard floating point type
* (float or double).
*/
CBOR_PRIVATE_API uint16_t _cbor_value_get_half_float_helper(const CborValue *value)
{
cbor_assert(cbor_value_is_half_float(value));
/* size has been computed already */
return get16(value->ptr + 1);
}

/** @} */
54 changes: 54 additions & 0 deletions src/cborparser_float.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/****************************************************************************
**
** Copyright (C) 2019 S.Phirsov
**
** 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.
**
****************************************************************************/

#define _BSD_SOURCE 1
#define _DEFAULT_SOURCE 1
#ifndef __STDC_LIMIT_MACROS
# define __STDC_LIMIT_MACROS 1
#endif

#include "cbor.h"

#include "cborinternal_p.h"

#ifndef CBOR_NO_HALF_FLOAT_TYPE
/**
* Retrieves the CBOR half-precision floating point (16-bit) value that \a
* value points to, converts it to the float and store it in \a result.
* If the iterator \a value does not point to a half-precision floating
* point value, the behavior is undefined, so checking with \ref
* cbor_value_get_type or with \ref cbor_value_is_half_float is recommended.
* \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_half_float(), cbor_value_get_half_float(), cbor_value_get_float()
*/
CborError cbor_value_get_half_float_as_float(const CborValue *value, float *result)
{
uint16_t v;

v = _cbor_value_get_half_float_helper(value);

*result = (float)decode_half((unsigned short)v);

return CborNoError;
}
#endif
2 changes: 2 additions & 0 deletions tests/cpp/tst_cpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@
****************************************************************************/

#include "../../src/cborencoder.c"
#include "../../src/cborencoder_float.c"
#include "../../src/cborerrorstrings.c"
#include "../../src/cborparser.c"
#include "../../src/cborparser_dup_string.c"
#include "../../src/cborparser_float.c"
#include "../../src/cborvalidation.c"

#include <QtTest>
Expand Down
Loading

0 comments on commit 814ec02

Please sign in to comment.