implement builtin function math.pow

This commit is contained in:
Connor Skees 2020-07-29 18:13:37 -04:00
parent 2fb19e161e
commit 8c1cde8a61
3 changed files with 109 additions and 1 deletions

View File

@ -174,7 +174,52 @@ fn log(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
fn pow(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> { fn pow(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
args.max_args(2)?; args.max_args(2)?;
todo!()
let base = match args.get_err(0, "base")? {
Value::Dimension(Some(n), Unit::None, ..) => n,
v @ Value::Dimension(Some(..), ..) => {
return Err((
format!(
"$base: Expected {} to have no units.",
v.inspect(args.span())?
),
args.span(),
)
.into())
}
Value::Dimension(None, ..) => return Ok(Value::Dimension(None, Unit::None, true)),
v => {
return Err((
format!("$base: {} is not a number.", v.inspect(args.span())?),
args.span(),
)
.into())
}
};
let exponent = match args.get_err(1, "exponent")? {
Value::Dimension(Some(n), Unit::None, ..) => n,
v @ Value::Dimension(Some(..), ..) => {
return Err((
format!(
"$exponent: Expected {} to have no units.",
v.inspect(args.span())?
),
args.span(),
)
.into())
}
Value::Dimension(None, ..) => return Ok(Value::Dimension(None, Unit::None, true)),
v => {
return Err((
format!("$exponent: {} is not a number.", v.inspect(args.span())?),
args.span(),
)
.into())
}
};
Ok(Value::Dimension(base.pow(exponent), Unit::None, true))
} }
fn sqrt(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> { fn sqrt(mut args: CallArgs, parser: &mut Parser<'_>) -> SassResult<Value> {
@ -375,6 +420,7 @@ pub(crate) fn declare(f: &mut Module) {
f.insert_builtin("asin", asin); f.insert_builtin("asin", asin);
f.insert_builtin("atan", atan); f.insert_builtin("atan", atan);
f.insert_builtin("log", log); f.insert_builtin("log", log);
f.insert_builtin("pow", pow);
#[cfg(feature = "random")] #[cfg(feature = "random")]
f.insert_builtin("random", random); f.insert_builtin("random", random);

View File

@ -128,6 +128,12 @@ impl Number {
self.as_float()?.ln(), self.as_float()?.ln(),
)?))) )?)))
} }
pub fn pow(self, exponent: Self) -> Option<Self> {
Some(Number::Big(Box::new(BigRational::from_float(
self.as_float()?.powf(exponent.as_float()?),
)?)))
}
} }
macro_rules! trig_fn( macro_rules! trig_fn(

View File

@ -390,3 +390,59 @@ test!(
"@use 'sass:math';\na {\n color: math.log(2, .5);\n}\n", "@use 'sass:math';\na {\n color: math.log(2, .5);\n}\n",
"a {\n color: -1;\n}\n" "a {\n color: -1;\n}\n"
); );
test!(
pow_exponent_and_base_one,
"@use 'sass:math';\na {\n color: math.pow(1, 1);\n}\n",
"a {\n color: 1;\n}\n"
);
test!(
pow_exponent_and_base_ten,
"@use 'sass:math';\na {\n color: math.pow(10, 10);\n}\n",
"a {\n color: 10000000000;\n}\n"
);
test!(
pow_base_negative_exponent_positive,
"@use 'sass:math';\na {\n color: math.pow(-2, 3);\n}\n",
"a {\n color: -8;\n}\n"
);
test!(
pow_base_positive_exponent_negative,
"@use 'sass:math';\na {\n color: math.pow(2, -3);\n}\n",
"a {\n color: 0.125;\n}\n"
);
test!(
pow_base_negative_exponent_negative,
"@use 'sass:math';\na {\n color: math.pow(-2, -3);\n}\n",
"a {\n color: -0.125;\n}\n"
);
test!(
pow_base_decimal,
"@use 'sass:math';\na {\n color: math.pow(2.4, 3);\n}\n",
"a {\n color: 13.824;\n}\n"
);
test!(
pow_exponent_decimal,
"@use 'sass:math';\na {\n color: math.pow(2, 3.5);\n}\n",
"a {\n color: 11.313708499;\n}\n"
);
test!(
pow_base_nan,
"@use 'sass:math';\na {\n color: math.pow((0 / 0), 3);\n}\n",
"a {\n color: NaN;\n}\n"
);
test!(
pow_exponent_nan,
"@use 'sass:math';\na {\n color: math.pow(2, (0 / 0));\n}\n",
"a {\n color: NaN;\n}\n"
);
test!(
pow_base_and_exponent_nan,
"@use 'sass:math';\na {\n color: math.pow((0 / 0), (0 / 0));\n}\n",
"a {\n color: NaN;\n}\n"
);
test!(
pow_exponent_zero,
"@use 'sass:math';\na {\n color: math.pow(2, 0);\n}\n",
"a {\n color: 1;\n}\n"
);