What is the equivalent of CGFloat.leastNonzeroMagnitude
equivalent in Objective-C?
I googled but could not find any answer.
CodePudding user response:
Note that the documentation of leastNonzeroMagnitude
says:
Compares less than or equal to all positive numbers, but greater than zero. If the target supports subnormal values, this is smaller than
leastNormalMagnitude
; otherwise they are equal.
So the value of this also depends on "if the target supports subnormal values". Looking at the implementation, we can see:
public static var leastNonzeroMagnitude: ${Self} {
#if arch(arm)
// On 32b arm, the default FPCR has subnormals flushed to zero.
return leastNormalMagnitude
#else
return leastNormalMagnitude * ulpOfOne
#endif
}
It turns out that ARM is the target that doesn't "support subnormal values". :)
If you translate the two branches into Objective-C separately, it would be:
CGFLOAT_MIN
and
CGFLOAT_MIN * CGFLOAT_EPSILON
CodePudding user response:
Apple doesn't provide an Objective-C constant equivalent to CGFloat.leastNonzeroMagnitude
.
Apple does provide CGFLOAT_MIN
, which is the smallest positive normal nonzero value. It's equivalent to CGFloat.leastNormalMagnitude
. This is 2.225073858507201e-308 on systems with 64-bit CGFloat
.
There are constants (specified by the C11 standard) for the smallest positive non-zero float
and double
, including subnormals: FLT_TRUE_MIN
is 1.401298e-45 and DBL_TRUE_MIN
is 4.940656458412465e-324.
Apple provides a constant CGFLOAT_IS_DOUBLE
which is 1 if CGFloat
is double
and zero if it is float
. So you can check that to define your own CGFLOAT_TRUE_MIN
. You should also guard against Apple adding its own definition in the future.
#ifndef CGFLOAT_TRUE_MIN
#if CGFLOAT_IS_DOUBLE
#define CGFLOAT_TRUE_MIN DBL_TRUE_MIN
#else
#define CGFLOAT_TRUE_MIN FLT_TRUE_MIN
#endif
#endif
But the only supported platform that still uses 32-bit CGFloat
is watchOS, and its unlikely that you're targeting watchOS if you're using Objective-C. If you are only targeting 64-bit versions of iOS/macOS/tvOS, you can simplify the definition:
#ifndef CGFLOAT_TRUE_MIN
#define CGFLOAT_TRUE_MIN DBL_TRUE_MIN
#endif