Documentation * FAQ * Download * Frink Applet * Web Interface * Sample Programs * Frink Server Pages * Frink on Android * Donate
Frink follows a rapid release schedule and is updated often. That doesn't mean that old programs will be invalidated, but that new, useful features and optimizations are added all the time.
While this page is the most detailed and constantly-updated source of information about changes in Frink, I also announce new features on Twitter at @frinklang. If you want to follow Alan's personal ramblings for some reason, those are on Twitter at @aeliasen.
image constructor from color channels when
    fewer than three color channels are passed in.
  abs function to work with arrays, multidimensional
    arrays, and symbolic values.
  base32Encode[expr, encoding]
     base32Decode[expr, encoding]
     base32DecodeToBytes[expr]
    factor functions to try essentially forever
    instead of timing out after a certain amount of time.
  partitions
    and partitionsOfSize functions.  See
    the Number Theory section of the
    documentation for more.
    
   partitionsOfSize[n, size]
   and partitionsOfSizeCompact[n, size, count=false]
   functions to return only the partitions of a number that
   have size number of elements.
  intersectionSize[set1, set2] to return
    the size of the intersection of two sets as an integer.  This can
    be more efficient than creating an intersection and taking its size.  See
    the Set Functions section of the
    documentation for more information.
   zipShorter[a, b] function to "zip"
    together corresponding elements of lists a
    and b.  Unlike zip, this terminates when the end
    of the shorter of the two lists is reached.  See
    the zip section of the documentation for more.
  img.cropSides[left, top, right, bottom]
   and img.cropSize[left, top, width, height]
   which crop an image and return a new image.  See
    the Image Methods documentation for more.
   graphics object, if you
    hit Cancel on the first (page layout) screen, it will now
    automatically skip the second print screen.
  plutomass, plutoradius,
    plutoyear, and plutoday in the
    standard data file to the lastest best
    values.
  multifor loop to make
    it work better (or at all) in certain conditions.  These conditions
    require that the bounds of one loop depend on the bounds of the loops to
    its left, and require backtracking to ensure that conditions can be met.
    
   next command for multifor
    loops, especially the version with a numbered level to jump to.  It now
    properly ensure loop bounds are enforced and recalculated correctly, even
    when backtracking is necessary.
  image.autocrop[levels=3] now
    takes an optional positive integer argument that determines how different
    that border pixels can be when autocropping.  This may need to be
    increased as high as, say, 127 for JPEG images with lots of artifacts.
  _f[0]) was not replaced with the
    correct literal arguments.
   insertColumn
    and removeColumn for adding and removing columns from
    two-dimensional arrays.  See the Column
     Operations section of the documentation for more details.
  dimensionsWithValues[] function which lists
    dimension types along with their base dimensions, that is pairs
    like ["velocity", 1 m s^-1].
  writeObj was accidentally defined twice so it
    incorrectly wrote a Wavefront .obj file as an STL file.
  negate and reciprocal functions to
    work with arrays, multidimensional arrays, and symbolic values.
   add, subtract, mul,
    divide, power, negate,
    and reciprocal.  These no longer perform a double-eval on
    their arguments.  This may not have been noticeable on numeric or unit
    values, but makes symbolic values work correctly.
    
   formatMatrixVeryCompact to render a 2-dimensional
    matrix with very compact spacing.
  reduceRows).  In other words,
    solution of a system of equations A x = b for x.
   baseUnitNames[] function which returns an array
    of names of the base units in a known order.  For example, this normally
    returns [m, s, kg, A, K, dollar, mol, bit, cd].
   baseDimensionNames[] function which returns an array
    of names of the base dimensions in a known order.  For example, this
    normally returns [length, time, mass, current, temperature, currency,
     amount_of_substance, information, luminous_intensity].
  -u option to a Frink program because it was consumed by the
    interpreter's argument parsing (which interprets -u to
    specify a units file.)  This only affects arguments that had meaning to
    the Frink parser.
    
   apply[function, argList] to more
    safely allow application of a function to an array of arguments.  See the Anonymous Functions section of the
    documentation. 
   
     
      {|x| x^2}[10]
     
     100
    
This is beginning to reek of the dreaded lambda calculus, but is here for symmetry. See the Anonymous Functions section of the documentation.
inputForm, not the previous
    format function[args].
    
   formatTableBoxedHeavy function which can format a
    table with heavy Unicode box-drawing characters separating the
    cells.  See the Formatting Tables
    section of the documentation for details.
   startsWith[string, prefix],
    startsWith[string, prefix, startPos], and
    endsWith[string, suffix] to test if a string starts or
     ends with the specified substrings.  For more information, see the Substrings section of the documentation.
    
   countConnected[startNode] which simply
      counts nodes connected to the specified node.
     shorten[] which simplifies a graph that has lots of long
      runs (like a maze with long hallways) to only include the decision
      points.  This greatly simplifies finding shortest paths in some
      instances.
    DeducerMove that
    can be implemented to enable smarter guesses.  The
    classes wordleDeducer.frink,
    nerdleDeducer.frink,
    and mastermindDeducer.frink
    have been updated to give smarter guesses.
  nthPrime[n] which returns the
    nth prime number (indexed from 1, that is, nthPrime[1]
    returns 2 and nthPrime[2] returns 3.)
    
   chunks function when there isn't even enough
    data to fill a single chunk.
    
   Cache-Control headers to the output of Frink
    Server Pages to help break unwanted caching of pages (and especially
    graphics) whose output changes each time they are loaded even if there
    is no input. 
  charList function.  It now uses a cache to efficiently
    return results.
    
   joinstr function to join elements of an array with
    no space separating elements.  This is equivalent
    to join["", array] 
  chunks functions to break an enumerating expression
    into a series of chunks of the specified size. See
    the Enumerating Expression
    Functions sections of the documentation for more.
  byColumns[array of int] which
    allows you to easily sort a multi-dimensional array based on multiple
    columns.  That is, if the first column compares equal, it then tries
    sorting by a second column, etc.   For example,
    sort[list, byColumns[[0,1]]].  See
    the sorting section of the
    documentation for examples.
   byColumn and byColumns functions.
  hypotenuse[array] to return the
    hypotenuse or Euclidean norm of an array of values.  This also works with
    symbolic values.
  ComplexArray and ComplexArray2D.  These are not
    documented yet but are used in image transformations.
    
   sqrtNearestInteger[x].
    
   sqrtNearestInteger[x] which is a
     fast function that takes a non-negative integer and returns the largest
     integer less than or equal to the square root of x.
     
   lexicalSort and lexicalCompare functions
    now compare the elements of sub-arrays to help sort them.  For
    example, [1,2,3] sorts before [2,1,3].
  inputForm output formatter for some multi-line
    anonymous functions, especially those containing a single if
    statement.
  read, lines
    and readLines when called with an HTTP or HTTPS URL.
    
   .jar file, even when in restrictive security mode.
    
   image.ANSI[columns=60] methods to
    display an image as ANSI graphics has been improved to not widen an image
    beyond its original width (which might make way-too-long images if the
    original was tall and narrow.)
   ls program (which lists files) but displays the contents
    of images in a command terminal!  This is very useful for someone who
    works on the command-line.
   frink.graphics.VoxelArray.makeSupertoroid when rx !=
    ry.  See Frink's 3-D routines for more.
   graphics.ANSI[columns=60]
    and image.ANSI[columns=60] methods to display a
    graphics object or an image as ANSI graphics. The terminal must support
    true-color ANSI and Unicode block characters.  This allows you to preview
    a graphic even over an SSH connection with no graphics capability.
  image.toColorChannels[] to turn an
    image into an array of 4 ComplexArray2D objects representing
    the red, green, blue, and alpha channels of an image.  The class returned
    may change in the future.  This array can be turned back into
    an image using the constructor new
    image[array].
  eval function).  All URLs are now
    restricted (previously, some types were allowed, while file URLs have
    always been restricted.)
    
   nth0[expr, index]
    and nth1[expr, index] which return the nth item
    of a list.  nth0 treats the first element as element 0,
    while nth1 treats the first element as element
    1.  nth0 was formerly called nth which is still
    there but deprecated.
  mean[list]), mean and standard
    deviation (meanAndSD[list, sample]), and
    mode(s) (modes[list]) of a list.  These preserve units
    of measure and can even be used symbolically.  See
    the Other Functions section of the
    documentation for details.
   meanAndSD has been
    removed from several sample programs where it had been cut-and-pasted, as
    it is now part of Frink's built-in functions.  This
    includes curveFit.frink,
    LeastSquares.frink,
 and
    statistics.frink.
   image.circularBlur[radius] which
    performs a circular blur on an image and returns a new image.
  image.applyKernel[matrix, normalize].
    The boolean argument normalize allows the user to specify if
    the brightness levels in an image will be normalized.
    If normalize is false, values outside the range 0 to 255 will
    just be clamped to fit in that range.  This may result in a blank image!
    However, some implementations of, say, edge detect filters do not
    normalize their output and this allows results to look more like other
    implementations.  If normalize is true, the ranges will be
    normalized to fit into the range 0 to 255, possibly decreasing contrast.
   image.normalize[] to normalize the brightness
    levels of an image so that color brightnesses range from 0 to 255.
   image.applyKernel[matrix]: After
    the image has been filtered, it previously underwent a normalization of
    the brightness of the channels so that they fit within the range [0,255].
    That normalization process has been improved and modified.  Previously,
    each color channel was normalized independently, which distorted relative
    colors (and made images "grayer".)  Colors are now normalized in a way
    that preserves relative colors.
    Note: If the elements of the matrix sum to (approximately) 1, then the average brightness of each pixel in the result should be about the same as in the original image, and pixel values outside the range [0,255] will be clamped to that range instead of being normalized. This preserves the color range of most pixels. However, if the elements of the matrix do not sum to 1, the color channels will be normalized so that they fall within the range [0,255] so the result is displayable. The relative brightness of each color channel is now preserved so colors are less uniform and gray.
negate[x] function.
   graphics.caption[text,
      align="bottom", angle=0 degrees] to add quick text to the
      specified side of a graphics object.  align is
      optional but defaults to "bottom".  If
      specified, align must be one of the following
      strings: "top", "bottom", "left",
      or "right" indicating the side of the graphic where the
      text will be placed.  See the Graphics
      with Text section of the documentation for more information.
  GammaByParts.frink and Gamma.frink have been
    removed and should be considered obsolete.
  factorUnits[unit] which factors a
    unit into a array of [scale, dimensions]
    where scale is a dimensionless number indicating a scale
    and dimensions is a unit with scale of 1 and the basic
    dimensions of the original unit.
  digitLength[num] to return the
    number of decimal digits in a number.  It works on floating-point numbers
    which makes it useful for arbitrary-precision functions.
   arbitraryExp
    and arbitraryLn functions
    in  ArbitraryPrecision.frink
    to be much faster and more accurate.  This improves the performance of other
    arbitrary-precision functions such as arbitraryPow.  This
    requires the digitLength function above.
   methods[expr] function is now
    sorted.
   image.applyKernel[array2d]
    method to apply an arbitrary filter / kernel to an image and return a new
    image.   See the Image Methods documentation
    for more.
  image.edgeDetect[] which applies an edge
    detect filter to an image and returns a new image.
  image.unsharpMask[width, amount]
    which performs an unsharp mask on an image (sharpening the image) and
    returns a new image.  Amount is usually 1 for 100% sharpening, but can be
    lower or higher.
   image.gaussianBlur[width] which
    performs a Gaussian blur on an image and returns a new image.
  VoxelArray.makeSupertoroid where
    the eccentricity of the smaller circle was a floating-point number that
    triggered numerical instability of the underlying algorithm.  This often
    manifested as the inner part of the toroid not being rendered.
    See Frink's 3-D routines for more.
  img.mirrorX[]
    and img.mirrorY[] to flip an image horizontally or
    vertically. See the images documentation for more.
  allShortestDistances[startNode] algorithms to
    Graph.frink, which finds all
    possible distances from the start node to all reachable nodes.
  Writer.printAndClose[expr] method to quickly
    write and close a file.
  allEqual[list, target]
    Returns true if all of the items in the EnumeratingExpression
    list are equal to target.  See
    the Enumerating Expression
    Functions sections of the documentation for more.
  lastIndexOf[str, substr]
    and lastIndexOf[str, substr, startPos]
    .  For more information, see the Substrings section of the documentation.
  .copyAndPut[value]
    and .copyAndRemove[value].  For more information, see
    the Sets section of the documentation.
  sverdrup.  Thanks to Ken
    Mankoff for the report.
   permutationCount[m,n] function which returns
     the number of permutations of m things being
     taken n at a time, with order being important. This is
     sometimes called "mPn".  This is equivalent to m!/((m-n)!)
     but calculated efficiently by calling factorialRatio[m,m-n]
     internally.
  VoxelArray.makeSphere when
    coordinates were just so in Frink's 3-D routines.
  getBitBool[num,
      bit] function to return the specified bit of an
    integer as a boolean value.
  electric_resistivity with
    dimensions ( ohm m ) and its reciprocal electric_conductivity
    with dimensions 1 / (ohm m) for use of bulk properties of materials (which
    is relevant to the current "superconductor" discussion.)
  VoxelArray.union methods now allow you to pass in up
    to 1 undef argument in which case the non-undef
    object will be copied.  This makes it easier to make unions of
    multiple objects.  See Frink's 3-D routines.
   planarEmboss method to
    Frink's VoxelArray class.  These allow you to emboss a bitmap
    into the top of an object and add or remove from the surface of the object
    with variable depth based on the gray level of the pixels..  This
    lets, you, say, etch text or images or textures into an object.
    See Frink's 3-D routines.  Also see the sample
    programs
    planarEmbossTest.frink
    for an example of its use.
  parseInt[str, base] function can now
    take an array (or other enumerating expression) of strings as input.
  sphericalEmboss
    method to Frink's VoxelArray 
    class.  These allow you to "wrap" a bitmap around any object and add or
    remove from the surface of the object with variable depth based on the
    gray level of the pixels..  This lets, you, say, etch text or images
    or textures into an object. 
    See Frink's 3-D routines.  Also see the sample programs
    sphericalEmbossGrayTest.frink
    for an example of its use.
   cylindricalEmboss
    method to Frink's VoxelArray 
    class.  These allow you to "wrap" a bitmap around any object and add or
    remove from the surface of the object with variable depth based on the
    gray level of the pixels..  This lets, you, say, etch text or images
    or textures into an object. 
    See Frink's 3-D routines.  Also see the sample programs
    cylindricalEmbossGrayTest.frink
    for an example of its use.
   unzip function to
    seperate the columns of an array or other enumerating expression into
    seperate arrays.
  ConformanceException when formatting some
    multiplication and exponentiation expressions which had units with
    dimensions as their first argument.
  This is a large release that includes many improvements that couldn't be released without some internal infrastructure changes. Apologies for the delays.
allDifferent constraint.
      
     allDifferent constraint to solve any Sudoku
      problem, no matter how difficult (and find all possible solutions if
      there are multiple solutions) in just a few lines of code.
     For example, see this quadratic equation solver.
floodFill method to Frink's VoxelArray
    class.  This allows you to fill an object and, say, compute its volume.
    See Frink's 3-D routines.  Also see the sample program
    floodFillTest.frink
    for an example of its use.
   cylindricalEmboss and sphericalEmboss
    methods to Frink's VoxelArray 
    class.  These allow you to "wrap" a bitmap around any object and add or
    remove from the surface of the object where the pixels in the bitmap are
    dark.  This lets, you, say, etch text or images into an object.
    See Frink's 3-D routines.  Also see the sample programs
    cylindricalEmbossTest.frink
    and sphericalEmbossTest.frink
    for an example of their use.
   newJavaArray[classname, length, initValue]
    This is much simpler than doing the same thing in Java, especially when initializing multidimensional arrays!
allSame[expr]
    and allDifferent[expr] functions to test if all the
    elements of an array or other Enumerating Expression are same or different
    respectively.  See
    the Enumerating Expression
    Functions sections of the documentation for more.
  read, readLines, and lines to
    allow reading from more Java data types
    including java.io.File, java.io.InputStream,
    and java.net.URL.
   getSymbolsAsSymbols[expr] function.
  minmax[array] function to return the smallest
    and largest items in an array simultaneously.  The return value is a
    two-item array [min, max]
  frink-tng.war file from Frink: The Next Generation
    (version 2022-12-31).
  | Factor | Name | Symbol | 
|---|---|---|
| 1030 | quetta | Q
      | 
| 1027 | ronna | R
      | 
| 10-27 | ronto | r
      | 
| 10-30 | quecto | q
     | 
See Resolution 3 of the 27th CGPM (2022) (link opens in a new window) for more details.
findShortestPath... algorithms to
    ensure that the start node and end node are actually in the graph.
   findShortestPath...
    algorithms now reliably return undef if there is no path from
    the start node to the end node.  Previously, they could loop forever or
    throw errors inside the methods.
   dump method to print an indented text representation of a
    Tree's structure.
  frink-tng.war file from Frink: The Next Generation
    (version 2022-12-08).
  array.transpose[] no longer fails on an empty array.
   I have a feeling that the Advent of Code problems will have a knapsack-packing problem this year. Day 3 was about rucksacks...
gasoline to match
    U.S. EPA definitions for the MPGe (miles per gallon electric).  The MPGe
    was defined to be the number of miles that can be traveled by an electric
    vehicle using 33.7 kWh of energy.  This changes the energy density in the
    unit gasoline from 1.4e8 J/gallon (which is about 38.88
    kWh/gallon) to 33.70 kWh/gallon.
    The previous definition may have been more accurate for very efficient combustion of gasoline, but this makes it match with EPA definitions and the MPGe. Please see the standard data file for more information about this change and to see current uncertainties and historical variations in the energy content of gasoline and other fuels.
MPGe and its synonym mpge (for
    symmetry with the existing all-lowercase mpg) to represent
    miles per gallon electric.  This unifies the current definition of the
    unit gasoline to match the MPGe.
    For example,
     100 MPGe -> miles/(gallon gasoline)
     100.0
    
array.shuffle[] now returns the shuffled
    array so methods can be chained.
   trim[string] function can now be applied to
    arrays of strings.
   array.get[index,
     altValue] which can be used to look up the value
    corresponding to the non-negative integer index or return the
    alternate value altValue if the array does not contain that
    index.
  readBytes[url] function to read to an array
    of byte.
   read function for better error-handling.
    
   base64Encode[expression, encoding,lineLength]
    to work correctly when expression is a Java array of bytes
    and the encoding is undef.
    
   getColumn and setColumn methods and
    functions for two-dimensional arrays.  See
    the Column Operations section of the
    documentation for more details.
  mostCommon[vals]
    and leastCommon[vals] which are specializations of
    the countToArray[vals] that only return the most or
    least common item(s) in a collection. See
    the Enumerating Expression
    Functions sections of the documentation for more.
   columnize[array, columns] function
    which turns a one-dimensional array (or enumerating expression) into a
    two-dimensional array with columns number of columns.  This
    can be used with the table formatting functions above to pretty-print a
    large array in columns for display.  See
    the Formatting Tables section of the
    documentation for details.
  a cos[x]2 plus b sin[x]2 terms to the trignonometric solvers
    in solveTrigonometric.frink.
    These can now solve equations like cos[x]^2 - 13 sin[x]^2 = 10 tan[z/4].
  cos[x]
    and sin[x] terms to the trignonometric solvers
    in solveTrigonometric.frink.
  paintAlongHull method to
     Frink's VoxelArray class.  This allows you to move a tool
     along the hull of a 3-D object, adding or removing material from the
     object and making larger or smaller.  This can be used to give a
     "rounded" shape and is similar to the Minkowski sum method in tools like
     OpenSCAD.  See Frink's 3-D routines.
    
   URLDecode[str, encoding="UTF8"] to
    decode part of a URL.
    
   URLEncode[str, encoding="UTF8"] to
    encode part of a URL.
  lcm[array] which returns the least
      common multiple of an array
      (or enumerating expression) of
    integers.
    
   gcd[array] which returns the
      greatest common denominator of an array
      (or enumerating expression) of
      integers.
  
     
      for c = "a" to "z"
     
         print[c]
     abcdefghijklmnopqrstuvwxyz
    
     
      for c = "z" to "a" step -1
     
         print[c]
     zyxwvutsrqponmlkjihgfedcba
    
formatMatrixCompact function which can format a
    table with Unicode bracket characters making traditional matrix brackets
    surrounding it.  This is smaller than formatMatrix. See
    the Formatting Tables section of the
    documentation for details.
  java.util.Comparator that uses a Frink function to perform
    the comparisons.  See
    the Iterating over Java
     Collections section of the documentation for more.
  dict.get[key, altValue=undef]
    which be used to look up the value corresponding to the key or return the
    alternate value altValue if the dictionary does not contain
    that key.  See the Dictionary Methods
    section of the documentation for more.
   nth function when
    requesting an item off the end of an enumerating expression.
  char[array] that changed its
    behavior by returning an array of separate characters.
  CoordinateTransformer3DFloat.IDENTITY public.  This
    class was very useful
    in Advent of Code 2021 Day
    19.
    
   dict.increment[key] which is similar
    to the two-argument
    dict.increment[key, increment]
    but which always increments by 1.
  frink.graphics.Point3DFloat objects in
    Frink's VoxelArray class.  See Frink's 3-D 
     routines.
  toASCIIHigh[str] to convert a string
    to a 7-bit ASCII safe representation that can be passed as input to
    Frink.  This differs from the existing toASCII[str] in
    that it keeps high Unicode codepoints (above \uFFFF) as a
    single Unicode codepoint in a format that looks
    like \u{1F384}.
   isNegativeUnit[expr] function which returns
    true if the expression is a unit of any kind (including dimensionless
    numbers) with a negative sign, false otherwise.
   formatBracketsCompact[expr] to
    format a table surrounded by Unicode square bracket characters, or
    ordinary square brackets if it fits into a single line.  Brackets are now
    smaller (putting brackets only on the sides) and use better Unicode
    characters. See the FormattingTables
    section of the documentation for details.
   rotateLeft and rotateRight to
    rotate the bits of an integer left or right by a specified number of bits.
    See the Number Theory section of the
    documentation for more information.
   secant[x] in some cases.  Thanks to
    Dr. Alberto Di Lullo for the bug report.  Additional contributions to
    making these functions even more robust are welcome.
   byColumn[int] and passing that as a
    sorting function.  The column number is zero-based.  For example,
    sort[list, byColumn[1]].  See
    the sorting section of the
    documentation for examples.
  VoxelArray.makeSphere in
    Frink's VoxelArray class.  See Frink's 3-D
    routines.
  formatBracketsCompact[expr] to format
    a table surrounded by Unicode bracket characters, or ordinary
    parentheses if it fits into a single line.  See
    the FormattingTables section of the
    documentation for details.
   getOperatorSymbol[expr] which
    returns the symbol for an expression that represents a mathematical
    operator like "+" or "*" as a string.  See
    the Other Functions section of the
    documentation for details.
    
   formatParens[expr]
    and formatParensCompact[expr] to format a table
    surrounded by Unicode parenthesis characters.  See
    the FormattingTables section of the
    documentation for details.
  isOperator[expr]
    and getOperatorPrecedence[expr] to determine if an
    expression represents a mathematical operator like +
    or *.  See the Other Functions section of the documentation
    for details.
   java.util.Comparator
    to perform the comparisons
    (e.g. java.util.PriorityQueue,) you can get Frink's
    default Comparator (which follows the same semantics as
    Frink's <=> three-way
    comparison operator,) by calling getDefaultComparator[].
    Frink's default comparator will also compare Java objects that implement
    the java.util.Comparable interface so it can be used for
    Frink and Java data types.
   VoxelArray class to create a variety of shapes.
    See Frink's 3-D routines.
   VoxelArray functions to correctly use the new
    extended range allowed by the new BiggerBitSet
    implementation.
   getNextSetBitIndex
    and getPreviousSetBitIndex methods
    to VoxelArray.
   getMinSetZ and getMaxSetZ methods
    to VoxelArray.
  VoxelArray for 3-D
    printing.  Most importantly, it was rewritten to use an improved BitSet,
    called BiggerBitSet.
   BiggerBitSet is an improvement on Java's java.util.BitSet
    class in a few ways:
    BiggerBitSet uses long instead
      of int to address bits in its API which greatly increases
      the size of bits addresable.  The implementation of BitSet allows a
      maximum number of pixels of (2^31 - 1) or 2147483647, which is about 2
      billion pixels.  If 3-D printing at a resolution of 0.1 mm/pixel, this
      gives a maximum size of about 5.07 inches on a side.
      
       ((2^31-1))^(1/3) 0.1 mm -> in
      
This is not quite big enough to fit a modern 3-D printer's bed.
With this class's API, the number of pixels is increased by a factor of 64. The calculation is:
       ((2^31-1) * 64)^(1/3) 0.1 mm -> in
      
which gives a cube of about 20 inches on a side. This is enough of an improvement to warrant the class.
BiggerBitSet does not not allow itself to be
       dynamically resized; this should give a performance improvement over
       BitSet.  BitSet takes a lot of effort to check dynamic ranges, to
       validate invariants and resize with every set operation.
      BiggerBitSet is constant across Java releases and
       implements functions (especially those to set a range of values quickly
       and efficiently) which did not exist in earlier versions of Java's
       BitSet.
    dict as the key in a dictionary, add it to
    a set, etc.  Be sure not to modify the dictionary after
    inserting it into another data structure, or results will be undefined
    (and probably wrong.)
    
   VoxelArray class, to create a variety of
    shapes.  See Frink's 3-D routines.
  & was
    encoded incorrectly using HTML encoding rules instead of the necessary
    JavaScript encoding rules.
  VoxelArray class, to create a variety of shapes.
    See Frink's 3-D routines.
   earthvolume in the
    standard data file.
  charName and charNames functions to
    return an empty string (rather than a null or crashing) if a Unicode
    codepoint is undefined or if the Java Virtual Machine does not know its
    name (JVMs lag far behind the latest Unicode definitions.)
  makeSupertoroid to
    Frink's VoxelArray class, to create a torus or other members
    of the toroid family.  See Frink's 3-D routines.
   VoxelArray.construct to
    be double instead of float for flexibility.
    See Frink's 3-D routines.
   VoxelArray
    class, to extrude an image or text onto a specific plane.
    See Frink's 3-D routines.
   VoxelArray
    class, fillCube which draws a 3-D cuboid.
    See Frink's 3-D routines.
   img.getPixelGrayInt[x,y] to
    return the color of a pixel as a grayscale from 0 to 255 inclusive.  This
    is meant for quick processing and does not perform any perceptual
    encoding. See the images documentation for more.
   VoxelArray
    class, strokeZTapered which allows drawing in 3-D along a
    polyline or polygon with a tapered tool.  See Frink's 3-D
     routines.
   polygon.isInside[x, y] method
    to test if a point is inside a polygon using the even-odd rule.
    See Polygon Methods for more information.
  Matrix class is still woefully incomplete
    but feel free to contribute unimplemented functions!
  charName
    and charNames functions.  For example:
    
     charNames["\u{1f63a}!"]
     [SMILING CAT FACE WITH OPEN MOUTH, EXCLAMATION MARK]
    
symmetricDifference[a, b]
    which calculates the "symmetric difference", also known as the
    "disjunctive union" of sets a and
    b.  In other words, the new set contains only the elements
    that are in either set a or b but not
    in both.  For example, the symmetric difference of the sets {1,2,3} and
    {3,4} is {1,2,4}.
    For more information, see the Sets section of the documentation.
