43 (*current_liboctave_error_handler)
44 (
"gcd: all values must be integers");
51 double tt = fmod (aa, bb);
62 template <
typename FP>
64 divide (
const std::complex<FP>& a,
const std::complex<FP>& b,
65 std::complex<FP>& q, std::complex<FP>& r)
70 q = std::complex<FP> (qr, qi);
75 template <
typename FP>
76 static std::complex<FP>
77 simple_gcd (
const std::complex<FP>& a,
const std::complex<FP>& b)
81 (*current_liboctave_error_handler)
82 (
"gcd: all complex parts must be integers");
84 std::complex<FP> aa = a;
85 std::complex<FP> bb = b;
92 std::complex<FP> qq, rr;
105 T aa = a.
abs ().value ();
106 T bb = b.
abs ().value ();
122 (*current_liboctave_error_handler)
123 (
"gcd: all values must be integers");
125 double aa = fabs (a);
126 double bb = fabs (b);
128 double xx, lx, yy, ly;
135 double tt = fmod (aa, bb);
140 double tx = lx - qq*xx;
144 double ty = ly - qq*yy;
149 x = a >= 0 ? lx : -lx;
150 y = b >= 0 ? ly : -ly;
155 template <
typename FP>
156 static std::complex<FP>
158 std::complex<FP>&
x, std::complex<FP>& y)
162 (*current_liboctave_error_handler)
163 (
"gcd: all complex parts must be integers");
165 std::complex<FP> aa = a;
166 std::complex<FP> bb = b;
167 bool swapped =
false;
174 std::complex<FP> xx, lx, yy, ly;
180 std::complex<FP> qq, rr;
185 std::complex<FP> tx = lx - qq*xx;
189 std::complex<FP> ty = ly - qq*yy;
208 T aa = a.
abs ().value ();
209 T bb = b.
abs ().value ();
240 typedef typename NDA::element_type T;
246 T aa = octave_value_extract<T> (a);
247 T bb = octave_value_extract<T> (b);
252 NDA aa = octave_value_extract<NDA> (a);
253 NDA bb = octave_value_extract<NDA> (b);
254 retval = binmap<T> (aa, bb,
simple_gcd,
"gcd");
272 retval = do_simple_gcd<SparseMatrix> (a, b);
278 retval = do_simple_gcd<NDArray> (a, b);
281 #define MAKE_INT_BRANCH(X) \
283 retval = do_simple_gcd<X ## NDArray> (a, b); \
295 #undef MAKE_INT_BRANCH
298 retval = do_simple_gcd<ComplexNDArray> (a, b);
302 retval = do_simple_gcd<FloatComplexNDArray> (a, b);
306 error (
"gcd: invalid class combination for gcd: %s and %s\n",
307 a.class_name ().c_str (), b.
class_name ().c_str ());
321 typedef typename NDA::element_type T;
327 T aa = octave_value_extract<T> (a);
328 T bb = octave_value_extract<T> (b);
336 NDA aa = octave_value_extract<NDA> (a);
337 NDA bb = octave_value_extract<NDA> (b);
340 if (aa.numel () == 1)
342 else if (bb.numel () != 1 && bb.dims () != dv)
345 NDA gg (dv), xx (dv), yy (dv);
347 const T *aptr = aa.fortran_vec ();
348 const T *bptr = bb.fortran_vec ();
350 bool inca = aa.numel () != 1;
351 bool incb = bb.numel () != 1;
353 T *gptr = gg.fortran_vec ();
354 T *xptr = xx.fortran_vec ();
355 T *yptr = yy.fortran_vec ();
362 *gptr++ =
extended_gcd (*aptr, *bptr, *xptr++, *yptr++);
390 retval = do_extended_gcd<NDArray> (a, b,
x, y);
393 #define MAKE_INT_BRANCH(X) \
395 retval = do_extended_gcd<X ## NDArray> (a, b, x, y); \
407 #undef MAKE_INT_BRANCH
410 retval = do_extended_gcd<ComplexNDArray> (a, b,
x, y);
414 retval = do_extended_gcd<FloatComplexNDArray> (a, b,
x, y);
418 error (
"gcd: invalid class combination for gcd: %s and %s\n",
419 a.class_name ().c_str (), b.class_name ().c_str ());
423 if (!
error_state && a.is_sparse_type () && b.is_sparse_type ())
426 x = x.sparse_matrix_value ();
433 x = x.float_array_value ();
440 DEFUN (gcd, args, nargout,
442 @deftypefn {Built-in Function} {@var{g} =} gcd (@var{a1}, @var{a2}, @dots{})\n\
443 @deftypefnx {Built-in Function} {[@var{g}, @var{v1}, @dots{}] =} gcd (@var{a1}, @var{a2}, @dots{})\n\
444 Compute the greatest common divisor of @var{a1}, @var{a2}, @dots{}.\n\
446 If more than one argument is given then all arguments must be the same size\n\
447 or scalar. In this case the greatest common divisor is calculated for each\n\
448 element individually. All elements must be ordinary or Gaussian (complex)\n\
449 integers. Note that for Gaussian integers, the gcd is only unique up to a\n\
450 phase factor (multiplication by 1, -1, i, or -i), so an arbitrary greatest\n\
451 common divisor among the four possible is returned.\n\
453 Optional return arguments @var{v1}, @dots{}, contain integer vectors such\n\
457 $g = v_1 a_1 + v_2 a_2 + \\cdots$\n\
462 @var{g} = @var{v1} .* @var{a1} + @var{v2} .* @var{a2} + @dots{}\n\
471 gcd ([15, 9], [20, 18])\n\
476 @seealso{lcm, factor, isprime}\n\
481 int nargin = args.
length ();
487 retval.
resize (nargin + 1);
491 for (
int j = 2; j < nargin; j++)
496 for (
int i = 0; i < j; i++)
507 for (
int j = 2; j < nargin; j++)
void gripe_nonconformant(const char *op, octave_idx_type op1_len, octave_idx_type op2_len)
OCTINTERP_API void print_usage(void)
bool is_scalar_type(void) const
static octave_value do_extended_gcd(const octave_value &a, const octave_value &b, octave_value &x, octave_value &y)
#define DEFUN(name, args_name, nargout_name, doc)
void error(const char *fmt,...)
octave_int< T > abs() const
#define MAKE_INT_BRANCH(X)
static void divide(const std::complex< FP > &a, const std::complex< FP > &b, std::complex< FP > &q, std::complex< FP > &r)
static double simple_gcd(double a, double b)
builtin_type_t btyp_mixed_numeric(builtin_type_t x, builtin_type_t y)
FloatNDArray float_array_value(bool frc_str_conv=false) const
bool is_sparse_type(void) const
octave_idx_type length(void) const
dim_vector dims(void) const
bool xisinteger(double x)
octave_int< T > signum() const
std::string class_name(void) const
void resize(octave_idx_type n, const octave_value &rfv=octave_value())
ColumnVector imag(const ComplexColumnVector &a)
SparseMatrix sparse_matrix_value(bool frc_str_conv=false) const
std::complex< T > floor(const std::complex< T > &x)
static octave_value do_simple_gcd(const octave_value &a, const octave_value &b)
ColumnVector real(const ComplexColumnVector &a)
static double extended_gcd(double a, double b, double &x, double &y)
builtin_type_t builtin_type(void) const
F77_RET_T const double * x