Function Repository Resource:

AlgebraicRange

Source Notebook

Generate ranges of algebraic numbers

Contributed by: Daniele Gregori

ResourceFunction["AlgebraicRange"][x]

gives the range of square roots Sqrt[Range[1,x^2]], for x>=1.

ResourceFunction["AlgebraicRange"][x,y]

gives the range of square roots Sqrt[Range[x^2,y^2]], for 0<=x<=y.

ResourceFunction["AlgebraicRange"][x,y,s]

generates steps bounded above by s, with 0<s<=y.

ResourceFunction["AlgebraicRange"][x,y,s,d]

requires the steps to be bounded below by d, with 0<=d<=s.

Details and Options

AlgebraicRange creates ranges made of algebraic numbers. This extends the basic concept of Range to include, besides Rational numbers, also roots, always restricted to the Reals domain.
The first two arguments represent the bounds of the range (minimum and maximum values), while the optional third and fourth arguments (by default equal to 1 and 0) regulate the upper and lower bounds of the steps (differences between successive elements).
If no step parameter is specified, the elementary algebraic range ResourceFunction["AlgebraicRange"][x,y] is determined by the square root range Sqrt[Range[x^2,y^2]], for x,y>0. The extension to negative bounds x <0 or y<0 is performed simply by reflection, since general real roots are mathematically defined only for positive arguments.
The step between successive algebraics is not straightforward to define univocally, as there exists no constant difference among the irrational numbers generated even with the elementary algebraic range. However, it turns out that an intuitively simple class of algebraic ranges, with non-unit step parameter s, is obtained by taking the outer product of ResourceFunction["AlgebraicRange"][Min[x,x/s],y] with Join[ Range[Max[1, s], y, s],Range[Max[1, s], 0, -s]], for s>0 and 0<=x<=y. Then the parameter s also becomes the upper bound for all the steps. For example,
The algebraic numbers thus generated can often be in a great number, with a tendency to accumulate towards certain points. To avoid these features, a further fourth argument d can be optionally provided to require a minimum (absolute value) difference between successive algebraics, that is a lower bound for all the steps. This truncation process typically leads to a nearly uniform distribution of numeric values.
Extended functionality and syntax, especially for creating algebraic numbers of a more general form, are provided in the homonymous function of the paclet DanieleGregori/GeneralizedRange.
A natural application of AlgebraicRange is in the search for closed forms for floating point numbers, possibly in terms of arbitrary combinations of mathematical functions with algebraic arguments, through ResourceFunction["FindClosedForm"].
ResourceFunction["AlgebraicRange"] accepts the following options:
"RootOrder"2the root orders to be included
"StepMethod""Outer"change the method to define the step
"FareyRange"Falsegenerate algebraic numbers with steps given by the Farey sequence
"FormulaComplexity"Infinityset a complexity threshold over which the algebraics are discarded
"AlgebraicsOnly"Trueaccept only algebraic arguments and output
The option "RootOrder" can take the following values:
rinclude roots up to r order
{r}include only roots of order r
{r1,r2,}include roots of all specified orders rk
The option "StepMethod" can be used to define the step in ResourceFunction["AlgebraicRange"][x,y,s] and can take the following values:
"Outer"take the Outer product of ResourceFunction["AlgebraicRange"][Min[x,x/s],y] with Join[ Range[Max[1, s], y, s],Range[Max[1, s], 0, -s]]
"Root"use Sqrt[Range[x^2,y^2,s^2]]
A more detailed explanation of the step definition, also for negative bounds, can be found in the Properties and Relations Examples subsection.
Besides using the fourth argument to impose a lower bound on the steps, another way to restrict the output of AlgebraicRange is by setting a threshold for the complexity of the numeric expressions involved through the option "FormulaComplexity". The heuristic prescription for computing such complexity values is the following: i) take all Integers appearing in the algebraic expression; ii) if a root or Power appears, duplicate its argument a number of times equal to the root or power degree; iii) if a negative integer or 0 appears, take its opposite and add 1; iv) for each positive integer, compute the Mean among its DigitSum, 5 times its IntegerLength, the total number of its prime factors and the square root of its absolute value; v) normalize these means by multiplying them by 1/2 (so to let the numbers 0 and 1 have unit complexity); vi) take the Total of all these means.

