1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

pkg: add USEPKG module "libfixmath"

This PR adds the USEPKG module "libfixmath".
It integrates https://code.google.com/p/libfixmath/ into RIOT, cmp. #1457.
This commit is contained in:
René Kijewski 2014-07-22 20:24:45 +02:00
parent f183730917
commit d7b4f1a5ba
11 changed files with 425 additions and 0 deletions

View File

@ -85,3 +85,7 @@ endif
ifneq (,$(filter pipe,$(USEMODULE)))
USEMODULE += lib
endif
ifneq (,$(filter libfixmath-unittests,$(USEMODULE)))
USEPKG += libfixmath
endif

1
pkg/libfixmath/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/checkout

65
pkg/libfixmath/Makefile Normal file
View File

@ -0,0 +1,65 @@
PKG_NAME := libfixmath
PKG_VERSION := 91
PKG_BRANCH := trunk
PKG_URL := http://libfixmath.googlecode.com/svn/$(PKG_BRANCH)/
CHECKOUT_FOLDER := $(CURDIR)/checkout/$(PKG_BRANCH)-r$(PKG_VERSION)
.PHONY: all clean distclean
all: $(BINDIR)$(PKG_NAME).a
all-unittests: $(BINDIR)$(PKG_NAME)-unittests.a
ifneq (,$(filter libfixmath-unittests,$(USEMODULE)))
all: all-unittests
endif
$(BINDIR)$(PKG_NAME).a: $(BINDIR)$(PKG_NAME)-src/Makefile $(BINDIR)$(PKG_NAME)-headers/fix16.h
"$(MAKE)" -C $(<D)
$(BINDIR)$(PKG_NAME)-unittests.a: $(BINDIR)$(PKG_NAME)-unittests-src/Makefile $(BINDIR)$(PKG_NAME)-headers/fix16.h
"$(MAKE)" -C $(<D)
$(BINDIR)$(PKG_NAME)-src/Makefile: $(CHECKOUT_FOLDER)/svn_info.xml
@rm -rf $(@D)
@mkdir -p $(@D)
$(AD)cp $(CURDIR)/Makefile.template $@
$(AD)cp $(CHECKOUT_FOLDER)/libfixmath/*.[ch] $(@D)
$(AD)rm -f $(BINDIR)$(PKG_NAME)-src/fix16.h
cd $(@D) && sed -i -e "s/1 <</(uint32_t) 1 <</g" uint32.c
$(BINDIR)$(PKG_NAME)-unittests-src/Makefile:
@rm -rf $(@D)
@mkdir -p $(@D)
$(AD)cp $(CURDIR)/Makefile.template-unittests $@
$(AD)cp $(CHECKOUT_FOLDER)/unittests/*.[ch] $(@D)
$(AD)cd $(@D) && for C_FILE in *.[ch]; do \
sed -e "s/int main()/int $$(basename $${C_FILE} .c)(void)/" \
-e '/fflush/d' \
-e 's/fprintf(std[^,]*,/printf(/' \
-i $${C_FILE}; \
done
$(BINDIR)$(PKG_NAME)-headers/fix16.h: $(CHECKOUT_FOLDER)/svn_info.xml
@rm -rf $(@D)
@mkdir -p $(@D)
$(AD)cp $(CHECKOUT_FOLDER)/libfixmath/fix16.h $(@D)
@echo $(patsubst %,'extern int %(void);',$(shell basename -a -s .c $(CHECKOUT_FOLDER)/unittests/*.c)) \
$(patsubst %,'%();',$(shell basename -a -s .c $(CHECKOUT_FOLDER)/unittests/*.c)) | sed -e 's/;\s*/;\n/g' > $(@D)/fix16_unittests.inc
$(CHECKOUT_FOLDER)/svn_info.xml:
@mkdir -p $(@D)
svn checkout -r $(PKG_VERSION) $(PKG_URL) $(@D)
@svn info --xml $(@D) > $@
clean::
rm -rf $(BINDIR)$(PKG_NAME)-src/ $(BINDIR)$(PKG_NAME)-headers/
distclean:: clean
rm -rf $(CHECKOUT_FOLDER)
Makefile.include:
@true

View File

@ -0,0 +1,4 @@
# The static cache is huge, disable it.
CFLAGS += -DFIXMATH_NO_CACHE
INCLUDES += -I$(BINDIR)libfixmath-headers/

View File

