11

Question

Consider layout code like this:

CGFloat descriptionHeight = // height of a paragraph of text with zero or more words;
CGFloat imageHeight = // height of an image;
CGFloat yCoordinateOfSomeOtherView = fmax(descriptionHeight, imageHeight) + 5.0f;

How should the third line be rewritten with support for 64-bit iOS devices?

(The current code doesn't take into account whether yCoordinateOfSomeOtherView is a float or a double.)

Options

A few options (I'm not sure which is best):

1. Define my own macro

#if defined(__LP64__) && __LP64__
#define cgfmax(x,y) fmaxf(x,y)
#else
#define cgfmax(x,y) fmax(x,y)
#endif

I could then replace fmax with cgfmax.

2. Use tgmath.h

This Stack Overflow answer from 2011 suggests replacing math.h with tgmath.h. This replaces the implementation of fmax with one that calls __typeof__ on each argument and returns either fmax or fmaxf depending on the argument types.

3. Ignore this issue

Since CGFloats relate to layout, the data loss potentially incurred storing a float into a double will usually be insignificant. That is, they'll represent tiny fractions of pixels.

Summary

I'm looking for any other options or helpful advice from someone who's done a 32-bit to 64-bit transition before.

Community
  • 1
  • 1
Aaron Brager
  • 65,323
  • 19
  • 161
  • 287
  • 1
    Yeah, layout stuff doesn't really hit the 32-bit limit. So it probably won't be a problem, but its fun to do the mental exercise for future reference. – David Wong Oct 21 '13 at 23:07

1 Answers1

6

There is never any "data loss" incurred when converting a float into a double. That conversion is always exact.

Your solutions 1 & 2 are entirely equivalent semantically, though (2) is more stylistically correct.

Your solution 3 is formally not equivalent; it may incur extra conversions between float and double, which may make it slightly less efficient (but the actual result is identical).

Basically, it doesn't matter, but use tgmath.

Stephen Canon
  • 103,815
  • 19
  • 183
  • 269
  • Sorry, I meant the other way around. (By "data loss", I mean the truncation of 64-bit values when they are assigned to a 32-bit type.) That is, two `double`s would go into `fmax`, and a `float` would come out. – Aaron Brager Oct 21 '13 at 23:27
  • @AaronBrager: Sure, but in your case you know that the arguments to `fmax` were originally `CGFloat`s, which means that their maximum (the return value) is exactly representable as a `CGFloat`, so there can be no rounding. The result is still exact. – Stephen Canon Oct 21 '13 at 23:36
  • Yeah, I wouldn't worry about it (I'd personally just use `fmax`, etc.) unless you measure a real performance issue. – Wevah Oct 21 '13 at 23:41
  • @StephenCanon To clarify I understand you correctly: the result is still exact because the implementation of `fmax` doesn't assign anything; it just returns one of its two arguments. But if the implementation of `fmax` assigned the value to a new `float` and then returned this variable, there could be truncation. Is that correct? – Aaron Brager Oct 21 '13 at 23:47
  • @AaronBrager no truncation occurs because the value of the result is guaranteed to be exactly representable as a CGFloat. Assignment doesn't play into it. – Stephen Canon Oct 22 '13 at 00:37