NoClassDefFoundError
    for frink.graphics.FrinkImage.  The problem was caused by the
    obfuscator.  Thanks to Ty Boyack for the report.
    
   formatTableInput function to format a
    2-dimensional table into
    Frink's inputForm so that it can
    be parsed by Frink, passed to the eval
    function, pasted into a Frink program, etc.  See
    the Formatting Tables section of the
    documentation for details.
   addLeap that
    manifested as a NoClassDefFoundError
    for frink.date.LeapSeconds.  The problem was caused by the
    obfuscator.  Thanks to Tobias Jordan for the report.
   frink.gui.FrinkStarter class,
      the -1 command-line option will start Frink in one-line
      input mode (default is two-line input mode).  This is similar to
      starting Frink and choosing the menu item Mode | One-Line or
      hitting Ctrl-1.
     frink.gui.FrinkStarter class,
      the -3 command-line option will start Frink in multi-line
      input mode (default is two-line input mode).  This is similar to
      starting Frink and choosing the menu item Mode | Multi-Line or
      hitting Ctrl-3.
     rest[array] function that
    produced a program crash.
   setBit[n, bit] which
    sets the specified bit of a number (least significant bit is 0) to 1 and
    returns a new number. This is equivalent to
    bitOr[n, shiftLeft[1, bit]]
   clearBit[n, bit]
    which clears the specified bit of a number (least significant bit is 0) to
    0 and returns a new number. This is equivalent to
    bitAnd[n, bitNot[shiftLeft[1, bit]]]
   flipBit[n, bit]
    which flips the specified bit of a number (least significant bit is 0) and
    returns a new number. This is equivalent to
    bitXor[n, shiftLeft[1, bit]]
   graphics object into a
    bitmapped image:
    
    
     
      graphics.toImage[width, height]
     
    
     which is identical to the image constructor:
    
     
      new image[graphics, width, height]
     
    
graphics object
    into an image, now if exactly one
    of width or height are specified
    as undef, and the other is an integer, the size of the
    undefined axis will be calculated from the defined width or height and the
    aspect ratio of the graphics that is being drawn.
   FrinkImageExpression to be used where
    a FrinkImage is required.  This enables some features in 3-D
    printing, notably extruding an image to 3 dimensions.
   VoxelArray which contains a lot of methods for drawing
     primitives (like cubes, spheres, cylinders, capped cylinders, tapered
     cylinders,) performing constructive solid geometry (that is, taking the
     intersection of two objects, the union of two objects, or the difference
     of two objects,) extruding images and text, and more.
   voxel.
    For older programs that render Wavefront .obj file formats
    directly, search
    for wavefront.
   extrude method to the VoxelArray
    class which allows you to extrude the black pixels of an image as a 3-D
    object.
    See extrudeTest.frink for a sample of its usage.
  formatMatrix function which can format a table
    with Unicode box-drawing characters making traditional matrix brackets
    surrounding it.  See
    the Formatting Tables section of the
    documentation for details.
      
   b = [[1,2], [3,10]]
  
    println[formatMatrix[b, "right"]]
   
      
┌     ┐
    
│1   2│
│     │
│3  10│
└     ┘
     
formatTableBoxed function which can format a table
    with Unicode box-drawing characters separating the cells.  See
    the Formatting Tables section of the
    documentation for details.
    
     b = [[1,2], [3,10]]
    
      println[formatTableBoxed[b, "right"]]
     
   
┌─┬──┐
  
│1│ 2│
├─┼──┤
│3│10│
└─┴──┘
   
approxLn function
   in  ArbitraryPrecision.frink
   (and all the functions that depend on it.  This performance will be most
   evident in Frink: The Next Generation.
   image.autocrop[] which
    automatically crops the sides of an image where the pixels are
    approximately equal.  This returns a new image.
  Writer.println[]
    method which may have caused the error message
    "AbstractExpressionFormatter.formatUnknown passed null expression!" to be
    displayed to the user and possibly written into the file.
  Planet.Mars
    were accidentally the radius and mass of planet Earth.  Please update.
    
    
     This did not affect anything about the orbit or position of Mars, nor did
     it affect the constants marsradius nor marsmass
     in the standard data file; it just exposed itself when accessing
     the planets.frink library
     and requesting the fields Planet.Mars.radius
     or Planet.Mars.mass
    
dict.keys[]
    and dict.values[] to let you enumerate through the
    keys and values of a dictionary.  (There was already
    a keys[dict] function.)  See
    the Dictionary Methods section of the
    documentation for more.
  SaturnRingPosition was renamed
      to SaturnEphemeris and calculates more parameters.
     rest[expr, num] returns
    everything after the first num elements of an array
    or enumerating expression.  If the expression passed in is an array, the
    result is an array, otherwise it is a (possibly-infinite) enumerating
    expression.  This is the opposite of
    first[expr, num]
    See the Slicing Arrays and Enumerating Expression Functions sections of the documentation for more.
trit in the standard data
    file. It was incorrectly listed as dimensionless, and should have had
    dimensions of bits.  Thanks to Adam Haun for the correction.
  /uU regex options essentially unnecessary and obsolete.
    
   [[:Alpha:]]
    and [[:Digit:]] are no longer available and have been
    replaced with Unicode regular expression classes as specified
    in Unicode
    Technical Standard 18: Unicode Regular Expressions.  See
    the Regular
    Expression Replacement documentation of Frink:TNG.
   wordList, lineBreakList,
    and sentenceList now have two-argument versions that allow you
    to specify a language specifier which
    uses different human language's rules for detecting words, sentences, and
    places to break lines.  See
    the Correct String Parsing
    section for details.
   countToArray[expr]
    and countToDict[expr] functions that count the
    number of times that each element occurs in an array or
    other enumerating expression and
    returns the number of occurrences of each item.  The array version returns
    an array with the most common items first.  These can be used to
    easily build frequency tables.  See
    the Enumerating Expression
    Functions for more details.
  formatTable function now can take any enumerating
    expression, instead of just an array as its input.  See
    the Formatting Tables section of the
    documentation for details.
   formatTable function can format a one-dimensional
    array into column form.  See the Formatting
     Tables section of the documentation for details.
   formatTable functions.
   array.isEmpty[]
    and array.peek[] which are useful when using an array
    as a stack.  See the Pushing and
     Popping section of the documentation for details.
    
   matrix.formatMatrix[]
     which use the new formatTable function to format a matrix
     that really looks like a matrix, complete with efficient use of space and
     Unicode box-drawing brackets.  The Matrix class is
     still woefully incomplete but feel free to contribute unimplemented
     functions!
    
   array.dimensions[] method to return the
    dimensions of a possibly-multiple-dimension array.  See
    the Dimensions array method documentation for
    details.
  join, joinln, etc.
    formatSci[value, divideBy, decPlaces]  (Scientific
        notation)
     formatEng[value, divideBy, decPlaces]  (Engineering
        notation)
     formatSig[value, divideBy, decPlaces]  (Significant
        figures)
     formatFixed[value, divideBy, decPlaces]  (Fixed
        decimal places)
    inputFormUnicode
    formatter that is like inputForm
    but assumes you have a working Unicode environment and does not escape
    non-ASCII characters.
  concat[array1, array2] function that
    concatenates the elements of two arrays (or other enumerating
    expressions.)  For now, the result is always an array, but this may change
    to be more memory-efficient by letting arbitrary enumerating expressions
    to follow each other.
  \uHHHH which matches a
      specified Unicode character, where HHHH is a 4-digit
      hexadecimal code indicating a Unicode codepoint.
      
     \u{h...h} (Frink notation)
      and \x{h...h} (Java regex notation)
      where h...h represents from 1 to 6 hexadecimal
      digits that represent the desired Unicode codepoint.
     \xhh
      where hh represents exactly 2 hexadecimal digits
      that represent the Unicode character.  These previously worked in the
      left-hand side but not the right-hand side.
     \0 (that dangerous
        notation dies with me!)
       \a (use \u0007 instead)
       \e (use \u001B
        instead)
       \cX
        (specify it with its Unicode character instead.)
      makeArray[dimensions, function, data]
   which allows you to pass in arbitrary additional data to a function when
   creating an array.  See the Initializing Arrays section of the
    documentation for examples.
   makeArray functions.  The Matrix class is
     still woefully incomplete but feel free to contribute unimplemented
     functions!
  makeArray[dims, value] function can now
   take a function as the value parameter.  The function will be
   called to provide the value of each cell.  See
   the Initializing Arrays section of the
    documentation for examples.
    
   
     I also added a huge diatribe about the so-called "Pochhammer function"
     and whether it means a rising or falling factorial, which is ambiguous
     through history and across fields of study.  The new preference is to
     call risingFactorial[x, n]
     or fallingFactorial[x, n]
    
generalizedBinomial[r, k]
    It basically generalizes it as:
    
     generalizedBinomial[r, k] := fallingFactorial[r, k] / k!
    
sqrt[x, digits]: Arbitrary-precision square root to
      the specified number of digits.  This can take arbitrarily-large and
      small arguments.  This function only works with real-valued inputs.
     sqrtExact[x, digits]: Arbitrary-precision square
      root to the specified number of digits.  This can take arbitrarily-large
      and small arguments.  If the input is an integer, this attempts to
      return an exact integer result when possible.  This function only works
      with real-valued inputs. 
    secantInvert function.
   until loop and
    a do...until loop which work
    just like the while loop and
    the do...while loop, except that
    they iterate until the condition becomes true.
    
     
      i=0
    
      until i>1000000
      {
         i = i+1
      }
     
     
      i=0
    
      do
      {
         i = i+1
      } until i == 1000
     
     This means that until is now a reserved keyword.
    
FrinkGeneration[] function that returns an integer
   indicating the generation of Frink.  0=Frink original,
    1=Frink:The Next Generation.
    
    Programs can use this flag to warn that, say, calculating thousands of digits will be slow in the original version, or even switch behavior (e.g. use an integer-based routine in original Frink and a floating-point routine in Frink:TNG.)
If you don't know what Frink:The Next Generation is, it's a new version of Frink that runs on Java 1.6 and higher, but you should use it on Java 1.8 and higher because Java 1.8 has algorithms that Frink contributed to Java which makes its floating-point numbers orders of magnitude faster for numbers with lots of digits. You should be using it unless you have an old or broken Java implementation.
      To support old versions of Frink before this function exists, you should
      probably wrap it in a call to eval:
     
      if eval["FrinkGeneration[]"] != 1
     
          println["""Note: this program will be orders of magnitude faster with Frink:The Next Generation, available at: https://frinklang.org/experimental.html"""]
      
(x^y)^z which did
    not work correctly in some cases if z was a non-integer.  It
    is highly recommended to update as soon as possible.
   frink-tng.war file from Frink: The Next Generation
    (version 2020-03-06).
  joinln[list] function
    which takes an array and returns its result as a single string joined by
    newline characters, that is, it puts each element of list on
    its own line with no trailing newline.
  frink-tng.war file from Frink: The Next Generation
    (version 2020-02-29).
  isEnumerating[expr] to test if an
    expression is an enumerating
     expression.
    
   condition ? trueClause : falseClause
    in the If / Then / Else section of the
    documentation.
  numerator, denominator,
    and numeratorDenominator functions.  These functions now take
    two optional parameters which allows you to select how rational numbers and
    units of measure are split between the numerator and denominator.  See the
    description of the numeratorDenominator function in the Other Functions section of the documentation
    for details.
  numerator[expr]
    and denominator[expr] functions.  They can now return
    the numerator and denominator of arbitrary symbolic
    expressions.  denominator[expr] works by collecting
    multiplicative terms that are obviously divisions or have negative
    exponents, and numerator[expr] works by collecting the
    other parts.
   numeratorDenominator[x] function which returns
    the numerator and denominator of an expression as a two-item
    array [numerator, denominator] This works on
    rational numbers, integers, units, and arbitrary symbolic expressions.
    It is better to use this function than to call numerator
    and denominator separately, as it's more efficient.
    
     [n,d] = numeratorDenominator[noEval[1/4 G^-1 a^-1 c^4]]
     [c^4, 4 G a]
    
graphics object.  Normally, Frink's graphics
    are automatically scaled and centered in the display.  All of the graphics
    that you draw will automatically be visible, no matter what coordinate
    system you use.  However, sometimes you may want to have fine-grained
    control over the region that is displayed, even if you don't fill it
    entirely, or if you want to draw outside the region, or if you want to
    "zoom in" on just part of a graphic.
  map["funcname", list]
    function when the first parameter was a string indicating a function name.
    This is a convenience function that tries to look up an appropriate
    function by name, based on the length of the first entry
    in list but may not have found an appropriate function
    if list was a list of non-list items.  This may have
    manifested in an error message like:
    
     MapFunction:  No function found named 'funcname' with 0 arguments.
    
The function worked correctly if passed an anonymous or named function as the first argument (which is probably a more robust solution.)
Thanks to Chris Hansen for the bug report.
In these, the exponents y and x can be negative, which indicates division by n.
frink-tng.war file from Frink: The Next Generation
    (version 2020-02-05).  This attempts to fix some compilation issues from
    the last version.  As a result, the Java Servlet API version compiled
    against had to be increased from 2.5 to 3.1.
  log[x, base] function (which takes
    logarithms of the number x to the specified
    base base.)  These did not return wrong results, but could
    throw ArithmeticExceptions or cause slowdowns.
  splitLines[str] function which splits a
    string on newline characters and returns an array of strings with the
    newlines removed.  See the split section of the
    documentation for an example.
  primes[begin, end] function can now take
    the undef parameter for either argument.
    If begin is undef, the enumeration begins with
    2.  If end is undef, the enumeration is
    potentially infinite.
  mohm as a synonym for the strange
    unit mobileohm.  This conflicted with the milliohm.
    Thanks to Enon Harris for the catch.
  first[expr] returns the first element of an array
      or enumerating expression as a single expression.
     first[expr, count] returns the
      first count elements of an array or enumerating expression.
      If the expression passed in is an array, the result is an array,
      otherwise it is a (possibly-infinite) enumerating expression.
     rest[expr] returns everything after the
      first element of an array or enumerating expression.  If the expression
      passed in is an array, the result is an array, otherwise it is a
      (possibly-infinite) enumerating expression.  This is the opposite of
      first[expr]
      
     last[expr] returns the last element of an array
      or enumerating expression as a single expression.
     last[expr, count] returns the
      last count elements of an array or enumerating expression.
      The result is an array.
     slice[expr, begin, end] returns a
      slice of an array or enumerating expression starting with
      index start and ending before
      index end.  If the indices are beyond the ends of the
      array, only existing items will be returned.  If begin
      or end is the value undef, the results will
      include the beginning or end of the expression respectively.  If the
      expression passed in is an array, the result is an array, otherwise it
      is a (possibly-infinite) enumerating expression.
     sliceLength[expr, begin, length]
      returns a slice of an array or enumerating expression starting with
      index start and having length items.  If the
      expression passed in is an array, the result is an array, otherwise it
      is an enumerating expression.
      
     nth[expr, index] returns the specified
      (zero-based) element of an array or enumerating expression.  For
      example, to return the millionth prime (again, indexing is
      zero-based,) nth[primes[], million-1]
    last[expr] function to return just the
    last element of an array or enumerating expression.
    
   primes[begin] function which returns an
    infinite enumerating expression of the prime numbers greater than or equal
    to begin and increasing.  Note that this will produce
    infinite output if you even try to print it, so you probably want to call
    it from a for loop or from something
    like first[primes[3], 100]
    
   primes[begin, end] function which
    returns a finite enumerating expression of the prime numbers greater
    than or equal to begin and less than or equal
    to end.
   meanAndSD function in statistics.frink
  arg[z] function that returns the argument
    (that is, the phase) of a complex (or real) number.  For a complex number z
    = x + i y, this is equivalent to arctan[y,x].
  %s/from/to/modifiers construct)
      contained character escapes, (for example, \u2090) the
      character escapes were not properly turned into the actual characters.
     \u{h...h} (Frink notation)
      and \x{h...h} (Java regex notation)
      where h...h represents from 1 to 6 hexadecimal
      digits that represent the desired Unicode codepoint.
     \xhh
      where hh represents exactly 2 hexadecimal digits
      that represent the Unicode character.  These previously worked in the
      left-hand side but not the right-hand side.
     \0 (that dangerous
        notation dies with me!)
       \a (use \u0007 instead)
       \e (use \u001B
        instead)
       \cX
        (specify it with its Unicode character instead.)
      These problematic patterns are still allowed on the left-hand side of a substitution expression, but that may change.
graphics.invertGrays[] when
    a graphics object contained other graphics
    objects.
  rlwrap program to allow you to use the up/down arrows to
    repeat and edit calculations, and even to autocomplete units and
    functions.  Download the updated file and its associated files from the
    Running Frink section of the documentation.
  rest[expr] function to return
    everything after the first element in a list.
   a x^3 + b x^2 + c x + d === 0)!
   It even now solves in the cases where b or c are
   zero and those terms disappear.  These updates are located in solvingTransformations.frink.
  On 2019-12-19, Google Play, in its infinite wisdom, removed the Frink app for two random unrelated reasons. These are under appeal. See below.
The first weird "reason" was that "something something...your app may appeal to children." This made no sense but if Frink makes children enjoy programming and getting physics answers right, then I'M ALL IN.
The second random banning was Google saying "something something... let's say billing policy violations." This was especially weird because:
log[x, base]
    function (which takes logarithms of the number x to the
    specified base base.)  These would manifest as a
    divide-by-zero error or an "exponent is too large" error when trying to
    take the logarithm of a rational number that was very close to 1.
    Incorrect values were never returned.  The errors were in the code that
    tries to return exact rational or integer results when possible.
   first[expr] function to return just the
    first element of an array or enumerating expression.
  bytesToString[bytes, encoding="UTF-8"]
    can now take an array of Frink integers that will fit into bytes, as well
    as an array of Java bytes.
   bytesToString above.
   last[expr, num] to take the
    last num items from an expression (which can be an array or
    enumerating expression.)  The result is returned as an array.
    
   dict.addToList[key, value]
    and dict.addToSet[key, value].  See
    the Dictionary Methods section of the
    documentation for more.
  n / ln[c n] ===
     a for n and equations of the form w e^(c w) ===
     z for w, both of which require solutions in terms of
     the Lambert W function.  This makes dependencies
     on LambertW.frink, ArbitraryPrecision.frink,
     and sqrtWayne.frink,
     and pi.frink
     These dependencies may change.  In addition, you can comment out
     the use LambertW.frink statement without problems;
     you just won't be able to get a numerical result for the LambertW
     function; it will just give a symbolic result.
     
    e using binary splitting.  This is
    efficient and resumable and maintains a cache; when you need more digits,
    the previous calculation is resumed, rather than restarted from scratch.
    
   isRational or isInteger in symbolic mode
    when evaluating conditions in a transformation rule.
  This is an improvement on the previous pi.frink sample program in that it can resume the binary splitting and square root, rather than starting over when a larger number of digits is requested.
This file is intended to be used with Frink: The Next Generation.
z = w ew for w.  It can
    be found at LambertW.frink
  isReal[expr] function which
    returns true if the argument is a real number (with or without
    dimensions, and not an interval,) false otherwise.
   unitsWithValues[] function which returns an
    enumeration of [unitName, value] pairs.
    
   unitsWithValues[expr] function which takes
    returns an enumeration of [unitName, value]
    pairs that match the specified dimensions.
  Z0 or impedanceofvacuum) and admittance of
    vacuum (Y0 or admittanceofvacuum) were swapped
    with each other.  Again, thanks to Alain Fontaine for bringing these
    changes to my attention.
  k.
      
     zerocelsius is now defined as an exact rational
      number.
      
     
       format[F[0 K], 1, 2]
       -459.67
      
Z0
      or impedanceofvacuum) and admittance of vacuum
      (Y0 or admittanceofvacuum) have been added.
    mu0 and epsilon0,
      the permeability and permittivity of vacuum (respectively) to match the
      changes made in the 2019 SI redefinitions.  These are no longer
      "exactly-defined" values, as they were before, but are now
      "experimentally-measured" quantities.  Their values changed very
      slightly, and they now have uncertainties.  Thanks to Alain Fontaine for
      bringing these changes to my attention.
    R.
   
     (Since Frink version 2018-12-11, you can specify floating-point numbers
     to be exact using the "exact exponent" indicator which will turn them
     into exact rational numbers or integers.  For example, the new exact SI
     value for Avogadro's number 6.02214076ee23 will become an
     exact integer.  The exponents can also be negative, which will usually
     lead to an exact rational number, such as 6ee-1 which
     produces the exact rational number 3/5 (exactly 0.6).
     Previously, only integer mantissas could be specified with the exact
     exponent indicator.)
    
The new exact values are:
h: Now exactly 6.62607015 *
      10-34 joule-second (J s).  This is now represented in Frink as
      an exact fraction, 6.62607015ee-34 J s
     elementarycharge, or
      similarly electroncharge (negative)
      or protoncharge (positive), is now defined as exactly
      1.602176634 * 10-19 coulombs, or, in Frink
      notation, 1.602176634ee-19 s A (a coulomb is an ampere
      times a second.)
     k is now defined as exactly
      1.380649 * 10−23 J/K, or, in Frink
      notation, 1.380649ee-23 J/K
     6.02214076ee23
      mol^-1
    Update: Since I posted this last night, the NIST site now states that it has the 2018 CODATA values of the constants! Frink's standard data file will change again with the new values.
The units that will change further include things like the gravitational constant G, masses of fundamental particles, etc., all of which are updated both because of new SI definitions and new experimental results. Watch for more Frink updates soon!
graphics object has been improved to
    fix a bug in horizontal labels with a customized formatting function.
   read and lines
    and readLines can now take a java.io.Reader as
    an argument.   Previously, they could take a URL or
    a java.io.InputStream.  See
    the Reading Entire Files section of
    the documentation for more.
  + sign in the
   exponent, e.g. 1ee+1000.  The + sign was
   previously allowed if the mantissa included a decimal point, but if it
   didn't, this wasn't parsed correctly (and could even produce parser
    crashes.)
    
   mapList[function, list, data] which
    allows arbitrary data to be passed to a function used in
    the mapList function.  In this case, the function passed
    to mapList must take two arguments instead of one.
    See the map section of the documentation
    for more details.
  log[x] (which takes logarithms to
      base 10) now returns exact integers or rational numbers in cases when
      arguments are integers and results are integers or 1 divided by an
      integer.
      
     log[x, base] function (which
      takes logarithms of the number x to the specified
      base base.)  This returns exact integers or rational
      numbers in most cases when arguments are integers or 1 divided by an
      integer.
      
       Note that the ordering of the arguments may be different from
       other programming languages!  This order was chosen
       because log[x, base] can be rewritten
       as log[x] / log[base] for any logarithmic
       function that takes a logarithm to any base.
      
       This follows the precedent set by functions
       like arctan[y, x] which is equivalent to
       arctan[y/x] except the former corrects for
       ambiguities in the quadrants.  Similarly, it's simple to
       change log[x] / log[base]
       to log[x, base] without errors.
      
Some programming languages have taken the opposite approach, where the first argument is the base and the second argument is the number. This seems like a bad design choice, so be careful when transliterating mathematical expressions from other programming languages.
java.lang.Iterable.  Previously, this eagerly
    fetched the Iterator from the object and returned the iterator, rather
    than the whole object itself.  This was fine if you just wanted to iterate
    over the contents of the object, but bad if you wanted to call any of its
    other methods.  You can once again call its methods or use it in
    a for loop.
   
     This fix takes a stronger approach to work around these bugs and to
     mitigate the damage done by Java 9 and later's not-really-useful "module"
     system (that can never work right in the face of this bug and similar
     others).  The code tries very hard to search for accessible method calls
     in the class, in its superclasses, and in its implemented interfaces to
     find and call a method, (that you would be able to call from compiled
     Java,) but if that fails, it will take the stronger step to call
     Java's AccessibleObject.setAccessible(true) on the method,
     and then try calling it again.  This fixes a lot of poor design in Java's
     libraries, especially com.sun.internal classes, and works
     around the aforementioned bugs that Java has been promising to sorta
     think about 2 decades ago.
    
     In Java 9 and later, you might get warnings about "illegal reflective
     access" if you call a method that has to be called using the stronger
     methods listed above (to work around the aforementioned Java bugs.)  For
     now, the java command allows you to pass
     the --illegal-access flag:
    
--illegal-access=value: permit or deny access to members of types in named modules by code in unnamed modules.valueis one ofdeny,permit,warn, ordebug. "This option will be removed in a future release."
     You might be able to see what extended options your Java Virtual Machine
     has by executing java -X.  You may have to add one of the
     options, especially --illegal-access=permit to your Frink
     startup script if you invoke methods that touch these Java bugs in Java 9
     or later and you need these warnings silenced.
    
conjugate[x] function to return the complex
    conjugate of a complex number or array of numbers.
  copyStream[inputStream, outputStream] function
     to copy the contents of one java.io.InputStream to
     a java.io.OutputStream.  See the I/O Functions section of the documentation for
     more details.
   parseFloat
    function can produce exact rational numbers or a number with approximately
    the same number of significant digits as the string being parsed.
  image.show[title] to show an
    image with the specified title.
   image.resize[width, height]
    method has been rewritten to use a much better area-averaging filter.
    This makes scaling of images much cleaner and less random, especially for
    strong downscaling.
   ComplexArray2D.subtract[ComplexArray2D]
    method to create, say, difference between two images (after calling
    their .toComplexArray[] methods.)  This can be turned back into
    an image by calling the toImage[] method on the result.
  ex
     and ln[x], and log[x].  These now
     solve many more equations.  It is frankly amazing how adding a
     single transformation rule makes the solver able to solve huge classes of
     new equations.
    ex and ln[x],
     and log[x] to
     solvingTransformations.frink.
     These rules may move.  See below.
    graphics object has been improved to
     provide better labels on the y axis when an "up is positive" orientation
     is chosen.
     ex
    and ln[x].
   DFT
    functions.  The speedup for processing a 2048 by 2048 image is about 334
    times.  The functions behave similarly, but the FFT functions
    pad their input to the next largest power of 2, which can give different
    results.
    See the Fourier Transforms section of the documentation for details.
toUnicodeSubscript[int] to turn an integer
    into a Unicode subscript string.
  dictionary.increment[key, increment]
   method to allow you to easily use a dictionary to count items.  See the Dictionary Methods section of the
    documentation for more.
  graphics.invertGrays[] method
    that makes your graphics objects invert their grayscales.
    Previously, if a graphics object contained other graphics
    objects, the sub-objects would not have their colors transformed.
  graphics object.  This has been improved in many ways,
      including adding coordinates based on the
      new Calendar Functions.
      See sample usage in manhattanhengemoon.frink and simplegraph5.frink.
All of these functions are described in detail in the Calendar Functions section of the documentation.
mapList function which performs like
     the map function but is better for working with lists.  It
     does not have map's behavior of breaking its input into
     named arguments.  Discussion of how to choose the appropriate function is
     contained in the map section of the
     documentation.
  isStrongPseudoprime[num, base(s)] function
      in several ways:
      Function to FunctionCall.
     This means that when constructing a function call from functions
     like constructExpression, the typename must be changed in code
     from Function to FunctionCall.  The relevant
     sample programs have been changed,
     notably Solver.frink, functionUtils.frink
      and systemSolver2.frink.
      
getFunctionCalls[expr] to return
       all of the function calls called directly from a specific expression.
       This does not return functions called recursively, nor resolve the
       specific function that may be called.  This behavior may change.
  /e
      modifier (to treat the substitution as a Frink expression,) exceptions
      could be thrown if the substitution contained a backslash or a dollar
      sign.   The error message was possibly "character to be escaped is
      missing."  This has been fixed.
    intersection[arg1, arg2] now behaves
   better when two interval arguments are passed in.  If only one of
   the arguments has a "main" value, then that main value is preserved in the
   result.
  isFunction[expr] function to test if an
    expression represents a (named or anonymous) function.
  (240 m^2 s^-3 kg A^-2)^(1/2) (previously, the
    left-hand side of the exponentiation operator would not have been
    parenthesized correctly.)
  n.  This gives
     asymptotically better estimates than LogIntegral.frink, which
     also gives really good estimates.
  primes[] function which returns an infinite
    enumerating expression of the prime numbers starting with 2 and increasing.
    Note that this will produce infinite output if you even try to print it, so
    you probably want to call it from a for loop or from something
    like first[primes[], 100]
   ee "exact exponent" indicator, which will turn them into
    exact rational numbers or integers.  For example, the new exact SI value
    for Avogadro's number 6.02214076ee23 will become an exact
    integer.  The exponents can also be negative, which will usually lead to
    an exact rational number, such as 6ee-1 which produces the
    exact rational number 3/5 (exactly 0.6).  Previously, only
    integer mantissas could be specified with the exact exponent indicator.
   secantInvert function.
  first[expr, num] to take the
   first num items from an expression (which can be an array or
   potentially infinite enumerating expression.)  The result is returned as an
   enumerating expression.
  
     Technical Reasons: This is due to the fact that the Google Play
     store now requires that all applications target API level 26, but API
     level 13 introduced some not-backwards-compatible changes to
     the AndroidManifest.xml files.  After API level 13, Android
     fires a screenSize change that needs to be handled when the
     screen is rotated.  However, this property does not exist before API
     level 13, and updating the target API level breaks application handling
     of screen rotates.  Previously, Frink targeted API level 3 (Android 1.5)
     and before.
    