@ -0,0 +1,3 @@
MODULE = libfixmath
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,3 @@
MODULE = libfixmath-unittests
include $(RIOTBASE)/Makefile.base

View File

@ -0,0 +1,6 @@
APPLICATION = libfixmath
include ../Makefile.tests_common
USEPKG += libfixmath
include $(RIOTBASE)/Makefile.include

96
tests/libfixmath/do-test.py Executable file
View File

@ -0,0 +1,96 @@
#!/usr/bin/env python3
import math
import operator
import sys
def rem(a, b):
ret = a % b
if ret < 0 and a > 0 and b < 0 or \
ret > 0 and a < 0 and b > 0:
ret -= b
return ret
FUNS = {
'add': operator.add,
'sub': operator.sub,
'mul': operator.mul,
'div': operator.truediv,
'mod': rem,
'sadd': operator.add,
'ssub': operator.sub,
'smul': operator.mul,
'sdiv': operator.truediv,
'min': min,
'max': max,
'abs': abs,
'sqrt': math.sqrt,
'sq': lambda x: x * x,
'sin': math.sin,
'cos': math.cos,
'tan': math.tan,
'asin': math.asin,
'acos': math.acos,
'atan': math.atan,
'exp': math.exp,
'log': math.log,
'log2': math.log2,
'slog2': math.log2,
}
ABS_ERROR_LIMIT = 0.011
def main():
total = 0
errors = 0
print('Calculation: abs result != exp result, abs error > limit')
started = False
for line in sys.stdin:
line = line.strip()
if not started:
if line == 'Unary.':
print(line)
started = True
continue
elif line == 'Binary.':
print(line)
continue
elif line == 'Done.':
print(line)
break
total += 1
try:
res_locals = {}
res_locals['input'], res_locals['expected'] = map(str.strip, line.split('='))
exec('result = {}'.format(res_locals['input']), FUNS, res_locals)
abs_error = abs(res_locals['result'] - float(res_locals['expected']))
res_locals['result'] = '{:.4f}'.format(res_locals['result'])
if abs_error > ABS_ERROR_LIMIT:
print('{}: {} != {}, {:.4f} > {}'.format(res_locals['input'], res_locals['result'], res_locals['expected'],
abs_error, ABS_ERROR_LIMIT))
errors += 1
except:
errors += 1
print('ERROR {}'.format(line))
print('{} calculations passed.'.format(total - errors))
if errors:
print('{} calculations had errors.'.format(errors))
return 1
else:
return 0
if __name__ == '__main__':
sys.exit(main())

195
tests/libfixmath/main.c Normal file
View File

