Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-11-07 10:15:10

0001 /*
0002     Copyright (C) 2021 Fredrik Johansson
0003 
0004     This file is part of FLINT.
0005 
0006     FLINT is free software: you can redistribute it and/or modify it under
0007     the terms of the GNU Lesser General Public License (LGPL) as published
0008     by the Free Software Foundation; either version 3 of the License, or
0009     (at your option) any later version.  See <https://www.gnu.org/licenses/>.
0010 */
0011 
0012 #ifndef FEXPR_H
0013 #define FEXPR_H
0014 
0015 #ifdef FEXPR_INLINES_C
0016 #define FEXPR_INLINE
0017 #else
0018 #define FEXPR_INLINE static inline
0019 #endif
0020 
0021 #include "mpoly_types.h"
0022 #include "arf_types.h"
0023 #include "gr_types.h"
0024 
0025 #ifdef __cplusplus
0026 extern "C" {
0027 #endif
0028 
0029 /* FIXME: We need calcium_stream in ca_types.h, but this header includes qqbar.h
0030    which conditionally defines functions using fexpr_t if and only if FEXPR_H is
0031    defined. And at this point FEXPR_H is defined, but not fexpr_t... */
0032 #ifndef calcium_stream_struct
0033 # define calcium_stream_struct gr_stream_struct
0034 # define calcium_stream_t gr_stream_t
0035 #endif
0036 
0037 #define FEXPR_TYPE_SMALL_INT     UWORD(0)
0038 #define FEXPR_TYPE_SMALL_SYMBOL  UWORD(1)
0039 #define FEXPR_TYPE_SMALL_STRING  UWORD(2)
0040 #define FEXPR_TYPE_BIG_INT_POS   UWORD(3)
0041 #define FEXPR_TYPE_BIG_INT_NEG   UWORD(4)
0042 #define FEXPR_TYPE_BIG_SYMBOL    UWORD(5)
0043 #define FEXPR_TYPE_BIG_STRING    UWORD(6)
0044 #define FEXPR_TYPE_CALL0         UWORD(7)
0045 #define FEXPR_TYPE_CALL1         UWORD(8)
0046 #define FEXPR_TYPE_CALL2         UWORD(9)
0047 #define FEXPR_TYPE_CALL3         UWORD(10)
0048 #define FEXPR_TYPE_CALL4         UWORD(11)
0049 #define FEXPR_TYPE_CALLN         UWORD(12)
0050 
0051 #define FEXPR_TYPE_BITS 4
0052 #define FEXPR_TYPE_MASK ((UWORD(1) << FEXPR_TYPE_BITS) - 1)
0053 
0054 #define FEXPR_COEFF_MAX ((WORD(1) << (FLINT_BITS - FEXPR_TYPE_BITS - 1)) - 1)
0055 #define FEXPR_COEFF_MIN (-FEXPR_COEFF_MAX)
0056 
0057 #define FEXPR_TYPE(head)  ((head) & FEXPR_TYPE_MASK)
0058 #define FEXPR_SIZE(head)  ((slong) ((FEXPR_TYPE(head) <= FEXPR_TYPE_SMALL_STRING) ? 1 : (head) >> FEXPR_TYPE_BITS))
0059 
0060 #define FEXPR_HEADER_SIZE        WORD(1)
0061 #define FEXPR_SMALL_SYMBOL_LEN   ((FLINT_BITS / 8) - 1)
0062 
0063 #define FEXPR_BUILTIN_ID(head) ((head) >> 16)
0064 
0065 typedef struct
0066 {
0067     ulong * data;
0068     slong alloc;
0069 }
0070 fexpr_struct;
0071 
0072 typedef fexpr_struct fexpr_t[1];
0073 typedef fexpr_struct * fexpr_ptr;
0074 typedef const fexpr_struct * fexpr_srcptr;
0075 
0076 typedef struct
0077 {
0078     fexpr_struct * entries;
0079     slong alloc;
0080     slong length;
0081 }
0082 fexpr_vec_struct;
0083 
0084 typedef fexpr_vec_struct fexpr_vec_t[1];
0085 
0086 #define fexpr_vec_entry(vec, i) ((vec)->entries + (i))
0087 
0088 FEXPR_INLINE void
0089 fexpr_init(fexpr_t expr)
0090 {
0091     expr->data = (ulong *) flint_malloc(sizeof(ulong));
0092     expr->data[0] = 0;
0093     expr->alloc = 1;
0094 }
0095 
0096 FEXPR_INLINE void
0097 fexpr_clear(fexpr_t expr)
0098 {
0099     flint_free(expr->data);
0100 }
0101 
0102 FEXPR_INLINE fexpr_ptr
0103 _fexpr_vec_init(slong len)
0104 {
0105     slong i;
0106     fexpr_ptr vec = (fexpr_ptr) flint_malloc(sizeof(fexpr_struct) * len);
0107     for (i = 0; i < len; i++)
0108         fexpr_init(vec + i);
0109     return vec;
0110 }
0111 
0112 FEXPR_INLINE void
0113 _fexpr_vec_clear(fexpr_ptr vec, slong len)
0114 {
0115     slong i;
0116     for (i = 0; i < len; i++)
0117         fexpr_clear(vec + i);
0118     flint_free(vec);
0119 }
0120 
0121 FEXPR_INLINE void
0122 fexpr_fit_size(fexpr_t expr, slong size)
0123 {
0124     if (expr->alloc < size)
0125     {
0126         size = FLINT_MAX(size, 2 * expr->alloc);
0127         expr->data = (ulong *) flint_realloc(expr->data, size * sizeof(ulong));
0128         expr->alloc = size;
0129     }
0130 }
0131 
0132 FEXPR_INLINE slong
0133 _fexpr_size(const ulong * expr)
0134 {
0135     ulong head = expr[0];
0136     return FEXPR_SIZE(head);
0137 }
0138 
0139 FEXPR_INLINE slong
0140 fexpr_size(const fexpr_t expr)
0141 {
0142     return _fexpr_size(expr->data);
0143 }
0144 
0145 FEXPR_INLINE void
0146 fexpr_set(fexpr_t res, const fexpr_t expr)
0147 {
0148     if (res != expr)
0149     {
0150         slong i;
0151         slong size = fexpr_size(expr);
0152         fexpr_fit_size(res, size);
0153         for (i = 0; i < size; i++)
0154             res->data[i] = expr->data[i];
0155     }
0156 }
0157 
0158 FEXPR_INLINE void
0159 fexpr_swap(fexpr_t a, fexpr_t b)
0160 {
0161     FLINT_SWAP(fexpr_struct, *a, *b);
0162 }
0163 
0164 FEXPR_INLINE int
0165 fexpr_equal(const fexpr_t a, const fexpr_t b)
0166 {
0167     ulong ha, hb;
0168     slong i, sa, sb;
0169 
0170     ha = a->data[0];
0171     hb = b->data[0];
0172 
0173     if (ha != hb)
0174         return 0;
0175 
0176     sa = FEXPR_SIZE(ha);
0177     sb = FEXPR_SIZE(hb);
0178 
0179     if (sa != sb)
0180         return 0;
0181 
0182     for (i = 1; i < sa; i++)
0183         if (a->data[i] != b->data[i])
0184             return 0;
0185 
0186     return 1;
0187 }
0188 
0189 /* todo: document, test */
0190 int fexpr_equal_si(const fexpr_t expr, slong c);
0191 int fexpr_equal_ui(const fexpr_t expr, ulong c);
0192 ulong fexpr_hash(const fexpr_t expr);
0193 
0194 int fexpr_cmp_fast(const fexpr_t a, const fexpr_t b);
0195 
0196 void
0197 _fexpr_vec_sort_fast(fexpr_ptr vec, slong len);
0198 
0199 FEXPR_INLINE int
0200 _fexpr_is_integer(const ulong * expr)
0201 {
0202     ulong type = FEXPR_TYPE(expr[0]);
0203     return (type == FEXPR_TYPE_SMALL_INT) || (type == FEXPR_TYPE_BIG_INT_POS) || (type == FEXPR_TYPE_BIG_INT_NEG);
0204 }
0205 
0206 FEXPR_INLINE int
0207 fexpr_is_integer(const fexpr_t expr)
0208 {
0209     return _fexpr_is_integer(expr->data);
0210 }
0211 
0212 /* todo: document, test */
0213 int fexpr_is_neg_integer(const fexpr_t expr);
0214 
0215 FEXPR_INLINE int
0216 _fexpr_is_symbol(const ulong * expr)
0217 {
0218     ulong type = FEXPR_TYPE(expr[0]);
0219     return (type == FEXPR_TYPE_SMALL_SYMBOL) || (type == FEXPR_TYPE_BIG_SYMBOL);
0220 }
0221 
0222 FEXPR_INLINE int
0223 fexpr_is_symbol(const fexpr_t expr)
0224 {
0225     return _fexpr_is_symbol(expr->data);
0226 }
0227 
0228 FEXPR_INLINE int
0229 _fexpr_is_string(const ulong * expr)
0230 {
0231     ulong type = FEXPR_TYPE(expr[0]);
0232     return (type == FEXPR_TYPE_SMALL_STRING) || (type == FEXPR_TYPE_BIG_STRING);
0233 }
0234 
0235 FEXPR_INLINE int
0236 fexpr_is_string(const fexpr_t expr)
0237 {
0238     return _fexpr_is_string(expr->data);
0239 }
0240 
0241 FEXPR_INLINE int
0242 _fexpr_is_atom(const ulong * expr)
0243 {
0244     return FEXPR_TYPE(expr[0]) <= FEXPR_TYPE_BIG_STRING;
0245 }
0246 
0247 FEXPR_INLINE int
0248 fexpr_is_atom(const fexpr_t expr)
0249 {
0250     return _fexpr_is_atom(expr->data);
0251 }
0252 
0253 FEXPR_INLINE void
0254 fexpr_zero(fexpr_t res)
0255 {
0256     res->data[0] = 0;
0257 }
0258 
0259 FEXPR_INLINE int
0260 fexpr_is_zero(const fexpr_t expr)
0261 {
0262     return expr->data[0] == 0;
0263 }
0264 
0265 void fexpr_set_si(fexpr_t res, slong c);
0266 void fexpr_set_ui(fexpr_t res, ulong c);
0267 void fexpr_set_fmpz(fexpr_t res, const fmpz_t c);
0268 int fexpr_get_fmpz(fmpz_t c, const fexpr_t x);
0269 void fexpr_set_fmpq(fexpr_t res, const fmpq_t x);
0270 
0271 FEXPR_INLINE void
0272 fexpr_set_symbol_builtin(fexpr_t res, slong id)
0273 {
0274     res->data[0] = FEXPR_TYPE_SMALL_SYMBOL | (id << 16);
0275 }
0276 
0277 void fexpr_set_symbol_str(fexpr_t res, const char * s);
0278 void fexpr_set_string(fexpr_t res, const char * s);
0279 
0280 char * fexpr_get_symbol_str(const fexpr_t expr);
0281 char * fexpr_get_string(const fexpr_t expr);
0282 char * fexpr_get_decimal_str(const fexpr_t expr, slong digits, ulong flags);
0283 
0284 slong fexpr_depth(const fexpr_t expr);
0285 slong fexpr_num_leaves(const fexpr_t expr);
0286 
0287 FEXPR_INLINE slong
0288 fexpr_size_bytes(const fexpr_t expr)
0289 {
0290     return fexpr_size(expr) * sizeof(ulong);
0291 }
0292 
0293 FEXPR_INLINE slong
0294 fexpr_allocated_bytes(const fexpr_t expr)
0295 {
0296     return expr->alloc * sizeof(ulong);
0297 }
0298 
0299 /* todo: document */
0300 FEXPR_INLINE int
0301 fexpr_is_any_builtin_symbol(const fexpr_t expr)
0302 {
0303     ulong head;
0304     head = expr->data[0];
0305     return (FEXPR_TYPE(head) == FEXPR_TYPE_SMALL_SYMBOL) && (((head >> 8) & 0xff) == 0);
0306 }
0307 
0308 /* todo: document */
0309 FEXPR_INLINE int
0310 fexpr_is_builtin_symbol(const fexpr_t expr, slong i)
0311 {
0312     ulong head;
0313     head = expr->data[0];
0314     return (FEXPR_TYPE(head) == FEXPR_TYPE_SMALL_SYMBOL) && (((head >> 8) & 0xff) == 0) && (FEXPR_BUILTIN_ID(head) == i);
0315 }
0316 
0317 /* todo: document, test */
0318 int fexpr_is_builtin_call(const fexpr_t expr, slong i);
0319 int fexpr_is_any_builtin_call(const fexpr_t expr);
0320 
0321 FEXPR_INLINE slong
0322 fexpr_nargs(const fexpr_t expr)
0323 {
0324     ulong type = FEXPR_TYPE(expr->data[0]);
0325 
0326     if (FEXPR_TYPE_CALL0 <= type && type <= FEXPR_TYPE_CALL4)
0327     {
0328         return type - FEXPR_TYPE_CALL0;
0329     }
0330     else if (type == FEXPR_TYPE_CALLN)
0331     {
0332         return expr->data[1];
0333     }
0334     else
0335     {
0336         return -1;
0337     }
0338 }
0339 
0340 void fexpr_func(fexpr_t res, const fexpr_t expr);
0341 void fexpr_view_func(fexpr_t res, const fexpr_t expr);
0342 
0343 void fexpr_arg(fexpr_t res, const fexpr_t expr, slong i);
0344 void fexpr_view_arg(fexpr_t res, const fexpr_t expr, slong i);
0345 
0346 FEXPR_INLINE void
0347 fexpr_view_next(fexpr_t view)
0348 {
0349     view->data += fexpr_size(view);
0350 }
0351 
0352 /* todo: handle aliasing! */
0353 void fexpr_call0(fexpr_t res, const fexpr_t f);
0354 void fexpr_call1(fexpr_t res, const fexpr_t f, const fexpr_t x1);
0355 void fexpr_call2(fexpr_t res, const fexpr_t f, const fexpr_t x1, const fexpr_t x2);
0356 void fexpr_call3(fexpr_t res, const fexpr_t f, const fexpr_t x1, const fexpr_t x2, const fexpr_t x3);
0357 void fexpr_call4(fexpr_t res, const fexpr_t f, const fexpr_t x1, const fexpr_t x2, const fexpr_t x3, const fexpr_t x4);
0358 
0359 void fexpr_call_vec(fexpr_t res, const fexpr_t f, fexpr_srcptr args, slong len);
0360 
0361 void fexpr_call_builtin1(fexpr_t res, slong f, const fexpr_t x);
0362 void fexpr_call_builtin2(fexpr_t res, slong f, const fexpr_t x, const fexpr_t y);
0363 
0364 /* Subexpressions and replacement */
0365 
0366 int fexpr_contains(const fexpr_t expr, const fexpr_t x);
0367 int fexpr_replace(fexpr_t res, const fexpr_t expr, const fexpr_t x, const fexpr_t y);
0368 int fexpr_replace2(fexpr_t res, const fexpr_t expr, const fexpr_t x1, const fexpr_t y1, const fexpr_t x2, const fexpr_t y2);
0369 int fexpr_replace_vec(fexpr_t res, const fexpr_t expr, const fexpr_vec_t xs, const fexpr_vec_t ys);
0370 
0371 
0372 /* Input/output */
0373 
0374 void fexpr_write(calcium_stream_t stream, const fexpr_t expr);
0375 void fexpr_print(const fexpr_t expr);
0376 char * fexpr_get_str(const fexpr_t expr);
0377 
0378 /* LaTeX output */
0379 
0380 #define FEXPR_LATEX_SMALL 1
0381 #define FEXPR_LATEX_LOGIC 2
0382 
0383 void fexpr_write_latex(calcium_stream_t out, const fexpr_t expr, ulong flags);
0384 void fexpr_print_latex(const fexpr_t expr, ulong flags);
0385 char * fexpr_get_str_latex(const fexpr_t expr, ulong flags);
0386 
0387 void fexpr_write_latex_call(calcium_stream_t out, const fexpr_t expr, ulong flags);
0388 void fexpr_write_latex_subscript(calcium_stream_t out, const fexpr_t expr, ulong flags);
0389 void fexpr_write_latex_subscript_call(calcium_stream_t out, const fexpr_t expr, ulong flags);
0390 void fexpr_write_latex_infix(calcium_stream_t out, const fexpr_t expr, ulong flags);
0391 void fexpr_write_latex_mul(calcium_stream_t out, const fexpr_t expr, ulong flags);
0392 void fexpr_write_latex_div(calcium_stream_t out, const fexpr_t expr, ulong flags);
0393 void fexpr_write_latex_neg_pos(calcium_stream_t out, const fexpr_t expr, ulong flags);
0394 void fexpr_write_latex_add(calcium_stream_t out, const fexpr_t expr, ulong flags);
0395 void fexpr_write_latex_sub(calcium_stream_t out, const fexpr_t expr, ulong flags);
0396 void fexpr_write_latex_pow(calcium_stream_t out, const fexpr_t expr, ulong flags);
0397 void fexpr_write_latex_exp(calcium_stream_t out, const fexpr_t expr, ulong flags);
0398 void fexpr_write_latex_factorial(calcium_stream_t out, const fexpr_t expr, ulong flags);
0399 void fexpr_write_latex_integral(calcium_stream_t out, const fexpr_t expr, ulong flags);
0400 void fexpr_write_latex_sum_product(calcium_stream_t out, const fexpr_t expr, ulong flags);
0401 void fexpr_write_latex_divsum(calcium_stream_t out, const fexpr_t expr, ulong flags);
0402 void fexpr_write_latex_limit(calcium_stream_t out, const fexpr_t expr, ulong flags);
0403 void fexpr_write_latex_derivative(calcium_stream_t out, const fexpr_t expr, ulong flags);
0404 void fexpr_write_latex_logic(calcium_stream_t out, const fexpr_t expr, ulong flags);
0405 void fexpr_write_latex_collection(calcium_stream_t out, const fexpr_t expr, ulong flags);
0406 void fexpr_write_latex_matrix(calcium_stream_t out, const fexpr_t expr, ulong flags);
0407 void fexpr_write_latex_simple(calcium_stream_t out, const fexpr_t expr, ulong flags);
0408 void fexpr_write_latex_simple2(calcium_stream_t out, const fexpr_t expr, ulong flags);
0409 void fexpr_write_latex_simple2_small(calcium_stream_t out, const fexpr_t expr, ulong flags);
0410 void fexpr_write_latex_alg_structure(calcium_stream_t out, const fexpr_t expr, ulong flags);
0411 void fexpr_write_latex_setop(calcium_stream_t out, const fexpr_t expr, ulong flags);
0412 void fexpr_write_latex_cases(calcium_stream_t out, const fexpr_t expr, ulong flags);
0413 void fexpr_write_latex_where(calcium_stream_t out, const fexpr_t expr, ulong flags);
0414 void fexpr_write_latex_show_form(calcium_stream_t out, const fexpr_t expr, ulong flags);
0415 void fexpr_write_latex_range(calcium_stream_t out, const fexpr_t expr, ulong flags);
0416 void fexpr_write_latex_decimal(calcium_stream_t out, const fexpr_t expr, ulong flags);
0417 void fexpr_write_latex_call1_optional_derivative(calcium_stream_t out, const fexpr_t expr, ulong flags);
0418 void fexpr_write_latex_call2_optional_derivative(calcium_stream_t out, const fexpr_t expr, ulong flags);
0419 void fexpr_write_latex_sub1_call1_optional_derivative(calcium_stream_t out, const fexpr_t expr, ulong flags);
0420 void fexpr_write_latex_sub1_call2_optional_derivative(calcium_stream_t out, const fexpr_t expr, ulong flags);
0421 void fexpr_write_latex_misc_special(calcium_stream_t out, const fexpr_t expr, ulong flags);
0422 void fexpr_write_latex_residue(calcium_stream_t out, const fexpr_t expr, ulong flags);
0423 
0424 void fexpr_set_arf(fexpr_t res, const arf_t x);
0425 void fexpr_set_d(fexpr_t res, double x);
0426 void fexpr_set_re_im_d(fexpr_t res, double x, double y);
0427 
0428 void fexpr_neg(fexpr_t res, const fexpr_t a);
0429 void fexpr_add(fexpr_t res, const fexpr_t a, const fexpr_t b);
0430 void fexpr_sub(fexpr_t res, const fexpr_t a, const fexpr_t b);
0431 void fexpr_mul(fexpr_t res, const fexpr_t a, const fexpr_t b);
0432 void fexpr_div(fexpr_t res, const fexpr_t a, const fexpr_t b);
0433 void fexpr_pow(fexpr_t res, const fexpr_t a, const fexpr_t b);
0434 
0435 int fexpr_is_arithmetic_operation(const fexpr_t expr);
0436 
0437 void fexpr_arithmetic_nodes(fexpr_vec_t nodes, const fexpr_t expr);
0438 
0439 int fexpr_get_fmpz_mpoly_q(fmpz_mpoly_q_t res, const fexpr_t expr, const fexpr_vec_t vars, const fmpz_mpoly_ctx_t ctx);
0440 
0441 void fexpr_set_fmpz_mpoly(fexpr_t res, const fmpz_mpoly_t poly, const fexpr_vec_t vars, const fmpz_mpoly_ctx_t ctx);
0442 void fexpr_set_fmpz_mpoly_q(fexpr_t res, const fmpz_mpoly_q_t frac, const fexpr_vec_t vars, const fmpz_mpoly_ctx_t ctx);
0443 
0444 int fexpr_expanded_normal_form(fexpr_t res, const fexpr_t expr, ulong flags);
0445 
0446 /* Vectors */
0447 
0448 FEXPR_INLINE void
0449 fexpr_vec_init(fexpr_vec_t vec, slong len)
0450 {
0451     if (len == 0)
0452     {
0453         vec->entries = NULL;
0454         vec->length = 0;
0455         vec->alloc = 0;
0456     }
0457     else
0458     {
0459         slong i;
0460         vec->entries = (fexpr_ptr) flint_malloc(sizeof(fexpr_struct) * len);
0461         for (i = 0; i < len; i++)
0462             fexpr_init(vec->entries + i);
0463         vec->length = vec->alloc = len;
0464     }
0465 }
0466 
0467 FEXPR_INLINE void
0468 fexpr_vec_print(const fexpr_vec_t F)
0469 {
0470     slong i;
0471 
0472     flint_printf("[");
0473     for (i = 0; i < F->length; i++)
0474     {
0475         fexpr_print(F->entries + i);
0476         if (i < F->length - 1)
0477             flint_printf(", ");
0478     }
0479     flint_printf("]");
0480 }
0481 
0482 FEXPR_INLINE void
0483 fexpr_vec_swap(fexpr_vec_t x, fexpr_vec_t y)
0484 {
0485     fexpr_vec_t tmp;
0486     *tmp = *x;
0487     *x = *y;
0488     *y = *tmp;
0489 }
0490 
0491 FEXPR_INLINE void
0492 fexpr_vec_fit_length(fexpr_vec_t vec, slong len)
0493 {
0494     if (len > vec->alloc)
0495     {
0496         slong i;
0497 
0498         if (len < 2 * vec->alloc)
0499             len = 2 * vec->alloc;
0500 
0501         vec->entries = (fexpr_struct *) flint_realloc(vec->entries, len * sizeof(fexpr_struct));
0502 
0503         for (i = vec->alloc; i < len; i++)
0504             fexpr_init(vec->entries + i);
0505 
0506         vec->alloc = len;
0507     }
0508 }
0509 
0510 FEXPR_INLINE void
0511 fexpr_vec_clear(fexpr_vec_t vec)
0512 {
0513     slong i;
0514 
0515     for (i = 0; i < vec->alloc; i++)
0516         fexpr_clear(vec->entries + i);
0517 
0518     flint_free(vec->entries);
0519 }
0520 
0521 FEXPR_INLINE void
0522 fexpr_vec_set(fexpr_vec_t dest, const fexpr_vec_t src)
0523 {
0524     if (dest != src)
0525     {
0526         slong i;
0527 
0528         fexpr_vec_fit_length(dest, src->length);
0529 
0530         for (i = 0; i < src->length; i++)
0531             fexpr_set(dest->entries + i, src->entries + i);
0532 
0533         dest->length = src->length;
0534     }
0535 }
0536 
0537 FEXPR_INLINE void
0538 fexpr_vec_append(fexpr_vec_t vec, const fexpr_t f)
0539 {
0540     fexpr_vec_fit_length(vec, vec->length + 1);
0541     fexpr_set(vec->entries + vec->length, f);
0542     vec->length++;
0543 }
0544 
0545 FEXPR_INLINE slong
0546 fexpr_vec_insert_unique(fexpr_vec_t vec, const fexpr_t f)
0547 {
0548     slong i;
0549 
0550     for (i = 0; i < vec->length; i++)
0551     {
0552         if (fexpr_equal(vec->entries + i, f))
0553             return i;
0554     }
0555 
0556     fexpr_vec_append(vec, f);
0557     return vec->length - 1;
0558 }
0559 
0560 FEXPR_INLINE void
0561 fexpr_vec_set_length(fexpr_vec_t vec, slong len)
0562 {
0563     slong i;
0564 
0565     if (len > vec->length)
0566     {
0567         fexpr_vec_fit_length(vec, len);
0568         for (i = vec->length; i < len; i++)
0569             fexpr_zero(vec->entries + i);
0570     }
0571     else if (len < vec->length)
0572     {
0573         for (i = len; i < vec->length; i++)
0574            fexpr_zero(vec->entries + i);
0575     }
0576 
0577     vec->length = len;
0578 }
0579 
0580 
0581 #ifdef __cplusplus
0582 }
0583 #endif
0584 
0585 #endif