First commit

This commit is contained in:
Timothy Warren 2020-02-12 22:29:57 -05:00
commit 4d15858e45
7 changed files with 356 additions and 0 deletions

141
.gitignore vendored Normal file
View File

@ -0,0 +1,141 @@
# Created by https://www.gitignore.io/api/rust,linux,macos,jetbrains+all
# Edit at https://www.gitignore.io/?templates=rust,linux,macos,jetbrains+all
### JetBrains+all ###
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
# User-specific stuff
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/usage.statistics.xml
.idea/**/dictionaries
.idea/**/shelf
# Generated files
.idea/**/contentModel.xml
# Sensitive or high-churn files
.idea/**/dataSources/
.idea/**/dataSources.ids
.idea/**/dataSources.local.xml
.idea/**/sqlDataSources.xml
.idea/**/dynamic.xml
.idea/**/uiDesigner.xml
.idea/**/dbnavigator.xml
# Gradle
.idea/**/gradle.xml
.idea/**/libraries
# Gradle and Maven with auto-import
# When using Gradle or Maven with auto-import, you should exclude module files,
# since they will be recreated, and may cause churn. Uncomment if using
# auto-import.
# .idea/modules.xml
# .idea/*.iml
# .idea/modules
# *.iml
# *.ipr
# CMake
cmake-build-*/
# Mongo Explorer plugin
.idea/**/mongoSettings.xml
# File-based project format
*.iws
# IntelliJ
out/
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Cursive Clojure plugin
.idea/replstate.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# Editor-based Rest Client
.idea/httpRequests
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
### JetBrains+all Patch ###
# Ignores the whole .idea folder and all .iml files
# See https://github.com/joeblau/gitignore.io/issues/186 and https://github.com/joeblau/gitignore.io/issues/360
.idea/
# Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023
*.iml
modules.xml
.idea/misc.xml
*.ipr
# Sonarlint plugin
.idea/sonarlint
### Linux ###
*~
# temporary files which can be created if a process still has a handle open of a deleted file
.fuse_hidden*
# KDE directory preferences
.directory
# Linux trash folder which might appear on any partition or disk
.Trash-*
# .nfs files are created when an open file is removed but is still being accessed
.nfs*
### macOS ###
# General
.DS_Store
.AppleDouble
.LSOverride
# Icon must end with two \r
Icon
# Thumbnails
._*
# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### Rust ###
# Generated by Cargo
# will have compiled files and executables
/target/
# These are backup files generated by rustfmt
**/*.rs.bk
# End of https://www.gitignore.io/api/rust,linux,macos,jetbrains+all

6
Cargo.lock generated Normal file
View File

@ -0,0 +1,6 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "rusty-numbers"
version = "0.1.0"

9
Cargo.toml Normal file
View File

@ -0,0 +1,9 @@
[package]
name = "rusty-numbers"
version = "0.1.0"
authors = ["Timothy J. Warren <tim@timshomepage.net>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]

58
src/bigint.rs Normal file
View File

@ -0,0 +1,58 @@
//! Arbitrarily large integers
use crate::Unsigned;
#[derive(Debug)]
enum BigIntSign {
Positive,
Negative
}
#[derive(Debug)]
pub struct BigInt {
inner: Vec<usize>,
sign: BigIntSign,
}
impl Default for BigInt {
fn default() -> Self {
Self {
inner: vec![],
sign: BigIntSign::Positive,
}
}
}
impl From<T: Unsigned> for BigInt {
fn from(n: T) -> Self {
let mut new = Self::default();
if n > usize::max_value() {
new.inner = Self.split(n);
}
new
}
}
impl<T: Unsigned> BigInt {
/// Split an unsigned number into BigInt parts
fn split(num: T) -> Vec<usize> {
// Pretty easy if you don't actually need to split the value!
if num < usize::max_value() {
return vec![T::into()];
}
todo!();
}
}
impl BigInt {
pub fn new() -> Self {
Self::default()
}
}
#[cfg(test)]
mod tests {
}

23
src/lib.rs Normal file
View File

@ -0,0 +1,23 @@
#![forbid(unsafe_code)]
pub mod bigint;
pub mod rational;
pub mod seq;
/// Dummy trait for implementing generics on unsigned number types
pub trait Unsigned {}
impl Unsigned for u8 {}
impl Unsigned for u16 {}
impl Unsigned for u32 {}
impl Unsigned for u64 {}
impl Unsigned for usize {}
impl Unsigned for u128 {}
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}

26
src/rational.rs Normal file
View File

@ -0,0 +1,26 @@
use crate::Unsigned;
pub enum FracType<T: Unsigned = usize> {
Proper(T, Frac),
Improper(Frac),
}
pub struct Frac<T: Unsigned = usize> {
numer: T,
denom: T,
}
impl<T: Unsigned> Frac<T> {
/// Create a new rational number
pub fn new(n: T, d: T) -> Self {
Frac {
numer: n,
denom: d,
}
}
}
#[cfg(test)]
mod tests {
}

93
src/seq.rs Normal file
View File

@ -0,0 +1,93 @@
///! Sequences and other 'stock' math functions
///! Calculate a number in the fibonacci sequence,
///! using a lookup table for better worst-case performance.
///
/// Can calculate up to 186 using native unsigned 128 bit integers.
pub fn fibonacci(n: usize) -> Option<u128> {
let mut table: Vec<u128> = vec![];
_fibonacci(n, &mut table)
}
/// Actual calculating function for `fibonacci`
#[inline]
fn _fibonacci(n: usize, table: &mut Vec<u128>) -> Option<u128> {
match table.get(n) {
Some(x) => Some(*x),
None => {
let a = _fibonacci(n - 1, table)?;
let b = _fibonacci(n - 2, table)?;
// Check for overflow when adding
let attempt = a.checked_add(b);
if let Some(current) = attempt {
table.insert(n, current);
}
attempt
}
}
}
///! Calculate the value of a factorial,
///! using a lookup table for better worst-case performance.
///
/// Can calculate up to 34! using native unsigned 128 bit integers.
/// If the result overflows, an error message will be displayed.
pub fn factorial(n: usize) -> Option<u128> {
let mut table: Vec<u128> = vec![0, 1, 1, 2, 3, 5];
_factorial(n, &mut table)
}
/// Actual Calculation function for factoral
#[inline]
fn _factorial (n: usize, table: &mut Vec<u128>) -> Option<u128> {
match table.get(n) {
// Vec<T>.get returns a Option with a reference to the value,
// so deref and wrap in Some() for proper return type
Some(x) => Some(*x),
None => {
// The ? suffix passes along the Option value
// to be handled later
// See: https://doc.rust-lang.org/reference/expressions/operator-expr.html#the-question-mark-operator
let prev = _factorial(n - 1, table)?;
// Do an overflow-checked multiply
let attempt = (n as u128).checked_mul(prev);
// If there isn't an overflow, add the result
// to the calculation table
if let Some(current) = attempt {
table.insert(n, current);
}
attempt // Some(x) if no overflow
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_factorial() {
let res = factorial(34);
assert!(res.is_some());
let res = factorial(35);
assert!(res.is_none());
}
#[test]
fn test_fibonacci() {
let res = fibonacci(186);
assert!(res.is_some());
let res = fibonacci(187);
assert!(res.is_none());
}
}