Examples

Basic Examples (2) 

Generate a range of square roots:

In[1]:=
range = ResourceFunction["AlgebraicRange"][3]
Out[1]=
In[2]:=
NumberLinePlot[range]
Out[2]=

Generate a square root range with non-unit step:

In[3]:=
range = ResourceFunction["AlgebraicRange"][0, 3, 1/2]
Out[3]=
In[4]:=
NumberLinePlot[range]
Out[4]=

Scope (4) 

Generate a range of negative square roots:

In[5]:=
range = ResourceFunction["AlgebraicRange"][-3, -1]
Out[5]=
In[6]:=
NumberLinePlot[range]
Out[6]=

Generate a range of mixed positive and negative roots, with a negative step:

In[7]:=
range = ResourceFunction["AlgebraicRange"][2, -2, -1/2]
Out[7]=
In[8]:=
NumberLinePlot[range]
Out[8]=

Generate a range of square roots, with certain upper and lower bounds on the steps:

In[9]:=
range = ResourceFunction["AlgebraicRange"][2, 7, 1/3, 1/4]
Out[9]=
In[10]:=
NumberLinePlot[range]
Out[10]=
In[11]:=
N@MinMax@Differences[range]
Out[11]=

Generate a range of nested square roots:

In[12]:=
ResourceFunction["AlgebraicRange"][Sqrt[1 + Sqrt[2]], 4, 1/Sqrt[2]]
Out[12]=

Options (14) 

RootOrder (4) 

Generate a range of square and cubic roots:

In[13]:=
ResourceFunction["AlgebraicRange"][2, "RootOrder" -> 3]
Out[13]=

Generate a range of fourth roots:

In[14]:=
ResourceFunction["AlgebraicRange"][0, 4, 2, "RootOrder" -> {4}]
Out[14]=

Generate a range of cube and fifth roots:

In[15]:=
ResourceFunction["AlgebraicRange"][1, 3/2, "RootOrder" -> {3, 5}]
Out[15]=

Generate algebraic terms up to fourth root order and require a minimum absolute difference between successive roots:

In[16]:=
ResourceFunction["AlgebraicRange"][0, 4, 2, 1/4, "RootOrder" -> 4]
Out[16]=

StepMethod (3) 

Change method to define the step:

In[17]:=
root = ResourceFunction["AlgebraicRange"][0, 3, 1/3, "StepMethod" -> "Root"]
Out[17]=

Compare with the default "Outer" step method:

In[18]:=
outer = ResourceFunction["AlgebraicRange"][0, 3, 1/3]
Out[18]=
In[19]:=
NumberLinePlot[{root, outer}, PlotLegends -> {"Root", "Outer"}]
Out[19]=

In general, the default range is a subset of this other:

In[20]:=
SubsetQ[root, outer]
Out[20]=

FareyRange (2) 

Generate an algebraic range that generalizes ResourceFunction["FareyRange"]:

In[21]:=
algrange = ResourceFunction["AlgebraicRange"][0, 3, 1/3, "FareyRange" -> True]
Out[21]=
In[22]:=
fareyrange = ResourceFunction["FareyRange"][0, 3, 3]
Out[22]=
In[23]:=
SubsetQ[algrange, fareyrange]
Out[23]=

Notice that the step parameter is originally the denominator of the step (both it and its reciprocal are accepted). This corresponds to the Union of ranges with steps equal to the elements of the FareySequence:

