python-on-a-chip online compiler

Dependencies:   mbed TSI

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers float.c Source File

float.c

Go to the documentation of this file.
00001 /*
00002 # This file is Copyright 2009 Dean Hall.
00003 # This file is part of the PyMite VM.
00004 # This file is licensed under the MIT License.
00005 # See the LICENSE file for details.
00006 */
00007 
00008 
00009 #undef __FILE_ID__
00010 #define __FILE_ID__ 0x17
00011 
00012 
00013 /**
00014  * \file
00015  * \brief Float Object Type
00016  *
00017  * Float object type operations.
00018  */
00019 
00020 
00021 #include "pm.h"
00022 
00023 
00024 #ifdef HAVE_FLOAT
00025 #include <math.h>
00026 
00027 
00028 PmReturn_t
00029 float_new(float f, pPmObj_t *r_pf)
00030 {
00031     PmReturn_t retval = PM_RET_OK;
00032 
00033     retval = heap_getChunk(sizeof(PmFloat_t), (uint8_t **)r_pf);
00034     PM_RETURN_IF_ERROR(retval);
00035     OBJ_SET_TYPE(*r_pf, OBJ_TYPE_FLT);
00036     ((pPmFloat_t) * r_pf)->val = f;
00037     return retval;
00038 }
00039 
00040 
00041 #ifdef HAVE_PRINT
00042 
00043 PmReturn_t
00044 float_print(pPmObj_t pf)
00045 {
00046     uint8_t tBuffer[32];
00047     uint8_t bytesWritten;
00048     uint8_t *p;
00049     PmReturn_t retval = PM_RET_OK;
00050 
00051     C_ASSERT(pf != C_NULL);
00052 
00053     /* Raise TypeError if obj is not an float */
00054     if (OBJ_GET_TYPE(pf) != OBJ_TYPE_FLT)
00055     {
00056         PM_RAISE(retval, PM_RET_EX_TYPE);
00057         return retval;
00058     }
00059 
00060     /* #212: Use homebrew float formatter */
00061     retval = sli_ftoa(((pPmFloat_t)pf)->val, tBuffer, sizeof(tBuffer));
00062     bytesWritten = sli_strlen((char *)tBuffer);
00063 
00064     /* Remove trailing zeroes (per Python convention) */
00065     for (p = &tBuffer[bytesWritten] - 1; 
00066          p[0] == '0' && p[-1] != '.'; 
00067          --p, bytesWritten--);
00068     ++p;
00069     *p = '\0';
00070 
00071     /* Sanity check */
00072     C_ASSERT(bytesWritten != 0);
00073     C_ASSERT(bytesWritten < sizeof(tBuffer));
00074 
00075     sli_puts(tBuffer);
00076     return PM_RET_OK;
00077 }
00078 
00079 
00080 PmReturn_t
00081 float_negative(pPmObj_t pf, pPmObj_t *r_pf)
00082 {
00083     /* Create new int obj */
00084     return float_new(-((pPmFloat_t) pf)->val, r_pf);
00085 }
00086 
00087 #endif /* HAVE_PRINT */
00088 
00089 
00090 PmReturn_t
00091 float_op(pPmObj_t px, pPmObj_t py, pPmObj_t *r_pn, int8_t op)
00092 {
00093     float x;
00094     float y;
00095     float r;
00096     PmReturn_t retval;
00097 
00098     /* Raise TypeError if args aren't ints or floats */
00099     if (((OBJ_GET_TYPE(px) != OBJ_TYPE_INT)
00100          && (OBJ_GET_TYPE(px) != OBJ_TYPE_FLT))
00101         || ((OBJ_GET_TYPE(py) != OBJ_TYPE_INT)
00102             && (OBJ_GET_TYPE(py) != OBJ_TYPE_FLT)))
00103     {
00104         PM_RAISE(retval, PM_RET_EX_TYPE);
00105         return retval;
00106     }
00107 
00108     /* Get the values as floats */
00109     if (OBJ_GET_TYPE(px) == OBJ_TYPE_INT)
00110     {
00111         x = (float)((pPmInt_t)px)->val;
00112     }
00113     else
00114     {
00115         x = ((pPmFloat_t) px)->val;
00116     }
00117 
00118     if (OBJ_GET_TYPE(py) == OBJ_TYPE_INT)
00119     {
00120         y = (float)((pPmInt_t)py)->val;
00121     }
00122     else
00123     {
00124         y = ((pPmFloat_t) py)->val;
00125     }
00126 
00127     /* Raise ZeroDivisionError if denominator is zero */
00128     if ((y == 0.0) && ((op == '/') || (op == '%')))
00129     {
00130         PM_RAISE(retval, PM_RET_EX_ZDIV);
00131         return retval;
00132     }
00133 
00134     /* Calculate x raised to y */
00135     switch (op)
00136     {
00137         /* *INDENT-OFF* */
00138         case '+': r = x + y; break;
00139         case '-': r = x - y; break;
00140         case '*': r = x * y; break;
00141         case '/': r = x / y; break;
00142         case '%': r = fmodf(x, y); break;
00143         case 'P': r = powf(x, y); break;
00144         default: r = 0.0; break;
00145         /* *INDENT-ON* */
00146     }
00147 
00148     retval = float_new(r, r_pn);
00149 
00150     return retval;
00151 }
00152 
00153 PmReturn_t
00154 float_compare(pPmObj_t px, pPmObj_t py, pPmObj_t *r_pobj, PmCompare_t cmp)
00155 {
00156     float x;
00157     float y;
00158     PmReturn_t retval = PM_RET_OK;
00159     int8_t t8 = 0;
00160 
00161     /* Raise TypeError if args aren't ints or floats */
00162     if (((OBJ_GET_TYPE(px) != OBJ_TYPE_INT)
00163          && (OBJ_GET_TYPE(px) != OBJ_TYPE_FLT))
00164         || ((OBJ_GET_TYPE(py) != OBJ_TYPE_INT)
00165             && (OBJ_GET_TYPE(py) != OBJ_TYPE_FLT)))
00166     {
00167         PM_RAISE(retval, PM_RET_EX_TYPE);
00168         return retval;
00169     }
00170 
00171     /* Get the values as floats */
00172     if (OBJ_GET_TYPE(px) == OBJ_TYPE_INT)
00173     {
00174         x = (float)((pPmInt_t)px)->val;
00175     }
00176     else
00177     {
00178         x = ((pPmFloat_t) px)->val;
00179     }
00180 
00181     if (OBJ_GET_TYPE(py) == OBJ_TYPE_INT)
00182     {
00183         y = (float)((pPmInt_t)py)->val;
00184     }
00185     else
00186     {
00187         y = ((pPmFloat_t) py)->val;
00188     }
00189 
00190     switch (cmp)
00191     {
00192         /* *INDENT-OFF* */
00193         case COMP_LT: t8 = (int8_t)(x <  y); break;
00194         case COMP_LE: t8 = (int8_t)(x <= y); break;
00195         case COMP_EQ: t8 = (int8_t)(x == y); break;
00196         case COMP_NE: t8 = (int8_t)(x != y); break;
00197         case COMP_GT: t8 = (int8_t)(x >  y); break;
00198         case COMP_GE: t8 = (int8_t)(x >= y); break;
00199         case COMP_IS: t8 = (int8_t)(px == py); break;
00200         case COMP_IS_NOT: t8 = (int8_t)(px != py);break;
00201         case COMP_IN:
00202         case COMP_NOT_IN:
00203             PM_RAISE(retval, PM_RET_EX_TYPE);
00204             break;
00205 
00206         default:
00207             /* Other compares are not yet supported */
00208             PM_RAISE(retval, PM_RET_EX_SYS);
00209             break;
00210         /* *INDENT-ON* */
00211     }
00212     *r_pobj = (t8) ? PM_TRUE : PM_FALSE;
00213 
00214     return retval;
00215 }
00216 
00217 #endif /* HAVE_FLOAT */