mirror of
https://github.com/lcn2/calc.git
synced 2025-08-16 01:03:29 +03:00
Converted all ASCII tabs to ASCII spaces using a 8 character tab stop, for all files, except for all Makefiles (plus rpm.mk). The `git diff -w` reports no changes.
445 lines
13 KiB
C
445 lines
13 KiB
C
/*
|
|
* size - size and sizeof functions are implemented here
|
|
*
|
|
* Copyright (C) 1999-2007,2021-2023 David I. Bell
|
|
*
|
|
* Calc is open software; you can redistribute it and/or modify it under
|
|
* the terms of the version 2.1 of the GNU Lesser General Public License
|
|
* as published by the Free Software Foundation.
|
|
*
|
|
* Calc is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
|
|
* Public License for more details.
|
|
*
|
|
* A copy of version 2.1 of the GNU Lesser General Public License is
|
|
* distributed with calc under the filename COPYING-LGPL. You should have
|
|
* received a copy with calc; if not, write to Free Software Foundation, Inc.
|
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*
|
|
* Under source code control: 1997/03/10 01:56:51
|
|
* File existed as early as: 1997
|
|
*
|
|
* Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/
|
|
*/
|
|
|
|
|
|
#include "value.h"
|
|
#include "zrand.h"
|
|
#include "zrandom.h"
|
|
#include "block.h"
|
|
|
|
|
|
#include "errtbl.h"
|
|
#include "banned.h" /* include after system header <> includes */
|
|
|
|
|
|
/*
|
|
* forward declarations
|
|
*/
|
|
S_FUNC size_t zsize(ZVALUE);
|
|
S_FUNC size_t qsize(NUMBER*);
|
|
S_FUNC size_t csize(COMPLEX*);
|
|
S_FUNC size_t memzsize(ZVALUE);
|
|
S_FUNC size_t memqsize(NUMBER*);
|
|
|
|
|
|
/*
|
|
* elm_count - return information about the number of elements
|
|
*
|
|
* Return information about the number of elements or part of
|
|
* a value. This is what the size() builtin returns with the
|
|
* exception of the V_FILE type. To get V_FILE size length,
|
|
* the getsize(vp->v_file, &len) should be called directly.
|
|
*
|
|
* This is not the sizeof, see lsizeof() for that information.
|
|
*
|
|
* given:
|
|
* vp pointer to a value
|
|
*
|
|
* return:
|
|
* number of elements
|
|
*/
|
|
long
|
|
elm_count(VALUE *vp)
|
|
{
|
|
long result;
|
|
|
|
/*
|
|
* return information about the number of elements
|
|
*
|
|
* This is not the sizeof, see lsizeof() for that information.
|
|
* This is does not include overhead, see memsize() for that info.
|
|
*/
|
|
|
|
switch (vp->v_type) {
|
|
case V_NULL:
|
|
case V_INT:
|
|
case V_ADDR:
|
|
case V_OCTET:
|
|
result = 0;
|
|
break;
|
|
case V_MAT:
|
|
result = vp->v_mat->m_size;
|
|
break;
|
|
case V_LIST:
|
|
result = vp->v_list->l_count;
|
|
break;
|
|
case V_ASSOC:
|
|
result = vp->v_assoc->a_count;
|
|
break;
|
|
case V_OBJ:
|
|
result = vp->v_obj->o_actions->oa_count;
|
|
break;
|
|
case V_STR:
|
|
result = vp->v_str->s_len;
|
|
break;
|
|
case V_BLOCK:
|
|
result = (long) vp->v_block->datalen;
|
|
break;
|
|
case V_NBLOCK:
|
|
result = (long) vp->v_nblock->blk->datalen;
|
|
break;
|
|
/*
|
|
* V_NUM, V_COM, V_RAND, V_RANDOM, V_CONFIG, V_HASH
|
|
*
|
|
* V_FILE (use getsize(vp->v_file, &len) for file length)
|
|
*/
|
|
default:
|
|
result = (vp->v_type > 0);
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
|
|
/*
|
|
* zsize - calculate memory footprint of a ZVALUE (excluding overhead)
|
|
*
|
|
* The numeric -1, - and 1 storage values are ignored.
|
|
*
|
|
* given:
|
|
* z ZVALUE to examine
|
|
*
|
|
* returns:
|
|
* value size
|
|
*/
|
|
S_FUNC size_t
|
|
zsize(ZVALUE z)
|
|
{
|
|
/* ignore the size of 0, 1 and -1 */
|
|
if (z.v != _zeroval_ && z.v != _oneval_ && !zisunit(z) && !ziszero(z)) {
|
|
return z.len * sizeof(HALF);
|
|
} else {
|
|
return (size_t)0;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* qsize - calculate memory footprint of a NUMBER (excluding overhead)
|
|
*
|
|
* The numeric -1, - and 1 storage values are ignored. Denominator
|
|
* parts of integers are ignored.
|
|
*
|
|
* given:
|
|
* q pointer to NUMBER to examine
|
|
*
|
|
* returns:
|
|
* value size
|
|
*/
|
|
S_FUNC size_t
|
|
qsize(NUMBER *q)
|
|
{
|
|
/* ignore denominator parts of integers */
|
|
if (qisint(q)) {
|
|
return zsize(q->num);
|
|
} else {
|
|
return (zsize(q->num) + zsize(q->den));
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* csize - calculate memory footprint of a COMPLEX (excluding overhead)
|
|
*
|
|
* The numeric -1, - and 1 storage values are ignored. Denominator
|
|
* parts of integers are ignored. Imaginary parts of pure reals
|
|
* are ignored.
|
|
*
|
|
* given:
|
|
* c pointer to COMPLEX to examine
|
|
*
|
|
* returns:
|
|
* value size
|
|
*/
|
|
S_FUNC size_t
|
|
csize(COMPLEX *c)
|
|
{
|
|
/* ignore denominator parts of integers */
|
|
if (cisreal(c)) {
|
|
return qsize(c->real);
|
|
} else {
|
|
return (qsize(c->real) + qsize(c->imag));
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* memzsize - calculate memory footprint of a ZVALUE including overhead
|
|
*
|
|
* given:
|
|
* z ZVALUE to examine
|
|
*
|
|
* returns:
|
|
* memory footprint
|
|
*/
|
|
S_FUNC size_t
|
|
memzsize(ZVALUE z)
|
|
{
|
|
return sizeof(ZVALUE) + (z.len * sizeof(HALF));
|
|
}
|
|
|
|
|
|
/*
|
|
* memqsize - calculate memory footprint of a NUMBER including overhead
|
|
*
|
|
* given:
|
|
* q pointer of NUMBER to examine
|
|
*
|
|
* returns:
|
|
* memory footprint
|
|
*/
|
|
S_FUNC size_t
|
|
memqsize(NUMBER *q)
|
|
{
|
|
return sizeof(NUMBER) + memzsize(q->num) + memzsize(q->den);
|
|
}
|
|
|
|
|
|
/*
|
|
* lsizeof - calculate memory footprint of a VALUE (not counting overhead)
|
|
*
|
|
* given:
|
|
* vp pointer of VALUE to examine
|
|
*
|
|
* returns:
|
|
* memory footprint
|
|
*/
|
|
size_t
|
|
lsizeof(VALUE *vp)
|
|
{
|
|
VALUE *p;
|
|
LISTELEM *ep;
|
|
OBJECTACTIONS *oap;
|
|
ASSOCELEM *aep;
|
|
ASSOCELEM **ept;
|
|
size_t s;
|
|
long i;
|
|
|
|
/*
|
|
* return information about memory footprint
|
|
*
|
|
* This is not the number of elements, see elm_count() for that info.
|
|
* This is does not include overhead, see memsize() for that info.
|
|
*/
|
|
i = 0;
|
|
s = 0;
|
|
if (vp->v_type > 0) {
|
|
switch(vp->v_type) {
|
|
case V_INT:
|
|
case V_ADDR:
|
|
case V_OCTET:
|
|
break;
|
|
case V_NUM:
|
|
s = qsize(vp->v_num);
|
|
break;
|
|
case V_COM:
|
|
s = csize(vp->v_com);
|
|
break;
|
|
case V_STR:
|
|
s = vp->v_str->s_len + 1;
|
|
break;
|
|
case V_MAT:
|
|
i = vp->v_mat->m_size;
|
|
p = vp->v_mat->m_table;
|
|
while (i-- > 0)
|
|
s += lsizeof(p++);
|
|
break;
|
|
case V_LIST:
|
|
for (ep = vp->v_list->l_first; ep; ep = ep->e_next) {
|
|
s += lsizeof(&ep->e_value);
|
|
}
|
|
break;
|
|
case V_ASSOC:
|
|
i = vp->v_assoc->a_size;
|
|
ept = vp->v_assoc->a_table;
|
|
while (i-- > 0) {
|
|
for (aep = ept[i]; aep; aep = aep->e_next) {
|
|
s += lsizeof(&aep->e_value);
|
|
}
|
|
}
|
|
break;
|
|
case V_OBJ:
|
|
oap = vp->v_obj->o_actions;
|
|
i = oap->oa_count;
|
|
p = vp->v_obj->o_table;
|
|
while (i-- > 0)
|
|
s += lsizeof(p++);
|
|
break;
|
|
case V_FILE:
|
|
s = sizeof(vp->v_file);
|
|
break;
|
|
case V_RAND:
|
|
s = sizeof(RAND);
|
|
break;
|
|
case V_RANDOM:
|
|
s = sizeof(RANDOM) +
|
|
zsize(vp->v_random->n) +
|
|
zsize(vp->v_random->r);
|
|
break;
|
|
case V_CONFIG:
|
|
s = sizeof(CONFIG) +
|
|
strlen(vp->v_config->prompt1) +
|
|
strlen(vp->v_config->prompt2) + 2;
|
|
break;
|
|
case V_HASH:
|
|
/* ignore the unused part of the union */
|
|
s = sizeof(HASH) +
|
|
vp->v_hash->unionsize -
|
|
sizeof(vp->v_hash->h_union);
|
|
break;
|
|
case V_BLOCK:
|
|
s = vp->v_block->maxsize;
|
|
break;
|
|
case V_NBLOCK:
|
|
s = vp->v_nblock->blk->maxsize;
|
|
break;
|
|
default:
|
|
math_error("sizeof not defined for value type");
|
|
not_reached();
|
|
}
|
|
}
|
|
return s;
|
|
}
|
|
|
|
|
|
/*
|
|
* memsize - calculate memory footprint of a VALUE including overhead
|
|
*
|
|
* given:
|
|
* vp pointer of VALUE to examine
|
|
*
|
|
* returns:
|
|
* memory footprint including overhead
|
|
*/
|
|
size_t
|
|
memsize(VALUE *vp)
|
|
{
|
|
size_t s;
|
|
long i, j;
|
|
VALUE *p;
|
|
LISTELEM *ep;
|
|
OBJECTACTIONS *oap;
|
|
ASSOCELEM *aep;
|
|
ASSOCELEM **ept;
|
|
|
|
/*
|
|
* return information about memory footprint
|
|
*
|
|
* This is not the sizeof, see memsize() for that information.
|
|
* This is not the number of elements, see elm_count() for that info.
|
|
*/
|
|
i = j = 0;
|
|
s = sizeof(VALUE);
|
|
if (vp->v_type > 0) {
|
|
switch(vp->v_type) {
|
|
case V_INT:
|
|
case V_ADDR:
|
|
case V_OCTET:
|
|
break;
|
|
case V_NUM:
|
|
s = memqsize(vp->v_num);
|
|
break;
|
|
case V_COM:
|
|
s = sizeof(COMPLEX) +
|
|
memqsize(vp->v_com->real) +
|
|
memqsize(vp->v_com->imag);
|
|
break;
|
|
case V_STR:
|
|
s = sizeof(STRING) + vp->v_str->s_len + 1;
|
|
break;
|
|
case V_MAT:
|
|
s = sizeof(MATRIX);
|
|
i = vp->v_mat->m_size;
|
|
p = vp->v_mat->m_table;
|
|
while (i-- > 0)
|
|
s += memsize(p++);
|
|
break;
|
|
case V_LIST:
|
|
s = sizeof(LIST);
|
|
for (ep = vp->v_list->l_first; ep; ep = ep->e_next) {
|
|
s += sizeof(LISTELEM) - sizeof(VALUE) +
|
|
memsize(&ep->e_value);
|
|
}
|
|
break;
|
|
case V_ASSOC:
|
|
s = sizeof(ASSOC);
|
|
i = vp->v_assoc->a_size;
|
|
ept = vp->v_assoc->a_table;
|
|
while (i-- > 0) {
|
|
s += sizeof(ASSOCELEM *);
|
|
for (aep = *ept++; aep; aep = aep->e_next) {
|
|
s += sizeof(ASSOCELEM) - sizeof(VALUE) +
|
|
memsize(&aep->e_value);
|
|
j = aep->e_dim;
|
|
p = aep->e_indices;
|
|
while (j-- > 0)
|
|
s += memsize(p++);
|
|
}
|
|
}
|
|
break;
|
|
case V_OBJ:
|
|
s = sizeof(OBJECT);
|
|
oap = vp->v_obj->o_actions;
|
|
i = oap->oa_count;
|
|
s += (i + 3) * sizeof(int);
|
|
p = vp->v_obj->o_table;
|
|
while (i-- > 0)
|
|
s += memsize(p++);
|
|
break;
|
|
case V_FILE:
|
|
s = sizeof(vp->v_file);
|
|
break;
|
|
case V_RAND:
|
|
s = sizeof(RAND);
|
|
break;
|
|
case V_RANDOM:
|
|
s = sizeof(RANDOM) +
|
|
memzsize(vp->v_random->n) +
|
|
memzsize(vp->v_random->r);
|
|
break;
|
|
case V_CONFIG:
|
|
s = sizeof(CONFIG) + 2 +
|
|
strlen(vp->v_config->prompt1) +
|
|
strlen(vp->v_config->prompt2);
|
|
break;
|
|
case V_HASH:
|
|
s = sizeof(HASH);
|
|
break;
|
|
case V_BLOCK:
|
|
s = sizeof(BLOCK) + vp->v_block->maxsize;
|
|
break;
|
|
case V_NBLOCK:
|
|
s = sizeof(NBLOCK) + sizeof(BLOCK) +
|
|
vp->v_nblock->blk->maxsize +
|
|
strlen(vp->v_nblock->name) + 1;
|
|
break;
|
|
default:
|
|
math_error("memsize not defined for value type");
|
|
not_reached();
|
|
}
|
|
}
|
|
return s;
|
|
}
|