The standard girl library

The standard girl library is a collection of macros, transducers, and signal procedures that are sufficiently useful that they ought to be standardized.  It is implemented in the package girl-library and it exports the following bindings:

Group Types

Group types representing vectors

There are a number of predefined group types that are used to represent vectors.   These are used when one wants to think of the elements of the vector as having names (x, y, z) rather than numeric indicies.  It allows code to distinguish syntactically between Cartesian and polar vectors, for example.

xy-vectors and polar-vectors

xy-vectors are used to represent 2D Cartesian coordinate vectors.  polar-vectors are used to represent 2D polar coordinate vectors.  The accessors for each have been hacked to accept either type of vector.

(xy-vector x  y)
(polar-vector angle magnitude)
(x-of vector)
(y-of vector)
(angle vector)
(magnitude vector)
(polar->xy polar-vector)
(xy->polar xy-vector)
Type conversion.
(squared-magnitude vector)
The squared magnitude vector.
(rotate-xy-vector xy-vector  radians)
Rotates an xy-vector by the specified angle.


rt-vectors are used to represent rotational and translational velocities.

(rt-vector rotation  translation)
(rotation-of rt-vector)
(translation-of rt-vector)
(rt->xy rt-vector)
(xy->rt xy-vector)
Type conversion.  These behave the same as xy->polar and polar->xy, but happen to use rt-vectors.  Note that technically these two data types represent incommensurable quantities, so these operations don't make sense as real type conversions.  None the less, they're fairly commonly used so they're provided here.


mxb-lines are used to represent lines in slope/intercept format.  At some point, we'll add other parameterizations.

(mxb-line slope  intercept)
(line-slope line)
(line-intercept line)
(points->line point1 point2)
Fits a line to two points.  Presently, requires that the line have finite slope.
(line-intersection line1 line2)
Fits a line to two points.  Presently, requires that the line have finite slope.
(point-line-distance point  line)
Returns the (vertical) distance between the point and line.

Other standard group types


Intervals represent closed  intervals in the range [min, max].

(interval min max)
(point-interval value)
(range value  ...)
Constructors for intervals.
(interval-min interval)
Basic accessors for intervals
(interval-empty? interval)
(interval-member? value  interval)
The only useful predicates I could think of on intervals.


interval1 interval2)
interval1 interval2)
interval1 interval2)
Arithmetic operators on intervals
(interval-intersection interval1 interval2)
interval1 interval2)
Set-theoretic operators on intervals.


Samplings represent the way in which a function is to be sampled.  They are used by the sample and histogram procedures.

(make-sampling interval samples)
min max samples)

(sampling-step sampling)
(sampling-interval-size sampling)
Derived attributes of samplings.
(value->sampling-index value  sampling)
(sampling-index->value index  sampling)
Convert between values in the sampled interval and indicies (buckets) to which they map under the sampling.

Standard library procedures and transducers

Time series analysis

(one-shot input)
(one-shot input  pulse-width)
(one-shot input  pulse-width   pulse-spacing)
When called with one argument, outputs true for one clock cycle whenever input transitions from false to true, otherwise outputs false.  When called with two arguments, the output is true for pulse-width milliseconds each time the input transitions from false to true.  When called with three arguments, the transducer stops monitoring the input for pulse-spacing milliseconds after each rising edge .
(integral input normalizer)
Returns the time integral of input divided by normalizer.  The normalizer is provided because girl measures time in milliseconds.  Thus the integral of 1 over 1 second is 1000, not 1.  The default value of normalizer is 1000.0.
(derivative input prescale)
Returns the time derivative of input multiplied by prescale.  The prescale is provided because girl measures time in milliseconds.   If the clock cycle is 100ms and the input changes from 0 to 100 in one clock cycle, then the derivative will be (100-0)/100 = 1, not 1000 as it would be if the unit of time was a second.  The default value of prescale is 1000.0.
(sum input)
Returns the temporal sum of input.  It is like integral, but successive updates to the sum are not adjusted for the clock period.
(delta input)
Returns the temporal difference of input - the difference between the current value of input and the value of the previous clock cycle.  It is therefore like derivative, but its output is not adjusted for clock period.
(hysteresis-threshold input low-threshold high-threshold)
Thresholds input.  The output is #t if input is above high-threshold.  However, the output will remain #t until input falls below low-threshold.   It then remains #f until the input rises above high-threshold again.
(true-time input)
Returns the number of milliseconds for which input has been true.  If the input is false, it returns 0.
(onset input)
True whenever input has just become true.  Equivalent to (one-shot input), however onset is implemented as a modality, so multiple uses of onset on the same argument return the same actual signal.
(termination input)
True whenever input has just become false.  Equivalent to (one-shot (not input)), however termination is implemented as a modality, so multiple uses of termination on the same argument return the same actual signal.
The target update-rate for the main control loop.
The actual measured update-rate for last cycle of the main control loop.

