Skip to content

Commit

Permalink
Add gr_poly_add_scalar, gr_poly_sub_scalar, etc. (#2194)
Browse files Browse the repository at this point in the history
  • Loading branch information
rburing authored Jan 31, 2025
1 parent e1d0493 commit 9f55d76
Show file tree
Hide file tree
Showing 7 changed files with 573 additions and 15 deletions.
45 changes: 35 additions & 10 deletions doc/source/gr_poly.rst
Original file line number Diff line number Diff line change
Expand Up @@ -158,16 +158,6 @@ Arithmetic
int _gr_poly_mullow(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, slong len, gr_ctx_t ctx)
int gr_poly_mullow(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, slong len, gr_ctx_t ctx)

.. function:: int gr_poly_mul_scalar(gr_poly_t res, const gr_poly_t poly, gr_srcptr c, gr_ctx_t ctx)
int gr_poly_scalar_mul(gr_poly_t res, gr_srcptr c, const gr_poly_t poly, gr_ctx_t ctx)
int gr_poly_mul_ui(gr_poly_t res, const gr_poly_t poly, ulong c, gr_ctx_t ctx)
int gr_poly_mul_si(gr_poly_t res, const gr_poly_t poly, slong c, gr_ctx_t ctx)
int gr_poly_mul_fmpz(gr_poly_t res, const gr_poly_t poly, const fmpz c, gr_ctx_t ctx)
int gr_poly_mul_fmpq(gr_poly_t res, const gr_poly_t poly, const fmpq c, gr_ctx_t ctx)

Sets *res* to *poly* multiplied by the scalar *c* (or the scalar *c* multiplied by *poly*)
which must be an element of or coercible to the coefficient ring.

.. function:: int _gr_poly_mul_karatsuba(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx)
int gr_poly_mul_karatsuba(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx)

Expand All @@ -190,6 +180,41 @@ Arithmetic
algorithm with `O(n^{1.5})` complexity, the ring must overload :func:`_gr_poly_mul` to dispatch
to :func:`_gr_poly_mul_toom33` above some cutoff.

.. function:: int gr_poly_add_scalar(gr_poly_t res, const gr_poly_t poly, gr_srcptr c, gr_ctx_t ctx)
int gr_poly_add_ui(gr_poly_t res, const gr_poly_t poly, ulong c, gr_ctx_t ctx)
int gr_poly_add_si(gr_poly_t res, const gr_poly_t poly, slong c, gr_ctx_t ctx)
int gr_poly_add_fmpz(gr_poly_t res, const gr_poly_t poly, const fmpz c, gr_ctx_t ctx)
int gr_poly_add_fmpq(gr_poly_t res, const gr_poly_t poly, const fmpq c, gr_ctx_t ctx)

Sets *res* to *poly* plus the scalar *c* which must be
an element of or coercible to the coefficient ring.

.. function:: int gr_poly_sub_scalar(gr_poly_t res, const gr_poly_t poly, gr_srcptr c, gr_ctx_t ctx)
int gr_poly_sub_ui(gr_poly_t res, const gr_poly_t poly, ulong c, gr_ctx_t ctx)
int gr_poly_sub_si(gr_poly_t res, const gr_poly_t poly, slong c, gr_ctx_t ctx)
int gr_poly_sub_fmpz(gr_poly_t res, const gr_poly_t poly, const fmpz c, gr_ctx_t ctx)
int gr_poly_sub_fmpq(gr_poly_t res, const gr_poly_t poly, const fmpq c, gr_ctx_t ctx)

Sets *res* to *poly* minus the scalar *c* which must be
an element of or coercible to the coefficient ring.

.. function:: int gr_poly_mul_scalar(gr_poly_t res, const gr_poly_t poly, gr_srcptr c, gr_ctx_t ctx)
int gr_poly_scalar_mul(gr_poly_t res, gr_srcptr c, const gr_poly_t poly, gr_ctx_t ctx)
int gr_poly_mul_ui(gr_poly_t res, const gr_poly_t poly, ulong c, gr_ctx_t ctx)
int gr_poly_mul_si(gr_poly_t res, const gr_poly_t poly, slong c, gr_ctx_t ctx)
int gr_poly_mul_fmpz(gr_poly_t res, const gr_poly_t poly, const fmpz c, gr_ctx_t ctx)
int gr_poly_mul_fmpq(gr_poly_t res, const gr_poly_t poly, const fmpq c, gr_ctx_t ctx)

Sets *res* to *poly* multiplied by the scalar *c* (or the scalar *c* multiplied by *poly*)
which must be an element of or coercible to the coefficient ring.

.. function:: int gr_poly_addmul_scalar(gr_poly_t res, const gr_poly_t poly, gr_srcptr c, gr_ctx_t ctx)

Adds *poly* multiplied by the scalar *c* to *res*.

.. function:: int gr_poly_submul_scalar(gr_poly_t res, const gr_poly_t poly, gr_srcptr c, gr_ctx_t ctx)

Subtracts *poly* multiplied by the scalar *c* from *res*.

Powering
--------------------------------------------------------------------------------
Expand Down
58 changes: 57 additions & 1 deletion src/gr/polynomial.c
Original file line number Diff line number Diff line change
Expand Up @@ -360,12 +360,60 @@ polynomial_neg(gr_poly_t res, const gr_poly_t mat, gr_ctx_t ctx)
return gr_poly_neg(res, mat, POLYNOMIAL_ELEM_CTX(ctx));
}

