summaryrefslogtreecommitdiffstats
path: root/Objects/floatobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/floatobject.c')
-rw-r--r--Objects/floatobject.c240
1 files changed, 240 insertions, 0 deletions
diff --git a/Objects/floatobject.c b/Objects/floatobject.c
new file mode 100644
index 0000000..f176333
--- /dev/null
+++ b/Objects/floatobject.c
@@ -0,0 +1,240 @@
+/* Float object implementation */
+
+#include <stdio.h>
+#include <math.h>
+#include <ctype.h>
+
+#include "PROTO.h"
+#include "object.h"
+#include "floatobject.h"
+#include "stringobject.h"
+#include "objimpl.h"
+
+object *
+newfloatobject(fval)
+ double fval;
+{
+ /* For efficiency, this code is copied from newobject() */
+ register floatobject *op = (floatobject *) malloc(sizeof(floatobject));
+ if (op == NULL) {
+ errno = ENOMEM;
+ }
+ else {
+ NEWREF(op);
+ op->ob_type = &Floattype;
+ op->ob_fval = fval;
+ }
+ return (object *) op;
+}
+
+double
+getfloatvalue(op)
+ object *op;
+{
+ if (!is_floatobject(op)) {
+ errno = EBADF;
+ return -1;
+ }
+ else
+ return ((floatobject *)op) -> ob_fval;
+}
+
+/* Methods */
+
+static void
+float_buf_repr(buf, v)
+ char *buf;
+ floatobject *v;
+{
+ register char *cp;
+ /* Subroutine for float_repr and float_print.
+ We want float numbers to be recognizable as such,
+ i.e., they should contain a decimal point or an exponent.
+ However, %g may print the number as an integer;
+ in such cases, we append ".0" to the string. */
+ sprintf(buf, "%.12g", v->ob_fval);
+ cp = buf;
+ if (*cp == '-')
+ cp++;
+ for (; *cp != '\0'; cp++) {
+ /* Any non-digit means it's not an integer;
+ this takes care of NAN and INF as well. */
+ if (!isdigit(*cp))
+ break;
+ }
+ if (*cp == '\0') {
+ *cp++ = '.';
+ *cp++ = '0';
+ *cp++ = '\0';
+ }
+}
+
+static void
+float_print(v, fp, flags)
+ floatobject *v;
+ FILE *fp;
+ int flags;
+{
+ char buf[100];
+ float_buf_repr(buf, v);
+ fputs(buf, fp);
+}
+
+static object *
+float_repr(v)
+ floatobject *v;
+{
+ char buf[100];
+ float_buf_repr(buf, v);
+ return newstringobject(buf);
+}
+
+static int
+float_compare(v, w)
+ floatobject *v, *w;
+{
+ double i = v->ob_fval;
+ double j = w->ob_fval;
+ return (i < j) ? -1 : (i > j) ? 1 : 0;
+}
+
+static object *
+float_add(v, w)
+ floatobject *v;
+ object *w;
+{
+ if (!is_floatobject(w)) {
+ errno = EINVAL;
+ return NULL;
+ }
+ return newfloatobject(v->ob_fval + ((floatobject *)w) -> ob_fval);
+}
+
+static object *
+float_sub(v, w)
+ floatobject *v;
+ object *w;
+{
+ if (!is_floatobject(w)) {
+ errno = EINVAL;
+ return NULL;
+ }
+ return newfloatobject(v->ob_fval - ((floatobject *)w) -> ob_fval);
+}
+
+static object *
+float_mul(v, w)
+ floatobject *v;
+ object *w;
+{
+ if (!is_floatobject(w)) {
+ errno = EINVAL;
+ return NULL;
+ }
+ return newfloatobject(v->ob_fval * ((floatobject *)w) -> ob_fval);
+}
+
+static object *
+float_div(v, w)
+ floatobject *v;
+ object *w;
+{
+ if (!is_floatobject(w)) {
+ errno = EINVAL;
+ return NULL;
+ }
+ if (((floatobject *)w) -> ob_fval == 0) {
+ errno = EDOM;
+ return NULL;
+ }
+ return newfloatobject(v->ob_fval / ((floatobject *)w) -> ob_fval);
+}
+
+static object *
+float_rem(v, w)
+ floatobject *v;
+ object *w;
+{
+ double wx;
+ extern double fmod();
+ if (!is_floatobject(w)) {
+ errno = EINVAL;
+ return NULL;
+ }
+ wx = ((floatobject *)w) -> ob_fval;
+ if (wx == 0.0) {
+ errno = EDOM;
+ return NULL;
+ }
+ return newfloatobject(fmod(v->ob_fval, wx));
+}
+
+static object *
+float_pow(v, w)
+ floatobject *v;
+ object *w;
+{
+ double iv, iw, ix;
+ extern double pow();
+ if (!is_floatobject(w)) {
+ errno = EINVAL;
+ return NULL;
+ }
+ iv = v->ob_fval;
+ iw = ((floatobject *)w)->ob_fval;
+ errno = 0;
+ ix = pow(iv, iw);
+ if (errno != 0)
+ return NULL;
+ else
+ return newfloatobject(ix);
+}
+
+static object *
+float_neg(v)
+ floatobject *v;
+{
+ return newfloatobject(-v->ob_fval);
+}
+
+static object *
+float_pos(v)
+ floatobject *v;
+{
+ return newfloatobject(v->ob_fval);
+}
+
+static number_methods float_as_number = {
+ float_add, /*tp_add*/
+ float_sub, /*tp_subtract*/
+ float_mul, /*tp_multiply*/
+ float_div, /*tp_divide*/
+ float_rem, /*tp_remainder*/
+ float_pow, /*tp_power*/
+ float_neg, /*tp_negate*/
+ float_pos, /*tp_plus*/
+};
+
+typeobject Floattype = {
+ OB_HEAD_INIT(&Typetype)
+ 0,
+ "float",
+ sizeof(floatobject),
+ 0,
+ free, /*tp_dealloc*/
+ float_print, /*tp_print*/
+ 0, /*tp_getattr*/
+ 0, /*tp_setattr*/
+ float_compare, /*tp_compare*/
+ float_repr, /*tp_repr*/
+ &float_as_number, /*tp_as_number*/
+ 0, /*tp_as_sequence*/
+ 0, /*tp_as_mapping*/
+};
+
+/*
+XXX This is not enough. Need:
+- automatic casts for mixed arithmetic (3.1 * 4)
+- mixed comparisons (!)
+- look at other uses of ints that could be extended to floats
+*/