+#if 0
+static void _fail_char(const char *str, unsigned int len, int pos)
+{
+ if (*(str+pos))
+ printf("ERROR: Unexpected character '%c'\n", *(str + pos));
+ else
+ printf("ERROR: Unexpected end of string\n");
+ while (len-- && *str) printf("%c", *str++); printf("\n");
+ while (pos--) printf(" "); printf("^\n");
+ /* the front end has to to check constant strings */
+ exit(-1);
+}
+#endif
+
+/* pack machine-like */
+static char* _pack(const char *int_float, char *packed)
+{
+ char *shift_val;
+ char *temp;
+ char *val_buffer;
+
+ temp = alloca(VALUE_SIZE);
+ shift_val = alloca(VALUE_SIZE);
+
+ switch (_desc(int_float).class) {
+ case NAN:
+ val_buffer = alloca(CALC_BUFFER_SIZE);
+ fc_get_qnan(_desc(int_float).exponent_size, _desc(int_float).mantissa_size, val_buffer);
+ int_float = val_buffer;
+ break;
+
+ case INF:
+ val_buffer = alloca(CALC_BUFFER_SIZE);
+ fc_get_plusinf(_desc(int_float).exponent_size, _desc(int_float).mantissa_size, val_buffer);
+ _sign(val_buffer) = _sign(int_float);
+ int_float = val_buffer;
+ break;
+
+ default:
+ break;
+ }
+ /* pack sign */
+ sc_val_from_ulong(_sign(int_float), temp);
+
+ sc_val_from_ulong(_desc(int_float).exponent_size + _desc(int_float).mantissa_size, NULL);
+ _shift_left(temp, sc_get_buffer(), packed);
+
+ /* extract exponent */
+ sc_val_from_ulong(_desc(int_float).mantissa_size, shift_val);
+
+ _shift_left(_exp(int_float), shift_val, temp);
+
+ sc_or(temp, packed, packed);
+
+ /* extract mantissa */
+ /* remove 2 rounding bits */
+ sc_val_from_ulong(2, shift_val);
+ _shift_right(_mant(int_float), shift_val, temp);
+
+ /* remove leading 1 (or 0 if denormalized) */
+ sc_max_from_bits(_desc(int_float).mantissa_size, 0, shift_val); /* all mantissa bits are 1's */
+ sc_and(temp, shift_val, temp);
+
+ /* save result */
+ sc_or(temp, packed, packed);
+
+ return packed;
+}
+
+char* _normalize(const char *in_val, char *out_val, int sticky)
+{
+ int hsb;
+ char lsb, guard, round, round_dir = 0;
+ char *temp;
+
+ temp = alloca(VALUE_SIZE);
+
+ /* +2: save two rounding bits at the end */
+ hsb = 2 + _desc(in_val).mantissa_size - sc_get_highest_set_bit(_mant(in_val)) - 1;
+
+ if (in_val != out_val)
+ {
+ _sign(out_val) = _sign(in_val);
+ memcpy(&_desc(out_val), &_desc(in_val), sizeof(descriptor_t));
+ }
+
+ _desc(out_val).class = NORMAL;
+
+ /* mantissa all zeroes, so zero exponent (because of explicit one)*/
+ if (hsb == 2 + _desc(in_val).mantissa_size)
+ {
+ sc_val_from_ulong(0, _exp(out_val));
+ hsb = -1;
+ }
+
+ /* shift the first 1 into the left of the radix point (i.e. hsb == -1) */
+ if (hsb < -1)
+ {
+ /* shift right */
+ sc_val_from_ulong(-hsb-1, temp);
+
+ _shift_right(_mant(in_val), temp, _mant(out_val));
+
+ /* remember if some bits were shifted away */
+ if (!sticky) sticky = sc_had_carry();
+
+ sc_add(_exp(in_val), temp, _exp(out_val));
+ }
+ else if (hsb > -1)
+ {
+ /* shift left */
+ sc_val_from_ulong(hsb+1, temp);
+
+ _shift_left(_mant(in_val), temp, _mant(out_val));
+
+ sc_sub(_exp(in_val), temp, _exp(out_val));
+ }
+
+ /* check for exponent underflow */
+ if (sc_is_negative(_exp(out_val)) || sc_is_zero(_exp(out_val))) {
+ DEBUGPRINTF(("Exponent underflow!\n"));
+ /* exponent underflow */
+ /* shift the mantissa right to have a zero exponent */
+ sc_val_from_ulong(1, temp);
+ sc_sub(temp, _exp(out_val), NULL);
+
+ _shift_right(_mant(out_val), sc_get_buffer(), _mant(out_val));
+ if (!sticky) sticky = sc_had_carry();
+ /* denormalized means exponent of zero */
+ sc_val_from_ulong(0, _exp(out_val));
+
+ _desc(out_val).class = SUBNORMAL;
+ }
+
+ /* perform rounding by adding a value that clears the guard bit and the round bit
+ * and either causes a carry to round up or not */
+ /* get the last 3 bits of the value */
+ lsb = sc_sub_bits(_mant(out_val), _desc(out_val).mantissa_size + 2, 0) & 0x7;
+ guard = (lsb&0x2)>>1;
+ round = lsb&0x1;
+
+ switch (ROUNDING_MODE)
+ {
+ case FC_TONEAREST:
+ /* round to nearest representable value, if in doubt choose the version
+ * with lsb == 0 */
+ round_dir = guard && (sticky || round || lsb>>2);
+ break;
+ case FC_TOPOSITIVE:
+ /* if positive: round to one if the exact value is bigger, else to zero */
+ round_dir = (!_sign(out_val) && (guard || round || sticky));
+ break;
+ case FC_TONEGATIVE:
+ /* if negative: round to one if the exact value is bigger, else to zero */
+ round_dir = (_sign(out_val) && (guard || round || sticky));
+ break;
+ case FC_TOZERO:
+ /* always round to 0 (chopping mode) */
+ round_dir = 0;
+ break;
+ }
+ DEBUGPRINTF(("Rounding (s%d, l%d, g%d, r%d, s%d) %s\n", _sign(out_val), lsb>>2, guard, round, sticky, (round_dir)?"up":"down"));
+
+ if (round_dir == 1)
+ {
+ guard = (round^guard)<<1;
+ lsb = !(round || guard)<<2 | guard | round;
+ }
+ else
+ {
+ lsb = -((guard<<1) | round);
+ }
+
+ /* add the rounded value */
+ if (lsb != 0) {
+ sc_val_from_long(lsb, temp);
+ sc_add(_mant(out_val), temp, _mant(out_val));
+ }
+
+ /* could have rounded down to zero */
+ if (sc_is_zero(_mant(out_val)) && (_desc(out_val).class == SUBNORMAL))
+ _desc(out_val).class = ZERO;
+
+ /* check for rounding overflow */
+ hsb = 2 + _desc(out_val).mantissa_size - sc_get_highest_set_bit(_mant(out_val)) - 1;
+ if ((_desc(out_val).class != SUBNORMAL) && (hsb < -1))
+ {
+ sc_val_from_ulong(1, temp);
+ _shift_right(_mant(out_val), temp, _mant(out_val));
+
+ sc_add(_exp(out_val), temp, _exp(out_val));
+ }
+ else if ((_desc(out_val).class == SUBNORMAL) && (hsb == -1))
+ {
+ /* overflow caused the matissa to be normal again,
+ * so adapt the exponent accordingly */
+ sc_val_from_ulong(1, temp);
+ sc_add(_exp(out_val), temp, _exp(out_val));
+
+ _desc(out_val).class = NORMAL;
+ }
+ /* no further rounding is needed, because rounding overflow means
+ * the carry of the original rounding was propagated all the way
+ * up to the bit left of the radix point. This implies the bits
+ * to the right are all zeros (rounding is +1) */
+
+ /* check for exponent overflow */
+ sc_val_from_ulong((1 << _desc(out_val).exponent_size) - 1, temp);
+ if (sc_comp(_exp(out_val), temp) != -1) {
+ DEBUGPRINTF(("Exponent overflow!\n"));
+ /* exponent overflow, reaction depends on rounding method:
+ *
+ * mode | sign of value | result
+ *--------------------------------------------------------------
+ * TO_NEAREST | + | +inf
+ * | - | -inf
+ *--------------------------------------------------------------
+ * TO_POSITIVE | + | +inf
+ * | - | smallest representable value
+ *--------------------------------------------------------------
+ * TO_NEAGTIVE | + | largest representable value
+ * | - | -inf
+ *--------------------------------------------------------------
+ * TO_ZERO | + | largest representable value
+ * | - | smallest representable value
+ *--------------------------------------------------------------*/
+ if (_sign(out_val) == 0)
+ {
+ /* value is positive */
+ switch (ROUNDING_MODE) {
+ case FC_TONEAREST:
+ case FC_TOPOSITIVE:
+ _desc(out_val).class = INF;
+ break;
+
+ case FC_TONEGATIVE:
+ case FC_TOZERO:
+ fc_get_max(_desc(out_val).exponent_size, _desc(out_val).mantissa_size, out_val);
+ }
+ } else {
+ /* value is negative */
+ switch (ROUNDING_MODE) {
+ case FC_TONEAREST:
+ case FC_TONEGATIVE:
+ _desc(out_val).class = INF;
+ break;
+
+ case FC_TOPOSITIVE:
+ case FC_TOZERO:
+ fc_get_min(_desc(out_val).exponent_size, _desc(out_val).mantissa_size, out_val);
+ }
+ }
+ }
+
+ return out_val;
+}
+
+/*
+ * calculate a + b, where a is the value with the bigger exponent
+ */
+static char* _add(const char* a, const char* b, char* result)
+{
+ char *temp;
+ char *exp_diff;
+
+ char sign;
+ char sticky;
+
+ if (_desc(a).class == NAN) {
+ if (a != result) memcpy(result, a, CALC_BUFFER_SIZE);
+ return result;
+ }
+ if (_desc(b).class == NAN) {
+ if (b != result) memcpy(result, b, CALC_BUFFER_SIZE);
+ return result;
+ }
+
+ /* make sure result has a descriptor */
+ if (result != a && result != b)
+ memcpy(&_desc(result), &_desc(a), sizeof(descriptor_t));
+
+ /* determine if this is an addition or subtraction */
+ sign = _sign(a) ^ _sign(b);
+
+ /* produce nan on inf - inf */
+ if (sign && (_desc(a).class == INF) && (_desc(b).class == INF))
+ return fc_get_qnan(_desc(a).exponent_size, _desc(b).mantissa_size, result);
+
+ temp = alloca(VALUE_SIZE);
+ exp_diff = alloca(VALUE_SIZE);
+
+ /* get exponent difference */
+ sc_sub(_exp(a), _exp(b), exp_diff);
+
+ /* initially set sign to be the sign of a, special treatment of subtraction
+ * when exponents are equal is required though.
+ * Also special care about the sign is needed when the mantissas are equal
+ * (+/- 0 ?) */
+ if (sign && sc_val_to_long(exp_diff) == 0) {
+ switch (sc_comp(_mant(a), _mant(b))) {
+ case 1: /* a > b */
+ if (_sign(a)) _sign(result) = 1; /* abs(a) is bigger and a is negative */
+ else _sign(result) = 0;
+ break;
+ case 0: /* a == b */
+ if (ROUNDING_MODE == FC_TONEGATIVE)
+ _sign(result) = 1;
+ else
+ _sign(result) = 0;
+ break;
+ case -1: /* a < b */
+ if (_sign(b)) _sign(result) = 1; /* abs(b) is bigger and b is negative */
+ else _sign(result) = 0;
+ break;
+ default:
+ /* can't be reached */
+ break;
+ }
+ } else {
+ _sign(result) = _sign(a);
+ }
+
+ /* sign has been taken care of, check for special cases */
+ if (_desc(a).class == ZERO) {
+ if (b != result) memcpy(result+SIGN_POS+1, b+SIGN_POS+1, CALC_BUFFER_SIZE-SIGN_POS-1);
+ return result;
+ }
+ if (_desc(b).class == ZERO) {
+ if (a != result) memcpy(result+SIGN_POS+1, a+SIGN_POS+1, CALC_BUFFER_SIZE-SIGN_POS-1);
+ return result;
+ }
+
+ if (_desc(a).class == INF) {
+ if (a != result) memcpy(result+SIGN_POS+1, a+SIGN_POS+1, CALC_BUFFER_SIZE-SIGN_POS-1);
+ return result;
+ }
+ if (_desc(b).class == INF) {
+ if (b != result) memcpy(result+SIGN_POS+1, b+SIGN_POS+1, CALC_BUFFER_SIZE-SIGN_POS-1);
+ return result;
+ }
+
+ /* shift the smaller value to the right to align the radix point */
+ /* subnormals have their radix point shifted to the right,
+ * take care of this first */
+ if ((_desc(b).class == SUBNORMAL) && (_desc(a).class != SUBNORMAL))
+ {
+ sc_val_from_ulong(1, temp);
+ sc_sub(exp_diff, temp, exp_diff);
+ }
+
+ _shift_right(_mant(b), exp_diff, temp);
+ sticky = sc_had_carry();
+
+ if (sticky && sign)
+ {
+ /* if subtracting a little more than the represented value or adding a little
+ * more than the represented value to a negative value this, in addition to the
+ * still set sticky bit, takes account of the 'little more' */
+ char *temp1 = alloca(CALC_BUFFER_SIZE);
+ sc_val_from_ulong(1, temp1);
+ sc_add(temp, temp1, temp);
+ }
+
+ if (sign) {
+ if (sc_comp(_mant(a), temp) == -1)
+ sc_sub(temp, _mant(a), _mant(result));
+ else
+ sc_sub(_mant(a), temp, _mant(result));
+ } else {
+ sc_add(_mant(a), temp, _mant(result));
+ }
+
+ /* _normalize expects a 'normal' radix point, adding two subnormals
+ * results in a subnormal radix point -> shifting before normalizing */
+ if ((_desc(a).class == SUBNORMAL) && (_desc(b).class == SUBNORMAL))
+ {
+ sc_val_from_ulong(1, NULL);
+ _shift_left(_mant(result), sc_get_buffer(), _mant(result));
+ }
+
+ /* resulting exponent is the bigger one */
+ memmove(_exp(result), _exp(a), VALUE_SIZE);
+
+ return _normalize(result, result, sticky);
+}
+
+static char* _mul(const char* a, const char* b, char* result)
+{
+ char *temp;
+
+ if (_desc(a).class == NAN) {
+ if (a != result) memcpy(result, a, CALC_BUFFER_SIZE);
+ return result;
+ }
+ if (_desc(b).class == NAN) {
+ if (b != result) memcpy(result, b, CALC_BUFFER_SIZE);
+ return result;
+ }
+
+ temp = alloca(VALUE_SIZE);
+
+ if (result != a && result != b)
+ memcpy(&_desc(result), &_desc(a), sizeof(descriptor_t));
+
+ _sign(result) = _sign(a) ^ _sign(b);
+
+ /* produce nan on 0 * inf */
+ if (_desc(a).class == ZERO) {
+ if (_desc(b).class == INF)
+ fc_get_qnan(_desc(a).exponent_size, _desc(a).mantissa_size, result);
+ else
+ if (a != result) memcpy(result+SIGN_POS+1, a+SIGN_POS+1, CALC_BUFFER_SIZE-1);
+ return result;
+ }
+ if (_desc(b).class == ZERO) {
+ if (_desc(a).class == INF)
+ fc_get_qnan(_desc(a).exponent_size, _desc(a).mantissa_size, result);
+ else
+ if (b != result) memcpy(result+SIGN_POS+1, b+SIGN_POS+1, CALC_BUFFER_SIZE-1);
+ return result;
+ }
+
+ if (_desc(a).class == INF) {
+ if (a != result) memcpy(result+SIGN_POS+1, a+SIGN_POS+1, CALC_BUFFER_SIZE-1);
+ return result;
+ }
+ if (_desc(b).class == INF) {
+ if (b != result) memcpy(result+SIGN_POS+1, b+SIGN_POS+1, CALC_BUFFER_SIZE-1);
+ return result;
+ }
+
+ /* exp = exp(a) + exp(b) - excess */
+ sc_add(_exp(a), _exp(b), _exp(result));
+
+ sc_val_from_ulong((1<<_desc(a).exponent_size)/2-1, temp);
+ sc_sub(_exp(result), temp, _exp(result));
+
+ /* mixed normal, subnormal values introduce an error of 1, correct it */
+ if ((_desc(a).class == SUBNORMAL) ^ (_desc(b).class == SUBNORMAL))
+ {
+ sc_val_from_ulong(1, temp);
+ sc_add(_exp(result), temp, _exp(result));
+ }
+
+ sc_mul(_mant(a), _mant(b), _mant(result));
+
+ /* realign result: after a multiplication the digits right of the radix
+ * point are the sum of the factors' digits after the radix point. As all
+ * values are normalized they both have the same amount of these digits,
+ * which has to be restored by proper shifting
+ * +2 because of the two rounding bits */
+ sc_val_from_ulong(2 + _desc(result).mantissa_size, temp);
+
+ _shift_right(_mant(result), temp, _mant(result));
+
+ return _normalize(result, result, sc_had_carry());
+}
+
+static char* _div(const char* a, const char* b, char* result)
+{
+ char *temp, *dividend;
+
+ if (_desc(a).class == NAN) {
+ if (a != result) memcpy(result, a, CALC_BUFFER_SIZE);
+ return result;
+ }
+ if (_desc(b).class == NAN) {
+ if (b != result) memcpy(result, b, CALC_BUFFER_SIZE);
+ return result;
+ }
+
+ temp = alloca(VALUE_SIZE);
+ dividend = alloca(VALUE_SIZE);
+
+ if (result != a && result != b)
+ memcpy(&_desc(result), &_desc(a), sizeof(descriptor_t));
+
+ _sign(result) = _sign(a) ^ _sign(b);
+
+ /* produce nan on 0/0 and inf/inf */
+ if (_desc(a).class == ZERO) {
+ if (_desc(b).class == ZERO)
+ /* 0/0 -> nan */
+ fc_get_qnan(_desc(a).exponent_size, _desc(a).mantissa_size, result);
+ else
+ /* 0/x -> a */
+ if (a != result) memcpy(result+SIGN_POS+1, a+SIGN_POS+1, CALC_BUFFER_SIZE-1);
+ return result;
+ }
+
+ if (_desc(b).class == INF) {
+ if (_desc(a).class == INF)
+ /* inf/inf -> nan */
+ fc_get_qnan(_desc(a).exponent_size, _desc(a).mantissa_size, result);
+ else {
+ /* x/inf -> 0 */
+ sc_val_from_ulong(0, NULL);
+ _save_result(_exp(result));
+ _save_result(_mant(result));
+ _desc(result).class = ZERO;
+ }
+ return result;
+ }
+
+ if (_desc(a).class == INF) {
+ /* inf/x -> inf */
+ if (a != result) memcpy(result+SIGN_POS+1, a+SIGN_POS+1, CALC_BUFFER_SIZE-1);
+ return result;
+ }
+ if (_desc(b).class == ZERO) {
+ /* division by zero */
+ if (_sign(result))
+ fc_get_minusinf(_desc(a).exponent_size, _desc(a).mantissa_size, result);
+ else
+ fc_get_plusinf(_desc(a).exponent_size, _desc(a).mantissa_size, result);
+ return result;
+ }
+
+ /* exp = exp(a) - exp(b) + excess - 1*/
+ sc_sub(_exp(a), _exp(b), _exp(result));
+ sc_val_from_ulong((1 << _desc(a).exponent_size)/2-2, temp);
+ sc_add(_exp(result), temp, _exp(result));
+
+ /* mixed normal, subnormal values introduce an error of 1, correct it */
+ if ((_desc(a).class == SUBNORMAL) ^ (_desc(b).class == SUBNORMAL))
+ {
+ sc_val_from_ulong(1, temp);
+ sc_add(_exp(result), temp, _exp(result));
+ }
+
+ /* mant(res) = mant(a) / 1/2mant(b) */
+ /* to gain more bits of precision in the result the dividend could be
+ * shifted left, as this operation does not loose bits. This would not
+ * fit into the integer precision, but due to the rounding bits (which
+ * are always zero because the values are all normalized) the divisor
+ * can be shifted right instead to achieve the same result */
+ sc_val_from_ulong(2 + _desc(result).mantissa_size, temp);
+
+ _shift_left(_mant(a), temp, dividend);
+
+ {
+ char *divisor = alloca(CALC_BUFFER_SIZE);
+ sc_val_from_ulong(1, divisor);
+ _shift_right(_mant(b), divisor, divisor);
+ sc_div(dividend, divisor, _mant(result));
+ }
+
+ return _normalize(result, result, sc_had_carry());
+}
+
+void _power_of_ten(int exp, descriptor_t *desc, char *result)
+{
+ char *build;
+ char *temp;
+
+ /* positive sign */
+ _sign(result) = 0;
+
+ /* set new descriptor (else result is supposed to already have one) */
+ if (desc != NULL)
+ memcpy(&_desc(result), desc, sizeof(descriptor_t));
+
+ build = alloca(VALUE_SIZE);
+ temp = alloca(VALUE_SIZE);
+
+ sc_val_from_ulong((1 << _desc(result).exponent_size)/2-1, _exp(result));
+
+ if (exp > 0)
+ {
+ /* temp is value of ten now */
+ sc_val_from_ulong(10, NULL);
+ _save_result(temp);
+
+ for (exp--; exp > 0; exp--) {
+ _save_result(build);
+ sc_mul(build, temp, NULL);
+ }
+ _save_result(build);
+
+ /* temp is amount of leftshift needed to put the value left of the radix point */
+ sc_val_from_ulong(_desc(result).mantissa_size + 2, temp);
+
+ _shift_left(build, temp, _mant(result));
+
+ _normalize(result, result, 0);
+ }
+}
+
+static char* _trunc(const char *a, char *result)
+{
+ /* when exponent == 0 all bits left of the radix point
+ * are the integral part of the value. For 15bit exp_size
+ * this would require a leftshift of max. 16383 bits which
+ * is too much.
+ * But it is enough to ensure that no bit right of the radix
+ * point remains set. This restricts the interesting
+ * exponents to the interval [0, mant_size-1].
+ * Outside this interval the truncated value is either 0 or
+ * it is are already truncated */
+
+ int exp_bias, exp_val;
+ char *temp;
+
+ temp = alloca(VALUE_SIZE);
+
+ if (a != result)
+ memcpy(&_desc(result), &_desc(a), sizeof(descriptor_t));
+
+ exp_bias = (1<<_desc(a).exponent_size)/2-1;
+ exp_val = sc_val_to_long(_exp(a)) - exp_bias;
+
+ if (exp_val < 0) {
+ sc_val_from_ulong(0, NULL);
+ _save_result(_exp(result));
+ _save_result(_mant(result));
+ _desc(result).class = ZERO;
+
+ return result;
+ }
+
+ if (exp_val > _desc(a).mantissa_size) {
+ if (a != result)
+ memcpy(result, a, CALC_BUFFER_SIZE);
+
+ return result;
+ }
+
+ /* set up a proper mask to delete all bits right of the
+ * radix point if the mantissa had been shifted until exp == 0 */
+ sc_max_from_bits(1 + exp_val, 0, temp);
+ sc_val_from_long(_desc(a).mantissa_size - exp_val + 2, NULL);
+ _shift_left(temp, sc_get_buffer(), temp);
+
+ /* and the mask and return the result */
+ sc_and(_mant(a), temp, _mant(result));
+
+ if (a != result) memcpy(_exp(result), _exp(a), VALUE_SIZE);
+
+ return result;
+}
+
+/*
+ * This does value sanity checking(or should do it), sets up any prerequisites,
+ * calls the proper internal functions, clears up and returns
+ * the result */
+char* _calc(const char *a, const char *b, int opcode, char *result)
+{
+ char *temp;
+#ifdef FLTCALC_TRACE_CALC
+ char *buffer;
+
+ buffer = alloca(100);
+#endif
+
+ if (result == NULL) result = calc_buffer;
+
+ TRACEPRINTF(("%s ", fc_print(a, buffer, 100, FC_PACKED)));
+ switch (opcode)
+ {
+ case FC_add:
+ /* make the value with the bigger exponent the first one */
+ TRACEPRINTF(("+ %s ", fc_print(b, buffer, 100, FC_PACKED)));
+ if (sc_comp(_exp(a), _exp(b)) == -1)
+ _add(b, a, result);
+ else
+ _add(a, b, result);
+ break;
+ case FC_sub:
+ TRACEPRINTF(("- %s ", fc_print(b, buffer, 100, FC_PACKED)));
+ temp = alloca(CALC_BUFFER_SIZE);
+ memcpy(temp, b, CALC_BUFFER_SIZE);
+ _sign(temp) = !_sign(b);
+ if (sc_comp(_exp(a), _exp(temp)) == -1)
+ _add(temp, a, result);
+ else
+ _add(a, temp, result);
+ break;
+ case FC_mul:
+ TRACEPRINTF(("* %s ", fc_print(b, buffer, 100, FC_PACKED)));
+ _mul(a, b, result);
+ break;
+ case FC_div:
+ TRACEPRINTF(("/ %s ", fc_print(b, buffer, 100, FC_PACKED)));
+ _div(a, b, result);
+ break;
+ case FC_neg:
+ TRACEPRINTF(("negated "));
+ if (a != result) memcpy(result, a, CALC_BUFFER_SIZE);
+ _sign(result) = !_sign(a);
+ break;
+ case FC_int:
+ _trunc(a, result);
+ break;
+ case FC_rnd:
+ break;
+ }
+
+ TRACEPRINTF(("= %s\n", fc_print(result, buffer, 100, FC_PACKED)));
+ return result;
+}