frinkold.apk
    file is downloadable directly from this website.
    
   clamp[num, min, max] function
    to limit a number to lie between a minimum and maximum value.  This
    function also works correctly when num is an interval.
  ChineseNumbers.formatCasual[123]
   apparentPosition: Now can optionally correct for radial
      velocity and distance in proper motion calculations.  This changes the
      order of arguments to this function.
     raDeclToEcliptical: This performs conversions from right
     ascension and declination to ecliptical coordinates.  This is symmetric
      to the eclipticalToRADecl function.
    else part of an if block when
    the then part of the block has multiple lines.  This caused
    invalid if statements to be generated by the code formatters.
  isPrime[n] primality-testing function's Rabin-Miller
    implementation for very large numbers.  It now again performs some trial
    division and always tests against bases 2 and 3 first before testing
    random bases.
  isPrime[n] primality-testing function's
    Rabin-Miller prime test to use 78 random bases instead of 78
    deterministic bases.  This helps mitigate the impact of
    adversarially-chosen numbers which are not actually prime.
    See Prime and Prejudice: Primality Testing Under Adversarial Conditions for more about primality-testing weaknesses in software under adversarial conditions. This paper is genius and describes heroic computations to find composite numbers that many modern software packages will mistakenly declare to be prime.
In some cases, the computations took "a total of 33,885 core-hours (3.87 core-years) of computation in parallel on 872 cores running at 2.4GHz" (p. 13) to find these counter-examples. That's impressive.
It is a wonderful paper that summarizes a lot of previous results in adversarial primality testing. Read it. Especially read the classic paper François Arnault. Constructing Carmichael numbers which are strong pseudoprimes to several bases. Journal of Symbolic Computation, 20(2):151-161, 1995.
Note that Java 1.6 and earlier cannot use Diffie-Hellman key exchange parameters longer than 1024 bits (the site uses 4096 bits.) You should still be able to access the site through any modern web browser, or through Java 1.7 or later.
_n:
    
     constructExpression["AnythingPattern", ["n"]]
     _n
    
https://frinklang.org/.
  floor, ceil,
      round, and truncate functions.  These were
      significant in some programs.
     k and even works with symbolic arguments.
  
       Try
       this ballistics
       example of a particle being shot upward which lets you calculate
       for initial height (h0), initial velocity
       (v0), time (t), gravitational acceleration
       (gravity) and solve for any one of these variables, both
       symbolically and numerically.  It is neat.  It even integrates for you!
     
poissonProbability[k,expected] function when
      k was exactly 1.  The function was also simplified and
      comments were improved.
     
     
      java -cp /path/to/frink.jar frink.gui.FrinkStarter --swing
     
    
     -Dsun.java2d.opengl=True
    
     (If you write "True" with a capital T then you get debug
     information that indicates if OpenGL is actually being used.  With a
     lowercase "true" then it's silent.)
    
Thus, the command-line becomes:
     
      java -Dsun.java2d.opengl=True -cp /path/to/frink.jar frink.gui.FrinkStarter --swing
     
    
     
      java -cp /path/to/frink.jar frink.gui.FrinkStarter --awt
     
    
Writer class that take
     java.io.OutputStream or java.io.Writer, so you
     can easily write to an already-existing stream.  This enabled the GZIP
     compression above.
  isString[expr] function.
  For example, when multiplying two 10-million-digit floating-point numbers, the time is reduced from over 9 days down to 62 seconds!
When calculating 3 million digits of pi, it used to take about a day. Now it can be calculated in just over 3 minutes! Try it with piChudnovskyNew.frink!
See the new Experimental Frink Features for detailed information on all these features!
--width and --height command-line
    options also work with SwingInteractivePanel.
   --fontsize int to set
    the font size of frink.gui.InteractivePanel or
    frink.gui.SwingInteractivePanel or 
    frink.gui.FullScreenAWTStarter.
   mod operator to improve containment,
    specifically when using imprecise floating-point arguments in the cases
    where numeric precision is being lost (such as when one argument is much
    bigger than the other.)  When no meaningful result can be given, this can
    now return 0.
  to keyword) that might have caused infinite
    loops when the ends of the loop were near or exactly 231-1 or,
    when counting downwards, around -231.
  isDate[expr] which returns true
    if the expression is a date/time, false otherwise.
    
   graphics objects to control their antialiasing behavior.  The antialiasing
    behavior of graphics and text can now be controlled (separately.)  This
    allows better-looking rendering of many adjacent rectangles to look more
    like pixels, without lighter lines connecting them.
   image.makeMono[] method to the image class.  This allows an image to be converted
    to a 1-bit monochrome image, if supported by your platform.  Android
    currently does not support monochrome Bitmaps so this does nothing on
    Android.
  mod and div
    operators for better performance, especially for integer values.
  collapseIntervals function's
    directives for degenerate intervals.  Sanity checks were also improved.
   BigInteger and BigDecimal. 
  div operator when one of its
    arguments was exactly -231.
   TAI (also
    called International Atomic Time) which was hiding in the
    code and hard-coded to an old offset.  The new definition takes into
    account not only historical and announced future leap seconds, but also
    interpolates for the period from 1961 January 1 to 1972 January 1 where
    the difference between TAI and UTC was constantly and linearly
    interpolated.  For more information see the Leap Seconds section of the documentation.
  GeneralPath.addPoint[x,
      y] method to more closely match polygon or
    polyline.  If the point added is the 
    first point, this does a moveTo the specified point.  If
    there are previous points, this does a lineTo the specified
    point.  This may simplify code by eliminating the initial
    moveTo call and allows easy migration from
    polygon or polyline to GeneralPath.
   GeneralPath.close[] method now
    explicitly forces you to add a moveTo or
    addPoint before starting a new curve.  This how the
    documentation always insisted that you do things, but the code might have
    implicitly allowed the previous point to be used.
   floor,
    ceil, trunc, and int functions.
   select[list,
   substr] function to allow a substring as the second
   argument.  This will return items which contain the specified substring
   (with an exact match.)  If you need a case-insensitive match, the second
   argument should be a regular expression.
   timezones[pattern] was
    added, allowing you to list timezones that match any pattern that match the
    specified pattern.  The pattern can be anything matched by the select function: that is, a function (that returns
    true for matches,) a regular expression, or an exact
    substring.
  Unfortunately, when testing this, I found out that the common image
     viewer "Eye of Gnome" (eog) or "Eye of Mate"
     (eom) chokes on large SVGZ files with a "huge input lookup"
     error.  (It opens the same uncompressed file just fine.)  I have filed a
     bug here.
  
JSONParse[str]:
    csch[x]: Hyperbolic cosecant of x, equivalent to
      1/sinh[x], or 2/(ex - e-x).  For some reason,
      arccsch[x] was already implemented.
      
     sech[x]: Hyperbolic secant of x, equivalent to
      1/cosh[x], (which was already implemented,) or 2/(ex -
      e-x)
     arcsech[x]: Inverse hyperbolic secant of x, or
      ln[sqrt[1/x - 1]*sqrt[1 + 1/x] + 1/x]
     coth[x]: Hyperbolic cotangent of x,
      (e2x + 1) / (e2x - 1)
     arccoth[x]: Inverse hyperbolic cotangent of x, or
      1/2 ( ln[1 + 1/x] - ln[1 - 1/x] )
    Writer class try harder to use
    platform-specific newline characters in its println method.
   writeln[] and println[]
    methods to simply append a newline to the file.
    
   flush more often if
      you need data to be written immediately.
     println.  If you do specify a buffer size,
      you will need to flush manually (this is to let you squeeze out a bit
      more performance.)
    -u
       filename command-line
       option now also applies to programming mode in the GUI, and not
      just to interactive mode.  Be warned if you're loading a custom units
      file.
     -open filename option.  (This is how
      double-clicking a .frink file works in Windows or some
      Linux environments with the proper file association set.)
    poundbookpaper which had incorrect dimensions.
    If you wanted to estimate the mass of a U.S. letter page of "20 pound bond" paper, you could calculate it as:
     20 poundbondpaper * 11 in * 8.5 in -> "grams"
     4.5359237 grams
    
area_density to describe
    the mass density per area of a sheet of something, such as
    kg/m^2.
   radian as a fundamental dimension.  (You really don't ever
    want to do this, unless you're having a really hard time debugging an
    example that uses angles.)  The inverse trigonometric functions like
    arcsin and arccos were not returning the results
    with dimensions of radians, and possibly producing conformance errors.
  specific_volume from its incorrect
    value m^3 kg to the correct m^3 kg^-1.  Thanks
    to Benjamin Zax for the correction.
  This will make it easier to perform symbolic transformations and calculus on functions and expressions that may not have been written with calculus or symbolic transformations in mind. It will also be useful in finding the minimum/maximum of expressions, graphing, inverting equations, and solving equations both numerically and with exact symbolic results. (Many of these are performed much more efficiently and exactly if you know the derivative of the function. For example, Newton's method requires knowing the derivative of a function.)
graphics.write... methods now allow you to
    specify exactly one of the width or height as
    undef, the undefined axis will be calculated from the defined
    width or height and the aspect ratio of the graphics that is
    being drawn.
   --prog command-line option to start Frink in
    programming mode directly from the FrinkStarter class.
   -open filename command-line option if passed a relative
    filename without a parent.
  graphics.invertGrays[] function
    that makes your graphics objects invert their grayscales so
    you can easily make a single graphics object that looks like
    Wargames (black background, white lines) for on-screen display but doesn't
    waste your printer ink (white background, black lines) when printed.
    Shall we play a game?
    For more information, see the Showing Graphics section of the documentation.
polygon, filledPolygon,
      and polyline can now take a list of points.
      
       
        a = [ [1,3], [7,4], [6,2] ]
      
        p = new polygon[a]
       
polygon,
    filledPolygon, and polyline.  See Polygon Methods for more information on any
    of these.
    
    .getPoints[] returns a list of the points in a polygon.
     .getArea[] calculates the area of the polygon.
     .getCentroid[] returns the centroid of the polygon as an
      [x,y] array.
     .show[] method to easily display a polygon
      without adding it to a graphics object.
    previousPrime[n] to efficiently return the
    previous prime number less than n.  This complements the
    existing nextPrime[n] function.
  This improvement works whenever Frink parses a large integer.
10000! using  either  the
      ! operator or the factorial[n] function)
      now use a binary
     splitting algorithm which makes them significantly faster on Java 1.8
      and later.  (Did you know that Java 1.8's BigInteger calculations got
      drastically faster because Frink's internal algorithms were contributed
      to it?)
     factorialRatio[a, b] was
      added, which allows efficient calculation of the ratio of two
      factorials a! / b!, using a binary
       splitting algorithm.
     binomial[m,n] that calculate
      binomial coefficients are more efficient because of the use of binary
       splitting algorithms.
      
       Note: binomial[m,n] is of the number of ways
       m things can be chosen n at a time, with
       order being unimportant.  This is sometimes called "m choose n" or "m C
       n".  This is equivalent to m!/(n! (m-n)!) although
       calculating that way often leads to way-too-big numbers.  For example,
       binomial[10000, 9998] is equal to 49995000, but if you
       calculated it naively, you'd have to calculate 10000! which is a
       35660-digit number, and divide it by another huge number, which could
       be inefficient and slow.
     
getSensorService[type] which may not have worked on
    newer versions of Android.  (It worked fine if you used the two-argument
    version getSensorService[type,
     updateFrequency].)
  .frink) to be loaded from your device's file
    manager:
    content: URI.
     use statements in your program not work correctly due to the
      opaqueness and security mechanisms built into content: URLs.
      Frink may make attempts to work around these issues in the future.
     .frink extension.  This works around some limitations of
      Android's pathPattern implementation.
     isPrime[n] is now guaranteed to
    prove primality for numbers up to
    3,317,044,064,679,887,385,961,981, and uses a smaller number of
    pseudoprime tests up to this value, improving performance of both
    primality testing and factorization.
  sort[array, function].  If
    the passed-in function had multiple return statements instead
    of a single simpler expression, it might not behave correctly.  (For
    example, in the case of sort the array might not be fully
    sorted.)  This may have affected:
    sort functions with
       user-defined comparison functions.
     map
     select
     rangeOf[array] which returns an enumeration
    of all the indices in an array:
    
     a = ["zero", "one", "two"]
     
      for i = rangeOf[a]
         println["index $i contains " + a@i]
     
      index 0 contains zero
    
      index 1 contains one
      index 2 contains two
     
    angles[]
    
    No function match found for angles with 0 arguments.
   
Suggestions:
  Functions:
   Ingles[arg1]
   Inglês[arg1]
   Inglés[arg1]
   Engels[arg1]
   Inglese[arg1]
   Anglais[arg1]
    
eval[expr] and unsafeEval[expr]
    functions to behave better when evaluating an expression containing an
    already-compiled list of statements (that is, a multi-line program compiled
    with parseToExpression[str].)  It now behaves much more
    similarly to running that program directly.  It now returns the same return
    value as running the program would, rather than the odd previous behavior
    of returning an array of results from each statement.
  getBit[n, bit] that affected n
    that would fit into a 32-bit integer and where the requested bit was
    outside of the integer.  Thanks to Jeremy Roach for the research and bug
    report.
   = instead of :=
  read[URL,
   encoding] function to read from a file or a URL where you
    specify the encoding of the file or URL.  The encoding might have been
    ignored.
  graphemeLength[str] function which
    returns the length of a string in graphemes, counting multiple
    Unicode codepoints that should be combined together as a single display
    glyph as a single character.  See the Correct String Parsing section of 
    the documentation for more details.
   frink.text.c.  This may also
    fix running on a Java 1.6 or 1.7 JVM.
  lexicalSort functions, there are now
    similar methods that compare two strings using human language rules and
    Unicode normalization:
    lexicalCompare[string1, string2]: Compares
     2 strings using a comparison method that understands human languages.
     This version uses the default locale and language settings defined on
      your Java Virtual Machine to perform the comparison.
     lexicalCompare[string1, string2,
       languageCode]: Like the previous function, this compares
      2 strings using a comparison method that understands human languages.
      This version uses a specified language.  The argument
      languageCode can be one of three types:
      "en" for
        English.
       java.text.Collator
         
       java.util.Locale
      Locale(String language) did not exist, so if you're on a very
    old JVM, you'll have to construct Locales manually with a language and a
    country.)
    
   lexicalSort functions:
    lexicalSort[array] sorts an array of
      strings using the default language and locale settings defined in your
      Java Virtual Machine.
     lexicalSort[array, languageCode] sorts
      according to the rules of the specified human language.
      languageCode is the ISO 
       639-1 two-letter code for the language.
      
       If you need extreme control over the sorting order,
       languageCode can also be either a java.text.Collator
       or a java.util.Locale
       object which allows you very detailed control over creating custom
       sorting rules or locales.  Please see the documentation for those
       classes for details on controlling sorting.
      
gravitational_constant and
    electric_force_constant so the -> operator could
    suggest their use in common calculations.
  < ,
    == , >= , including the three-way comparison
    operator <=> can now compare Java objects that implement
    the java.lang.Comparable
    interface.  This includes numeric types, strings, and many other types.
  Comparable interface.
   normalizeUnicode[string, method="NFC"]
    function.  This function normalizes the characters in a Unicode string
    using one of the methods described in the Unicode standard, specifically Unicode Standard Annex #15,
     Unicode Normalization Forms.
    
     A Unicode string can use various methods to encode what is essentially
     the same character/glyph.  For example, the character
     ô can be represented as either "\u00F4"
     or "\u006F\u0302".  The former is a "composed" character,
     "LATIN SMALL LETTER O WITH CIRCUMFLEX", and the latter is two Unicode
     codepoints, an o followed by "COMBINING CIRCUMFLEX ACCENT".
     (This is usually referred to as a "decomposed" representation.)  This
     function can convert these "equivalent" encodings into a canonical
     representation, whether it be composed or decomposed.
    
Unicode Standard Annex #15 currently defines four different methods of converting between these representations. (You might get the best idea of the differences between these by looking at figure 6 in the document.)
See the Correct String Parsing section of the documentation for more details on this function.
byte to
    Frink types, bytes are now always returned as positive, unsigned values.
    That is, you no longer see Java's weird negative bytes that nobody in the
    world has ever wanted. (You could always convert numbers up to 255 into
    bytes, so this behavior change is only on output.  You can still put
    negative numbers from -128 to -1 into bytes, but they'll be made into
    positive values when converted back to Frink types.  This does not change
    their representation in Java objects.)
    If your program did any of the following to work around signed bytes, it will still work fine:
     if (byte < 0)
    
        byte = byte + 256
     byte = (byte + 256) mod 256
    
messageDigest
    functions now force their input to be converted to bytes using the
     UTF-8 encoding before hashing.  Previously, they used your
    platform's default encoding (which was likely UTF-8 already) but which may
    not have been portable from one system to another.  See the Cryptographic Functions section of
    the documentation for more details on how to modify this behavior.
   messageDigest functions have been improved in several
    ways:
    messageDigest functions can now take an array of
      Java bytes as input.
     messageDigestBytes[input,
       algorithm] function to return the message digest as an
      array of Java bytes.  Note: Most of the underlying cryptography
      routines in Java work with arrays of bytes, as these are safer than
      Strings which are immutable after construction and are eventually
      garbage-collected.  Using arrays of bytes means that you can zero-out
      input buffers as soon as you're done with them.
     stringToBytes[str, encoding="UTF-8"] turns 
      a string into an array of Java bytes using the specified 
      encoding.  The encoding defaults to UTF-8, but can be a string
      indicating any encoding supported on your system.
      See the encodings.frink sample program to see how to list all character encodings (and their aliases) available on your system.
bytesToString[bytes, encoding="UTF-8"]
      turns a Java array of bytes into a string using the specified
      encoding.  The encoding defaults to UTF-8, but can be a string
      indicating any encoding supported on your system.
     The new behavior is that user-defined date formats are given precedence when parsing. Frink will first attempt to match any user-defined date format, and, failing this, will attempt to match one of the formats in the default date formats file. This prevents ambiguity when two different patterns can match the same date. This usually happens only when a user-defined format uses a two-digit year (please don't do this, as even humans can't distinguish what format is intended in many cases. Learn from the lessons of Y2K, and prefer date formats like ISO-8601 where significant digits are first, like yyyy-MM-dd.)
