1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
use libm::atan2f;

use std::cell::RefCell;
use std::rc::Rc;
use mech_core::*;
use mech_utilities::*;

lazy_static! {
  static ref Y: u64 = hash_str("y");
  static ref X: u64 = hash_str("x");
}

#[derive(Debug)]
pub struct MathAtan2VV {
  pub y_col: (ColumnV<F32>, usize, usize),
  pub x_col: (ColumnV<F32>, usize, usize),
  pub out: ColumnV<F32>,
}

impl MechFunction for MathAtan2VV {
  fn solve(&self) {
    let (y_col,siy,eiy) = &self.y_col;
    let (x_col,six,eix) = &self.x_col;
    self.out.borrow_mut()
            .iter_mut()
            .zip(y_col.borrow()[*siy..=*eiy].iter())
            .zip(x_col.borrow()[*six..=*eix].iter())
            .for_each(|((out,y), x)| *out = F32::new(atan2f(y.unwrap(),x.unwrap()))); 
  }
  fn to_string(&self) -> String { format!("{:#?}", self)}
}

pub struct MathAtan2 {}

impl MechFunctionCompiler for MathAtan2 {
  fn compile(
      &self,
      block: &mut Block,
      arguments: &Vec<Argument>,
      out: &(TableId, TableIndex, TableIndex)
  ) -> std::result::Result<(),MechError>
  {
    if arguments.len() > 2 {
      return Err(MechError{msg: "".to_string(), id: 1347, kind: MechErrorKind::TooManyInputArguments(arguments.len(),1)});
    }
    let arg_dims = block.get_arg_dims(&arguments)?;
    let (arg_name1,arg_table_id1,_) = arguments[0];
    let (arg_name2,arg_table_id2,_) = arguments[1];
    let (out_table_id, _, _) = out;
    let out_table = block.get_table(out_table_id)?;
    let mut out_brrw = out_table.borrow_mut();
    if (arg_name1 == *Y && arg_name2 == *X) {
      match (arg_dims[0],arg_dims[1]) {
        (TableShape::Scalar,TableShape::Scalar) => {
          let arg1 = block.get_arg_columns(arguments)?[0].clone();
          let arg2 = block.get_arg_columns(arguments)?[0].clone();
          out_brrw.resize(1,1);
          out_brrw.set_kind(ValueKind::F32);
          if let Column::F32(out_col) = out_brrw.get_column_unchecked(0) {
            match (arg1,arg2) {
              ((_,Column::F32(y_col),ColumnIndex::Index(_)),(_,Column::F32(x_col),ColumnIndex::Index(_))) |
              ((_,Column::F32(y_col),ColumnIndex::All),(_,Column::F32(x_col),ColumnIndex::All)) => block.plan.push(MathAtan2VV{y_col: (y_col.clone(),0,0), x_col: (x_col.clone(),0,0), out: out_col.clone()}),
              ((_,col,_),_) => { return Err(MechError{msg: "".to_string(), id: 1348, kind: MechErrorKind::UnhandledFunctionArgumentKind(col.kind())}); }
            }
          }
        }
        x => {return Err(MechError{msg: "".to_string(), id: 1350, kind: MechErrorKind::UnhandledTableShape(arg_dims[0])});},
      }
    } else {
      return Err(MechError{msg: "".to_string(), id: 1351, kind: MechErrorKind::UnknownFunctionArgument(arg_name1)});
    }
    Ok(())
  }
}


export_mech_function!(math_atan2, math_atan2_reg);

extern "C" fn math_atan2_reg(registrar: &mut dyn MechFunctionRegistrar) {
  registrar.register_mech_function(hash_str("math/atan2"),Box::new(MathAtan2{}));
}