static Value* eval_abs(const Context* ctx, const ArgList* arglist, bool internal) { if(arglist->count != 1) { return ValErr(builtinArgs("abs", 1, arglist->count)); } Value* val = Value_coerce(arglist->args[0], ctx); if(val->type == VAL_ERR) { return val; } Value* ret; switch(val->type) { case VAL_INT: ret = ValInt(ABS(val->ival)); break; case VAL_REAL: ret = ValReal(ABS(val->rval)); break; case VAL_FRAC: ret = ValFrac(Fraction_new(ABS(val->frac->n), val->frac->d)); break; case VAL_VEC: ret = Vector_magnitude(val->vec, ctx); break; default: badValType(val->type); } Value_free(val); return ret; }
static Value* vecMagOp(const Vector* vec, const Value* scalar, const Context* ctx, BINTYPE bin) { /* Calculate old magnitude */ Value* mag = Vector_magnitude(vec, ctx); /* Calculate new magnitude */ BinOp* magOp = BinOp_new(bin, Value_copy(mag), Value_copy(scalar)); Value* newMag = BinOp_eval(magOp, ctx); BinOp_free(magOp); /* Calculate scalar factor */ BinOp* newDivOld = BinOp_new(BIN_DIV, newMag, mag); Value* scalFact = BinOp_eval(newDivOld, ctx); BinOp_free(newDivOld); /* Both newMag and mag are freed with newDivOld */ /* Calculate new vector */ return vecScalarOp(vec, scalFact, ctx, BIN_MUL); }