In[24]:=
FareySequence[3] // DeleteCases[#, 0] &
Out[24]=
In[25]:=
SortBy[Union@
   Flatten@Map[ResourceFunction["AlgebraicRange"][0, 3, #] &, %], N] ==
  ResourceFunction["AlgebraicRange"][0, 3, 3, "FareyRange" -> True]
Out[25]=

FormulaComplexity (3) 

With the default option "FormulaComplexity" set to Infinity, a very large number of algebraics can be produced:

In[26]:=
ResourceFunction["AlgebraicRange"][1, 4, 1, "RootOrder" -> 4] // Short
Out[26]=
In[27]:=
NumberLinePlot[%]
Out[27]=

One way to limit these is by using the fourth argument, to require a minimum absolute difference between successive algebraics:

In[28]:=
ResourceFunction["AlgebraicRange"][1, 4, 1, 1/10, "RootOrder" -> 4]
Out[28]=
In[29]:=
NumberLinePlot[%]
Out[29]=

An alternative way is by setting the option "FormulaComplexity" to a finite threshold value, to select only numeric symbols with complexity less than that:

In[30]:=
ResourceFunction["AlgebraicRange"][4, "RootOrder" -> 4, "FormulaComplexity" -> 8]
Out[30]=
In[31]:=
NumberLinePlot[%]
Out[31]=

AlgebraicsOnly (2) 

By default, only algebraic numbers are accepted as input parameters:

In[32]:=
ResourceFunction["AlgebraicRange"][0, 5, Sqrt[E]]
Out[32]=

Set this option to deliberately accept an output range which includes transcendental numbers:

In[33]:=
ResourceFunction["AlgebraicRange"][0, 5, Sqrt[E], "AlgebraicsOnly" -> False]
Out[33]=
In[34]:=
Element[%, Algebraics]
Out[34]=

Applications (2) 

AlgebraicRange[x,y] is naturally suited for searching possible closed forms through ResourceFunction["FindClosedForm"]:

In[35]:=
ResourceFunction["FindClosedForm"][1.05592, BarnesG, "SearchRange" -> Function[ResourceFunction["AlgebraicRange"][-#, #, "RootOrder" -> 4]]]
Out[35]=
In[36]:=
N[%]
Out[36]=

Compare with the more complex result found with the "Plain" rational range:

In[37]:=
ResourceFunction["FindClosedForm"][1.05592, BarnesG, "SearchRange" -> "Plain"]
Out[37]=
In[38]:=
N[%]
Out[38]=

AlgebraicRange[x,y,s] provides a more general search range:

In[39]:=
ResourceFunction["AlgebraicRange"][-3, 3, 1/3, "RootOrder" -> 4] // Short
Out[39]=
In[40]:=
MemberQ[%, 4/3]
Out[40]=

The built-in function RootApproximant may have difficulty recognizing even relatively simple nested roots:

In[41]:=
N[4 Sqrt[5 + Sqrt[2]], 10]
Out[41]=
In[42]:=
RootApproximant[%] // ToRadicals
Out[42]=

In principle, these may be recognized by equipping ResourceFunction["FindClosedForm"] with a suitable search range in terms of AlgebraicRange[x,y,s]:

In[43]:=
ResourceFunction["FindClosedForm"][10.13051909, Identity, "SearchRange" -> Function[
   Join[ResourceFunction["AlgebraicRange"][1, #, 1/2], ResourceFunction["AlgebraicRange"][Sqrt[1 + Sqrt[2]], #, 1/Sqrt[2]]]]]
Out[43]=

Properties and Relations (6) 

AlgebraicRange[x,y] extends Range[x,y]:

In[44]:=
algrange = ResourceFunction["AlgebraicRange"][2, 5]
Out[44]=
In[45]:=
range = Range[2, 5]
Out[45]=
In[46]:=
SubsetQ[algrange, range]
Out[46]=

AlgebraicRange[x,y] for x<=y<0 is equivalent to Reverse[-AlgebraicRange[-y,-x]]:

In[47]:=
ResourceFunction["AlgebraicRange"][-3, -1]
Out[47]=
In[48]:=
Reverse[-ResourceFunction["AlgebraicRange"][1, 3]]
Out[48]=

Compute the algebraic range for 0<=x<=y and positive step upper bound s>0:

In[49]:=
ResourceFunction["AlgebraicRange"][1, 3, 1/2]
Out[49]=

This is an equivalent calculation:

In[50]:=
Select[SortBy[
  Outer[Times, Range[0, 3, 1/2], ResourceFunction["AlgebraicRange"][1, 3]] // Flatten // DeleteDuplicates, N], 1 <= # <= 3 &]
Out[50]=

An algebraic range with a negative irrational step size:

In[51]:=
ResourceFunction["AlgebraicRange"][3, 3/2, -1/Sqrt[3]]
Out[51]=

An equivalent calculation:

In[52]:=
Select[ReverseSortBy[
  Outer[Times, Join[Range[1, 3, 1/Sqrt[3]], Range[1, 0, -1/Sqrt[3]]], Range[3^2, (3/2)^2, -1]^(1/2)] // Flatten // DeleteDuplicates, N],
  3/2 <= # <= 3 &]
Out[52]=

Because of this peculiar definition, a negative step is not always equivalent to the reversed positive step:

In[53]:=
ResourceFunction["AlgebraicRange"][3/2, -3/2, -1/3]
Out[53]=
In[54]:=
ResourceFunction["AlgebraicRange"][-3/2, 3/2, 1/3] // Reverse
Out[54]=

As a general rule, a positive starting point is always preserved:

In[55]:=
ResourceFunction["AlgebraicRange"][Sqrt[10], -Sqrt[10], -2]
Out[55]=
In[56]:=
ResourceFunction["AlgebraicRange"][
  2 Sqrt[2 + Sqrt[3]], -2 Sqrt[2 + Sqrt[3]], -Sqrt[5]] // Simplify
Out[56]=

The numbers generated always belong to the domains of Algebraics and Reals:

In[57]:=
algrange = Block[{$MaxExtraPrecision = 10000}, ResourceFunction["AlgebraicRange"][
   2 Sqrt[1 + Sqrt@RandomInteger[{2, 4}]], -2 Sqrt[
     1 + Sqrt@RandomInteger[{2, 4}]], -Sqrt[2]/RandomInteger[{2, 4}], 1/4, "RootOrder" -> RandomInteger[{2, 5}, 2]]]
Out[57]=
In[58]:=
Element[algrange, Algebraics]
Out[58]=
In[59]:=
Element[algrange, Reals]
Out[59]=

Possible Issues (2) 

Only real arguments are accepted:

In[60]:=
ResourceFunction["AlgebraicRange"][Sqrt[1 - Sqrt[2]], 4, 1/Sqrt[2]]
Out[60]=

A simple numeric input can be automatically recognized with its exact expression:

In[61]:=
range = ResourceFunction["AlgebraicRange"][0.1, 3.1]
Out[61]=
In[62]:=
N[range]
Out[62]=

However, some numeric input is not adequately recognized:

In[63]:=
approxrange = ResourceFunction["AlgebraicRange"][1.266314886, 3]
Out[63]=
In[64]:=
N[approxrange]
Out[64]=

In any case, the numeric difference with the corresponding exact expressions remains negligible:

In[65]:=
range = ResourceFunction["AlgebraicRange"][1/2 Sqrt[5 + Sqrt[2]], 3]
Out[65]=
In[66]:=
N[range - approxrange]
Out[66]=
In[67]:=
NumberLinePlot[{approxrange, range}]
Out[67]=

Publisher

Daniele Gregori

Requirements

Wolfram Language 12.0 (April 2019) or above

Version History

  • 1.0.0 – 29 October 2025

Related Resources

Author Notes

Extended functionality is provided in the homonymous function of the paclet "DanieleGregori/GeneralizedRange".

The definition of the "FormulaComplexity" option values in ResourceFunction["FindClosedForm"] will be made uniform with here.

License Information