gmp 0.5.3 → 0.5.23

Sign up to get free protection for your applications and to get access to all the features.
data/ext/gmp.c CHANGED
@@ -98,55 +98,6 @@ static VALUE r_gmpfsg_set_default_prec(VALUE klass, VALUE arg)
98
98
  }
99
99
 
100
100
  #ifdef MPFR
101
- static VALUE r_gmpfsg_get_default_rounding_mode(VALUE klass)
102
- {
103
- (void)klass;
104
- const char *rounding_string_val;
105
- rounding_string_val = mpfr_print_rnd_mode (mpfr_get_default_rounding_mode ());
106
- if ( rounding_string_val == NULL ) {
107
- return Qnil;
108
- }
109
- else {
110
- return rb_const_get (mGMP, rb_intern (rounding_string_val));
111
- }
112
- }
113
-
114
- static VALUE r_gmpfsg_set_default_rounding_mode(VALUE klass, VALUE arg)
115
- {
116
- (void)klass;
117
- VALUE mode;
118
- if (GMPRND_P(arg)) {
119
- mode = rb_funcall (arg, rb_intern("mode"), 0);
120
- if (FIX2INT(mode) < 0 || FIX2INT(mode) > 3) {
121
- rb_raise(rb_eRangeError, "rounding mode must be one of the rounding mode constants.");
122
- }
123
- } else {
124
- rb_raise(rb_eTypeError, "rounding mode must be one of the rounding mode constants.");
125
- }
126
-
127
- switch (FIX2INT(mode)) {
128
- case 0:
129
- mpfr_set_default_rounding_mode (GMP_RNDN);
130
- break;
131
- case 1:
132
- mpfr_set_default_rounding_mode (GMP_RNDZ);
133
- break;
134
- case 2:
135
- mpfr_set_default_rounding_mode (GMP_RNDU);
136
- break;
137
- case 3:
138
- mpfr_set_default_rounding_mode (GMP_RNDD);
139
- break;
140
- #if MPFR_VERSION_MAJOR>2
141
- case 4:
142
- mpfr_set_default_rounding_mode (MPFR_RNDA);
143
- break;
144
- #endif
145
- }
146
-
147
- return Qnil;
148
- }
149
-
150
101
  mp_rnd_t r_get_rounding_mode(VALUE rnd)
