Droidulator is a powerful, feature-rich scientific mathematical calculator and REPL scripting environment for Android devices, ported from the original Cardulator C++ engine.
Built with Kotlin for the Android UI and a high-performance C++ NDK core (TinyExpr-PlusPlus + GNU Units), Droidulator provides real-time Gruvbox-themed syntax highlighting, 7-stage rainbow bracket matching, SI prefix parsing, scientific notation, user variables and functions, interactive multi-argument formula wizards, a C-style scripting engine with 1D array support, REPL script runner run("script_name"), interactive 2D function plotting, and persistent JSON storage.
- High-Performance REPL: Interactive evaluation loop with
Tabautocompletion, 1-based answer history (e1,e2...), SI prefix parsing (1k=1000,2M2=2,200,000), scientific notation (5e10), and multi-statement execution using;. - Gruvbox Design & Theme Engine: Sleek dark and light mode UI powered by a centralized
ThemePalettedesign system matching the iconic Gruvbox retro aesthetic. - Dynamic Syntax Highlighting & Rainbow Brackets: Real-time syntax coloring (purple numbers, aqua functions, yellow constants, red keywords/errors, orange operators) with 7-level depth rainbow bracket matching (
( ),[ ],{ }). - Interactive Script Editor & Runner (
run("script_name")):- Full-screen script editor with
Cancel,TAB,RUN, andSAVEcontrols. - In-editor
TABbutton for local variable & global symbol autocompletion. - Dedicated REPL command
run("script_name")withTabautocompletion to execute saved scripts directly from the calculation prompt and inspect output.
- Full-screen script editor with
- Formula Library & Parameter Wizard: Multi-argument formula manager using standard
f(x, y) = expressionsyntax. Interactive parameter dialog calculates live preview without side effects and exports results directly into REPL history with sequentiale#variables. - 2D Function Plotting Engine: Interactive Matplotlib-style function and vector plotter (
plot(y),plot(x, y, color, linestyle)) with hold overlays (plot.hold(1)), custom axis bounds (plot.xlim,plot.ylim), panning, and zooming. - GNU Units Integration: Built-in physical unit conversion and evaluation engine powered by C++ GNU Units library.
- Persistent Storage: Automatic JSON-based storage (
user_data.json) preserving user variables, formulas, constants, and scripts across app restarts.
Droidulator features a mode selection dropdown at the top navigation header bar to switch between views:
| Mode | Functionality |
|---|---|
| Calculator (REPL) | Primary REPL terminal for live calculation, history review, script running run(), and navigation toolbar. |
| Scripts | Manage saved user scripts. Create new scripts, edit existing ones, run scripts with popup output logs, or delete scripts. |
| Variables | Unified variable manager (x = 42, e# history variables). Single-field definition editor for inline modification and removal. |
| Formulas | Interactive formula library (f(x) = x^2 + 2*x). Tap a formula to open the live parameter preview wizard and export results to REPL. |
| Constants | Custom & built-in constant definitions (const MY_PI = 3.14159). |
| Plot | 2D graph viewer for interactive function visualization and plotting. |
| Settings | Configure number formatting modes, decimal precision (DP), digit grouping, e# history variable visibility, and light/dark theme modes. |
| Help | Contextual help reference for available functions, operators, and syntax. |
Droidulator provides fine-grained control over numerical result representation via the top header bar spinners or the Settings menu:
-
NORM(Normal): Default floating-point representation. Drops unnecessary trailing zeros. -
FLT(Float): Standard floating-point output with default precision. -
FIX(Fixed Point): Rounds results to a fixed number of decimal places defined by DP. (e.g.,3.14159265$\rightarrow$ 3.141593at 6 DP). -
SCI(Scientific Notation): Displays numbers in exponential$m \times 10^n$ format (e.g.,1.234567e+06). -
ENG(Engineering Notation): Displays numbers in scientific notation where the exponent is restricted to multiples of 3 (e.g.,$10^3, 10^6, 10^{-3}$ ), matching standard SI engineering units.
- Configurable decimal precision level ranging from 0 to 12 decimal places (default: 6 DP).
- Directly controls fractional digit rounding across
FIX,SCI, andENGmodes.
- Digit Grouping (Thousands Separator): Toggles space separators for large numbers (e.g.,
1 000 000.00vs1000000.00). - History Variable Visibility (
#/e#): Toggle (ON/OFF) displaying sequential history evaluation results (e1 = ...,e2 = ...) in the Variables manager tab. - Hide Welcome Message on Start: Toggle (
ON/OFF) hiding the initial welcome banner in the REPL terminal. - Auto-Pair Brackets & Quotes: Toggle (
ON/OFF) automatic insertion of closing pairs for( ),[ ],{ }," ",' '.
Droidulator supports dynamic theme switching via Settings:
- Auto: Automatically matches Android system Day/Night mode.
- Dark: Dark palette mode.
- Light: Light palette mode.
- Custom Theme Source: Load custom JSON theme files directly from device storage or reset to built-in defaults.
A custom theme file contains a JSON object with optional "dark" and "light" sections. Every color is defined as a hexadecimal RGB/RGBA string (e.g., "#282828").
{
"dark": {
"bg": "#282828",
"bg_soft": "#3C3836",
"bg_card": "#3C3836",
"bg_dark_text": "#282828",
"fg_text": "#EBDBB2",
"fg_dim": "#A89984",
"fg_inverted": "#282828",
"border_color": "#504945",
"aqua": "#689D6A",
"green": "#8EC07C",
"yellow": "#FABD2F",
"yellow_dark": "#D79921",
"orange": "#FE8019",
"orange_dark": "#D65D0E",
"red": "#FB4934",
"purple": "#D3869B",
"blue": "#83A598",
"rainbow_0": "#FABD2F",
"rainbow_1": "#FE8019",
"rainbow_2": "#FB4934",
"rainbow_3": "#D3869B",
"rainbow_4": "#83A598",
"rainbow_5": "#8EC07C",
"rainbow_6": "#B8BB26"
},
"light": {
"bg": "#FBF1C7",
"bg_soft": "#EBDBB2",
"bg_card": "#EBDBB2",
"bg_dark_text": "#282828",
"fg_text": "#3C3836",
"fg_dim": "#7C6F64",
"fg_inverted": "#FBF1C7",
"border_color": "#A89984",
"aqua": "#427B58",
"green": "#98971A",
"yellow": "#B57614",
"yellow_dark": "#B57614",
"orange": "#AF3A03",
"orange_dark": "#AF3A03",
"red": "#9D0006",
"purple": "#8F3F71",
"blue": "#076678",
"rainbow_0": "#B57614",
"rainbow_1": "#AF3A03",
"rainbow_2": "#9D0006",
"rainbow_3": "#8F3F71",
"rainbow_4": "#076678",
"rainbow_5": "#427B58",
"rainbow_6": "#79740E"
}
}Save the snippet below as tokyo_night.json and load it via Settings
{
"dark": {
"bg": "#1a1b26",
"bg_soft": "#24283b",
"bg_card": "#24283b",
"bg_dark_text": "#1a1b26",
"fg_text": "#c0caf5",
"fg_dim": "#565f89",
"fg_inverted": "#1a1b26",
"border_color": "#414868",
"aqua": "#7dcfff",
"green": "#9ece6a",
"yellow": "#e0af68",
"yellow_dark": "#e0af68",
"orange": "#ff9e64",
"orange_dark": "#ff9e64",
"red": "#f7768e",
"purple": "#bb9af7",
"blue": "#7aa2f7",
"rainbow_0": "#e0af68",
"rainbow_1": "#ff9e64",
"rainbow_2": "#f7768e",
"rainbow_3": "#bb9af7",
"rainbow_4": "#7aa2f7",
"rainbow_5": "#7dcfff",
"rainbow_6": "#9ece6a"
}
}- Addition
+, Subtraction-, Multiplication*, Division/, Modulo%(ormod(a, b)). - Exponentiation
^(e.g.,2^10$\rightarrow$ 1024). Supports fractional exponents (8^(1/3)$\rightarrow$ 2). - Negation
-xand unary plus+x.
Default angular unit is Degrees.
sin(x),cos(x),tan(x),ctan(x)— Standard trigonometric functions (takes degrees).asin(x),acos(x),atan(x)— Inverse trigonometric functions (returns degrees).- Radians conversions:
deg2rad(x)(ord2r(x)),rad2deg(x)(orr2d(x)).
-
ln(x)— Natural logarithm (base$e$ ). -
log(x)(orlog10(x)) — Common logarithm (base 10). -
log2(x)— Binary logarithm (base 2). -
logb(x, base)— Logarithm with arbitrary base. -
exp(x)— Exponential function$e^x$ .
-
abs(x)— Absolute value / magnitude. -
sqrt(x)/cbrt(x)— Square root / Cube root. -
floor(x),ceil(x),round(x),trunc(x). -
sgn(x)— Signum function (-1 for$x < 0$ , 0 for$x = 0$ , 1 for$x > 0$ ).
mean(a1, a2, ...)— Arithmetic mean of sample.median(a1, a2, ...)— Median of sample.std(a1, a2, ...)— Standard deviation.var(a1, a2, ...)— Sample variance.min(a1, a2, ...)/max(a1, a2, ...)— Minimum / maximum value.
-
C(n, k)(orCnk(n, k)) — Binomial coefficient (combinations$n$ choose$k$ ). -
P(n, k)— Permutations$n$ P$k$ . -
fact(n)(orn!) — Factorial. -
gcd(a, b, ...)— Greatest common divisor. -
lcm(a, b, ...)— Least common multiple. -
fib(n)—$n$ -th Fibonacci number.
-
pi— Mathematical constant$\pi \approx 3.141592653589793$ -
e— Euler's number$e \approx 2.718281828459045$
-
Constant
e: Standalone lowercase token (e.g.,e,e^2,2*e). -
Scientific Notation: Numerical suffix exponent (e.g.,
5e10$= 5 \times 10^{10}$ ,1e-5$= 10^{-5}$ ). -
REPL History Variables: Sequential history reference (e.g.,
e1,e2,e3).
Droidulator performs all mathematical evaluations using 64-bit IEEE 754 Double-Precision Floating-Point arithmetic (double):
- Significant Precision: 53-bit significand (~15–17 decimal digits of precision).
-
Exact Integers: Exact integer representation up to
$\pm 2^{53}$ ($\pm 9,007,199,254,740,992$ ). -
Dynamic Range: Numbers from
$\approx \pm 2.225 \times 10^{-308}$ to$\approx \pm 1.797 \times 10^{308}$ . -
Special Values: Full IEEE 754 support for
+inf/-inf(overflow / division by zero) andNaN(undefined indeterminate forms).
Droidulator supports standard SI prefixes directly within expressions (e.g., 1.5k + 200 1700). SI prefixes can also replace the decimal separator in R-notation (e.g., 1k7 1700).
| Power | Prefix | Symbol | Example |
|---|---|---|---|
| deca | da |
1da = 10
|
|
| hecto | h |
1h = 100
|
|
| kilo | k |
1.5k = 1500
|
|
| mega | M |
2M2 = 2,200,000
|
|
| giga | G |
1G = 1,000,000,000
|
|
| tera | T |
1T = 10^{12}
|
|
| peta | P |
1P = 10^{15}
|
|
| exa | E |
1E = 10^{18}
|
|
| zetta | Z |
1Z = 10^{21}
|
|
| yotta | Y |
1Y = 10^{24}
|
| Power | Prefix | Symbol | Example |
|---|---|---|---|
| deci | d |
1d = 0.1
|
|
| centi | c |
1c = 0.01
|
|
| milli | m |
100m = 0.1
|
|
| micro | u |
10u = 0.00001
|
|
| nano | n |
1n5 = 0.0000000015
|
|
| pico | p |
1p = 10^{-12}
|
|
| femto | f |
1f = 10^{-15}
|
|
| atto | a |
1a = 10^{-18}
|
|
| zepto | z |
1z = 10^{-21}
|
|
| yocto | y |
1y = 10^{-24}
|
Droidulator provides native support for physical unit conversions, logarithmic ratio calculations, and electronic component marking code conversions (SMD 3-digit, SMD 4-digit, EIA-96, and RKM notation).
-
Physical & Engineering Units:
conv(5, "mile", "km"),conv(100, "km/hr"),conv(24, "AWG", "mm^2"). -
Standard Metric Wire Gauges (
std_mm2): Rounds cross-section up (IEC 60228 / GOST 22483 standard series: 0.03 ... 1200 mm²) with copper safety margin:-
conv(2.1, "mm2", "std_mm2")$\rightarrow$ 2.5 std_mm2 -
conv(14, "AWG", "std_mm2")$\rightarrow$ 2.5 std_mm2(14 AWG is 2.08 mm²)
-
-
Standard AWG Wire Gauges (
std_awg): Rounds gauge down to thicker integer wire (more copper area):-
conv(2.5, "mm2", "std_awg")$\rightarrow$ 13 std_awg(13 AWG = 2.62 mm²)
-
-
dB & Power/Voltage Ratios:
conv(30, "dBm", "mW"),conv(20, "dB", "times")(Power 100x),conv(20, "dB_v", "times")(Voltage 10x).
The conv() function handles conversion between numeric values (in base SI units like
-
Marking Code String to Value: Strings with marking codes must be enclosed in quotes:
-
conv("01C", "ohm")$\rightarrow$ 10000 ohm(10 kΩ) -
conv("104", "uf")$\rightarrow$ 0.1 uF(100 nF) -
conv("4R7", "uh")$\rightarrow$ 4.7 uH
-
-
Numeric Value to Code: Numbers are passed directly without quotes:
-
conv(10000, "eia96")$\rightarrow$ "01C" -
conv(4700, "smd3")$\rightarrow$ "472" -
conv(4700, "smd4")$\rightarrow$ "4701" -
conv(220, "smd3")orconv(220, "ohm", "smd3")$\rightarrow$ "221"
-
-
Code to Code Conversion:
conv("472", "smd4")$\rightarrow$ "4701".
-
SMD 3-Digit (
smd3): 2-digit mantissa + 1-digit exponent ($M \times 10^E ;\Omega$ ).-
conv("100", "ohm")$\rightarrow$ 10 ohm(E24) -
conv("472", "ohm")$\rightarrow$ 4700 ohm(4.7 kΩ, E24) -
conv("104", "ohm")$\rightarrow$ 100000 ohm(100 kΩ, E24)
-
-
SMD 4-Digit (
smd4): 3-digit mantissa + 1-digit exponent ($M \times 10^E ;\Omega$ ).-
conv("1000", "ohm")$\rightarrow$ 100 ohm(E96) -
conv("4701", "ohm")$\rightarrow$ 4700 ohm(4.7 kΩ, E96) -
conv("1002", "ohm")$\rightarrow$ 10000 ohm(10 kΩ, E96)
-
-
RKM Decimal Notation (
2R2,R2,4R7): Uses lettersR/K/M/P/N/Uas decimal points without interfering with user variables:-
conv("R22", "ohm")$\rightarrow$ 0.22 ohm(E24) -
conv("2R2", "ohm")$\rightarrow$ 2.2 ohm(E24) -
conv("4R7", "ohm")$\rightarrow$ 4.7 ohm(E24)
-
-
EIA-96 1% Precision Code (
eia96): 2-digit value lookup index (01–96) + 1-character multiplier letter.
All standard and alternative EIA-96 multiplier letters are supported on input:
| Multiplier Letter | Multiplier Factor | Example Code | Equivalent Resistance |
|---|---|---|---|
Z |
"01Z" |
0.1 ohm |
|
Y or R
|
"01Y", "01R"
|
1 ohm |
|
X or S
|
"01X", "01S"
|
10 ohm |
|
A |
"01A" |
100 ohm (E96 index 01 = 100)
|
|
B or H
|
"01B", "01H"
|
1000 ohm (1 kΩ)
|
|
C |
"01C" |
10000 ohm (10 kΩ)
|
|
D |
"01D" |
100000 ohm (100 kΩ)
|
|
E |
"01E" |
1000000 ohm (1 MΩ)
|
|
F |
"01F" |
10000000 ohm (10 MΩ)
|
-
Capacitance Marking Codes: 3-digit pF base codes and RKM pF/nF/uF markings:
-
conv("104", "uf")$\rightarrow$ 0.1 uF(100 nF) -
conv("473", "nf")$\rightarrow$ 47 nF -
conv("4p7", "pf")$\rightarrow$ 4.7 pF
-
-
Inductance Marking Codes: 3-digit uH base codes and RKM uH/nH markings:
-
conv("4R7", "uh")$\rightarrow$ 4.7 uH -
conv("101", "uh")$\rightarrow$ 100 uH -
conv("10n", "nh")$\rightarrow$ 10 nH
-
-
Simple Range (step = 1):
start:end(e.g.,1:10$\rightarrow$ [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) -
Range with Step:
start:step:end(e.g.,1:2:10$\rightarrow$ [1, 3, 5, 7, 9],10:-1:1$\rightarrow$ [10, 9, ..., 1]) -
Indexing (1-based):
(1:2:10)[1]$\rightarrow$ 1
-
if(condition, expr_true, expr_false)(e.g.,if(5 > 3, 10, 20)$\rightarrow$ 10) - Multi-branch condition:
iff(cond1, val1, cond2, val2, ..., default)(e.g.,iff(x > 0, 1, x < 0, -1, 0))
-
Summation:
sum(index, start, end, expr)(e.g.,sum(i, 1, 10, i^2)$\rightarrow$ $\sum_{i=1}^{10} i^2 = 385$ ) -
Product:
prod(index, start, end, expr)(e.g.,prod(i, 1, 5, i)$\rightarrow$ $5! = 120$ ) -
Range Min/Max:
min(index, start, end, expr)/max(index, start, end, expr)
- Variables:
temp = 25, thentemp * 2$\rightarrow$ 50. - Constants:
const a = 3. Constants can be updated with explicitconst(const a = 2), but assigninga = 10raises aConst Error.
-
Single-line functions:
f(x) = x^2orf(x, y) = 2*x + y -
Multi-line / Block functions (
fn/def/function):fn calculate(a, b) { c = a * 2; return c + b }
-
Multiple statements on one line: Separate instructions with
;(e.g.,x = 5; y = 10; x + y$\rightarrow$ 15).
The script manager allows creating, editing, and executing multi-line C-style programs with structural logic.
-
Conditionals:
if (x > 10) { print("x is large") } else if (x > 5) { print("x is medium") } else { print("x is small") }
-
Loops:
while (cond) { ... }for (i = 1; i <= 10; i++) { ... }
-
Assignments & Shorthands:
i++,i--,a += b,a -= b. -
Execution Control & Output:
sleep(ms)— Pause execution for specified milliseconds.print("Text {expr}")— Formatted printing with interpolated expressions inside curly braces.
-
1D Arrays in Scripts:
- Creation:
A = [1, 2, 3]orA = 1:10. - 1-based Indexing:
A[1] = 99. - Element-wise Math:
C = A .* B,C = A ./ B,C = A + B,C = A * 5. - Dot Product:
dot_val = A * B. - Length:
len(A).
- Creation:
Execute any saved script directly from the REPL input prompt:
> run("my_script")
- Typing
run(in REPL and pressingTabautomatically suggests registered user script names.
Visualize functions or datasets directly on screen.
plot(x, y)/plot(y)— Plot array/vector data.plot(x, y, color, linestyle)— Plot with custom color ("r","g","b","c","m","y","k","w") and line style ("-","--","-.",":","").plot.show()/plot.close()— Open / close plot display.plot.hold(1)/plot.hold(0)— Retain overlay of multiple plots.plot.xlim([min, max])/plot.ylim([min, max])— Manual axis limit boundaries.
- Android Studio (Ladybug or newer recommended) or Android SDK + NDK.
- Java JDK 17 / 21.
- CMake 3.22+.
git clone --recursive https://github.com/aroum/droidulator.git
cd droidulator./gradlew assembleDebugThis project is licensed under the GNU General Public License v3.0 (GPLv3).
- GNU Units: Licensed under the GNU General Public License v3.0 (GPLv3).
- TinyExpr++: Licensed under the zlib License.





