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.
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.value
is 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 countPermutation
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.
ListExpression
s are now also
EnumeratingExpression
s.) 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.
NullPointerException
s. 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
InputStream
s 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.
NullPointerException
s 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 -> Richter
sovereigns_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 = 10
Classname.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 length
var t is time = 0 seconds
More description can be found in the Constraints on Variables section of the documentation.
var a
var 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 10
for 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.