double Tile_Engine::get_y_collision_move(double y1, double y2, double x1, double x_size, double y_size) { double pos_y = y1; if (y2 > y1 ) { int x_start = floor(x1/32.0); int x_end = floor(nextafter(x_size+x1, x_size-1)/32.0); int y_start = floor(nextafter(y_size+y1, y_size-1)/32.0); int y_end = floor(nextafter(y_size+y2, y_size-1)/32.0); for (int i = y_start; i <= y_end; i++) { for (int k = x_start; k <= x_end; k++) { if (getTile(k, i)->getType() == COLLIDES) { return pos_y; } } pos_y = (i==y_end)?y2:(double)(i+1)*32.0-y_size;//-nextafter(y_size, y_size-1); } } else { int x_start = floor(x1/32.0); int x_end = floor(nextafter(x_size+x1,x_size-1)/32.0); int y_start = floor(y1/32.0); int y_end = floor(y2/32.0); for (int i = y_start; i >= y_end; i--) { for (int k = x_start; k <= x_end; k++) { if (getTile(k, i)->getType() == COLLIDES) { return pos_y; } } pos_y = (i==y_end)?y2:(32*i); } } return pos_y; }
void test_fp_utilities( void ) { #if __STDC_VERSION__ >= 199901L printf( "Testing C99 miscellaneous functions...\n" ); VERIFY( CompDbl( copysign( -2.0, 1.0), 2.0 ) ); VERIFY( CompDbl( copysign( -2.0, -1.0), -2.0 ) ); VERIFY( CompDbl( copysign( 2.0, -1.0), -2.0 ) ); VERIFY( CompDbl( copysign( 2.0, 1.0), 2.0 ) ); VERIFY( CompDbl( fmax( 2.0, 1.0), 2.0 ) ); VERIFY( CompDbl( fmax( -2.0, -1.0), -1.0 ) ); VERIFY( CompDbl( fmin( 2.0, 1.0), 1.0 ) ); VERIFY( CompDbl( fmin( -2.0, -1.0), -2.0 ) ); VERIFY( CompDbl( fma( 2.0, 3.0, 4.0), 10.0 ) ); VERIFY( CompDbl( fma( 2.0, 3.0, -4.0), 2.0 ) ); VERIFY( CompDbl( fma( -2.0, 3.0, 4.0), -2.0 ) ); VERIFY( CompDbl( fma( -2.0, -3.0, 4.0), 10.0 ) ); VERIFY( CompDbl( fdim( 3.0, 2.0), 1.0 ) ); VERIFY( CompDbl( fdim( 2.0, 3.0), 0.0 ) ); VERIFY( CompDbl( nextafter( 1.0, 2.0), 1.0+1.0E-16 ) ); VERIFY( CompDbl( nextafter( 1.0, 0.0), 1.0-1.0E-16 ) ); VERIFY( CompDbl( scalbn( 1.0, 3.0), 8.0 ) ); VERIFY( CompDbl( scalbn( 4.0, 3.0), 32.0 ) ); #endif }
void test_nextafter() { static_assert((std::is_same<decltype(nextafter((double)0, (double)0)), double>::value), ""); static_assert((std::is_same<decltype(nextafterf(0,0)), float>::value), ""); static_assert((std::is_same<decltype(nextafterl(0,0)), long double>::value), ""); assert(nextafter(0,1) == hexfloat<double>(0x1, 0, -1074)); }
double Tile_Engine::get_x_collision_move(double x1, double x2, double y1, double x_size, double y_size) { double pos_x = x1; if (x2 > x1 ) { //Player bewegt sich rechts int y_start = floor(y1/32.0); int y_end = floor(nextafter(y_size+y1, y_size-1)/32.0); int x_start = floor(nextafter(x_size+x1, x_size-1)/32.0); int x_end = floor(nextafter(x_size+x2, x_size-1)/32.0); for (int i = x_start; i <= x_end; i++) { for (int k = y_start; k <= y_end; k++) { if (getTile(i, k)->getType() == COLLIDES) { return pos_x; } } pos_x = (i==x_end)?x2:(double)(i+1)*32.0-x_size;//-nextafter(x_size, x_size-1); } } else if (x2 < x1){ //Player bewegt sich links int y_start = floor(y1/32.0); int y_end = floor(nextafter(y_size+y1, y_size-1)/32.0); int x_start = floor(x1/32.0); int x_end = floor(x2/32.0); for (int i = x_start; i >= x_end; i--) { for (int k = y_start; k <= y_end; k++) { if (getTile(i, k)->getType() == COLLIDES) { return pos_x; } } pos_x = (i==x_end)?x2:(32.0*i); } } return pos_x; }
RGBA32 makeRGBAFromCMYKA(float c, float m, float y, float k, float a) { double colors = 1 - k; int r = static_cast<int>(nextafter(256, 0) * (colors * (1 - c))); int g = static_cast<int>(nextafter(256, 0) * (colors * (1 - m))); int b = static_cast<int>(nextafter(256, 0) * (colors * (1 - y))); return makeRGBA(r, g, b, static_cast<float>(nextafter(256, 0) * a)); }
TEST_F(SerializationTest, FloatingTypesTest) { HasManyFloats hmf; hmf.a = nextafter(10000.0f, 10000.1f); hmf.b = nextafter(20000.0, 20000.1); hmf.c = nextafter(30000.0L, 30000.1L); std::stringstream ss; leap::Serialize(ss, hmf); auto deserialized = leap::Deserialize<HasManyFloats>(ss); ASSERT_EQ(hmf.a, deserialized->a) << "Float datatype not properly round-trip serialized"; ASSERT_EQ(hmf.b, deserialized->b) << "Double datatype not properly round-trip serialized"; ASSERT_EQ(hmf.c, deserialized->c) << "Long double datatype not properly round-trip serialized"; }
ScmObj Scm_MakeBignumFromDouble(double val) { if (LONG_MIN <= val #if SIZEOF_LONG == 4 && val <= LONG_MAX #else && val <= nextafter((double)LONG_MAX, 0.0) #endif ) return Scm_MakeBignumFromSI((long)val); int exponent, sign; ScmObj mantissa = Scm_DecodeFlonum(val, &exponent, &sign); if (!SCM_NUMBERP(mantissa)) { Scm_Error("can't convert %lf to an integer", val); } ScmObj b = Scm_Ash(mantissa, exponent); if (sign < 0) b = Scm_Negate(b); /* always returns bignum */ if (SCM_INTP(b)) { return Scm_MakeBignumFromSI(SCM_INT_VALUE(b)); } else { return b; } }
int main() { double x = 1.0; double y = 1.0; int i = 1; acosh(x); asinh(x); atanh(x); cbrt(x); expm1(x); erf(x); erfc(x); isnan(x); j0(x); j1(x); jn(i,x); ilogb(x); logb(x); log1p(x); rint(x); y0(x); y1(x); yn(i,x); # ifdef _THREAD_SAFE gamma_r(x,&i); lgamma_r(x,&i); # else gamma(x); lgamma(x); # endif hypot(x,y); nextafter(x,y); remainder(x,y); scalb(x,y); return 0; }
/** * Santiago Akle * ICME Stanford University 2014 * * Exemplifies the use of wrightOmega * * */ int main(void) { pfloat r = 0.0; pfloat z = 1.0; pfloat w = 0.0; pfloat maxerr = 0.0; pfloat maxeval = 0.0; pfloat smallest = z; int i = 0; //Caculate the factor that will skip 2^25 floating points pfloat scaling = nextafter(1.0,2.0); //1+eps for(;i<27;i++) scaling = scaling*scaling; for(i=0;i<1E9;i++) { z *= scaling; w = wrightOmega(z); r = w+log(w)-z; r = fabs(r); //abs r r = r/fabs(z); if(r>maxerr) { maxerr = r; maxeval = w; } } pfloat largest = z; printf("Largerst relative error %e achieved at %e\n",maxerr,maxeval); printf("Smallest number evaluated %e largest %e range %e\n",smallest,largest,largest-smallest); }
static bool parseRGBParameters(CSSParserTokenRange& range, RGBA32& result, bool parseAlpha) { ASSERT(range.peek().functionId() == CSSValueRgb || range.peek().functionId() == CSSValueRgba); CSSParserTokenRange args = consumeFunction(range); CSSPrimitiveValue* colorParameter = consumeInteger(args); if (!colorParameter) colorParameter = consumePercent(args, ValueRangeAll); if (!colorParameter) return false; const bool isPercent = colorParameter->isPercentage(); int colorArray[3]; colorArray[0] = clampRGBComponent(*colorParameter); for (int i = 1; i < 3; i++) { if (!consumeCommaIncludingWhitespace(args)) return false; colorParameter = isPercent ? consumePercent(args, ValueRangeAll) : consumeInteger(args); if (!colorParameter) return false; colorArray[i] = clampRGBComponent(*colorParameter); } if (parseAlpha) { if (!consumeCommaIncludingWhitespace(args)) return false; double alpha; if (!consumeNumberRaw(args, alpha)) return false; // Convert the floating pointer number of alpha to an integer in the range [0, 256), // with an equal distribution across all 256 values. int alphaComponent = static_cast<int>(clampTo<double>(alpha, 0.0, 1.0) * nextafter(256.0, 0.0)); result = makeRGBA(colorArray[0], colorArray[1], colorArray[2], alphaComponent); } else { result = makeRGB(colorArray[0], colorArray[1], colorArray[2]); } return args.atEnd(); }
template <int N, typename T> static double test_parse_fixed_r(skiatest::Reporter* reporter, double low, double high, double inc) { double SK_FixedMax_double = nextafter(1 << (sizeof(T) * CHAR_BIT - N - 1), 0.0); double SK_FixedEpsilon_double = (1.0 / (1 << N)); double maxError = 0; char buffer[64]; for (double f = low; f < high; f += inc) { SkString s; // 'sprintf' formatting as expected depends on the current locale being "C". // We currently expect tests and tools to run in the "C" locale. sprintf(buffer, "%.20f", f); T fix; bool b = parse_fixed<N>(buffer, &fix); if (b) { double f2 = fix * SK_FixedEpsilon_double; double error = fabs(f - f2); REPORTER_ASSERT(reporter, error <= SK_FixedEpsilon_double); maxError = SkTMax(maxError, error); } else { REPORTER_ASSERT(reporter, f < -SK_FixedMax_double || SK_FixedMax_double < f); } } //SkDebugf("maxError: %.20f\n", maxError); return maxError; }
jdouble internal_nextafter(jdouble arg1,jdouble arg2){ jdouble result; result = nextafter (arg1,arg2); return result; }
extern "C" void *Texture2D_create(Vec2i &size, void *data, uint32_t type, uint32_t flags) { Texture2D *self = (Texture2D*) alignedMalloc(sizeof(Texture2D)); self->size = size; // Due to float rounding frac(x) can be exactly 1.0f (e.g. for very small // negative x), although it should be strictly smaller than 1.0f. We handle // this case by having sizef slightly smaller than size, such that // frac(x)*sizef is always < size. self->sizef = Vec2f(nextafter((float)size.x, -1.0f), nextafter((float)size.y, -1.0f)); self->halfTexel = Vec2f(0.5f/size.x, 0.5f/size.y); self->data = data; self->get = Texture2D_get_addr(type, flags & TEXTURE_FILTER_NEAREST); return self; }
void Math_nextafter(void *fp) { F_Math_nextafter *f; f = fp; *f->ret = nextafter(f->x, f->y); }
_f_real8 _NEAREST(_f_real8 x, _f_real8 s) { #ifdef KEY /* Bug 10771 */ if (s == (_f_real8) 0.0) { _lerror (_LELVL_ABORT, FENEARZS); } _f_int8 infinity = signbit(s) ? (0x8000000000000000ull | IEEE_64_INFINITY) : IEEE_64_INFINITY; _f_real8 result = nextafter(x, * (_f_real8 *) &infinity); return result; #elif 0 /* KEY Bug 3399 */ /* See comment in _NEAREST_4 */ REGISTER_8 x_reg; int positive_s = (s > (_f_real8) 0.0); if (s == (_f_real8) 0.0) { _lerror (_LELVL_ABORT, FENEARZS); } x_reg.f = x; if (IEEE_64_EXPO_ALL_ONES(x_reg.ui)) { return x; } if (x == (_f_real8) 0.0) { /* either +0.0 or -0.0 */ x_reg.ui = positive_s ? 1 : (IEEE_64_SIGN_BIT | 1); } else { int increment = (positive_s == (x > (_f_real8) 0.0)) ? 1 : -1; x_reg.ui += increment; } return x_reg.f; #else REGISTER_8 s1, s2; s1.f = x; if (s == 0.0) { _lerror (_LELVL_ABORT, FENEARZS); } s2.ui = (s1.f > 0) ? LL_CONST(0x1) : -(LL_CONST(0x1)); if (s1.f == 0.0) { s1.f = (s > 0.0) ? TINY_REAL8_F90 : -TINY_REAL8_F90; } else if (s > 0.0) { s1.ui += s2.ui; } else { s1.ui -= s2.ui; } if (isnormal64(s1.ui)) return s1.f; if (x > 1.0 || x < -1.0) return s1.f; return (0.0); #endif /* KEY */ }
bool Tile_Engine::does_bottom_collide(position _pos, position _size) { int _y = floor((_size.y+_pos.y)/32.0); int x_start = floor(_pos.x/32.0); int x_end = floor(nextafter(_size.x+_pos.x, _size.x-1))/32; for (int i = x_start; i <= x_end; i++) { if (getTile(i, _y)->getType() == COLLIDES) { return COLLIDES; } } return N_COLLIDES; }
static inline bool parseAlphaValue(const CharacterType*& string, const CharacterType* end, const char terminator, int& value) { while (string != end && isHTMLSpace<CharacterType>(*string)) string++; bool negative = false; if (string != end && *string == '-') { negative = true; string++; } value = 0; int length = end - string; if (length < 2) return false; if (string[length - 1] != terminator || !isASCIIDigit(string[length - 2])) return false; if (string[0] != '0' && string[0] != '1' && string[0] != '.') { if (checkForValidDouble(string, end, terminator)) { value = negative ? 0 : 255; string = end; return true; } return false; } if (length == 2 && string[0] != '.') { value = !negative && string[0] == '1' ? 255 : 0; string = end; return true; } if (isTenthAlpha(string, length - 1)) { static const int tenthAlphaValues[] = {0, 25, 51, 76, 102, 127, 153, 179, 204, 230}; value = negative ? 0 : tenthAlphaValues[string[length - 2] - '0']; string = end; return true; } double alpha = 0; if (!parseDouble(string, end, terminator, alpha)) return false; value = negative ? 0 : static_cast<int>(alpha * nextafter(256.0, 0.0)); string = end; return true; }
IGL_INLINE void igl::copyleft::cgal::assign_scalar( const typename CGAL::Epeck::FT & _cgal, float& d) { // FORCE evaluation of the exact type otherwise interval might be huge. const typename CGAL::Epeck::FT cgal = _cgal.exact(); const auto interval = CGAL::to_interval(cgal); d = interval.first; do { const float next = nextafter(d, interval.second); if (CGAL::abs(cgal-d) < CGAL::abs(cgal-next)) break; d = next; } while (d < interval.second); }
IntRect RenderSlider::thumbRect() { if (!m_thumb) return IntRect(); IntRect thumbRect; RenderBox* thumb = toRenderBox(m_thumb->renderer()); thumbRect.setWidth(thumb->style()->width().calcMinValue(contentWidth())); thumbRect.setHeight(thumb->style()->height().calcMinValue(contentHeight())); double fraction = sliderPosition(static_cast<HTMLInputElement*>(node())); IntRect contentRect = contentBoxRect(); if (style()->appearance() == SliderVerticalPart || style()->appearance() == MediaVolumeSliderPart) { thumbRect.setX(contentRect.x() + (contentRect.width() - thumbRect.width()) / 2); thumbRect.setY(contentRect.y() + static_cast<int>(nextafter((contentRect.height() - thumbRect.height()) + 1, 0) * (1 - fraction))); } else { thumbRect.setX(contentRect.x() + static_cast<int>(nextafter((contentRect.width() - thumbRect.width()) + 1, 0) * fraction)); thumbRect.setY(contentRect.y() + (contentRect.height() - thumbRect.height()) / 2); } return thumbRect; }
int main() { float from1 = 0, to1 = nextafterf(0, 1); printf("The next representable float after %.2f (%a) is %.20g (%a)\n", from1, from1, to1, to1); float from2 = 1, to2 = nextafterf(1, 2); printf("The next representable float after %.2f (%a) is %.23f (%a)\n", from2, from2, to2, to2); double from3 = nextafter(0.1, 0), to3 = 0.1; printf("The number 0.1 lies between two valid doubles:\n %.56f (%a)\nand %.55f (%a)\n", from3, from3, to3, to3); { #pragma STDC FENV_ACCESS ON feclearexcept(FE_ALL_EXCEPT); double from4 = DBL_MAX, to4 = nextafter(DBL_MAX, INFINITY); printf("The next representable double after %.2g (%a) is %.23f (%a)\n", from4, from4, to4, to4); if(fetestexcept(FE_OVERFLOW)) puts(" raised FE_OVERFLOW"); if(fetestexcept(FE_INEXACT)) puts(" raised FE_INEXACT"); } // end FENV_ACCESS block }
// all values are in the range of 0 to 1.0 RGBA32 makeRGBAFromHSLA(double hue, double saturation, double lightness, double alpha) { const double scaleFactor = nextafter(256.0, 0.0); if (!saturation) { int greyValue = static_cast<int>(lightness * scaleFactor); return makeRGBA(greyValue, greyValue, greyValue, static_cast<int>(alpha * scaleFactor)); } double temp2 = lightness < 0.5 ? lightness * (1.0 + saturation) : lightness + saturation - lightness * saturation; double temp1 = 2.0 * lightness - temp2; return makeRGBA(static_cast<int>(calcHue(temp1, temp2, hue + 1.0 / 3.0) * scaleFactor), static_cast<int>(calcHue(temp1, temp2, hue) * scaleFactor), static_cast<int>(calcHue(temp1, temp2, hue - 1.0 / 3.0) * scaleFactor), static_cast<int>(alpha * scaleFactor)); }
int main(int argc, char *argv[]) { assert(test(nextafter(0.0, 0.0), 0.0)); assert(test(nextafter(-0.0, 0.0), 0.0)); assert(test(nextafter(0.0, -0.0), -0.0)); assert(test(nextafter(-0.0, -0.0), -0.0)); assert(test(nextafterf(0.0F, 0.0F), 0.0F)); assert(test(nextafterf(-0.0F, 0.0F), 0.0F)); assert(test(nextafterf(0.0F, -0.0F), -0.0F)); assert(test(nextafterf(-0.0F, -0.0F), -0.0F)); assert(test(nextafterl(0.0L, 0.0L), 0.0L)); assert(test(nextafterl(-0.0L, 0.0L), 0.0L)); assert(test(nextafterl(0.0L, -0.0L), -0.0L)); assert(test(nextafterf(-0.0L, -0.0L), -0.0L)); assert(test(nextafter(NAN, 1.0), NAN)); assert(test(nextafter(1.0, NAN), NAN)); assert(test(nextafter(NAN, NAN), NAN)); assert(test(nextafterf(NAN, 1.0F), NAN)); assert(test(nextafterf(1.0F, NAN), NAN)); assert(test(nextafterf(NAN, NAN), NAN)); assert(test(nextafterl(NAN, 1.0L), NAN)); assert(test(nextafterl(1.0L, NAN), NAN)); assert(test(nextafterl(NAN, NAN), NAN)); assert(test(nextafter(0x1.fffffffffffffp+0, INFINITY), 0x1p1)); assert(test(nextafter(0x1p1, -INFINITY), 0x1.fffffffffffffp+0)); assert(test(nextafterf(0x1.fffffep+0f, INFINITY), 0x1p1f)); assert(test(nextafterf(0x1p1f, -INFINITY), 0x1.fffffep+0f)); return (0); }
int main(int argc, char *argv[]) { int i; float f; double d; long double ld; char *eptr; for (i = 1; i < argc; i++) { errno = 0; f = strtof(argv[i], &eptr); f = nextafterf(f, INFINITY); printf("%a (*eptr:%d errno:%d)\n", f, *eptr, errno); errno = 0; d = strtod(argv[i], &eptr); d = nextafter(d, INFINITY); printf("%a (*eptr:%d errno:%d)\n", d, *eptr, errno); errno = 0; ld = strtold(argv[i], &eptr); ld = nextafterl(ld, INFINITY); printf("%La (*eptr:%d errno:%d)\n", ld, *eptr, errno); } return 0; }
static inline GFC_REAL_8 almostone_r8 () { #ifdef HAVE_NEXTAFTER return nextafter (1.0, 0.0); #else static volatile GFC_REAL_8 val = 0.0; GFC_REAL_8 x; if (val != 0.0) return val; val = 0.9999; do { x = val; val = (val + 1.0) / 2.0; } while (val > x && val < 1.0); if (val == 1.0) val = x; return val; #endif }
double epsD(double x) { x = copysign(x, 1.0); double y = nextafter(x, INFINITY); return y-x; }
static char* toStringWithRadix(RadixBuffer& buffer, double number, unsigned radix) { ASSERT(std::isfinite(number)); ASSERT(radix >= 2 && radix <= 36); // Position the decimal point at the center of the string, set // the startOfResultString pointer to point at the decimal point. char* decimalPoint = buffer + sizeof(buffer) / 2; char* startOfResultString = decimalPoint; // Extract the sign. bool isNegative = number < 0; if (std::signbit(number)) number = -number; double integerPart = floor(number); // We use this to test for odd values in odd radix bases. // Where the base is even, (e.g. 10), to determine whether a value is even we need only // consider the least significant digit. For example, 124 in base 10 is even, because '4' // is even. if the radix is odd, then the radix raised to an integer power is also odd. // E.g. in base 5, 124 represents (1 * 125 + 2 * 25 + 4 * 5). Since each digit in the value // is multiplied by an odd number, the result is even if the sum of all digits is even. // // For the integer portion of the result, we only need test whether the integer value is // even or odd. For each digit of the fraction added, we should invert our idea of whether // the number is odd if the new digit is odd. // // Also initialize digit to this value; for even radix values we only need track whether // the last individual digit was odd. bool integerPartIsOdd = integerPart <= static_cast<double>(0x1FFFFFFFFFFFFFull) && static_cast<int64_t>(integerPart) & 1; ASSERT(integerPartIsOdd == static_cast<bool>(fmod(integerPart, 2))); bool isOddInOddRadix = integerPartIsOdd; uint32_t digit = integerPartIsOdd; // Check if the value has a fractional part to convert. double fractionPart = number - integerPart; if (fractionPart) { // Write the decimal point now. *decimalPoint = '.'; // Higher precision representation of the fractional part. Uint16WithFraction fraction(fractionPart); bool needsRoundingUp = false; char* endOfResultString = decimalPoint + 1; // Calculate the delta from the current number to the next & previous possible IEEE numbers. double nextNumber = nextafter(number, std::numeric_limits<double>::infinity()); double lastNumber = nextafter(number, -std::numeric_limits<double>::infinity()); ASSERT(std::isfinite(nextNumber) && !std::signbit(nextNumber)); ASSERT(std::isfinite(lastNumber) && !std::signbit(lastNumber)); double deltaNextDouble = nextNumber - number; double deltaLastDouble = number - lastNumber; ASSERT(std::isfinite(deltaNextDouble) && !std::signbit(deltaNextDouble)); ASSERT(std::isfinite(deltaLastDouble) && !std::signbit(deltaLastDouble)); // We track the delta from the current value to the next, to track how many digits of the // fraction we need to write. For example, if the value we are converting is precisely // 1.2345, so far we have written the digits "1.23" to a string leaving a remainder of // 0.45, and we want to determine whether we can round off, or whether we need to keep // appending digits ('4'). We can stop adding digits provided that then next possible // lower IEEE value is further from 1.23 than the remainder we'd be rounding off (0.45), // which is to say, less than 1.2255. Put another way, the delta between the prior // possible value and this number must be more than 2x the remainder we'd be rounding off // (or more simply half the delta between numbers must be greater than the remainder). // // Similarly we need track the delta to the next possible value, to dertermine whether // to round up. In almost all cases (other than at exponent boundaries) the deltas to // prior and subsequent values are identical, so we don't need track then separately. if (deltaNextDouble != deltaLastDouble) { // Since the deltas are different track them separately. Pre-multiply by 0.5. Uint16WithFraction halfDeltaNext(deltaNextDouble, 1); Uint16WithFraction halfDeltaLast(deltaLastDouble, 1); while (true) { // examine the remainder to determine whether we should be considering rounding // up or down. If remainder is precisely 0.5 rounding is to even. int dComparePoint5 = fraction.comparePoint5(); if (dComparePoint5 > 0 || (!dComparePoint5 && (radix & 1 ? isOddInOddRadix : digit & 1))) { // Check for rounding up; are we closer to the value we'd round off to than // the next IEEE value would be? if (fraction.sumGreaterThanOne(halfDeltaNext)) { needsRoundingUp = true; break; } } else { // Check for rounding down; are we closer to the value we'd round off to than // the prior IEEE value would be? if (fraction < halfDeltaLast) break; } ASSERT(endOfResultString < (buffer + sizeof(buffer) - 1)); // Write a digit to the string. fraction *= radix; digit = fraction.floorAndSubtract(); *endOfResultString++ = radixDigits[digit]; // Keep track whether the portion written is currently even, if the radix is odd. if (digit & 1) isOddInOddRadix = !isOddInOddRadix; // Shift the fractions by radix. halfDeltaNext *= radix; halfDeltaLast *= radix; } } else { // This code is identical to that above, except since deltaNextDouble != deltaLastDouble // we don't need to track these two values separately. Uint16WithFraction halfDelta(deltaNextDouble, 1); while (true) { int dComparePoint5 = fraction.comparePoint5(); if (dComparePoint5 > 0 || (!dComparePoint5 && (radix & 1 ? isOddInOddRadix : digit & 1))) { if (fraction.sumGreaterThanOne(halfDelta)) { needsRoundingUp = true; break; } } else if (fraction < halfDelta) break; ASSERT(endOfResultString < (buffer + sizeof(buffer) - 1)); fraction *= radix; digit = fraction.floorAndSubtract(); if (digit & 1) isOddInOddRadix = !isOddInOddRadix; *endOfResultString++ = radixDigits[digit]; halfDelta *= radix; } } // Check if the fraction needs rounding off (flag set in the loop writing digits, above). if (needsRoundingUp) { // Whilst the last digit is the maximum in the current radix, remove it. // e.g. rounding up the last digit in "12.3999" is the same as rounding up the // last digit in "12.3" - both round up to "12.4". while (endOfResultString[-1] == radixDigits[radix - 1]) --endOfResultString; // Radix digits are sequential in ascii/unicode, except for '9' and 'a'. // E.g. the first 'if' case handles rounding 67.89 to 67.8a in base 16. // The 'else if' case handles rounding of all other digits. if (endOfResultString[-1] == '9') endOfResultString[-1] = 'a'; else if (endOfResultString[-1] != '.') ++endOfResultString[-1]; else { // One other possibility - there may be no digits to round up in the fraction // (or all may be been rounded off already), in which case we may need to // round into the integer portion of the number. Remove the decimal point. --endOfResultString; // In order to get here there must have been a non-zero fraction, in which case // there must be at least one bit of the value's mantissa not in use in the // integer part of the number. As such, adding to the integer part should not // be able to lose precision. ASSERT((integerPart + 1) - integerPart == 1); ++integerPart; } } else { // We only need to check for trailing zeros if the value does not get rounded up. while (endOfResultString[-1] == '0') --endOfResultString; } *endOfResultString = '\0'; ASSERT(endOfResultString < buffer + sizeof(buffer)); } else *decimalPoint = '\0'; BigInteger units(integerPart); // Always loop at least once, to emit at least '0'. do { ASSERT(buffer < startOfResultString); // Read a single digit and write it to the front of the string. // Divide by radix to remove one digit from the value. digit = units.divide(radix); *--startOfResultString = radixDigits[digit]; } while (!!units); // If the number is negative, prepend '-'. if (isNegative) *--startOfResultString = '-'; ASSERT(buffer <= startOfResultString); return startOfResultString; }
EXPORT_C double fma(double x, double y, double z) { #ifndef __SYMBIAN32__ static const double split = 0x1p27 + 1.0; #else static const double split = 134217729; #endif //__SYMBIAN32__ double xs, ys, zs; double c, cc, hx, hy, p, q, tx, ty; double r, rr, s; int oround; int ex, ey, ez; int spread; if (z == 0.0) return (x * y); if (x == 0.0 || y == 0.0) return (x * y + z); /* Results of frexp() are undefined for these cases. */ if (!isfinite(x) || !isfinite(y) || !isfinite(z)) return (x * y + z); xs = frexp(x, &ex); ys = frexp(y, &ey); zs = frexp(z, &ez); oround = fegetround(); spread = ex + ey - ez; /* * If x * y and z are many orders of magnitude apart, the scaling * will overflow, so we handle these cases specially. Rounding * modes other than FE_TONEAREST are painful. */ if (spread > DBL_MANT_DIG * 2) { fenv_t env; feraiseexcept(FE_INEXACT); switch(oround) { case FE_TONEAREST: return (x * y); case FE_TOWARDZERO: if (x > 0.0 ^ y < 0.0 ^ z < 0.0) return (x * y); feholdexcept(&env); r = x * y; if (!fetestexcept(FE_INEXACT)) r = nextafter(r, 0); feupdateenv(&env); return (r); case FE_DOWNWARD: if (z > 0.0) return (x * y); feholdexcept(&env); r = x * y; if (!fetestexcept(FE_INEXACT)) r = nextafter(r, -INFINITY); feupdateenv(&env); return (r); default: /* FE_UPWARD */ if (z < 0.0) return (x * y); feholdexcept(&env); r = x * y; if (!fetestexcept(FE_INEXACT)) r = nextafter(r, INFINITY); feupdateenv(&env); return (r); } } if (spread < -DBL_MANT_DIG) { feraiseexcept(FE_INEXACT); if (!isnormal(z)) feraiseexcept(FE_UNDERFLOW); switch (oround) { case FE_TONEAREST: return (z); case FE_TOWARDZERO: if (x > 0.0 ^ y < 0.0 ^ z < 0.0) return (z); else return (nextafter(z, 0)); case FE_DOWNWARD: if (x > 0.0 ^ y < 0.0) return (z); else return (nextafter(z, -INFINITY)); default: /* FE_UPWARD */ if (x > 0.0 ^ y < 0.0) return (nextafter(z, INFINITY)); else return (z); } } /* * Use Dekker's algorithm to perform the multiplication and * subsequent addition in twice the machine precision. * Arrange so that x * y = c + cc, and x * y + z = r + rr. */ fesetround(FE_TONEAREST); p = xs * split; hx = xs - p; hx += p; tx = xs - hx; p = ys * split; hy = ys - p; hy += p; ty = ys - hy; p = hx * hy; q = hx * ty + tx * hy; c = p + q; cc = p - c + q + tx * ty; zs = ldexp(zs, -spread); r = c + zs; s = r - c; rr = (c - (r - s)) + (zs - s) + cc; spread = ex + ey; if (spread + ilogb(r) > -1023) { fesetround(oround); r = r + rr; } else { /* * The result is subnormal, so we round before scaling to * avoid double rounding. */ #ifndef __SYMBIAN32__ p = ldexp(copysign(0x1p-1022, r), -spread); #else p = ldexp(copysign(0, r), -spread); #endif //__SYMBIAN32__ c = r + p; s = c - r; cc = (r - (c - s)) + (p - s) + rr; fesetround(oround); r = (c + cc) - p; } return (ldexp(r, spread)); }
long double nexttowardl(long double ld, long double td) { return nextafter((double)ld, (double)td); }
double nexttoward(double d, long double td) { return nextafter(d, (double)td); }
float nextafterf (float x, float y) { return (float) nextafter( (double)x, (double)y ); }