Class: Float

Inherits:
Object
  • Object
show all
Defined in:
(unknown)

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.acos(x, rnd = :nearest) ⇒ Float

Returns the arc-cosine of x, rounded in the direction rnd.

Note that since Float.acos(-1.0) returns the floating-point number closest to pi according to the given rounding mode, this number might not be in the output range 0 <= acos(x) < pi of the arc-cosine function; still, the result lies in the image of the output range by the rounding function.

Parameters:

  • x (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



946
947
948
949
950
951
952
953
954
955
956
957
958
959
# File 'ext/crmf/crmf.c', line 946

static VALUE crmf_float_acos(int argc, VALUE *argv, VALUE self)
{
	VALUE x = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "11", &x, &rnd);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	MPFR_DECL_INIT(mpfrx, 53);
	crmf_rbfloat_to_mpfr53(x, mpfrx);
	int t = mpfr_acos(mpfrx, mpfrx, rndt);
	mpfr_subnormalize(mpfrx, t, rndt);
	double d = mpfr_get_d(mpfrx, rndt);
	return DBL2NUM(d);
}

.acosh(x, rnd = :nearest) ⇒ Float

Returns the inverse hyperbolic cosine of x, rounded in the direction rnd.

Parameters:

  • x (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
# File 'ext/crmf/crmf.c', line 1138

static VALUE crmf_float_acosh(int argc, VALUE *argv, VALUE self)
{
	VALUE x = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "11", &x, &rnd);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	MPFR_DECL_INIT(mpfrx, 53);
	crmf_rbfloat_to_mpfr53(x, mpfrx);
	int t = mpfr_acosh(mpfrx, mpfrx, rndt);
	mpfr_subnormalize(mpfrx, t, rndt);
	double d = mpfr_get_d(mpfrx, rndt);
	return DBL2NUM(d);
}

.add(a, b, rnd = :nearest) ⇒ Float

Add a and b, round according to rnd.

