Created
November 9, 2022 20:25
-
-
Save MyKo101/52a2c3299237c5bd8db9fc4c8246a782 to your computer and use it in GitHub Desktop.
Function to calculate whether a vector is prime.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # This function will calculate whether a vector is prime. It is not completely efficient, but it's not too bad | |
| isPrime <- function(n){ | |
| # Check inputs are integers, and coerce | |
| if(any(n %% 1 >0)) stop("Input must be all integers") | |
| n2 <- as.integer(n) | |
| # Create default output | |
| out <- rep(NA,length(n2)) | |
| # Check for already discovered primes & return early if possible | |
| out[n2 %in% p_list] <- TRUE | |
| if(all(!is.na(out))) return(out) | |
| # Check for already discovered non-Primes & return early if possible | |
| out[is.na(out) & n2 <= MaxChecked] <- FALSE | |
| if(all(!is.na(out))) return(out) | |
| # Check for divisibility by current prime list | |
| n3 <- n2[is.na(out)] | |
| # Create a divisibility matrix, and sum for any non-zero modulos | |
| is_divisible <- rowSums( | |
| !( | |
| matrix(rep(n3,length(p_list)),nrow=length(n3)) %% | |
| matrix(rep(p_list,each=length(n3)),nrow=length(n3)) | |
| ) | |
| ) > 0 | |
| # Any that are divisble by a previously found Prime, are non-Prime | |
| out[is.na(out)][is_divisible] <- FALSE | |
| if(all(!is.na(out))) return(out) | |
| # Create a sequence from the previous maximum to the new current maximum | |
| NewMax <- max(n2)+1 | |
| new_checks <- seq(MaxChecked+1,NewMax) | |
| # Check values in this new sequence, adding new primes when found | |
| for(c_new in new_checks){ | |
| if(all(c_new %% p_list)){ | |
| # Current checked value is prime, add to list and output | |
| out[n2 == c_new] <- TRUE | |
| out[is.na(out) & (n2 %% c_new == 0)] <- FALSE | |
| p_list <- c(p_list,c_new) | |
| # If all results have now been found, break early | |
| if(all(!is.na(out))) break | |
| } | |
| } | |
| # Re-cache the variables | |
| e <- parent.env(environment()) | |
| e$MaxChecked <- c_new | |
| e$p_list <- p_list | |
| # Any that aren't marked as TRUE or FALSE must be non-Prime | |
| out[is.na(out)] <- FALSE | |
| return(out) | |
| } | |
| # Create a cache in the function's environment | |
| environment(isPrime) <- list2env(list( | |
| # The L here forces the values to be integers (more efficient than numeric) | |
| p_list = c(2L,3L,5L), | |
| MaxChecked = 5L | |
| )) | |
| # First run is slow! | |
| start_timer <- Sys.time() | |
| isPrime(300007) | |
| print(Sys.time() - start_timer) | |
| # Second run is fast because of caching | |
| start_timer <- Sys.time() | |
| isPrime(300007) | |
| print(Sys.time() - start_timer) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment