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:
parent
f183730917
commit
d7b4f1a5ba
@ -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
1
pkg/libfixmath/.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/checkout
|
65
pkg/libfixmath/Makefile
Normal file
65
pkg/libfixmath/Makefile
Normal 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
|
4
pkg/libfixmath/Makefile.include
Normal file
4
pkg/libfixmath/Makefile.include
Normal file
@ -0,0 +1,4 @@
|
||||
# The static cache is huge, disable it.
|
||||
CFLAGS += -DFIXMATH_NO_CACHE
|
||||
|
||||
INCLUDES += -I$(BINDIR)libfixmath-headers/
|
3
pkg/libfixmath/Makefile.template
Normal file
3
pkg/libfixmath/Makefile.template
Normal file
@ -0,0 +1,3 @@
|
||||
MODULE = libfixmath
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
3
pkg/libfixmath/Makefile.template-unittests
Normal file
3
pkg/libfixmath/Makefile.template-unittests
Normal file
@ -0,0 +1,3 @@
|
||||
MODULE = libfixmath-unittests
|
||||
|
||||
include $(RIOTBASE)/Makefile.base
|
6
tests/libfixmath/Makefile
Normal file
6
tests/libfixmath/Makefile
Normal 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
96
tests/libfixmath/do-test.py
Executable 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
195
tests/libfixmath/main.c
Normal 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;
|
||||
}
|
12
tests/libfixmath_unittests/Makefile
Normal file
12
tests/libfixmath_unittests/Makefile
Normal 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
|
36
tests/libfixmath_unittests/main.c
Normal file
36
tests/libfixmath_unittests/main.c
Normal 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;
|
||||
}
|
Loading…
Reference in New Issue
Block a user