int
polynomial_add_ui(gr_poly_t res, const gr_poly_t poly, ulong c, gr_ctx_t ctx)
{
return gr_poly_add_ui(res, poly, c, POLYNOMIAL_ELEM_CTX(ctx));
}

int
polynomial_add_si(gr_poly_t res, const gr_poly_t poly, slong c, gr_ctx_t ctx)
{
return gr_poly_add_si(res, poly, c, POLYNOMIAL_ELEM_CTX(ctx));
}

int
polynomial_add_fmpz(gr_poly_t res, const gr_poly_t poly, const fmpz_t c, gr_ctx_t ctx)
{
return gr_poly_add_fmpz(res, poly, c, POLYNOMIAL_ELEM_CTX(ctx));
}

int
polynomial_add_fmpq(gr_poly_t res, const gr_poly_t poly, const fmpq_t c, gr_ctx_t ctx)
{
return gr_poly_add_fmpq(res, poly, c, POLYNOMIAL_ELEM_CTX(ctx));
}

int
polynomial_add(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx)
{
return gr_poly_add(res, poly1, poly2, POLYNOMIAL_ELEM_CTX(ctx));
}

int
polynomial_sub_ui(gr_poly_t res, const gr_poly_t poly, ulong c, gr_ctx_t ctx)
{
return gr_poly_sub_ui(res, poly, c, POLYNOMIAL_ELEM_CTX(ctx));
}

int
polynomial_sub_si(gr_poly_t res, const gr_poly_t poly, slong c, gr_ctx_t ctx)
{
return gr_poly_sub_si(res, poly, c, POLYNOMIAL_ELEM_CTX(ctx));
}

int
polynomial_sub_fmpz(gr_poly_t res, const gr_poly_t poly, const fmpz_t c, gr_ctx_t ctx)
{
return gr_poly_sub_fmpz(res, poly, c, POLYNOMIAL_ELEM_CTX(ctx));
}

int
polynomial_sub_fmpq(gr_poly_t res, const gr_poly_t poly, const fmpq_t c, gr_ctx_t ctx)
{
return gr_poly_sub_fmpq(res, poly, c, POLYNOMIAL_ELEM_CTX(ctx));
}

