1/* Test mpf_ui_div.
2
3Copyright 2004 Free Software Foundation, Inc.
4
5This file is part of the GNU MP Library.
6
7The GNU MP Library is free software; you can redistribute it and/or modify
8it under the terms of the GNU Lesser General Public License as published by
9the Free Software Foundation; either version 3 of the License, or (at your
10option) any later version.
11
12The GNU MP Library is distributed in the hope that it will be useful, but
13WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
15License for more details.
16
17You should have received a copy of the GNU Lesser General Public License
18along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.  */
19
20#include <stdio.h>
21#include <stdlib.h>
22#include "gmp.h"
23#include "gmp-impl.h"
24#include "tests.h"
25
26
27void
28check_one (const char *desc, mpf_ptr got, unsigned long u, mpf_srcptr v)
29{
30  mpf_t      uf;
31  mp_limb_t  ulimbs[2];
32  mp_size_t  usize;
33
34  ulimbs[0] = u & GMP_NUMB_MASK;
35  usize = (u != 0);
36#if BITS_PER_ULONG > GMP_NUMB_BITS
37  u >>= GMP_NUMB_BITS;
38  ulimbs[1] = u;
39  usize += (u != 0);
40#endif
41  PTR(uf) = ulimbs;
42  SIZ(uf) = usize;
43  EXP(uf) = usize;
44
45  if (! refmpf_validate_division ("mpf_ui_div", got, uf, v))
46    {
47      mp_trace_base = -16;
48      printf    ("  u 0x%lX  (%lu)\n", u, u);
49      mpf_trace ("  v", v);
50      printf    ("  %s\n", desc);
51      abort ();
52    }
53}
54
55void
56check_rand (void)
57{
58  unsigned long  min_prec = __GMPF_BITS_TO_PREC (1);
59  gmp_randstate_ptr  rands = RANDS;
60  unsigned long  prec, u;
61  mpf_t  got, v;
62  int    i;
63
64  mpf_init (got);
65  mpf_init (v);
66
67  for (i = 0; i < 200; i++)
68    {
69      /* got precision */
70      prec = min_prec + gmp_urandomm_ui (rands, 15L);
71      refmpf_set_prec_limbs (got, prec);
72
73      /* u */
74      prec = gmp_urandomm_ui (rands, BITS_PER_ULONG+1);
75      u = gmp_urandomb_ui (rands, prec);
76
77      /* v precision */
78      prec = min_prec + gmp_urandomm_ui (rands, 15L);
79      refmpf_set_prec_limbs (v, prec);
80
81      /* v, non-zero */
82      do {
83        mpf_random2 (v, PREC(v), (mp_exp_t) 20);
84      } while (SIZ(v) == 0);
85
86      /* v possibly negative */
87      if (gmp_urandomb_ui (rands, 1L))
88        mpf_neg (v, v);
89
90      if ((i % 2) == 0)
91        {
92          /* src != dst */
93          mpf_ui_div (got, u, v);
94          check_one ("separate", got, u, v);
95        }
96      else
97        {
98          /* src == dst */
99          prec = refmpf_set_overlap (got, v);
100          mpf_ui_div (got, u, got);
101          check_one ("overlap src==dst", got, u, v);
102
103          mpf_set_prec_raw (got, prec);
104        }
105    }
106
107  mpf_clear (got);
108  mpf_clear (v);
109}
110
111void
112check_various (void)
113{
114  mpf_t got, v;
115
116  mpf_init (got);
117  mpf_init (v);
118
119  /* 100/4 == 25 */
120  mpf_set_prec (got, 20L);
121  mpf_set_ui (v, 4L);
122  mpf_ui_div (got, 100L, v);
123  MPF_CHECK_FORMAT (got);
124  ASSERT_ALWAYS (mpf_cmp_ui (got, 25L) == 0);
125
126  {
127    /* 1/(2^n+1), a case where truncating the divisor would be wrong */
128    unsigned long  u = 1L;
129    mpf_set_prec (got, 500L);
130    mpf_set_prec (v, 900L);
131    mpf_set_ui (v, 1L);
132    mpf_mul_2exp (v, v, 800L);
133    mpf_add_ui (v, v, 1L);
134    mpf_ui_div (got, u, v);
135    check_one ("1/2^n+1, separate", got, u, v);
136  }
137
138  mpf_clear (got);
139  mpf_clear (v);
140}
141
142int
143main (void)
144{
145  tests_start ();
146
147  check_various ();
148  check_rand ();
149
150  tests_end ();
151  exit (0);
152}
153