rustymath_core/
characters.rs1use crate::buffer::{DType, Ints, View, Width};
3use crate::error::{Error, Kind};
4use std::cmp::Ordering;
5
6#[derive(Clone, Copy, Debug, PartialEq, Eq)]
7pub enum Rule { Identity, Ordered, Shift, Difference }
8
9#[derive(Clone, Copy, Debug, PartialEq, Eq)]
10pub enum ByKinds { Truth(bool), Left, Right }
11impl ByKinds {
12 pub fn ordered([left, _]: [i32; 2], result: i32, boolean: bool) -> Self {
13 if boolean { Self::Truth(result != 0) } else if result == left { Self::Left } else { Self::Right }
14 }
15}
16
17#[derive(Clone, Copy, Debug, PartialEq, Eq)]
18pub enum Policy { Codes { computing: DType, result: DType }, Kinds(ByKinds) }
19
20pub(crate) fn policy(
21 rule: Option<Rule>, types: [DType; 2], numeric_result: DType, kinds: impl FnOnce([i32; 2]) -> Option<i32>) -> Result<Option<Policy>, Error> {
22 let [xc, yc] = types.map(|t| t == DType::Character);
23 if !xc && !yc { return Ok(None); }
24 let (computing, result) = match (rule, xc, yc) {
25 (Some(Rule::Ordered), true, true) => (DType::Integer(Width::I32), if numeric_result == DType::Boolean { DType::Boolean } else { DType::Character }),
26 (Some(Rule::Ordered), _, _) => {
27 let classes = [i32::from(xc), i32::from(yc)];
28 let result = kinds(classes).ok_or_else(|| Error::new(Kind::Domain, "ordered character function has no integer body"))?;
29 return Ok(Some(Policy::Kinds(ByKinds::ordered(classes, result, numeric_result == DType::Boolean))));
30 }
31 (Some(Rule::Difference), true, true) => (DType::Integer(Width::I32), DType::Integer(Width::I32)),
32 (Some(Rule::Shift), true, false) | (Some(Rule::Shift), false, true) | (Some(Rule::Difference), true, false)
33 if !types.iter().any(|t| matches!(t, DType::Complex(_))) =>
34 { (DType::Integer(Width::I64), DType::Character) }
35 _ => return Err(Error::new(Kind::Domain, "function does not take these character arguments")),
36 };
37 Ok(Some(Policy::Codes { computing, result }))
38}
39
40pub fn order_of_kinds(x_character: bool, y_character: bool) -> Ordering { x_character.cmp(&y_character) }
41
42pub fn codes(chars: &[char]) -> &[i32] {
44 unsafe { std::slice::from_raw_parts(chars.as_ptr().cast(), chars.len()) }
46}
47
48pub fn as_codes(view: View<'_>) -> View<'_> { match view { View::Characters(c) => View::Integers(Ints::I32(codes(c))), view => view } }