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* File: remmod.c *
24* *
25* Contains: C source code for implementations of some floating-point *
26* functions defined in header <fp.h>. In particular, this *
27* file contains implementations of functions fmod, remainder, *
28* and remquo. *
29* *
30* Copyright � 1992-2001 by Apple Computer, Inc. All rights reserved. *
31* *
32* Written by Jon Okada, started on December 7th, 1992. *
33* Modified by Paul Finlayson (PAF) for MathLib v2. *
34* Modified by A. Sazegari (ali) for MathLib v3. *
35* Modified and ported by Robert A. Murley (ram) for Mac OS X. *
36* *
37* A MathLib v4 file. *
38* *
39* Change History (most recent first): *
40* *
41* 08 Nov 01 ram renamed remquo to avoid conflict with CarbonCore. *
42* 06 Nov 01 ram commented out warning about Intel architectures. *
43* changed i386 stub to call abort(). *
44* 02 Nov 01 ram added stub for i386 version of remquo. *
45* 08 Oct 01 ram removed <CoreServices/CoreServices.h>. *
46* changed compiler errors to warnings. *
47* 18 Sep 01 ali added <CoreServices/CoreServices.h> to get <fp.h>. *
48* 17 Sep 01 ali replaced "fp.h" & "fenv.h" with <fp.h> & <fenv.h>. *
49* 13 Sep 01 ali replaced double_t by double. *
50* 10 Sep 01 ali added more comments. *
51* 09 Sep 01 ali added macros to detect PowerPC and correct compiler. *
52* 06 Sep 01 ram added #ifdef __ppc__. *
53* 16 Jul 01 ram Replaced __setflm with FEGETENVD/FESETENVD. *
54* replaced DblInHex typedef with hexdouble. *
55* 09 Oct 94 ali made environmental changes to use __setflm *
56* instead of _feprocentry. *
57* 05 Oct 93 PAF Fixed rounding sensitivity and flag errors. *
58* 14 Dec 92 JPO Fixed case where |x| = |y|. *
59* 11 Dec 92 JPO Fixed bug that created overflow for |x| in *
60* highest binade. *
61* 07 Dec 92 JPO First created. *
62* *
63* W A R N I N G: *
64* These routines require a 64-bit double precision IEEE-754 model. *
65* They are written for PowerPC only and are expecting the compiler *
66* to generate the correct sequence of multiply-add fused instructions. *
67* *
68* These routines are not intended for 32-bit Intel architectures. *
69* *
70* A version of gcc higher than 932 is required. *
71* *
72* GCC compiler options: *
73* optimization level 3 (-O3) *
74* -fschedule-insns -finline-functions -funroll-all-loops *
75* *
76********************************************************************************/
77
78#include "math.h"
79#include "fp_private.h"
80#include "fenv_private.h"
81
82#define REM_NAN "9"
83
84#if defined(BUILDING_FOR_CARBONCORE_LEGACY)
85
86static const hexdouble Huge = HEXDOUBLE(0x7ff00000, 0x00000000);
87static const hexdouble HugeHalved = HEXDOUBLE(0x7fe00000, 0x00000000);
88
89static int ___fpclassifyd ( double arg )
90{
91 register uint32_t exponent;
92 hexdouble x;
93
94 x.d = arg;
95 __NOOP;
96 __NOOP;
97 __NOOP;
98
99 exponent = x.i.hi & 0x7ff00000;
100 if ( exponent == 0x7ff00000 )
101 {
102 if ( ( ( x.i.hi & 0x000fffff ) | x.i.lo ) == 0 )
103 return FP_INFINITE;
104 else
105 return ( x.i.hi & dQuietNan ) ? FP_QNAN : FP_SNAN;
106 }
107 else if ( exponent != 0)
108 return FP_NORMAL;
109 else
110 {
111 if ( ( ( x.i.hi & 0x000fffff ) | x.i.lo ) == 0 )
112 return FP_ZERO;
113 else
114 return FP_SUBNORMAL;
115 }
116}
117
118static const double twoTo52 = 0x1.0p+52; // 4.50359962737049600e15;
119static const double klTod = 4503601774854144.0; // 0x1.000008p52
120static const hexdouble minusInf = HEXDOUBLE(0xfff00000, 0x00000000);
121
122static double __logb ( double x )
123{
124 hexdouble xInHex;
125 int32_t shiftedExp;
126
127 xInHex.d = x;
128 __NOOP;
129 __NOOP;
130 __NOOP;
131
132 shiftedExp = ( xInHex.i.hi & 0x7ff00000 ) >> 20;
133
134 if (unlikely( shiftedExp == 2047 ))
135 { // NaN or INF
136 if ( ( ( xInHex.i.hi & 0x80000000 ) == 0 ) || ( x != x ) )
137 return x; // NaN or +INF return x
138 else
139 return -x; // -INF returns +INF
140 }
141
142 if (likely( shiftedExp != 0 )) // normal number
143 shiftedExp -= 1023; // unbias exponent
144 else if ( x == 0.0 )
145 { // zero
146 hexdouble OldEnvironment;
147 FEGETENVD_GRP( OldEnvironment.d ); // raise zero divide for DOMAIN error
148 OldEnvironment.i.lo |= FE_DIVBYZERO;
149 FESETENVD_GRP( OldEnvironment.d );
150 return ( minusInf.d ); // return -infinity
151 }
152 else
153 { // subnormal number
154 xInHex.d *= twoTo52; // scale up
155 __NOOP;
156 __NOOP;
157 __NOOP;
158
159 shiftedExp = ( xInHex.i.hi & 0x7ff00000 ) >> 20;
160 shiftedExp -= 1075; // unbias exponent
161 }
162
163 if (unlikely( shiftedExp == 0 )) // zero result
164 return ( 0.0 );
165 else
166 { // nonzero result
167 xInHex.d = klTod;
168 __NOOP;
169 __NOOP;
170 __NOOP;
171
172 xInHex.i.lo += shiftedExp;
173 return ( xInHex.d - klTod );
174 }
175}
176
177static const double twoTo1023 = 0x1.0p+1023;
178static const double twoToM1022 = 0x1.0p-1022;
179
180static double __scalbn ( double x, int n )
181{
182 hexdouble xInHex;
183
184 xInHex.i.lo = 0u; // init. low half of xInHex
185
186 if ( n > 1023 )
187 { // large positive scaling
188 if ( n > 2097 ) // huge scaling
189 return ( ( x * twoTo1023 ) * twoTo1023 ) * twoTo1023;
190 while ( n > 1023 )
191 { // scale reduction loop
192 x *= twoTo1023; // scale x by 2^1023
193 n -= 1023; // reduce n by 1023
194 }
195 }
196
197 else if ( n < -1022 )
198 { // large negative scaling
199 if ( n < -2098 ) // huge negative scaling
200 return ( ( x * twoToM1022 ) * twoToM1022 ) * twoToM1022;
201 while ( n < -1022 )
202 { // scale reduction loop
203 x *= twoToM1022; // scale x by 2^( -1022 )
204 n += 1022; // incr n by 1022
205 }
206 }
207
208/*******************************************************************************
209* -1022 <= n <= 1023; convert n to double scale factor. *
210*******************************************************************************/
211
212 xInHex.i.hi = ( ( uint32_t ) ( n + 1023 ) ) << 20;
213 __NOOP;
214 __NOOP;
215 __NOOP;
216
217 return ( x * xInHex.d );
218}
219
220static int ___signbitd ( double arg )
221{
222 hexdouble z;
223
224 z.d = arg;
225 __NOOP;
226 __NOOP;
227 __NOOP;
228 return (((int32_t)z.i.hi) < 0);
229}
230
231/***********************************************************************
232 The function remquo returns the IEEE-mandated floating-point remainder
233 of its floating-point arguments x and y: x REM y. It also calculates
234 the low seven bits of the integral quotient and writes the signed
235 low quotient result to the location pointed to by the int pointer
236 argument, quo: -127 <= iquo <= +127.
237
238 This function calls: __fpclassifyd, logb, scalbn, __FABS, signbitd.
239***********************************************************************/
240
241double remquo ( double x, double y, int *quo)
242{
243 int iclx,icly; /* classify results of x,y */
244 int32_t iquo; /* low 32 bits of integral quotient */
245 int32_t iscx, iscy, idiff; /* logb values and difference */
246 int i; /* loop variable */
247 double absy,x1,y1,z; /* local floating-point variables */
248 double rslt;
249 fenv_t OldEnv;
250 hexdouble OldEnvironment;
251 int newexc;
252
253 FEGETENVD ( OldEnvironment.d );
254 FESETENVD ( 0.0 );
255 __NOOP;
256 __NOOP;
257
258 OldEnv = OldEnvironment.i.lo;
259
260 *quo = 0; /* initialize quotient result */
261 iclx = ___fpclassifyd(x);
262 icly = ___fpclassifyd(y);
263 if (likely((iclx & icly) >= FP_NORMAL)) { /* x,y both nonzero finite case */
264 x1 = __FABS(x); /* work with absolute values */
265 absy = __FABS(y);
266 iquo = 0; /* zero local quotient */
267 iscx = (int32_t) __logb(x1); /* get binary exponents */
268 iscy = (int32_t) __logb(absy);
269 idiff = iscx - iscy; /* exponent difference */
270 if (idiff >= 0) { /* exponent of x1 >= exponent of y1 */
271 if (idiff != 0) { /* exponent of x1 > exponent of y1 */
272 y1 = __scalbn(absy,-iscy); /* scale |y| to unit binade */
273 x1 = __scalbn(x1,-iscx); /* ditto for |x| */
274 for (i = idiff; i != 0; i--) { /* begin remainder loop */
275 if ((z = x1 - y1) >= 0) { /* nonzero remainder step result */
276 x1 = z; /* update remainder (x1) */
277 iquo += 1; /* increment quotient */
278 }
279 iquo += iquo; /* shift quotient left one bit */
280 x1 += x1; /* shift (double) remainder */
281 } /* end of remainder loop */
282 x1 = __scalbn(x1,iscy); /* scale remainder to binade of |y| */
283 } /* remainder has exponent <= exponent of y */
284 if (x1 >= absy) { /* last remainder step */
285 x1 -= absy;
286 iquo +=1;
287 } /* end of last remainder step */
288 } /* remainder (x1) has smaller exponent than y */
289 if (likely( x1 < HugeHalved.d ))
290 z = x1 + x1; /* double remainder, without overflow */
291 else
292 z = Huge.d;
293 if ((z > absy) || ((z == absy) && ((iquo & 1) != 0))) {
294 x1 -= absy; /* final remainder correction */
295 iquo += 1;
296 }
297 if (x < 0.0)
298 x1 = -x1; /* remainder if x is negative */
299 iquo &= 0x0000007f; /* retain low 7 bits of integer quotient */
300 if ((___signbitd(x) ^ ___signbitd(y)) != 0) /* take care of sign of quotient */
301 iquo = -iquo;
302 *quo = iquo; /* deliver quotient result */
303 rslt = x1;
304 goto ret;
305 } /* end of x,y both nonzero finite case */
306 else if ((iclx <= FP_QNAN) || (icly <= FP_QNAN)) {
307 rslt = x+y; /* at least one NaN operand */
308 goto ret;
309 }
310 else if ((iclx == FP_INFINITE)||(icly == FP_ZERO)) { /* invalid result */
311 rslt = nan(REM_NAN);
312 OldEnvironment.i.lo |= SET_INVALID;
313 FESETENVD_GRP( OldEnvironment.d );
314 goto ret;
315 }
316 else /* trivial cases (finite REM infinite */
317 rslt = x; /* or zero REM nonzero) with *quo = 0 */
318 ret:
319 FEGETENVD_GRP( OldEnvironment.d );
320 newexc = OldEnvironment.i.lo & FE_ALL_EXCEPT;
321 OldEnvironment.i.lo = OldEnv;
322 if ((newexc & FE_INVALID) != 0)
323 OldEnvironment.i.lo |= SET_INVALID;
324 OldEnvironment.i.lo |= newexc & ( FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW );
325 FESETENVD_GRP( OldEnvironment.d );
326 return rslt;
327}
328
329#else /* !BUILDING_FOR_CARBONCORE_LEGACY */
330
331static const hexsingle HugeF = { 0x7f800000 };
332static const hexsingle HugeFHalved = { 0x7f000000 };
333
334float remquof ( float x, float y, int *quo)
335{
336 int iclx,icly; /* classify results of x,y */
337 int32_t iquo; /* low 32 bits of integral quotient */
338 int32_t iscx, iscy, idiff; /* logb values and difference */
339 int i; /* loop variable */
340 float absy,x1,y1,z; /* local floating-point variables */
341 float rslt;
342 fenv_t OldEnv;
343 hexdouble OldEnvironment;
344 int newexc;
345
346 FEGETENVD ( OldEnvironment.d );
347 FESETENVD ( 0.0 );
348 __NOOP;
349 __NOOP;
350
351 OldEnv = OldEnvironment.i.lo;
352
353 *quo = 0; /* initialize quotient result */
354 iclx = __fpclassifyf(x);
355 icly = __fpclassifyf(y);
356 if (likely((iclx & icly) >= FP_NORMAL)) { /* x,y both nonzero finite case */
357 x1 = __FABSF(x); /* work with absolute values */
358 absy = __FABSF(y);
359 iquo = 0; /* zero local quotient */
360 iscx = (int32_t) logbf(x1); /* get binary exponents */
361 iscy = (int32_t) logbf(absy);
362 idiff = iscx - iscy; /* exponent difference */
363 if (idiff >= 0) { /* exponent of x1 >= exponent of y1 */
364 if (idiff != 0) { /* exponent of x1 > exponent of y1 */
365 y1 = scalbnf(absy,-iscy); /* scale |y| to unit binade */
366 x1 = scalbnf(x1,-iscx); /* ditto for |x| */
367 for (i = idiff; i != 0; i--) { /* begin remainder loop */
368 if ((z = x1 - y1) >= 0) { /* nonzero remainder step result */
369 x1 = z; /* update remainder (x1) */
370 iquo += 1; /* increment quotient */
371 }
372 iquo += iquo; /* shift quotient left one bit */
373 x1 += x1; /* shift (double) remainder */
374 } /* end of remainder loop */
375 x1 = scalbnf(x1,iscy); /* scale remainder to binade of |y| */
376 } /* remainder has exponent <= exponent of y */
377 if (x1 >= absy) { /* last remainder step */
378 x1 -= absy;
379 iquo +=1;
380 } /* end of last remainder step */
381 } /* remainder (x1) has smaller exponent than y */
382 if (likely( x1 < HugeFHalved.fval ))
383 z = x1 + x1; /* double remainder, without overflow */
384 else
385 z = HugeF.fval;
386 if ((z > absy) || ((z == absy) && ((iquo & 1) != 0))) {
387 x1 -= absy; /* final remainder correction */
388 iquo += 1;
389 }
390 if (x < 0.0)
391 x1 = -x1; /* remainder if x is negative */
392 iquo &= 0x0000007f; /* retain low 7 bits of integer quotient */
393 if ((signbit(x) ^ signbit(y)) != 0) /* take care of sign of quotient */
394 iquo = -iquo;
395 *quo = iquo; /* deliver quotient result */
396 rslt = x1;
397 goto ret;
398 } /* end of x,y both nonzero finite case */
399 else if ((iclx <= FP_QNAN) || (icly <= FP_QNAN)) {
400 rslt = x+y; /* at least one NaN operand */
401 goto ret;
402 }
403 else if ((iclx == FP_INFINITE)||(icly == FP_ZERO)) { /* invalid result */
404 rslt = nanf(REM_NAN);
405 OldEnvironment.i.lo |= SET_INVALID;
406 FESETENVD_GRP( OldEnvironment.d );
407 goto ret;
408 }
409 else /* trivial cases (finite REM infinite */
410 rslt = x; /* or zero REM nonzero) with *quo = 0 */
411 ret:
412 FEGETENVD_GRP( OldEnvironment.d );
413 newexc = OldEnvironment.i.lo & FE_ALL_EXCEPT;
414 OldEnvironment.i.lo = OldEnv;
415 if ((newexc & FE_INVALID) != 0)
416 OldEnvironment.i.lo |= SET_INVALID;
417 OldEnvironment.i.lo |= newexc & ( FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW );
418 FESETENVD_GRP( OldEnvironment.d );
419 return rslt;
420}
421
422
423
424/***********************************************************************
425 The function remainder returns the IEEE-mandated floating-point remainder
426 of its floating-point arguments x and y: x REM y. It returns the
427 same result as remquo, but it discards the integral quotient.
428
429 This function calls: remquo.
430***********************************************************************/
431
432double remainder ( double x, double y )
433{
434 int quo;
435
436 return ( remquo( x, y, &quo ));
437}
438
439float remainderf ( float x, float y )
440{
441 int quo;
442
443 return ( remquof( x, y, &quo ));
444}
445
446
447
448
449/***********************************************************************
450 The function fmod returns the floating-point modulus of its floating-
451 point arguments x and y: x MOD y, such that the return value has
452 the same sign as x.
453 This function calls: --fpclassify, logb, scalbn, --fabs.
454***********************************************************************/
455
456double fmod ( double x, double y )
457{
458 int iclx,icly; /* classify results of x,y */
459 int32_t iscx,iscy,idiff; /* logb values and difference */
460 int i; /* loop variable */
461 double absy,x1,y1,z; /* local floating-point variables */
462 double rslt;
463 fenv_t OldEnv;
464 hexdouble OldEnvironment;
465 int newexc;
466
467 FEGETENVD( OldEnvironment.d );
468 FESETENVD( 0.0 );
469 __NOOP;
470 __NOOP;
471
472 OldEnv = OldEnvironment.i.lo;
473
474 iclx = __fpclassifyd(x);
475 icly = __fpclassifyd(y);
476 if (likely((iclx & icly) >= FP_NORMAL)) { /* x,y both nonzero finite case */
477 x1 = __FABS(x); /* work with absolute values */
478 absy = __FABS(y);
479 if (absy > x1) {
480 rslt = x; /* trivial case */
481 goto ret;
482 }
483 else { /* nontrivial case requires reduction */
484 iscx = (int32_t) logb(x1); /* get binary exponents of |x| and |y| */
485 iscy = (int32_t) logb(absy);
486 idiff = iscx - iscy; /* exponent difference */
487 if (idiff != 0) { /* exponent of x1 > exponent of y1 */
488 y1 = scalbn(absy,-iscy); /* scale |y| to unit binade */
489 x1 = scalbn(x1,-iscx); /* ditto for |x| */
490 for (i = idiff; i != 0; i--) { /* begin remainder loop */
491 if ((z = x1 - y1) >= 0) { /* nonzero remainder step result */
492 x1 = z; /* update remainder (x1) */
493 }
494 x1 += x1; /* shift (by doubling) remainder */
495 } /* end of remainder loop */
496 x1 = scalbn(x1,iscy); /* scale result to binade of |y| */
497 } /* remainder exponent >= exponent of y */
498 if (x1 >= absy) { /* last step to obtain modulus */
499 x1 -= absy;
500 }
501 } /* x1 is |result| */
502 if (x < 0.0)
503 x1 = -x1; /* modulus if x is negative */
504 rslt = x1;
505 goto ret;
506 } /* end of x,y both nonzero finite case */
507 else if ((iclx <= FP_QNAN) || (icly <= FP_QNAN)) {
508 rslt = x+y; /* at least one NaN operand */
509 goto ret;
510 }
511 else if ((iclx == FP_INFINITE)||(icly == FP_ZERO)) { /* invalid result */
512 rslt = nan(REM_NAN);
513 OldEnvironment.i.lo |= SET_INVALID;
514 FESETENVD_GRP ( OldEnvironment.d );
515 goto ret;
516 }
517 else /* trivial cases (finite MOD infinite */
518 rslt = x; /* or zero REM nonzero) with *quo = 0 */
519 ret:
520 FEGETENVD_GRP (OldEnvironment.d );
521 newexc = OldEnvironment.i.lo & FE_ALL_EXCEPT;
522 OldEnvironment.i.lo = OldEnv;
523 if ((newexc & FE_INVALID) != 0)
524 OldEnvironment.i.lo |= SET_INVALID;
525 OldEnvironment.i.lo |= newexc & ( FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW );
526 FESETENVD_GRP (OldEnvironment.d );
527 return rslt;
528}
529
530float fmodf ( float x, float y )
531{
532 int iclx,icly; /* classify results of x,y */
533 int32_t iscx,iscy,idiff; /* logb values and difference */
534 int i; /* loop variable */
535 float absy,x1,y1,z; /* local floating-point variables */
536 float rslt;
537 fenv_t OldEnv;
538 hexdouble OldEnvironment;
539 int newexc;
540
541 FEGETENVD( OldEnvironment.d );
542 FESETENVD( 0.0 );
543 __NOOP;
544 __NOOP;
545
546 OldEnv = OldEnvironment.i.lo;
547
548 iclx = __fpclassifyf(x);
549 icly = __fpclassifyf(y);
550 if (likely((iclx & icly) >= FP_NORMAL)) { /* x,y both nonzero finite case */
551 x1 = __FABSF(x); /* work with absolute values */
552 absy = __FABSF(y);
553 if (absy > x1) {
554 rslt = x; /* trivial case */
555 goto ret;
556 }
557 else { /* nontrivial case requires reduction */
558 iscx = (int32_t) logbf(x1); /* get binary exponents of |x| and |y| */
559 iscy = (int32_t) logbf(absy);
560 idiff = iscx - iscy; /* exponent difference */
561 if (idiff != 0) { /* exponent of x1 > exponent of y1 */
562 y1 = scalbnf(absy,-iscy); /* scale |y| to unit binade */
563 x1 = scalbnf(x1,-iscx); /* ditto for |x| */
564 for (i = idiff; i != 0; i--) { /* begin remainder loop */
565 if ((z = x1 - y1) >= 0) { /* nonzero remainder step result */
566 x1 = z; /* update remainder (x1) */
567 }
568 x1 += x1; /* shift (by doubling) remainder */
569 } /* end of remainder loop */
570 x1 = scalbnf(x1,iscy); /* scale result to binade of |y| */
571 } /* remainder exponent >= exponent of y */
572 if (x1 >= absy) { /* last step to obtain modulus */
573 x1 -= absy;
574 }
575 } /* x1 is |result| */
576 if (x < 0.0)
577 x1 = -x1; /* modulus if x is negative */
578 rslt = x1;
579 goto ret;
580 } /* end of x,y both nonzero finite case */
581 else if ((iclx <= FP_QNAN) || (icly <= FP_QNAN)) {
582 rslt = x+y; /* at least one NaN operand */
583 goto ret;
584 }
585 else if ((iclx == FP_INFINITE)||(icly == FP_ZERO)) { /* invalid result */
586 rslt = nanf(REM_NAN);
587 OldEnvironment.i.lo |= SET_INVALID;
588 FESETENVD_GRP ( OldEnvironment.d );
589 goto ret;
590 }
591 else /* trivial cases (finite MOD infinite */
592 rslt = x; /* or zero REM nonzero) with *quo = 0 */
593 ret:
594 FEGETENVD_GRP (OldEnvironment.d );
595 newexc = OldEnvironment.i.lo & FE_ALL_EXCEPT;
596 OldEnvironment.i.lo = OldEnv;
597 if ((newexc & FE_INVALID) != 0)
598 OldEnvironment.i.lo |= SET_INVALID;
599 OldEnvironment.i.lo |= newexc & ( FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW );
600 FESETENVD_GRP (OldEnvironment.d );
601 return rslt;
602}
603
604#endif /* !BUILDING_FOR_CARBONCORE_LEGACY */