partial_function

[Done] Partial Function library for Rust.
git clone https://git.jojolepro.com/partial_function.git
Log | Files | Refs | README | LICENSE

commit 837efa1d3d072e3fa62f34b7a8e404b395f71131
parent f67c9f48161d67044517d657f74eb8113f0d89cc
Author: Joël Lupien (Jojolepro) <jojolepromain@gmail.com>
Date:   Wed,  8 Aug 2018 19:23:54 -0400

Added LowerPartialFunction

Diffstat:
A.gitignore | 3+++
A.idea/misc.xml | 10++++++++++
A.idea/modules.xml | 9+++++++++
A.idea/partial_function.iml | 10++++++++++
A.idea/vcs.xml | 7+++++++
A.idea/workspace.xml | 254+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/lib.rs | 38+++++++++++++++++++++++++++++++++++++-
Mtests/tests.rs | 35+++++++++++++++++++++++++++++++++++
8 files changed, 365 insertions(+), 1 deletion(-)

diff --git a/.gitignore b/.gitignore @@ -0,0 +1,3 @@ +/target/ +**/*.rs.bk +Cargo.lock diff --git a/.idea/misc.xml b/.idea/misc.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="CargoProjects"> + <cargoProject FILE="$PROJECT_DIR$/Cargo.toml" /> + </component> + <component name="RustProjectSettings"> + <option name="toolchainHomeDirectory" value="/usr/bin" /> + </component> +</project>+ \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="ProjectModuleManager"> + <modules> + <module fileurl="file://$PROJECT_DIR$/.idea/partial_function.iml" filepath="$PROJECT_DIR$/.idea/partial_function.iml" /> + </modules> + </component> +</project>+ \ No newline at end of file diff --git a/.idea/partial_function.iml b/.idea/partial_function.iml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8"?> +<module type="JAVA_MODULE" version="4"> + <component name="NewModuleRootManager" inherit-compiler-output="true"> + <exclude-output /> + <content url="file://$MODULE_DIR$" /> + <orderEntry type="inheritedJdk" /> + <orderEntry type="sourceFolder" forTests="false" /> + </component> +</module>+ \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="VcsDirectoryMappings"> + <mapping directory="" vcs="Git" /> + </component> +</project>+ \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml @@ -0,0 +1,253 @@ +<?xml version="1.0" encoding="UTF-8"?> +<project version="4"> + <component name="ChangeListManager"> + <list default="true" id="c61cb26e-cd20-4478-b386-32735fce1844" name="Default" comment=""> + <change afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" /> + <change afterPath="$PROJECT_DIR$/.idea/vcs.xml" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/src/lib.rs" beforeDir="false" afterPath="$PROJECT_DIR$/src/lib.rs" afterDir="false" /> + <change beforePath="$PROJECT_DIR$/tests/tests.rs" beforeDir="false" afterPath="$PROJECT_DIR$/tests/tests.rs" afterDir="false" /> + </list> + <option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" /> + <option name="TRACKING_ENABLED" value="true" /> + <option name="SHOW_DIALOG" value="false" /> + <option name="HIGHLIGHT_CONFLICTS" value="true" /> + <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" /> + <option name="LAST_RESOLUTION" value="IGNORE" /> + </component> + <component name="FileEditorManager"> + <leaf> + <file leaf-file-name="lib.rs" pinned="false" current-in-tab="true"> + <entry file="file://$PROJECT_DIR$/src/lib.rs"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="348"> + <caret line="153" column="13" lean-forward="true" selection-start-line="153" selection-start-column="13" selection-end-line="153" selection-end-column="13" /> + <folding> + <element signature="e#4017#4018#0" expanded="true" /> + <element signature="e#4066#4067#0" expanded="true" /> + </folding> + </state> + </provider> + </entry> + </file> + <file leaf-file-name="tests.rs" pinned="false" current-in-tab="false"> + <entry file="file://$PROJECT_DIR$/tests/tests.rs"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="1068"> + <caret line="99" column="29" selection-start-line="99" selection-start-column="29" selection-end-line="99" selection-end-column="29" /> + </state> + </provider> + </entry> + </file> + <file leaf-file-name=".gitignore" pinned="false" current-in-tab="false"> + <entry file="file://$PROJECT_DIR$/.gitignore"> + <provider selected="true" editor-type-id="text-editor" /> + </entry> + </file> + </leaf> + </component> + <component name="Git.Settings"> + <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" /> + </component> + <component name="IdeDocumentHistory"> + <option name="CHANGED_PATHS"> + <list> + <option value="$PROJECT_DIR$/tests/tests.rs" /> + <option value="$PROJECT_DIR$/src/lib.rs" /> + </list> + </option> + </component> + <component name="ProjectFrameBounds"> + <option name="x" value="12" /> + <option name="y" value="15" /> + <option name="width" value="1896" /> + <option name="height" value="1053" /> + </component> + <component name="ProjectLevelVcsManager"> + <ConfirmationsSetting value="2" id="Add" /> + </component> + <component name="ProjectView"> + <navigator proportions="" version="1"> + <foldersAlwaysOnTop value="true" /> + </navigator> + <panes> + <pane id="PackagesPane" /> + <pane id="Scope" /> + <pane id="AndroidView" /> + <pane id="ProjectPane"> + <subPane> + <expand> + <path> + <item name="partial_function" type="b2602c69:ProjectViewProjectNode" /> + <item name="partial_function" type="462c0819:PsiDirectoryNode" /> + </path> + <path> + <item name="partial_function" type="b2602c69:ProjectViewProjectNode" /> + <item name="partial_function" type="462c0819:PsiDirectoryNode" /> + <item name="src" type="462c0819:PsiDirectoryNode" /> + </path> + <path> + <item name="partial_function" type="b2602c69:ProjectViewProjectNode" /> + <item name="partial_function" type="462c0819:PsiDirectoryNode" /> + <item name="tests" type="462c0819:PsiDirectoryNode" /> + </path> + </expand> + <select /> + </subPane> + </pane> + </panes> + </component> + <component name="PropertiesComponent"> + <property name="last_opened_file_path" value="$PROJECT_DIR$" /> + <property name="org.rust.cargo.project.model.PROJECT_DISCOVERY" value="true" /> + </component> + <component name="RunDashboard"> + <option name="ruleStates"> + <list> + <RuleState> + <option name="name" value="ConfigurationTypeDashboardGroupingRule" /> + </RuleState> + <RuleState> + <option name="name" value="StatusDashboardGroupingRule" /> + </RuleState> + </list> + </option> + </component> + <component name="RunManager"> + <configuration default="true" type="Application" factoryName="Application"> + <option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" /> + </configuration> + <configuration default="true" type="JUnit" factoryName="JUnit"> + <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" /> + <option name="ALTERNATIVE_JRE_PATH" /> + <option name="PACKAGE_NAME" /> + <option name="MAIN_CLASS_NAME" /> + <option name="METHOD_NAME" /> + <option name="TEST_OBJECT" value="class" /> + <option name="VM_PARAMETERS" value="-ea" /> + <option name="PARAMETERS" /> + <option name="WORKING_DIRECTORY" value="%MODULE_WORKING_DIR%" /> + <option name="PASS_PARENT_ENVS" value="true" /> + <option name="TEST_SEARCH_SCOPE"> + <value defaultName="singleModule" /> + </option> + <patterns /> + </configuration> + <configuration default="true" type="TestNG" factoryName="TestNG"> + <option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" /> + <option name="ALTERNATIVE_JRE_PATH" /> + <option name="SUITE_NAME" /> + <option name="PACKAGE_NAME" /> + <option name="MAIN_CLASS_NAME" /> + <option name="METHOD_NAME" /> + <option name="GROUP_NAME" /> + <option name="TEST_OBJECT" value="CLASS" /> + <option name="VM_PARAMETERS" value="-ea" /> + <option name="PARAMETERS" /> + <option name="WORKING_DIRECTORY" value="%MODULE_WORKING_DIR%" /> + <option name="OUTPUT_DIRECTORY" /> + <option name="PASS_PARENT_ENVS" value="true" /> + <option name="TEST_SEARCH_SCOPE"> + <value defaultName="singleModule" /> + </option> + <option name="USE_DEFAULT_REPORTERS" value="false" /> + <option name="PROPERTIES_FILE" /> + <properties /> + <listeners /> + </configuration> + </component> + <component name="SbtLocalSettings"> + <option name="projectSyncType"> + <map> + <entry key="$PROJECT_DIR$/../../HoppinWorldBackend" value="PREVIEW" /> + <entry key="$PROJECT_DIR$/../../gamestatx_backend/gamestatx_backend" value="PREVIEW" /> + </map> + </option> + </component> + <component name="SvnConfiguration"> + <configuration /> + </component> + <component name="TaskManager"> + <task active="true" id="Default" summary="Default task"> + <changelist id="c61cb26e-cd20-4478-b386-32735fce1844" name="Default" comment="" /> + <created>1533767911688</created> + <option name="number" value="Default" /> + <option name="presentableId" value="Default" /> + <updated>1533767911688</updated> + </task> + <servers /> + </component> + <component name="ToolWindowManager"> + <frame x="12" y="15" width="1896" height="1053" extended-state="0" /> + <editor active="true" /> + <layout> + <window_info anchor="right" id="Palette" /> + <window_info anchor="bottom" id="TODO" order="6" /> + <window_info anchor="right" id="Cargo" /> + <window_info anchor="right" id="Palette&#9;" /> + <window_info id="Image Layers" /> + <window_info anchor="right" id="Capture Analysis" /> + <window_info anchor="bottom" id="Event Log" side_tool="true" /> + <window_info anchor="right" id="Maven Projects" /> + <window_info anchor="bottom" id="Version Control" /> + <window_info anchor="bottom" id="Run" order="2" /> + <window_info anchor="bottom" id="Terminal" /> + <window_info id="Capture Tool" /> + <window_info id="Designer" /> + <window_info active="true" content_ui="combo" id="Project" order="0" visible="true" weight="0.121081084" /> + <window_info id="Structure" order="1" side_tool="true" weight="0.25" /> + <window_info anchor="right" id="Ant Build" order="1" weight="0.25" /> + <window_info id="UI Designer" /> + <window_info anchor="right" id="Theme Preview" /> + <window_info id="Favorites" side_tool="true" /> + <window_info anchor="bottom" id="Debug" order="3" weight="0.4" /> + <window_info anchor="bottom" id="Find" order="1" /> + <window_info anchor="right" id="Commander" order="0" weight="0.4" /> + <window_info anchor="right" content_ui="combo" id="Hierarchy" order="2" weight="0.25" /> + <window_info anchor="bottom" id="Inspection" order="5" weight="0.4" /> + <window_info anchor="bottom" id="Message" order="0" /> + <window_info anchor="bottom" id="Cvs" order="4" weight="0.25" /> + </layout> + </component> + <component name="VcsContentAnnotationSettings"> + <option name="myLimit" value="2678400000" /> + </component> + <component name="editorHistoryManager"> + <entry file="file://$PROJECT_DIR$/.gitignore"> + <provider selected="true" editor-type-id="text-editor" /> + </entry> + <entry file="file://$PROJECT_DIR$/tests/tests.rs"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="1068"> + <caret line="99" column="29" selection-start-line="99" selection-start-column="29" selection-end-line="99" selection-end-column="29" /> + </state> + </provider> + </entry> + <entry file="file://$PROJECT_DIR$/src/lib.rs"> + <provider selected="true" editor-type-id="text-editor"> + <state relative-caret-position="348"> + <caret line="153" column="13" lean-forward="true" selection-start-line="153" selection-start-column="13" selection-end-line="153" selection-end-column="13" /> + <folding> + <element signature="e#4017#4018#0" expanded="true" /> + <element signature="e#4066#4067#0" expanded="true" /> + </folding> + </state> + </provider> + </entry> + </component> + <component name="masterDetails"> + <states> + <state key="ProjectJDKs.UI"> + <settings> + <last-edited>1.8</last-edited> + <splitter-proportions> + <option name="proportions"> + <list> + <option value="0.2" /> + </list> + </option> + </splitter-proportions> + </settings> + </state> + </states> + </component> +</project>+ \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs @@ -37,7 +37,7 @@ where } /// Evaluates the partial function. - /// Returns NAN if no function is defined. + /// Returns None if no function is defined. pub fn eval(&self, x: B) -> Option<O> { let iter = self.funcs.iter().enumerate(); for (i, bounded) in iter { @@ -104,6 +104,7 @@ where } +/// A lower bounded function is a function that is valid from [x..infinite[, or until it hits another function's start. struct LowerBoundedFunction<B, O> where B: PartialOrd, @@ -114,6 +115,17 @@ where pub lower: B, } + +/// A lower partial function is a function that is defined by segments valid from [x..infinite[, or until it hits another function's start. +/// It starts searching at -infinity and goes up to infinity, and takes the last seen function that contains the desired invariable value (x). +/// +/// Example: +/// [0..infinity[ = 5 +/// [1..infinity[ = 10 +/// +/// f(0.5) = 5 +/// f(1) = 10 +/// f(70) = 10 pub struct LowerPartialFunction<B, O> where B: PartialOrd, @@ -121,6 +133,30 @@ where funcs: Vec<LowerBoundedFunction<B, O>>, } +impl<B, O> LowerPartialFunction<B, O> +where + B: PartialOrd, +{ + /// Creates a new LowerPartialFunctionBuilder. + pub fn new() -> LowerPartialFunctionBuilder<B, O> { + LowerPartialFunctionBuilder::new() + } + + /// Evaluates the partial function. + /// Returns None if no function is defined for the searched invariable value (x). + pub fn eval(&self, x: B) -> Option<O> { + let iter = self.funcs.iter().enumerate(); + for (i, bounded) in iter { + let next = self.funcs.get(i + 1); + if x >= bounded.lower && ((next.is_some() && next.unwrap().lower > x) || next.is_none()){ + let f = bounded.func; + return Some(f(x)); + } + } + None + } +} + /// A builder to create an immutable PartialFunction. pub struct LowerPartialFunctionBuilder<B, O> where diff --git a/tests/tests.rs b/tests/tests.rs @@ -80,4 +80,39 @@ mod tests { .with(0.0, 1.0, |x| 5.0) .build(); } + + #[test] + fn lower_partial_normal() { + let f = LowerPartialFunction::new() + .with(0.0, |x| 1) + .with(1.0, |x| 2) + .build(); + assert_eq!(f.eval(-1.0),None); + assert_eq!(f.eval(0.0),Some(1)); + assert_eq!(f.eval(0.5),Some(1)); + assert_eq!(f.eval(1.0),Some(2)); + assert_eq!(f.eval(1000.0),Some(2)); + } + + #[test] + fn lower_partial_inverse_insert() { + let f = LowerPartialFunction::new() + .with(1.0, |x| 2) + .with(0.0, |x| 1) + .build(); + assert_eq!(f.eval(-1.0),None); + assert_eq!(f.eval(0.0),Some(1)); + assert_eq!(f.eval(0.5),Some(1)); + assert_eq!(f.eval(1.0),Some(2)); + assert_eq!(f.eval(1000.0),Some(2)); + } + + #[test] + #[should_panic] + fn lower_partial_overlap() { + let f = LowerPartialFunction::new() + .with(0.0, |x| 1) + .with(0.0, |x| 2) + .build(); + } }