This should not change the behavior of any program that worked correctly before, but might change the behavior of a program which was spuriously matching patterns incorrectly. Thanks to Jerrett Townsend for the bug report.
10⁻²³, which is
    equivalent to writing 10^-23, or x³,
    which is equivalent to x^3.  See the Unicode Operators section of the
    documentation for more discussion and caveats.
   toUnicodeSuperscript[int] to turn an
    integer into a string containing the equivalent Unicode superscript digits
    in base 10.
   RingBuffer is now deep
    copyable with the deepCopy[expr] function.
  RingBuffer.isFull[]
    method.
  RingBuffer class that
    is useful for making efficient limited-sized queues and caches.
  padLeft[str, width, padChar] and
    padRight[str, width, padChar] functions
    can now take an arbitrary expression (instead of just a string) as the
    first argument.  This makes it easier to pad numbers (but to be safe, you
    probably want to make sure that they're stringified correctly first.)
   timezones[] function is now sorted.
  array.transpose[] method to transpose the
    elements of a 2-dimensional array, like in matrix calculations.  This
    means that rows and columns are swapped.  In other words, the element at
    array@i@j becomes the element at
    array@j@i.
   lineBreakList[string] which
    returns an enumeration of the places that a line can be broken.  It
      correctly handles punctuation, numbers, and hyphenated words.  See the
    Correct String Parsing section of
    the documentation for more details.
  reverse[str] function which reverses a string.  This
    is now a smarter reversal that follows Unicode rules to keep combining
    characters and graphemes together and properly ordered.
    
     For example, the string "g\u0308o"
     represents a g with combining diaeresis followed by the
     letter o.  Or, in other words,
     "g̈o".
     Reversing this naïvely would cause the diaeresis to incorrectly
     show over the o instead of the g.
    
     As another example, the Devanagari string
     "\u0915\u094D\u0937\u093F"
     (shown as क्षि ) is recognized as a single
     grapheme and the 4 Unicode codepoints that make it up are kept intact
     and not reversed.
    
If you, for some reason, need the old behavior, you can do something like:
     reverse[charList[string]]
    
but keep in mind that this will still do many of the right things like keeping surrogate pairs ordered correctly. Don't do this. It's never right for Unicode strings. Frink tries to always work on Unicode strings, and not individual characters, as working on individual characters or codepoints is almost always the wrong thing to do when processing Unicode.
graphemeList[string]:  Enumerates through the
      graphemes of a string.
     wordList[string]:  Enumerates through the
      words of a string.
     sentenceList[string]:  Enumerates through the
      sentences of a string.
    
     This allows you to both parse and format numbers in another base using a
     custom character set (as opposed to, say, the typical
     "0123456789abcdef" alphabet of base 16.)  It also allows you
     to do custom base conversions well above base 36.
    
The examples show how to format and parse numbers in Bitcoin address format, Devanagari, and Unicode Superscripts
image.resize[width, height] method to
    resize an image to the new specified width and height and returns a new
    image.  It does not modify the original image.  If either
    width or height are the special value
    undef or 0, then one dimension is constrained and
    the other dimension is calculated to preserve the aspect ratio of the
    original image.
  removeSlice[array, start, end]
    and removeSliceLength[array, start,
     length] functions to remove a "slice" from an array.  These
    are the inverses of the previously-existing slice[array,
     start, end] and sliceLength[array,
     start, length] functions.  See the Slicing Arrays section of the documentation
    for more.
   (3 +
     2i)^3 or (3 + 1/2 i)^4.  Results are improved in
    several ways:
    apparentPosition: Calculates the apparent position of
      a star, correcting for proper motion, precession, nutation, and annual
      aberration.
     longitudeOfEarthPerihelion: Calculates location of
      earth's perihelion
     highAccuracyNutationInRADecl: Calculates nutation in
      right ascension and declination coordinates.
     annualAberration: Calculates the effect of annual
      aberration.
     precess: Calculates precession of the earth's axis.
    HMS functions to convert times to hours, minutes,
    and seconds, or to parse times given as hours, minutes, and seconds.
  eval[expr] and
    unsafeEval[expr] functions so they wouldn't totally
    die when evaluating an array in which an element throws an exception.
    Now, elements of the aray that throw exceptions are returned as the
    special value undef.
   positive[array] function to systemSolver2.frink
    which returns only positive results from a list.
   (1/2
     meter)^(-1/2).  For a while, these were not simplified.  They are
    now again simplified correctly.
   realSignum[expr] which is a
    slightly-more-dangerous version of the 
    signum[expr] function.  This version only handles real
    numbers and returns -1, 0, or 1 depending on the number.  All other values
    return the special value undef.
  (1/2)^(-1/2) (which works correctly and
    transforms to 2^(1/2)) but did not work correctly in some
    cases if the base had units of measure and had a rational number
    for its scale and the exponent was a negative rational number.
    Due to the way this code is invoked, it only appears to happen when using Frink's (somewhat undocumented) symbolic transformation capabilities which triggered this case. That is, it only appears to occur when building a symbolic expression and then transforming it by substituting parts of the expression. However, in any case, it is strongly recommended that you update whether you are using symbolic transformations or not.
https://frinklang.org/
  factorFlat[x] function to factor integers and
    return the results as a one-dimensional list instead of the
    two-dimensional list returned by factor[x].  This
    really isn't necessary, but makes some functional programs slightly easier
    to write.
    
     factorFlat[1000]
     [2, 2, 2, 5, 5, 5]
    
approximationsWithErrors to the continuedFraction.frink
   program to easily calculate the errors in continued fractions.  This is
   demonstrated in the above program.
  use statement on some platforms where
    the underlying system may throw a null pointer exception.  This primarily
    affected Android 5.0.1 and higher.  Thanks to Karel Šnajdr for the
    problem report and debugging.
  
     This includes changes in fundamental constants like Planck's constant
     (h), the gravitational constant (G), Avogadro's
     constant (avogadro), Boltzmann's constant (k),
     the gas constant (R), fundamental particle masses and
     charges, and hundreds more constants that rely on these values.
    
The standard data file has all of the changes and links to the new CODATA values.
     #2015-07-01 UTC#
    
graphics.backgroundColor[colorObject]
    method that sets the background color from a previously-obtained
    color object.
  for and multifor loops
    that have labels.
  getExponent[unit, dimension] to get
    the exponent for the specified base dimension.  See the Other Functions section of the documentation
    for details.  Thanks to Mike Meyer for the suggestion.
    
   graphics.show[width, height]
     image.show[] should now consistently display
      images at their exact native size by default.  Previously, it may have
      been a couple of pixels off.
     int[x] and
    trunc[x] functions (which are the same thing) to work
    for interval arguments.
  partitions[n] Returns an enumeration of the
     partitions of the integer n.  For example:
      
       
        for a = partitions[4]
       
           println[a]
       
        [4]
      
        [3, 1]
        [2, 2]
        [2, 1, 1]
        [1, 1, 1, 1]
       
partitionsCompact[n,
     countPermutations=false]: Like the partitions
     function above, but returns a more compact enumeration of the partitions
     of the integer n.  Each list contains [num, count] pairs indicating the
     number and its count in a partition.  For example, compare the following
     representation with the one from the partitions function
     above.
      
       
        for a = partitionsCompact[4]
       
           println[a]
       
        [[4, 1]]
      
        [[3, 1], [1, 1]]
        [[2, 2]]
        [[2, 1], [1, 2]]
        [[1, 4]]
       
       If the optional argument countPermutations is
       true, then each element also contains the number of
       possible permutations of the list.
    
filenameToURL[string] turns a string
     containing a filename into a URL string.
     fileURLs[string] takes a string
      representing a file or directory and returns an enumeration of files in
      that directory.  Each string is the URL of a file in that directory.
     fileURLsRecursive[string] takes a string
      representing a file or directory and returns an enumeration of files in
      that directory and all its subdirectories. Each string is the
      URL of a file in that directory.
    double value. (i.e. if the numerator
    or denominator or result of the rational number couldn't fit into a
    double).  When converting rationals to double,
    validity of results is now checked much more strongly, and alternate
    methods are used to perform the division if the numerator, denominator, or
    result isn't representable as an IEEE double.
    
    
     While most Frink functions don't use IEEE-754 double values
     directly, they are used in some APIs (like graphics libraries and
     hardware-accelerated trigonometric functions).  The problems are usually
     directly apparent and cause programs to stop at higher levels, but Java's
     graphics APIs silently swallow NaN and infinite values,
     which made these cases possibly slip through the graphics system
     undetected.
   
toRational[num] function to convert Frink's
    internal representation of a floating-point number to an exact rational
    number representation of the number represented.
  sin[] function.
  electroncharge, which changed
    sign recently.
   format,
      formatFix and formatFixed functions (which are
      currently identical to each other) to improve calculation of more
      significant digits for exact values like rational numbers.  (This is at
      the cost of more work needing to be done in this function, so it's
      possibly slower.  That is, it needs to predict how many digits will be
      in the result, and then has to adjust its working precision to calculate
      the full number of digits after the decimal point.)
      For example, the following now produces as many significant figures as are requested:
       format[2/3 * 10^20, 1, 30]
       66666666666666666666.666666666666666666666666666667
      
formatSci[value, divideBy, decPlaces]  (Scientific
        notation)
       formatEng[value, divideBy, decPlaces]  (Engineering
        notation)
       formatSig[value, divideBy, decPlaces]  (Significant
        figures)
       formatFixed[value, divideBy, decPlaces]  (Fixed
        decimal places)
      formatFix and
      formatFix is somewhat deprecated.  See the description in
      the new Formatting Functions
      sections of the documentation.
     image.averagePixels[left,
     top, right, bottom] to allow left and right
    and top and bottom to be out of order.
  electroncharge to be negative.  Also
    added units elementarycharge, protoncharge,
    neutroncharge, upquarkcharge and
    downquarkcharge, and modified several definitions to use
    elementarycharge instead of electroncharge.
    Thanks to Enon Harris for the catch.
    
   = to := in defintions of Mars's moons
    Phobos and Deimos in the standard data file.  Thanks to Daniel Beskin for
    the catch.
    Also thanks to Daniel for writing an entertaining introductory article about Frink.
graphics object, the text can now
    contain embedded newlines, which are broken into separate lines and
    handled appropriately.  This makes it much easier to lay out multi-line
    blocks of text.  It is now essential to explicitly set a font size on a
    graphics object before adding multi-line text.  Example:
    
     
      g = new graphics
    
      g.font["SansSerif", 12]
      g.text["One\nTwo\nThree"] // Note newlines
      g.show[]
     
     (To be more precise, the text was always rendered where it should have
     been, but due to miscalculation of the bounding box, it may not have been
     visible in the rendering area if it was on the edge of the graphic, or
     the only thing in the graphic.  This did not affect the default case
     where the text was centered at the specified coordinates, but may have
     affected cases where horizontal and vertical alignment was not
     "center".)
   
array.lexicographicPermute[function] which
    takes an ordering function to perform the permutation. See the Array Methods section of the
    documentation.
   (I tried to make each bitmapped image only render to the SVG one time, even if it was rendered multiple times, like the fix for HTML files above, but after much effort, I found that according to the SVG spec, the image tag cannot reference elements within an SVG file, so you can't reference a single image multiple times. I tried.)
new
      keyword or constructExpression function are now printed
      more specifically.
      
     constructExpression function.
    graphics.fillCenter[img, cx, cy, width,
      height] and graphics.fillCenter[img, cx, cy,
      width, height, leftSrc, topSrc, rightSrc, bottomSrc] methods
    which draw an image onto the graphics object with the
    specified center coordinates (cx,cy), making it completely fill the
     specified width and height without modifying the aspect ratio.  Note
    that this may cut off part of the image.  See the Images section of the documentation for more.
  GeneralPath, which
    means that graphics can now be clipped to all of the
    two-dimensional shapes that Frink supports.  See the Clipping Graphics section of the
    documentation for more.
   A cool thing about the clipping implementation is that, like all of Frink's graphics, you can render to any coordinate system that makes sense to you, even if it's rotated, scaled, skewed, and clipped, and Frink will automatically center and scale that into your graphics window by default, greatly simplifying many graphics programming tasks. In other words, this can be used to "zoom in" on a section of a larger graphic--just set a clipping region before drawing the graphic and only the section within the clipping region will be displayed.
See the Clipping Graphics section of the documentation for more.
     This feature is being gradually implemented in current browsers, (but not
     yet in the official 
      HTML5 Canvas spec!)  Your browser needs to support the HTML
     Canvas's context.fill("evenodd") method for Frink's graphics
     to work properly now.  This appears to be supported in current versions of
     Firefox (21+), Firefox on Android, Chrome (27+), Opera (15+), Safari 8.0,
     and IE11 (according
      to this).
  
random[min, max] and random[int]
    functions can now handle arbitrarily-large integer arguments (previously,
    they could only handle arguments with magnitudes up to 231.)
    This change was inspired by my Twitter contest: "What is the smallest positive integer that does not return a Google result?" The earlier results were on the order of 1015 which could not be randomly-generated directly. Try your hand at this contest, preferably without peeking at the results from the link above!
lakh (100 thousand) and
    crore (10 million).  Thanks to Emily Lakdawalla for pointing
    these out in her coverage of India's Mars Orbiter's successful orbital
    insertion burn around Mars.
   
     
      array.indexOf[value]
    
      array.indexOf[value, startIndex]
      array.lastIndexOf[value]
      array.lastIndexOf[value, startIndex]
      array.contains[value]
     
See the Array Methods section of the documentation.
left[string, len] and
     right[string, len] methods can now take
     negative arguments for len.  If len is
     negative, it returns a string with -len characters removed,
     that is, if the original string is 5 characters long, and
     len is -1, 4 characters are returned.  In any
     case, if the original string is shorter than the number of characters
     requested, the string returned will contain only the number of
     characters available, and will not return an error.
  exp[n] to not overflow or underflow.  The
    functions in ArbitraryPrecision.frink are still preferred if you need exact, very large exponents.
   parseInt[str,
     base] function.
  It's likely that the current behavior will change further.  If you 
     expect a program loaded from a file to output the last expression
     evaluated, you will soon likely have to wrap it in a
    println[] statement, as Frink will likely someday never
     output the value of the last expression evaluated.
   
format[num, divideBy,
     decPlaces] function.
    The new functions are:
formatSig[num, divideBy,
       decPlaces] : Divides
      num by divideBy and returns a string with
      decPlaces significant figures.  The value will be in
      normal notation when possible and scientific notation when required to
      display the requested number of significant figures.
      
     formatSci[num, divideBy,
       decPlaces] : Divides
      num by divideBy and returns a string in
      scientific notation with decPlaces significant figures.
     formatEng[num, divideBy,
       decPlaces] : Divides
      num by divideBy and returns a string in
      engineering notation (that is, the exponent is a multiple of 3) with
      decPlaces significant figures.
     formatFix[num, divideBy,
       decPlaces] : Divides
      num by divideBy and returns a string in
      with a fixed number decPlaces of digits after the decimal
      point.
      formatFix matches the historical and current behavior of
       the format[num, divideBy, decPlaces]
       function.
      
Warning: format and formatFix are
       almost necessarily broken, lose information, and do not necessarily
       calculate all decimal places correctly, especially when displaying the
       values of exact fractions like 2/3 to a large number of
       decimal places.  The behavior of the format function will
       eventually change to follow the behavior of formatSig as
       listed above.  You may want to prepare modifying your programs now.
       Changing all instances of format[ to
       formatFix[ should preserve the current behavior forever,
       but it is strongly recommended to move to smarter functions like
       formatSig.
    
     In all of the above, divideBy should be 1 if
     the number is dimensionless.  If divideBy is a string, this
     evaluates the string, expecting a unit to be returned, and both divides
     by this unit and concatenates the string after the result.
    
\uFFFF) much more easily and
    correctly.  These changes will not affect you if you don't process high
    Unicode characters, but if you do, there will be some changes:
    For more information, see the Unicode in Frink and Unicode in Strings sections of the documentation.
\u{XXXXXX} places a
     Unicode character into the string, where XXXXXX is a 1- to 6-digit
     hex value for the Unicode codepoint.  For example, to create a string with
     a cat face, you would use "\u{1f638}" (this is the Unicode
     character "GRINNING CAT FACE WITH SMILING EYES".)  For more information,
     see the Unicode in Strings section of
    the documentation.
   
   😸 = "kittyface" // Unicode \u{1f638}
    \u{1f638} = "kittyface" // Alternate ASCII-safe representation.
   
  
array.remove[start, end]
    and array.removeLen[start, length]
    methods to remove a range of items from an array.  See the Array Methods section of the
    documentation.
  
       2014-06-02T02:24:10Z
      
       This required making changes so that quoted text literals in a format
       could actually work correctly. (e.g. the literal character
       T in the example above that separates the date from the
       time.)  The above format is actually specified as:
      
       # yyyy-MM-dd'T'HH:mm:ss #
      
       where the single quotes do not actually appear in the date; they are
       ways of escaping the literal text T.
      
This allows ISO-8601 formats with the custom numeric-only timezone jammed directly onto the end of the date, such as:
       2014-06-02T02:24:10-06:00
      
Z (Zulu; a synonym for Universal Coordinated Time)
      timezone alias.  This is required by ISO-8601 format dates.
     Etc/GMT+7 or
      GMT+7 as defined by the Olson timezone database, the POSIX
      standard, and Java.  These aliases should be considered error-prone and
      dangerous.  Please read that section carefully.
     .S instead of .SSS which gives more
      flexibility and correctness in parsing (using .SSS
      required 3 digits to be present while .S can
      handle 1 to 3 digits.)  There are also bugs in Java's parsing if
      .SSS is used and less than 3 digits were provided.
     graphics.show[insets] method to allow
    you to specify the insets for a graphic without specifying height and
    width. See the Showing Graphics section of the
    documentation for details.
  integerDigits[num] and
    integerDigits[num, base] to return an array of
    the digits of a non-negative integer in the specified base.
  deepCopy[expr] function which was
    broken recently.
  select and
    remove functions now allow
    selector functions with more than one argument.  Previously, all arguments
    were passed as an array to a single-formal-argument function, which will
    continue to work the same if you pass in a one-argument selector function.
    See the documentation select
    and remove for examples.
   select and remove functions now try harder
    to keep their return values as arrays if passed an array, and an
    enumerating expression if passed an enumerating expression.  In addition,
    they now keep dictionaries as dictionaries, OrderedLists as OrderedLists,
    and sets as sets.  To obtain other types,
    toArray[expr], toDict[expr], and
    toSet[expr] functions.  If in doubt, use these
    functions directly to change the return types.
    
   ListExpressions are now also
    EnumeratingExpressions.) Almost all of them were already, but
    now all are.  (The only changes were to ComplexArray and
    ComplexArray2D, used mostly in
    Fourier transforms.)  This
    allows for simplification of some code (e.g. the select
    function has turned into a single, simpler implementation.)
  select and remove functions to make them
    return an enumerating expression if passed an enumerating expression.
    (Previously, they returned an array.  They still return an array if passed
    an array.)  This makes these functions now work properly with very large
    or infinite series, and work much better with long-running operations.
    This change may also allow significantly-reduced memory consumption, as
    you can process each element and then forget about it, rather than holding
    on to a large array of values.
    
     If for some reason you need them as arrays, you may want to wrap the call
     to select in a call to the toArray function to
     restore the original behavior.
    
java.io.File into a
    URL.  This is safer and uses better libraries on Java Virtual Machines
    that have them (at the expense of doing a bunch of call-by-introspection.)
   remove function
    which is the inverse of the select function.  It removes
    items that match a condition from an array or enumeration.
    
   (?!pattern) and (?=pattern) that
    have always been available but were not documented.  See the Basic Patterns and
     Metacharacters section of the documentation for more.
  pound_1914) and then requesting
    another unit for the same year. (e.g. pence_1914).
  Whenever Java Web Start gets confused (which seems to be always,) I always recommend deleting the application from your Java console and reinstalling it from the links in the Java Web Start section of the documentation (after reading the new warnings in that section.) Please let me know if older (or newer) versions of Java Web Start cannot start with these new changes. Again, make sure you read the new warnings in the Java Web Start section first.
staticJava functions now try
    harder to turn their return values into Frink types.  For example, types
    that were previously returned as JavaObject:java.lang.Integer
    are now returned as a normal Frink integer.  This should not affect most
    programs, but If you need the original behavior, you can call the
    three-argument version, with the third argument false
    indicating that the value should not be converted to a Frink
    type.  See the Accessing
     Static Java Fields section of the documentation for more details.
   newJava functions
    to explicitly throw exceptions when the user attempts to call a Java
    constructor with invalid arguments.  Previously, the call could fail
    silently in some cases.  Thanks to Frank van Noorden for the report.
  This involved a large cleanup of lots of formatting code and redesign of many classes which should make it easier to make Frink render code in other languages and supports planned future features like genetic programming.
This involved changes/additions to about 5000 lines of code, and took longer than I thought it would. (This started out as an attempt to make nested data structures indent themselves properly, and became a huge re-design!)
format[expression, format] formats the
      expression to a string using the specified formatter.  Current formatters
      include the strings "Input"
      and "Output".  "Input" is a formatter that
      provides Frink's input form that can be easily parsed by a call
      to eval[str].  "Output" is the
      human-friendly formatter, which has been greatly improved in this
      release.
      
     formatters[] lists the currently-available
      expression formatters.
     inputForm[expression]
      and outputForm[expression] are aliases
      for format[expression,"Input"]
      and format[expression,"Output"] respectively.
      
     showApproximations[],
      rationalAsFloat[], setEngineering[], and
      showDimensionName[] and the :-> operator are
      now local to the interpreter, (and only effect the
      "Output" formatter,) not global to the entire Java Virtual
      Machine.  This makes it safer to embed multiple Frink parsers in a single
      virtual machine, each with their own preferences, and makes Java Server
      Pages more robust against poorly-behaved scripts.  (Programs still need
      to pass a security check to set these flags on an interpreter basis.)
    eval[str]
    functions !)
   # JD 212263942857555001/86400000000 #
     # [JD 212263942933679/86400000, JD 70754647644893/28800000] #
    class specification will
    be output as a dict with name-value pairs for all instance
    variables.  This may change.  This is currently done because there's no
    way to guarantee that the Frink interpreter on the other end has loaded
    the same class or a compatible version.  There are potential
    security and correctness issues if the classes are incompatible.  A
    malicious user could also modify the data to get around security or logic
    checks and create invalid or dangerous objects.  It's currently left up to
    the programmer to take these objects and turn them back into the objects
    they want on the other end.  This may change.
    
   toASCII[str] function to turn a string into
    a network and file-encoding safe ASCII-encoded equivalent.  This is
    useful if you don't want the full quoting of inputForm.
   getChildCount[function] and
    getChild[function, index], expect some changes.
    Hopefully universally for the better.
   do...while loop can now have a newline before
    the while clause when brackets are used:
    
     
      do
    
      {
         println[i]
         i = i + 1
      }
      while i<10
     
getChildCount[function]
    and getChild[function, index].  
    getFunction[name, argCount] actually
      remember their names and allow you to display their names and
      arguments correctly, and call them through an indirect variable.
     inputForm, the body of an function is dumped in a
      usable way (for anonymous functions defined in Frink code.  The body
      of Frink functions implemented in Java are not dumped.)
    expressionConstructors[] function which returns the
    names of all the expressions that can be constructed by name and
    argument list.
   <=> is now a
    proper first-class operator with a proper precedence, and can dump itself
    properly.
   =~ is now a proper first-class
    operator with a proper precedence, and can dump itself properly.
   and instead of &&.)
   toArray[expr] or
    array[expr] can turn an object created from a
    class specification into an array of
    [key, value] pairs.
   toDict[expr] can turn an
    object created from a class specification into a dictionary of
    key, value pairs.
   children[expr]: Returns an array containing
      all the children of the expression.
     childrenWithTypes[expr]: Returns an array
      containing all the children of the expression and their types.
     childTypes[expr]: Returns an array
      containing the types of all the children of an expression.
    frink.servlet.ServletUtils was missing from some builds.
  Update: See their discontinuation statement about their FTP site and their FTP migration document.
sum[list, emptyValue] and
    product[list, emptyValue] sum and multiply
    lists respectively, and if the list is empty, these return the
    user-provided emptyValue.
  parseJSON[string] function.  See the
    Parsing JSON section of the
    documentation.
   java.util.Map (this includes
    classes like HashMap, Hashtable,
    Properties, etc), can now be treated like a Frink dictionary, including the ability to
    enumerate over [key, value] pairs.  See the Iterating over Java
     Collections section of the documentation for more.
   HashingExpressions so they can be
    used as keys to dictionaries, placed into sets, and more.
  parseInt[str] function can now take an array of
    strings as input.
  image class, so an image
    can be copied and the copy can be modified without modifying the original:
    
     
      orig = new image[url]
    
      copy = new image[orig]
     
     Internally, the rendering of polylines was changed from using Java's
     drawPolygon methods (which could only use integer
     coordinates) to using GeneralPath which can use sub-pixel
     coordinates.  It also forces "pure" rendering of strokes in Java's
     graphics subsystem.  This may be slower to render, but the results will
     look much better and be more accurate.
     
    
     Note that this only applies to environments where Java's
     Graphics2D is used (that is, almost any modern Java
     distribution.)  Android's graphics were unchanged as they have always
     rendered properly due to better design of Android's graphics routines.
  
isArray[expr],
    isDict[expr], isSet[expr] to allow
    you to test if an expression is of the specified types.
  Detailed information on the new methods is found in the new Composing Graphics section of the documentation.
graphics.add that
    might have caused a Null Pointer Exception.  Thanks to Nicholas Spies for
    the bug report.
   graphics object from several other graphics
    objects.  You can now add a graphics object to another
    graphics object while automatically scaling it to fit into a 
    specified area, no matter what coordinates it was originally drawn
     to! 
    This makes it easy to take graphics objects from a variety of
    sources, drawn into their "natural" coordinates, and easily compose them
    into other graphics objects.
    Detailed information on the new methods is found in the new Composing Graphics section of the documentation.
editDistanceDamerau[str1, str2] which
    calculates the Levenshtein-Damerau edit distance between two strings.
    This is similar to the editDistance function which calculates
    the Levenshtein edit distance, but also allows swaps between two adjoining
    characters. See the Other String
     Functions section of the documentation for more.
  graphics objects with very little additional
    code.  See the Animated Images
    section of the documentation for details.
  rationalAsFloat[true] is called.  Note
     that the approximations are calculated slightly differently before
     (before, they could use IEEE-754 math and now they use Frink's division
     with proper rounding.)  Many more numbers are correctly displayed as
     "exact" now.  Note that this may change the display of some numbers
     (numbers close to zero with 5 or fewer leading zeros after the decimal
     point are currently not displayed in scientific notation.)  Thanks to
     Phil Knodle for the bug report.
      
   graphics objects
    into bitmapped images in memory using the constructor:
    
     
      new image[graphics, width, height]
     
    
See the Images section of the documentation for more examples.
readLines[URL] to read the
    contents of an entire URL into an array with one line per entry.  Thanks
    to Millicent (whose name, when converted to lowercase, is a parseable
    Frink unit) for the inspiration.
  base64[integer] to encode an integer to/from
    a string in standard base64 encoding format.  If passed an integer, returns
    a string representing the integer as a base 64-encoded value.  This uses
    standard base-64 indices in the order A-Za-z0-9+/.  If passed a base-64
    encoded string, this returns an integer with the corresponding value.
   base[integer, base] base conversion
    function can now have 64 as a base.
   parseInt[integer, base] base conversion
    function can now have 64 as a base.
  graphics.alpha[opacity] command to set
   the transparency (often called "alpha channel") of all subsequent drawing
   operations.  The opacity is a dimensionless number from 0 (fully
   transparent) to 1 (fully opaque.)  This primarily allows you to draw
   transparent images, as transparency could already be specified when setting
   colors.  If a color already has a transparency, that transparency value
    will be multiplied by this global transparency.
   graphics.alpha[opacity] before rendering the
    bitmap.
    
    This global alpha channel also affects any other subsequent drawings that are being done, multiplying the alpha channel in drawn colors by the global alpha channel.
The first sample was posted today, exploring and quantifying the effects of the Coriolis effect on a kicked football (or other projectile.)
next LABEL level statement
    to jump to the next specified level of a multifor
    construct. See the documentation for multifor and the sample program multinexttest.frink
    for more.
   OrderedList to take a second
    parameter which is an arbitrary data object that will be passed to the
    comparison function.  See the documentation for examples.
  OrderedList, which extends
    array but automatically keeps items in order.
    
   image.toComplexArray[] method which turns the
    pixels of an image into a 2-dimensional array of complex numbers
    (ComplexArray2D) which can be manipulated, Fourier
    transformed, etc.  The behavior of this method will change.
   ComplexArray and ComplexArray2D, primarily for
    transforming the pixels of an image.
   ComplexArray and
    ComplexArray2D classes to support Fourier analysis of images,
    normalizing, etc.  These methods may change so they're not documented yet.
  /g modifier and assigning the results to a variable
    directly (as opposed to using it in a for loop.)  Spurious
    null values could have been appended to the list, and the return values
    could be duplicated.
   set.putAll[expr] method to put all of
    the elements of expr into the set as individual items.  See
    the Sets section of the documentation for
    examples.
   dict.remove[key] method.  This returns
    the value corresponding to the key that was removed, undef if
    the key was not in the dictionary.
  As a result, Frink will now temporarily fetch the file from my site, http://futureboy.us/frinkdata/cpiai.txt instead of the URL ftp://ftp.bls.gov/pub/special.requests/cpi/cpiai.txt . I mirror the file on a daily basis for now. The current release of Frink will fix the problem temporarily.
This problem didn't affect Android. I guess their programmers use more sane FTP code.
Frink has always tried (and usually succeeded after about a 90 second timeout) to fall back to an internal copy of the Consumer Price Index file, but in the case of the web page, the timeout for the FTP connection was longer than the webpage's timeout, so it never had a chance to complete.
Technical reasons: The problem is that modern versions of Java don't seem to retrieve FTP data from the BLS site correctly, specifically this URL.
     I can fetch that file just fine with my web browser or programs like
     wget but Java 1.7 and 1.8 just time out while trying to
     download it.
    
I dug deep into this problem, (packet-sniffing the network traffic and even hacking debug code into the Java Virtual Machine itself) and can put the blame in 1 of 2 places:
I sent the message below to the BLS, but they have proven to be incapable of fixing the problem so far. I have a 1-line fix that fixes Java, but it's against the current JDK 8 codebase which isn't really stable and isn't easily available to customers. I'm not especially positive about getting it fixed on the Java side. I finally got a couple of my fixes to bugs in Java checked into the official code this week. I first gave them those fixes 11 years ago. Seriously.
Message to BLS:
This question is for the person who administers your FTP server, ftp.bls.gov. Please forward it appropriately.
It appears that your FTP server does not correctly handle FTP connections that use the EPSV command. While your server responds to EPSV commands, returning the status something like:
     229 Entering Extended Passive Mode (|||55226|)
    
It is then impossible for a client to make a data connection on the specified port (55226). I verified this manually using telnet and hand-crafted FTP requests. The FTP client just waits until timing out. I don't know if this is a firewall issue on your end, with those ports not opening for listening correctly, but it prevents some clients from working correctly (e.g. anything written in a modern version of Java, which defaults to EPASV.)
If the client uses the PASV command instead, the file transfer works.
If you don't actually support EPSV commands properly in your FTP server and firewall, you must disable them in your FTP server. A web search for "disable EPSV" will probably show how to do this.
I am willing to help you debug this problem further if necessary.
Alternately, is there a way to access the file via an HTTP URL?
array.clear[] method to remove all elements
    of an array.
  NullPointerExceptions.  The design
    and implementation of Java's Calendar, Date, and TimeZone classes are
    quite insane.
  approxTransit function could
    potentially jump a day backward or forward, which could affect the date
    returned by the approxRiseSet, sunrise and
    sunset functions.
  undef is now a hashing expression, so it
    can be placed into a set, used as a key in a dictionary, and so on.
   div, mod, and conforms
      operators into true operators in Frink so they know their precedence and
      can display themselves more effectively.
    colorize.fsp
      and highlight.fsp to have shorter links.  Old links will
      still work too.
  next statements to break out to the next
    iteration of a specified loop (this includes for,
    multifor, do, and while loops.  See
    the for loop section of the documentation
    for an example.
   while loops.
    
   getLowestSetBit[num] function which returns
    the index of the rightmost (lowest-order) one bit in an integer (the number
    of zero bits to the right of the rightmost one bit). Returns -1 if the
    integer contains no one bits.
   shiftLeft[num, bits] function which
    shifts the bits of an integer left by the specified number of bits.  New
    bits will contain zero.  This is equivalent to multiplying by
    2bits but is usually more efficient for large numbers.
   shiftRight[num, bits] function which
    shifts the bits of an integer right by the specified number of bits, losing
    the bits pushed off the right side.  This is equivalent to performing a
    div by 2bits but is usually more efficient for
    large numbers.
  DFT and InverseDFT functions can now take
      2-dimensional arrays as well as 1-dimensional arrays.  See the Other Functions section of the
    documentation for details.
   randomBytes[numBytes] function to generate an
    array of random bytes (as a Java byte array.)
   array.shuffle[] method.
  int, byte, double, etc.)
     
       This helps to disambiguate between previously-ambiguous calls such
       as doSomething[int] and doSomething[float].
       If the value is a floating-point value, the above will always select
       the float method, rather than indicate that the call is
       ambiguous.  If the value happens to be an integer, this is still
       ambiguous, because the integer could be coerced to a float
       parameter (but not the other way around.)
     
The code still does not try to disambiguate by the size of the value,
       such as between (int and short)
       or (double and float) if the value will fit
       into both, but if an integer value is too big to fit into a short, this
       will be unambiguous.
  
getSensorService[sensorNum,
       updateFrequency] which allows the user to specify the
      update frequency for sensors.  See the documentation for SensorService for more
      information.
      
     SensorService.getAccuracy[] method to return the accuracy of the readings from the sensor.
     SensorService.waitForValues[]
      method.  This returns the latest raw values from the sensor as an array
      of floating-point values without dimensions.  If new, unread values are
      available, this returns them immediately, otherwise it blocks until new
      values become available.  This is much preferable to polling.
     waitForGPSLocationJava[]
       method which returns the current-known
      GPS position as a Java object of type Location.
      If a new, unread GPS location is available, this returns it
      immediately, otherwise it blocks until the next GPS location is
      available.  It should not return data until GPS locations are being
      returned.  This is much preferable to polling.
    return,
      next, and break to be faster.  When calling a
      tight loop with short functions that return data, performance was
      improved by a factor of 2.7 to 3.4 on some architectures and JVMs!
      Unfortunately, it's only 1.15 times faster on Android/Dalvik.
    listen[prompt,
     numOptions] to actually present no more than the specified
    number of options to the user.  Thanks to Andrew Webb for the bug report.
  eval
    statement or when restrictive security has been turned on.)  This prevents
    untrusted users from calling potentially-unsafe methods on arbitrary Java
    objects that might be accessible from their scope.
   callJava["classname", "method", argList]
    can now be eliminated if there are no arguments to the method.
   callByName[obect, "methodName", argList]
    can now be eliminated if there are no arguments to the method.
    
   newJava function to simplify and
    reduce code.
   getChildCount[function] and
    getChild[function, index] to do useful things.
    Child 0 of a function is now a string representation of its argument list,
    (which may change to a more useful object type in the future),
    and child 1, if it exists, is the body of the function.  This may allow
    you to do interesting things like take the derivative of a user-defined
    function.
  lines[] function can now be a
     java.io.InputStream, allowing you to iterate over
     InputStreams provided by other libraries.
   new image[java.io.InputStream]
     allows you to construct an image from a java.io.InputStream,
     possibly entirely in memory.
   graphics.rotate[angle, cx, cy] and
    graphics.scale[sx, sy, cx,
     cy] to rotate and scale around the specified point
    respectively.  See the Transforming Graphics section
    of the documentation for more information. 
   graphics.transform[a,b,c,d,e,f] which allows you
    to specify all the coordinates of the affine transformation matrix,
    enabling skews and other effects.  See the Transforming Graphics section
    of the documentation for more information.
   java.util.Iterator or
    java.util.Iterable interface are now turned into Frink
    enumerating expressions, which means that they can now be used in
    for loops transparently, among other uses.  This is done in a
    call-by-name fashion so the code will still work on Java 1.1 and later.
  This makes many graphics coding tasks much simpler. It also makes certain things possible that were impossible before, such as rotating bitmaps or distorting text. These few little functions add a huge amount of power, while even allowing you to simplify your code!
