Permalink
Switch branches/tags
Find file
Fetching contributors…
Cannot retrieve contributors at this time
659 lines (435 sloc) 13.9 KB
/*
Copyright (C) 2003-2014, Parrot Foundation.
=head1 NAME
src/pmc/float.pmc - Float PMC
=head1 DESCRIPTION
C<Float> PMC extends the abstract C<Scalar> PMC to provide floating-point
number operations.
=head2 Functions
=over 4
=cut
*/
/* HEADERIZER HFILE: none */
/* HEADERIZER BEGIN: static */
/* HEADERIZER END: static */
pmclass Float extends scalar provides float provides scalar auto_attrs {
ATTR FLOATVAL fv;
/*
=item C<void init()>
Initializes the number to zero.
=cut
*/
VTABLE void init() {
SET_ATTR_fv(INTERP, SELF, 0.0);
}
/*
=item C<PMC *clone()>
Make an exact copy of this PMC.
=cut
*/
VTABLE PMC *clone() :no_wb {
FLOATVAL fv;
PMC * const dest = Parrot_pmc_new(INTERP, SELF->vtable->base_type);
GET_ATTR_fv(INTERP, SELF, fv);
SET_ATTR_fv(INTERP, dest, fv);
return dest;
}
/*
=item C<void *get_pointer()>
Return the memory address of an Float PMC. This is needed for certain NCI
applications and may be disabled in certain security contexts.
=cut
*/
VTABLE void *get_pointer() :no_wb {
UNUSED(INTERP)
return &(PARROT_FLOAT(SELF)->fv);
}
/*
=item C<FLOATVAL get_number()>
Returns the value of the number.
=cut
*/
VTABLE FLOATVAL get_number() :no_wb {
FLOATVAL fv;
GET_ATTR_fv(INTERP, SELF, fv);
return fv;
}
/*
=item C<INTVAL get_integer()>
Returns an integer representation of the number by truncating
(rounding toward zero).
=cut
*/
VTABLE INTVAL get_integer() :no_wb {
/* two steps avoid casting warnings */
const FLOATVAL n = SELF.get_number();
return (INTVAL) n;
}
/*
=item C<INTVAL get_bool()>
Evaluates the number as a boolean, i.e. it's true if it's not zero.
=cut
*/
VTABLE INTVAL get_bool() :no_wb {
const FLOATVAL f = SELF.get_number();
return !FLOAT_IS_ZERO(f);
}
/*
=item C<STRING *get_string()>
Returns a Parrot string representation of the number.
=item C<STRING *get_repr()>
=cut
*/
VTABLE STRING *get_string() :no_wb {
return Parrot_str_from_num(INTERP, SELF.get_number());
}
VTABLE STRING *get_repr() :no_wb {
const FLOATVAL val = SELF.get_number();
#if defined(PARROT_HAS_FABSL) && NUMVAL_SIZE > 8
const FLOATVAL d = fabsl((long double)val);
#else
const FLOATVAL d = fabs((double)val);
#endif
const char * const sign = val < 0 ? "-" : "";
return Parrot_sprintf_c(INTERP, "%s" FLOATVAL_FMT, sign, d);
}
/*
=item C<void set_integer_native(INTVAL value)>
=item C<void set_bool(INTVAL value)>
=cut
*/
VTABLE void set_integer_native(INTVAL value) :manual_wb {
Parrot_pmc_reuse(INTERP, SELF,
Parrot_hll_get_ctx_HLL_type(INTERP, enum_class_Integer), 0);
SELF.set_integer_native(value);
}
VTABLE void set_bool(INTVAL value) :manual_wb {
Parrot_pmc_reuse(INTERP, SELF,
Parrot_hll_get_ctx_HLL_type(INTERP, enum_class_Boolean), 0);
SELF.set_bool(value);
}
/*
=item C<void set_number_native(FLOATVAL value)>
Sets the value of the number to C<value>.
=cut
*/
VTABLE void set_number_native(FLOATVAL value) {
SET_ATTR_fv(INTERP, SELF, value);
}
/*
=item C<void set_string_native(STRING *value)>
Sets the value of the number to the value of C<*value>.
Note that this method morphs the number into a C<String>.
=cut
*/
VTABLE void set_string_native(STRING *value) :manual_wb {
Parrot_pmc_reuse(INTERP, SELF,
Parrot_hll_get_ctx_HLL_type(INTERP, enum_class_String), 0);
SELF.set_string_native(value);
}
/*
=item C<void set_pmc(PMC *value)>
Sets the value of the number to the value in C<*value>.
=cut
*/
VTABLE void set_pmc(PMC *value) {
SET_ATTR_fv(INTERP, SELF, VTABLE_get_number(INTERP, value));
}
/*
=item C<PMC *neg(PMC *dest)>
=item C<void i_neg()>
Set C<dest> to the negated value of C<SELF>.
=cut
*/
VTABLE PMC *neg(PMC *dest) :no_wb {
const FLOATVAL a = -SELF.get_number();
dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
VTABLE_set_number_native(INTERP, dest, a);
return dest;
}
VTABLE void i_neg() :manual_wb {
const FLOATVAL a = -SELF.get_number();
VTABLE_set_number_native(INTERP, SELF, a);
}
/*
=item C<INTVAL is_equal(PMC *value)>
The C<==> operation.
=cut
*/
MULTI INTVAL is_equal(Float value) :no_wb {
return (INTVAL)(SELF.get_number() == VTABLE_get_number(INTERP, value));
}
MULTI INTVAL is_equal(DEFAULT *value) :no_wb {
return (INTVAL)(SELF.get_number() == VTABLE_get_number(INTERP, value));
}
MULTI INTVAL is_equal_num(Float value) :no_wb {
return (INTVAL)(SELF.get_number() == VTABLE_get_number(INTERP, value));
}
MULTI INTVAL is_equal_num(DEFAULT value) :no_wb {
return (INTVAL)(SELF.get_number() == VTABLE_get_number(INTERP, value));
}
/*
=item C<INTVAL cmp(PMC *value)>
The C<cmp> operation.
=cut
*/
MULTI INTVAL cmp(Float value) :no_wb {
const FLOATVAL diff = SELF.get_number() - VTABLE_get_number(INTERP, value);
return diff > 0 ? 1 : diff < 0 ? -1 : 0;
}
MULTI INTVAL cmp(DEFAULT value) :no_wb {
const FLOATVAL diff =
SELF.get_number() - VTABLE_get_number(INTERP, value);
return diff > 0 ? 1 : diff < 0 ? -1 : 0;
}
/*
=item C<INTVAL cmp_num(PMC *value)>
Returns the result of comparing the number with C<*value>.
=cut
*/
MULTI INTVAL cmp_num(Float value) :no_wb {
const FLOATVAL diff = SELF.get_number() - VTABLE_get_number(INTERP, value);
return diff > 0 ? 1 : diff < 0 ? -1 : 0;
}
MULTI INTVAL cmp_num(DEFAULT value) :no_wb {
/* fix an apparent gcc 4.4.x and 4.5.x bug that manifests itself when
* using g++ and an optimized build. See TT #1978.
*/
volatile FLOATVAL n1 = SELF.get_number();
volatile FLOATVAL n2 = VTABLE_get_number(INTERP, value);
const FLOATVAL diff = n1 - n2;
return diff > 0 ? 1 : diff < 0 ? -1 : 0;
}
/*
=item C<void increment()>
Increments the number.
=cut
*/
VTABLE void increment() {
FLOATVAL fv;
GET_ATTR_fv(INTERP, SELF, fv);
++fv;
SET_ATTR_fv(INTERP, SELF, fv);
}
/*
=item C<void decrement()>
Decrements the number.
=cut
*/
VTABLE void decrement() {
FLOATVAL fv;
GET_ATTR_fv(INTERP, SELF, fv);
--fv;
SET_ATTR_fv(INTERP, SELF, fv);
}
/*
=item C<PMC *absolute(PMC *dest)>
=item C<void i_absolute()>
Sets C<dest> to the absolute value of SELF.
=cut
*/
VTABLE PMC *absolute(PMC *dest) :no_wb {
const FLOATVAL a = fabs(SELF.get_number());
dest = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
VTABLE_set_number_native(INTERP, dest, a);
return dest;
}
VTABLE void i_absolute() :manual_wb {
const FLOATVAL a = fabs(SELF.get_number());
VTABLE_set_number_native(INTERP, SELF, a);
}
/*
=item C<void freeze(PMC *info)>
Used to archive the number.
=cut
*/
VTABLE void freeze(PMC *info) :no_wb {
SUPER(info);
VTABLE_push_float(INTERP, info, SELF.get_number());
}
/*
=item C<void thaw(PMC *info)>
Used to unarchive the number.
=cut
*/
VTABLE void thaw(PMC *info) {
SUPER(info);
SET_ATTR_fv(INTERP, SELF, VTABLE_shift_float(INTERP, info));
}
/*
=back
=head2 Methods
=over 4
=item C<METHOD PMC *acos()>
Calculate and return the inverse cosine (a.k.a C<arccos>) of the
input argument.
=item C<METHOD PMC *acot()>
Calculate and return the inverse cotangent (a.k.a. C<arccot>) of the
input argument.
=item C<METHOD PMC *asec()>
Calculate and return the inverse secant (a.k.a. C<arcsec>) of the input argument.
=item C<METHOD PMC *asin()>
Calculate and return the inverse sine (a.k.a. C<arcsin>) of the input
argument.
=item C<METHOD PMC *atan()>
Calculate and return the inverse tangent (a.k.a. C<arctan>) of the
input argument.
=item C<METHOD PMC *atan2()>
Calculate and return the two argument inverse tangent (a.k.a.
C<arctan>) of the input argument.
=item C<METHOD PMC *cos()>
Calculate and return the cosine of the input argument.
=item C<METHOD PMC *cosh()>
Calculate and return the hyperbolic cosine of the input argument.
=item C<METHOD PMC *cot()>
Calculate and return the cotangent of the input argument.
=item C<METHOD PMC *coth()>
Calculate and return the hyperbolic cotangent of the input argument.
=item C<METHOD PMC *csc()>
Calculate and return the cosecant of the input argument.
=item C<METHOD PMC *exp()>
Calculate and return the exponential of the input argument.
=item C<METHOD PMC *ln()>
Calculate and return the natural log (logarithm with base C<e>) of the input argument.
=item C<METHOD PMC *log10()>
Calculate and return the base 10 logarithm of the input argument.
=item C<METHOD PMC *log2()>
Calculate and return the base 2 logarithm of the input argument.
=item C<METHOD PMC *sec()>
Calculate and return the secant of the input argument.
=item C<METHOD PMC *sech()>
Calculate and return the hyperbolic secant of the input argument.
=item C<METHOD PMC *sin()>
Calculate and return the sine of the input argument.
=item C<METHOD PMC *sinh()>
Calculate and return the hyperbolic sine of the input argument.
=item C<METHOD PMC *tan()>
Calculate and return the tangent of the input argument.
=item C<METHOD PMC *tanh()>
Calculate and return the hyperbolic tangent of the input argument.
=item C<METHOD PMC *sqrt()>
Calculate and return the square root of the input argument.
=cut
*/
METHOD acos() :no_wb {
PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
SET_ATTR_fv(INTERP, d, acos(SELF.get_number()));
RETURN(PMC *d);
}
METHOD acot() :no_wb {
PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
SET_ATTR_fv(INTERP, d, atan(1.0 / SELF.get_number()));
RETURN(PMC *d);
}
METHOD asec() :no_wb {
PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
SET_ATTR_fv(INTERP, d, acos(1.0 / SELF.get_number()));
RETURN(PMC *d);
}
METHOD asin() :no_wb {
PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
SET_ATTR_fv(INTERP, d, asin(SELF.get_number()));
RETURN(PMC *d);
}
METHOD atan() :no_wb {
PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
SET_ATTR_fv(INTERP, d, atan(SELF.get_number()));
RETURN(PMC *d);
}
METHOD atan2(PMC *val) :no_wb {
PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
SET_ATTR_fv(INTERP, d, atan2(SELF.get_number(), VTABLE_get_number(INTERP, val)));
RETURN(PMC *d);
}
METHOD cos() :no_wb {
PMC * const d = Parrot_pmc_new(INTERP,
Parrot_hll_get_ctx_HLL_type(INTERP, enum_class_Float));
SET_ATTR_fv(INTERP, d, cos(SELF.get_number()));
RETURN(PMC *d);
}
METHOD cosh() :no_wb {
PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
SET_ATTR_fv(INTERP, d, cosh(SELF.get_number()));
RETURN(PMC *d);
}
METHOD cot() :no_wb {
PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
SET_ATTR_fv(INTERP, d, 1.0 / tan(SELF.get_number()));
RETURN(PMC *d);
}
METHOD coth() :no_wb {
PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
SET_ATTR_fv(INTERP, d, 1.0 / tanh(SELF.get_number()));
RETURN(PMC *d);
}
METHOD csc() :no_wb {
PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
SET_ATTR_fv(INTERP, d, 1.0 / sin(SELF.get_number()));
RETURN(PMC *d);
}
METHOD exp() :no_wb {
PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
SET_ATTR_fv(INTERP, d, exp(SELF.get_number()));
RETURN(PMC *d);
}
METHOD ln() :no_wb {
PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
SET_ATTR_fv(INTERP, d, log(SELF.get_number()));
RETURN(PMC *d);
}
METHOD log10() :no_wb {
PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
SET_ATTR_fv(INTERP, d, log10(SELF.get_number()));
RETURN(PMC *d);
}
METHOD log2() :no_wb {
PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
SET_ATTR_fv(INTERP, d, log(SELF.get_number()) / log(2.0));
RETURN(PMC *d);
}
METHOD sec() :no_wb {
PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
SET_ATTR_fv(INTERP, d, 1.0 / cos(SELF.get_number()));
RETURN(PMC *d);
}
METHOD sech() :no_wb {
PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
SET_ATTR_fv(INTERP, d, 1.0 / cosh(SELF.get_number()));
RETURN(PMC *d);
}
METHOD sin() :no_wb {
PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
SET_ATTR_fv(INTERP, d, sin(SELF.get_number()));
RETURN(PMC *d);
}
METHOD sinh() :no_wb {
PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
SET_ATTR_fv(INTERP, d, sinh(SELF.get_number()));
RETURN(PMC *d);
}
METHOD tan() :no_wb {
PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
SET_ATTR_fv(INTERP, d, tan(SELF.get_number()));
RETURN(PMC *d);
}
METHOD tanh() :no_wb {
PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
SET_ATTR_fv(INTERP, d, tanh(SELF.get_number()));
RETURN(PMC *d);
}
METHOD sqrt() :no_wb {
PMC * const d = Parrot_pmc_new(INTERP, VTABLE_type(INTERP, SELF));
SET_ATTR_fv(INTERP, d, sqrt(SELF.get_number()));
RETURN(PMC *d);
}
}
/*
=back
=cut
*/
/*
* Local variables:
* c-file-style: "parrot"
* End:
* vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
*/