Browse Source
This PR adds the USEPKG module "libfixmath". It integrates https://code.google.com/p/libfixmath/ into RIOT, cmp. #1457.dev/timer

11 changed files with 425 additions and 0 deletions
@ -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
|
@ -0,0 +1,4 @@
|
||||
# The static cache is huge, disable it.
|
||||
CFLAGS += -DFIXMATH_NO_CACHE
|
||||
|
||||
INCLUDES += -I$(BINDIR)libfixmath-headers/
|
@ -0,0 +1,3 @@
|
||||
MODULE = libfixmath
|
||||
|
||||
include $(RIOTBASE)/Makefile.base |
@ -0,0 +1,3 @@
|
||||
MODULE = libfixmath-unittests
|
||||
|
||||
include $(RIOTBASE)/Makefile.base |
@ -0,0 +1,6 @@
|
||||
APPLICATION = libfixmath
|
||||
include ../Makefile.tests_common |
||||
|
||||
USEPKG += libfixmath
|
||||
|
||||
include $(RIOTBASE)/Makefile.include |
@ -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()) |
@ -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; |
||||
} |
@ -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 |
@ -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