See the Transforming Graphics section of the documentation for more information.
getBoundingBox[graphicsExpression] now returns
    undef if graphicsExpression contains an empty
    bounding box.  (That is, there are no drawable elements in it.)
    
   obj.member)
     obj.member in
      transformation rules.
    startGPS[minTime, minDist] which allows you to
    configure the GPS unit for less power consumption if you want less-frequent
    updates, or want to try to force your device to send updates more
    frequently than once per second (mine won't.)  See the GPS/Location section of the
    documentation for more information about this function.  You probably don't
    want to use this version of the function without a lot of testing on
    multiple devices and Android versions.  (The Android documentation says
    that Android versions before 4.1 (Jellybean) could have ignored these
    settings.)
  noEval[expr] block if you don't want them to evaluate
    their arguments first:
    childCount[expr] (Returns number of children of
      the expression.)
     type[expr] (Returns the type of the expression as
      a string.  This behavior may change to return a more useful object in
      the future.)
     isConstant[expr]  (Returns a boolean value
      indicating if the specified expression is constant.)
    Also note that the behavior of these "undocumented" functions may change in the future, or the functions may be removed entirely.
ellipse function but most browsers don't implement that
     yet, so we have to draw circular arcs and transform them to kludge around
     it.)
   canvas feature.  While HTML5 will not be a finalized
    specification until at least 2014, major modern browsers for desktop and
    mobile devices (Firefox, Chrome, Opera, Safari, IE) support the HTML5
    features that Frink requires.  This includes the following features:
    data URIs encoded in base-64, allowing you to send the
      entire graphic as a single HTML file.  Bitmapped images are transmitted
      at the end of the file, and displayed as they are loaded, allowing
      progressive display of documents containing multiple bitmaps.
     GeneralPath, partially-transparent graphics, and rotated
      text.
     1 inch) does not get rendered properly to HTML5.  I'm
        still doing research to see if we can get a reasonable resolution
        figure from the rendering environment.
        
       GeneralPath and self-intersecting filled
        polygons.  HTML5 only supports the rather stupid and useless nonzero winding rule which will make some objects
        with "hollow" centers not render the same in HTML5 as they do in all
        other sane environments (e.g. Swing, AWT, Android, SVG, PostScript,
        PDF).
        This means that you may have to draw the inside and outside paths of an object with "holes" in different "directions" to make it work correctly. See GeneralPathTest.frink for an example of a working and non-working hollow object. The commented-out code demonstrates how the code had to be changed to accommodate this stupid deficiency in HTML5, which will hopefully be improved before the specification is finalized.
Frink goes to some lengths to kludge around this problem, such as by alternating the drawing direction of circles/ellipses each time one is drawn. Sigh.
canvas
        element, Frink could theoretically render a small thumbnail image (or
        full-resolution image, but that would be wasteful) showing the user
        what they're missing.  If the browser doesn't support
        canvas, the user is warned about possibly needing to open
        the document in a newer browser.
      FrinkImage interface to render to
    an OutputStream instead of a File, which gives
    more flexibility to the rendering process, and allows images to be
    rendered to base-64 strings in memory, for example.
   image.toBase64[format] method to allow
    a bitmapped image to render itself to a base-64 encoded string in the
    specified image format (e.g. "jpg", "png").
   graphics.toBase64[format, width,
      height] method to allow a graphics object to render itself, as a bitmap, to a base-64 encoded string in the specified image format (e.g. "jpg",
    "png").
  zip[a, b] and zip[a,
   b, defaultA, defaultB] functions to "zip"
   together corresponding elements of lists a and b
   and return each pair as a two-element array. See the zip section of the documentation for more.
   base64Encode[expr,
      encoding] function can now take a Java array of bytes
    for the input expression.
   base64DecodeToBytes[string] function to
    decode a base-64 encoded string to a Java array of bytes.
  array.pushAll[array] method to push
    all elements of an array onto the end of another array.
   array.removeAll[value] to remove
    all elements in the array which have the specified value. 
  [a, b] = 1 now assigns a=1 and
      b=undef (previously nothing was assigned if the
      right-hand-side was not a list.)
     map function:
    map is a
      string indicating the name of a function.  This allows you to call
      simple functions like:
      
       
        a = [[1,2],[2,3],[3,4]]
      
        map["lcm", a]
       
Thanks to Hakan Kjellerstrand for many useful suggestions and tests.
#2000 Jan
     1#.
  split function when passed an empty 
    delimiter string. 
  
     multifor [f,g] = [new range[1,3], new range[f+1,3]]
    
         println["$f $g"]
      
listen[prompt] and listen[prompt,
     numOptions] will now listen for voice input and return the
    text as a string.  This is extremely powerful, and it allows you to write
    voice-controlled programs, automatic translators, voice calculators, and
    more!  For more information, see the Speech Recognition section of the
    Android documentation.
  units[1] .
   void doSomething(Serializable)
     void doSomething(CharSequence)
     void doSomething(String)
    
     Formerly, if we iterated in that order, the code would detect that
     neither of the interfaces Serializable nor
     CharSequence were more specific than each other (sharing no
     common parent class,) and disambiguation would fail.  However, the new
     code now detects that String implements both
     interfaces and dispatches to the String version.
    
A sane class hierarchy wouldn't have cases like this, but Android does not have a sane class hierarchy. This will help to work around some issues with Android calls, and enables us to do things like send messages prepopulated with text!
AmbiguousMethodException if method
    calls can not be disambiguated.  (Previously, it would just print an error
    and continue.)
  speakSAMPA now sends out a briefer SSML
     (link opens in new window) string that appears to work better on many
     devices.  The language used is no longer hardcoded to en-US
     but should better follow your platform's voice.
     encodeSAMPA function to allow you to encode part
      of a string to be pronounced correctly.
     = to Android user interface.  Thanks to Albert de
    Koninck for the suggestion.
  9 AM and 10 PM to the date formats file.
  set.subsets[] and
    set.subsets[allowEmptySet, allowOriginalSet]
    to return subsets of the elements in an set.  For more information, see
    the Sets section of the
    documentation.
  setDifference[arg1, arg2] function now
    tries to coerce its arguments into sets.  This allows you to perform
    set-like differences on arrays and other types.  Note that ordering and
    duplicates will be lost from arrays in this case.
   array.subsets[] and
    array.subsets[allowEmptySet, allowOriginalSet]
    to return subsets of the elements in an array.  For more information, see
    the Sets section of the
    documentation.
  I've kludged in a workaround to my build processes to get a release out, and I've pushed it to the market. You should see the new version as "2012-06-09b". Sometimes it takes Google a long time from when I upload the new software until it is available in the Market or visible from devices, so please wait a bit if it's not visible.
union[a, b] function to return the
    union of two intervals, or an interval and a real number.  (Or two real
    numbers, in which case an interval containing both real numbers is
    returned.)  The return type will be an interval or an ordinary real number
    if the two numbers are the same real number.  It also works with dates and
    date intervals.
   min, max,
    union, and intersection work with date intervals.
  input functions which make it
   easier and more consistent to build simple interactive applications that
   work consistently across operating systems, windowing libraries, and in
    text-based input mode:
    input functions to behave
      similarly on user cancels.  This means that if the user cancels/closes
      an input dialog, or end-of-file is encountered, all input
      functions return the special value undef.
     undef.
     undef on window close. (Previously, you couldn't close it.)
      Made multi-line input windows return undef if
      closed/cancelled by user.
     input functions will return
      undef when end-of-file (EOF) is encountered.  If EOF is
      encountered on the first line of a multi-input field, the return value is
      the single value undef.  If EOF is encountered
      after the first line of a multi-input field, the
      partially-completed values will be returned, and the rest of the fields
      will be undef.
     input function, hitting the "back"
      button now returns undef when cancelling single and
      multi-line inputs.
     4^(1/2) is immediately simplified to 2, and
    8^(1/2) is immediately simplified to 2 *
     2^(1/2).  Other fractional powers are similarly simplified.  The
    compile-time simplifications improve symbolic math.  More compile-time
    simplifications and canonicalizations will follow.
    
   intersection[arg1,arg2] function to
    return the intersection of intervals or ordinary units.  The return type
    in this case will be an interval or an ordinary real number.  If there is
    no intersection between the arguments, the function will currently return
    undef although this behavior may change to return an empty
    interval in the future.
   min and max functions do something
    sensible when passed overlapping intervals.  (Previously, they just threw
    an OverlapException, which could be improved.)
   sunMoonAngularSeparation[date] to
    geocentricSunMoonAngularSeparation[date] to make it more
    clear that the calculation was from the center of the earth.
   sunMoonAngularSeparation[date, lat, long] to calculate the
    angular separation of the sun and the moon from a particular point on
    earth.  This is usually the function you want.
  newJavaArray function.  For example, the following creates a
   two-dimensional array of double with dimensions 3 by 4:
  
   
    d = newJavaArray["double", [3,4]]
    
    d@0@0 = 3.14
     
See the Creating Java Objects section of the documentation for more.
new dict[array]
    to construct a dictionary from an array.  See the Dictionary Constructors
    section of the documentation for more.
   toDict[array] function which behaves exactly
    as the constructor above.
    
   new dict[keys,
     values] to construct a dictionary from two separate arrays
    (or enumerating expressions.) 
    See the Dictionary
     Constructors section of the documentation for more.
    
   dictionary.invert[] method to return a new
    dictionary with key-value pairs inverted.  See the Dictionary Methods section of the
    documentation for more.
    
   ceil[x,y] and floor[x,y] to
    round x up or down to the nearest multiple of y,
    analogous to the two-argument version of round.  See the Rounding Functions section of
    the documentation for more.
   read and lines functions now allow the
    first argument to be an instance of java.io.InputStream,
    which simplifies reading from other input streams (for example, 
    reading from a URLConnection or an external process, or a
    pipe.)
  dollar_1910).
   map[function, list] applies the
    specified function to all the members of a list, and returns a new list
    containing the results. See the map section
    of the documentation for more.
   getFunction[name, numArgs] which
    returns a reference to the function with the specified name (specified as
    a string) and number of arguments.  This can then be assigned to
    variables, or called as noted in the Anonymous Functions and map sections of the documentation. 
   split and join sections of the
    documentation.
  Writer class to enable easy writing to
    files without including external libraries.  See the Writing Files section of the
    documentation for more information.
   urlFile[string] to return a string indicating
   the filename of a specifed URL string, that is the last path part of a URL
   (e.g. "http://futureboy.us/frinkdocs/whatsnew.html" will
    return "whatsnew.html")
   urlPath[string] to return a string indicating
    the entire path of a specifed URL string,
   (e.g. "http://futureboy.us/frinkdocs/whatsnew.html" will 
    return "/frinkdocs/whatsnew.html")
   browse[URL] function to launch the specified
    URL in your computer's browser (or however your computer likes to launch
    things.)  This also works on Android, but Android doesn't like to launch
    many protocol types other than http.
   isComplex[expr] function.
   eulerTotient[1] to return 1.
   hashCode[expr] to return the hashcode for a
    particular expression.
  allFactors function which effectively
    made the parameter onlyToSqrt always equal false.  Thanks to
    Tom Louie for the bug report.
   sort function to allow the user to
    pass in arbitrary "helper" data to be used in a sorting operation.  See
    the Sorting section of the documentation
    for more information.  Thanks to Jim Fishman for the report.
  read[location] to read from standard
    input (stdin) if passed the argument "-".  See the Reading Entire Files section of
    the documentation for examples.
  callByName[object, methodName, argList]
    function.  See the Calling Functions and
     Methods by Name section of the documentation for more.
   slice[array, start, end] and
    sliceLength[array, start, length]
    functions to take a "slice" out of an array.
   lines[location] to read from standard
    input (stdin) if passed the argument "-".  See the Reading Lines section of the
     documentation for examples.
   messageDigestInt[str, algorithm] to
    calculate a message digest and return its value as an integer.  See the
    sample program drawMD5.frink which
    graphs the output of subsequent inputs to the MD5 hashing algorithm.
  array.combinations[take] method to
    generate the combinations of the elements in an array.  See the Array Methods section of the
    documentation.
   combinations method to enumerate all
    possible 5-card poker hands.
  doSomething(String) and
      doSomething(Object), and the method is passed a string,
      Frink will call doSomething(String).  This will not yet
      disambiguate between primitive types.
     void now return Frink's
      void type instead of undef.  I don't really like having a
      void type, so this may change back.
    newJava function now displays the original cause of
    the exception in the case of an InvocationTargetException.
  input
    functions.
    input functions now return undef at EOF, or
      when the user enters an end-of-file (EOF) character (usualy Ctrl-D on
      Unix variants, Ctrl-Z on Windows).
     input function.  A trailing space is
      still added if the prompt string is non-empty.  This is to make input
      legible and give some uniformity to both GUI-based and command-line
      based calls to the function.
     input function now returns undef for arguments
      on which the user enters the EOF character and for following arguments.
     input functions now works in a less error-prone fashion.
      Previously, it could throw NullPointerException if you were
      testing its return value in certain ways.  Now, with it always returning
      undef on EOF, its behavior is more predictable.
     readStdin[] to read
      one line from standard input.  This is just like calling
      input[""] from command-line mode, which is what you really
      want to be calling if you're trying to make programs that work both
      interactively and non-interactively, and in GUI mode and non-GUI mode.
     12^-1 is immediately reduced to the exact rational number
    1/12.
  parseToExpression[str].
   setIntersection[set1, set2]
    function.
     
   setsIntersect[set1, set2] function.
   allFactors function to find all factors of a number,
    not just the prime factors.  See the Number Theory section of the 
    documentation for more information.
   for loop or range object
      to be boolean values, for example:  for a=false to true.
   for loop.
   not
    operator.  If possible, this simplifies boolean expressions on
    construction.
   graphics.print[] and
    graphics.printTiled[pagesWide, pagesHigh] functions
    now print with no insets--that is, they print as wide as possible on the
    page.  (Previously, they filled up 95% of the page.)  If you want the old
    behavior, see the new functions that take insets arguments in the Showing Graphics section of the
    documentation.
   image.print[] and
    image.printTiled[pagesWide, pagesHigh] functions
    now print with no insets--that is, they print as wide as possible on the
    page.  (Previously, they filled up 95% of the page.)  If you want the old
    behavior, see the new functions in the Images section of the documentation.
  image.getPixelAsColor[x,y] and 
    image.setPixel[x,y,color] to allow getting/setting
    pixel colors from a portable color object that can also be
    used on graphics objects.
  methods[obj] function will now display argument
    types and return types of a method if known. Notably, this is only for
    methods on Java objects at the moment.  This makes it easier to play
    around interactively with Java objects without a reference.
    
   getBoundingBox[graphicsExpression] to return
    the bounding box of a graphics expression.  See the Graphics Functions section of the
    documentation for more.
   \u00B0) to the standard
    datafile as a synonym for degree.  This is an
    angular degree and should not be used for temperatures.
   frink.jar now launches the Swing GUI
    by default.  If you're on some old Java VM without a Swing implementation
    and you've been launching Frink by something like the equivalent of
    double-clicking the file, you'll need to specify the old AWT main class
    when you start.  See the Running
     Frink section of the documentation for more information.
    
   polyline in an enviroment that
    uses Java's Graphics2D class.  This might have manifested as
    "blurred" polylines if your Java platform's renderer isn't repeatable.  The
    internal method for rendering also changed from using a GeneralPath to
    Graphics2D.drawPolyline, which might be a bit faster or more
    memory-efficient.
  product[x] function to return the product of
    the elements of an array or enumerating expression.
  \u00F7 ) as a
    synonym for the normal divide operator.  And why not.  This complements
    the other Unicode multiplication operators × ( \u00D7
    ) and the Unicode "INVISIBLE TIMES" operator ( \u2062 ).
   moonTransit and sunTransit functions.
     moonrise, moonset, sunrise,
      and sunset functions now return undef when the
      body is circumpolar and does not rise or set for that date (rather than
      just doing something undefined.)
    array@index .  Symbolic values can now
    be retrieved from an array correctly.
   new range[lower, upper] and new range[lower,
     upper, stepSize] constructors to create a range operator.  This is
    similar to writing lower to upper or lower to upper
     step stepSize, but more useful in many places.
   new range syntax.
   multifor construct.  Compare this to the allFactors.frink
    program which does not use the construct.
   new range syntax to the For Loop documentation.
   multifor structure support to the Frink Emacs Mode.
  multifor loop construct to perform several
    loops at once.  See the multifoor loop section
    of the documentation.
  toString[expr] to convert an expression into
    a string.  This could already be done in other ways, but this may be more
    concise in certain cases.
  binaryToGray[num] and
    grayToBinary[num] functions to convert numbers to/from
    binary reflected Gray code.  More information in the Other Functions section of the
    documentation.
   new array now match the arguments for
   makeArray  See the Initializing Arrays section of
     the documentation for more information.
   select statement that allows
    you to pass in arbitrary helper data.
   Worked around a bug in Java's Calendar.add
     method which exists in some JVMs.  This would cause displayed times of day
     to be sometimes in error by an hour when doing date/time math around a
     daylight saving time boundary, usually only during part of that day.  It
     is very strongly recommended to update.
    
     It's not clear which JVMs are susceptible to the above bug, but it occurs
     in the latest JVM from Oracle and in current OpenJDK.  All calls to the
     broken and insane Calendar.add methods have been removed.
    
Due to the way that date/time values are stored internally in Frink (as a Julian Day referenced to UTC,) this bug only occurred when formatting dates for display to the user. Internal calculations were still likely to be correct, and this error did not tend to propagate unless a date was output and that text re-parsed as input.
makeArray[dims, initialValue] and
    makeArray[dims] functions to allow easy construction
    and initialization of multi-dimensional (and one-dimensional) arrays.
    See the Initializing Arrays
    section of the documentation for more information.
    
   (1/2)^(-1/2)
    are canonicalized to 2^(1/2).
   image
    as values from 0 to 255, rather than as floating-point numbers.  These
    allow you to work with pixel values as integers, if that's what you prefer.
    See the Images section of the documentation
    for more.
   getPixel[x,y] in the
    documentation.  (Arguments were omitted.)
   addLeap[date,offset] and
    subtractLeap[date2,date1].  For more information see the Leap Seconds section of the
    documentation.
  
     a = 10^100
     
      a^(1/20)100000
    
     (8/125)^(1/3)
     2/5
    
bitAnd[n,m],
    bitOr[n,m],
    bitXor[n,m],
    bitNor[n,m],
    bitNand[n,m], and
    bitNot[n] to perform efficient bitwise operations on
    numbers.  See the documentation
    for more information on how these functions work.
  == and != operators to test sets for
    equality and inequality.  Previously, they just returned the identity
    equality (that is, true iff both sets pointed to the same object in
    memory.)
   equals method for sets to be more
    reliable.
   deepCopy[expr] call.  It does, however, allow reduced
    memory usage and faster execution, and more control to the programmer.
   class specification were made deep-copyable, and were
    deep-copied when put into a set, triggering the problem, which manifested
    itself when the identity comparison == started returning
    false for the copied object.
  a AND b AND c are parsed into a single AND expression with
    three children.
   deepCopy[x] function now also copies the fields
    of objects generated from a class specification.  It performs
    a recursive deep copy of all the parts of a container class.  The function
    can be called with any expression type.  The function currently deep copies
    everything contained in arrays, dictionaries, sets, and objects created
    from a class specification, and everything contained within
    them.  It is thus useful for copying nested data structures,
    multi-dimensional arrays (which are arrays of arrays, etc.) and prevents
    modification of the original or the copy from changing the other. It does
    not currently deep copy Java objects, nor Java arrays, nor
    enumerating expressions.
  moonApogee[date] and
    moonPerigee[date] functions.
   
     /* This is a 
    
         multi-line comment. */
     
See the Comments section of the documentation for more information.
     
      #!/path/to/frink 
     
    
     then you can start Frink programs easily from a (newish) Bourne or bash
     shell, by just typing the filename, instead of frink
     thefilename. (Up until recently, many versions of bash or sh
     wouldn't allow you to specify another script as your start script; it
     required an "executable binary" magic number.)
    
