nixfilter-logicsignal
Version:
Filters for handling (compressing/uncompressing etc.) logic signals
158 lines (136 loc) • 5.4 kB
JavaScript
'use strict';
var Logic_Signal, first_valid_value, get_number_of_repetitions_in_array, greatest_common_divisor, greatest_common_divisor_in_array, is_array, is_object_type, is_of_type, is_string_type, is_valid_value, logic_signal_pattern, logic_signal_regexp, repeat_array;
// Returns true if the passed argument <value> is neither null nor undefined
is_valid_value = function(value) {
return (value !== void 0) && (value !== null);
};
// Returns the first value in <values...> that is neither null nor undefined
first_valid_value = function(...values) {
var i, len, value;
for (i = 0, len = values.length; i < len; i++) {
value = values[i];
if (is_valid_value(value)) {
return value;
}
}
};
// Assuming that array <array> can be constructed by repeating another array n times, returns the largest n
get_number_of_repetitions_in_array = function(array) {
var i, index, j, number_of_repetitions, ref, ref1, ref2, repeated_array_length;
for (number_of_repetitions = i = ref = array.length; i >= 2; number_of_repetitions = i += -1) {
if ((array.length % number_of_repetitions) === 0) {
repeated_array_length = Math.floor(array.length / number_of_repetitions);
for (index = j = ref1 = repeated_array_length, ref2 = array.length; j < ref2; index = j += 1) {
if (array[index] !== array[index % repeated_array_length]) {
break;
}
}
if (index === array.length) {
return number_of_repetitions;
}
}
}
return 1;
};
// Returns the greatest common divisor (GCD) of <first_number> and <second_number>
greatest_common_divisor = function(first_number, second_number) {
return (first_number ? greatest_common_divisor(second_number % first_number, first_number) : second_number);
};
// Returns the greatest_common_divisor (GCD) of all numbers in array <numbers_array>
greatest_common_divisor_in_array = function(numbers_array) {
return numbers_array.reduce(greatest_common_divisor);
};
// Returns true if <value> is an array
is_array = function(value) {
return Array.isArray(value);
};
// Returns a function with <value> argument that returns true if <value> is of type <type_string>
is_of_type = function(type_string) {
return function(value) {
return typeof value === type_string;
};
};
// Returns true if <value> is of type "string"
is_object_type = is_of_type('object');
// Returns true if <value> is of type "string"
is_string_type = is_of_type('string');
// The regular expression pattern of a valid logic signal, as a string
logic_signal_pattern = '^\\s*\\[?(\\s*[+-]?\\d+?(?:,\\s*[+-]?\\d+)*)\\]?(?:\\s*@\\s*(\\d+))?(?:\\s*\\*\\s*(\\d+))?\\s*$';
// The regular expression pattern of a valid logic signal, as a RegExp
logic_signal_regexp = new RegExp(logic_signal_pattern);
// Repeat array <array> <number_of_repetitions> times
repeat_array = function(array, number_of_repetitions) {
var i, index, ref, results;
results = [];
for (index = i = 0, ref = array.length * number_of_repetitions; i < ref; index = i += 1) {
results.push(array[index % array.length]);
}
return results;
};
// This class represents a logic/binary signal
Logic_Signal = class {
constructor(data, cycle_time, repetitions) {
var cycle_string;
if (is_array(data)) {
this.cycles = data;
this.cycle_time = cycle_time;
this.repetitions = repetitions;
} else if (is_object_type(data)) {
this.cycles = data.cycles;
this.cycle_time = data.cycle_time;
this.repetitions = data.repetitions;
} else if (is_string_type(data)) {
data = logic_signal_regexp.exec(data);
this.cycles = (function() {
var i, len, ref, results;
ref = data[1].split(',');
results = [];
for (i = 0, len = ref.length; i < len; i++) {
cycle_string = ref[i];
results.push(parseInt(cycle_string));
}
return results;
})();
this.cycle_time = data[2];
this.repetitions = data[3];
} else {
throw new Error('Logic signal constructor called with invalid arguments');
}
this.cycle_time = first_valid_value(this.cycle_time, 1);
this.repetitions = first_valid_value(this.repetitions, 1);
}
get_unrepeated_timings() {
return this.cycles.map((cycle) => {
return cycle * this.cycle_time;
});
}
get_timings() {
return repeat_array(this.get_unrepeated_timings(), this.repetitions);
}
compress() {
var cycle_time, cycles, repetitions, timing, timings, unrepeated_timings;
timings = this.get_timings();
repetitions = get_number_of_repetitions_in_array(timings);
unrepeated_timings = timings.slice(0, Math.floor(timings.length / repetitions));
cycle_time = greatest_common_divisor_in_array(unrepeated_timings);
cycles = (function() {
var i, len, results;
results = [];
for (i = 0, len = unrepeated_timings.length; i < len; i++) {
timing = unrepeated_timings[i];
results.push(Math.floor(timing / cycle_time));
}
return results;
})();
return new Logic_Signal(cycles, cycle_time, repetitions);
}
to_string() {
return `${this.cycles.join(',')}@${this.cycle_time}*${this.repetitions}`;
}
to_timings_string() {
return this.get_timings().join(',');
}
};
// What this module exports
module.exports = Logic_Signal;
//# sourceMappingURL=logic_signal.js.map