Norimasa Okamoto
/
pymite
python-on-a-chip online compiler
Embed:
(wiki syntax)
Show/hide line numbers
int.c
Go to the documentation of this file.
00001 /* 00002 # This file is Copyright 2002 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__ 0x08 00011 00012 00013 /** 00014 * \file 00015 * \brief Integer Object Type 00016 * 00017 * Integer object type operations. 00018 */ 00019 00020 #include <limits.h> 00021 00022 #include "pm.h" 00023 00024 00025 PmReturn_t 00026 int_dup(pPmObj_t pint, pPmObj_t *r_pint) 00027 { 00028 PmReturn_t retval = PM_RET_OK; 00029 00030 /* Allocate new int */ 00031 retval = heap_getChunk(sizeof(PmInt_t), (uint8_t **)r_pint); 00032 PM_RETURN_IF_ERROR(retval); 00033 00034 /* Copy value */ 00035 OBJ_SET_TYPE(*r_pint, OBJ_TYPE_INT); 00036 ((pPmInt_t)*r_pint)->val = ((pPmInt_t)pint)->val; 00037 return retval; 00038 } 00039 00040 00041 PmReturn_t 00042 int_new(int32_t n, pPmObj_t *r_pint) 00043 { 00044 PmReturn_t retval = PM_RET_OK; 00045 00046 /* If n is 0,1,-1, return static int objects from global struct */ 00047 if (n == 0) 00048 { 00049 *r_pint = PM_ZERO; 00050 return PM_RET_OK; 00051 } 00052 if (n == 1) 00053 { 00054 *r_pint = PM_ONE; 00055 return PM_RET_OK; 00056 } 00057 if (n == -1) 00058 { 00059 *r_pint = PM_NEGONE; 00060 return PM_RET_OK; 00061 } 00062 00063 /* Else create and return new int obj */ 00064 retval = heap_getChunk(sizeof(PmInt_t), (uint8_t **)r_pint); 00065 PM_RETURN_IF_ERROR(retval); 00066 OBJ_SET_TYPE(*r_pint, OBJ_TYPE_INT); 00067 ((pPmInt_t)*r_pint)->val = n; 00068 return retval; 00069 } 00070 00071 00072 PmReturn_t 00073 int_positive(pPmObj_t pobj, pPmObj_t *r_pint) 00074 { 00075 PmReturn_t retval; 00076 00077 /* Raise TypeError if obj is not an int */ 00078 if (OBJ_GET_TYPE(pobj) != OBJ_TYPE_INT) 00079 { 00080 PM_RAISE(retval, PM_RET_EX_TYPE); 00081 return retval; 00082 } 00083 00084 /* Create new int obj */ 00085 return int_new(((pPmInt_t)pobj)->val, r_pint); 00086 } 00087 00088 00089 PmReturn_t 00090 int_negative(pPmObj_t pobj, pPmObj_t *r_pint) 00091 { 00092 PmReturn_t retval; 00093 00094 /* Raise TypeError if obj is not an int */ 00095 if (OBJ_GET_TYPE(pobj) != OBJ_TYPE_INT) 00096 { 00097 PM_RAISE(retval, PM_RET_EX_TYPE); 00098 return retval; 00099 } 00100 00101 /* Create new int obj */ 00102 return int_new(-((pPmInt_t)pobj)->val, r_pint); 00103 } 00104 00105 00106 PmReturn_t 00107 int_bitInvert(pPmObj_t pobj, pPmObj_t *r_pint) 00108 { 00109 PmReturn_t retval; 00110 00111 /* Raise TypeError if obj is not an int */ 00112 if (OBJ_GET_TYPE(pobj) != OBJ_TYPE_INT) 00113 { 00114 PM_RAISE(retval, PM_RET_EX_TYPE); 00115 return retval; 00116 } 00117 00118 /* Create new int obj */ 00119 return int_new(~((pPmInt_t)pobj)->val, r_pint); 00120 } 00121 00122 00123 PmReturn_t 00124 int_print(pPmObj_t pint) 00125 { 00126 PmReturn_t retval = PM_RET_OK; 00127 uint8_t buf[12]; 00128 00129 C_ASSERT(pint != C_NULL); 00130 00131 /* Raise TypeError if obj is not an int */ 00132 if (OBJ_GET_TYPE(pint) != OBJ_TYPE_INT) 00133 { 00134 PM_RAISE(retval, PM_RET_EX_TYPE); 00135 return retval; 00136 } 00137 00138 retval = sli_ltoa10(((pPmInt_t)pint)->val, buf, sizeof(buf)); 00139 PM_RETURN_IF_ERROR(retval); 00140 sli_puts(buf); 00141 00142 return retval; 00143 } 00144 00145 00146 PmReturn_t 00147 int_printHex(pPmObj_t pint) 00148 { 00149 uint8_t buf[9]; 00150 PmReturn_t retval = PM_RET_OK; 00151 00152 C_ASSERT(OBJ_GET_TYPE(pint) == OBJ_TYPE_INT); 00153 00154 /* Print the integer object */ 00155 retval = sli_ltoa16(((pPmInt_t)pint)->val, buf, sizeof(buf), 1); 00156 sli_puts(buf); 00157 return retval; 00158 } 00159 00160 00161 PmReturn_t 00162 int_pow(pPmObj_t px, pPmObj_t py, pPmObj_t *r_pn) 00163 { 00164 int32_t x; 00165 int32_t y; 00166 int32_t n; 00167 PmReturn_t retval; 00168 00169 /* Raise TypeError if args aren't ints */ 00170 if ((OBJ_GET_TYPE(px) != OBJ_TYPE_INT) 00171 || (OBJ_GET_TYPE(py) != OBJ_TYPE_INT)) 00172 { 00173 PM_RAISE(retval, PM_RET_EX_TYPE); 00174 return retval; 00175 } 00176 00177 x = ((pPmInt_t)px)->val; 00178 y = ((pPmInt_t)py)->val; 00179 00180 /* Raise Value error if exponent is negative */ 00181 if (y < 0) 00182 { 00183 PM_RAISE(retval, PM_RET_EX_VAL); 00184 return retval; 00185 } 00186 00187 /* Calculate x raised to y */ 00188 n = 1; 00189 while (y > 0) 00190 { 00191 n = n * x; 00192 y--; 00193 } 00194 retval = int_new(n, r_pn); 00195 00196 return retval; 00197 } 00198 00199 00200 PmReturn_t 00201 int_divmod(pPmObj_t px, pPmObj_t py, uint8_t op, pPmObj_t *r_pxopy) 00202 { 00203 int32_t x; 00204 int32_t y; 00205 int32_t xdivy; 00206 int32_t xmody; 00207 int32_t xopy; 00208 PmReturn_t retval = PM_RET_OK; 00209 00210 /* Raise TypeError if args aren't ints */ 00211 if ((OBJ_GET_TYPE(px) != OBJ_TYPE_INT) 00212 || (OBJ_GET_TYPE(py) != OBJ_TYPE_INT)) 00213 { 00214 PM_RAISE(retval, PM_RET_EX_TYPE); 00215 return retval; 00216 } 00217 00218 x = ((pPmInt_t)px)->val; 00219 y = ((pPmInt_t)py)->val; 00220 00221 /* Raise ZeroDivisionError if denominator is zero */ 00222 if (y == 0) 00223 { 00224 PM_RAISE(retval, PM_RET_EX_ZDIV); 00225 return retval; 00226 } 00227 00228 /* Issue #167: Make overflow silent until exceptions can be caught */ 00229 /* (-sys.maxint-1)/-1 is the only overflow case. */ 00230 /* TODO: enable the overflow for Issue #169 */ 00231 /* 00232 if ((y == -1) && (op == '/') && (x < 0) 00233 && ((uint32_t)x == (0 - (uint32_t)x))) 00234 { 00235 PM_RAISE(retval, PM_RET_EX_OFLOW); 00236 return retval; 00237 } 00238 */ 00239 00240 /* Shortcut when denominator is one or negative one */ 00241 if (y == 1) 00242 { 00243 xdivy = x; 00244 xmody = 0; 00245 } 00246 else if (y == -1) 00247 { 00248 xdivy = -x; 00249 xmody = 0; 00250 } 00251 00252 else 00253 { 00254 xdivy = x / y; 00255 xmody = x - xdivy * y; 00256 00257 /* 00258 * If the remainder is non-0 and the signs of x and y differ, 00259 * C89 doesn't define whether xdivy is now the floor or the 00260 * ceiling of the infinitely precise quotient. We want the floor, 00261 * and we have it iff the remainder's sign matches y's. 00262 */ 00263 if ((xmody != 0) && ((y ^ xmody) < 0)) 00264 { 00265 xmody += y; 00266 --xdivy; 00267 C_ASSERT(xmody && ((y ^ xmody) >= 0)); 00268 } 00269 } 00270 xopy = (op == '/') ? xdivy : xmody; 00271 return int_new(xopy, r_pxopy); 00272 }
Generated on Tue Jul 12 2022 23:13:47 by 1.7.2