Parameters:

  • a (Float)
  • b (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
# File 'ext/crmf/crmf.c', line 275

static VALUE crmf_float_add(int argc, VALUE *argv, VALUE self)
{
	VALUE a = Qnil, b = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	MPFR_DECL_INIT(mpfra, 53);
	MPFR_DECL_INIT(mpfrb, 53);
	rb_scan_args(argc, argv, "21", &a, &b, &rnd);
	crmf_rbfloat_to_mpfr53(a, mpfra);
	crmf_rbfloat_to_mpfr53(b, mpfrb);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	int t = mpfr_add(mpfra, mpfra, mpfrb, rndt);
	mpfr_subnormalize(mpfra, t, rndt);
	double d = mpfr_get_d(mpfra, rndt);
	return DBL2NUM(d);
}

.asin(x, rnd = :nearest) ⇒ Float

Returns the arc-sine of x, rounded in the direction rnd.

Note that since Float.asin(1) returns the floating-point number closest to pi/2 according to the given rounding mode, this number might not be in the output range -pi/2 <= asin(x) < pi/2 of the arc-sine function; still, the result lies in the image of the output range by the rounding function. The same holds for asin(-1).

Parameters:

  • x (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



973
974
975
976
977
978
979
980
981
982
983
984
985
986
# File 'ext/crmf/crmf.c', line 973

static VALUE crmf_float_asin(int argc, VALUE *argv, VALUE self)
{
	VALUE x = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "11", &x, &rnd);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	MPFR_DECL_INIT(mpfrx, 53);
	crmf_rbfloat_to_mpfr53(x, mpfrx);
	int t = mpfr_asin(mpfrx, mpfrx, rndt);
	mpfr_subnormalize(mpfrx, t, rndt);
	double d = mpfr_get_d(mpfrx, rndt);
	return DBL2NUM(d);
}

.asinh(x, rnd = :nearest) ⇒ Float

Returns the inverse hyperbolic sine of x, rounded in the direction rnd.

Parameters:

  • x (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
# File 'ext/crmf/crmf.c', line 1159

static VALUE crmf_float_asinh(int argc, VALUE *argv, VALUE self)
{
	VALUE x = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "11", &x, &rnd);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	MPFR_DECL_INIT(mpfrx, 53);
	crmf_rbfloat_to_mpfr53(x, mpfrx);
	int t = mpfr_asinh(mpfrx, mpfrx, rndt);
	mpfr_subnormalize(mpfrx, t, rndt);
	double d = mpfr_get_d(mpfrx, rndt);
	return DBL2NUM(d);
}

.atan(x, rnd = :nearest) ⇒ Float

Returns the arc-tangent of x, rounded in the direction rnd.

Note that since Float.atan(Float::INFINITY) returns the floating-point number closest to pi/2 according to the given rounding mode, this number might not be in the output range -pi/2 <= atan(x) < pi/2 of the arc-tangent function; still, the result lies in the image of the output range by the rounding function. The same holds for atan(-Inf).

Parameters:

  • x (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
# File 'ext/crmf/crmf.c', line 1000

static VALUE crmf_float_atan(int argc, VALUE *argv, VALUE self)
{
	VALUE x = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "11", &x, &rnd);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	MPFR_DECL_INIT(mpfrx, 53);
	crmf_rbfloat_to_mpfr53(x, mpfrx);
	int t = mpfr_atan(mpfrx, mpfrx, rndt);
	mpfr_subnormalize(mpfrx, t, rndt);
	double d = mpfr_get_d(mpfrx, rndt);
	return DBL2NUM(d);
}

.atan2(y, x, rnd = :nearest) ⇒ Float

Returns the arc-tangent2 of y and x, rounded in the direction rnd.

  • if x > 0, atan2(y, x) = atan(y/x);
  • if x < 0, atan2(y, x) = sign(y)*(Pi - atan(abs(y/x))), thus a number from -Pi to Pi.

As for atan, in case the exact mathematical result is +Pi or -Pi, its rounded result might be outside the function output range.

Float.atan2(y, 0) does not raise any floating-point exception. Special values are handled as described in the ISO C99 and IEEE 754-2008 standards for the atan2 function:

  • atan2(+0, -0) returns +Pi.
  • atan2(-0, -0) returns -Pi.
  • atan2(+0, +0) returns +0.
  • atan2(-0, +0) returns -0.
  • atan2(+0, x) returns +Pi for x < 0.
  • atan2(-0, x) returns -Pi for x < 0.
  • atan2(+0, x) returns +0 for x > 0.
  • atan2(-0, x) returns -0 for x > 0.
  • atan2(y, 0) returns -Pi/2 for y < 0.
  • atan2(y, 0) returns +Pi/2 for y > 0.
  • atan2(+Inf, -Inf) returns +3*Pi/4.
  • atan2(-Inf, -Inf) returns -3*Pi/4.
  • atan2(+Inf, +Inf) returns +Pi/4.
  • atan2(-Inf, +Inf) returns -Pi/4.
  • atan2(+Inf, x) returns +Pi/2 for finite x.
  • atan2(-Inf, x) returns -Pi/2 for finite x.
  • atan2(y, -Inf) returns +Pi for finite y > 0.
  • atan2(y, -Inf) returns -Pi for finite y < 0.
  • atan2(y, +Inf) returns +0 for finite y > 0.
  • atan2(y, +Inf) returns -0 for finite y < 0.

Parameters:

  • y (Float)
  • x (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
# File 'ext/crmf/crmf.c', line 1052

static VALUE crmf_float_atan2(int argc, VALUE *argv, VALUE self)
{
	VALUE y = Qnil, x = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "21", &y, &x, &rnd);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	MPFR_DECL_INIT(mpfry, 53);
	crmf_rbfloat_to_mpfr53(y, mpfry);
	MPFR_DECL_INIT(mpfrx, 53);
	crmf_rbfloat_to_mpfr53(x, mpfrx);
	int t = mpfr_atan2(mpfrx, mpfry, mpfrx, rndt);
	mpfr_subnormalize(mpfrx, t, rndt);
	double d = mpfr_get_d(mpfrx, rndt);
	return DBL2NUM(d);
}

.atanh(x, rnd = :nearest) ⇒ Float

Returns the inverse hyperbolic tangent of x, rounded in the direction rnd.

Parameters:

  • x (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
# File 'ext/crmf/crmf.c', line 1180

static VALUE crmf_float_atanh(int argc, VALUE *argv, VALUE self)
{
	VALUE x = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "11", &x, &rnd);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	MPFR_DECL_INIT(mpfrx, 53);
	crmf_rbfloat_to_mpfr53(x, mpfrx);
	int t = mpfr_atanh(mpfrx, mpfrx, rndt);
	mpfr_subnormalize(mpfrx, t, rndt);
	double d = mpfr_get_d(mpfrx, rndt);
	return DBL2NUM(d);
}

.bits_to_f32(bits) ⇒ Float

Interpret bits (from a 32-bit integer) as a binary32 floating point number.

Parameters:

  • bits (Integer)

Returns:



1763
1764
1765
1766
1767
1768
1769
1770
1771
# File 'ext/crmf/crmf.c', line 1763

static VALUE crmf_float_bits_to_f32(VALUE self, VALUE bits)
{
	uint32_t bts = NUM2ULL(bits);
	union {
		float    f;
		uint32_t u;
	} fu = {.u=bts};
	return DBL2NUM((double)fu.f);
}

.bits_to_f64(bits) ⇒ Float

Interpret bits (from a 64-bit integer) as a binary64 floating point number.

Parameters:

  • bits (Integer)

Returns:



1778
1779
1780
1781
1782
1783
1784
1785
1786
# File 'ext/crmf/crmf.c', line 1778

static VALUE crmf_float_bits_to_f64(VALUE self, VALUE bits)
{
	uint64_t bts = NUM2ULL(bits);
	union {
		double   d;
		uint64_t u;
	} du = {.u=bts};
	return DBL2NUM(du.d);
}

.build_up(sign_bit, exponent_bits, fraction_bits) ⇒ Float

Build a float from its bit fields.

Examples:

Float.build_up(0, 1023,  0) #=>  1.0
Float.build_up(1, 1024,  0) #=> -2.0
Float.build_up(0, 2047,  0) #=>  Infinity
Float.build_up(1, 2047,  0) #=> -Infinity
Float.build_up(0, 2047, 42) #=>  NaN
Float.build_up(0,    0,  0) #=>  0.0
Float.build_up(0,    0,  1) #=>  5.0e-324

Parameters:

  • sign_bit (Integer)

    0 for positive, 1 for negative.

  • exponent_bits (Integer)

    the biased exponent (exponent + 1023), from 0 to 2047.

  • fraction_bits (Integer)

    the fraction bits of the significand, without the implicit leading 1. From 0 to 4503599627370495.

Returns:

See Also:



135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'ext/crmf/crmf.c', line 135

static VALUE crmf_float_build_up(VALUE self, VALUE sign_bit, VALUE exponent_bits, VALUE fraction_bits)
{
	long long sb, eb, fb;
	union {
		double d;
		unsigned long long l;
	} dudul;

	if (!rb_integer_type_p(sign_bit))
		rb_raise(rb_eTypeError, "expecting an integer as sign bit, not a %s", rb_obj_classname(sign_bit));
	sb = NUM2LL(sign_bit);
	if ((sb & 0xfffffffffffffffeULL) != 0)
		rb_raise(rb_eArgError, "sign bit must be 0 or 1");

	if (!rb_integer_type_p(exponent_bits))
		rb_raise(rb_eTypeError, "expecting an integer as exponent bits, not a %s", rb_obj_classname(exponent_bits));
	eb = NUM2LL(exponent_bits);
	if ((eb & 0xfffffffffffff800ULL) != 0)
		rb_raise(rb_eArgError, "exponent bits must be between 0 and 2047");

	if (!rb_integer_type_p(fraction_bits))
		rb_raise(rb_eTypeError, "expecting an integer as fraction bits, not a %s", rb_obj_classname(fraction_bits));
	fb = NUM2LL(fraction_bits);
	if ((fb & 0xfff0000000000000ULL) != 0)
		rb_raise(rb_eArgError, "fraction bits must be between 0 and 4503599627370495");

	dudul.l = (sb << 63) | (eb << 52) | fb;

	return DBL2NUM(dudul.d);
}

.cbrt(a, rnd = :nearest) ⇒ Float

Return the cubic root of a rounded in the direction rnd.

Parameters:

  • a (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



393
394
395
396
397
398
399
400
401
402
403
404
405
406
# File 'ext/crmf/crmf.c', line 393

static VALUE crmf_float_cbrt(int argc, VALUE *argv, VALUE self)
{
	VALUE a = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "11", &a, &rnd);
	MPFR_DECL_INIT(mpfra, 53);
	crmf_rbfloat_to_mpfr53(a, mpfra);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	int t = mpfr_cbrt(mpfra, mpfra, rndt);
	mpfr_subnormalize(mpfra, t, rndt);
	double d = mpfr_get_d(mpfra, rndt);
	return DBL2NUM(d);
}

.cos(x, rnd = :nearest) ⇒ Float

Returns the cosine of x, rounded in the direction rnd.

Parameters:

  • x (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



878
879
880
881
882
883
884
885
886
887
888
889
890
891
# File 'ext/crmf/crmf.c', line 878

static VALUE crmf_float_cos(int argc, VALUE *argv, VALUE self)
{
	VALUE x = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "11", &x, &rnd);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	MPFR_DECL_INIT(mpfrx, 53);
	crmf_rbfloat_to_mpfr53(x, mpfrx);
	int t = mpfr_cos(mpfrx, mpfrx, rndt);
	mpfr_subnormalize(mpfrx, t, rndt);
	double d = mpfr_get_d(mpfrx, rndt);
	return DBL2NUM(d);
}

.cosh(x, rnd = :nearest) ⇒ Float

Returns the hyperbolic cosine of x, rounded in the direction rnd.

Parameters:

  • x (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
# File 'ext/crmf/crmf.c', line 1075

static VALUE crmf_float_cosh(int argc, VALUE *argv, VALUE self)
{
	VALUE x = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "11", &x, &rnd);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	MPFR_DECL_INIT(mpfrx, 53);
	crmf_rbfloat_to_mpfr53(x, mpfrx);
	int t = mpfr_cosh(mpfrx, mpfrx, rndt);
	mpfr_subnormalize(mpfrx, t, rndt);
	double d = mpfr_get_d(mpfrx, rndt);
	return DBL2NUM(d);
}

.dim(a, b, rnd = :nearest) ⇒ Float

Returns the positive difference of a and b rounded in the direction rnd. That is a - b if a > b, +0 if a <= b, and NaN if a or b is NaN.

Parameters:

  • a (Float)
  • b (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
# File 'ext/crmf/crmf.c', line 452

static VALUE crmf_float_dim(int argc, VALUE *argv, VALUE self)
{
	VALUE a = Qnil, b = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "21", &a, &b, &rnd);
	MPFR_DECL_INIT(mpfra, 53);
	MPFR_DECL_INIT(mpfrb, 53);
	crmf_rbfloat_to_mpfr53(a, mpfra);
	crmf_rbfloat_to_mpfr53(b, mpfrb);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	int t = mpfr_dim(mpfra, mpfra, mpfrb, rndt);
	mpfr_subnormalize(mpfra, t, rndt);
	double d = mpfr_get_d(mpfra, rndt);
	return DBL2NUM(d);
}

.div(a, b, rnd = :nearest) ⇒ Float

Divide a by b, rounding according to rnd.

Parameters:

  • a (Float)
  • b (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
# File 'ext/crmf/crmf.c', line 347

static VALUE crmf_float_div(int argc, VALUE *argv, VALUE self)
{
	VALUE a = Qnil, b = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	MPFR_DECL_INIT(mpfra, 53);
	MPFR_DECL_INIT(mpfrb, 53);
	rb_scan_args(argc, argv, "21", &a, &b, &rnd);
	crmf_rbfloat_to_mpfr53(a, mpfra);
	crmf_rbfloat_to_mpfr53(b, mpfrb);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	int t = mpfr_div(mpfra, mpfra, mpfrb, rndt);
	mpfr_subnormalize(mpfra, t, rndt);
	double d = mpfr_get_d(mpfra, rndt);
	return DBL2NUM(d);
}

.exp(x, rnd = :nearest) ⇒ Float

Returns the exponential of x, rounded in the direction rnd.

Parameters:

  • x (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



715
716
717
718
719
720
721
722
723
724
725
726
727
728
# File 'ext/crmf/crmf.c', line 715

static VALUE crmf_float_exp(int argc, VALUE *argv, VALUE self)
{
	VALUE x = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "11", &x, &rnd);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	MPFR_DECL_INIT(mpfrx, 53);
	crmf_rbfloat_to_mpfr53(x, mpfrx);
	int t = mpfr_exp(mpfrx, mpfrx, rndt);
	mpfr_subnormalize(mpfrx, t, rndt);
	double d = mpfr_get_d(mpfrx, rndt);
	return DBL2NUM(d);
}

.exp10(x, rnd = :nearest) ⇒ Float

Returns the 10 power of x, rounded in the direction rnd.

Parameters:

  • x (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



757
758
759
760
761
762
763
764
765
766
767
768
769
770
# File 'ext/crmf/crmf.c', line 757

static VALUE crmf_float_exp10(int argc, VALUE *argv, VALUE self)
{
	VALUE x = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "11", &x, &rnd);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	MPFR_DECL_INIT(mpfrx, 53);
	crmf_rbfloat_to_mpfr53(x, mpfrx);
	int t = mpfr_exp10(mpfrx, mpfrx, rndt);
	mpfr_subnormalize(mpfrx, t, rndt);
	double d = mpfr_get_d(mpfrx, rndt);
	return DBL2NUM(d);
}

.exp2(x, rnd = :nearest) ⇒ Float

Returns the 2 power of x, rounded in the direction rnd.

Parameters:

  • x (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



736
737
738
739
740
741
742
743
744
745
746
747
748
749
# File 'ext/crmf/crmf.c', line 736

static VALUE crmf_float_exp2(int argc, VALUE *argv, VALUE self)
{
	VALUE x = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "11", &x, &rnd);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	MPFR_DECL_INIT(mpfrx, 53);
	crmf_rbfloat_to_mpfr53(x, mpfrx);
	int t = mpfr_exp2(mpfrx, mpfrx, rndt);
	mpfr_subnormalize(mpfrx, t, rndt);
	double d = mpfr_get_d(mpfrx, rndt);
	return DBL2NUM(d);
}

.expm1(x, rnd = :nearest) ⇒ Float

Returns the exp(x) - 1, rounded in the direction rnd.

Parameters:

  • x (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



778
779
780
781
782
783
784
785
786
787
788
789
790
791
# File 'ext/crmf/crmf.c', line 778

static VALUE crmf_float_expm1(int argc, VALUE *argv, VALUE self)
{
	VALUE x = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "11", &x, &rnd);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	MPFR_DECL_INIT(mpfrx, 53);
	crmf_rbfloat_to_mpfr53(x, mpfrx);
	int t = mpfr_expm1(mpfrx, mpfrx, rndt);
	mpfr_subnormalize(mpfrx, t, rndt);
	double d = mpfr_get_d(mpfrx, rndt);
	return DBL2NUM(d);
}

.f32_to_bits(f, rnd = :nearest) ⇒ Integer

Converts the binary64 floating point number f to a binary32 floating point in the direction rnd, then returns the bits (as a 32-bit integer) constituting this 32-bit floating-point number.

Parameters:

  • f (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away

Returns:

  • (Integer)


1811
1812
1813
1814
1815
1816
1817
1818
1819
1820
1821
1822
1823
1824
1825
1826
1827
1828
1829
# File 'ext/crmf/crmf.c', line 1811

static VALUE crmf_float_f32_to_bits(int argc, VALUE *argv, VALUE self)
{
	VALUE f;
	VALUE rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "11", &f, &rnd);
	if (rnd != Qnil) {
		rndt = crmf_sym_to_rnd(rnd);
	}
	double d = NUM2DBL(f);
	MPFR_DECL_INIT(mp, 53);
	mpfr_set_d(mp, d, rndt);
	float flt = mpfr_get_flt(mp, rndt);
	union {
		float    f;
		uint32_t u;
	} fu = {.f=flt};
	return UINT2NUM(fu.u);
}

.f64_to_bits(f) ⇒ Integer

Return the bits (as a 64-bit integer) constituting the binary64 floating point number f.

Parameters:

Returns:

  • (Integer)


1793
1794
1795
1796
1797
1798
1799
1800
1801
# File 'ext/crmf/crmf.c', line 1793

static VALUE crmf_float_f64_to_bits(VALUE self, VALUE f)
{
	double d = NUM2DBL(f);
	union {
		double   d;
		uint64_t u;
	} du = {.d=d};
	return ULL2NUM(du.u);
}

.fma(a, b, c, rnd = :nearest) ⇒ Float

Returns (a times b) + c rounded in the direction rnd. Concerning special values (signed zeros, infinities, NaN), these functions behave like a multiplication followed by a separate addition or subtraction. That is, the fused operation matters only for rounding.

Parameters:

  • a (Float)
  • b (Float)
  • c (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
# File 'ext/crmf/crmf.c', line 479

static VALUE crmf_float_fma(int argc, VALUE *argv, VALUE self)
{
	VALUE a = Qnil, b = Qnil, c = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "31", &a, &b, &c, &rnd);
	MPFR_DECL_INIT(mpfra, 53);
	MPFR_DECL_INIT(mpfrb, 53);
	MPFR_DECL_INIT(mpfrc, 53);
	crmf_rbfloat_to_mpfr53(a, mpfra);
	crmf_rbfloat_to_mpfr53(b, mpfrb);
	crmf_rbfloat_to_mpfr53(c, mpfrc);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	int t = mpfr_fma(mpfra, mpfra, mpfrb, mpfrc, rndt);
	mpfr_subnormalize(mpfra, t, rndt);
	double d = mpfr_get_d(mpfra, rndt);
	return DBL2NUM(d);
}

.fmma(a, b, c, d, rnd = :nearest) ⇒ Float

Returns (a times b) + (c times d) rounded in the direction rnd. In case the computation of a times b overflows or underflows (or that of c times d), the result is computed as if the two intermediate products were computed with rounding toward zero.

Parameters:

  • a (Float)
  • b (Float)
  • c (Float)
  • d (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
# File 'ext/crmf/crmf.c', line 538

static VALUE crmf_float_fmma(int argc, VALUE *argv, VALUE self)
{
	VALUE a = Qnil, b = Qnil, c = Qnil, d = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "41", &a, &b, &c, &d, &rnd);
	MPFR_DECL_INIT(mpfra, 53);
	MPFR_DECL_INIT(mpfrb, 53);
	MPFR_DECL_INIT(mpfrc, 53);
	MPFR_DECL_INIT(mpfrd, 53);
	crmf_rbfloat_to_mpfr53(a, mpfra);
	crmf_rbfloat_to_mpfr53(b, mpfrb);
	crmf_rbfloat_to_mpfr53(c, mpfrc);
	crmf_rbfloat_to_mpfr53(d, mpfrd);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	int t = mpfr_fmma(mpfra, mpfra, mpfrb, mpfrc, mpfrd, rndt);
	mpfr_subnormalize(mpfra, t, rndt);
	double r = mpfr_get_d(mpfra, rndt);
	return DBL2NUM(r);
}

.fmms(a, b, c, d, rnd = :nearest) ⇒ Float

Returns (a times b) - (c times d) rounded in the direction rnd. In case the computation of a times b overflows or underflows (or that of c times d), the result is computed as if the two intermediate products were computed with rounding toward zero.

Parameters:

  • a (Float)
  • b (Float)
  • c (Float)
  • d (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
# File 'ext/crmf/crmf.c', line 570

static VALUE crmf_float_fmms(int argc, VALUE *argv, VALUE self)
{
	VALUE a = Qnil, b = Qnil, c = Qnil, d = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "41", &a, &b, &c, &d, &rnd);
	MPFR_DECL_INIT(mpfra, 53);
	MPFR_DECL_INIT(mpfrb, 53);
	MPFR_DECL_INIT(mpfrc, 53);
	MPFR_DECL_INIT(mpfrd, 53);
	crmf_rbfloat_to_mpfr53(a, mpfra);
	crmf_rbfloat_to_mpfr53(b, mpfrb);
	crmf_rbfloat_to_mpfr53(c, mpfrc);
	crmf_rbfloat_to_mpfr53(d, mpfrd);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	int t = mpfr_fmms(mpfra, mpfra, mpfrb, mpfrc, mpfrd, rndt);
	mpfr_subnormalize(mpfra, t, rndt);
	double r = mpfr_get_d(mpfra, rndt);
	return DBL2NUM(r);
}

.fms(a, b, c, rnd = :nearest) ⇒ Float

Returns (a times b) - c rounded in the direction rnd. Concerning special values (signed zeros, infinities, NaN), these functions behave like a multiplication followed by a separate addition or subtraction. That is, the fused operation matters only for rounding.

Parameters:

  • a (Float)
  • b (Float)
  • c (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
# File 'ext/crmf/crmf.c', line 508

static VALUE crmf_float_fms(int argc, VALUE *argv, VALUE self)
{
	VALUE a = Qnil, b = Qnil, c = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "31", &a, &b, &c, &rnd);
	MPFR_DECL_INIT(mpfra, 53);
	MPFR_DECL_INIT(mpfrb, 53);
	MPFR_DECL_INIT(mpfrc, 53);
	crmf_rbfloat_to_mpfr53(a, mpfra);
	crmf_rbfloat_to_mpfr53(b, mpfrb);
	crmf_rbfloat_to_mpfr53(c, mpfrc);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	int t = mpfr_fms(mpfra, mpfra, mpfrb, mpfrc, rndt);
	mpfr_subnormalize(mpfra, t, rndt);
	double d = mpfr_get_d(mpfra, rndt);
	return DBL2NUM(d);
}

.hypot(a, b, rnd = :nearest) ⇒ Float

Returns the Euclidean norm of x and y, rounded in the direction rnd. That is, the square root of the sum of the squares of x and y. Special values are handled as described in the ISO C99 (Section F.9.4.3) and IEEE 754-2008 (Section 9.2.1) standards: If x or y is an infinity, then +Inf is returned, even if the other number is NaN.

Parameters:

  • a (Float)
  • b (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
# File 'ext/crmf/crmf.c', line 601

static VALUE crmf_float_hypot(int argc, VALUE *argv, VALUE self)
{
	VALUE a = Qnil, b = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "21", &a, &b, &rnd);
	MPFR_DECL_INIT(mpfra, 53);
	MPFR_DECL_INIT(mpfrb, 53);
	crmf_rbfloat_to_mpfr53(a, mpfra);
	crmf_rbfloat_to_mpfr53(b, mpfrb);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	int t = mpfr_hypot(mpfra, mpfra, mpfrb, rndt);
	mpfr_subnormalize(mpfra, t, rndt);
	double d = mpfr_get_d(mpfra, rndt);
	return DBL2NUM(d);
}

.log(x, rnd = :nearest) ⇒ Float

Returns the natural logarithm of x, rounded in the direction rnd. Returns +0 if x is 1 (in all rounding modes), for consistency with the ISO C99 and IEEE 754-2008 standards. Returns -Inf if x is ±0 (i.e., the sign of the zero has no influence on the result).

Parameters:

  • x (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



626
627
628
629
630
631
632
633
634
635
636
637
638
639
# File 'ext/crmf/crmf.c', line 626

static VALUE crmf_float_log(int argc, VALUE *argv, VALUE self)
{
	VALUE x = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "11", &x, &rnd);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	MPFR_DECL_INIT(mpfrx, 53);
	crmf_rbfloat_to_mpfr53(x, mpfrx);
	int t = mpfr_log(mpfrx, mpfrx, rndt);
	mpfr_subnormalize(mpfrx, t, rndt);
	double d = mpfr_get_d(mpfrx, rndt);
	return DBL2NUM(d);
}

.log10(x, rnd = :nearest) ⇒ Float

Returns the logarithm base 10 of x, rounded in the direction rnd. Returns +0 if x is 1 (in all rounding modes), for consistency with the ISO C99 and IEEE 754-2008 standards. Returns -Inf if x is ±0 (i.e., the sign of the zero has no influence on the result).

Parameters:

  • x (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



672
673
674
675
676
677
678
679
680
681
682
683
684
685
# File 'ext/crmf/crmf.c', line 672

static VALUE crmf_float_log10(int argc, VALUE *argv, VALUE self)
{
	VALUE x = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "11", &x, &rnd);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	MPFR_DECL_INIT(mpfrx, 53);
	crmf_rbfloat_to_mpfr53(x, mpfrx);
	int t = mpfr_log10(mpfrx, mpfrx, rndt);
	mpfr_subnormalize(mpfrx, t, rndt);
	double d = mpfr_get_d(mpfrx, rndt);
	return DBL2NUM(d);
}

.log1p(x, rnd = :nearest) ⇒ Float

Returns the natural logarithm of 1 + x, rounded in the direction rnd. Returns +0 if x is -1.

Parameters:

  • x (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



694
695
696
697
698
699
700
701
702
703
704
705
706
707
# File 'ext/crmf/crmf.c', line 694

static VALUE crmf_float_log1p(int argc, VALUE *argv, VALUE self)
{
	VALUE x = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "11", &x, &rnd);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	MPFR_DECL_INIT(mpfrx, 53);
	crmf_rbfloat_to_mpfr53(x, mpfrx);
	int t = mpfr_log1p(mpfrx, mpfrx, rndt);
	mpfr_subnormalize(mpfrx, t, rndt);
	double d = mpfr_get_d(mpfrx, rndt);
	return DBL2NUM(d);
}

.log2(x, rnd = :nearest) ⇒ Float

Returns the logarithm base 2 of x, rounded in the direction rnd. Returns +0 if x is 1 (in all rounding modes), for consistency with the ISO C99 and IEEE 754-2008 standards. Returns -Inf if x is ±0 (i.e., the sign of the zero has no influence on the result).

Parameters:

  • x (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



649
650
651
652
653
654
655
656
657
658
659
660
661
662
# File 'ext/crmf/crmf.c', line 649

static VALUE crmf_float_log2(int argc, VALUE *argv, VALUE self)
{
	VALUE x = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "11", &x, &rnd);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	MPFR_DECL_INIT(mpfrx, 53);
	crmf_rbfloat_to_mpfr53(x, mpfrx);
	int t = mpfr_log2(mpfrx, mpfrx, rndt);
	mpfr_subnormalize(mpfrx, t, rndt);
	double d = mpfr_get_d(mpfrx, rndt);
	return DBL2NUM(d);
}

.mul(a, b, rnd = :nearest) ⇒ Float

Multiply a and b, rounding according to rnd.

Parameters:

  • a (Float)
  • b (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
# File 'ext/crmf/crmf.c', line 323

static VALUE crmf_float_mul(int argc, VALUE *argv, VALUE self)
{
	VALUE a = Qnil, b = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	MPFR_DECL_INIT(mpfra, 53);
	MPFR_DECL_INIT(mpfrb, 53);
	rb_scan_args(argc, argv, "21", &a, &b, &rnd);
	crmf_rbfloat_to_mpfr53(a, mpfra);
	crmf_rbfloat_to_mpfr53(b, mpfrb);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	int t = mpfr_mul(mpfra, mpfra, mpfrb, rndt);
	mpfr_subnormalize(mpfra, t, rndt);
	double d = mpfr_get_d(mpfra, rndt);
	return DBL2NUM(d);
}

.pow(x, y, rnd = :nearest) ⇒ Float

Returns x raised to y, rounded in the direction rnd.

Special values are handled as described in the ISO C99 and IEEE 754-2008 standards for the pow function:

  • pow(±0, y) returns plus or minus infinity for y a negative odd integer.
  • pow(±0, y) returns plus infinity for y negative and not an odd integer.
  • pow(±0, y) returns plus or minus zero for y a positive odd integer.
  • pow(±0, y) returns plus zero for y positive and not an odd integer.
  • pow(-1, ±Inf) returns 1.
  • pow(+1, y) returns 1 for any y, even a NaN.
  • pow(x, ±0) returns 1 for any x, even a NaN.
  • pow(x, y) returns NaN for finite negative x and finite non-integer y.
  • pow(x, -Inf) returns plus infinity for 0 < abs(x) < 1, and plus zero for abs(x) > 1.
  • pow(x, +Inf) returns plus zero for 0 < abs(x) < 1, and plus infinity for abs(x) > 1.
  • pow(-Inf, y) returns minus zero for y a negative odd integer.
  • pow(-Inf, y) returns plus zero for y negative and not an odd integer.
  • pow(-Inf, y) returns minus infinity for y a positive odd integer.
  • pow(-Inf, y) returns plus infinity for y positive and not an odd integer.
  • pow(+Inf, y) returns plus zero for y negative, and plus infinity for y positive.

Parameters:

  • x (Float)
  • y (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
# File 'ext/crmf/crmf.c', line 817

static VALUE crmf_float_pow(int argc, VALUE *argv, VALUE self)
{
	VALUE x = Qnil, y = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "21", &x, &y, &rnd);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	MPFR_DECL_INIT(mpfrx, 53);
	MPFR_DECL_INIT(mpfry, 53);
	crmf_rbfloat_to_mpfr53(x, mpfrx);
	crmf_rbfloat_to_mpfr53(y, mpfry);
	int t = mpfr_pow(mpfrx, mpfrx, mpfry, rndt);
	mpfr_subnormalize(mpfrx, t, rndt);
	double d = mpfr_get_d(mpfrx, rndt);
	return DBL2NUM(d);
}

.pown(x, n, rnd = :nearest) ⇒ Float

Returns x raised to the integer power n, rounded in the direction rnd.

Special values are handled as described in the ISO C99 and IEEE 754-2008 standards for the pow function:

  • pow(±0, n) returns plus or minus infinity for n a negative odd integer.
  • pow(±0, n) returns plus infinity for n negative and not an odd integer.
  • pow(±0, n) returns plus or minus zero for n a positive odd integer.
  • pow(±0, n) returns plus zero for n positive and not an odd integer.
  • pow(+1, n) returns 1 for any n.
  • pow(x, 0) returns 1 for any x, even a NaN.
  • pow(-Inf, n) returns minus zero for n negative and odd.
  • pow(-Inf, n) returns plus zero for n negative and even.
  • pow(-Inf, n) returns minus infinity for n positive and odd.
  • pow(-Inf, n) returns plus infinity for n positive and even.
  • pow(+Inf, n) returns plus zero for n negative, and plus infinity for n positive.

Parameters:

  • x (Float)

    base

  • n (Integer)

    exponent

  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
# File 'ext/crmf/crmf.c', line 854

static VALUE crmf_float_pown(int argc, VALUE *argv, VALUE self)
{
	VALUE x = Qnil, n = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "21", &x, &n, &rnd);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	MPFR_DECL_INIT(mpfrx, 53);
	crmf_rbfloat_to_mpfr53(x, mpfrx);
	if (!rb_integer_type_p(n))
		rb_raise(rb_eTypeError, "expecting an integer as second argument, not a %s", rb_obj_classname(n));
	long int nn = NUM2LL(n);
	int t = mpfr_pow_si(mpfrx, mpfrx, nn, rndt);
	mpfr_subnormalize(mpfrx, t, rndt);
	double d = mpfr_get_d(mpfrx, rndt);
	return DBL2NUM(d);
}

.rootn(a, n, rnd = :nearest) ⇒ Float

Returns the n th root of a rounded in the direction rnd. For n = 0, returns NaN. For n odd (resp. even) and a negative (including −Inf), returns a negative number (resp. NaN). If a is zero, returns zero with the sign obtained by the usual limit rules, i.e., the same sign as a if n is odd, and negative if n is even.

This functions agree with the rootn function of the IEEE 754-2008 standard and the P754/D2.41 draft of the next standard (Section 9.2). Note that it is here restricted to n >= 0. Functions allowing a negative n may be implemented in the future.

Parameters:

  • a (Float)
  • n (Integer)

    n >= 0

  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
# File 'ext/crmf/crmf.c', line 424

static VALUE crmf_float_rootn(int argc, VALUE *argv, VALUE self)
{
	VALUE a = Qnil, n = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "21", &a, &n, &rnd);
	MPFR_DECL_INIT(mpfra, 53);
	crmf_rbfloat_to_mpfr53(a, mpfra);
	if (!rb_integer_type_p(n))
		rb_raise(rb_eTypeError, "expecting an integer as second argument, not a %s", rb_obj_classname(n));
	if (rb_funcall(n, id_syminf, 1, INT2NUM(0)) == Qtrue)
		rb_raise(rb_eRangeError, "n must be >= 0, not %" PRIsVALUE, n);
	unsigned long int nn = NUM2ULL(n);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	int t = mpfr_rootn_ui(mpfra, mpfra, nn, rndt);
	mpfr_subnormalize(mpfra, t, rndt);
	double d = mpfr_get_d(mpfra, rndt);
	return DBL2NUM(d);
}

.sin(x, rnd = :nearest) ⇒ Float

Returns the sine of x, rounded in the direction rnd.

Parameters:

  • x (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



899
900
901
902
903
904
905
906
907
908
909
910
911
912
# File 'ext/crmf/crmf.c', line 899

static VALUE crmf_float_sin(int argc, VALUE *argv, VALUE self)
{
	VALUE x = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "11", &x, &rnd);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	MPFR_DECL_INIT(mpfrx, 53);
	crmf_rbfloat_to_mpfr53(x, mpfrx);
	int t = mpfr_sin(mpfrx, mpfrx, rndt);
	mpfr_subnormalize(mpfrx, t, rndt);
	double d = mpfr_get_d(mpfrx, rndt);
	return DBL2NUM(d);
}

.sinh(x, rnd = :nearest) ⇒ Float

Returns the hyperbolic sine of x, rounded in the direction rnd.

Parameters:

  • x (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
# File 'ext/crmf/crmf.c', line 1096

static VALUE crmf_float_sinh(int argc, VALUE *argv, VALUE self)
{
	VALUE x = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "11", &x, &rnd);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	MPFR_DECL_INIT(mpfrx, 53);
	crmf_rbfloat_to_mpfr53(x, mpfrx);
	int t = mpfr_sinh(mpfrx, mpfrx, rndt);
	mpfr_subnormalize(mpfrx, t, rndt);
	double d = mpfr_get_d(mpfrx, rndt);
	return DBL2NUM(d);
}

.sqrt(a, rnd = :nearest) ⇒ Float

Return the square root of a rounded in the direction rnd. Returns −0 if a is −0, to be consistent with the IEEE 754 standard. Returns NaN if op is negative.

Parameters:

  • a (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



372
373
374
375
376
377
378
379
380
381
382
383
384
385
# File 'ext/crmf/crmf.c', line 372

static VALUE crmf_float_sqrt(int argc, VALUE *argv, VALUE self)
{
	VALUE a = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "11", &a, &rnd);
	MPFR_DECL_INIT(mpfra, 53);
	crmf_rbfloat_to_mpfr53(a, mpfra);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	int t = mpfr_sqrt(mpfra, mpfra, rndt);
	mpfr_subnormalize(mpfra, t, rndt);
	double d = mpfr_get_d(mpfra, rndt);
	return DBL2NUM(d);
}

.sub(a, b, rnd = :nearest) ⇒ Float

Subtract b from a, round according to rnd.

Parameters:

  • a (Float)
  • b (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
# File 'ext/crmf/crmf.c', line 299

static VALUE crmf_float_sub(int argc, VALUE *argv, VALUE self)
{
	VALUE a = Qnil, b = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	MPFR_DECL_INIT(mpfra, 53);
	MPFR_DECL_INIT(mpfrb, 53);
	rb_scan_args(argc, argv, "21", &a, &b, &rnd);
	crmf_rbfloat_to_mpfr53(a, mpfra);
	crmf_rbfloat_to_mpfr53(b, mpfrb);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	int t = mpfr_sub(mpfra, mpfra, mpfrb, rndt);
	mpfr_subnormalize(mpfra, t, rndt);
	double d = mpfr_get_d(mpfra, rndt);
	return DBL2NUM(d);
}

.tan(x, rnd = :nearest) ⇒ Float

Returns the tangent of x, rounded in the direction rnd.

Parameters:

  • x (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



920
921
922
923
924
925
926
927
928
929
930
931
932
933
# File 'ext/crmf/crmf.c', line 920

static VALUE crmf_float_tan(int argc, VALUE *argv, VALUE self)
{
	VALUE x = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "11", &x, &rnd);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	MPFR_DECL_INIT(mpfrx, 53);
	crmf_rbfloat_to_mpfr53(x, mpfrx);
	int t = mpfr_tan(mpfrx, mpfrx, rndt);
	mpfr_subnormalize(mpfrx, t, rndt);
	double d = mpfr_get_d(mpfrx, rndt);
	return DBL2NUM(d);
}

.tanh(x, rnd = :nearest) ⇒ Float

Returns the hyperbolic tangent of x, rounded in the direction rnd.

Parameters:

  • x (Float)
  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away



1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
# File 'ext/crmf/crmf.c', line 1117

static VALUE crmf_float_tanh(int argc, VALUE *argv, VALUE self)
{
	VALUE x = Qnil, rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "11", &x, &rnd);
	if (rnd != Qnil)
		rndt = crmf_sym_to_rnd(rnd);
	MPFR_DECL_INIT(mpfrx, 53);
	crmf_rbfloat_to_mpfr53(x, mpfrx);
	int t = mpfr_tanh(mpfrx, mpfrx, rndt);
	mpfr_subnormalize(mpfrx, t, rndt);
	double d = mpfr_get_d(mpfrx, rndt);
	return DBL2NUM(d);
}

Instance Method Details

#break_downHash{Symbol => Object}

Returns a hash containing the components of the float.

The returned hash contains the folowing fields:

  • :sign_bit An integer: 0 for positive, 1 for negative. Corresponds to bit 63.
  • :exponent_bits The biased exponent as an integer. Corresponds to bits 62 downto 52.
  • :fraction_bits The stored fraction bits (without the implicit leading 1). Corresponds to bits 51 downto 0.
  • :sign An integer: 1 for positive, -1 for negative
  • :flag A symbol, either :nan, :infinite, :zero, :subnormal or nil.
  • :exponent The unbiased exponent as an integer.
  • :isignificand An integer corresponding to fraction_bits plus the leading implicit 1 if not a subnormal.
  • :significand The significand part as a float, in the range [1.0, 2.0[, or less than 1.0 if the number is subnormal.

The number can be retreived with sign * 2**exponent * significand

Returns:

  • (Hash{Symbol => Object})

See Also:



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'ext/crmf/crmf.c', line 65

static VALUE crmf_float_break_down(VALUE self)
{
	union {
		double d;
		unsigned long long l;
	} dudul;
	dudul.d = NUM2DBL(self);
	unsigned long long sign = (dudul.l >> 63) & 1;
	unsigned long long expo = (dudul.l >> 52) & 0x7ff;
	unsigned long long frac =  dudul.l & 0x000fffffffffffffULL;
	VALUE h = rb_hash_new();
	rb_hash_aset(h, rb_id2sym(id_sign_bit), ULL2NUM(sign));
	rb_hash_aset(h, rb_id2sym(id_exponent_bits), RB_ULL2NUM(expo));
	rb_hash_aset(h, rb_id2sym(id_fraction_bits), RB_ULL2NUM(frac));
	rb_hash_aset(h, rb_id2sym(id_sign), INT2NUM((sign == 0) ? 1 : -1));

	if (expo == 0x7ffULL) {
		if (frac == 0ULL) // Infinity
			rb_hash_aset(h, rb_id2sym(id_flag), rb_id2sym(id_infinity));
		else // NaN
			rb_hash_aset(h, rb_id2sym(id_flag), rb_id2sym(id_nan));
	}
	else if (expo == 0ULL) {
		if (frac == 0ULL) { // Zero
			rb_hash_aset(h, rb_id2sym(id_flag), rb_id2sym(id_zero));
			rb_hash_aset(h, rb_id2sym(id_isignificand), INT2NUM(0));
			rb_hash_aset(h, rb_id2sym(id_exponent), INT2NUM(-1022));
			rb_hash_aset(h, rb_id2sym(id_significand), DBL2NUM(0.0));
		}
		else { // Subnormal
			rb_hash_aset(h, rb_id2sym(id_flag), rb_id2sym(id_subnormal));
			rb_hash_aset(h, rb_id2sym(id_isignificand), RB_ULL2NUM(frac));
			rb_hash_aset(h, rb_id2sym(id_exponent), INT2NUM(-1022));
			expo = 1023;
			while ((frac & 0x0010000000000000ULL) == 0ULL) {
				frac <<= 1;
				expo -= 1;
			}
			dudul.l = (expo << 52) | (frac & 0x000fffffffffffffULL);
			rb_hash_aset(h, rb_id2sym(id_significand), DBL2NUM(dudul.d));
		}
	}
	else {
		rb_hash_aset(h, rb_id2sym(id_flag), Qnil);
		rb_hash_aset(h, rb_id2sym(id_isignificand), ULL2NUM(frac | 0x10000000000000ULL));
		rb_hash_aset(h, rb_id2sym(id_exponent), INT2NUM((int)expo - 1023));
		dudul.l &= 0x000fffffffffffffULL;
		dudul.l |= 0x3ff0000000000000ULL;
		rb_hash_aset(h, rb_id2sym(id_significand), DBL2NUM(dudul.d));
	}

	return h;
}

#subnormal?Boolean

Tels if the float is subnormal. That is, if its biased exponent is 0 and its fraction part is not null.

Returns:

  • (Boolean)


171
172
173
174
175
176
177
178
179
180
181
182
183
# File 'ext/crmf/crmf.c', line 171

static VALUE crmf_float_is_subnormal(VALUE self)
{
	union dul {
		double d;
		unsigned long long l;
	} dudul;
	dudul.d = NUM2DBL(self);
	unsigned long long expo = (dudul.l >> 52) & 0x7ff;
	unsigned long long frac =  dudul.l & 0x000fffffffffffffULL;
	if (expo == 0ULL && frac != 0ULL)
		return Qtrue;
	return Qfalse;
}

#to_f32(rnd = :nearest) ⇒ Float

Round a Float to a binary32 in the direction rnd.

Parameters:

  • rnd (Symbol) (defaults to: :nearest)

    :nearest, :down, :up, :zero or :away

Returns:



1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
# File 'ext/crmf/crmf.c', line 1744

static VALUE crmf_float_to_f32(int argc, VALUE *argv, VALUE self)
{
	VALUE rnd = Qnil;
	mpfr_rnd_t rndt = MPFR_RNDN;
	rb_scan_args(argc, argv, "01", &rnd);
	if (rnd != Qnil) {
		rndt = crmf_sym_to_rnd(rnd);
	}
	MPFR_DECL_INIT(mp, 53);
	mpfr_set_d(mp, NUM2DBL(self), rndt);
	float f = mpfr_get_flt(mp, rndt);
	return DBL2NUM((double)f);
}