pike.git
/
src
/
operators.c
version
»
Context lines:
10
20
40
80
file
none
3
pike.git/src/operators.c:1312:
#endif /* PIKE_DEBUG */ apply_low(o, i, e); args -= e; /* Replace the object with the result. */ assign_svalue(Pike_sp-(args+1), Pike_sp-1); pop_stack(); return args; } }
+
/* Sift down large (absolute) values on the heap. */
+
static void float_heap_sift_down(struct svalue *svalues, int root, int nelems)
+
{
+
FLOAT_ARG_TYPE val = svalues[root].u.float_number;
+
FLOAT_ARG_TYPE abs_val = abs(val);
+
int child;
+
+
while ((child = ((root<<1) +1)) < nelems) {
+
int swap = root;
+
FLOAT_ARG_TYPE s_abs_val;
+
if ((s_abs_val = abs(svalues[child].u.float_number)) < abs_val) {
+
swap = child;
+
} else {
+
s_abs_val = abs_val;
+
}
+
child++;
+
if ((child < nelems) &&
+
(abs(svalues[child].u.float_number) < s_abs_val)) {
+
swap = child;
+
}
+
if (swap == root) break;
+
svalues[root] = svalues[swap];
+
root = swap;
+
}
+
svalues[root].u.float_number = val;
+
}
+
/*! @decl mixed `+(mixed arg) *! @decl mixed `+(object arg, mixed ... more) *! @decl int `+(int arg, int ... more) *! @decl float `+(float|int arg, float|int ... more) *! @decl string `+(string|float|int arg, string|float|int ... more) *! @decl array `+(array arg, array ... more) *! @decl mapping `+(mapping arg, mapping ... more) *! @decl multiset `+(multiset arg, multiset ... more) *! *! Addition/concatenation.
pike.git/src/operators.c:1392:
*! *! @seealso *! @[`-()], @[lfun::`+()], @[lfun::``+()] */ PMOD_EXPORT void f_add(INT32 args) { INT_TYPE e,size; TYPE_FIELD types; tail_recurse:
+
if (args == 1) return;
+
types=0; for(e=-args;e<0;e++) types|=1<<sp[e].type; switch(types) { default: if(!args) { SIMPLE_TOO_FEW_ARGS_ERROR("`+", 1); }else{
pike.git/src/operators.c:1660:
#else size=0; for(e=-args; e<0; e++) size+=sp[e].u.integer; sp-=args-1; sp[-1].u.integer=size; sp[-1].subtype = NUMBER_NUMBER; #endif /* AUTO_BIGNUM */ break; case BIT_FLOAT:
-
{
-
FLOAT_ARG_TYPE
sum;
-
sum=0
.
0;
-
for(e=
-
args; e
<0
;
e++
)
sum+=sp[e].u.float_number;
-
sp-=args-1;
-
sp[-1].u.
float_
number =
(
FLOAT
_
TYPE)
sum;
-
break
;
+
if (args > 2)
{
+
/* Attempt to minimize the accumulated summation error
+
* by adding the smallest (absolute) values first
.
+
*
+
* This can eg happen when the number of values to add
+
* is in the same order as the number of bits in the
+
* mantissa.
+
*/
+
/* Heapify */
+
for(e
=
args
>>1
; e
--
;)
{
+
float_
heap_sift_down
(
Pike
_
sp-args,
e,
args)
;
}
-
+
while (args > 2) {
+
FLOAT_ARG_TYPE top = Pike_sp[-args].u.float_number;
+
Pike_sp[-args] = *(--Pike_sp);
+
args--;
+
float_heap_sift_down(Pike_sp-args, 0, args);
-
+
Pike_sp[-args].u.float_number += top;
+
float_heap_sift_down(Pike_sp-args, 0, args);
+
}
+
}
+
sp[-2].u.float_number += sp[-1].u.float_number;
+
sp--;
+
break;
+
case BIT_FLOAT|BIT_INT: {
-
FLOAT_ARG_TYPE
sum
;
-
sum=0.0;
-
for(e=-args;
e<0;
e++)
-
{
-
if(sp[e].type
=
=T_FLOAT)
-
{
-
sum+=sp[e].u.float_number;
-
}else{
-
sum+=
(
FLOAT_ARG_TYPE)
sp[
e
].
u.integer
;
+
/*
For improved precision
;
partition the values
+
* into floats followed by ints, so that we
+
*
can add the integers exactly.
+
*/
+
int
i
=
args-1;
+
e
=
0;
+
while
(e
<
i)
{
+
for(;e < i; i--) {
+
if
(sp[
i-args
].
type == T_FLOAT) break
;
}
-
+
for(;e < i; e++) {
+
if (sp[e-args].type == T_INT) break;
}
-
sp-=args-1;
-
sp[-
1
]
.type=T_FLOAT
;
-
sp[-
1
]
.u.float_number
=
(FLOAT_TYPE) sum
;
-
break
;
+
if (e < i) {
+
/* Swap */
+
struct svalue sval =
sp[
e
-
args
];
+
sp[
e
-
args
] =
sp[i-args]
;
+
sp[i-args] = sval
;
}
-
+
}
+
if (sp[e-args].type == T_FLOAT) e++;
+
/* Sum the integers. */
+
if (args - e > 1) {
+
f_add(args-e);
+
}
+
args = e+1;
+
o_cast(float_type_string, PIKE_T_FLOAT);
-
+
/* Now all the values should be floats. */
+
goto tail_recurse;
+
}
+
#define ADD_WITH_UNDEFINED(TYPE, T_TYPEID, ADD_FUNC, PUSH_FUNC) do { \ int e; \ if (sp[-args].type == T_INT) { \ if(IS_UNDEFINED(sp-args)) \ { \ struct TYPE *x; \ \ for(e=1;e<args;e++) \ if(sp[e-args].type != T_TYPEID) \ SIMPLE_ARG_TYPE_ERROR("`+", e+1, #TYPE); \