-- | Compatability layer between Harpie..Array and uiua arrays. -- -- The main purpose is to change types from Double to Int and back as necessary. (all uiua arrays are doubles). module Huihua.ArrayU ( -- $usage ArrayU (..), arrayi, arrayi', arrayi_, Res, isInt, asInt, showU, -- * uiua API duplicate, pop, identity, not, sign, negate', absoluteValue, sqrt, sine, floor, ceiling, round, length, shape, range, first, reverse, deshape, fix, bits, transpose, rise, fall, where', classify, deduplicate, unique, -- * dyadics equals, notequals, lessThan, lessOrEqual, greaterThan, greaterOrEqual, add, subtract, multiply, divide, modulus, power, logarithm, minimum, maximum, atangent, match, couple, join, select, pick, reshape, rerank, take, drop, rotate, windows, keep, find, mask, member, indexOf, -- * reductions equalsR, notEqualsR, lessThanR, lessOrEqualR, greaterThanR, greaterOrEqualR, addR, subtractR, multiplyR, divideR, modulusR, powerR, logarithmR, minimumR, maximumR, -- * testing only ptree, unfoldF, ) where import Data.Bool (bool) import Data.Either import Data.Function ((&)) import Data.List qualified as List import Data.Maybe import Data.Text (Text, pack, unpack) import Data.Text qualified as Text import Data.Tree qualified as Tree import GHC.Generics import Harpie.Array (Array (..)) import Harpie.Array qualified as D import Huihua.Array qualified as A import Huihua.Warning import Prettyprinter hiding (equals) import Prelude hiding (ceiling, drop, floor, length, maximum, minimum, not, reverse, round, sin, sqrt, subtract, take) import Prelude qualified as P -- $setup -- >>> :set -XOverloadedStrings -- >>> :set -XQuasiQuotes -- >>> import Data.String.Interpolate -- >>> import Huihua.Array as A -- >>> import Harpie.Array as D -- >>> import Prettyprinter -- >>> import Huihua.Parse -- | A uiua array which is always an Array Double underneath. -- -- >>> x = D.array [2,2] [2, 2.222,200.001,200.01] :: Array Double -- >>> pretty (ArrayU x) -- ╭─ -- ╷ 2 2.222 -- 200.001 200.01 -- ╯ newtype ArrayU = ArrayU {arrayd :: Array Double} deriving (Eq, Show, Generic) instance Pretty ArrayU where pretty (ArrayU x) = case D.rank x of 0 -> pretty $ showU (D.fromScalar x) 1 -> pretty "[" <> hsep (fmap (pretty . showU) (D.arrayAs x)) <> pretty "]" _ -> final where t = ptree (fmap showU x) maxp = D.reduces [1] (P.maximum . fmap Text.length) (D.join $ D.asArray $ rights t) s = fmap (fmap (D.zipWith (\m a -> lpad' ' ' m a) maxp)) t sdoc = mconcat $ fmap (either (\n -> replicate (n - 1) mempty) (pure . hsep . fmap pretty . D.arrayAs)) s sdocMin = D.concatenate 0 (D.konst [max 0 (D.rank x - P.length sdoc - 1)] mempty) (D.asArray sdoc) rankPrefix = fmap pretty (D.pad " " [D.length sdocMin] (D.konst [D.rank x - 1] "╷")) deco = zipWith (<+>) (D.arrayAs rankPrefix) (D.arrayAs sdocMin) final = pretty "╭─" <> line <> vsep deco <> hang 1 (line <> pretty "╯") showU :: Double -> Text showU x = bool mempty (pack "¯") (x < 0) <> bool (pack $ show (abs x)) (pack $ show (asInt (abs x))) (isInt x) lpad' :: Char -> Int -> Text -> Text lpad' c maxl x = (pack $ replicate (maxl - P.length (unpack x)) c) <> x unfoldF :: Either Int (Array a) -> (Maybe (Either Int (Array a)), [Either Int (Array a)]) unfoldF (Left n) = (Just (Left n), []) unfoldF (Right a) = case D.rank a of 1 -> (Just (Right a), []) _ -> (Nothing, List.intersperse (Left (D.rank a - 1)) (Right <$> D.arrayAs (D.extracts [0] a))) ptree :: Array a -> [Either Int (Array a)] ptree a = catMaybes $ Tree.flatten $ Tree.unfoldTree unfoldF (Right a) arrayi :: ArrayU -> Array Int arrayi (ArrayU a) = fmap asInt a arrayi' :: ArrayU -> Either HuihuaWarning (Array Int) arrayi' (ArrayU a) = bool (Left NotNat) (Right (fmap asInt a)) (all isInt a) isInt :: Double -> Bool isInt x = x == fromIntegral (P.floor x :: Int) asInt :: Double -> Int asInt x = P.floor x arrayi_ :: ArrayU -> Array Int arrayi_ a = either (error . show) id (arrayi' a) type Res = Either HuihuaWarning [ArrayU] -- | . -- -- >>> run ". [1 2 3]" -- [1 2 3] -- [1 2 3] duplicate :: ArrayU -> Res duplicate x = Right [x, x] -- | ◌ -- -- >>> run [i|◌1 2|] -- 2 pop :: ArrayU -> Res pop _ = Right [] -- | ∘ -- -- >>> run [i|∘ 5|] -- 5 identity :: ArrayU -> Res identity x = Right [x] -- | ¬ -- -- >>> run [i|¬0|] -- 1 -- >>> run [i|¬[0 1 2 3]|] -- [1 0 ¯1 ¯2] not :: ArrayU -> Res not (ArrayU a) = Right . pure . ArrayU . A.not $ a -- | ± -- -- >>> run [i|± 1|] -- 1 sign :: ArrayU -> Res sign (ArrayU a) = Right . pure . ArrayU . A.sign $ a -- | ¯ -- -- negate is just about a reserved word in haskell eg -2 is parsed as negate 2. -- -- >>> run [i|¯ 1|] -- ¯1 negate' :: ArrayU -> Res negate' (ArrayU a) = Right . pure . ArrayU . A.negate' $ a -- | ⌵ -- -- >>> run [i|⌵ ¯1|] -- 1 absoluteValue :: ArrayU -> Res absoluteValue (ArrayU a) = Right . pure . ArrayU . A.absolute $ a -- | √ -- -- >>> run [i|√4|] -- 2 sqrt :: ArrayU -> Res sqrt (ArrayU a) = Right . pure . ArrayU . A.sqrt $ a -- | ∿ -- -- >>> run [i|∿ 1|] -- 0.8414709848078965 sine :: ArrayU -> Res sine (ArrayU a) = Right . pure . ArrayU . A.sin $ a -- | ⌊ -- -- >>> run [i|⌊1.5|] -- 1 floor :: ArrayU -> Res floor (ArrayU a) = Right . pure . ArrayU . fmap fromIntegral . A.floor $ a -- | ⌈ -- -- >>> run [i|⌈1.5|] -- 2 ceiling :: ArrayU -> Res ceiling (ArrayU a) = Right . pure . ArrayU . fmap fromIntegral . A.ceiling $ a -- | ⁅ -- -- >>> run [i|⁅1.5|] -- 2 round :: ArrayU -> Res round (ArrayU a) = Right . pure . ArrayU . fmap fromIntegral . A.round $ a -- | ⧻ -- -- >>> run [i|⧻[1 3 5]|] -- 3 length :: ArrayU -> Res length (ArrayU a) = Right . pure . ArrayU . fmap fromIntegral . A.length $ a -- | △ -- -- >>> run [i|△1_2_3|] -- [3] -- >>> run [i|△1|] -- [] -- >>> run [i|△[]|] -- [0] shape :: ArrayU -> Res shape (ArrayU a) = Right . pure . ArrayU . fmap fromIntegral . A.shape $ a -- | ⇡ -- -- >>> run [i|⇡5|] -- [0 1 2 3 4] -- >>> run [i|⇡2_3|] -- ╭─ -- ╷ 0 0 -- ╷ 0 1 -- 0 2 -- ... -- 1 0 -- 1 1 -- 1 2 -- ╯ -- >>> run [i|⇡[3]|] -- ╭─ -- ╷ 0 -- 1 -- 2 -- ╯ range :: ArrayU -> Res range (ArrayU a) = Right . pure . ArrayU . fmap fromIntegral . A.range $ fmap asInt a -- | ⊢ -- -- >>> run [i|⊢1_2_3|] -- 1 first :: ArrayU -> Res first (ArrayU a) = Right . pure . ArrayU . A.first $ a -- | ⇌ -- -- >>> run [i|⇌[1_2 3_4 5_6]|] -- ╭─ -- ╷ 5 6 -- 3 4 -- 1 2 -- ╯ reverse :: ArrayU -> Res reverse (ArrayU a) = Right . pure . ArrayU . A.reverse $ a -- | ♭ -- -- >>> run [i|♭[1_2 3_4 5_6]|] -- [1 2 3 4 5 6] deshape :: ArrayU -> Res deshape (ArrayU a) = Right . pure . ArrayU . A.deshape $ a -- | ¤ -- -- >>> run [i|¤1_2]|] -- ╭─ -- ╷ 1 2 -- ╯ fix :: ArrayU -> Res fix (ArrayU a) = Right . pure . ArrayU . A.fix $ a -- | ⋯ -- -- >>> run [i|⋯[1_2 3_4 5_6]|] -- ╭─ -- ╷ 1 0 0 -- ╷ 0 1 0 -- ... -- 1 1 0 -- 0 0 1 -- ... -- 1 0 1 -- 0 1 1 -- ╯ bits :: ArrayU -> Res bits (ArrayU a) = Right . pure . ArrayU . fmap fromIntegral . A.bits . fmap asInt $ a -- | ⍉ -- -- >>> run [i|⍉[[1_2 3_4] [5_6 7_8]]|] -- ╭─ -- ╷ 1 5 -- ╷ 2 6 -- ... -- 3 7 -- 4 8 -- ╯ transpose :: ArrayU -> Res transpose (ArrayU a) = Right . pure . ArrayU . A.transpose $ a -- | ⍏ -- -- >>> run [i|⍏ 6_2_7_0_1_5|] -- [3 4 1 5 0 2] rise :: ArrayU -> Res rise (ArrayU a) = Right . pure . ArrayU . fmap fromIntegral . A.rise $ a -- | ⍖ -- -- >>> run [i|⍖ 6_2_7_0_1_5|] -- [2 0 5 1 4 3] fall :: ArrayU -> Res fall (ArrayU a) = Right . pure . ArrayU . fmap fromIntegral . A.fall $ a -- | ⊚ -- -- >>> run [i|⊚[1_0_0 0_1_1 0_2_0]|] -- ╭─ -- ╷ 0 0 -- 1 1 -- 1 2 -- 2 1 -- 2 1 -- ╯ where' :: ArrayU -> Res where' (ArrayU a) = Right . pure . ArrayU . fmap fromIntegral . A.where' . fmap asInt $ a -- | ⊛ -- -- >>> run [i|⊛7_7_8_0_1_2_0|] -- [0 0 1 2 3 4 2] classify :: ArrayU -> Res classify (ArrayU a) = Right . pure . ArrayU . fmap fromIntegral . A.classify $ a -- | ◴ -- -- >>> run [i|◴ 7_7_8_0_1_2_0|] -- [7 8 0 1 2] deduplicate :: ArrayU -> Res deduplicate (ArrayU a) = Right . pure . ArrayU . A.deduplicate $ a -- | ◰ -- -- >>> run [i|◰ [3_2 1_4 3_2 5_6 1_4 7_8]|] -- [1 1 0 1 0 1] unique :: ArrayU -> Res unique (ArrayU a) = Right . pure . ArrayU . fmap fromIntegral . A.unique $ a -- | ∊ -- -- >>> run [i|∊ [1 2 3] [0 3 4 5 1]|] -- [1 0 1] member :: ArrayU -> ArrayU -> Res member (ArrayU x) (ArrayU y) = Right . pure . ArrayU . fmap fromIntegral $ A.member x y -- | ⊗ -- -- >>> run [i|⊗ 2 [1 2 3]|] -- 1 indexOf :: ArrayU -> ArrayU -> Res indexOf (ArrayU x) (ArrayU y) = Right . pure . ArrayU . fmap fromIntegral $ A.indexOf x y -- * dyadic operators -- | = -- -- >>> run [i| =2 1|] -- 0 -- >>> run [i| =2 [1 2 3]|] -- [0 1 0] -- >>> run [i| = [1 2 2] [1 2 3]|] -- [1 1 0] equals :: ArrayU -> ArrayU -> Res equals (ArrayU x) (ArrayU y) = fmap (pure . ArrayU . fmap fromIntegral) $ A.equals x y -- | ≠ -- -- >>> run [i| ≠2 1|] -- 1 -- >>> run [i| ≠2 [1 2 3]|] -- [1 0 1] -- >>> run [i| ≠ [1 2 2] [1 2 3]|] -- [0 0 1] notequals :: ArrayU -> ArrayU -> Res notequals (ArrayU x) (ArrayU y) = fmap (pure . ArrayU . fmap fromIntegral) $ A.notequals x y -- | < -- -- >>> run [i|<2 1|] -- 1 -- >>> run [i|<2 [1 2 3]|] -- [1 0 0] -- >>> run [i|< [1 2 2] [1 2 3]|] -- [0 0 0] lessThan :: ArrayU -> ArrayU -> Res lessThan (ArrayU x) (ArrayU y) = fmap (pure . ArrayU . fmap fromIntegral) $ A.lessThan x y -- | ≤ -- -- >>> run [i|≤1 2|] -- 0 -- >>> run [i|≤5 5|] -- 1 lessOrEqual :: ArrayU -> ArrayU -> Res lessOrEqual (ArrayU x) (ArrayU y) = fmap (pure . ArrayU . fmap fromIntegral) $ A.lessOrEqual x y -- | > -- -- >>> run [i| >1 2|] -- 1 -- >>> run [i| >5 5|] -- 0 greaterThan :: ArrayU -> ArrayU -> Res greaterThan (ArrayU x) (ArrayU y) = fmap (pure . ArrayU . fmap fromIntegral) $ A.greaterThan x y -- | ≥ -- -- >>> run [i| ≥1 2|] -- 1 -- >>> run [i| ≥5 5|] -- 1 greaterOrEqual :: ArrayU -> ArrayU -> Res greaterOrEqual (ArrayU x) (ArrayU y) = fmap (pure . ArrayU . fmap fromIntegral) $ A.greaterOrEqual x y -- | + -- -- >>> run [i|+2 1|] -- 3 -- >>> run [i|+2 [1 2 3]|] -- [3 4 5] -- >>> run [i|+ [1 2 2] [1 2 3]|] -- [2 4 5] -- >>> run [i|+ [1_2_3 4_5_6] [1 2]|] -- ╭─ -- ╷ 2 3 4 -- 6 7 8 -- ╯ -- >>> run [i|+ [1 2] [1_2_3 4_5_6]|] -- ╭─ -- ╷ 2 3 4 -- 6 7 8 -- ╯ add :: ArrayU -> ArrayU -> Res add (ArrayU x) (ArrayU y) = fmap (pure . ArrayU) $ A.add x y -- | - -- -- >>> run [i|-2 1|] -- ¯1 -- >>> run [i|-2 [1 2 3]|] -- [¯1 0 1] -- >>> run [i|-[1 2 3] [4 5 6]|] -- [3 3 3] subtract :: ArrayU -> ArrayU -> Res subtract (ArrayU x) (ArrayU y) = fmap (pure . ArrayU) $ A.subtract x y -- | × -- -- >>> run [i|×2 1|] -- 2 -- >>> run [i|×2 [1 2 3]|] -- [2 4 6] multiply :: ArrayU -> ArrayU -> Res multiply (ArrayU x) (ArrayU y) = fmap (pure . ArrayU) $ A.multiply x y -- | ÷ -- -- >>> run [i|÷2 1|] -- 0.5 divide :: ArrayU -> ArrayU -> Res divide (ArrayU x) (ArrayU y) = fmap (pure . ArrayU) $ A.divide x y -- | ◿ -- -- >>> run [i|◿10 27|] -- 7 -- >>> run [i|◿5 [3 7 14]|] -- [3 2 4] modulus :: ArrayU -> ArrayU -> Res modulus (ArrayU x) (ArrayU y) = fmap (pure . ArrayU) $ A.modulus x y -- | doctest bug power :: ArrayU -> ArrayU -> Res power (ArrayU x) (ArrayU y) = fmap (pure . ArrayU) $ A.power x y -- | doctest bug logarithm :: ArrayU -> ArrayU -> Res logarithm (ArrayU x) (ArrayU y) = fmap (pure . ArrayU) $ A.logarithm x y -- | ↧ -- -- >>> run [i|↧ 3 5|] -- 3 -- >>> run [i|↧ [1 4 2] [3 7 1]|] -- [1 4 1] minimum :: ArrayU -> ArrayU -> Res minimum (ArrayU x) (ArrayU y) = fmap (pure . ArrayU) $ A.minimum x y -- | ↥ -- -- >>> run [i|↥ 3 5|] -- 5 -- >>> run [i|↥ [1 4 2] [3 7 1]|] -- [3 7 2] maximum :: ArrayU -> ArrayU -> Res maximum (ArrayU x) (ArrayU y) = fmap (pure . ArrayU) $ A.maximum x y -- | ∠ -- -- >>> run [i|∠ 1 0|] -- 1.5707963267948966 -- >>> run [i|∠ ¯1 0|] -- ¯1.5707963267948966 atangent :: ArrayU -> ArrayU -> Res atangent (ArrayU x) (ArrayU y) = fmap (pure . ArrayU) $ A.atangent x y -- | ≍ -- -- >>> run [i|≍ 1_2_3 [1 2 3]|] -- 1 -- >>> run [i|≍ 1_2_3 1_2|] -- 0 match :: ArrayU -> ArrayU -> Res match (ArrayU x) (ArrayU y) = Right . pure . ArrayU . fmap fromIntegral $ A.match x y -- | ⊟ -- -- >>> run [i|⊟ 1 2|] -- [1 2] -- >>> run [i|⊟ [1 2 3] [4 5 6]|] -- ╭─ -- ╷ 1 2 3 -- 4 5 6 -- ╯ couple :: ArrayU -> ArrayU -> Res couple (ArrayU x) (ArrayU y) = Right . pure . ArrayU $ A.couple x y -- | ⊂ -- -- >>> run [i|⊂ 1 2|] -- [1 2] -- >>> run [i|⊂ [1 2 3] [4 5 6]|] -- [1 2 3 4 5 6] -- >>> run [i|⊂ 1 [2 3]|] -- [1 2 3] -- >>> run [i|⊂ [1 2] 3|] -- [1 2 3] -- >>> run [i|⊂ [1_2 3_4] 5_6|] -- ╭─ -- ╷ 1 2 -- 3 4 -- 5 6 -- ╯ -- >>> run [i|⊂ [1_2] [3_4 5_6]|] -- ╭─ -- ╷ 1 2 -- 3 4 -- 5 6 -- ╯ -- >>> run [i|⊂ 0 [1_2 3_4]|] -- ╭─ -- ╷ 0 0 -- 1 2 -- 3 4 -- ╯ -- >>> run [i|⊂ [1_2 3_4] 0|] -- ╭─ -- ╷ 1 2 -- 3 4 -- 0 0 -- ╯ join :: ArrayU -> ArrayU -> Res join (ArrayU x) (ArrayU y) = fmap (pure . ArrayU) (A.join x y) -- | ⊂ -- -- >>> run [i|⊏ 2 [8 3 9 2 0]|] -- 9 -- >>> run [i|⊏ 4_2 [8 3 9 2 0]|] -- [0 9] -- >>> run [i|⊏ 0_2_1_1 [1_2_3 4_5_6 7_8_9]|] -- ╭─ -- ╷ 1 2 3 -- 7 8 9 -- 4 5 6 -- 4 5 6 -- ╯ -- >>> run [i|⊏ [0_1 1_2 2_3] [2 3 5 7]|] -- ╭─ -- ╷ 2 3 -- 3 5 -- 5 7 -- ╯ select :: ArrayU -> ArrayU -> Res select (ArrayU x) (ArrayU y) = Right . pure . ArrayU $ A.select (fmap asInt x) y -- | ⊡ -- -- >>> run [i|⊡ [1_2 0_1] [1_2_3 4_5_6]|] -- [6 2] -- >>> run [i|⊡ 2_1 [8 3 9 2 0]|] -- 9 -- >>> run [i|⊡ 1 [1_2_3 4_5_6]|] -- [4 5 6] pick :: ArrayU -> ArrayU -> Res pick (ArrayU x) (ArrayU y) = fmap (pure . ArrayU) $ A.pick (fmap asInt x) y -- | ↯ -- -- >>> run [i|↯ 2_3 [1 2 3 4 5 6]|] -- ╭─ -- ╷ 1 2 3 -- 4 5 6 -- ╯ -- >>> run [i|↯ 2_2 [1_2_3 4_5_6]|] -- ╭─ -- ╷ 1 2 -- 3 4 -- ╯ -- >>> run [i|↯ [5] 2|] -- [2 2 2 2 2] -- >>> run [i|↯ 3_7 1_2_3_4|] -- ╭─ -- ╷ 1 2 3 4 1 2 3 -- 4 1 2 3 4 1 2 -- 3 4 1 2 3 4 1 -- ╯ -- >>> run [i|↯ 4 [1 2 3 4 5]|] -- ╭─ -- ╷ 1 2 3 4 5 -- 1 2 3 4 5 -- 1 2 3 4 5 -- 1 2 3 4 5 -- ╯ -- >>> run [i|↯ 2 [1_2_3 4_5_6]|] -- ╭─ -- ╷ 1 2 3 -- ╷ 4 5 6 -- ... -- 1 2 3 -- 4 5 6 -- ╯ reshape :: ArrayU -> ArrayU -> Res reshape (ArrayU x) (ArrayU y) = Right . pure . ArrayU $ A.reshape (fmap asInt x) y -- | ☇ -- -- >>> run [i|☇ 1 ↯2_3_3⇡18|] -- ╭─ -- ╷ 0 1 2 -- 3 4 5 -- 6 7 8 -- 9 10 11 -- 12 13 14 -- 15 16 17 -- ╯ -- >>> run [i|△☇ 3 ↯2_3_3⇡18|] -- [1 2 3 3] rerank :: ArrayU -> ArrayU -> Res rerank (ArrayU x) (ArrayU y) = A.rerank (fmap asInt x) y & fmap (pure . ArrayU) -- | ↙ -- -- >>> run [i|↙ [3] [8 3 9 2 0]|] -- [8 3 9] take :: ArrayU -> ArrayU -> Res take (ArrayU x) (ArrayU y) = fmap (pure . ArrayU) $ A.take (fmap asInt x) y -- | ↘ -- -- >>> run [i|↘ 3 [8 3 9 2 0]|] -- [2 0] drop :: ArrayU -> ArrayU -> Res drop (ArrayU x) (ArrayU y) = fmap (pure . ArrayU) $ A.drop (fmap asInt x) y -- | ↻ -- -- >>> run [i|↻1 ⇡5|] -- [1 2 3 4 0] rotate :: ArrayU -> ArrayU -> Res rotate (ArrayU x) (ArrayU y) = Right . pure . ArrayU $ A.rotate (fmap asInt x) y -- | ▽ -- -- >>> run [i|▽ [3 2] [8 3 9 2 0]|] -- [8 8 8 3 3 9 9 9 2 2 0 0 0] keep :: ArrayU -> ArrayU -> Res keep (ArrayU x) (ArrayU y) = Right . pure . ArrayU $ A.keep (fmap asInt x) y -- | ◫ -- -- >>> run [i|◫2 ⇡4|] -- ╭─ -- ╷ 0 1 -- 1 2 -- 2 3 -- ╯ windows :: ArrayU -> ArrayU -> Res windows (ArrayU x) (ArrayU y) = Right . pure . ArrayU $ A.windows (fmap asInt x) y -- | ⌕ -- -- >>> run [i|⌕ [5] [1 8 5 2 3 5 4 5 6 7]|] -- [0 0 1 0 0 1 0 1 0 0] -- >>> run [i|⌕ [1_2 2_0] ↯4_4⇡3|] -- ╭─ -- ╷ 0 1 0 0 -- 1 0 0 0 -- 0 0 1 0 -- 0 0 0 0 -- ╯ find :: ArrayU -> ArrayU -> Res find (ArrayU x) (ArrayU y) = Right . pure . ArrayU . fmap fromIntegral $ A.find x y -- | ⦷ -- -- >>> run [i|⦷ [1_1 1_1] ↯ [5 5] 1|] -- ╭─ -- ╷ 1 1 2 2 0 -- 1 1 2 2 0 -- 3 3 4 4 0 -- 3 3 4 4 0 -- 0 0 0 0 0 -- ╯ mask :: ArrayU -> ArrayU -> Res mask (ArrayU x) (ArrayU y) = Right . pure . ArrayU . fmap fromIntegral $ A.mask x y -- | /= -- -- >>> run [i|/=[0_1_0 0_4_3]|] -- [1 0 0] equalsR :: ArrayU -> Res equalsR (ArrayU x) = Right . pure . ArrayU . fmap fromIntegral $ A.equalsR x -- | /≠ -- -- >>> run [i|/≠[0_1_0 0_4_3]|] -- [0 1 1] notEqualsR :: ArrayU -> Res notEqualsR (ArrayU x) = Right . pure . ArrayU . fmap fromIntegral $ A.notEqualsR x -- | /< -- -- >>> run [i|/<[2_1_0 0_4_3]|] -- [1 0 0] lessThanR :: ArrayU -> Res lessThanR (ArrayU x) = Right . pure . ArrayU . fmap fromIntegral $ A.lessThanR x -- | /≤ -- -- >>> run [i|/≤[0_1_0 0_4_3]|] -- [1 0 0] lessOrEqualR :: ArrayU -> Res lessOrEqualR (ArrayU x) = Right . pure . ArrayU . fmap fromIntegral $ A.lessOrEqualR x -- | /> -- -- >>> run [i|/>[0_1_0 0_4_3]|] -- [0 1 1] greaterThanR :: ArrayU -> Res greaterThanR (ArrayU x) = Right . pure . ArrayU . fmap fromIntegral $ A.greaterThanR x -- | /≥ -- -- >>> run [i|/≥[0_1_0 0_4_3]|] -- [1 1 1] greaterOrEqualR :: ArrayU -> Res greaterOrEqualR (ArrayU x) = Right . pure . ArrayU . fmap fromIntegral $ A.greaterOrEqualR x -- | /+ -- -- >>> run [i|/+[0_1_0 0_4_3]|] -- [0 5 3] addR :: ArrayU -> Res addR (ArrayU x) = Right $ pure $ ArrayU $ A.addR x -- | /- -- -- >>> run [i|/- 1_2_3|] -- 2 -- >>> run [i|/- [1_2_3 4_5_6]|] -- [3 3 3] subtractR :: ArrayU -> Res subtractR (ArrayU x) = Right $ pure $ ArrayU $ A.subtractR x -- | /× -- -- >>> run [i|/× 1_2_3|] -- 6 -- >>> run [i|/× [1_2_3 4_5_6]|] -- [4 10 18] multiplyR :: ArrayU -> Res multiplyR (ArrayU x) = Right $ pure $ ArrayU $ A.multiplyR x -- | /÷ -- -- >>> run [i|/÷ 1_2_3|] -- 1.5 -- >>> run [i|/÷ [1_2_3 4_5_6]|] -- [4 2.5 2] divideR :: ArrayU -> Res divideR (ArrayU x) = Right $ pure $ ArrayU $ A.divideR x -- | /◿ -- -- >>> run [i|/◿ []|] -- Infinity -- >>> run [i|/◿ [2]|] -- 2 -- >>> run [i|/◿ 2_1|] -- 1 -- >>> run [i|/◿ [1_2_3 4_5_6]|] -- [0 1 0] modulusR :: ArrayU -> Res modulusR (ArrayU x) = Right $ pure $ ArrayU $ A.modulusR x -- | doctest subscript bug. see readme for test powerR :: ArrayU -> Res powerR (ArrayU x) = Right $ pure $ ArrayU $ A.powerR x -- | doctest subscript bug. see readme for test logarithmR :: ArrayU -> Res logarithmR (ArrayU x) = fmap (pure . ArrayU) $ A.logarithmR x -- | /↧ -- -- >>> run [i|/↧ []|] -- Infinity -- >>> run [i|/↧ [2]|] -- 2 -- >>> run [i|/↧ 2_1|] -- 1 -- >>> run [i|/↧ [1_2_3 4_5_6]|] -- [1 2 3] minimumR :: ArrayU -> Res minimumR (ArrayU x) = Right $ pure $ ArrayU $ A.minimumR x -- | /↥ -- -- >>> run [i|/↥ []|] -- ¯Infinity -- >>> run [i|/↥[2]|] -- 2 -- >>> run [i|/↥ 2_1|] -- 2 -- >>> run [i|/↥ [1_2_3 4_5_6]|] -- [4 5 6] maximumR :: ArrayU -> Res maximumR (ArrayU x) = Right $ pure $ ArrayU $ A.maximumR x