www.digitalmars.com         C & C++   DMDScript  

D - float -> double conversion

reply "Walter" <walter digitalmars.com> writes:
In C, floats passed as a variant function argument get promoted to doubles.
This is an artifact of how the PDP-11 floating point hardware worked, and
has become thoroughly ingrained into C ever since. Should D break this? The
advantage is that it saves a bit of space and time. The options are:

1) Just leave it the C way.
2) Pass them as floats - this will require a new float format for printf.
May 03 2002
next sibling parent reply Jonathan Andrew <jon ece.arizona.edu> writes:
Walter wrote:

 In C, floats passed as a variant function argument get promoted to doubles.
 This is an artifact of how the PDP-11 floating point hardware worked, and
 has become thoroughly ingrained into C ever since. Should D break this? The
 advantage is that it saves a bit of space and time. The options are:
 
 1) Just leave it the C way.
 2) Pass them as floats - this will require a new float format for printf.
 
 
 

Yes! Break it, I think leaving it as-is breaks the philosophy of "arbitrary, obscure, and forgettable rules in ambiguous cases" ;) -Jon
May 03 2002
parent "Pavel Minayev" <evilone omen.ru> writes:
"Jonathan Andrew" <jon ece.arizona.edu> wrote in message
news:3CD34661.3000304 ece.arizona.edu...

 Yes! Break it, I think leaving it as-is breaks the philosophy of
 "arbitrary, obscure, and forgettable rules in ambiguous cases" ;)

What about short->int then? It should be forbidden as well... but why? I mean, it doesn't hurt after all, no data loss occurs, and you don't have to remember all the specifiers. ints are %d. floats are %f. By the way, there is another idea. Convert byte, short, int -> long, and float, double -> extended. After doing that, there is no longer need in %Ld and %Lf.
May 03 2002
prev sibling parent reply Burton Radons <loth users.sourceforge.net> writes:
On Fri, 3 May 2002 17:13:09 -0700, "Walter" <walter digitalmars.com>
wrote:

In C, floats passed as a variant function argument get promoted to doubles.
This is an artifact of how the PDP-11 floating point hardware worked, and
has become thoroughly ingrained into C ever since. Should D break this? The
advantage is that it saves a bit of space and time. The options are:

1) Just leave it the C way.
2) Pass them as floats - this will require a new float format for printf.

C varargs should be as simple to parse as possible; they're already unwieldy enough as it is, and printf formatting emphatically does not need extra complications. Particularly to save a couple bytes on functions that are only rarely recursed. I think the opposite route should be taken: varargs should be refined so that they have an associated object that allows the caller to abstractly retrieve arguments. For example, with something like: wchar[] fmt(wchar[] format, args...); Where args is an instance of: class Varargs { int length (); /* Number of arguments */ Type type (int index); /* Get the runtime type of an argument */ bit get (int index, out $type value); /* Try to get a single value, converting if possible */ /* Without generics... */ bit get_int (int index, out int value); ... } Then min could be generically written as: $type min ($type a, args...) { $type n; int c; for (c = 0; c < args.length; c ++) { if (!args.get (c, n)) throw new Error ("incompatible types in min"); if (n < a) a = n; } return a; } Although it would of course be better to have a couple specific argument counts first in lieu of a very intelligent compiler. Take the code I use to get extended from the C varargs stream: value = *(extended*) args; args += (extended.size + 3) & ~3; Beautiful, no? With a varargs object I could just ask for an extended from the stream and get it (if possible), no problems. It could even be a float as passed, or an int, or a byte, but I'll still get my extended. We wouldn't even need "%lg" any more (or the 'l' flag at all) or think through complex; just always use complex internally, always use wchar, always use long/ulong, with a clean handling of cent/ucent later.
May 04 2002
parent Burton Radons <loth users.sourceforge.net> writes:
On Sat, 04 May 2002 03:09:06 -0700, Burton Radons
<loth users.sourceforge.net> wrote:

[snip]
I think the opposite route should be taken: varargs should be refined
so that they have an associated object that allows the caller to
abstractly retrieve arguments.  For example, with something like:

    wchar[] fmt(wchar[] format, args...);

Where args is an instance of:

    class Varargs
    {
        int length (); /* Number of arguments */
        Type type (int index); /* Get the runtime type of an argument
*/
        bit get (int index, out $type value); /* Try to get a single
value, converting if possible */
    
        /* Without generics... */
        bit get_int (int index, out int value);
        ...
    }

To further extend this issue, varargs are just a part of the argument construction and destruction that you have to do for automated script interfacing. Let's say that we made it generic; "class Arguments" instead of Varargs. This is immutable in this case but a subclass, "class ArgumentsBuilder : Arguments" would be mutable and take a "void add ($type value);" method, among others. The constructor for that would also take the calling convention as an argument. Say that you want to call a D function from Python. First you export it: void qbert (int a, float b); ... PyExport (qbert.type); Then to call it you start building the arguments: PyObject *tuple = from function call; ArgumentsBuilder args; FunctionInfo func = retrieved from our proxy function object; int intValue; int c; /* Function overloading could be handled with some effort... */ if (func.args.length != PyTuple_Size (tuple)) /* Error */ args = new DArgumentsBuilder (func.convention); for (c = 0; c < func.args.length; c ++) { FunctionArgumentInfo arg = func.args [c]; PyObject *tuple_arg; /* Check argument parameters, bail if dimensions are weird */ tuple_arg = PyTuple_GET_ITEM (tuple, c); switch (arg.basetype) { case BaseType.Int: intValue = PyInt_AsLong (tuple_arg); if (PyErr_Occurred ()) /* Error, not convertable */ args.add ((int) intValue); break; /* ... */ } } /* Check return parameters and dimensions */ switch (func.returnType.basetype) { case BaseType.Int: case BaseType.Long: args.call (func.pointer, intValue); return PyInt_FromLong (intValue); } It's still a lot of code to support it properly, but it offloads all the nonportable concerns and is a hell of a lot simpler than asm code I've seen for dispatch (which this may degenerate into internally... none of my beeswax), and it could support a great variety of operations automatically. This could be made even easier by taking a subclass of ArgumentsBuilder that instead takes a FunctionInfo as a construction argument, and automatically casts as you add arguments to it. This would greatly lessen the number of cases above as Python only has two integer types. The object ownership issue is another thing entirely. I suspect you would have to construct proxy structs that reference our objects, and are thus included in the GC and also in Python. It's tricky stuff. To support the other direction, calling Python from D, you would have to be able to get the "Arguments" instance of the current function. Failing that you could just do: /* Takes int, float, char[] */ int python_function_to_call (args...) { int value; PyDispatch ("python_function_to_call", args, value); return value; } Things get more complicated when you try to subclass D classes in Python. Calling D superclass methods is not a problem, but getting D to call Python automatically. I can't think through any easy solution right now.
May 04 2002