Data storage

(latch input control)
Like a D flip-flip or a sample-and-hold device.  Returns the value of input from the last time that control was true.  That is, whenever control true, it saves the current value of input.  It outputs the last saved value.
(flip-flop set clear &key break-ties  initial-value)
Roughly like a JK flip-flop.  Whenver the input set is active, the output changes to true, whenever clear is active, it changes to false.  When both are false, the output remains unchanged.  When both are true, the output goes true, however, this can be changed by setting the break-ties keyword parameter to #f.  The signal is initially false, unless changed with the initial-value keyword parameter. 
(toggle control  &optional  initial-value)
Output alternates between #t and #f each time control is true.  The default initial value is #f.
(latch-runs input min-run-length)
Outputs the value of the last run of at least min-run-length identical values in the input.  Arguably, min-run-length should have been specified in milliseconds rather than clock ticks.

Signal conditioning

(low-pass-filter input half-life)
A first-order causal low-pass-filter.  Note that half-life must be a constant.
(median3 a  b  c)
Returns the median of a, b, and c.
(temporal-median3 input)
Returns the median of the last three samples of input.
(clip input  low-threshold   high-threshold)
input  low-threshold   high-threshold)   (deprecated)
Returns input, unless it goes outside of the range [low-threshold, high-threshold].  If input falls under low-threshold, clip returns low-theshold.  If it rises above high-threshold, clip returns high-threshold.  Note that the name "clamp" is now deprecated.
(saturate input  level)
Equivalent to (clip input (- level) level).
(suppress-weak input  threshold)
The opposite of saturate.  Returns:
  • input, if its absolute value is over threshold,
  • 0, otherwise.
(dead-zone input  threshold)
The standard control-theoretic dead-zone.  Output is:
  • 0, if the absolute value of input is under threshold,
  • input - threshold, if input is over threshold, and
  • input + threshold, if input is less than -threshold.

Operations on angles

Angles should really be their own data types, but for the moment, they're just represented as numbers.  That means you need to use special operations to normalize them into cannonical ranges (assuming you want to).  The standard library provides normalization operations for angles represented in radians and degress.  Angles can be normalized into signed values or unsigned values.  Signed angles range from -p to +p radians (-180 to +180 degrees), while unsigned angles range from 0 to 2p radians (0 to 360 degrees).

(normalize-degrees degrees)
(normalize-radians radians)
(signed-normalize-degrees degrees)
(signed-normalize-radians radians)
Maps an angle to its canonical signed or unsigned range.

(sign-extend-degrees degrees)
(sign-extend-radians radians)
Maps a canonical unsigned angle to its canonical signed version.  These are special cases of signed-normalize-X for angles that are already normalized as unsigned numbers.

(degrees->radians degrees)
(radians->degrees radians)
Unit conversion.

(subtract-angles-degrees angle1 angle2)
(subtract-angles-radians angle1 angle2)
Subtracts angle2 from angle1 and then normalizes the result as a signed angle.

The obvious constants.

Other scalar procedures