unit_
   mol in the
    standard data file from substance to
    amount_of_substance.
   if/then and if/then/else
    statement.  Thanks to Laszlo Hars for the bug report.
  
   [first, last] = input["What is your name",[["First
    Name", "Jeff"], ["Last Name", "Albertson"]]]
  
     
    
This works on Swing, AWT, and Android GUIs, and in pure text mode.
     
      b = new set[1,2,3]  // Construct a set with
      the specified elements
    
toSet[x] function to turn the specified
    expression into a set, if possible. This works with enumerating
    expressions, arrays, or simple expressions (making a single-item set out of
    the latter.)
    
     
      c = [3,6,9]  
    // Create an array
      d = toSet[c] // Create a set from the
       array
      
   The following single-line program demonstrates turning an enumerating
   expression into a set (the lines[url] function returns
   an enumerating expression of all of the lines in a file,) turning that into
   an set (to remove duplicates) and sorting it (implicitly turning it into an
   array in the process.) The result is a sorted array containing all of the
   unique lines in a file, discarding duplicates.
  
     
      sort[toSet[lines["file:myfile.txt"]]]
     
    
     
      #!/path/to/frink 
     
    
     then you can start Frink programs easily from a (newish) Bourne or bash
     shell, by just typing the filename, instead of frink
     thefilename. (Up until recently, many versions of bash or sh
     wouldn't allow you to specify another script as your start script; it
     required an "executable binary" magic number.)
    
repeat[str, times] method to repeat a
    string the specified number of times.
   padLeft[str, width, padChar] and
    padRight[str, width, padChar] functions
     to pad a string to the specified width.
   speakSAMPA[str] to speak
   strings encoded in the Extended SAMPA
   alphabet.  This allows you to describe exactly how text is to be
   pronounced.
  set.shallowCopy[] method.
   eval[expr, rethrows,
      hidesPrevious] function to allow hiding of local variables.
   class definition to be
    added to sets and dictionaries.  For now, only the identity of the object
     is used for hashing.
     
   getSymbolsByComplexity[expr] function to
    return a list of the symbols in an expression with a rough estimate of
    their depth and usage.
  Frink class to simplify setting of
    variables from an Object.  See Frink's integration
    methods, specifically for the Frink class.
  child[expr,
     index] when expression has no children.
  inverseErf and inverseErfc
          calculations greatly by implementing a much faster algorithm
          for their tails.  This improves performance by orders of magnitude in
          the tails of the inverseErf and inversePhi
          functions.
        inversePhi[phi, mean, sd] function.
        sqrt for numbers between 0 and 1.
        sqrt for numbers too small to be
          represented by IEEE-754 double-precision math, that is, smaller than
          10-323.
        sqrt function to work with negative numbers.
      setDefaultTimezone[tzstring]
     function to allow setting of default timezone used for parsing and
     display.
   dict.containsKey[key] method to see if
    a dictionary contains the specified key.
  array.push[x]
    method.  You can now push symbolic quantities onto an array correctly.
    
   kcal_mol to be cal_mol so
    various prefixes would work with it.  You can still write
    kcal_mol of course.
    
   J_mol so you could write stuff like
    kJ_mol.  Thanks to Richard Terrett for the suggestions.
  .frink can
   now be launched from applications like Astro, or launched with an Intent
   with the ACTION_VIEW
   action. (the data must be a Uri
   with a file: URL.)  This allows you to, say, make a folder of
   Frink programs on your Android device that can be opened with a single
   click.  See the Viewing Files
   section of the Android documentation for more information.
    
    The following restrictions on launching files are for security reasons:
.frink extension will be launched if they
      are on the filesystem.  Files with the .frink extension
      will never be launched from http URLs or from the
      network.
    /lib", even if it didn't have
    anything in it.  Dear Android Market, you are the worstest thing evAr!
  Integrate[1/x+x, x])
  hubbleconstant with the latest WMAP data.
   x^(1/2) are
    printed correctly with those parentheses.
  isRational[num] function which returns true if
    a number is a rational number (and not an integer,) false
    otherwise.
   === which is intended as
    a special form for equations that are going to be solved, manipulated, and
    rearranged.  It does not do any evaluation on its children, so equations
    can be passed around to functions easily.  Its behavior may change.
   noEval[expr] special function that does not
    evaluate its arguments, but passes them to the next level unmodified.  It
    is primarily useful for symbolic manipulation.  It's similar to the Lisp
    "quote" operator, if that helps you.
   === operator and for
    symbols. This simply means that they can be used in transformation
    rules.
   constructExpression[stringType,
     [args]] 
   getSymbols[expr] which
    to return a set of symbol names
    (now as strings.)  This may change again!
   ===
     operator.
   arctanh[x]
    or atanh[x].  This function works for complex and
    interval arguments.
   lcm[x,y] function to return the least common
    multiple of two integers.
  new image[width,
      height] call.
  doUI[expr] function to
    execute the specified message on the user interface thread.  Android
      requires that many methods, including anything to create views or user
      interface components, is executed on the UI thread.  This allows you to
    call more Java methods to create Toasts, AlertDialogs, etc, that require
    construction or modification on the UI thread.
   graphics.show[width, height] and
    graphics.show[width, height, insets] methods to
    allow display of a graphics window at a specified size (when supported on
    the target platform.)  See the Showing Graphics section of the
    documentation for more information.
  graphics.color[r,g,b]
     and graphics.color[r,g,b,a] methods now return
     a color object that you can use again later to set the color.
   graphics.color[colorObject] method so
     you can set the color with a color object you obtained from the calls
     above.
   new color[r, g, b,
      alpha] and new color[r, g, b] to create a
      color object.  See the Shapes and
      Colors section of the document for more information about these
    methods.  Thanks to Duncan McKenzie for the suggestions.
   frink.jar.  This may prompt you to accept the new certificate
    if you're using Java Web Start.
  NullPointerException when trying to
      assign to something that wasn't a dictionary as if it were a dictionary.
    CharSequence which was first introduced in Java 1.4 and is
    becoming popular.)  Frink still only requires Java 1.1 and later.
   try/catch blocks because they like to throw exceptions rather
   than do nothing gracefully.
   
   new expressions and
     method calls.  This simply means that they can be used in transformation
     rules.  As a result of this, you can now do something resembling operator
     overloading of user-defined classes, such as in
     the simulatedOverload.frink
     sample program.
   NullPointerExceptions in the Android code
     if you're attempting to access sensors or GPS and your device returns
     null for these.  This allows programs to recover from errors more
     simply.  These calls now return undef where Java returns
     null.
  use statements on the Android platform.
    expressionContains[a,b] function to properly
   match expressions.  This manifested itself in a failure to reduce the
   double derivative D[D[x,x], x].
  URLEncode[str, encoding] to
      encode a string to be used as part of a URL.  The encoding should probably
      be the string "UTF8" for most applications.
    URLEncode function above to work, so this release is
      required.
    isSubset[setA, setB]
    and isProperSubset[setA, setB] functions to perform
    relation tests on sets.
  This includes anti-aliased graphics with transparency, animation, image manipulation, integration with the Android's sensors, GPS, text-to-speech, and other features. For more details please see the Frink for Android page.
getSymbols[expr] which returns a set of symbols defined in the expression.
  transformExpressionDebug[rulesetname, expr]
    and transformExpressionDebug[expr] to transform an
    expression and return the intermediate expressions and the
     transformation rules used.
   transformExpression...[rulesetname,
     expr] functions can now also take an array of
    strings for the rulesetname parameter which contains the names
    of multiple rulesets to apply.
  
     (_a:1)
    
     Which creates a pattern called _a which, if it does not
     appear, is assigned the value 1.  For example, if you wanted
     to match a quadratic equation, with optional coefficients for each of the
     the terms, you could write your pattern as:
    
     (_a:1) _x^2 + (_b:1) _x + _c
    
See the solvingTransformations.frink file for a concrete example of a transformation rule that solves quadratic equations.
The method for replacing the default value is pretty interesting and complicated. It actually undergoes all of the symbolic reductions that ordinary expressions undergo, so you can generally write your pattern the same way you write your equations. Again, all possible orderings of commutative/associative operators will be tested.
substituteExpression[orig, from,
     to] to backtrack and try all patterns with conditions in
    all possible orders.
    
   isPositive[num] and
    isNegative[num] functions which return true if 
    a number is a positive (or negative, respectively) dimensionless real
    number, false otherwise.
   transformations block to create a named set of
    transformation rules which can be applied to an expression.  See below.
    Also see the solvingTransformations.frink file which demonstrates the use of this construct.
   transformExpression[rulesetname, expr]
    and transformExpressionTrace[rulesetname, expr]
    to apply a named set of transformations to an expression.
   transformExpressionTrace[expr] function
    to transform an expression and return the intermediate steps as a list.
   molarvolume to follow the accepted defintion (its units are
    now m^3/mol.)  This allows easy conversion of some quantities to and from
    moles.  For example, to find number of moles in 1 gallon of gas at STP,
    you can use:
    
     1 gallon / molarvolume
     0.16888608262948273721
    
isUnit[expr] which returns true if the
    specified expression is a unit of any type, including dimensionless
    numbers.
   eval[expression,
     rethrows] where the rethrows argument is a
    boolean flag indicating if we want errors to be thrown or just suppressed
    and undef returned.  If it is true, errors will be rethrown
    as Java exceptions.
    
   methods[object] function to list the methods
    of an object.
   
       
         f = newJava["java.awt.Frame", []]
    
         sort[methods[f]]
       
In other words, this is a potentially severe bug and it is highly recommended that you update your version of Frink.
getPressureAltitude[pressure] and
   getDensityAltitude[density] to StandardAtmosphere.frink.
   In addition, fixed a potential problem with calculating molecular Hydrogen
    densities below 150 km.
   graphics.writeFormat... methods to allow a
    filename argument of "-" which writes the image data to
    standard output.
  image.print[] and
    image.printTiled[pagesWide, pagesHigh] methods
    to an image to allow them to be easily printed to a printer.
   image.show[] now displays images at their original
    size by default.
   See the Rendering Graphics section of the FSP documentation for more.
moonrise and moonset functions to predict
    rising and setting times of the moon.
   moonSecantAzimuth and sunSecantAzimuth
    functions to handle wrapping around the circle.
   signum[x] function to return a number
    indicating the sign of its argument.  More information in the Other Functions section of the
    documentation.
  Fixed an important bug which could cause underflow when raising a floating-point number to a large negative rational power. It is very strongly recommended to update.
.jnlp files for Java Web Start to hopefully
    allow Frink to start properly even if you're offline or my servers are
    down.  I already had the offline-allowed setting enabled, but
    found another switch dealing with shortcuts that would cause JNLP to throw
    an exception if the server was unavailable.
  x-x would be symbolically
    simplified to 0.  This affects date calculations in a subtle
    way.  A date can now be multiplied by zero, returning 0 s.
      
   In short,
     this is done by calling the replaceGraphics[g] method
     on a graphics window.  Thanks to Warren Schudy for the suggestions.
      
   
sleep[time] function which sleeps for the
     specified amount of time.  The argument time must have units
     of time, for example 1 s or 4.9 minutes
     or 1/30 s.  This supports smooth animation.
  x-x would be symbolically
    simplified to 0.
    Note that this change was rolled back later in the day because it caused premature simplifications of some expressions. Please obtain the current version.
x + 2x is transformed
        into 3x.
      x * 3x^2 is
        transformed into 3 x^3.
    This allows purely symbolic conversions to be performed. For example:
       
         pack = 10 dog
       
         tribe = 10 pack
         tribe / dog
       100
    
     Hint: to avoid "undefined symbol" warnings, call
     symbolicMode[true] which suppresses warnings about undefined
     variables and changes some behavior when encountering undefined symbols
     from fail-fast to a more tolerant deferred evaluation.
    
     Note that at all times, dog is an undefined variable that is
     manipulated purely symbolically.  Also note that prefix, suffix, and
     plural checking is not performed on local variable names, so
     you can't write dog or dogs interchangeably
     like you can if you define a concrete unit.
    
These changes should be essentially invisible to most programs, but may have an effect on variables that later contain interval arguments. The symbolic simplification will sometimes create a different result than the original formulation may have produced. In most cases, the resultant interval will actually be tighter than the previous result, such as in the case:
       
         a = new interval[-2, 3]
       
         a*a
       [0,9]
     
       Note that this interval is tighter than a naïve implementation
       which would produce [-6,9].  This will also symbolically
       simplify expressions such as x/x to 1.
    
isDefined[x] and
     isVariableDefined[x] to test if an identifier is
     defined in the current scope.  The difference is that
     isDefined[x] checks local variables and unit
     definitions, while isVariableDefined[x] just checks
     local variables.
    These functions can be called with either a variable name or a string. For example:
       
         isVariableDefined[a]
    
         isVariableDefined["a"]
       
See the Testing Variables section of the documentation for more.
-> to allow more relaxed
      conversion of undefined variables to give better symbolic behavior.
    x is on the left-hand-side of an expression is:
     
       
         solve[_left == _right, _x] :: freeOf[_left, _x]  <-> solve[_right == _left, _x]
       
     
        The condition follows the :: operator.  This allows much
        more powerful transformation rules to be written.  For example, see
        the solvingTransformations.frink
        file which solves many algebraic equations with only a very small
        number of rules.
      
Note that the syntax for anything dealing with transformation rules may change.
DFT[array, divFactor=-1, direction =
     1] and InverseDFT[array, divFactor=-1, direction =
     1] functions to make a Discrete Fourier Transform of the
    specified array, or its inverse.  These were previously only available in
    the Fourier.frink
    external file.
    
     Note that the default value for divFactor has changed in
     both of these files.  If your code relied on the default value of
     divFactor, you may need to specify it.  See the Number Theory section of the 
     documentation for more information.
    
Re[x] and Im[x] (functions that return
     the real and imaginary parts of a number return the number) with its
     units rather than blowing up if the number wasn't dimensionless.
   eulerPhi[n] function to calculate the
     Euler's Totient of a number.  See
     the Number Theory section of the
     documentation for more information.
   3x sorts before the
     expression y.  This is necessary to make a variety of
     symbolic transformations easier to write.
   -> print "Unconvertable
     expression:" before the expression if it's not convertible and not in
     symbolic mode.  This may make it more clear that the conversion failed.
     If in symbolic mode, this returns the partially-converted expression,
     which might succeed later after setting variables and
     calling eval[] on it.
  unit_ to the standard data file.  This
    allows you to use the original definition of a unit even if you've
    "shadowed" it by declaring a local variable with the same name.  For
    example, if you define a local variable called g, that hides
    the original definition of the gram.  You can get the original definition
    of the unit g by writing unit_g instead.
    Note that this is not generally a problem when writing programs. If you realized that you shadowed a unit definition that you want later in the same function, just rename your variables and run the program again. It's only a problem in interactive sessions, where you're already at the top level and can't undefine the variable.
functions[] function to list the signatures of all
    functions.
  
     Warning:  This release changes the behavior of the
     abs[x] function when called with an interval
     argument.  It does not alter its behavior for any other
     numerical types (e.g. real or complex numbers.)
     
    
The behavior of the abs[x] function has changed for
    interval arguments.  Previously, it returned a single scalar value instead
    of an interval.  To be precise, it used to return the absolute value of
    the endpoint furthest from zero (which is a definition that goes back to
    Ramon Moore's early texts on interval analysis.)  However, this was
    considered to be a surprising definition by many (including myself.)  It
    didn't follow the spirit of absolute value for real numbers, it chose one
    endpoint arbitrarily as being more important than the other, discarded the
    other endpoint and the "main/middle" value, and caused loss of information
    and unexpected results when passing interval arguments to a program
    initially written with real numbers in mind.
     
    
Thus, after surveying a large number of implementations of interval arithmetic and discussing this with the leading practitioners in the field, it was decided to change the implementation of this function to more closely follow the spirit of the definition of abs[x] for real numbers, and to follow a more modern convention that is widely used in interval arithmetic implementations. The abs[x] function now returns an interval (possibly with a main/middle value) which contains the interval that would be obtained by calling abs[x] on both endpoint (and the middle value) of the interval, with one exception. If the interval contains zero, then the lower bound of the new interval will be zero.
     The previous behavior is now moved to a new function called
     magnitude[x] which returns a scalar which corresponds to the
     absolute value of the endpoint farthest from zero.  For symmetry, another
     function mignitude[x] has been added, which returns the
     absolute value of the endpoint closest to zero.
    
This change should make the results of passing an interval to an equation designed for real numbers much less surprising.
Thanks to Alan Stebbens for the initial inquiry into this behavior, and to the respondents on the "Reliable Computing" mailing list and on the IEEE-1788 expert group mailing list, which is working toward defining an IEEE standard for interval arithmetic. Special thanks to R. Baker Kearfott, Arnold Neumaier, George Corliss, Ramon Moore, Dan Zuras and Richard Smith for directly answering questions related to these definitions.
Please see the Interval Arithmetic Status section of the documentation for more information about the new functions.
JavaObject:int) to
    be mapped to that primitive type in a Java call.
  graphics.write[] or when
    calling leap-second-related functions like TAIMinusUTC.  This
    was due to calling some classes by name, and those names no longer matched
    their obfuscated versions in the jar file available to the public.
   g.font["SansSerif", 1 inch].  The
    fix improves cases where the bounding box was wildly overestimated, and
    caused everything to be drawn very tiny.  However, there's really not
    enough information available at the time that the bounding box is
    calculated (because we don't know what other objects may be drawn) to
    calculate an accurate bounding box.  Thus, a zero-sized bounding box is
    calculated, which may make constant-sized text be drawn off screen if it's
    too big, but it eliminates the "everything drawn too small" problem.
   graphics object (which can then be printed, saved to
   a file, printed tiled across several pages, modified, drawn upon, etc.)
    
     This gives the ability to modify images, add watermarks or text to
     images, build collages or thumbnails, rescale images, overlay transparent
     images on each other, and much more.  See the new Images section of the documentation
     to see how to load and display images.
    
   
graphics.write[filename, x, y,
      insets] and graphics.write[filename, x, y,
      insets] which allow you to control the borders around your
    graphics when written to a file. The default is to only use 95% of the
    width and height of the image file to allow a small border around the
    image, but setting insets to 1 (which equals 100%)
    forces 100% of the space to be used, that is, no border to be drawn.  This
    allows an image to be effectively re-rendered to different formats,
    watermarked, or modified, without changing its size or introducing a
    border.
   GeneralPath to allow drawing of true
    ellipses and circular arcs.  This allows drawing of perfect circles with
    transparent holes in the center, which was previously impossible.
    Previously, circular arc segments could be approximated with cubic
    Bézier curves, but this was an imperfect approximation.
    More information is available in the GeneralPath section of the documentation.
GeneralPath class to allow these
    new curve types, and to allow curves to calculate their own tight bounding
    boxes.
   marsday has been changed to use the
    solar day instead of the sidereal day.  Both definitions are
     still available, as always, as marssiderealday and
     marssolarday.
  graphics.print[] and
   graphics.printTiled[pagesWide, pagesHigh] now
   also render the background color.  The background color was not drawn
   previously in an attempt to minimize ink usage, but this is easier than
   drawing a colored rectangle for the background.
  GeneralPath class
    which allows drawing of complicated outlines and filled shapes, which may
    be composed of straight lines and quadratic and cubic Bézier
    curves.  This allows filled shapes with transparent holes (such as the
    letter "P") which were previously impossible to obtain.
    Note: The GeneralPath functionality is only available under Java 1.2 and later.
More information is available in the GeneralPath section of the documentation.
(1/4)^(1/2).  Previously, if intermediate results were too
    big (such as when the numerator of the exponent became large enough,) this
    could stop the program with an error due to overflow.  This situation has
    been fixed.
   graphics.show[] method to suppress
    printing "frink.graphics.PaintController" if it's the last method called
    in a program.
  TAIMinusUTC[date] returns this value.  See the International Atomic Time
     (TAI) section of the documentation for more details.
  ->) when the left-hand-side
    is an interval and the right-hand-side is an array, like:
    
     
      a = new interval[1.0 kg, 2.0 kg]
     
      a -> ["lb", "oz"]
     [(2 lb, 3.2739619495804129157 oz), (4 lb, 6.5479238991608258314 oz)]
     
    
Previously, this would return strange results in a strange format that didn't make much sense. Thanks to Mark Feeney for reporting the problem.
graphics.writeFormat[filename, format,
      width, height] methods so that if filename is
    the string "-" then the image file data is written to
    standard out.
  graphics.printTiled[pagesWide,
      pagesHigh] method to allow a graphics object to be printed to
    a printer at extremely large sizes and tiled across several pieces of
    paper.
   graphics.stroke[width] to
    change the width of the stroke used to draw lines, polygons, or other
    outlines.  (Note that the stroke width can not be changed in Java 1.1.)
  array.remove[index] :
      Removes the item with the specified index from an array and returns its
      value.
     array.removeRandom[] : Removes a
      random element from an array and returns its value.
    More information is available in the Array Methods section of the documentation.
randomSeed[seed].
    To obtain repeatable results with a program that generates random numbers,
    sometimes it is desirable to use the same random sequence.  This function
    seeds the random number generator with a known value.  The seed must a
    number from -263 to 263-1 (both inclusive.)
   graphics.text[text, x, y,
      horizontalAlign, verticalAlign] to allow text to be drawn
    with its sides aligned to the right, left, top, bottom, centered, etc.
    See the Graphics with Text
    section of the documentation for more information.
   Please see the Graphics section of the documentation for detailed information on this major update, including sample programs. This update consists of over 7000 lines of new code, with a large number of new features and capabilities.
input[] function) to return empty strings instead of null
    strings when the user cancels or closes the dialog.  The null strings
    caused problems in many cases, such as simply checking to see if it's true
    or not.
   frink.gui.FrinkStarter class that
    caused errors like "cannot load file --swing" when you were actually
    passing a flag.
  setRestrictiveSecurity(true) method to the
    frink.parser.Frink class to easily enable the most
    restrictive security.  See the Embedding Frink section of the
    documentation for more information.
  frink.gui.InteractivePanel) is now the "Main-Class" of the
    jar file.
    I pondered over this, and figured that if there were platforms (like handheld devices) where you don't have Java Web Start or you downloaded the .jar file and didn't have any way to specify how to start it, or you didn't know what you were doing, and just randomly started it by double-clicking or using the platform's "launch" command or something, it would use the least common denominator to start and display itself, which is AWT and not Swing. So, sorry, if you're just randomly clicking on the .jar file, it may not look as pretty as it (briefly) did, but it should work on more platforms. The differences are probably purely aesthetic.
nextPrime[n] function to return the next
    prime number greater than n.  The value of n may
    be any real number.  This uses a "wheel factoring" method to completely
    avoid checking composites with small factors.
  basetiming.frink to something awful and 1980's era DOS-like
    BASETI~4.FRI.
  # August 19, 1969 AD 04:54 PM #
     # 18 February 3102 BC 06:00 Ujjain #
    #1582-10-04 23:59:59 UTC# (Julian) is followed
    immediately by #1582-10-15 00:00:00 UTC# (Gregorian) Note
    that if a date is specified between these dates, behavior will be
    undefined.
   Ujjain timezone for use in ancient Indian astronomy
    calculations.  See IndianAstronomy.frink for more information.
   setDimensionNameDelimiters[string,string]
   function which changes the text printed around the dimension name (default
   is parentheses).  For example, when you enter "1 K", the
   result is displayed as 1 K (temperature).  Setting
   setDimensionNameDelimiters["UN[", "]"] makes this output as
   1 K UN[temperature].
  showDimensionName[bool] function which
    switches display of the names of dimensions on and off.  For example, when
    you enter "1 K", the result is displayed as 1 K
     (temperature).  Setting this flag to false suppresses
    the "(temperature)" display.  For more information, see the Setting Number Formats section
    of the documentation.
  frink.parser.Frink.getVariableAsDouble(String variable, String units)units to be either null or
    the empty string.  This tries to return the value of the variable as a
    dimensionless number.  And it must be a dimensionless number or an
    exception will be thrown.  See the documentation on Frink's integration methods for more
    information.  Thanks to Alberto Di Lullo for the suggestions.
  secantAzimuth function to calculate the time that
      a planet will pass through a given azimuth as seen from a location on
      earth.
    
     list = newJava["java.util.ArrayList", [] ]
    
      ulist = callJava["java.util.Collections", "unmodifiableList", list]
      ulist.size[]
     
     This problem occurs because ulist is an instance of the
     inner class
     java.util.Collections$UnmodifiableRandomAccessList in which,
     for some reason, the class has no access specifier and is thus "package
     private" which, due to the aforementioned bug in Java's handling of
     method invocation, is considered not accessible (even though the
     method is public) when using reflection, but would be perfectly fine to
     call from compiled code.  Sigh.  There may be a nasty workaround to try
     and call this method via an interface specification, but I'm not sure.
     For more information, see the discussion in the entry for 2007-06-28.  I already implemented some nasty
     workarounds to try and fix part of these bugs.
    
Thanks to Rowan Worth for the bug report.
     100 m -> "ft"
    
     and returned undef in these situations.  The excessive
     security check has been modified.  Thanks to André Sihera for the
     report.
    
deepCopy[x] function to perform a recursive
    deep copy of all the parts of a container class.  The function can be
    called with any expression type.  The function currently deep copies
    everything contained in arrays, dictionaries, and sets, and all of the sets
    contained within them.  It is thus useful for copying nested data
    structures, multi-dimensional arrays (which are arrays of arrays, etc.) and
    prevents modification of the original or the copy from changing the other.
    It does not currently deep copy Java objects, Java arrays, nor
    objects created from a class specification, although it may do some of
    these in the future.
  
     symbolicMode[true]
      f[x] := sin[x] + 4
      f[y^2]
     4 + sin[y^2]
    
\u0966-\u096f.
    
    
     ९८७६५४३२१०
     9876543210
    
approxLog2[0].
   10.0^32000.5
   sqrt[n,digits] in root.frink.  This now
    uses adaptive working precision and smart initial guesses to produce
    results more rapidly.
   6_0).  Thanks to Neal Crook for the bug
    report.
    
   feed_face\\16
     0xfeed_face
     0b0001_0101_0000
    Thanks to Neal Crook for the suggestion.
FrinkVersion[] function to return the current
     version of Frink from within a program.  (You can also find out the
    current version from the command-line by running:
    
     frink -v
     or
     frink --version
    
binomial[m,n] to calculate
    binomial coefficients.  This is of the number of ways m things
    can be chosen n at a time, with order being unimportant.  This
    is sometimes called "m choose n" or "m C n".  This is equivalent to
    m!/(n! (m-n)!) although calculating that way often leads to
    way-too-big numbers.  For example, binomial[10000, 9998] is equal to
    49995000, but if you calculated it naively, you'd have to calculate 10000! 
    which is a 35660-digit number, and divide it by another huge number, which
    could be inefficient and slow.
  ->
    operator, Frink will now make more suggestions for factors to multiply or
    divide by.  Notably, it will look for squares and square roots of existing
    units and suggest those as well.  For example:
    
     (8 pi 1 erg/cm^3)^(1/2) -> gauss
     
      Conformance error
    
   Left side is: 1.5853309190424043 m^(-1/2) s^-1 kg^(1/2) (unknown unit type)
  Right side is: 1/10000 (exactly 1.0e-4) s^-2 kg A^-1 (magnetic_flux_density)
     Suggestion: multiply left side by permeability^(1/2)
 For help, type: units[permeability]
      to list known units with these dimensions.
Thanks to Anne Archibald for the suggestion.
     watt
     1 m^2 s^-3 kg (power)
    
     watt^(1/2)
     1 m s^(-3/2) kg^(1/2) (unknown unit type)
    
The exponents of base dimensions can now be either integers or rational numbers. (Previously, only integers were allowed.)
     This change was necessary to support some systems of units such as the
     Gaussian and Heaviside-Lorentz systems of units, which build on the
     "cgs" (centimeter-gram-second) system of units, but have very different
     definitions of electromagnetic quantities than the International System
     of Units (SI).  For example, in the Gaussian system, electric current has
     dimensions of cm^(3/2) g^(1/2) s^-2, and working
     natively with this system requires fractional exponents.
     
    
While it does not usually make sense to have fractional exponents in
     many systems of measurement nor in physical measurements, it is sometimes
     necessary in some fields, quantum physics being another example.  I have
     also seen the use of fractional exponents in physical equations, such as
     the square root of volumetric flow ( m^(3/2) s^(-1/2) ).
     
    
In the future, enabling fractional exponents may require a flag, but it may not. The reason for having a flag would be to detect certain types of errors as early as possible.
Thanks to Anne Archibald for a very edifying discussion of the needs of handling Gaussian units properly.
a/b where the numerator a was a large integer
    (magnitude greater than 231).  This did not happen in the cases
    where the values of the expressions could be immediately evaluated at
    compile time, but happened when more complex expressions involving
    uncommon operators or functions were encountered, like
    2^40 / 40!.
    
     The error manifested itself by printing
     NotAnIntegerException and halting the program.  This bug did
     not cause silent errors, nor did it ever produce incorrect
     answers; if you encountered it, the program halted with this error
     message.
    
Also note that multi-line mode requires that you click the "Go" button to execute the statement. Hitting the return key just moves the cursor to a new line.
array.pushFirst[x] and
    array.popFirst[] methods to allow pushing and popping
    from the front of an array.
   == or !=
    operators.  Previously, this would return an error.  Comparing complex
    numbers using other relational operators, such as <, will
    still return an error, as the complex numbers are not a well-ordered field.
   EulerMascheroniConstant to the standard data file.
  array.lexicographicPermute[]
    to produce all the permutations of the elements in the array in
     lexicographical order.  This is in contrast to the
    array.permute[] method which returns the permutations
    in no particular order (and does thus not require them to be comparable.)
   update method in
    FrinkCanvas.
   sunApparentRA and
      sunApparentDecl into a single
      sunApparentRADecl function.
     xxxSiderealTime to the more accurate
      xxxSiderealAngle.
     apparentLocalSiderealTime function which was
      completely broken in two different ways.
     hourAngle function to calculate the hour angle of
      an object.
     parallacticAngle function to calculate the
      parallactic angle of an object.
     moonPositionAngle and
      moonPositionAngleRelativeToZenith functions that calculate
      the position angle of the moon's bright limb relative to the North Point
      of the moon and the zenith respectively.
    paint methods in the guitoolstest.frink  file.
   metretes and fixed the
    definition of oldhollandcable (from a prefix to a unit
    definition) in the standard data file.
    Thanks to John G. Malecki for spotting these problems.
  sum[x]
    function to add the elements of a list or an enumerating expression.
   this member variable to objects created from
    classes.  This was necessary to be able to pass the current object as a
    parameter to functions.
   EnglishToChinese, Chinese, FromChinese to imply
    simplified Chinese instead of traditional Chinese.  This probably
    reflects modern practice more closely.  Traditional Chinese will likely
    not work.
  charList[str] to return a list of characters
    in a string.
   isInteger[num] function which returns true if
    a number is a dimensionless integer, false otherwise.
  It now supports calculation of the following at different altitudes:
     6.3 hour -> [0, "weeks", "day1", "hours", "minutes"]
    
This is still an error, but now it produces a more helpful error message. Thanks to Eric Hill for the bug report.
eval[] and unsafeEval[] are passed an
    array, all elements of the array will now be evaluated and the
    result will be returned in an array.  This greatly simplifies things like
    reading from a file and turning strings into numbers.
   newJavaArray[classname, length] method to allow
    creation of arrays of Java objects or Java primitives.  See the Creating Java Objects section
    of the documentation.
  collapseIntervals[bool]
   function to control the collapse of degenerate intervals (those with the
   same upper and lower bound) into a single real number.
  As an important note, this fixes the case where you couldn't create an external process through introspection, for example:
     
      runtime = callJava["java.lang.Runtime", "getRuntime", []]
    
      process = runtime.exec["ls"]
      istream = process.getInputStream[]
      println[istream.available[]]
     
     The above wouldn't work in the past because the process
     object wasn't usually an instance of java.lang.Process, but
     of a subclass like UNIXProcess (on Linux) or
     ProcessImpl (on Windows), and the aforementioned Java bug
     caused failure when trying to invoke methods on these classes, which were
     declared private, even though the methods were public and
     the calls would work fine in normal Java code.  So now you can really
     call external processes from Frink, if you want.
    
chars[x]
    function to return an array of Unicode character codes even when passed a
    single-character string.
  partitionCount[n] to return the number of
    ways that the positive integer n can be partitioned.
   for, do...while, and
    while loops.  This allows for cleaner breaking out of nested
    loops.  See the Loops section of the
    documentation for examples.
  length[set] function return a value much
    more efficiently for sets.
  Warning: This release fixes a significant bug that was introduced recently.
Fixed a major bug that was introduced recently when multiplying by zero. I had added an over-eager optimization that turned this case into 0 (without dimensions) at compile-time, which worked for many cases, but this broke dimensional analysis. For example, the case below would produce a conformance error:
     4 s + 0 s
    
     If that produces an error, make sure you update your version of Frink!
     It should, of course, produce 4 s (time).
    
You would also see the loss of units in something like:
     0 s
    
     If this produces 0, and not 0 s (time), then you should
     update.
    
Many thanks to Jared Updike for informing me of the bug.
sin[x] when x is an undefined variable will
    immediately halt with an error.  (If you've set
    symbolicMode[true] then this will return the unevaluated 
    expression sin[x] and will not generate a warning.)
    "Fail-fast" behavior prevents traditional programs from running along merrily and building (potentially huge) symbolic expressions if you forgot to define a variable. For most programs, you'll want to know immediately if you forgot to define a variable's value. This behavior had been altered with this month's symbolic algebra changes.
JDE[day] function to take a
    dimensionless value (the JDE value in days) and create a date object from
    it:
    
     JDE[2451545.0]
     AD 2000-01-01 04:58:56.170 AM (Sat) Mountain Standard Time
    
x+0 to
    0.
   x^x.
  symbolicMode[bool] flag to suppress a variety
    of warnings that are normally presented to the user when running in
    ordinary programming mode.  When set to true, warnings for
    undefined symbols and functions are suppressed.
   frink.gui.FrinkStarter class that allows
    selection of starting in command-line mode (with no arguments) in AWT GUI
    mode (with --gui or --awt or -open
     filename command-line arguments), or in Swing GUI mode (with
    --swing command-line argument.)
  sin[x] to not always throw
    fatal exceptions when passed arguments that can't immediately be
    evaluated.  If these functions cannot evaluate their arguments, they check
    to see if any of the arguments contain undefined symbols, and, if so,
    return the original expression quietly.  If the arguments are of the wrong
    type entirely, they will still throw an exception.  This is an attempt to
    allow symbolic manipulation of these functions, while trying to preserve
    some "fail-fast" behavior for ordinary programs.  In the future, this
    behavior may be further altered by a "symbolic mode" flag.
   
     
      D[_f[_u], _x]   <->   D[_u, _x] D[_f[_u], _u]
     
    
rationalAsFloat[true] function to force
    display of rational numbers as floating-point.  Setting this to
    true will display all rational numbers as floating-point
    approximations.  They will continue to be represented internally as
    floating-point numbers for accuracy.  For more information, see the Setting Number Formats section
    of the documentation.  Thanks to Robert Munafo for the suggestion, as well
    as several good suggestions for improving the documentation.
   rationalAsFloat, showApproximations, setPrecision) in a
    restricted context.  This prevents, say, users of the web
    interface from messing up the display settings for all users.  Note that
    someday these flags might be on a per-interpreter basis, but that'll be
    significantly slower.
   setPrecision[digits]
    function, which allows the user to set the number of digits of precision in
     floating-point calculations.  I kept this function as somewhat of a
     secret due to the possibility listed above.  For more information, see the
     Setting Precision section 
    of the documentation.
   transformExpression[expr] function
    pre-evaluate its arguments like most normal functions.
   The new frink.jar file can now be compiled to a stand-alone executable using the experimental gcj 4.3 eclipse-merge-branch. (Unfortunately, it's compiled without optimization, because that pegs the CPU for over 72 minutes, and then blows out my system after trying to use over a gigabyte of virtual memory. Anyone want to donate me a new computer with tons of memory? Or try compiling it with -O3?) Thanks to Reuben Thomas for the suggestions and error reports.
Hint: If you install the gcj package linked above, the command line to compile with full optimization will be something like:
     
      gcj -O3 --main=frink.parser.Frink -o frinkx.exe frink.jar
     
    
Note: Yes, the executable has been stripped to reduce its size (original was about 48 MB.) I may further compress it with an executable packer which will reduce the size to less than 5 MB at the cost of slightly slower startup time.
     
      showUndefinedSymbols[false]
    
      _x + _x <-> 2 _x
     The <-> operator seperates the two sides of a
     transformation rule.
    
     The above implements the usual mathematical equivalence x+x=2x.  A
     variable preceded with an underscore like _x is a pattern
     that matches any expression.  (If you just have a variable
     called, say, x in a rule, it will match only the literal
     symbol x.)  The fact that the above expression has
     _x in two places on the left-hand side enforces that the
     same pattern has to be the same on both sides of the addition
     operator.
    
     All defined patterns can then be applied by the
     transformExpression[expr] function:
    
     transformExpression[y+y]
     2 y
    
Note that it also works with arbitrary expressions on either side:
     transformExpression[2x + 2x]
     4 x
    
You can define more transformation rules, and they will all be applied. Below are a couple of the most common transformation rules:
     
      0 _x <-> 0
    
      1 _x <-> _x
      0 + _x <-> _x
      _x * _x <-> _x^2
      _a _x + _b _x <-> (_a+_b) _x
      _x^_a * _x^_b <-> _x^(_a+_b)
     
If you play with this a bit, you'll see that the structure of the expression is matched, and the structure has to match exactly.
More work needs to be done with matching all orderings of addition and multiplication operators, which are commutative, and the syntax may change, but this is a huge, huge step forward for Frink!
     Homework:  Using the above examples, define transformation rules
     to take the derivatives of expressions, like:  D[sin[2x],x]
     You can do it for many types of expressions, but not all.
    
frink.jar file and added
    some apparently-unused inner classes that were preventing compilation with
    some picky tools like gcj.  These missing classes may have also prevented
    execution on some odd JVMs, at least in theory.  Thanks to Reuben Thomas
    for the information.
  
     The exact workings of this may change, but you can now specify arbitrary
     patterns beginning with the underscore character _ and with
     an optional name.  For example, to transform instances of x +
     x (where x is any pattern) into 2x, you
     can try the following code:
    
     
      substituteExpression[x+x, _y + _y, 2 _y]
     2 x
    
     The pattern _y + _y matches any pattern where both
     sides of the + operator are the same pattern, and replaces
     that pattern in the first expression x+x with 2
      x.  
    
Or, more generally, to handle sums of products of similar variables:
     
      substituteExpression[3x+4x, _z _y + _x _y, (_z+_x)_y]
     7 x
    
Using the same rule:
     
        substituteExpression[(z-3) x+4x, _z _y + _x _y, _y (_z+_x)]
     x (1 + z)
    
That may seem simple, but it's an amazingly powerful feature that will allow arbitrary mathematical transformations. More information and features to come, and more easy specification of transformation rules to come.
+ operator to also allow string concatenation gets in the way
   of doing this universally.  Sigh.  I need to choose a different string
   concatenation operator.  I knew I'd regret that choice.
   parseInt[str, base] to
    parse a string into an integer, treating the string as being in the
    specified base.  This is faster, but less flexible, and more sensitive,
    than using something like eval[str\\16] for the same
    purpose.
   arccosh[x]
    or acosh[x].  This function works for complex and
    interval arguments.
  set datatype useful.  You can now construct sets,
    add elements to a set (using the put method), test for
    containment, and more.  For more information, see the Sets section of the documentation.
   showUndefinedSymbols[bool] to
    control whether or not "(undefined symbol)" should be shown after all
    undefined symbols.  This would be annoying in symbolic calculations.  This
    function may change.
  approxLog2[x] function to return a double
    and return a much better initial estimate for integers.  This will help
    the initial estimate in many numeric algorithms.
   collapseIntervals[bool] function to indicate
    whether or not degenerate intervals (that is, those with equivalent lower
    and upper bounds) should be collapsed into a single real number.  The
    default is false.  This feature is still somewhat
    experimental, but it should allow you to see what may happen with
    different rounding directions in interval arithmetic, and see how
    numerical error propagates as a result of different rounding directions.
   substituteExpression[orig, from,
     to] function to allow substitution of parts of an
    expression with other expressions.  This is part of the upcoming symbolic
    mathematical capabilities.  The name and behavior of this function may
    change.
  + ) in several ways:
    Note that the following changes may affect existing programs! It's very doubtful that anyone expects or codes for the old behaviors, but these changes could affect some oddly-written programs.
