mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2024-11-30 08:24:11 +01:00
220 lines
4.9 KiB
C
220 lines
4.9 KiB
C
|
/*
|
||
|
# This file is Copyright 2009, 2010 Dean Hall.
|
||
|
#
|
||
|
# This file is part of the PyMite VM.
|
||
|
# The PyMite VM is free software: you can redistribute it and/or modify
|
||
|
# it under the terms of the GNU GENERAL PUBLIC LICENSE Version 2.
|
||
|
#
|
||
|
# The PyMite VM 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.
|
||
|
# A copy of the GNU GENERAL PUBLIC LICENSE Version 2
|
||
|
# is seen in the file COPYING in this directory.
|
||
|
*/
|
||
|
|
||
|
|
||
|
#undef __FILE_ID__
|
||
|
#define __FILE_ID__ 0x17
|
||
|
|
||
|
|
||
|
/**
|
||
|
* \file
|
||
|
* \brief Float Object Type
|
||
|
*
|
||
|
* Float object type operations.
|
||
|
*/
|
||
|
|
||
|
|
||
|
#include <math.h>
|
||
|
#include "pm.h"
|
||
|
|
||
|
|
||
|
#ifdef HAVE_FLOAT
|
||
|
|
||
|
|
||
|
PmReturn_t
|
||
|
float_new(float f, pPmObj_t *r_pf)
|
||
|
{
|
||
|
PmReturn_t retval = PM_RET_OK;
|
||
|
|
||
|
retval = heap_getChunk(sizeof(PmFloat_t), (uint8_t **)r_pf);
|
||
|
PM_RETURN_IF_ERROR(retval);
|
||
|
OBJ_SET_TYPE(*r_pf, OBJ_TYPE_FLT);
|
||
|
((pPmFloat_t) * r_pf)->val = f;
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
|
||
|
#ifdef HAVE_PRINT
|
||
|
PmReturn_t
|
||
|
float_print(pPmObj_t pf)
|
||
|
{
|
||
|
uint8_t tBuffer[32];
|
||
|
uint8_t bytesWritten;
|
||
|
uint8_t i;
|
||
|
PmReturn_t retval = PM_RET_OK;
|
||
|
|
||
|
C_ASSERT(pf != C_NULL);
|
||
|
|
||
|
/* Raise TypeError if obj is not an float */
|
||
|
if (OBJ_GET_TYPE(pf) != OBJ_TYPE_FLT)
|
||
|
{
|
||
|
PM_RAISE(retval, PM_RET_EX_TYPE);
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
/* #196: Changed to use snprintf */
|
||
|
bytesWritten = snprintf((char *)&tBuffer, 32, "%f", ((pPmFloat_t) pf)->val);
|
||
|
|
||
|
/* Sanity check */
|
||
|
C_ASSERT(bytesWritten != 0);
|
||
|
C_ASSERT(bytesWritten < sizeof(tBuffer));
|
||
|
|
||
|
for (i = (uint8_t)0; i < bytesWritten; i++)
|
||
|
{
|
||
|
retval = plat_putByte(tBuffer[i]);
|
||
|
PM_RETURN_IF_ERROR(retval);
|
||
|
}
|
||
|
return PM_RET_OK;
|
||
|
}
|
||
|
|
||
|
|
||
|
PmReturn_t
|
||
|
float_negative(pPmObj_t pf, pPmObj_t *r_pf)
|
||
|
{
|
||
|
/* Create new int obj */
|
||
|
return float_new(-((pPmFloat_t) pf)->val, r_pf);
|
||
|
}
|
||
|
|
||
|
#endif /* HAVE_PRINT */
|
||
|
|
||
|
|
||
|
PmReturn_t
|
||
|
float_op(pPmObj_t px, pPmObj_t py, pPmObj_t *r_pn, int8_t op)
|
||
|
{
|
||
|
float x;
|
||
|
float y;
|
||
|
float r;
|
||
|
PmReturn_t retval;
|
||
|
|
||
|
/* Raise TypeError if args aren't ints or floats */
|
||
|
if (((OBJ_GET_TYPE(px) != OBJ_TYPE_INT)
|
||
|
&& (OBJ_GET_TYPE(px) != OBJ_TYPE_FLT))
|
||
|
|| ((OBJ_GET_TYPE(py) != OBJ_TYPE_INT)
|
||
|
&& (OBJ_GET_TYPE(py) != OBJ_TYPE_FLT)))
|
||
|
{
|
||
|
PM_RAISE(retval, PM_RET_EX_TYPE);
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
/* Get the values as floats */
|
||
|
if (OBJ_GET_TYPE(px) == OBJ_TYPE_INT)
|
||
|
{
|
||
|
x = (float)((pPmInt_t)px)->val;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
x = ((pPmFloat_t) px)->val;
|
||
|
}
|
||
|
|
||
|
if (OBJ_GET_TYPE(py) == OBJ_TYPE_INT)
|
||
|
{
|
||
|
y = (float)((pPmInt_t)py)->val;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
y = ((pPmFloat_t) py)->val;
|
||
|
}
|
||
|
|
||
|
/* Raise ZeroDivisionError if denominator is zero */
|
||
|
if ((y == 0.0) && ((op == '/') || (op == '%')))
|
||
|
{
|
||
|
PM_RAISE(retval, PM_RET_EX_ZDIV);
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
/* Calculate x raised to y */
|
||
|
switch (op)
|
||
|
{
|
||
|
/* *INDENT-OFF* */
|
||
|
case '+': r = x + y; break;
|
||
|
case '-': r = x - y; break;
|
||
|
case '*': r = x * y; break;
|
||
|
case '/': r = x / y; break;
|
||
|
case '%': r = fmodf(x, y); break;
|
||
|
case 'P': r = powf(x, y); break;
|
||
|
default: r = 0.0; break;
|
||
|
/* *INDENT-ON* */
|
||
|
}
|
||
|
|
||
|
retval = float_new(r, r_pn);
|
||
|
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
PmReturn_t
|
||
|
float_compare(pPmObj_t px, pPmObj_t py, pPmObj_t *r_pobj, PmCompare_t cmp)
|
||
|
{
|
||
|
float x;
|
||
|
float y;
|
||
|
PmReturn_t retval = PM_RET_OK;
|
||
|
int8_t t8 = 0;
|
||
|
|
||
|
/* Raise TypeError if args aren't ints or floats */
|
||
|
if (((OBJ_GET_TYPE(px) != OBJ_TYPE_INT)
|
||
|
&& (OBJ_GET_TYPE(px) != OBJ_TYPE_FLT))
|
||
|
|| ((OBJ_GET_TYPE(py) != OBJ_TYPE_INT)
|
||
|
&& (OBJ_GET_TYPE(py) != OBJ_TYPE_FLT)))
|
||
|
{
|
||
|
PM_RAISE(retval, PM_RET_EX_TYPE);
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
/* Get the values as floats */
|
||
|
if (OBJ_GET_TYPE(px) == OBJ_TYPE_INT)
|
||
|
{
|
||
|
x = (float)((pPmInt_t)px)->val;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
x = ((pPmFloat_t) px)->val;
|
||
|
}
|
||
|
|
||
|
if (OBJ_GET_TYPE(py) == OBJ_TYPE_INT)
|
||
|
{
|
||
|
y = (float)((pPmInt_t)py)->val;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
y = ((pPmFloat_t) py)->val;
|
||
|
}
|
||
|
|
||
|
switch (cmp)
|
||
|
{
|
||
|
/* *INDENT-OFF* */
|
||
|
case COMP_LT: t8 = (int8_t)(x < y); break;
|
||
|
case COMP_LE: t8 = (int8_t)(x <= y); break;
|
||
|
case COMP_EQ: t8 = (int8_t)(x == y); break;
|
||
|
case COMP_NE: t8 = (int8_t)(x != y); break;
|
||
|
case COMP_GT: t8 = (int8_t)(x > y); break;
|
||
|
case COMP_GE: t8 = (int8_t)(x >= y); break;
|
||
|
case COMP_IS: t8 = (int8_t)(px == py); break;
|
||
|
case COMP_IS_NOT: t8 = (int8_t)(px != py);break;
|
||
|
case COMP_IN:
|
||
|
case COMP_NOT_IN:
|
||
|
PM_RAISE(retval, PM_RET_EX_TYPE);
|
||
|
break;
|
||
|
|
||
|
default:
|
||
|
/* Other compares are not yet supported */
|
||
|
PM_RAISE(retval, PM_RET_EX_SYS);
|
||
|
break;
|
||
|
/* *INDENT-ON* */
|
||
|
}
|
||
|
*r_pobj = (t8) ? PM_TRUE : PM_FALSE;
|
||
|
|
||
|
return retval;
|
||
|
}
|
||
|
|
||
|
#endif /* HAVE_FLOAT */
|