#ifndef ACF_H
#define ACF_H
#ifdef ACF_INLINES_C
#define ACF_INLINE
#else
#define ACF_INLINE static inline
#endif
#include "arf.h"
#include "acf_types.h"
#ifdef __cplusplus
extern "C" {
#endif
#define acf_realref(x) (&(x)->real)
#define acf_imagref(x) (&(x)->imag)
ACF_INLINE void
acf_init(acf_t x)
{
arf_init(acf_realref(x));
arf_init(acf_imagref(x));
}
ACF_INLINE void
acf_clear(acf_t x)
{
arf_clear(acf_realref(x));
arf_clear(acf_imagref(x));
}
ACF_INLINE acf_ptr _acf_vec_init(slong n) { return (acf_ptr) _arf_vec_init(2 * n); }
ACF_INLINE void _acf_vec_clear(acf_ptr v, slong n) { _arf_vec_clear((arf_ptr) v, 2 * n); }
ACF_INLINE arf_ptr acf_real_ptr(acf_t z) { return acf_realref(z); }
ACF_INLINE arf_ptr acf_imag_ptr(acf_t z) { return acf_imagref(z); }
ACF_INLINE void
acf_set(acf_t z, const acf_t x)
{
arf_set(acf_realref(z), acf_realref(x));
arf_set(acf_imagref(z), acf_imagref(x));
}
ACF_INLINE void
acf_swap(acf_t z, acf_t x)
{
FLINT_SWAP(acf_struct, *z, *x);
}
ACF_INLINE int
acf_equal(const acf_t x, const acf_t y)
{
return arf_equal(acf_realref(x), acf_realref(y)) &&
arf_equal(acf_imagref(x), acf_imagref(y));
}
ACF_INLINE void
acf_printd(const acf_t x, slong n)
{
arf_printd(acf_realref(x), n);
flint_printf(" + ");
arf_printd(acf_imagref(x), n);
flint_printf("*I");
}
ACF_INLINE slong
acf_bits(const acf_t x)
{
slong b1, b2;
b1 = arf_bits(acf_realref(x));
b2 = arf_bits(acf_imagref(x));
return FLINT_MAX(b1, b2);
}
ACF_INLINE slong
acf_allocated_bytes(const acf_t x)
{
return arf_allocated_bytes(acf_realref(x)) + arf_allocated_bytes(acf_imagref(x));
}
ACF_INLINE void acf_randtest(acf_t x, flint_rand_t state, slong bits, slong mag_bits)
{
arf_randtest(acf_realref(x), state, bits, mag_bits);
arf_randtest(acf_imagref(x), state, bits, mag_bits);
}
ACF_INLINE void
acf_get_mag(mag_t res, const acf_t x)
{
mag_t t, u;
mag_init(t);
mag_init(u);
arf_get_mag(t, acf_realref(x));
arf_get_mag(u, acf_imagref(x));
mag_hypot(res, t, u);
mag_clear(t);
mag_clear(u);
}
ACF_INLINE void
acf_neg(acf_t z, const acf_t x)
{
arf_neg(acf_realref(z), acf_realref(x));
arf_neg(acf_imagref(z), acf_imagref(x));
}
ACF_INLINE int
acf_set_round(acf_t res, const acf_t x, slong prec, arf_rnd_t rnd)
{
return arf_set_round(acf_realref(res), acf_realref(x), prec, rnd) |
(arf_set_round(acf_imagref(res), acf_imagref(x), prec, rnd) << 1);
}
ACF_INLINE int
acf_neg_round(acf_t res, const acf_t x, slong prec, arf_rnd_t rnd)
{
return arf_neg_round(acf_realref(res), acf_realref(x), prec, rnd) |
(arf_neg_round(acf_imagref(res), acf_imagref(x), prec, rnd) << 1);
}
ACF_INLINE int
acf_add(acf_t res, const acf_t x, const acf_t y, slong prec, arf_rnd_t rnd)
{
return arf_add(acf_realref(res), acf_realref(x), acf_realref(y), prec, rnd) |
(arf_add(acf_imagref(res), acf_imagref(x), acf_imagref(y), prec, rnd) << 1);
}
ACF_INLINE int
acf_sub(acf_t res, const acf_t x, const acf_t y, slong prec, arf_rnd_t rnd)
{
return arf_sub(acf_realref(res), acf_realref(x), acf_realref(y), prec, rnd) |
(arf_sub(acf_imagref(res), acf_imagref(x), acf_imagref(y), prec, rnd) << 1);
}
ACF_INLINE int
acf_mul(acf_t res, const acf_t x, const acf_t y, slong prec, arf_rnd_t rnd)
{
if (x == y)
return arf_complex_sqr(acf_realref(res), acf_imagref(res),
acf_realref(x), acf_imagref(x),
prec, rnd);
else
return arf_complex_mul(acf_realref(res), acf_imagref(res),
acf_realref(x), acf_imagref(x),
acf_realref(y), acf_imagref(y),
prec, rnd);
}
void acf_approx_inv(acf_t res, const acf_t x, slong prec, arf_rnd_t rnd);
void acf_approx_div(acf_t res, const acf_t x, const acf_t y, slong prec, arf_rnd_t rnd);
void acf_approx_sqrt(acf_t res, const acf_t x, slong prec, arf_rnd_t rnd);
void acf_approx_dot(acf_t res, const acf_t initial, int subtract, acf_srcptr x, slong xstep, acf_srcptr y, slong ystep, slong len, slong prec, arf_rnd_t rnd);
#ifdef __cplusplus
}
#endif
#endif