--============================================================================= --| --| PACKAGE NAME: numbers --| --| PURPOSE: Provide multiple-precision integer type and operations. --| --| PROGRAMMER: Lionel Deimel DATE WRITTEN: 5/20/90 --| DATE OF LAST REVISION: 8/9/90 VERSION: 2.1 --| --| NOTES: The operations provided are extensive, but not exhaustive. --| Uninitialized numbers and numbers resulting from invalid operations are --| "invalid," that is, they have a special representation recognized as --| invalid. Zero is always treated as positive. --| --============================================================================= PACKAGE numbers IS -- Constants related to the representation of numbers: -- Number of digits in representation maximum_number_length : CONSTANT := 60; -- Largest possible radix (must be at least 2) maximum_radix : CONSTANT := 90; -- Maximum number of digits required to represent radix maximum_radix_length : CONSTANT := 2; -- Maximum number of digits required to represent single digit of number maximum_digit_length : CONSTANT := 2; -- Type derivatives of above constants: -- To hold representation of a single digit SUBTYPE digit_string IS string(1 .. maximum_digit_length); -- Range of values possible for radix SUBTYPE radix_range IS natural RANGE 1 .. maximum_radix; -- Range of digit positions (low-order digit numbered 1) SUBTYPE digit_range IS natural RANGE 1 .. maximum_number_length; -- Range of allowable values for individual digits SUBTYPE radix_digit IS natural RANGE 0 .. (maximum_radix - 1); -- Declarations to implement variable-length string representing a number: -- Maximum number of characters in representation of number (allows for -- sign and base) maximum_string_length : CONSTANT := 1 + (maximum_digit_length + 1) * maximum_number_length + 6 + maximum_radix_length; -- Range of length of string SUBTYPE dynamic_string_length_range IS natural RANGE 0 .. maximum_string_length; -- Range of character positions within string (leftmost character numbered 1) SUBTYPE dynamic_string_index_range IS natural RANGE 1 .. maximum_string_length; -- Definition of variable-length string TYPE dynamic_string IS RECORD -- Length of string (possibly 0) length : dynamic_string_length_range; -- Characters of string char : string(dynamic_string_index_range); END RECORD; -- Variable length string representing "Error" invalid_number_string : CONSTANT dynamic_string := (5, ('E', 'r', 'r', 'o', 'r', others => ' ') ); -- Number type TYPE number IS LIMITED PRIVATE; --========================================================================== --| --| FUNCTION NAME: numbers.make_number --| --| PURPOSE: Produce a multiple-precision integer, given a radix and the --| value of a single-digit number in that radix. --| --| PROGRAMMER: Lionel Deimel DATE WRITTEN: 5/21/90 --| DATE OF LAST REVISION: 7/25/90 VERSION: 1.1 --| --| PARAMETERS: --| radix (in) base of number to be created --| --| digit (in) value of number (|digit| < radix) --| --| RETURNS: Multiple-precision representation of digit in base-radix. --| --| INPUT/OUTPUT: None. --| --| ASSUMPTIONS/LIMITATIONS: None. --| --| ERROR CHECKS/RESPONSES: Invalid number returned if digit out --| of range. If digit is negative, negative number is returned. --| --| NOTES: None. --| --========================================================================== FUNCTION make_number (radix : IN radix_range; digit : IN integer) RETURN number; --========================================================================== --| --| FUNCTION NAME: numbers."-" (unary minus) --| --| PURPOSE: Negate multiple-precision integer. --| --| PROGRAMMER: Lionel Deimel DATE WRITTEN: 5/21/90 --| DATE OF LAST REVISION: 8/9/90 VERSION: 1.2 --| --| PARAMETERS: --| a (in) number to be negated --| --| RETURNS: Multiple-precision representation of negation of a. --| --| INPUT/OUTPUT: None. --| --| ASSUMPTIONS/LIMITATIONS: None. --| --| ERROR CHECKS/RESPONSES: None. --| --| NOTES: None. --| --========================================================================== FUNCTION "-" (a : IN number) RETURN number; --========================================================================== --| --| FUNCTION NAME: numbers."abs" --| --| PURPOSE: Take absolute value of multiple-precision integer. --| --| PROGRAMMER: Lionel Deimel DATE WRITTEN: 5/25/90 --| DATE OF LAST REVISION: 7/25/90 VERSION: 1.1 --| --| PARAMETERS: --| a (in) number --| --| RETURNS: Multiple-precision representation of absolute value of a. --| --| INPUT/OUTPUT: None. --| --| ASSUMPTIONS/LIMITATIONS: None. --| --| ERROR CHECKS/RESPONSES: None. --| --| NOTES: None. --| --========================================================================== FUNCTION "abs" (a : IN number) RETURN number; --========================================================================== --| --| FUNCTION NAME: numbers."<=" --| --| PURPOSE: Compare multiple-precision integers. --| --| PROGRAMMER: Lionel Deimel DATE WRITTEN: 5/21/90 --| DATE OF LAST REVISION: 7/25/90 VERSION: 1.1 --| --| PARAMETERS: --| a (in) number --| --| b (in) number --| --| RETURNS: Boolean result of a <= b --| --| INPUT/OUTPUT: None. --| --| ASSUMPTIONS/LIMITATIONS: None. --| --| ERROR CHECKS/RESPONSES: Returns false if either parameter is invalid or --| if the parameters are in different bases, irrespective of their actual --| values. --| --| NOTES: None. --| --========================================================================== FUNCTION "<=" (a, b : IN number) RETURN Boolean; --========================================================================== --| --| FUNCTION NAME: numbers."=" --| --| PURPOSE: Compare multiple-precision integers for equality. --| --| PROGRAMMER: Lionel Deimel DATE WRITTEN: 5/21/90 --| DATE OF LAST REVISION: 7/25/90 VERSION: 1.1 --| --| PARAMETERS: --| a (in) number --| --| b (in) number --| --| RETURNS: Boolean result of a = b. --| --| INPUT/OUTPUT: None. --| --| ASSUMPTIONS/LIMITATIONS: None. --| --| ERROR CHECKS/RESPONSES: Returns false if either parameter is invalid or --| if the parameters are in different bases, irrespective of their actual --| values. --| --| NOTES: None. --| --========================================================================== FUNCTION "=" (a, b : IN number) RETURN Boolean; --========================================================================== --| --| FUNCTION NAME: numbers.convert_to_string --| --| PURPOSE: To convert multiple-precision into a printable string. --| --| PROGRAMMER: Lionel Deimel DATE WRITTEN: 5/21/90 --| DATE OF LAST REVISION: 7/25/90 VERSION: 1.1 --| --| PARAMETERS: --| a (in) number --| --| RETURNS: String representation of the value of parameter a. For --| example, the hexadecimal number -6A4F causes the string --| "- 6 10 4 15 Base 16" to be returned. --| --| INPUT/OUTPUT: None. --| --| ASSUMPTIONS/LIMITATIONS: None. --| --| ERROR CHECKS/RESPONSES: Returns "Error" if parameter a is invalid. --| --| NOTES: None. --| --========================================================================== FUNCTION convert_to_string (a : IN number) RETURN dynamic_string; --========================================================================== --| --| FUNCTION NAME: numbers."-" (binary minus) --| --| PURPOSE: To subtract two multiple-precision integers. --| --| PROGRAMMER: Lionel Deimel DATE WRITTEN: 5/21/90 --| DATE OF LAST REVISION: 7/26/90 VERSION: 2.1 --| --| PARAMETERS: --| a (in) first operand --| --| b (in) second operand --| --| RETURNS: Multiple-precision representation of a - b. --| --| INPUT/OUTPUT: None. --| --| ASSUMPTIONS/LIMITATIONS: None. --| --| ERROR CHECKS/RESPONSES: Returns invalid number if either parameter is --| invalid or if the parameters are in different bases, irrespective --| of their actual values. --| --| NOTES: None. --| --========================================================================== FUNCTION "-" (a, b : IN number) RETURN number; --========================================================================== --| --| FUNCTION NAME: numbers."+" (binary plus) --| --| PURPOSE: To add two multiple-precision integers. --| --| PROGRAMMER: Lionel Deimel DATE WRITTEN: 5/21/90 --| DATE OF LAST REVISION: 7/25/90 VERSION: 1.1 --| --| PARAMETERS: --| a (in) first operand --| --| b (in) second operand --| --| RETURNS: Multiple-precision representation of a + b. --| --| INPUT/OUTPUT: None. --| --| ASSUMPTIONS/LIMITATIONS: None. --| --| ERROR CHECKS/RESPONSES: Returns invalid number if either parameter is --| invalid or if the parameters are in different bases, irrespective --| of their actual values. Overflow generates an invalid result. --| --| NOTES: None. --| --========================================================================== FUNCTION "+" (a, b : IN number) RETURN number; --========================================================================== --| --| FUNCTION NAME: numbers."*" --| --| PURPOSE: To multiply a multiple-precision integer by a single-digit --| number in the same base. --| --| PROGRAMMER: Lionel Deimel DATE WRITTEN: 5/21/90 --| DATE OF LAST REVISION: 7/25/90 VERSION: 1.1 --| --| PARAMETERS: --| f (in) single-digit value in base of a --| --| a (in) number --| --| RETURNS: Multiple-precision representation of f * a. --| --| INPUT/OUTPUT: None. --| --| ASSUMPTIONS/LIMITATIONS: None. --| --| ERROR CHECKS/RESPONSES: Returns invalid number if parameter a is invalid, --| or if the result generates overflow. --| --| NOTES: The value of a may be negative. --| --========================================================================== FUNCTION "*" (f : IN radix_digit; a : IN number) RETURN number; --========================================================================== --| --| FUNCTION NAME: numbers.length_of_number --| --| PURPOSE: To determine the number of digits in a multiple-precision --| integer. --| --| PROGRAMMER: Lionel Deimel DATE WRITTEN: 5/21/90 --| DATE OF LAST REVISION: 7/25/90 VERSION: 1.1 --| --| PARAMETERS: --| a (in) number --| --| RETURNS: Number of digits in representation of parameter a. --| --| INPUT/OUTPUT: None. --| --| ASSUMPTIONS/LIMITATIONS: Parameter a is assumed to be a valid number. --| --| ERROR CHECKS/RESPONSES: None. --| --| NOTES: If a has the value 0, the function returns 1. --| --========================================================================== FUNCTION length_of_number (a : IN number) RETURN digit_range; --========================================================================== --| --| PACKAGE NAME: numbers.search --| --| PURPOSE: To perform searches for PPDIs, including interaction with user. --| --| PROGRAMMER: Lionel Deimel DATE WRITTEN: 7/25/90 --| DATE OF LAST REVISION: 8/8/90 VERSION: 1.1 --| --| NOTES: None. --| --========================================================================== PACKAGE search IS -- Messages to be passed from synchronize to do_search to indicate what -- action has been requested by the user. The meanings of the values is -- as follows: -- -- checkpoint_change change checkpoint frequency -- max_calls_change change frequency of keyboard polling -- status display search status -- continue resume search after user interrupt -- no_interrupt resume search after no user interrupt TYPE interrupt_flag_type IS (checkpoint_change, max_calls_change, status, continue, no_interrupt); --======================================================================= --| --| TASK NAME: numbers.search.process_normal_input --| --| PURPOSE: To read parameters for PDI searches from input file (i.e., --| to implement "normal" input mode) and initiate searches. --| --| PROGRAMMER: Lionel Deimel DATE WRITTEN: 7/31/90 --| DATE OF LAST REVISION: 7/28/90 VERSION: 1.2 --| --| INPUT: (From file "input.dat") triples of integers representing --| PDI searches to be performed. "Input.dat" is a normal text file --| (i.e., of type text_io.in_file). Integers should be separated by --| blanks or new lines. After the third integer of a triple is read, --| the remainder of the line on which it occurs is discarded. The --| integers represent, respectively, the radix, order, and length --| of the PDIs to be searched for. The numbers must be consistent --| with types (and subtypes) numbers.radix_range, natural, and --| numbers.digit_range. --| --| OUTPUT: (To default file) error messages. --| --| ASSUMPTIONS/LIMITATIONS: None. --| --| ERROR CHECKS/RESPONSES: Errors relating to opening and reading the --| input file are trapped and result in error messages being output --| and the program's being terminated. --| --| NOTES: A triple is not read from the input file until previous --| triple have resulted in completed searches. --| --======================================================================= TASK process_normal_input IS --==================================================================== --| --| ENTRY NAME: numbers.search.process_normal_input.start --| --| PURPOSE: To accept signal to start reading input from file --| to direct PDI searches. --| --| NOTES: Only one call to this entry should be made. (Entry for --| synchronization purposes only.) --| --==================================================================== ENTRY start; END process_normal_input; --======================================================================= --| --| TASK NAME: numbers.search.monitor_keyboard --| --| PURPOSE: To read lines from keyboard and call task synchronize. --| --| PROGRAMMER: Lionel Deimel DATE WRITTEN: 7/31/90 --| DATE OF LAST REVISION: 8/1/90 VERSION: 1.2 --| --| INPUT: (From default file) lines, whose exact contents is ignored. --| After each line is read, a call is made to entry --| synchronize.keyboard_interrupt. This task does nothing until --| a call is made to entry begin_keyboard_monitor. --| --| OUTPUT: None. --| --| ASSUMPTIONS/LIMITATIONS: None. --| --| ERROR CHECKS/RESPONSES: None. --| --| NOTES: This task must be terminated with an abort. --| --======================================================================= TASK monitor_keyboard IS --==================================================================== --| --| ENTRY NAME: numbers.search.monitor_keyboard.begin_keyboard_monitor --| --| PURPOSE: To accept signal to start reading input lines. --| --| NOTES: Only one call to this entry should be made. (Entry for --| synchronization purposes only.) --| --==================================================================== ENTRY begin_keyboard_monitor; END monitor_keyboard; --======================================================================= --| --| TASK NAME: numbers.search.synchronize --| --| PURPOSE: To coordinate PDI search and user requests from the --| keyboard. --| --| PROGRAMMER: Lionel Deimel DATE WRITTEN: 7/31/90 --| DATE OF LAST REVISION: 8/1/90 VERSION: 1.2 --| --| INPUT: (From default file ) user commands and associated --| parameters. Commands recognized are "r" (resume search), "s" --| (display status of search), "c" (change checkpoint interval), --| "k" (change keyboard polling frequency), and "q" (quit search). --| Commands "c" and "k" require input of some number of seconds --| (time between checkpoints) and an integer (some number of --| invocations of do_search.start_search.select_digits between --| check for user requests). --| --| OUTPUT: (To default file) prompts for commands and error messages. --| --| ASSUMPTIONS/LIMITATIONS: In order to achieve proper termination, --| this task assumes a call is made to entry start_monitor. --| --| ERROR CHECKS/RESPONSES: Erroneous user input results in error --| messages and reprompts. --| --| NOTES: When "q" command is entered, synchronize aborts tasks --| do_search, monitor_keyboard, and process_normal_input. In other --| cases, synchronize terminates using a terminate option in select --| statement. --| --======================================================================= TASK synchronize IS --==================================================================== --| --| ENTRY NAME: numbers.search.synchronize.start_monitor --| --| PURPOSE: To accept signal to start executing the function of --| package synchronize. --| --| NOTES: Only one call to this entry should be made. (Entry for --| synchronization purposes only.) Call results in call to --| entry monitor_keyboard.begin_keyboard_monitor to initiate --| operation of task monitor_keyboard. --| --==================================================================== ENTRY start_monitor; --==================================================================== --| --| ENTRY NAME: numbers.search.synchronize.check_interrupts --| --| PURPOSE: To allow task synchronize to take user commands and --| execute them or have the caller (task do_search) execute them, --| that is, to coordinate user command processing with the PDI --| search. --| --| PARAMETERS: --| flag (out) message flag returned by --| synchronize to indicate user --| request (see type definition at --| beginning of package for message --| interpretations --| --| interval (out) if command was "c" (and --| therefore flag set to --| checkpoint_change), the new --| number of seconds between --| checkpoints; otherwise meaningless --| --| max_calls (out) if command was "k" (and --| therefore flag set to --| max_calls_change), the new number --| of calls of --| do_search.start_search.select_digits --| between calls to this entry; --| otherwise meaningless --| --| NOTES: When rendezvous completes, task synchronize waits for --| confirmation that the caller has acted on the information --| transmitted by parameter flag. This confirmation is in the --| form of a call to entry clear_keyboard. Only when there --| was no request for service by the user (that is, when flag is --| returned as no_interrupt) is no subsequent call to --| clear_keyboard expected. --| --==================================================================== ENTRY check_interrupts (flag : OUT interrupt_flag_type; interval : OUT duration; max_calls : OUT natural); --==================================================================== --| --| ENTRY NAME: numbers.search.synchronize.keyboard_interrupt --| --| PURPOSE: To accept signal that user has requested service. --| --| NOTES: Rendezvous does not complete until service has been --| provided. --| --==================================================================== ENTRY keyboard_interrupt; --==================================================================== --| --| ENTRY NAME: numbers.search.synchronize.clear_keyboard --| --| PURPOSE: To receive confirmation that information returned --| from rendezvous at entry check_interrupts has been --| appropriately acted upon. --| --| NOTES: See notes for entry check_interrupts. --| --==================================================================== ENTRY clear_keyboard; END synchronize; --======================================================================= --| --| TASK TYPE NAME: numbers.search.(do_search_type) --| --| PURPOSE: To actually perform PDI searches. (Only one task is --| needed. A task type is required, so the storage allocated --| can be set with FOR ... USE.) --| --| PROGRAMMER: Lionel Deimel DATE WRITTEN: 7/31/90 --| DATE OF LAST REVISION: 8/9/90 VERSION: 1.3 --| --| INPUT: (From file "pdi.ckp") if entry --| enter_start_search_from_checkpoint is called, task reads --| a checkpoint record from this file and restarts a search from --| the information in the record. The task terminates when the --| search completes. --| --| OUTPUT: (To default file) search-related messages and results. --| (To file "pdi.ckp") periodic checkpoint records, from which --| a search can be restarted. The entire file is rewritten each --| time a checkpoint record is written, so that the file never --| contains more than a single record. --| --| ASSUMPTIONS/LIMITATIONS: It is assumed that either entry --| enter_start_search_from_checkpoint is called once or entry --| enter_start_search is called zero or more times, once for each --| search to be performed. --| --| ERROR CHECKS/RESPONSES: Problems related to reading the checkpoint --| file result in error messages and task termination. --| --| NOTES: None. --| --======================================================================= TASK TYPE do_search_type IS --==================================================================== --| --| ENTRY NAME: numbers.search.(do_search_type).enter_start_search --| --| PURPOSE: To tell task to perform a particular PDI search from the --| beginning. --| --| PARAMETERS: --| radix (in) base of PDIs sought --| --| order (in) order of PDIs sought --| --| search_length (in) number of digits in PDIs --| sought --| --| NOTES: Entry may be called multiple times. --| --==================================================================== ENTRY enter_start_search (radix : IN radix_range; order : IN natural; search_length : IN digit_range); --==================================================================== --| --| ENTRY NAME: numbers.search.(do_search_type).- --| enter_start_search_from_checkpoint --| --| PURPOSE: To receive signal to begin PDI search using checkpoint --| record in "pdi.ckp". --| --| NOTES: This entry should be called at most once. --| --==================================================================== ENTRY enter_start_search_from_checkpoint; END do_search_type; -- Assure adequate storage is available for search; the number below -- is quite machine-dependent FOR do_search_type'storage_size USE 1_048_576; -- Actual task to perform PDI searches do_search : do_search_type; END search; PRIVATE -- Flag used to indicate invalid number invalid_number_flag : CONSTANT := 1; -- Sign values TYPE sign_type IS (plus, minus); -- To represent digits of number TYPE digit_set IS ARRAY(digit_range) OF radix_digit; -- Representation of number TYPE number IS RECORD -- Base (initialized to invalid value) radix : radix_range := invalid_number_flag; -- Position of leftmost digit high_order_digit : digit_range; -- Sign of number sign : sign_type; -- Digits of number digit : digit_set; END RECORD; END numbers;