File: call_vec.c

package info (click to toggle)
calcium 0.4.1-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 4,756 kB
  • sloc: ansic: 62,836; python: 2,827; sh: 518; makefile: 163
file content (77 lines) | stat: -rw-r--r-- 1,945 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
/*
    Copyright (C) 2021 Fredrik Johansson

    This file is part of Calcium.

    Calcium 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 2.1 of the License, or
    (at your option) any later version.  See <http://www.gnu.org/licenses/>.
*/

#include "fexpr.h"

void
fexpr_call_vec(fexpr_t res, const fexpr_t f, fexpr_srcptr args, slong len)
{
    if (len == 0)
    {
        fexpr_call0(res, f);
    }
    else if (len == 1)
    {
        fexpr_call1(res, f, args);
    }
    else if (len == 2)
    {
        fexpr_call2(res, f, args, args + 1);
    }
    else if (len == 3)
    {
        fexpr_call3(res, f, args, args + 1, args + 2);
    }
    else if (len == 4)
    {
        fexpr_call4(res, f, args, args + 1, args + 2, args + 3);
    }
    else
    {
        slong i, f_size, args_size, index_size, size, pos, arg_size;
        mp_ptr out;

        f_size = fexpr_size(f);

        args_size = 0;
        for (i = 0; i < len; i++)
            args_size += fexpr_size(args + i);

        /* write index:
            data[1] = nargs
            data[2] = position of f
            data[3], data[4], ..., positions of every 1/4 args for random access */
        index_size = 2 + (len + 4 - 1) / 4;

        size = 1 + index_size + f_size + args_size;

        fexpr_fit_size(res, size);
        out = res->data;

        out[0] = FEXPR_TYPE_CALLN | (size << FEXPR_TYPE_BITS);
        out[1] = len;

        pos = 1 + index_size;
        out[2] = pos;
        flint_mpn_copyi(out + pos, f->data, f_size);
        pos += f_size;

        for (i = 0; i < len; i++)
        {
            if (i % 4 == 0)
                out[3 + i / 4] = pos;

            arg_size = fexpr_size(args + i);
            flint_mpn_copyi(out + pos, args[i].data, arg_size);
            pos += arg_size;
        }
    }
}