drasi_core/evaluation/functions/drasi/
stdevp.rs1use crate::evaluation::functions::ScalarFunction;
16use crate::evaluation::{FunctionError, FunctionEvaluationError};
17use async_trait::async_trait;
18use drasi_query_ast::ast;
19use statistical::{mean, population_standard_deviation};
20
21use crate::evaluation::{variable_value::VariableValue, ExpressionEvaluationContext};
22
23#[derive(Clone)]
24pub struct DrasiStdevP {}
25
26#[async_trait]
28impl ScalarFunction for DrasiStdevP {
29 async fn call(
30 &self,
31 _context: &ExpressionEvaluationContext,
32 expression: &ast::FunctionExpression,
33 args: Vec<VariableValue>,
34 ) -> Result<VariableValue, FunctionError> {
35 if args.len() != 1 {
36 return Err(FunctionError {
37 function_name: expression.name.to_string(),
38 error: FunctionEvaluationError::InvalidArgumentCount,
39 });
40 }
41 match &args[0] {
42 VariableValue::Null => Ok(VariableValue::Null),
43 VariableValue::List(l) => {
44 let mut cleaned_list = vec![];
45 for element in l {
46 match element {
47 VariableValue::Integer(i) => {
48 cleaned_list.push(match i.as_i64() {
49 Some(i) => i as f64,
50 None => {
51 return Err(FunctionError {
52 function_name: expression.name.to_string(),
53 error: FunctionEvaluationError::OverflowError,
54 })
55 }
56 });
57 }
58 VariableValue::Float(f) => {
59 cleaned_list.push(match f.as_f64() {
60 Some(f) => f,
61 None => {
62 return Err(FunctionError {
63 function_name: expression.name.to_string(),
64 error: FunctionEvaluationError::OverflowError,
65 })
66 }
67 });
68 }
69 VariableValue::Null => {
70 continue;
71 }
72 _ => {
73 continue;
74 }
75 }
76 }
77 let mean = mean(&cleaned_list);
78 let stdevp = population_standard_deviation(&cleaned_list, Some(mean));
79
80 Ok(VariableValue::Float(stdevp.into()))
81 }
82 _ => Err(FunctionError {
83 function_name: expression.name.to_string(),
84 error: FunctionEvaluationError::InvalidArgument(0),
85 }),
86 }
87 }
88}