this repo has no description
1/*
2 * Copyright (c) 2002 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22/*******************************************************************************
23* *
24* File tableExpD.c, *
25* Functions exp, exp2 and expm1. *
26* Implementation of exp(x) based on IBM/Taligent table method. *
27* *
28* Copyright � 1997-2001 Apple Computer, Inc. All rights reserved. *
29* *
30* Written by Ali Sazegari, started on April 1997. *
31* Modified and ported by Robert A. Murley (ram) for Mac OS X. *
32* *
33* A MathLib v4 file. *
34* *
35* November 07 2001: removed exp2 to prevent conflict with CarbonCore. *
36* November 06 2001: commented out warning about Intel architectures. *
37* changed i386 stub to call abort(). *
38* November 02 2001: added stub for i386 version of exp2. *
39* April 28 1997: port of the ibm/taligent exp routines. *
40* July 16 1997: changed the rounding direction sensitivity of *
41* delivered results to default rounding at all times. *
42* August 28 2001: replaced __setflm with FEGETENVD/FESETENVD. *
43* replaced DblInHex typedef with hexdouble. *
44* used standard exception symbols from fenv.h. *
45* added #ifdef __ppc__. *
46* September 09 2001: added more comments. *
47* September 10 2001: added macros to detect PowerPC and correct compiler. *
48* September 18 2001: added <CoreServices/CoreServices.h> to get <fenv.h>. *
49* October 08 2001: removed <CoreServices/CoreServices.h>. *
50* changed compiler errors to warnings. *
51* *
52* W A R N I N G: *
53* These routines require a 64-bit double precision IEEE-754 model. *
54* They are written for PowerPC only and are expecting the compiler *
55* to generate the correct sequence of multiply-add fused instructions. *
56* *
57* These routines are not intended for 32-bit Intel architectures. *
58* *
59* A version of gcc higher than 932 is required. *
60* *
61* GCC compiler options: *
62* optimization level 3 (-O3) *
63* -fschedule-insns -finline-functions -funroll-all-loops *
64* *
65*******************************************************************************/
66
67#include "math.h"
68#include "fenv_private.h"
69#include "fp_private.h"
70
71/*******************************************************************************
72* Floating-point constants. *
73*******************************************************************************/
74
75static const double rintFactor = 6.7553994410557440000e+15; /* 0x43380000, 0x00000000 */
76static const double oneOverLn2 = 1.4426950408889633000e+00; /* 0x3ff71547, 0x652b82fe */
77static const double ln2Head = 6.9314718055994530000e-01; /* 0x3fe62e42, 0xfefa39ef */
78static const double ln2Tail = 2.3190468138462996000e-17; /* 0x3c7abc9e, 0x3b39803f */
79static const double maxExp = 7.0978271289338397000e+02; /* 0x40862e42, 0xfefa39ef */
80static const double denormal = 2.9387358770557188000e-39; /* 0x37f00000, 0x00000000 */
81static const hexdouble infinity = HEXDOUBLE(0x7ff00000, 0x00000000);
82
83/*******************************************************************************
84* Approximation coefficients. *
85*******************************************************************************/
86
87static const double cm1 = 8.3333336309523691e-03; /* 0x3f811111,0x1b4af38e */
88static const double c0 = 4.1666668402777808000e-02; /* 0x3fa55555,0x643f1505 */
89static const double c1 = 1.6666666666666655000e-01; /* 0x3fc55555,0x55555551 */
90static const double c2 = 4.9999999999999955000e-01; /* 0x3fdfffff,0xfffffff8 */
91
92extern const uint32_t expTable[];
93
94struct expTableEntry
95 {
96 double x;
97 double f;
98 };
99
100static const double kMinNormal = 0x1.0p-1022; // 2.2250738585072014e-308;
101static const double kMaxNormal = 1.7976931348623157e308;
102
103#if !defined(BUILDING_FOR_CARBONCORE_LEGACY)
104/*******************************************************************************
105* Floating-point constants. *
106*******************************************************************************/
107static const double minExp = -7.4513321910194122000e+02; /* 0xc0874910, 0xd52d3052 */
108static const double oneOverDenorm = 3.402823669209384635e+38; /* 0x47f00000, 0x00000000 */
109
110/*******************************************************************************
111* Approximation coefficients. *
112*******************************************************************************/
113
114static const double cc4 = 0.5000000000000000000;
115static const double cc3 = 0.16666666666663809522820;
116static const double cc2 = 0.04166666666666111110939;
117static const double cc1 = 0.008333338095239329810170;
118static const double cc0 = 0.001388889583333492938381;
119
120/*******************************************************************************
121* *
122* The base e exponential function. *
123* *
124********************************************************************************
125* *
126* Raised exceptions are inexact, overflow & inexact and underflow & inexact.*
127* *
128*******************************************************************************/
129
130double exp ( double x )
131{
132 hexdouble scale, xInHex, yInHex;
133 register double d, y, yTail, z, zTail, z2, temp1, temp2, power, result;
134 register int32_t i;
135 register struct expTableEntry *tablePointer, *pT;
136
137 register double FPR_oneOverLn2, FPR_rintFactor, FPR_ln2Head, FPR_ln2Tail, FPR_h, FPR_z, FPR_512, FPR_scale;
138 register double FPR_env, FPR_x, FPR_f, FPR_cm1, FPR_c0, FPR_c1, FPR_c2;
139
140 FPR_x = __FABS( x );
141
142 FPR_z = 0.0; FPR_512 = 512.0;
143 FPR_oneOverLn2 = oneOverLn2; FPR_rintFactor = rintFactor;
144 FPR_ln2Head = ln2Head; FPR_ln2Tail = ln2Tail;
145 tablePointer = ( struct expTableEntry * ) expTable + 177;
146
147 FEGETENVD ( FPR_env ); // save old environment, set default
148 __ENSURE( FPR_z, FPR_512, FPR_oneOverLn2 ); __ENSURE( FPR_ln2Head, FPR_ln2Tail, FPR_rintFactor );
149 FESETENVD ( FPR_z );
150
151 // Compute FPR_h and store it to yInHex as early as possible, even for cases that don't need it
152 FPR_h = __FMADD( x, FPR_oneOverLn2, FPR_rintFactor );
153 yInHex.d = FPR_h;
154 FPR_h -= FPR_rintFactor;
155
156 if (likely( FPR_x < FPR_512 ))
157 {
158 if (likely( x != FPR_z ))
159 {
160
161 scale.i.hi = ( yInHex.i.lo + 1023 ) << 20; scale.i.lo = 0;
162
163 y = __FNMSUB( FPR_ln2Head, FPR_h, x ); yTail = __FMUL( FPR_ln2Tail, FPR_h );
164
165 xInHex.d = __FMADD( FPR_512, y, FPR_rintFactor );
166
167 __NOOP;
168 __NOOP;
169 __NOOP;
170 i = xInHex.i.lo;
171
172 pT = &(tablePointer[i]);
173
174 FPR_x = pT->x; FPR_f = pT->f;
175
176 d = y - FPR_x;
177
178 z = d - yTail;
179 FPR_cm1 = cm1; FPR_c1 = c1;
180 FPR_c0 = c0; FPR_c2 = c2;
181
182 z2 = __FMUL( z, z ); zTail = d - z - yTail;
183
184 temp1 = __FMADD( FPR_cm1, z2, FPR_c1 ); temp2 = __FMADD( FPR_c0, z2, FPR_c2 );
185
186 temp1 = __FMADD( temp1, z, temp2 );
187 FPR_scale = scale.d;
188
189 temp2 = __FMADD( temp1, z2, z );
190
191 temp1 = __FMADD( zTail, temp2, zTail ); result = __FMUL( FPR_scale, FPR_f );
192
193 temp1 = temp1 + temp2;
194
195 result = __FMADD( result, temp1, result );
196
197 FESETENVD ( FPR_env );
198 __PROG_INEXACT( FPR_cm1 );
199 return result;
200 }
201 else
202 {
203 FESETENVD ( FPR_env );
204 return 1.0;
205 }
206 }
207
208 if (likely( ( x <= maxExp ) && ( x > minExp ) ))
209 {
210 if ( x >= FPR_512 )
211 {
212 power = 2.0;
213 scale.i.hi = ( yInHex.i.lo + 1022 ) << 20; scale.i.lo = 0;
214 }
215 else
216 {
217 power = denormal;
218 scale.i.hi = ( yInHex.i.lo + 1023+128 ) << 20; scale.i.lo = 0;
219 }
220
221 y = __FNMSUB( FPR_ln2Head, FPR_h, x ); yTail = __FMUL( FPR_ln2Tail, FPR_h );
222 FPR_scale = scale.d;
223
224 xInHex.d = __FMADD( FPR_512, y, FPR_rintFactor );
225
226 __NOOP;
227 __NOOP;
228 __NOOP;
229 i = xInHex.i.lo;
230
231 pT = &(tablePointer[i]);
232
233 FPR_x = pT->x; FPR_f = pT->f;
234
235 d = y - FPR_x; result = __FMUL( FPR_scale, FPR_f );
236
237 z = d - yTail;
238 FPR_cm1 = cm1; FPR_c1 = c1;
239 FPR_c0 = c0; FPR_c2 = c2;
240
241 z2 = __FMUL( z, z ); zTail = d - z - yTail;
242
243 temp1 = __FMADD( FPR_cm1, z2, FPR_c1 ); temp2 = __FMADD( FPR_c0, z2, FPR_c2 );
244
245 temp1 = __FMADD( temp1, z, temp2 );
246
247 temp2 = __FMADD( temp1, z2, z );
248
249 temp1 = __FMADD( zTail, temp2, zTail );
250
251 temp1 = temp1 + temp2;
252
253 result = __FMADD( result, temp1, result );
254
255 result = __FMUL( result, power );
256
257 FESETENVD ( FPR_env );
258 __PROG_INEXACT( FPR_oneOverLn2 );
259 return result;
260 }
261
262 FESETENVD ( FPR_env );
263 if ( x != x )
264 return x;
265 else if ( x == infinity.d )
266 return infinity.d;
267 else if ( x == -infinity.d )
268 return FPR_z;
269 else if ( x > maxExp )
270 {
271 __PROG_OF_INEXACT( kMaxNormal );
272 return infinity.d;
273 }
274 else
275 {
276 __PROG_UF_INEXACT( kMinNormal );
277 return FPR_z;
278 }
279}
280
281/*******************************************************************************
282* *
283* The expm1 function. *
284* *
285*******************************************************************************/
286
287static const hexdouble k2M55 = HEXDOUBLE(0x3c800000, 0x00000000);
288
289double expm1 ( double x )
290{
291 hexdouble scale, invScale, xInHex, yInHex;
292 register double d, y, yTail, z, zTail, z2, temp1, temp2, power, result, f;
293 register int32_t i;
294 register struct expTableEntry *tablePointer, *pT;
295
296 register double FPR_oneOverLn2, FPR_rintFactor, FPR_ln2Head, FPR_ln2Tail, FPR_h, FPR_z, FPR_512, FPR_scale;
297 register double FPR_env, FPR_x, FPR_f, FPR_cc0, FPR_cc1, FPR_cc2, FPR_cc3, FPR_cc4, FPR_iscale;
298
299 FPR_x = __FABS( x );
300
301 FPR_z = 0.0; FPR_512 = 512.0;
302 FPR_oneOverLn2 = oneOverLn2; FPR_rintFactor = rintFactor;
303 FPR_ln2Head = ln2Head; FPR_ln2Tail = ln2Tail;
304 tablePointer = ( struct expTableEntry * ) expTable + 177;
305
306 FEGETENVD ( FPR_env ); // save old environment, set default
307 __ENSURE( FPR_z, FPR_512, FPR_oneOverLn2 ); __ENSURE( FPR_ln2Head, FPR_ln2Tail, FPR_rintFactor );
308 FESETENVD ( FPR_z );
309
310 // Compute FPR_h and store it to yInHex as early as possible, even for cases that don't need it
311 FPR_h = __FMADD( x, FPR_oneOverLn2, FPR_rintFactor );
312 yInHex.d = FPR_h;
313 FPR_h -= FPR_rintFactor;
314
315 if (likely( FPR_x < FPR_512 ))
316 {
317 if (unlikely( FPR_x < k2M55.d ))
318 {
319 FESETENVD ( FPR_env );
320 if ( x == FPR_z )
321 {
322 /* NOTHING */
323 }
324 else
325 {
326 if ( FPR_x < kMinNormal )
327 __PROG_UF_INEXACT( kMinNormal );
328 else
329 __PROG_INEXACT( FPR_oneOverLn2 );
330 }
331 return x;
332 }
333
334 scale.i.hi = ( yInHex.i.lo + 1023 ) << 20; scale.i.lo = 0;
335
336 y = __FNMSUB( FPR_ln2Head, FPR_h, x ); yTail = __FMUL( FPR_ln2Tail, FPR_h );
337
338 xInHex.d = __FMADD( FPR_512, y, FPR_rintFactor );
339 invScale.i.hi = 0x7fe00000 - scale.i.hi; invScale.i.lo = 0;
340
341 i = xInHex.i.lo;
342
343 pT = &(tablePointer[i]);
344
345 FPR_x = pT->x; FPR_f = pT->f;
346
347 d = y - FPR_x;
348 FPR_cc4 = cc4;
349
350 z = d - yTail;
351 FPR_cc0 = cc0; FPR_cc2 = cc2;
352 FPR_cc1 = cc1; FPR_cc3 = cc3;
353
354 z2 = __FMUL( z, z ); zTail = d - z - yTail;
355
356 temp1 = __FMADD( FPR_cc0, z2, FPR_cc2 ); temp2 = __FMADD( FPR_cc1, z2, FPR_cc3 );
357
358 temp1 = __FMADD( temp1, z2, FPR_cc4 );
359
360 temp2 = __FMADD( temp2, z, temp1 );
361 FPR_iscale = invScale.d;
362
363 temp1 = __FMADD( temp2, z2, z );
364
365 temp2 = __FMADD( zTail, temp1, zTail );
366
367 temp2 = temp1 + temp2; d = FPR_f - FPR_iscale;
368 FPR_scale = scale.d;
369
370 temp1 = __FMADD( FPR_f, temp2, d );
371
372 result = __FMUL( temp1, FPR_scale );
373
374 FESETENVD ( FPR_env );
375 __PROG_INEXACT( FPR_oneOverLn2 );
376 return result;
377 }
378
379 if (likely( ( x <= maxExp ) && ( x > minExp ) ))
380 {
381 if ( x >= FPR_512 )
382 {
383 power = 2.0;
384 f = 0.5;
385 scale.i.hi = ( yInHex.i.lo + 1022 ) << 20; scale.i.lo = 0;
386 }
387 else
388 {
389 power = denormal;
390 f = oneOverDenorm;
391 scale.i.hi = ( yInHex.i.lo + 1023+128 ) << 20; scale.i.lo = 0;
392 if ( scale.i.hi < ( 168<<20 ) )
393 {
394 FESETENVD ( FPR_env );
395 __PROG_INEXACT( FPR_oneOverLn2 );
396 return -1.0;
397 }
398 }
399
400 y = __FNMSUB( FPR_ln2Head, FPR_h, x ); yTail = __FMUL( FPR_ln2Tail, FPR_h );
401 FPR_scale = scale.d;
402
403 xInHex.d = __FMADD( FPR_512, y, FPR_rintFactor );
404 invScale.i.hi = 0x7fe00000 - scale.i.hi; invScale.i.lo = 0;
405
406 i = xInHex.i.lo;
407
408 pT = &(tablePointer[i]);
409
410 FPR_x = pT->x; FPR_f = pT->f;
411
412 d = y - FPR_x;
413 FPR_iscale = invScale.d; FPR_cc4 = cc4;
414
415 z = d - yTail;
416 FPR_cc0 = cc0; FPR_cc2 = cc2;
417 FPR_cc1 = cc1; FPR_cc3 = cc3;
418
419 z2 = __FMUL( z, z ); zTail = d - z - yTail;
420
421 temp1 = __FMADD( FPR_cc0, z2, FPR_cc2 ); temp2 = __FMADD( FPR_cc1, z2, FPR_cc3 );
422
423 temp1 = __FMADD( temp1, z2, FPR_cc4 ); d = __FNMSUB( f, FPR_iscale, FPR_f );
424
425 temp2 = __FMADD( temp2, z, temp1 );
426
427 temp1 = __FMADD( temp2, z2, z );
428
429 temp2 = __FMADD( zTail, temp1, zTail );
430
431 temp2 = temp1 + temp2;
432
433 temp1 = __FMADD( FPR_f, temp2, d );
434
435 result = __FMUL( temp1, FPR_scale );
436
437 result = __FMUL( result, power );
438
439 FESETENVD ( FPR_env );
440 __PROG_INEXACT( FPR_oneOverLn2 );
441 return result;
442 }
443
444 FESETENVD ( FPR_env );
445 if ( x != x )
446 return x;
447 else if ( x == infinity.d )
448 return infinity.d;
449 else if ( x == -infinity.d )
450 return -1.0;
451 else if ( x > maxExp )
452 {
453 __PROG_OF_INEXACT( kMaxNormal );
454 return infinity.d;
455 }
456 else
457 {
458#if 0 /* XXX scp: test vectors don't want this to underflow */
459 __PROG_UF_INEXACT( kMinNormal );
460#else
461 __PROG_INEXACT( FPR_oneOverLn2 );
462#endif
463 return -1.0;
464 }
465}
466
467#else /* BUILDING_FOR_CARBONCORE_LEGACY */
468/*******************************************************************************
469* Floating-point constants. *
470*******************************************************************************/
471
472static const double maxExp2 = 1024.0;
473static const double minNormExp2 = -1022.0;
474static const double minExp2 = -1075.0;
475
476/*******************************************************************************
477* *
478* The base 2 exponential function. *
479* *
480*******************************************************************************/
481
482double exp2 ( double x )
483{
484 hexdouble OldEnvironment, scale, xInHex, yInHex;
485 register double d, y, yTail, z, zTail, z2, temp1, temp2, power, result;
486 register int32_t i;
487 register struct expTableEntry *tablePointer, *pT;
488
489 register double FPR_oneOverLn2, FPR_rintFactor, FPR_ln2Head, FPR_ln2Tail, FPR_h, FPR_z, FPR_512, FPR_scale;
490 register double FPR_env, FPR_diff, FPR_x, FPR_f, FPR_cm1, FPR_c0, FPR_c1, FPR_c2;
491
492 FPR_x = __FABS( x );
493
494 FPR_z = 0.0; FPR_512 = 512.0;
495 FPR_oneOverLn2 = oneOverLn2; FPR_rintFactor = rintFactor;
496 FPR_ln2Head = ln2Head; FPR_ln2Tail = ln2Tail;
497 tablePointer = ( struct expTableEntry * ) expTable + 177;
498
499 FEGETENVD ( FPR_env ); // save old environment, set default
500 __ENSURE( FPR_z, FPR_512, FPR_oneOverLn2 ); __ENSURE( FPR_ln2Head, FPR_ln2Tail, FPR_rintFactor );
501 FESETENVD ( FPR_z );
502
503 // Compute FPR_h and store it to yInHex as early as possible, even for cases that don't need it
504 FPR_h = x + FPR_rintFactor;
505 yInHex.d = FPR_h;
506 FPR_h -= FPR_rintFactor;
507
508 FPR_diff = x - FPR_h;
509
510 if (likely( FPR_x < FPR_512 ))
511 {
512 if (likely( FPR_x != FPR_z ))
513 {
514 scale.i.hi = ( yInHex.i.lo + 1023 ) << 20; scale.i.lo = 0;
515
516 y = __FMUL( FPR_ln2Head, FPR_diff ); yTail = __FMUL( FPR_ln2Tail, FPR_diff );
517
518 xInHex.d = __FMADD( FPR_512, y, FPR_rintFactor );
519
520 __NOOP;
521 __NOOP;
522 __NOOP;
523 i = xInHex.i.lo;
524
525 pT = &(tablePointer[i]);
526
527 FPR_x = pT->x; FPR_f = pT->f;
528
529 d = y - FPR_x;
530
531 z = d - yTail;
532 FPR_cm1 = cm1; FPR_c1 = c1;
533 FPR_c0 = c0; FPR_c2 = c2;
534
535 z2 = __FMUL( z, z ); zTail = d - z - yTail;
536
537 temp1 = __FMADD( FPR_cm1, z2, FPR_c1 ); temp2 = __FMADD( FPR_c0, z2, FPR_c2 );
538
539 temp1 = __FMADD( temp1, z, temp2 );
540
541 temp2 = __FMADD( temp1, z2, z );
542 FPR_scale = scale.d;
543
544 temp1 = __FMADD( zTail, temp2, zTail );
545
546 temp1 = temp1 + temp2; result = __FMUL( FPR_scale, FPR_f );
547
548 result = __FMADD( result, temp1, result );
549
550 FESETENVD ( FPR_env );
551 if ( FPR_diff != FPR_z)
552 __PROG_INEXACT( FPR_oneOverLn2 );
553
554 return result;
555 }
556 else
557 {
558 FESETENVD ( FPR_env );
559 return 1.0;
560 }
561 }
562
563 if (likely( ( x < maxExp2 ) && ( x > minExp2 ) ))
564 {
565 if ( x >= FPR_512 )
566 {
567 power = 2.0;
568 scale.i.hi = ( yInHex.i.lo + 1022 ) << 20; scale.i.lo = 0;
569 }
570 else
571 {
572 power = denormal;
573 scale.i.hi = ( yInHex.i.lo + 1023+128 ) << 20; scale.i.lo = 0;
574 }
575
576 FPR_diff = x - FPR_h;
577 FPR_scale = scale.d;
578
579 y = __FMUL( FPR_ln2Head, FPR_diff ); yTail = __FMUL( FPR_ln2Tail, FPR_diff );
580
581 xInHex.d = __FMADD( FPR_512, y, FPR_rintFactor );
582
583 __NOOP;
584 __NOOP;
585 __NOOP;
586 i = xInHex.i.lo;
587
588 pT = &(tablePointer[i]);
589
590 FPR_x = pT->x; FPR_f = pT->f;
591
592 d = y - FPR_x; result = __FMUL( FPR_scale, FPR_f );
593
594 z = d - yTail;
595 FPR_cm1 = cm1; FPR_c1 = c1;
596 FPR_c0 = c0; FPR_c2 = c2;
597
598 z2 = __FMUL( z, z ); zTail = d - z - yTail;
599
600 temp1 = __FMADD( FPR_cm1, z2, FPR_c1 ); temp2 = __FMADD( FPR_c0, z2, FPR_c2 );
601
602 temp1 = __FMADD( temp1, z, temp2 );
603
604 temp2 = __FMADD( temp1, z2, z );
605
606 temp1 = __FMADD( zTail, temp2, zTail );
607
608 temp1 = temp1 + temp2;
609
610 result = __FMADD( result, temp1, result );
611
612 result = __FMUL( result, power );
613
614 FESETENVD ( FPR_env );
615 if ( x < minNormExp2 )
616 {
617 OldEnvironment.d = FPR_env;
618 __NOOP;
619 __NOOP;
620 __NOOP;
621
622 OldEnvironment.i.lo |= FE_UNDERFLOW; // set underflow flag
623
624 if ( FPR_h != x )
625 OldEnvironment.i.lo |= FE_INEXACT; // set inexact flag
626
627 FESETENVD_GRP ( OldEnvironment.d );
628 }
629 else if ( FPR_h != x )
630 __PROG_INEXACT( FPR_oneOverLn2 );
631
632 return result;
633 }
634
635 FESETENVD ( FPR_env );
636 if ( x != x )
637 return x;
638 else if ( x == infinity.d )
639 return infinity.d;
640 else if ( x == -infinity.d )
641 return FPR_z;
642 else if ( x > maxExp )
643 {
644 __PROG_OF_INEXACT( kMaxNormal );
645 return infinity.d;
646 }
647 else
648 {
649 __PROG_UF_INEXACT( kMinNormal );
650 return FPR_z;
651 }
652}
653
654#endif /* BUILDING_FOR_CARBONCORE_LEGACY */