Slightly altered the semantics so that two units (i.e. numbers) which are added together in the midst of a string concatenation will get added first before the string is concatenated. This altered/fixed the case where string concatenation was always done first. For example:
       s = 1
      
        println["Next=" + s + 1]
       
       now outputs Next=2 instead of the old behavior, which was
       to print Next=11.  (See how the promotion to string and
       then string concatenation was done first.)
      
If you want the old behavior, you can get it by coercing one of the units to a string explicitly using the string interpolation rules. Either of the following works to give the old, weird behavior:
        println["Next=$s" + 1]
      
        println["Next=" + "$s" + 1]
       
        date = now[]
       
        offset = 1 year
        println["1 year from now is about: " + date + offset]
       1 year from now is about: AD 2008-04-11 10:07:45.100 AM (Fri) Mountain Daylight Time
      
The previous behavior was to do a string concatenation of the date and time, without separators, which is probably never what anyone wanted. And yes, it may have been best to have a completely different string concatenation operator in the first place.
expressionContains[a,b] and
    freeOf[a,b] functions to support
    symbolic calculations.  These functions determine if the expression
    a either contains or is free of expression b.  The names and
    behaviors of these functions may change.
   gcd function if one of the
    arguments was zero.
  
     ?rich
     [metrichorsepower, electrichorsepower, Richter[n]]
     
    
     ??rich
     [metrichorsepower = 588399/800 (exactly 735.49875)
      m^2 s^-3 kg (power),
    
      electrichorsepower = 746 m^2 s^-3 kg (power),
      Richter[n]]
     
     Note that this now displays the Richter[n] function which
     converts energy values to/from their equivalent on the Richter scale.
    
This facility will make interactive calculations more friendly, and somewhat reduce the need to go to the documentation to find information about functions. This will also reveal some functionality that you may not have known about, such as the Richter function which must be implemented as a function because it's not linear.
     Note that user-defined functions display their proper named arguments,
     while built-in functions may display something like arg1.
     This may change, or it may not, as Frink checks to see if a function has
     named arguments and performs several optimizations if there are no named
     arguments.
    
numerator[num] and
    denominator[num] functions to return the numerator and
    denominator of a rational number (or any number).
  left[str,len] and
    right[str,len] convenience functions to give
    the left or right side of a string.
   childCount[expr] and
    child[expr, index] functions to support
    symbolic calculations.  These functions give information about the
    structure of an expression and any child expressions.  The names and
    behaviors of these functions may change.
   indexOf[string, substring] function to
    find the first index of a given substring within a string.  This returns
    -1 if the substring is not found.
  dict.clear[] to clear the contents of a dictionary.
   length[dict] function return a value much
    more efficiently for dictionaries.
  earth...) from the sun.frink astronomical 
    library to its own new file, navigation.frink.
    If you have programs written to use the above functions, they may require modifications:
East and West defined at the top of
      the sun.frink file, changing your use
      statement to instead include navigation.frink will
      automatically give you the proper sign convention.  Otherwise, you will
      need to verify that your sign convention uses negative numbers for west
      longitudes and positive for east.
      
       Note: The sun.frink sign convention was chosen to
       match the one that is widely used in all astronomical
       calculations, by the International Astronomical Union, etc.  It would
       be nice to rewrite all the astronomical algorithms to follow the same
       sign convention as geodetics, but that's really fraught with peril.
       Sigh.
     
earthBearing and resultantLatLong) used
      spheroidal calculations which would cause small errors and asymmetries
      between the forward and reverse calculations.  The calculations are now
      symmetrical.  These functions have replaced the old functions of the
      same name, with the old functions being renamed to
      lowAccuracy...  You should be able to use the updated
      functions without modification, as long as you note the sign convention
      change.
      
       Even the previous ellipsoidal calculation in the function
       earthDistance has been replaced with the new algorithm.
       The new algorithm will be more accurate as it uses an iterative
       procedure to reduce error on the ellipsoid (most calculations on an
       ellipsoid cannot be expressed in a closed form.)  Currently,
       convergence limit is set at 1 microdegree, which corresponds to about
       .1 mm on the earth's surface.  The previous calculations could have a
       relative error on the order of earth's flattening squared.
       
     
earthDistanceAndBearing which returns a list
      containing [distance, initBearing, finalBearing] as the
      calculations for distance and bearing would repeat many of the same
      calculations.  If you're calculating both distance and bearing, this
      function will be more efficient than calling earthDistance
      and earthBearing.
    update tag to the JNLP specification files
    (used for Java Web Start and available only in Java 6) as it caused
    problems in Java 1.5 and before (it said that the file was missing a
    <jnlp> tag when it wasn't.)  Thanks to the lovely Tara Stewart for
    the bug report.
  Added a couple of sample scripts to run Frink in command-line mode. You will need to edit them to match the paths on your system!
There is more information on startup options in the Running Frink section of the documentation.
update tag to the JNLP specification files
    (used for Java Web Start and available only in Java 6) to tell Frink to
    check for updates in the background while launching and then automatically
    update if there's a newer version.  I'm not sure how well this works, so
    let me know if you have problems with Java Web Start.
  set data type.
   new dict
    for new array.  The syntax for accessing elements of an array
    and of a dictionary is otherwise identical:
    
    
     a = new dict
    
      b@0 = 123
      b@100 = 301
showApproximations[bool] function
    which switches display of floating-point approximations for rational
    numbers on and off.  For more information, see the Setting Number Formats section
    of the documentation.
   gcd algorithm, as it was tested to be
    faster than the new algorithm for larger numbers, especially on some
    platforms.
  i^4 is now exactly 1.
   factor function for the first time.
  break statement to break out of the
    currently-executing loop.  This applies to for,
    do, and while loops.  Labeled breaks may come
    later.
   gcd function to be about 10% faster.
    This will improve the speed of Frink's gcd function and
    improve performance when reducing rational numbers to simplest terms.
  messageDigest[str,
   algorithm] to calculate a variety of cryptographic hashes of
    various strings.  The algorithm parameter is a string
    containing one of any hashing algorithms your Java platform supports, which
    probably includes: "MD2", "MD5", "SHA-1", "SHA-256", "SHA-384",
     "SHA-512".  See the Cryptographic Functions
    sections of the documentation for code samples.
  modDiv[n,m,
     modulus] to perform the integer modular division
    n/m mod modulus which returns the integer result
    if one exists, otherwise returns undef.
   modInverse[n,modulus] to 
    find the integer modular inverse of n to the base
    modulus and returns the integer result if it is invertible,
    otherwise returns undef.
   array.permute[]
    to produce all the permutations of the elements in the array.
   Warning: Older versions of Java may contain incorrect daylight saving time conversion for the U.S. in 2007 and beyond. Read below for more details.
If you use Frink to perform calculations with dates in the future, especially dates in the U.S.A., I would like to strongly urge you to make sure that your version of Java is updated to match U.S. daylight saving time changes. These changes were signed into law as part of the Energy Policy Act of 2005 and will take effect in 2007.
In short, "Clocks will be set ahead one hour on the second Sunday of March instead of the current first Sunday of April. Clocks will be set back one hour on the first Sunday in November, rather than the last Sunday of October."
Sun claims that this change has been made to the following Sun Java releases:
However, at the time of this writing, the latter three are apparently unavailable for download from Sun's web site.
In practice, I have apparently seen this change to be made in some earlier versions of the 1.5 branch, but they would probably know better than I would if the problem was only half-fixed in earlier releases. Updating is recommended.
There is also a (beta) timezone updater tool if you're not allowed to update to any of these VMs.
Failure to update your VM may cause significant errors in converting to or from any U.S. timezones. No changes to your Frink jar files or Frink programs will be necessary when your Java environment is up to date.
Note that Java 6 (also known as 1.6) has very recently been released and is available for download.
If anyone notices any unexpected changes in any Frink behavior under Java 6, please let me know!
randomGaussian[mean, sd] to return a 
    normally-distributed (i.e. "bell curve") random floating-point value with
    the specified mean and standard deviation.
  randomFloat[lower, upper] to return a 
    uniformly-distributed random floating-point value in the specifed range.
  array.shallowCopy[]
    to perform a shallow copy of the elements of an array.  Arrays are normally
    passed by reference, and this allows them to be copied easily and
    efficiently.
   Important Fix: Fixed a problem in the makefile introduced when checking in yesterday's changes. This may have caused certain files not to be packaged correctly and could have broken Frink entirely. Please download Frink again if you experienced problems with yesterday's build.
Turkey_Lira to Turkey_New_Turkish_Lira.
    The symbols changed are:
    | Country | Old Symbol | New Symbol | 
|---|---|---|
| Azerbaijan | AZM | AZN | 
| Mozambique | MZM | MZN | 
| Romania | ROL | RON | 
| Turkey | TRL | TRY | 
earthradius_equatorial,
    earthradius_polar, and earth_flattening in the
    standard data file to use the WGS84 datum, which is most commonly used in
    modern maps.
    
   eval[string] more robust in the face of errors
    thrown from low levels of Java, such as divide by zero errors.
    Now, any Throwable is caught and the function returns undef
    when an exception is caught.
  java.vm.name.
    If the VM did not have a property with this name, initialization of the
    base converter class would fail and Frink would not display larger numbers
    (absolute value 231 or larger) properly.  This was a problem in
    some Java 1.1 environments, notably on Nokia handhelds.  Be sure that when
    you install Frink on these environments, it says version 3.4 or 3.04 or
    later.  Thanks to Francis for the bug report!
  return statement
    was the last statement in the function.  This is now much faster.  It
    improves the speed of calling such functions from 3% up to 700%.
   sin[x].  This
    gives a small speedup and a reduction in runtime memory usage.
  arccsch[x] or
    acsch[x], defined as ln[sqrt[1 + 1/x^2] + 1/x].
    This function works for complex and interval arguments.
   format function was not an integer.
  arcsinh[x]
    or asinh[x].  This function works for complex and
    interval arguments.
   use statements to look for files in an
    internal library shipped within the jar file.  (In directory
    /lib/).  This library is currently empty, but this paves the
    way for a distribution of Frink with a larger standard library of code
    implemented in Frink.
   array.removeValue[value] now returns
    true if the value is found and removed, and
    false if no matching item was found.  See the
    Array Methods section of the
    documentation for more.
   futureboy.homeip.net to
    futureboy.us.  It appears that this may make pre-existing
    Java Web Start icons ask you if you want to make file associations or
    create icons.  If you answer "yes," it looks like it won't bother you
    again.
  File |
       Interrupt Calculation menu item.
     It's possible that this causes problems on platforms with minimal Java support and no support for threading. If this is the case, please let me know.
version tag of Java Web Start
    JNLP files to hopefully work around bugs in Sun's implementations where
    the latest installed version of Java is not used.  See below on how to fix
    this manually.
   Note that when Frink first starts up as a widget, it might appear to hang. This is because Sun's Java installation pops up a dialog box behind other windows that asks you if you want to trust the Frink applet. You may have to hunt for this window. You can choose to "always trust" the application so you don't have this problem repeatedly. This was supposedly fixed in Java 1.5, but it still seems flaky.
I should note that installing Frink via Java Web Start (outlined here) is still in all ways a better way to install Frink than via a widget. It's resizable, automatically updates itself when Frink changes, and more. But the kids these days seem to like these widgety dealies.
Many thanks to the lovely Tara Stewart and the lovely Adam Singer for showing me how a Mac works, updating their Java settings, letting me screw with their computers, helping me test this stuff, and making dinner while I screwed around.
deltaT[now[]] returns 65.184 seconds,
    due to the leap second introduced at the end of 2005.  (Frink planned for
    this change in the 2005-08-30 release.)  Be sure to set your clocks back
    one second!
    The current value of delta-T, the difference between Terrestrial Dynamical Time and UTC is now 65.184 seconds. Astronomers take note.
     deltaT[now[]]
     65.184 s (time)
    
-v or
    --version command-line flag actually works.  Thanks to Bill
    Poser for the bug report.
   -v or --version command-line flag to
    print out the Frink version and exit.  The format of this version string
    may change in the future.
  BigInteger.ONE 
    from the new factoring code.  This yet again fixes some
    incompatibility problems with some Java 1.1 distributions.  I
    didn't realize that these variables weren't required to be public until
    Java 1.2, and all of the Java distributions that I'd tested with made them
    public, even on PersonalJava 1.1.  But not on the Sharp Zaurus.
  The choice of using pack200 compression should be automatic and transparent. Note that pack200 compression is only chosen if you're using Java 1.5 or later. If you're using something older, downloads should still work as before.
The advantage of using pack200 compression is that the size of the file you have to download is reduced from 615 kB to 220 kB. This should happen automatically the next time you launch Frink from your Java Web Start icon.
If you haven't used Java Web Start to install and automatically update Frink, you can do so here.
The pack200 compression scheme is a little screwy, and requires repacking the original jar file. This may cause issues on some platforms that I haven't detected. If you have any problems with downloading Frink or running Frink on any platform, or if you get verification errors, please let me know as soon as possible.
(1/4)^(1/2) :
    (-27)^(1/3) now
      returns the real number -3.0 instead of the complex number
      (1.5 + 2.598076 i) that it returned
      previously.  Both of these are valid cube roots, (all numbers can be
      said to have three cube roots, at least 2 of which are complex,) but now
      the "principal" real cube root is returned for real negative bases.
      
      
       Please note that if an inexact floating-point number is substituted for
       the exponent (e.g. (-27)^.333333333), this will
       (correctly) return a complex number if the base is negative.  This
       means that exponentiation may be somewhat "discontinuous" in the
       complex plane for negative bases (you're actually picking a different
       root at nearby points,) so if continuity matters to you, you might need
       to either make conscious adjustment of the root you desire, or just
       force the exponent to be a floating-point number before exponentiation.
       (Say, by multiplying by 1.0.)
     
(1/4)^(1/2) now returns
      the exact rational 1/2, instead of 0.5.
      Currently, this is only true for exponents with denominators of 2, which
      will hopefully be improved when I add routines to find exact integer
      roots, if such exist, for roots other than 2.
    isPrime[x] to automatically use a faster
    Lucas-Lehmer test if x is of the form 2n-1 (i.e.
    Mersenne numbers).  Note that the Lucas-Lehmer test is sufficient to
    prove primality for numbers of this form, regardless of their
    size.  If Frink says that a Mersenne number is prime, it is.
   factor[num] to detect Mersenne numbers
    (that is, those of the form 2n-1) and use certain properties of
    these numbers to speed factorization when n is composite.  This
    currently performs some recursive subdivision of the number, detecting
    some known factors rapidly.  This makes factoring some Mersenne numbers
    much, much faster.
  It should be noted that any calendar dates before October 15, 1582, (the date that the first countries switched from the Julian to the Gregorian calendar) should be treated as suspect when converting a Julian day to a Julian date or Gregorian date or vice versa. Not to mention the glitches in the proleptic leap year rules projected backwards, the fact that there was no year zero, and the fact that there was no Julian calendar before 4 AD. I need to figure out and state my policies as to what calendar dates before this mean (and probably make all the options of interpretation user-configurable.)
array.removeValue[value] method to
    remove the first item having the specified value from the array.  See the
    Array Methods section of the
    documentation for more.
   new operator, e.g.
      new Something instead of
      new Something[] .
      
   arctan[x,
    y] to work with all combinations of intervals and real
    numbers.  This was an enormous pain.  Thanks to G. William Walster for his
    assistance in making this much less painful.
   format[x, divideBy,
      decPlaces] function to allow intervals to be formatted to the
    specified number of decimal places.
  format[x, divideBy,
      decPlaces] function to be a string representing a more
    complex expression (previously, it only allowed unit names.)
   -> and in the format[x, divideBy,
     decPlaces] function.  This has the result that some complex
    formatting done through the web-based interface will not work.  This may
    be weakened in the future.
  0 -> m . Thanks to
    the lovely David Rysdam for the report.
  eval[string] return undef if
    something goes wrong during parsing.  Previously, it would throw an
    exception and halt evaluation.
   floor[x],
    arccos[x], arcsec[x], and
    arctan[x] to work with intervals.
   mod operator to work with intervals.
   This added a huge amount of power. All of a sudden, almost all of the astronomical calculations in my sun.frink libraries work with fuzziness and uncertainties.
infimum[x],
    supremum[x], and mainValue[x]
    functions to work on date intervals.
   tan[x],
    csc[x], sec[x], and
    cot[x] to work with intervals and all of their
    inflection points.
  sin[x] and
    cos[x] to work with intervals and all of their
    inflection points.
  sqrt[x], ln[x],
     log[x], and exp[x] to work with intervals.
   frink.errors.FrinkEvaluationException
    when something goes wrong in the course of parsing or executing.  If
    you're integrating Frink into another program, you'll have to catch this
    exception.  This hopefully makes it easier to detect and handle error
    cases.  Previously, the error message just appeared in the output string,
    which made it difficult to distinguish from normal program results.
    See the documentation on Frink's
     integration methods for more information.
    
   infimum[x],
    supremum[x], and mainValue[x] to
    return the lower, upper, and main (middle) bounds of an interval.  If these
    functions are called with a unit that's not an interval, these just return
    the unit.
    
   < == >, etc) to
    work with intervals.  These operators try to Do The Right Thing when
    applied to intervals.  If you compare intervals that do not overlap, they
    return the appropriate result.  If, however, the intervals do
    overlap, they terminate the program with an error similar to the following:
    Comparison expression: Using operator > to compare intervals [2, 3] and 2.5.
This operator is only defined if there is no overlap between intervals.
Please modify your program to use interval-aware comparison operators.
CLT (certainly-less-than) and
    PGE (possibly greater-or-equal).
   1^x to always return the exact integer 1.
   So what's interval arithmetic? It's a way of tracking errors or imprecise values automatically throughout your calculations. Check out the new section in the documentation about it.
Internally, the math libraries were rewritten extensively to allow rigorous interval arithmetic.
Currently, only the mathematical operators + - * / ^ are
     implemented for intervals.  The notation may also change in the future,
     but it's already quite usable for many programs and calculations.
   
min[array] and max[array]
    functions to return the smallest and largest items in an array
    respectively.
   new expressions to go just about anywhere in
    expressions.  These were somewhat limited before.
   1.234e100 + 1 the answer would be calculated and
      stored with all 100 digits, most of which were almost certainly illusory
      digits of precision, and far more digits than were specified in the
      original number.  The result is now only calculated and stored to the
      number of digits of working precision (by default 20, but you can
      increase this by using the setPrecision[digits]
      call.) Note that this does not affect integers or rationals,
      which are still calculated with all of their digits.
     mod function also
      produces less digits of illusory precision when working with
      floating-point numbers.
    length[expr] function now returns the number of
    items in an enumerating expression.
  eval[] now disallows defining of functions in 
     untrusted code.  (You can still do this in unsafeEval[]).
     This may be relaxed in the future--it may be beneficial to allow users to
     define functions that are marked as being defined in a restricted context
     and would only be allowed to be called in the same restricted context.
     But that'll take work.  What this means for users of the web-based 
     interface is that they won't be allowed to define functions any more.
    --sandbox command line option which enables Frink's
     internal sandbox mode for untrusted code.  See the Command-Line Options section of
    the documentation for more.
   <, >, =,
     <=>, etc.) to make better comparisons when numbers were
    really large or really small.  Previously, there could be issues if
    floating-point numbers were larger than about 10308or when
     comparing very large and very-nearly-identical rational numbers or
     comparing some numbers of different types (e.g. integers and rationals)
    when the numbers were very large and almost identical.
   Double.compareTo() which did not
    exist before Java 1.2.  This may have caused problems doing comparisons on
    some handheld devices.
   Numeric hierarchy so that they
    would support the above.
  .frink file extension and the
    text/frink MIME type with the Frink program you just
    downloaded.  This simply allows you to edit files with the .frink file
    extension by double-clicking them.  This will not run the files,
    but simply open them in editing mode.  Java Web Start will also
    never change the MIME associations used by your browser... the
    MIME associations are only made for the operating system. If you don't want
    this behavior, choose "no" when prompted by Java Web Start.  (You can also
    prevent associations from ever being made by setting your Java Web Start
    preferences wherever that may reside on your system.  In Windows, It's in
    the Control Panel.)
  hubbleconstant and H_0 units for the
    expansion rate of the universe.  These are based on WMAP data.
  afghani, baht, balboa, birr, bolivar, boliviano, cedi, dalasi, denar, deutsche_mark, dobra, dong, drachma, euro, fin, florin, forint, gold_cordoba, gourde, guarani, hryvna, indonesia_rupiah, israel_new_shekel, italy_lira, kina, kroon, kuna, kwanza, lari, lat, lek, lempira, leone, lev, lilangeni, litas, loti, luigino, markka, metical, moldova_leu, morocco_dirham, naira, nakfa, new_dinar, new_dollar, new_shekel, ngultrum, norway_krone, nuevo_sol, ouguiya, pa'anga, pataca, peseta, pula, punt, quetzal, rand, real, riel, ringgit, rubel, ruble, rufiyaa, rupiah, schilling, somoni, switzerland_franc, taka, tenge, tolar, tughrik, vatu, yen, yuan_renminbi, zloty
     Type sort[units[currency]] to get a list of all currencies
     sorted by name, or ?currencyname to figure out what
     country each of these comes from.  Do you know?
  
-> operator where the
    right-hand-side was a function that used a "return" statement.  This may
    have previously thrown a "Return used outside a function" error.  For
    example, 10 kilotons TNT -> Richtersovereigns_yyyy (with the trailing
    "s") work properly.  Before I just had sovereign_yyyy
    entered twice.  Thanks to the lovely Berrian (Eno)-(Van Fleet) for filing
    a bug report so Zen-like and subtle that it was like it wasn't a bug
    report at all.  And thanks for the lovely comments about Frink.
  randomBits[numBits] .
   
    Fixed a bug in the function JacobiSymbol[a,n] which
    returned the wrong value in some cases when a was negative and
    within the range [-2147483648, -1].  (Values were correct for other values
     of a.)  Thanks to Aaron Bertram for the bug report.
    
I'd like to note, as an interesting aside, that I remembered that Sun had a similar bug in their calculation of the Jacobi Symbol. (I don't use their algorithm, by the way, so Frink's Jacobi symbol calculations will work properly in any JVM.) It took Sun three years to release a fix since the bug was first reported. (It was reported against Java 1.3.1, and not fixed until 1.5.) Many of their primality tests were broken due to this. (So much for your secure communications!)
To contrast, I got the bug report this morning, and I was ashamed that I didn't have time to fix it before I left for work. I had to wait until I got home to release a fix.
setEngineering[boolean] function to switch
    back to the old "engineering" format.  See the Setting Number Formats section
    of the documentation for more details.
   --nounits or -nu command-line option to
    start Frink without parsing the standard units file.
  /g modifier) where repeating the match may
    cause null pointer exceptions.
   flatten[list] function to allow enumerating
    expressions to be passed in.
   for loop of the form:
    
     for [a,b] = enumeratingExpression[]
    
ARGS global variable which contains the values of
    any command-line arguments following the name of the program.
   There are some oddities and inconsitencies in NIST's data (and it's certainly not the first time I've found mistakes in NIST data.) For example, dividing their definition of electron mass in kilograms, their definition of the "unified atomic mass unit (u)", and the electron mass in u do not yield values that are self-consistent. They're close, but off in some significant figures. These sorts of errors and inconsistencies seem to go all through their data--values that are derived from other values, such as the fine structure constant α, or the Rydberg constant, show more precision than the values they are derived from, and the values derived from multiplying their published values aren't self-consistent.
