26 #if defined (HAVE_CONFIG_H)
44 simple_gcd (
double a,
double b)
47 error (
"gcd: all values must be integers");
54 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)
83 error (
"gcd: all complex parts must be integers");
85 std::complex<FP> aa = a;
86 std::complex<FP> bb = b;
88 if (abs (aa) < abs (bb))
93 std::complex<FP> qq, rr;
94 divide (aa, bb, qq, rr);
102 template <
typename T>
106 T aa = a.
abs ().value ();
107 T bb = b.
abs ().value ();
120 extended_gcd (
double a,
double b,
double&
x,
double& y)
123 error (
"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>
157 extended_gcd (
const std::complex<FP>& a,
const std::complex<FP>& b,
158 std::complex<FP>&
x, std::complex<FP>& y)
164 error (
"gcd: all complex parts must be integers");
166 std::complex<FP> aa = a;
167 std::complex<FP> bb = b;
168 bool swapped =
false;
169 if (abs (aa) < abs (bb))
175 std::complex<FP> xx, lx, yy, ly;
181 std::complex<FP> qq, rr;
182 divide (aa, bb, qq, rr);
186 std::complex<FP> tx = lx - qq*xx;
190 std::complex<FP> ty = ly - qq*yy;
204 template <
typename T>
209 T aa = a.
abs ().value ();
210 T bb = b.
abs ().value ();
237 template <
typename NDA>
241 typedef typename NDA::element_type T;
247 T aa = octave_value_extract<T> (a);
248 T bb = octave_value_extract<T> (b);
249 retval = simple_gcd (aa, bb);
253 NDA aa = octave_value_extract<NDA> (a);
254 NDA bb = octave_value_extract<NDA> (b);
255 retval = binmap<T> (aa, bb, simple_gcd,
"gcd");
273 retval = do_simple_gcd<SparseMatrix> (a, b);
279 retval = do_simple_gcd<NDArray> (a, b);
282 #define MAKE_INT_BRANCH(X) \
284 retval = do_simple_gcd<X ## NDArray> (a, b); \
296 #undef MAKE_INT_BRANCH
299 retval = do_simple_gcd<ComplexNDArray> (a, b);
303 retval = do_simple_gcd<FloatComplexNDArray> (a, b);
307 error (
"gcd: invalid class combination for gcd: %s and %s\n",
317 template <
typename NDA>
322 typedef typename NDA::element_type T;
328 T aa = octave_value_extract<T> (a);
329 T bb = octave_value_extract<T> (b);
331 retval = extended_gcd (aa, bb, xx, yy);
337 NDA aa = octave_value_extract<NDA> (a);
338 NDA bb = octave_value_extract<NDA> (b);
341 if (aa.numel () == 1)
343 else if (bb.numel () != 1 && bb.dims () != dv)
346 NDA gg (dv), xx (dv), yy (dv);
348 const T *aptr = aa.data ();
349 const T *bptr = bb.data ();
351 bool inca = aa.numel () != 1;
352 bool incb = bb.numel () != 1;
354 T *gptr = gg.fortran_vec ();
355 T *xptr = xx.fortran_vec ();
356 T *yptr = yy.fortran_vec ();
363 *gptr++ = extended_gcd (*aptr, *bptr, *xptr++, *yptr++);
391 retval = do_extended_gcd<NDArray> (a, b,
x, y);
394 #define MAKE_INT_BRANCH(X) \
396 retval = do_extended_gcd<X ## NDArray> (a, b, x, y); \
408 #undef MAKE_INT_BRANCH
411 retval = do_extended_gcd<ComplexNDArray> (a, b,
x, y);
415 retval = do_extended_gcd<FloatComplexNDArray> (a, b,
x, y);
419 error (
"gcd: invalid class combination for gcd: %s and %s\n",
427 x =
x.sparse_matrix_value ();
434 x =
x.float_array_value ();
441 DEFUN (gcd, args, nargout,
490 int nargin = args.length ();
499 retval.
resize (nargin + 1);
501 retval(0) = do_extended_gcd (args(0), args(1), retval(1), retval(2));
503 for (
int j = 2; j < nargin; j++)
506 retval(0) = do_extended_gcd (retval(0), args(j),
x, retval(j+1));
507 for (
int i = 0; i < j; i++)
513 retval(0) = do_simple_gcd (args(0), args(1));
515 for (
int j = 2; j < nargin; j++)
516 retval(0) = do_simple_gcd (retval(0), args(j));
549 OCTAVE_END_NAMESPACE(
octave)
Vector representing the dimensions (size) of an Array.
octave_int< T > signum() const
octave_int< T > abs() const
void resize(octave_idx_type n, const octave_value &rfv=octave_value())
SparseMatrix sparse_matrix_value(bool frc_str_conv=false) const
std::string class_name() const
bool is_scalar_type() const
FloatNDArray float_array_value(bool frc_str_conv=false) const
builtin_type_t builtin_type() const
ColumnVector real(const ComplexColumnVector &a)
ColumnVector imag(const ComplexColumnVector &a)
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
void() error(const char *fmt,...)
#define MAKE_INT_BRANCH(X)
void err_nonconformant(const char *op, octave_idx_type op1_len, octave_idx_type op2_len)
std::complex< T > floor(const std::complex< T > &x)
F77_RET_T const F77_DBLE * x
builtin_type_t btyp_mixed_numeric(builtin_type_t x, builtin_type_t y)
Determine the resulting type for a possible mixed-type operation.
template int8_t abs(int8_t)