151
102
  {
152
103
  VALUE mode;
@@ -193,12 +144,13 @@ mp_rnd_t r_get_rounding_mode(VALUE rnd)
193
144
 
194
145
  void Init_gmp() {
195
146
  mGMP = rb_define_module("GMP");
196
- rb_define_const(mGMP, "GMP_VERSION", rb_str_new2(gmp_version));
197
- rb_define_const(mGMP, "GMP_CC", rb_str_new2(__GMP_CC));
198
- rb_define_const(mGMP, "GMP_CFLAGS", rb_str_new2(__GMP_CFLAGS));
147
+ rb_define_const(mGMP, "GMP_VERSION", rb_str_new2(gmp_version));
148
+ rb_define_const(mGMP, "GMP_CC", rb_str_new2(__GMP_CC));
149
+ rb_define_const(mGMP, "GMP_CFLAGS", rb_str_new2(__GMP_CFLAGS));
199
150
  rb_define_const(mGMP, "GMP_BITS_PER_LIMB", INT2FIX(mp_bits_per_limb));
151
+ rb_define_const(mGMP, "GMP_NUMB_MAX", ULONG2NUM(GMP_NUMB_MAX));
200
152
  #ifdef MPFR
201
- rb_define_const(mGMP, "MPFR_VERSION", rb_str_new2(MPFR_VERSION_STRING));
153
+ rb_define_const(mGMP, "MPFR_VERSION", rb_str_new2(MPFR_VERSION_STRING));
202
154
  rb_define_const(mGMP, "MPFR_PREC_MIN", INT2FIX(MPFR_PREC_MIN));
203
155
  rb_define_const(mGMP, "MPFR_PREC_MAX", INT2FIX(MPFR_PREC_MAX));
204
156
  #endif /* MPFR */
@@ -220,8 +172,6 @@ void Init_gmp() {
220
172
  rb_define_singleton_method (cGMP_F, "default_prec=", r_gmpfsg_set_default_prec, 1);
221
173
  #ifdef MPFR
222
174
  cGMP_Rnd = rb_define_class_under (mGMP, "Rnd", rb_cObject);
223
- rb_define_singleton_method (cGMP_F, "default_rounding_mode", r_gmpfsg_get_default_rounding_mode, 0);
224
- rb_define_singleton_method (cGMP_F, "default_rounding_mode=", r_gmpfsg_set_default_rounding_mode, 1);
225
175
  init_gmprnd ();
226
176
  #endif /* MPFR */
227
177
  rb_define_method (cGMP_F, "coerce", r_gmpf_coerce, 1); // new method - testing
data/ext/gmpf.c CHANGED
@@ -10,17 +10,6 @@
10
10
  * Instances of this class can store variables of the type mpf_t. This class
11
11
  * also contains many methods that act as the functions for mpf_t variables,
12
12
  * as well as a few methods that attempt to make this library more Ruby-ish.
13
- *
14
- * The following list is just a simple checklist for me, really. A better
15
- * reference should be found in the rdocs.
16
- *
17
- * Ruby method C Extension function GMP function
18
- * to_d r_gmpf_to_d mpf_get_d
19
- * to_s r_gmpf_to_s mpf_get_s
20
- * + r_gmpf_add mpf_add
21
- * - r_gmpf_sub mpf_sub
22
- * * r_gmpf_mul mpf_mul
23
- * / r_gmpf_div mpf_div
24
13
  */
25
14
 
26
15
  /**********************************************************************
@@ -250,6 +239,12 @@ VALUE r_gmpmod_f(int argc, VALUE *argv, VALUE module)
250
239
  * Converting Floats *
251
240
  **********************************************************************/
252
241
 
242
+ /*
243
+ * call-seq:
244
+ * x.to_d
245
+ *
246
+ * Returns _x_ as a Float.
247
+ */
253
248
  VALUE r_gmpf_to_d(VALUE self)
254
249
  {
255
250
  MP_FLOAT *self_val;
@@ -260,12 +255,10 @@ VALUE r_gmpf_to_d(VALUE self)
260
255
 
261
256
  #ifdef MPFR
262
257
  /*
263
- * Document-method: to_s
264
- *
265
258
  * call-seq:
266
- * float.to_s
259
+ * x.to_s
267
260
  *
268
- * Returns the decimal representation of +float+, as a string.
261
+ * Returns the decimal representation of _x_, as a String.
269
262
  */
270
263
  VALUE r_gmpf_to_s(VALUE self)
271
264
  {
@@ -301,12 +294,10 @@ VALUE r_gmpf_to_s(VALUE self)
301
294
  }
302
295
  #else
303
296
  /*
304
- * Document-method: to_s
305
- *
306
297
  * call-seq:
307
- * float.to_s
298
+ * x.to_s
308
299
  *
309
- * Returns the decimal representation of +float+, as a string.
300
+ * Returns the decimal representation of _x_, as a string.
310
301
  */
311
302
  VALUE r_gmpf_to_s(VALUE self)
312
303
  {
@@ -346,9 +337,9 @@ VALUE r_gmpf_to_s(VALUE self)
346
337
  #ifndef MPFR
347
338
  /*
348
339
  * call-seq:
349
- * float + other
340
+ * x + y
350
341
  *
351
- * Returns the sum of +float+ and +other+. +other+ can be
342
+ * Returns the sum of _x_ and _y_. _y_ must be an instance of:
352
343
  * * GMP::Z
353
344
  * * Fixnum
354
345
  * * GMP::Q
@@ -404,9 +395,9 @@ VALUE r_gmpf_add(VALUE self, VALUE arg)
404
395
  #else
405
396
  /*
406
397
  * call-seq:
407
- * float + other
398
+ * x + y
408
399
  *
409
- * Returns the sum of +float+ and +other+. +other+ can be
400
+ * Returns the sum of _x_ and _y_. _y_ must be an instance of:
410
401
  * * GMP::Z
411
402
  * * Fixnum
412
403
  * * GMP::Q
@@ -470,9 +461,9 @@ DEFUN_F_ZQXFBD2F(mul)
470
461
 
471
462
  /*
472
463
  * call-seq:
473
- * float1 - float2
464
+ * x - y
474
465
  *
475
- * Subtracts +float2+ from +float1+. +float2+ can be
466
+ * Subtracts _y_ from _x_. _y_ must be an instance of:
476
467
  * * GMP::Z
477
468
  * * Fixnum
478
469
  * * GMP::Q
@@ -528,9 +519,9 @@ VALUE r_gmpf_sub(VALUE self, VALUE arg)
528
519
 
529
520
  /*
530
521
  * call-seq:
531
- * float * other
522
+ * x * y
532
523
  *
533
- * Returns the product of +float+ and +other+. +other+ can be
524
+ * Returns the product of _x_ and _y_. _y_ can be
534
525
  * * GMP::Z
535
526
  * * Fixnum
536
527
  * * GMP::Q
@@ -544,7 +535,6 @@ VALUE r_gmpf_mul(VALUE self, VALUE arg)
544
535
  MP_RAT *arg_val_q;
545
536
  MP_INT *arg_val_z;
546
537
  VALUE res;
547
- //unsigned long prec;
548
538
  mpfr_prec_t prec;
549
539
 
550
540
  mpf_get_struct_prec (self, self_val, prec);
@@ -587,10 +577,10 @@ VALUE r_gmpf_mul(VALUE self, VALUE arg)
587
577
 
588
578
  /*
589
579
  * call-seq:
590
- * float ** integer
580
+ * x ** y
591
581
  *
592
- * Returns +float+ raised to the +integer+ power. +integer+ must be
593
- * * Fixnum or Bignum
582
+ * Returns _x_ raised to the _y_ power. _y_ must be
583
+ * * an instance of Fixnum or Bignum
594
584
  * * non-negative
595
585
  */
596
586
  VALUE r_gmpf_pow(VALUE self, VALUE arg)
@@ -617,65 +607,11 @@ VALUE r_gmpf_pow(VALUE self, VALUE arg)
617
607
  return res;
618
608
  }
619
609
 
620
- #ifdef MPFR
621
- /*
622
- * call-seq:
623
- * float ** other
624
- *
625
- * Returns +float+ raised to the +other+ power. +other+ must be an instance of
626
- * * Fixnum
627
- * * Bignum
628
- * * Float
629
- * * GMP::Z
630
- * * GMP::F
631
- */
632
- /*VALUE r_gmpfr_pow(int argc, VALUE *argv, VALUE self)
633
- {
634
- MP_FLOAT *self_val, *res_val, *arg_val_f;
635
- VALUE arg, rnd_mode, res_prec;
636
- unsigned long arg_val, prec, res_prec_value;
637
- mp_rnd_t rnd_mode_value;
638
- MP_INT *arg_val_z;
639
- VALUE res;
640
-
641
- rb_scan_args (argc, argv, "12", &arg, &rnd_mode, &res_prec);
642
-
643
- mpf_get_struct_prec (self, self_val, prec);
644
-
645
- if (NIL_P (rnd_mode)) { rnd_mode_value = __gmp_default_rounding_mode; }
646
- else { rnd_mode_value = r_get_rounding_mode(rnd_mode); }
647
- if (NIL_P (res_prec)) { res_prec_value = prec; }
648
- else { res_prec_value = FIX2INT (res_prec); }
649
- mpf_make_struct_init (res, res_val, res_prec_value);
650
-
651
- if (FIXNUM_P(arg)) {
652
- mpfr_pow_ui(res_val, self_val, FIX2NUM(arg), rnd_mode_value);
653
- } else if (BIGNUM_P(arg)) {
654
- mpz_temp_from_bignum(arg_val_z, arg);
655
- mpfr_pow_z (res_val, self_val, arg_val_z, rnd_mode_value);
656
- mpz_temp_free(arg_val_z);
657
- } else if (FLOAT_P(arg)) {
658
- r_mpf_set_d (res_val, NUM2DBL(arg));
659
- mpfr_pow (res_val, self_val, res_val, rnd_mode_value);
660
- } else if (GMPZ_P(arg)) {
661
- mpz_get_struct (arg, arg_val_z);
662
- mpfr_pow_z (res_val, self_val, arg_val_z, rnd_mode_value);
663
- } else if (GMPF_P(arg)) {
664
- mpf_get_struct (arg, arg_val_f);
665
- mpfr_pow (res_val, self_val, arg_val_f, rnd_mode_value);
666
- } else {
667
- typeerror(ZFXBD);
668
- }
669
-
670
- return res;
671
- }*/
672
- #endif
673
-
674
610
  /*
675
611
  * call-seq:
676
- * float1 / float2
612
+ * x / y
677
613
  *
678
- * Divides +float1+ by +float2+. +float2+ can be
614
+ * Divides _x_ by _y_. _y_ can be
679
615
  * * GMP::Z
680
616
  * * Fixnum
681
617
  * * GMP::Q
@@ -729,45 +665,93 @@ VALUE r_gmpf_div(VALUE self, VALUE arg)
729
665
  return res;
730
666
  }
731
667
 
668
+ #ifdef MPFR
669
+ /*
670
+ * call-seq:
671
+ * float ** other
672
+ *
673
+ * Returns _x_ raised to the _y_ power. _y_ must be an instance of
674
+ * * Fixnum
675
+ * * Bignum
676
+ * * Float
677
+ * * GMP::Z
678
+ * * GMP::F
679
+ */
680
+ /*VALUE r_gmpfr_pow(int argc, VALUE *argv, VALUE self)
681
+ {
682
+ MP_FLOAT *self_val, *res_val, *arg_val_f;
683
+ VALUE arg, rnd_mode, res_prec;
684
+ unsigned long arg_val, prec, res_prec_value;
685
+ mp_rnd_t rnd_mode_value;
686
+ MP_INT *arg_val_z;
687
+ VALUE res;
688
+
689
+ rb_scan_args (argc, argv, "12", &arg, &rnd_mode, &res_prec);
690
+
691
+ mpf_get_struct_prec (self, self_val, prec);
692
+
693
+ if (NIL_P (rnd_mode)) { rnd_mode_value = __gmp_default_rounding_mode; }
694
+ else { rnd_mode_value = r_get_rounding_mode(rnd_mode); }
695
+ if (NIL_P (res_prec)) { res_prec_value = prec; }
696
+ else { res_prec_value = FIX2INT (res_prec); }
697
+ mpf_make_struct_init (res, res_val, res_prec_value);
698
+
699
+ if (FIXNUM_P(arg)) {
700
+ mpfr_pow_ui(res_val, self_val, FIX2NUM(arg), rnd_mode_value);
701
+ } else if (BIGNUM_P(arg)) {
702
+ mpz_temp_from_bignum(arg_val_z, arg);
703
+ mpfr_pow_z (res_val, self_val, arg_val_z, rnd_mode_value);
704
+ mpz_temp_free(arg_val_z);
705
+ } else if (FLOAT_P(arg)) {
706
+ r_mpf_set_d (res_val, NUM2DBL(arg));
707
+ mpfr_pow (res_val, self_val, res_val, rnd_mode_value);
708
+ } else if (GMPZ_P(arg)) {
709
+ mpz_get_struct (arg, arg_val_z);
710
+ mpfr_pow_z (res_val, self_val, arg_val_z, rnd_mode_value);
711
+ } else if (GMPF_P(arg)) {
712
+ mpf_get_struct (arg, arg_val_f);
713
+ mpfr_pow (res_val, self_val, arg_val_f, rnd_mode_value);
714
+ } else {
715
+ typeerror(ZFXBD);
716
+ }
732
717
 
718
+ return res;
719
+ }*/
720
+ #endif
733
721
 
734
722
  /*
735
723
  * Document-method: neg
736
724
  *
737
725
  * call-seq:
738
- * float.neg
739
- * -float
726
+ * x.neg
727
+ * -x
740
728
  *
741
- * From the GMP Manual:
742
- *
743
- * Returns -+float+.
729
+ * Returns -_x_.
744
730
  */
745
731
  /*
746
732
  * Document-method: neg!
747
733
  *
748
734
  * call-seq:
749
- * float.neg!
735
+ * x.neg!
750
736
  *
751
- * Sets +float+ to -+float+.
737
+ * Sets _x_ to -_x_.
752
738
  */
753
739
  DEFUN_FLOAT2FLOAT(neg,mpf_neg)
754
740
  /*
755
741
  * Document-method: abs
756
742
  *
757
743
  * call-seq:
758
- * float.abs
744
+ * x.abs
759
745
  *
760
- * From the GMP Manual:
761
- *
762
- * Returns the absolute value of +float+.
746
+ * Returns the absolute value of _x_.
763
747
  */
764
748
  /*
765
749
  * Document-method: abs!
766
750
  *
767
751
  * call-seq:
768
- * float.abs!
752
+ * x.abs!
769
753
  *
770
- * Sets +float+ to the absolute value of +float+.
754
+ * Sets _x_ to the absolute value of _x_.
771
755
  */
772
756
  DEFUN_FLOAT2FLOAT(abs,mpf_abs)
773
757
 
@@ -793,7 +777,10 @@ int mpf_cmp_value(MP_FLOAT *self_val, VALUE arg)
793
777
  }
794
778
  }
795
779
 
796
- /* what does really "equal" mean ? it's not obvious */
780
+ /*
781
+ * what does really "equal" mean ? it's not obvious
782
+ * Is this a note that I, SRR, put in here? It is now obvious to me...
783
+ */
797
784
  VALUE r_gmpf_eq(VALUE self, VALUE arg)
798
785
  {
799
786
  MP_FLOAT *self_val;
@@ -820,6 +807,28 @@ DEFUN_FLOAT_CMP(le,<=)
820
807
  DEFUN_FLOAT_CMP(gt,>)
821
808
  DEFUN_FLOAT_CMP(ge,>=)
822
809
 
810
+ /*
811
+ * call-seq:
812
+ * x.sgn
813
+ *
814
+ * Returns +1 if _x_ > 0, 0 if _x_ == 0, and -1 if _x_ < 0.
815
+ */
816
+ VALUE r_gmpf_sgn(VALUE self)
817
+ {
818
+ MP_FLOAT *self_val;
819
+ mpf_get_struct (self, self_val);
820
+ return INT2FIX (mpf_sgn (self_val));
821
+ }
822
+
823
+
824
+ /**********************************************************************
825
+ * Miscellaneous Float Functions *
826
+ **********************************************************************/
827
+
828
+ DEFUN_FLOAT2FLOAT(floor,mpf_floor)
829
+ DEFUN_FLOAT2FLOAT(trunc,mpf_trunc)
830
+ DEFUN_FLOAT2FLOAT(ceil,mpf_ceil)
831
+
823
832
 
824
833
  #ifdef MPFR
825
834
 
@@ -827,15 +836,14 @@ DEFUN_FLOAT_CMP(ge,>=)
827
836
  VALUE r_gmpfr_##name(int argc, VALUE *argv, VALUE self) \
828
837
  { \
829
838
  MP_FLOAT *self_val, *res_val; \
830
- VALUE rnd_mode, res_prec; \
839
+ VALUE rnd_mode, res_prec, res; \
831
840
  mpfr_prec_t prec, res_prec_value; \
832
841
  mp_rnd_t rnd_mode_val; \
833
- VALUE res; \
834
- \
835
- rb_scan_args (argc, argv, "02", &rnd_mode, &res_prec); \
836
842
  \
837
843
  mpf_get_struct_prec (self, self_val, prec); \
838
- if (NIL_P (rnd_mode)) { rnd_mode_val = __gmp_default_rounding_mode; } \
844
+ \
845
+ rb_scan_args (argc, argv, "02", &rnd_mode, &res_prec); \
846
+ if (NIL_P (rnd_mode)) { rnd_mode_val = __gmp_default_rounding_mode; } \
839
847
  else { rnd_mode_val = r_get_rounding_mode(rnd_mode); } \
840
848
  if (NIL_P (res_prec)) { res_prec_value = prec; } \
841
849
  else { res_prec_value = FIX2INT (res_prec); } \
@@ -845,7 +853,31 @@ VALUE r_gmpfr_##name(int argc, VALUE *argv, VALUE self) \
845
853
  return res; \
846
854
  }
847
855
 
848
- #define MPFR_SINGLE_1ARG_FUNCTION(name) \
856
+ #define MPFR_DOUBLE_FUNCTION(name) \
857
+ VALUE r_gmpfr_##name(int argc, VALUE *argv, VALUE self) \
858
+ { \
859
+ MP_FLOAT *self_val, *sin_val, *cos_val; \
860
+ VALUE rnd_mode, sin_prec, cos_prec, sinn, coss; \
861
+ mpfr_prec_t prec, sin_prec_val, cos_prec_val; \
862
+ mp_rnd_t rnd_mode_val; \
863
+ \
864
+ mpf_get_struct_prec (self, self_val, prec); \
865
+ \
866
+ rb_scan_args (argc, argv, "03", &rnd_mode, &sin_prec, &cos_prec); \
867
+ if (NIL_P (rnd_mode)) { rnd_mode_val = __gmp_default_rounding_mode; } \
868
+ else { rnd_mode_val = r_get_rounding_mode(rnd_mode); } \
869
+ if (NIL_P (sin_prec)) { sin_prec_val = prec; } \
870
+ else { sin_prec_val = FIX2INT (sin_prec); } \
871
+ if (NIL_P (cos_prec)) { cos_prec_val = sin_prec_val; } \
872
+ else { cos_prec_val = FIX2INT (cos_prec); } \
873
+ mpf_make_struct_init (sinn, sin_val, sin_prec_val); \
874
+ mpf_make_struct_init (coss, cos_val, cos_prec_val); \
875
+ mpfr_##name (sin_val, cos_val, self_val, rnd_mode_val); \
876
+ \
877
+ return rb_ary_new3(2, sinn, coss); \
878
+ }
879
+
880
+ #define MPFR_SINGLE_LONG_FUNCTION(name) \
849
881
  VALUE r_gmpfr_##name(int argc, VALUE *argv, VALUE self) \
850
882
  { \
851
883
  MP_FLOAT *self_val, *res_val; \
@@ -861,11 +893,35 @@ VALUE r_gmpfr_##name(int argc, VALUE *argv, VALUE self) \
861
893
  if (NIL_P (res_prec)) { res_prec_value = prec; } \
862
894
  else { res_prec_value = FIX2INT (res_prec); } \
863
895
  mpf_make_struct_init (res, res_val, res_prec_value); \
864
- mpfr_##name (res_val, arg1_val, self_val, __gmp_default_rounding_mode); \
896
+ mpfr_##name (res_val, arg1_val, self_val, __gmp_default_rounding_mode); \
865
897
  \
866
898
  return res; \
867
899
  }
868
900
 
901
+ #define MPFR_SINGLE_MPF_FUNCTION(name) \
902
+ VALUE r_gmpfr_##name(int argc, VALUE *argv, VALUE self) \
903
+ { \
904
+ MP_FLOAT *self_val, *arg1_val, *res_val; \
905
+ VALUE arg1, rnd_mode, res_prec; \
906
+ mpfr_prec_t prec, arg1_prec, res_prec_value; \
907
+ VALUE res; \
908
+ mp_rnd_t rnd_mode_val; \
909
+ \
910
+ rb_scan_args (argc, argv, "12", &arg1, &rnd_mode, &res_prec); \
911
+ \
912
+ mpf_get_struct_prec (self, self_val, prec); \
913
+ if (!GMPF_P (arg1)) { typeerror(FD); } \
914
+ mpf_get_struct_prec (arg1, arg1_val, arg1_prec); \
915
+ if (NIL_P (rnd_mode)) { rnd_mode_val = __gmp_default_rounding_mode; } \
916
+ else { rnd_mode_val = r_get_rounding_mode(rnd_mode); } \
917
+ if (NIL_P (res_prec)) { res_prec_value = prec; } \
918
+ else { res_prec_value = FIX2INT (res_prec); } \
919
+ mpf_make_struct_init (res, res_val, res_prec_value); \
920
+ mpfr_##name (res_val, arg1_val, self_val, rnd_mode_val); \
921
+ \
922
+ return res; \
923
+ }
924
+
869
925
  #define MPFR_SINGLE_BOOLEAN_FUNCTION(name) \
870
926
  static VALUE r_gmpfr_##name(VALUE self) \
871
927
  { \
@@ -879,17 +935,26 @@ static VALUE r_gmpfr_##name(VALUE self) \
879
935
  }
880
936
 
881
937
 
882
- #define MPFR_CONST_FUNCTION(name) \
883
- VALUE r_gmpfrsg_##name() \
884
- { \
885
- MP_FLOAT *res_val; \
886
- VALUE res; \
887
- \
888
- mpf_make_struct (res, res_val); \
889
- mpf_init (res_val); \
890
- mpfr_##name (res_val, __gmp_default_rounding_mode); \
891
- \
892
- return res; \
938
+ #define MPFR_CONST_FUNCTION(name) \
939
+ VALUE r_gmpfrsg_##name(int argc, VALUE *argv, VALUE self) \
940
+ { \
941
+ (void)self; \
942
+ MP_FLOAT *res_val; \
943
+ VALUE res; \
944
+ VALUE rnd_mode, prec; \
945
+ mp_rnd_t rnd_mode_val; \
946
+ mpfr_prec_t prec_val; \
947
+ \
948
+ rb_scan_args (argc, argv, "02", &rnd_mode, &prec); \
949
+ \
950
+ if (NIL_P (rnd_mode)) { rnd_mode_val = __gmp_default_rounding_mode; } \
951
+ else { rnd_mode_val = r_get_rounding_mode(rnd_mode); } \
952
+ if (NIL_P (prec)) { prec_val = mpfr_get_default_prec(); } \
953
+ else { prec_val = FIX2INT (prec); } \
954
+ mpf_make_struct_init (res, res_val, prec_val); \
955
+ mpfr_##name (res_val, rnd_mode_val); \
956
+ \
957
+ return res; \
893
958
  }
894
959
 
895
960
  MPFR_SINGLE_FUNCTION(sqrt)
@@ -905,18 +970,18 @@ MPFR_SINGLE_FUNCTION(exp10)
905
970
  MPFR_SINGLE_FUNCTION(cos)
906
971
  MPFR_SINGLE_FUNCTION(sin)
907
972
  MPFR_SINGLE_FUNCTION(tan)
973
+ MPFR_DOUBLE_FUNCTION(sin_cos)
908
974
  MPFR_SINGLE_FUNCTION(sec)
909
975
  MPFR_SINGLE_FUNCTION(csc)
910
976
  MPFR_SINGLE_FUNCTION(cot)
911
-
912
977
  MPFR_SINGLE_FUNCTION(acos)
913
978
  MPFR_SINGLE_FUNCTION(asin)
914
979
  MPFR_SINGLE_FUNCTION(atan)
915
-
980
+ MPFR_SINGLE_MPF_FUNCTION(atan2)
916
981
  MPFR_SINGLE_FUNCTION(cosh)
917
982
  MPFR_SINGLE_FUNCTION(sinh)
918
983
  MPFR_SINGLE_FUNCTION(tanh)
919
-
984
+ MPFR_DOUBLE_FUNCTION(sinh_cosh)
920
985
  MPFR_SINGLE_FUNCTION(sech)
921
986
  MPFR_SINGLE_FUNCTION(csch)
922
987
  MPFR_SINGLE_FUNCTION(coth)
@@ -939,10 +1004,13 @@ MPFR_SINGLE_FUNCTION(erf)
939
1004
  MPFR_SINGLE_FUNCTION(erfc)
940
1005
  MPFR_SINGLE_FUNCTION(j0)
941
1006
  MPFR_SINGLE_FUNCTION(j1)
942
- MPFR_SINGLE_1ARG_FUNCTION(jn)
1007
+ MPFR_SINGLE_LONG_FUNCTION(jn)
943
1008
  MPFR_SINGLE_FUNCTION(y0)
944
1009
  MPFR_SINGLE_FUNCTION(y1)
945
- MPFR_SINGLE_1ARG_FUNCTION(yn)
1010
+ MPFR_SINGLE_LONG_FUNCTION(yn)
1011
+
1012
+ MPFR_SINGLE_MPF_FUNCTION(agm)
1013
+ MPFR_SINGLE_MPF_FUNCTION(hypot)
946
1014
 
947
1015
  MPFR_CONST_FUNCTION(const_log2)
948
1016
  MPFR_CONST_FUNCTION(const_pi)
@@ -1010,32 +1078,84 @@ static VALUE r_gmpfr_pow(VALUE self, VALUE arg)
1010
1078
  return res;
1011
1079
  }
1012
1080
 
1013
- #endif
1014
-
1015
-
1016
1081
  /**********************************************************************
1017
- * _unsorted_ *
1082
+ * Rounding Related Functions *
1018
1083
  **********************************************************************/
1019
1084
 
1020
- DEFUN_FLOAT2FLOAT(floor,mpf_floor)
1021
- DEFUN_FLOAT2FLOAT(trunc,mpf_trunc)
1022
- DEFUN_FLOAT2FLOAT(ceil,mpf_ceil)
1085
+ VALUE r_gmpfsg_get_default_rounding_mode(VALUE klass)
1086
+ {
1087
+ (void)klass;
1088
+ const char *rounding_string_val;
1089
+ rounding_string_val = mpfr_print_rnd_mode (mpfr_get_default_rounding_mode ());
1090
+ if ( rounding_string_val == NULL ) {
1091
+ return Qnil;
1092
+ }
1093
+ else {
1094
+ return rb_const_get (mGMP, rb_intern (rounding_string_val));
1095
+ }
1096
+ }
1023
1097
 
1024
- /*
1025
- * call-seq:
1026
- * float.sgn
1027
- *
1028
- * From the GMP Manual:
1029
- *
1030
- * Returns +1 if +float+ > 0, 0 if +float+ == 0, and -1 if +float+ < 0.
1031
- */
1032
- VALUE r_gmpf_sgn(VALUE self)
1098
+ VALUE r_gmpfsg_set_default_rounding_mode(VALUE klass, VALUE arg)
1099
+ {
1100
+ (void)klass;
1101
+ VALUE mode;
1102
+ if (GMPRND_P(arg)) {
1103
+ mode = rb_funcall (arg, rb_intern("mode"), 0);
1104
+ if (FIX2INT(mode) < 0 || FIX2INT(mode) > 3) {
1105
+ rb_raise(rb_eRangeError, "rounding mode must be one of the rounding mode constants.");
1106
+ }
1107
+ } else {
1108
+ rb_raise(rb_eTypeError, "rounding mode must be one of the rounding mode constants.");
1109
+ }
1110
+
1111
+ switch (FIX2INT(mode)) {
1112
+ case 0:
1113
+ mpfr_set_default_rounding_mode (GMP_RNDN); break;
1114
+ case 1:
1115
+ mpfr_set_default_rounding_mode (GMP_RNDZ); break;
1116
+ case 2:
1117
+ mpfr_set_default_rounding_mode (GMP_RNDU); break;
1118
+ case 3:
1119
+ mpfr_set_default_rounding_mode (GMP_RNDD); break;
1120
+ #if MPFR_VERSION_MAJOR>2
1121
+ case 4:
1122
+ mpfr_set_default_rounding_mode (MPFR_RNDA); break;
1123
+ #endif
1124
+ }
1125
+
1126
+ return Qnil;
1127
+ }
1128
+
1129
+ VALUE r_gmpf_can_round(VALUE self, VALUE err, VALUE rnd1, VALUE rnd2, VALUE prec)
1033
1130
  {
1034
1131
  MP_FLOAT *self_val;
1035
- mpf_get_struct (self, self_val);
1036
- return INT2FIX (mpf_sgn (self_val));
1132
+ mp_exp_t err_val;
1133
+ mpfr_rnd_t rnd1_val, rnd2_val;
1134
+ mpfr_prec_t prec_val;
1135
+
1136
+ mpf_get_struct(self, self_val);
1137
+ if (FIXNUM_P(err)) {
1138
+ err_val = FIX2INT(err);
1139
+ } else {
1140
+ typeerror_as(X, "err");
1141
+ }
1142
+ rnd1_val = r_get_rounding_mode(rnd1);
1143
+ rnd2_val = r_get_rounding_mode(rnd2);
1144
+ prec_val = FIX2INT (prec);
1145
+
1146
+ if (mpfr_can_round (self_val, err_val, rnd1_val, rnd2_val, prec_val))
1147
+ return Qtrue;
1148
+ else
1149
+ return Qfalse;
1037
1150
  }
1038
1151
 
1152
+ #endif
1153
+
1154
+
1155
+ /**********************************************************************
1156
+ * _unsorted_ *
1157
+ **********************************************************************/
1158
+
1039
1159
  VALUE r_gmpf_get_prec(VALUE self)
1040
1160
  {
1041
1161
  MP_FLOAT *self_val;
@@ -1162,37 +1282,33 @@ void init_gmpf()
1162
1282
  //"unordered", r_gmpfr_unordered_p
1163
1283
 
1164
1284
  // Special Functions
1165
- rb_define_method(cGMP_F, "log", r_gmpfr_log, -1);
1166
- rb_define_method(cGMP_F, "log2", r_gmpfr_log2, -1);
1167
- rb_define_method(cGMP_F, "log10", r_gmpfr_log10, -1);
1168
- rb_define_method(cGMP_F, "exp", r_gmpfr_exp, -1);
1169
- rb_define_method(cGMP_F, "exp2", r_gmpfr_exp2, -1);
1170
- rb_define_method(cGMP_F, "exp10", r_gmpfr_exp10, -1);
1171
- rb_define_method(cGMP_F, "cos", r_gmpfr_cos, -1);
1172
- rb_define_method(cGMP_F, "sin", r_gmpfr_sin, -1);
1173
- rb_define_method(cGMP_F, "tan", r_gmpfr_tan, -1);
1174
- // "sin_cos", r_gmpfr_sin_cos
1175
- rb_define_method(cGMP_F, "sec", r_gmpfr_sec, -1);
1176
- rb_define_method(cGMP_F, "csc", r_gmpfr_csc, -1);
1177
- rb_define_method(cGMP_F, "cot", r_gmpfr_cot, -1);
1178
-
1179
- rb_define_method(cGMP_F, "acos", r_gmpfr_acos, -1);
1180
- rb_define_method(cGMP_F, "asin", r_gmpfr_asin, -1);
1181
- rb_define_method(cGMP_F, "atan", r_gmpfr_atan, -1);
1182
- // "atan2", r_gmpfr_atan2
1183
-
1184
- rb_define_method(cGMP_F, "cosh", r_gmpfr_cosh, -1);
1185
- rb_define_method(cGMP_F, "sinh", r_gmpfr_sinh, -1);
1186
- rb_define_method(cGMP_F, "tanh", r_gmpfr_tanh, -1);
1187
-
1188
- // "sinh_cosh", r_gmpfr_sinh_cosh
1189
-
1190
- rb_define_method(cGMP_F, "sech", r_gmpfr_sech, -1);
1191
- rb_define_method(cGMP_F, "csch", r_gmpfr_csch, -1);
1192
- rb_define_method(cGMP_F, "coth", r_gmpfr_coth, -1);
1193
- rb_define_method(cGMP_F, "acosh", r_gmpfr_acosh, -1);
1194
- rb_define_method(cGMP_F, "asinh", r_gmpfr_asinh, -1);
1195
- rb_define_method(cGMP_F, "atanh", r_gmpfr_atanh, -1);
1285
+ rb_define_method(cGMP_F, "log", r_gmpfr_log, -1);
1286
+ rb_define_method(cGMP_F, "log2", r_gmpfr_log2, -1);
1287
+ rb_define_method(cGMP_F, "log10", r_gmpfr_log10, -1);
1288
+ rb_define_method(cGMP_F, "exp", r_gmpfr_exp, -1);
1289
+ rb_define_method(cGMP_F, "exp2", r_gmpfr_exp2, -1);
1290
+ rb_define_method(cGMP_F, "exp10", r_gmpfr_exp10, -1);
1291
+ rb_define_method(cGMP_F, "cos", r_gmpfr_cos, -1);
1292
+ rb_define_method(cGMP_F, "sin", r_gmpfr_sin, -1);
1293
+ rb_define_method(cGMP_F, "tan", r_gmpfr_tan, -1);
1294
+ rb_define_method(cGMP_F, "sin_cos", r_gmpfr_sin_cos, -1);
1295
+ rb_define_method(cGMP_F, "sec", r_gmpfr_sec, -1);
1296
+ rb_define_method(cGMP_F, "csc", r_gmpfr_csc, -1);
1297
+ rb_define_method(cGMP_F, "cot", r_gmpfr_cot, -1);
1298
+ rb_define_method(cGMP_F, "acos", r_gmpfr_acos, -1);
1299
+ rb_define_method(cGMP_F, "asin", r_gmpfr_asin, -1);
1300
+ rb_define_method(cGMP_F, "atan", r_gmpfr_atan, -1);
1301
+ rb_define_method(cGMP_F, "atan2", r_gmpfr_atan2, -1);
1302
+ rb_define_method(cGMP_F, "cosh", r_gmpfr_cosh, -1);
1303
+ rb_define_method(cGMP_F, "sinh", r_gmpfr_sinh, -1);
1304
+ rb_define_method(cGMP_F, "tanh", r_gmpfr_tanh, -1);
1305
+ rb_define_method(cGMP_F, "sinh_cosh", r_gmpfr_sinh_cosh, -1);
1306
+ rb_define_method(cGMP_F, "sech", r_gmpfr_sech, -1);
1307
+ rb_define_method(cGMP_F, "csch", r_gmpfr_csch, -1);
1308
+ rb_define_method(cGMP_F, "coth", r_gmpfr_coth, -1);
1309
+ rb_define_method(cGMP_F, "acosh", r_gmpfr_acosh, -1);
1310
+ rb_define_method(cGMP_F, "asinh", r_gmpfr_asinh, -1);
1311
+ rb_define_method(cGMP_F, "atanh", r_gmpfr_atanh, -1);
1196
1312
 
1197
1313
  // "fac", r_gmpfr_fac
1198
1314
 
@@ -1218,17 +1334,22 @@ void init_gmpf()
1218
1334
 
1219
1335
  // "fma", r_gmpfr_fma
1220
1336
  // "fms", r_gmpfr_fms
1221
- // "agm", r_gmpfr_agm
1222
- // "hypot", r_gmpfr_hypot
1337
+ rb_define_method(cGMP_F, "agm", r_gmpfr_agm, -1);
1338
+ rb_define_method(cGMP_F, "hypot", r_gmpfr_hypot, -1);
1223
1339
  // "ai", r_gmpfr_ai !! 3.0.0
1224
1340
 
1225
- rb_define_singleton_method(cGMP_F, "const_log2", r_gmpfrsg_const_log2, 0);
1226
- rb_define_singleton_method(cGMP_F, "const_pi", r_gmpfrsg_const_pi, 0);
1227
- rb_define_singleton_method(cGMP_F, "const_euler", r_gmpfrsg_const_euler, 0);
1228
- rb_define_singleton_method(cGMP_F, "const_catalan", r_gmpfrsg_const_catalan, 0);
1341
+ rb_define_singleton_method(cGMP_F, "const_log2", r_gmpfrsg_const_log2, -1);
1342
+ rb_define_singleton_method(cGMP_F, "const_pi", r_gmpfrsg_const_pi, -1);
1343
+ rb_define_singleton_method(cGMP_F, "const_euler", r_gmpfrsg_const_euler, -1);
1344
+ rb_define_singleton_method(cGMP_F, "const_catalan", r_gmpfrsg_const_catalan, -1);
1229
1345
 
1230
1346
  // Integer and Remainder Related Functions
1231
1347
  // "integer?", r_gmpfr_integer_p
1348
+
1349
+ // Rounding Related Functions
1350
+ rb_define_singleton_method (cGMP_F, "default_rounding_mode", r_gmpfsg_get_default_rounding_mode, 0);
1351
+ rb_define_singleton_method (cGMP_F, "default_rounding_mode=", r_gmpfsg_set_default_rounding_mode, 1);
1352
+ rb_define_method(cGMP_F, "can_round?", r_gmpf_can_round, 4);
1232
1353
  #endif /* MPFR */
1233
1354
 
1234
1355
  // _unsorted_