our Int multi Num::round_toward_nearest (Num $x, int $symmetrical? = 1) {
# XXX -- Not implemented
# How should I implement this? As in
# http://www.pldesignline.com/howto/showArticle.jhtml?articleID=175801189
# says, This may be considered as the superset of round_half_up and
# round_half_down

}

our Int multi Num::round_half_up (Num $x, int $symmetrical? = 1) {
	return int($x + 0.5)
		if $x > 0;

	$symmetrical ??
		-(int(abs($x) + 0.5)) !!
		-(int(abs($x) + 0.4))
}

our Int multi Num::round_half_down (Num $x, int $symmetrical? = 1) {
	return int($x + 0.4)
		if $x > 0;

	$symmetrical ??
		-(int(abs($x) + 0.4)) !!
		-(int(abs($x) + 0.5))
}

# No symmetry flag
our Int multi Num::round_half_even (Num $x) {
	return int($x.is_even ?? $x + 0.4 !! $x + 0.5)
		if $x > 0;

	return 0 if $x == 0;

	return -(&?ROUTINE(abs($x)));
}

our Int multi Num::round_half_odd (Num $x) {
	return int($x.is_odd ?? $x + 0.4 !! $x + 0.5)
		if $x > 0;

	return 0 if $x == 0;

	return -(&?ROUTINE(abs($x)));
}

our Int multi Num::round_alternate (Num $x) {
# XXX I don't understand what round-alternate means.
# But in my understanding, The implemention below might be right.
	state $t;
	if $t {
		$t = 0;
		return $x.round_half_even;
	} else {
		$t = 1;
		return $x.round_half_odd;
	}
}

our Int multi Num::round_random (Num $x) {
	my @l = (
		{ $^a.round_half_up: symmetrical => $^b },
		{ $^a.round_half_down: symmetrical => $^b },
		{ $^a.round_half_even },
		{ $^a.round_half_odd },

#		{ $^a.round_half_alternate },
#		{ $^a.round_half_random },

		{ $^a.round_half_ceiling },
		{ $^a.round_toward_zero },
		{ $^a.round_away_from_zero },

#		{ $^a.round_up: symmetrical => $^b },
#		{ $^a.round_down: symmetrical => $^b },
		);
	my $sym_flag = (int(rand() * 10)) % 2;
	my $selector = (int(rand() * 100)) % @l.elems;

	@l[$selector]($x, $sym_flag);
}

our Int multi Num::round_ceiling (Num $x) {
	my Int $t = int($x);
	$x > 0 && $x != $t ??
		$t + 1 !! $t
}

our Int multi Num::round_floor (Num $x) {
	my Int $t = int($x);
	$x > 0 || $x == $t ??
		$t !! $t - 1
}

our Int multi Num::round_toward_zero (Num $x) {
	return(int $x);
}

our Int multi Num::round_away_from_zero (Num $x) {
	return 0 if $x == 0;

	my Int $t = int($x);
	return $x if $x == $t;
	$x > 0 ?? $t + 1 !! $t - 1;
}

our Int multi Num::round_up (Num $x, int $symmetrical? = 1) {
	$symmetrical ?? $x.round_away_from_zero
		!! $x.round_ceiling
}

our Int multi Num::round_down (Num $x, int $symmetrical? = 1) {
	$symmetrical ?? $x.round_toward_zero
		!! $x.round_floor
}

our Int multi Num::truncation (Num $x) {
	...
}

# Other math functions.
our bool multi Num::is_odd (Num $x) {
        return ?(int($x) % 2);
}

our bool multi Num::is_even (Num $x) {
        return !(int($x) % 2);
}

our Num multi Num::abs (Num $x) {
	$x < 0 ?? -$x !! $x;
}

our int multi Num::sign (Num $x) {
	return 0 if $x == 0;
	$x > 0 ?? 1 !! -1;
}