editDistance[str1, str2] function
    to calculate the edit distance or Levenshtein distance between two
    strings.  This can be used for a wide variety of purposes, including
    performing fuzzy spelling checks, detecting plagiarism, or finding
    correlations between strands of DNA.  More information is available in the
    Other String Functions
    section of the documentation.
   editDistance[str1, str2] function
    allowed fuzzy spelling suggestions to be suggested in the hints provided by the
    web interface.  If a misspelled unit is entered in the web-based
    interface, it will suggest alternates which have edit distances less than
    1/3 the length of the longer word.  (This matching is done in a
    case-insensitive manner.)
    
   min[arg1, arg2] and
    max[arg1, arg2] functions.  More
    description can be found in the Other
     Functions section of the documentation.
   lines[] function.  The
    security check was deferred until the enumerator was actually accessed.
    This meant that an enumerator could "leak" out of a secure context and its
    security may not have been checked until later, when, say, its contents
    were printed.  I now check security repeatedly at several points.  Many
    thanks to 31337 |-|Ax0r Clayton O'Neill for discovering this bug,
    and many more thanks for reporting it (and not exploiting it!)
  -Xnative-big-math argument to the Kaffe executable.  See the
    Performance Tips section of the
    documentation.
  Re[x], Im[x], and
    abs[x].
    
    This allows you, say, to get a list of all of the hexadecimal values of the Unicode characters in a string. The following translates a string to Japanese and then gets the Unicode codepoints for each character in the translated string.
     hex[char["Year of the beagle" -> Japanese]]
     [30d3, 30fc, 30b0, 30eb, 72ac, 306e, 5e74]
    
This improves performance enormously. On a 800 MHz Pentium III, it originally took 808 seconds to print the numbers from 1 to 10000 in the AWT interface. After the change, it takes 0.3 seconds, a factor of 2700 times faster! Similarly, performance is improved greatly on handheld devices. On a Symbian 7 emulator, the time was improved from 2432 seconds to 45 seconds, faster by a factor of 54.
class
    specification to use less memory.
   use statement now searches paths relative to the
      file being included.  This allows code libraries that consist of files
      which include other files to work in a straightforward fashion, whether
      the file is local, or included from another file, or part of a remote
      library fetched by an HTTP or other URL.  See Including Other Files section
      of the documentation for more information about the search order.
    for loop:  if the enumerating
    expression evaluates to undef, it's treated as the empty list
    and returns without an error, and without evaluating the body of the
    loop.  Previously, it threw an exception.
  NullPointerException if an unknown timezone name
    was specified.
   China as a timezone alias for
    Asia/Shanghai, as China has only one (big) time zone.  Thanks
    to Mike Kordik for the suggestion.
   "\\t" wouldn't
    work right.  (It's supposed to turn into one backslash followed by a "t"
    (that is, \t ).  Any single character following a backslash
    that isn't a special character just becomes that character.  Added more
    documentation to the Strings section of
    the documentation.
  split[pattern, str] to run
    faster when the pattern is a simple string.
   parseInt[str] to parse a string into an
    integer.  This is faster, but less flexible, and more sensitive, than
    using eval[str] for the same purpose.
   class specification.
   .jar file might only get reloaded the
    second time after it changes if the web server gives a redirect
    response.
  split[pattern, str] to be either a regular
    expression or, now, a string.
   NullPointerException that occurred if a class
    didn't have any class-level methods or variables.
   input[x]
    function was calling methods (getWidth() / getHeight()) that
    don't exist on Java 1.1 platforms.  This caused the input function to not
    work on Java 1.1 platforms.  This was unfortunately introduced in the
    2004-04-23 update.  Thanks to a mysterious being who calls himself "Casual
    Programmer" for the bug report.
  trim[string] function to remove whitespace
    from both ends of a string.
   new as
    the name of the function.  More documentation and discussion is in the classtest.frink
    sample which documents object-oriented programming.
   new,
    for example:
    
     jupiter = Sphere.new["Jupiter"]
    
     jupiter = "Sphere".new["Jupiter"]
    
See the end of classtest.frink for a sample.
string
    or dict.  The complete list and documentation is found in the
    Constraining to Built-in
     Types section of the documentation.  For example,
    
     var name is string
    
DimensionListConstraintSource for memory
    usage.
   isStrongPseudoprime[num,
      base] 
    function to deterimine if a number is a strong pseudoprime to a specified
    base.
   mod operator.
  Eventually, FFT routines will be ported to Java and more highly optimized (pre-caching of sines and cosines, possible real transforms, possibly caching of swaps and butterflies, and probably implemented entirely in machine-precision floating-point for speed.)
class keyword:
    class keyword to
      share class-level variables efficiently with their metaclass instance.
     isA(String type) method to FrinkObject interface
      to allow objects to claim to be of a certain type.
     TestClass, the following will ensure
      that the value assigned to the variable a is always an
      instance of TestClass.
      
       a is TestClass = new TestClass[]
      
Environment objects to
    allow for more flexibility in construction, and better error reporting.
  input[] window to be the same size as the
    parent window, or the minimum size necessary to contain the prompt,
    whichever is bigger.  Also made the input window resizeable.  This should
    prevent too-small input boxes and still work on handheld devices.  Thanks
    to Kip Barros for the suggestion.
   BigInteger.toString() (this only recognizes Kaffe right now, but Kaffe can use the
    incredibly fast GMP libraries for
    its BigInteger work, making it thousands of times faster than Sun's
    implementation for large integers.
   oldToString[integer] and
    newToString[integer] functions to test the speed of
    integer formatting using, respectively, the method implemented by the VM's
    version of BigInteger, and my own hand-written recursive
    divide-and-conquer algorithm.  You generally won't use either of these,
    but my version is orders of magnitude faster than Sun's for large numbers,
    and just as fast for small numbers.
    
   Re[x] function (to return real part of a complex
    number.)  It wasn't working correctly before for complex numbers due to a
    stupid cut-n-paste.
  JacobiSymbol[a,
      n] function to calculate the Jacobi symbol of two
    numbers.  This is used in factoring and primality testing.
   format[x, divideBy,
      decPlaces] function to be a string, which prints the value of
    the string after the result.
  input[] box.  Thanks to Jon Hoskin for the bug report.
  
     1/2
     1/2 (exactly 0.5)
    
     1/11
     1/11 (approx. 0.09090909090909091)
    
frink.ipk file (these are
    really just .tar.gz files,) without warning you or changing
    the filename.  If you have problems with the installer, you should try
    downloading with another browser.
  BigInteger.ONE and
    BigInteger.ZERO from the code.  This fixes some
    incompatibility problems with some Java 1.1 distributions.  I
    didn't realize that these variables weren't required to be public until
    Java 1.2, and all of the Java distributions that I'd tested with made them
    public, even on PersonalJava 1.1.  But not on the Sharp Zaurus.  Thanks to
    Karl Heinz Kremer for the report.
    
   frink.gui.InteractivePanel
    and frink.gui.FullScreenAWTStarter
    to specify size of the initial GUI window.  You can specify either width
    or height or both.  The syntax would look something like:
    
     java -cp frink.jar frink.gui.InteractivePanel -width
      500 -height 400
    
Thanks to Karl Heinz Kremer for testing this on the Sharp Zaurus.
class var x = 10Classname.variable  Note that this now
    essentially allows "clean" global variables.
  conforms operator to take a string on the
    right-hand side.  This string is taken to be the name of a dimension list.
   units[x] was a variable name
    and improved error messages.
   sqrt[-1] now returns i and not
      the inexact 1.0 i.
    M-; work for inserting comments.
    do...while loop.
   getBit[num,
      bit] function to test bits in the binary representation
    of an integer.
   bitLength[num] function
    to return the length of bits in the base 2 representation of a number.
    factor[num] function.  Factoring now first tries
      trial division, then the Pollard p-1 algorithm, then the Pollard
      rho algorithm.
     /e switch to
    evaluate the right-hand-side as a Frink expression.
  new array
    which is now the recommended syntax.
   Important Changes: Several major changes were made to the command-line options and syntax for Frink. These may require you to change your startup scripts. Please read below for details.
-e option is now
    required to execute a command-line argument as a Frink expression.  The
    -f option to specify a filename to interpret is now
    deprecated and unnecessary, and has slightly different functionality,
    although it will still work the same in most cases.  See the Command-Line Options section of
    the documentation for more.
   
     {{ |x|  x mod 2 == 0 }}
    
is now written as:
     { |x|  x mod 2 == 0 }
    
Programs using the old notation will still work, (for some unspecified time,) but will produce a warning. This syntax is now identical to Ruby's, and is more concise and less noisy.
gcd[x,y] function to return the greatest common
    divisor of two integers.
   !! to ||| to allow chained
    factorials.  If you use your own data file, you'll have to change it.
   isPrime[x] and factor[x] functions
    explicitly raise an error on non-positive arguments, and return reasonable
    values for 1.
   ln[x] and common log (base 10)
    log[x] to handle and produce complex numbers.
   exp[x] function for real and complex numbers.
   Re[x] and Im[x] functions to
    return real and imaginary parts of a complex number.
   sinh[x], cosh[x], and
    tanh[x] hyperbolic functions.
   sin[x]
     cos[x]
     tan[x]
     sec[x]
     csc[x]
     cot[x]
     arcsin[x]
     arccos[x]
     arctan[x]
     arcsec[x]
     arccsc[x]
     arccot[x]
    now[] function without the
      square brackets.
     USD_ as a possible prefix for historical US dollar
    conversions.  See the Historical U.S. Price Data
    section of the documentation for more information.  Changed to bootstrap
    the loading if someone requests a unit starting with the incorrect
    lowercase usd_ for help purposes.
   GBP_ as a possible prefix for historical British
    pound conversions.  See the Historical British Price
     Data section of the documentation for more information.
   subst[fromStr, toStr] and
    subst[fromStr, toStr, options] to allow
    building of search-and-replace expression with variable interpolation on
    the left-hand-side.  See Search and
     Replace in the documentation for more.
  SelfDisplayingExpression interface which
    Expressions can implement if they want to display themselves in a certain
    way.  Modified formatters to use this.
   \u00D7 )
    × and INVISIBLE TIMES ( \u2062 ) as synonyms for
    multiplication.  I'll be digging through more Unicode tables and putting
    in Unicode synonyms for other operators.
   There was actually a great adventure a couple of days ago where I predicted the moon crossings and noticed that the next rare predicted crossing would happen in two hours and managed to contact Keith Winstein at MIT to run over and verify. Many thanks to Keith Winstein and Ken Olum for providing location information for the corridor, and helping to verify predictions. It's a good story. If you're interested in the predictions (or the story,) please contact me. Thanks also to Stuart J. Goldman and his interesting article "Sun Worship in Cambridge" in the November 2003 Sky & Telescope magazine.
4 miles / 10 hours which explains
    normal mathematical rules of precedence and suggests 4 miles / (10
     hours).  See this section of the
     FAQ for more information.
  new operator to create new objects by name.
    Currently, the only object that can be constructed is dict,
    but the underlying architecture to make this happen will allow for
    arbitrary objects to be constructed in a very flexible fashion.
  undef to Java
      null.
     java.util.Enumeration to allow their use as a Frink
      EnumeratingExpression.
    inchmercury and irregular plural
    inchesmercury.  Thanks to Howard Tanner for the suggestions.
  
     f = newJava["java.awt.Frame", "Whee!"]
    
      f.setSize[200,200]
      f.show[]
??moon-style help
    messages.
  0xFFFF notation for hexadecimal numbers and
    0b1111 notation for binary numbers.  I refuse to use
    the normal convention that numbers beginning with a zero are treated as
    octal.  That madness has to end.
   1000! (approx. 4e+2567) that will be cached.  If
    you regularly need factorials larger than this, performance will be
    degraded.  Please let me know if this is the case.
   
     ??moon
     
      moonlum = 2500 m^-2 cd (illuminance),
    
      moondist = 0.002569555301823481845 au,
      moonmass = 73.483E+21 kg (mass),
      moonradius = 0.000011617812472864754024 au,
      moongravity = 1.62 m s^-2 (acceleration)]
More information can be found in the Integrated Help section of the documentation.
parseDate[string] function to parse a date
    from a string.
   ?horse which
    produces a list of unit names that contain the word "horse" can be
    converted to a list of those units and their values:
    
     ?horsepower -> watts
     [horsepower = 37284993579113511/50000000000000
      (approx. 745.6998715822702),
    
       brhorsepower = 745.7,
       boilerhorsepower = 9809.5,
       waterhorsepower = 746.043,
       metrichorsepower = 588399/800 (approx. 735.49875),
       electrichorsepower = 746]
More information can be found in the Integrated Help section of the documentation.
Rankine as a synonym for degreesRankine
    and its family, because Rankine has its zero at absolute zero, and this
    usage works for both the size of a degree and absolute temperatures.
   var keyword (you can still use it if you
    want) when specifying formal arguments of a function.  More information
    can be found in the
    Constraining Function
     Arguments section of the documentation.
   octal,
    binary, hexadecimal, duodecimal,
    and so on up to base 20.  More information can be found in the All Your Base Conversions...
    section of the documentation.
   conforms operator to be allowed to take a
    named DimensionList on the right-hand side, for example:a conforms lengthvar t is time = 0 seconds
    More description can be found in the Constraints on Variables section of the documentation.
var avar a = initVal
    More description can be found in the Declaring Variables section of the documentation.
persistent=boolean directive to Frink Server
    Pages.
  println[] function.
  timezone[] function with no arguments to return
    the name of the default timezone.
   JD[] and MJD[] functions to be able
    to take a unit with dimensions of time and create a date object from it.
    This makes the functions self-symmetrical.
   fmt = ### yyyy-MM-dd hh:mm a (E) zzzz ###
     # 2003-06-12 02:25 PM Mountain # -> [fmt, "Japan"]
   FrinkEnumeration interface to give a bit more
    flexibility and improve error-handling capabilities.
    
   -I
    command-line option to specify include paths that will be searched when a
    use statement is encountered.
   \u20ac).
   \u00a5) to be used as
    fundamental currency as well as an identifier.
   \u0163) to be used as
    fundamental currency as well as an identifier.
  String.intern() for all identifiers found by the
    lexer to slightly improve runtime and decrease memory usage.
   for loop where you're
    assigning to a single variable.  This makes very tight loops run about 1.7
    times faster.
   for
     loop to reflect the preferred use of the format for i = 1 to 10
   http://futureboy.us/frink/bitLength[x] function to return the number of bits
    in the minimal two's-complement representation of an integer,
    excluding a sign bit.
  modPow[] and randomBits[]
    functions.  More description can be found in the Other Functions section of the
    documentation.
  to codeword most
    commonly used in for loops) for the case where indices are
    dimensionless integers, which should be the most common case.
  input functionality to allow input from a
    wider array of user interfaces.
   input[prompt, defaultValue] function to
    allow default values in prompts.
   sort
    function to use a method that would be available in Java 1.1.
   random functions so they would work on Java
    1.1.
   for loop.  This
    makes some tight loops run about 3-4 times faster.
   -> conversion
      operator.
     deltaT[date] to get the offset to be added to
    Universal Time to get Dynamical Time.
    
   JDE[date] and date ->
     JDE  date formatter to parse Julian Day (Ephemeris) which is the
    Julian Day with respect to Dynamical Time, not Universal
    Coordinated Time.
   Dynamical
     Time (TD) and Terrestrial Time (TT).  You can now
    parse dates correctly for any date using these formats.  For example:#1992 October 13 00:00 TD# (from example 25.a in Meeus.)
  dateformats.txt.
   use statement.
   select[list,
      regex] function to allow a regular expression as the
    second argument.  This expects the list to contain all strings and returns
    all of the strings that match the regular expression.
  use statement try to load the specified file from a
    location relative to the working directory or as a fully-qualified URL.
    See Including Other Files
    section of the documentation for more.
   ?name where name is part of the
    name of a unit to be looked up.  This is not case-sensitive.  See the
    Integrated Help section of the
    documentation for more information.
   ! and function
    factorial[x].
   =!=.  This only affects you if you use your own units
    file.
  while loop no
    longer require parenthesis.
   for loop
    able to be written as for a = 1 to 10for a 1 to 10
   for and while
    loops.
  .sis file so that Frink
    can be easily installed on Symbian devices like the
    Sony Ericcson
     P800 smartphone, and the
    Nokia 92x0 Communicator
    and the Nokia 7650.  The installer is now built as part of the Frink
    release process, so the SIS version will be up-to-date with the latest
    Frink.
    
    Huge thanks to the lovely David Bergman of Remote Proximity for his immense enthusiasm and efforts in porting Java to these small devices.
centillion.)
     centuries and
    juliancenturies to units file.
   JD[date] and MJD[date]
    functions to return a value of the specified date as a Unit containing the
    time since JD 0, or MJD 0, referenced to UTC.  To convert this to a number
    of days, divide by day.  This function is often unnecessary
    as dates and times can be added and subtracted directly.
   units[x] function to
    work appropriately if x is a variable.
  dict keyword to create dictionary to
    dict[] function.  This means that dict no longer has to be a
    weird reserved word.
   units[force] work as expected.  Thanks to Anthony Crowson for
    the bug report.
  substr[string, startPos,
     endBefore] and substrLen[string,
     startPos, len] functions to take substrings.  See
    the Substrings section of the
    documentation for more information.
   :-> operator.  This will catch the errors (if the
    right-hand side is a string or list of strings) at compile-time at the
    expense of some flexibility at runtime.  It's probably for the best this
    way.  Some cases (such as if the right-hand-side is a function or raw
    symbol) cannot be checked at compile-time and will produce errors at
    runtime. Thanks to Anthony Crowson for the bug report.
  eval[] and unsafeEval[]
    functions to evaluate a non-string argument.
   1 m^2 s^-3 kg A^-1 (electric_potential):->
    operator:
    
     electric_potential :-> "volts"
    
See the Setting Display Units section of the documentation for more. Thanks to Anthony Crowson for suggestions.
use statement to include other
    files.  For the moment, this can only include files in its classpath until
    I get the security implications worked out.
   units.txt file that I
    put in yesterday in response to Anthony Crowson's report.
   Environment.outputln.
   x/x is simplified to 1
     x^0 is simplified to 1
     x^1 is simplified to x
     (x^y)^z is flattened if y and z are numeric.
     eval[]
    statements.
   eval[] statement and created unsafeEval[]
    function.
   lines[URL] and
    read[URL] functions try to set the charset encoding
    from the Content-Type header in an HTTP request.  This should
    often eliminate the need for using the two-argument version for
    well-behaved websites, but will not fix the case where the encoding is set
    in an HTTP <META> tag, or if the header is sent out incorrectly.
  ln[2]
    to only be evaluated once.
  abs[x] function to take absolute value.
  sec[x], csc[x], cot[x],
    arcsec[x], arccsc[x], and arccot[x]
    functions.
  --encoding
    str command-line switch to allow you to specify the
    character encoding of your Frink program files.  Frink programs can now be
    more directly written in any language and encoding system.
    The encoding is a string representing any encoding that your version of
    Java supports, e.g. "UTF-8", "US-ASCII",
    "ISO-8859-1", "UTF-16", "UTF-16BE",
    "UTF-16LE".  Your release of Java may support more charsets,
    but all implementations of Java are required to support the above.  Check
    the release notes for your Java implementation to see if other charsets
    are supported.
  
FSPRoot which gives
    the root directory containing FSP pages.
   char[x]
    function to convert back and forth between Unicode character code and the
    actual characters.
   base[x, b] which returns a string
    representing the integer x in base b.
   base2[x] ... base36[x]
    functions which return a string representing the integer x in the
    specified base.  These are useful on the right-hand-side of the
    -> operator.
   uppercase[str] or uc[str]
    and lowercase[str] or lc[str]
    functions to convert a string to upper- or lowercase.  These functions try
    to do the right thing with Unicode, possibly making the string longer in
    some cases.
   1_234_567_890
   frink.expr.AddExpression[x (undefined symbol), y (undefined
     symbol)], you'll see x + y (with maybe a few
    "undefined symbol" warnings depending on my mood of the day.)
   [key, value] pairs in an
    enumerating context.
  conforms operator not blow up if the items on both
    sides aren't units--just returns false.
  {{ || 2+3
     }} ) or even nonexistent argument lists, if the body is a single
    line (e.g. {{ 2+3
     }} )
  timezones[]
    function to list all known timezone names.
   now[] function
    to return the current date/time.  This is a bit slicker than the old way,
    which was to call eval["##"]
   lines[URL,
   encoding] function to read from a file or a URL where you
   need to specify the encoding of the file.  The encoding is a string
   representing any encoding that your version of Java supports, e.g.
   "UTF-8", "US-ASCII", "ISO-8859-1",
   "UTF-16", "UTF-16BE", "UTF-16LE".
   Your release of Java may support more charsets, but all implementations of
   Java are required to support the above.  Check the release notes for your
   Java implementation to see if other charsets are supported.
   read[URL,
   encoding] function to read from a file or a URL where you
    need to specify the encoding of the file.  See the previous note for more
    information about encodings.
   e be the base of the natural logarithm
    (2.718281828459...)  This supplants the former definition which was the
    charge on an electron.  This is now electroncharge.  Fight it
    out, mathematicians and physicists.
  dimensions[] function to return an enumeration of all
    DimensionList names.
  "$1.99" is not a candidate for variable replacement
    because variables must begin with a letter.  This makes it less
    error-prone (and somewhat faster) to have literal dollar amounts in
    Frink Server
     Pages, which internally treat literal blocks of HTML as a
    triple-quoted string and thus candidates for replacement.
  /e modifier to regex substitution expression to
    allow $0 match to match the whole pattern, even if it's not
    parenthesized.
  /e modifier to regex substitution expression which
    treats the right-hand-side of the substitution as an expression.  The
    values on the left-hand side in parentheses are put into the variables
    $1 , $2 , etc.
  
     
      lyrics = """Oh, Danny Boy,
   
      The pipes, the pipes are calling
      From glen to glen and down the mountainside"""
     
Truth class to return false for undefined symbols
    or the empty string.
   StringInterpolator.
   sqrt[x] function.
   NOR, NAND, IMPLIES and
    XOR operators.
   Truth.isTrue() to force
    truth-testing in all contexts.
  round[x,y] to round x to the nearest
    multiple of y.
   a.push[x] and
    a.pop[].
  -u [unitsfile] command-line option to allow
    you to specify your own alternate units file.
   random[min, max] to select a random integer between
    min and max (inclusive).
  -> operator.
  next statement to allow you to skip to the next
    iteration of while or for loops before reaching
    the end of the body.  This is not necessary, just some nice syntactic
    sugar.
   \uXXXX where XXXX is a
    4-digit hexadecimal number.  For example, the Unicode symbol for the Greek
    lowercase mu is \u03BC.
   for construct.
  frink.gui.InteractivePanel.
   ->
    could take an unbracketed comma-separated list on the right-hand
    side. This made default arguments in function definitions not work.
   pow() function.
  random[int] to generate random numbers
    between 0 (inclusive) and the value of int (exclusive.)
  square or sq and
    cubic or cu to raise the unit on their
    right-hand-side to the second and third power.  Thanks to the lovely
    Marcus Downing for the suggestion.  (I had linear as a no-op,
    but took it out.)
    
   squared and cubed operators to
    modify all the multiplicative units to their left.  This has a precedence
    between multiplication and addition, so 3 feet squared is
    equivalent to (3 feet)^2.  I tried to get the operator
    square to work in both contexts but decided that this was
    less arbitrary and better English.  (Okay, actually I gave up because I
    couldn't get the conflicts resolved.)
   /g modifier to make it work
    better (yet again.)  It now returns an array of arrays if evaluated in a
    non-enumerating context, and saves its values so it isn't evaluated
    multiple times.
   flatten[list] to flatten the elements of a
    list of lists into a one-dimensional list.  This is useful in the pattern
    match above if you want the results returned in a flat list.
   units[] function to list the names of all known
    units.
   units[unit] function to list the names of all
    of the units with the same dimensions as unit, or with a specific
    dimension list (e.g. acceleration, time, velocity, etc.)
   unit[string] function to return the unit with
    the given name.
  random[list] to select a random element
    from a list.
  -> able to take an
    unbracketed comma-separated list on the right-hand side.  It saves
    a few keystrokes.  Tweaked some precedence rules to make this possible.
    (Note: this was later repealed as it made default arguments in
    function definitions not work.)
  %r/.../g so
    that it made more sense and can be used in more places.
  <=> to compare the
    magnitude of 2 expressions (it works for strings, dates, and units.)
    
   sort[list] and sort[list,
     proc] functions to sort lists.  The second form takes a
    user-defined comparison routine.
    See the Sorting section of the
    documentation for samples.  This uses a quicksort algorithm.
   reverse[list] function to reverse the order
    of items in a list.
  dict keyword.  See the
    Dictionaries section of the
    documentation for a sample.
   keys[dict] function to return an enumeration
    of the keys contained in a dictionary (in no particular order.)
  select[list, proc]
    which returns the elements of list for which
    proc returns true.
  read[URL] function which reads the entire
    contents of an URL into a string.
  /g-modified regular expression
    matches to make the implementation more logical.  This implies that if
    you're going to use the /g modifier, you gotta use it in a
    loop, and you can't use it in a simple if statement.  This may be revised.
   +10.
   split[regex, str] function to split a
    string into an array based on a regular expression separator.
   join[separator,
     array] function to join the elements of an array into a
    string with the specified separator.
   line =~ %s/pattern/replacement/opts
  /g pattern-match modifier and allowed patterns to
    match multiple times in a single line by using the for loop.
   [first, second] = [1,2]
  regex[] functions to create a regular expression
    object from a string.
   lines[URL]
    function to read from a file or a URL.
   array[] function to turn a enumerating expression
    into an array.
   for loop for
    iterating over the contents of an enumerating expression.
  return statement in a function.
   Fahrenheit and Celsius functions to
    F[x] and C[x].  This means that to convert
    Fahrenheit to Celsius, you can enter the shorter F[98.6] -> C
   conforms operator to see if two units are conformal
    with each other.
   Fahrenheit[x], Celsius[x], and
    Reaumur[x] to convert to/from these temperature scales.
  # 2002-01-03
     10:00 AM New York #.  This allows easy conversions between all the
    timezones Frink knows about, and is a major improvement in timezone
    handling.  See main documentation for examples.
    
   dateformats.txt, as all
    date formats now allow a freeform timezone to be specified at the end.
   dateformats.txt file.
   1/3
     (approx. 0.3333333333333333) )  I like and dislike this... it
    shows you the true, exact, representation, and also puts it into terms you
    may better understand, but it's a bit cluttered.  I'll decide if I like it
    before I rewrite the affected documentation.
    
   year mod day -> days to find out how much
    the length of the year actually differs from 365 days.
   int[x] or trunc[x] functions which
    truncate the decimal part off a number.
   div operator, defined as x div y ===
     floor[x/y].  I'm not sure that floor[] is sensible and
    the correct rounding method to complement our definition of mod; I may
    change this definition.
  floor[x], ceil[x],
    recip[x], round[x], and modulus operator
    (% or mod).
   -> operator, like ## ->
     Germany to get the current time in Germany.
  ->).  This makes all of the language
    translation pairs work as advertised.
   ->) in quotes; this both evaluates the value in quotes and
    appends the quoted value so that you can eliminate some redundancy in
    formatting.  For example, you can say 10 feet ->
     "meters"3.048
     meters", as opposed to the "3.048" you would get if
    the right-hand-side was unquoted.
   2^13466917 - 1.  (A decimal number of over 4
    million digits.) This now works quickly (the exponentiation is performed in
    only 0.13 seconds,) but the algorithm to convert that gigantic binary
    number to decimal for display is still really slow for very large numbers
    (it takes over 14 hours.)  So, you can calculate really large values, but
    if you want to see the results, you'll have to wait.  (Note: the
    arbitrary-precision 2.^13466917 is very fast, if you don't
    need to see every digit.)
  Comments/questions to Alan Eliasen.
Back to Frink documentation.