@ -0,0 +1,195 @@
/*
* Copyright (C) 2014 René Kijewski <rene.kijewski@fu-berlin.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @ingroup tests
* @{
*
* @file
* @brief Print some calculations for libfixmath
*
* @author René Kijewski <rene.kijewski@fu-berlin.de>
*
* @}
*/
#include <stdio.h>
#include "fix16.h"
#ifndef M_PI
# define M_PI 3.14159265359
#endif
static void binary_ops(void)
{
static const struct {
const char *op;
fix16_t (*fun)(fix16_t, fix16_t);
} ops[] = {
{ "add", fix16_add },
{ "sub", fix16_sub },
{ "mul", fix16_mul },
{ "div", fix16_div },
{ "mod", fix16_mod },
{ "sadd", fix16_sadd },
{ "ssub", fix16_ssub },
{ "smul", fix16_smul },
{ "sdiv", fix16_sdiv },
{ "min", fix16_min },
{ "max", fix16_max },
};
for (fix16_t a = fix16_from_dbl(-5.0); a < fix16_from_dbl(5.0); a += fix16_from_dbl(0.25)) {
for (fix16_t b = fix16_from_dbl(-5.0); b < fix16_from_dbl(5.0); b += fix16_from_dbl(0.25)) {
if (b == 0) {
continue;
}
for (unsigned o = 0; o < sizeof(ops) / sizeof(*ops); ++o) {
fix16_t c = ops[o].fun(a, b);
char buf[3][14];
fix16_to_str(a, buf[0], 12);
fix16_to_str(b, buf[1], 12);
fix16_to_str(c, buf[2], 12);
printf("%s(%s, %s) = %s\n", ops[o].op, buf[0], buf[1], buf[2]);
}
}
}
}
static void unary_ops(void)
{
/* range [-10 : +10 : 0.25] */
{
static const struct {
const char *op;
fix16_t (*fun)(fix16_t);
} ops[] = {
{ "abs", fix16_abs },
{ "sq", fix16_sq },
{ "atan", fix16_atan },
{ "exp", fix16_exp },
};
for (fix16_t input = fix16_from_dbl(-10.0); input < fix16_from_dbl(+10.0); input += fix16_from_dbl(0.25)) {
for (unsigned o = 0; o < sizeof(ops) / sizeof(*ops); ++o) {
fix16_t result = ops[o].fun(input);
char buf[2][14];
fix16_to_str(input, buf[0], 12);
fix16_to_str(result, buf[1], 12);
printf("%s(%s) = %s\n", ops[o].op, buf[0], buf[1]);
}
}
}
/* range [-pi/2 : +pi/2 : 0.05] */
{
static const struct {
const char *op;
fix16_t (*fun)(fix16_t);
} ops[] = {
/* { "sin_parabola", fix16_sin_parabola }, FIXME: what is sin_parabola? */
{ "sin", fix16_sin },
{ "cos", fix16_cos },
{ "tan", fix16_tan },
};
for (fix16_t input = fix16_from_dbl(-M_PI/2); input < fix16_from_dbl(+M_PI/2); input += fix16_from_dbl(0.05)) {
for (unsigned o = 0; o < sizeof(ops) / sizeof(*ops); ++o) {
fix16_t result = ops[o].fun(input);
char buf[2][14];
fix16_to_str(input, buf[0], 12);
fix16_to_str(result, buf[1], 12);
printf("%s(%s) = %s\n", ops[o].op, buf[0], buf[1]);
}
}
}
/* range [-1 : +1 : 0.05] */
{
static const struct {
const char *op;
fix16_t (*fun)(fix16_t);
} ops[] = {
{ "asin", fix16_asin },
{ "acos", fix16_acos },
};
for (fix16_t input = fix16_from_dbl(-1.0); input < fix16_from_dbl(+1.0); input += fix16_from_dbl(0.05)) {
for (unsigned o = 0; o < sizeof(ops) / sizeof(*ops); ++o) {
fix16_t result = ops[o].fun(input);
char buf[2][14];
fix16_to_str(input, buf[0], 12);
fix16_to_str(result, buf[1], 12);
printf("%s(%s) = %s\n", ops[o].op, buf[0], buf[1]);
}
}
}
/* range [+0.05 : +10 : 0.25] */
{
static const struct {
const char *op;
fix16_t (*fun)(fix16_t);
} ops[] = {
{ "sqrt", fix16_sqrt },
{ "log", fix16_log },
{ "log2", fix16_log2 },
{ "slog2", fix16_slog2 },
};
for (fix16_t input = fix16_from_dbl(0.05); input < fix16_from_dbl(+10.0); input += fix16_from_dbl(0.25)) {
for (unsigned o = 0; o < sizeof(ops) / sizeof(*ops); ++o) {
fix16_t result = ops[o].fun(input);
char buf[2][14];
fix16_to_str(input, buf[0], 12);
fix16_to_str(result, buf[1], 12);
printf("%s(%s) = %s\n", ops[o].op, buf[0], buf[1]);
}
}
}
}
int main(void)
{
puts("Unary.");
unary_ops();
puts("Binary.");
binary_ops();
puts("Done.");
return 0;
}

View File

@ -0,0 +1,12 @@
APPLICATION = libfixmath_unittests
include ../Makefile.tests_common
# The MSP boards don't feature round(), exp(), and log(), which are used in the unittests
BOARD_INSUFFICIENT_RAM := chronos msb-430 msb-430h telosb wsn430-v1_3b wsn430-v1_4 z1
# Insufficient RAM / ROM
BOARD_INSUFFICIENT_RAM += redbee-econotag stm32f0discovery
USEMODULE += libfixmath-unittests
include $(RIOTBASE)/Makefile.include

View File

@ -0,0 +1,36 @@
/*
* Copyright (C) 2014 René Kijewski <rene.kijewski@fu-berlin.de>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
/**
* @ingroup tests
* @{
*
* @file
* @brief execute libfixmath's unittests in RIOT
*
* @author René Kijewski <rene.kijewski@fu-berlin.de>
*
* @}
*/
int main(void)
{
#include "fix16_unittests.inc"
return 0;
}