(reduce-signals proc list)
Proc should be a procedure, signal procedure, or transducer and list should be a list of signals.  Returns the result of recursively applying proc pairwise to all the elements of list.
(delay input time)
Returns a version of input that has been delayed by approximately time milliseconds.
(count step? reset?)
step? reset?)
Counts upward each time step? is true.  Resets to zero when reset? is true.  Note that the name "counter" is now deprecated.
(median3 a  b  c)
Returns the median (middle value) of the three values.
(temporal-median3 signal)
Returns the median (middle value) of the last three values of the signal.
(square number)
Returns the square of number.
(sgn input)
Returns +1 if input is positive, -1 if input is negative, or else 0.
(pd-controller input  p-gain  d-gain)
A standard proportional-derivative controller.

Vector operations

Vector operations come in several different flavors.  The naming conventions are as follows:

Performs the x operation on a vector.  The argument is a vector.
Performs the x operation on a segment of the vector.  The argument is a vector, the index of the starting element of the segment, and the length of the segment.
Performs the x operation on a segment of the vector.  The argument is a vector, the index of the starting element of the segment, and the length of the segment.   However, if the segment extends past the end of the vector, it wraps around to the beginning.

Most of the region version are now made redundant by the primitives for extracting regions from vectors.  However, they are maintained for backward compatibility and (arguably) for convenience.

(vector-reduce proc  init  vector)
proc  init  vector  start  length)
proc  init  vector  start   length)
Analogous to reduce or reduce-signals.   Computes the result of applying proc to init and each successive element of vector.  Note that proc must be a primitive procedure, not a signal procedure or a transducer.
(prefix-scan proc  init  vector)
(prefix-backscan proc  init  vector)
Like vector-reduce, but returns a vector containing the reductions of all the prefixes (or suffixes) of the input vector.  Thus (prefix-scan + 0 v) returns a vector of the same length and element type as v whose ith element is the sum of the first i elements of v.   Prefix-backscan is the same except it works backward through the vector, so it returns a vector of reductions over suffixes of the array, rather than of prefixes.
(vector-min vector)
vector  start  length)
vector  start   length)
Returns the minium value of the selected vector or region.
(vector-max  vector)
vector  start  length)
vector  start   length)
Returns the maximum value of the selected vector or region.
(gated-vector-min  vector   predicate-vector default)
  vector  predicate-vector default)
Returns the minumum (maximum) of all the elements of vector for which the corresponding position in the vector predicate-vector is true, or default, whichever is smaller (or larger, respectively).
(vector-arg-min vector)
vector  start  length)
Returns the index of the minium value of the selected vector or region.
(vector-arg-max vector)
vector  start  length)
Returns the index of the maximum value of the selected vector or region.
(vector-min->group vector)
Returns both the minimum/maximum value of the vector and its index.  The result is returned as a group with components index and min (or max).
(vector-centroid vector)
vector  start  length)
vector  start  length)
Computes the centroid of the vector (or vector region), i.e. the sum of vector[i]*i divided by the length of the vector (or region).
(dot-product vector1  vector2)
Returns the sum of the products of the elements of the two vectors.
(vector-range vector)
Returns the range of elements spanned by vector, represented as an interval.
(vector-region vector  start   length)
(vector-region-circular vector  start   length)
Returns the subvector of vector starting with element start and running for length elements.

Sampling operations

(sample function  sampling)
(sample function  min-arg  max-arg   sample-count)
Samples the function function, which may be a primitive procedure or a signal procedure, and returns the samples as a vector.  The procedure takes sample-count samples from min-arg to max-arg.
(histogram vector  sampling)
Returns a histogram of the values of vector, as divided into buckets by sampling.
(histogram-nth-median histogram  n)
Returns a number such that n% of the values in the histogram are less than that number.

Sequencing Macros

(sequence reset?  first-output (condition? next-output) ...)
Returns a signal that begins with first-output, then moves on to each next-output as their respective condition?s become true.  Returns to first-output when reset? is true.
(trt-sequence first-output (condition? next-output) ...)
Always outputs the leftmost output whose associated condition? is false.   Thus, it is like a sequence that can move backward when one of the condition?s becomes false.