proposed syntax change

Yigal Chripun yigal100 at gmail.com
Fri Aug 7 12:03:43 PDT 2009


Robert Jacques wrote:
> On Fri, 07 Aug 2009 01:22:31 -0700, Yigal Chripun <yigal100 at gmail.com> 
> wrote:
> 
>> Robert Jacques wrote:
>>> On Thu, 06 Aug 2009 13:34:21 -0700, Yigal Chripun 
>>> <yigal100 at gmail.com> wrote:
>>>
>>>> Ary Borenszweig wrote:
>>>>> Adam D. Ruppe wrote:
>>>>>> On Thu, Aug 06, 2009 at 03:06:49PM -0400, Paul D. Anderson wrote:
>>>>>>> Oh wait...I think "//" is used elsewhere.
>>>>>>
>>>>>> Is this a joke?
>>>>>  No. When porting C, C++, Java or C# code just search "//" and 
>>>>> replace it with "--".
>>>>>  Oh wait... I think "--" is used elsewhere.
>>>>
>>>> Why would I as a user want to have two ops that do the same thing?!
>>>> Python's solution for this is wrong IMHO since the problem is not 
>>>> with the op itself but rather with the way C handles numbers.
>>>>
>>>> 5 / 2 should always be the more precise FP division unless the 
>>>> compiler knows or is instructed to do otherwise.
>>>>
>>>> int a = 5 / 2; // compiler knows to use integer division
>>>  No, it doesn't. (i.e. Welcome to the limitations of a context-free 
>>> grammar) The right hand of the expression has to be evaluated before 
>>> the left, or otherwise function overloads, etc, don't work, so 
>>> there's no way for the compiler to know the type of the expected 
>>> result when 5/2 is evaluated.
>>>
>>>> auto b = 5 / 2; // b is double, FP division
>>>>
>>>> auto c = cast(int)(5/2)); // compiler instructed to use integer 
>>>> division
>>>  No, the cast would apply to the result of (5/2), not the '/' operator.
>>>
>>>> auto d = floor(5 / 2); // FP division floored by a function to int
>>>  floor returns a real, not an int. I think you were looking for 
>>> roundTo!int or roundTo!int(floor(5/2))
>>>
>>>> auto f = std.math.div(5, 2); // intristic that does integer division
>>>>
>>>> what's the rationale of not doing the above, besides C compatibility?
>>>  The rationale is that integer division is very common and is usually 
>>> assigned back into an int, and not a real. The only issue is 
>>> literals, which were going to be handled with polysemous values (but 
>>> that got dropped). But 2/5.0 is really not that much overhead.
>>
>> As you noted yourself, polysemous types help solve this and also the 
>> compiler can have special handling (peep hole optimizations) for some 
>> of the above cases.
>> in case D roundTo sounds indeed better (and since in the above it's 
>> compile time, it should be possible to optimize it.
>>
>> you've ignored case f which seems to me the most important: instead of 
>> currently 5/2 == 2 there should be a div intristic function such that 
>> div(5, 2) == 2  and that intristic will be the appropriate ASM 
>> instruction for integer division.
> 
> No, I didn't. I just didn't have anything to say.
> 
>> In general, you can always round down a float but you can't get the 
>> correct double out of the rounded int, so my question is how much a 
>> performance hit is it to use the FP as default and only use the div 
>> intristic where performance is really an issue?
> 
> Now that I think about it, turning integer division into a function is a 
> really bad idea: 1) there's function call overhead and 2) even if 
> inlined, register values and the stack still have to be manipulated (as 
> function call syntax dictates where the inputs and outputs are located) 
> Today, DMD can choose any set of register inputs and outputs.
> 
> As for the int-float conversion, apperently float-int is somewhat slow 
> and destroys the floating point pipeline
>  From http://mega-nerd.com/FPcast/
>> The instruction which causes the real damage in this block is fldcw, 
>> (FPU load control word) on lines 8 and 11. Whenever the FPU encounters 
>> this instruction it flushes its pipeline and loads the control word 
>> before continuing operation. The FPUs of modern CPUs like the Pentium 
>> III, Pentium IV and AMD Athlons rely on deep pipelines to achieve 
>> higher peak performance. Unfortunately certain pieces of C code can 
>> reduce the floating point performance of the CPU to level of a 
>> non-pipelined FPU.
> 
>> So why is the fldcw instruction used? Unfortunately, it is required to 
>> make the calculation meet the ISO C Standard which specifies that 
>> casting from floating point to integer is a truncation operation. 
>> However, if the fistpl instruction was executed without changing the 
>> mode of the FPU, the value would have been rounded instead of 
>> truncated. The standard rounding mode is required for all normal 
>> operations like addition, subtraction, multiplication etc while 
>> truncation mode is required for the float to int cast. Hence if a 
>> block of code contains a float to int cast, the FPU will spend a large 
>> amount of its time switching between the two modes.

Thanks for the info about the cast.

regarding the div() function above, I was thinking about using D's naked 
asm feature. From what little I know about this, the compiler doesn't 
generate the usual asm code for this sort of function to handle 
registers, stack, etc, and you're supposed to do everything yourself in 
asm.
I don't think your comment above about the function call overhead 
applies if div is implemented in such a way but I'm no expert and 
someone more knowledgeable can shed more light on this. (Don?)

also, div can be implemented in the compiler in the same way c++ style 
casts have template syntax ( e.g. static_cast<whatever>(thing) ) but are 
  implemented inside the compiler.



More information about the Digitalmars-d mailing list