int
polynomial_sub(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx)
{
Expand All @@ -391,7 +439,7 @@ polynomial_mul_fmpz(gr_poly_t res, const gr_poly_t poly, const fmpz_t c, gr_ctx_
}

int
polynomial_mul_fmpq(gr_poly_t res, const gr_poly_t poly, fmpq_t c, gr_ctx_t ctx)
polynomial_mul_fmpq(gr_poly_t res, const gr_poly_t poly, const fmpq_t c, gr_ctx_t ctx)
{
return gr_poly_mul_fmpq(res, poly, c, POLYNOMIAL_ELEM_CTX(ctx));
}
Expand Down Expand Up @@ -618,7 +666,15 @@ gr_method_tab_input _gr_poly_methods_input[] =
before converting to the dense representation, to avoid O(n^2) behavior */
{GR_METHOD_SET_STR, (gr_funcptr) gr_generic_set_str_balance_additions},
{GR_METHOD_NEG, (gr_funcptr) polynomial_neg},
{GR_METHOD_ADD_UI, (gr_funcptr) polynomial_add_ui},
{GR_METHOD_ADD_SI, (gr_funcptr) polynomial_add_si},
{GR_METHOD_ADD_FMPZ, (gr_funcptr) polynomial_add_fmpz},
{GR_METHOD_ADD_FMPQ, (gr_funcptr) polynomial_add_fmpq},
{GR_METHOD_ADD, (gr_funcptr) polynomial_add},
{GR_METHOD_SUB_UI, (gr_funcptr) polynomial_sub_ui},
{GR_METHOD_SUB_SI, (gr_funcptr) polynomial_sub_si},
{GR_METHOD_SUB_FMPZ, (gr_funcptr) polynomial_sub_fmpz},
{GR_METHOD_SUB_FMPQ, (gr_funcptr) polynomial_sub_fmpq},
{GR_METHOD_SUB, (gr_funcptr) polynomial_sub},
{GR_METHOD_MUL, (gr_funcptr) polynomial_mul},
{GR_METHOD_MUL_OTHER, (gr_funcptr) polynomial_mul_other},
Expand Down
24 changes: 20 additions & 4 deletions src/gr_poly.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,17 +120,33 @@ WARN_UNUSED_RESULT int gr_poly_mul(gr_poly_t res, const gr_poly_t poly1, const g
WARN_UNUSED_RESULT int _gr_poly_mullow_generic(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, slong n, gr_ctx_t ctx);
GR_POLY_INLINE WARN_UNUSED_RESULT int _gr_poly_mullow(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, slong len, gr_ctx_t ctx) { return GR_POLY_BINARY_TRUNC_OP(ctx, POLY_MULLOW)(res, poly1, len1, poly2, len2, len, ctx); }
WARN_UNUSED_RESULT int gr_poly_mullow(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, slong n, gr_ctx_t ctx);

WARN_UNUSED_RESULT int _gr_poly_mul_karatsuba(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx);
WARN_UNUSED_RESULT int gr_poly_mul_karatsuba(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx);
WARN_UNUSED_RESULT int _gr_poly_mul_toom33(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx);
WARN_UNUSED_RESULT int gr_poly_mul_toom33(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx);

WARN_UNUSED_RESULT int gr_poly_add_scalar(gr_poly_t res, const gr_poly_t poly, gr_srcptr c, gr_ctx_t ctx);
WARN_UNUSED_RESULT int gr_poly_add_ui(gr_poly_t res, const gr_poly_t poly, ulong c, gr_ctx_t ctx);
WARN_UNUSED_RESULT int gr_poly_add_si(gr_poly_t res, const gr_poly_t poly, slong c, gr_ctx_t ctx);
WARN_UNUSED_RESULT int gr_poly_add_fmpz(gr_poly_t res, const gr_poly_t poly, const fmpz_t c, gr_ctx_t ctx);
WARN_UNUSED_RESULT int gr_poly_add_fmpq(gr_poly_t res, const gr_poly_t poly, const fmpq_t c, gr_ctx_t ctx);

WARN_UNUSED_RESULT int gr_poly_sub_scalar(gr_poly_t res, const gr_poly_t poly, gr_srcptr c, gr_ctx_t ctx);
WARN_UNUSED_RESULT int gr_poly_sub_ui(gr_poly_t res, const gr_poly_t poly, ulong c, gr_ctx_t ctx);
WARN_UNUSED_RESULT int gr_poly_sub_si(gr_poly_t res, const gr_poly_t poly, slong c, gr_ctx_t ctx);
WARN_UNUSED_RESULT int gr_poly_sub_fmpz(gr_poly_t res, const gr_poly_t poly, const fmpz_t c, gr_ctx_t ctx);
WARN_UNUSED_RESULT int gr_poly_sub_fmpq(gr_poly_t res, const gr_poly_t poly, const fmpq_t c, gr_ctx_t ctx);

WARN_UNUSED_RESULT int gr_poly_mul_scalar(gr_poly_t res, const gr_poly_t poly, gr_srcptr c, gr_ctx_t ctx);
WARN_UNUSED_RESULT int gr_poly_scalar_mul(gr_poly_t res, gr_srcptr c, const gr_poly_t poly, gr_ctx_t ctx);
WARN_UNUSED_RESULT int gr_poly_mul_ui(gr_poly_t res, const gr_poly_t poly, ulong c, gr_ctx_t ctx);
WARN_UNUSED_RESULT int gr_poly_mul_si(gr_poly_t res, const gr_poly_t poly, slong c, gr_ctx_t ctx);
WARN_UNUSED_RESULT int gr_poly_mul_fmpz(gr_poly_t res, const gr_poly_t poly, const fmpz_t c, gr_ctx_t ctx);
WARN_UNUSED_RESULT int gr_poly_mul_fmpq(gr_poly_t res, const gr_poly_t poly, const fmpq_t c, gr_ctx_t ctx);

WARN_UNUSED_RESULT int _gr_poly_mul_karatsuba(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx);
WARN_UNUSED_RESULT int gr_poly_mul_karatsuba(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx);
WARN_UNUSED_RESULT int _gr_poly_mul_toom33(gr_ptr res, gr_srcptr poly1, slong len1, gr_srcptr poly2, slong len2, gr_ctx_t ctx);
WARN_UNUSED_RESULT int gr_poly_mul_toom33(gr_poly_t res, const gr_poly_t poly1, const gr_poly_t poly2, gr_ctx_t ctx);
WARN_UNUSED_RESULT int gr_poly_addmul_scalar(gr_poly_t res, const gr_poly_t poly, gr_srcptr c, gr_ctx_t ctx);
WARN_UNUSED_RESULT int gr_poly_submul_scalar(gr_poly_t res, const gr_poly_t poly, gr_srcptr c, gr_ctx_t ctx);

/* powering */

Expand Down
188 changes: 188 additions & 0 deletions src/gr_poly/add_scalar.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
/*
Copyright (C) 2025 Ricardo Buring
This file is part of FLINT.
FLINT is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License (LGPL) as published
by the Free Software Foundation; either version 3 of the License, or
(at your option) any later version. See <https://www.gnu.org/licenses/>.
*/

#include "fmpq.h"
#include "gr_poly.h"

int
gr_poly_add_scalar(gr_poly_t res, const gr_poly_t poly, gr_srcptr c, gr_ctx_t ctx)
{
int status;
slong len = poly->length;

if (len == 0) {
if (gr_is_zero(c, ctx) == T_TRUE) {
return gr_poly_zero(res, ctx);
} else {
gr_poly_fit_length(res, 1, ctx);
_gr_poly_set_length(res, 1, ctx);
status = gr_set(res->coeffs, c, ctx);
_gr_poly_normalise(res, ctx);
return status;
}
}

status = GR_SUCCESS;

if (res != poly) {
status |= gr_poly_set(res, poly, ctx);
}

if (gr_is_zero(c, ctx) != T_TRUE) {
gr_ptr constant_coeff = gr_poly_entry_ptr(res, 0, ctx);
status |= gr_add(constant_coeff, constant_coeff, c, ctx);
if (len == 1 && gr_is_zero(constant_coeff, ctx) == T_TRUE) {
_gr_poly_set_length(res, 0, ctx);
}
}

return status;
}

int
gr_poly_add_ui(gr_poly_t res, const gr_poly_t poly, ulong c, gr_ctx_t ctx)
{
int status;
slong len = poly->length;

if (len == 0) {
if (c == 0) {
return gr_poly_zero(res, ctx);
} else {
gr_poly_fit_length(res, 1, ctx);
_gr_poly_set_length(res, 1, ctx);
status = gr_set_ui(res->coeffs, c, ctx);
_gr_poly_normalise(res, ctx);
return status;
}
}

status = GR_SUCCESS;

if (res != poly) {
status |= gr_poly_set(res, poly, ctx);
}

if (c != 0) {
gr_ptr constant_coeff = gr_poly_entry_ptr(res, 0, ctx);
status |= gr_add_ui(constant_coeff, constant_coeff, c, ctx);
if (len == 1 && gr_is_zero(constant_coeff, ctx) == T_TRUE) {
_gr_poly_set_length(res, 0, ctx);
}
}

return status;
}

int
gr_poly_add_si(gr_poly_t res, const gr_poly_t poly, slong c, gr_ctx_t ctx)
{
int status;
slong len = poly->length;

if (len == 0) {
if (c == 0) {
return gr_poly_zero(res, ctx);
} else {
gr_poly_fit_length(res, 1, ctx);
_gr_poly_set_length(res, 1, ctx);
status = gr_set_si(res->coeffs, c, ctx);
_gr_poly_normalise(res, ctx);
return status;
}
}

status = GR_SUCCESS;

if (res != poly) {
status |= gr_poly_set(res, poly, ctx);
}

if (c != 0) {
gr_ptr constant_coeff = gr_poly_entry_ptr(res, 0, ctx);
status |= gr_add_si(constant_coeff, constant_coeff, c, ctx);
if (len == 1 && gr_is_zero(constant_coeff, ctx) == T_TRUE) {
_gr_poly_set_length(res, 0, ctx);
}
}

return status;
}

int
gr_poly_add_fmpz(gr_poly_t res, const gr_poly_t poly, const fmpz_t c, gr_ctx_t ctx)
{
int status;
slong len = poly->length;

if (len == 0) {
if (fmpz_is_zero(c)) {
return gr_poly_zero(res, ctx);
} else {
gr_poly_fit_length(res, 1, ctx);
_gr_poly_set_length(res, 1, ctx);
status = gr_set_fmpz(res->coeffs, c, ctx);
_gr_poly_normalise(res, ctx);
return status;
}
}

status = GR_SUCCESS;

if (res != poly) {
status |= gr_poly_set(res, poly, ctx);
}

if (!fmpz_is_zero(c)) {
gr_ptr constant_coeff = gr_poly_entry_ptr(res, 0, ctx);
status |= gr_add_fmpz(constant_coeff, constant_coeff, c, ctx);
if (len == 1 && gr_is_zero(constant_coeff, ctx) == T_TRUE) {
_gr_poly_set_length(res, 0, ctx);
}
}

return status;
}

int
gr_poly_add_fmpq(gr_poly_t res, const gr_poly_t poly, const fmpq_t c, gr_ctx_t ctx)
{
int status;
slong len = poly->length;

if (len == 0) {
if (fmpq_is_zero(c)) {
return gr_poly_zero(res, ctx);
} else {
gr_poly_fit_length(res, 1, ctx);
_gr_poly_set_length(res, 1, ctx);
status = gr_set_fmpq(res->coeffs, c, ctx);
_gr_poly_normalise(res, ctx);
return status;
}
}

status = GR_SUCCESS;

if (res != poly) {
status |= gr_poly_set(res, poly, ctx);
}

if (!fmpq_is_zero(c)) {
gr_ptr constant_coeff = gr_poly_entry_ptr(res, 0, ctx);
status |= gr_add_fmpq(constant_coeff, constant_coeff, c, ctx);
if (len == 1 && gr_is_zero(constant_coeff, ctx) == T_TRUE) {
_gr_poly_set_length(res, 0, ctx);
}
}

return status;
}
Loading

0 comments on commit 9f55d76

Please sign in to comment.