| # This is a demo of ivy. Type a newline to advance to each new step. Type one now. |
| # At any time, type the word "quit" or EOF to end the demo and return to ivy. |
| # Each step in the demo is one line of input followed by some output from ivy. Type a newline now to see. |
| 2+2 |
| # The first line you see above (2+2) is input; the next (4) is output from a running ivy. |
| # Comments start with # and produce no output. |
| # Whenever you like, you can type an expression yourself. Try typing 2*3 now, followed by two newlines: |
| # Keep typing newlines; the ivy demo is about to start. |
| # Arithmetic has the obvious operations: + - * etc. ** is exponentiation. mod is modulo. |
| 23 |
| 23 + 45 |
| 23 * 45 |
| 23 - 45 |
| 7 ** 3 |
| 7 mod 3 |
| # Operator precedence is unusual. |
| # Unary operators operate on everything to the right. |
| # Binary operators operate on the item immediately to the left, and everything to the right. |
| 2*3+4 # Parsed as 2*(3+4), not the usual (2*3)+4. |
| 2**2+3 # 2**5, not (2**2) + 3 |
| (2**2)+3 # Use parentheses if you need to group differently. |
| # Ivy can do rational arithmetic, so 1/3 is really 1/3, not 0.333.... |
| 1/3 |
| 1/3 + 4/5 |
| 1/3 ** 2 # We'll see non-integral exponents later. |
| # Even when a number is input in floating notation, it is still an exact rational number inside. |
| 1.2 |
| # In fact, ivy is a "bignum" calculator that can handle huge numbers and rationals made of huge numbers. |
| 1e10 # Still an integer. |
| 1e100 # Still an integer. |
| 1e10/3 # Not an integer, but an exact rational. |
| 3/1e10 # Not an integer, but an exact rational. |
| 2**64 # They can get big. |
| 2**640 # They can get really big. |
| # They can get really really big. Type a newline to see 2**6400 scroll by. |
| 2**6400 |
| # Ivy also has characters, which represent a Unicode code point. |
| 'x' |
| char 0x61 # char is an operator: character with given value. |
| char 0x1f4a9 |
| code '💩' # char's inverse, the value of given character, here printed in decimal. |
| # Everything in ivy can be placed into a vector. |
| # Vectors are written and displayed with spaces between the elements. |
| 1 2 3 |
| 1 4/3 5/3 (2+1/3) |
| # Note that without the parens this becomes (1 4/3 5/3 2)+1/3 |
| 1 4/3 5/3 2+1/3 |
| # Vectors of characters print without quotes or spaces. |
| 'h' 'e' 'l' 'l' 'o' |
| # This is a nicer way to write 'h' 'e' 'l' 'l' 'o'. It means the same. |
| 'hello' |
| # Arithmetic works elementwise on vectors. |
| 1 2 3 + 4 5 6 |
| # Arithmetic between scalar and vector also works, either way. |
| 23 + 1 2 3 |
| 1 2 3 + 23 # Note the grouping: vector is a single value. |
| # More fun with scalar and vector. |
| 1 << 1 2 3 4 5 |
| (1 << 1 2 3 4 5) == (2 ** 1 2 3 4 5) # Note: true is 1, false is 0. |
| # iota is an "index generator": It counts from 1. |
| iota 10 |
| 2 ** iota 5 |
| (1 << iota 100) == 2 ** iota 100 |
| 2 ** -1 + iota 32 # Again, see how the precedence rules work. |
| # The take operator removes n items from the beginning of the vector. |
| 3 take iota 10 |
| -3 take iota 10 # Negative n takes from the end. |
| # Drop is the other half: it drops n from the vector. |
| 3 drop iota 10 |
| -3 drop iota 10 # Negative n drops from the end. |
| 6 drop 'hello world' |
| # Reduction |
| iota 15 |
| # Add them up: |
| 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 |
| # Automate this by reducing + over the vector, like this: |
| +/iota 15 |
| # We can reduce using any binary operator. This is factorial: |
| 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10 |
| */iota 10 |
| */iota 100 |
| # Type this: */iota 10000 |
| # That printed using floating-point notation for manageability but it is still an integer inside. |
| # max and min are binary operators that do the obvious. (Use semicolons to separate expressions.) |
| 3 max 7; 'is max and'; 3 min 7; 'is min' |
| # Like all binary arithmetic operators, max applies elementwise. |
| 2 3 4 max 4 3 2 |
| # Reduce using max to find maximum element in vector. |
| max/2 34 42 233 2 2 521 14 1 4 1 55 133 |
| # Ivy allows multidimensional arrays. The binary shape operator, rho, builds them. |
| # Dimension (which may be a vector) on the left, data on the right. |
| 5 rho 1 |
| 5 5 rho 1 |
| 5 5 rho 25 |
| 5 5 rho iota 25 |
| 3 5 5 rho iota 125 |
| # Unary rho tells us the shape of an item. |
| x = 3 5 rho iota 15; x |
| rho x |
| x = 3 5 5 rho iota 75; x |
| rho x |
| # Arithmetic on matrices works as you would expect by now. |
| x/2 |
| x**2 |
| x**3 |
| x**10 |
| # Inner product is written with a . between the operators. |
| # This gives dot product: multiply corresponding elements and add the result. |
| 1 2 3 4 +.* 2 3 4 5 |
| # Any operator works. How many items are the same? |
| (1 2 3) +.== (1 3 3) |
| # How many differ? |
| (1 2 3) +.!= (1 3 3) |
| # Outer product generates a matrix of all combinations applying the binary operator. |
| (iota 5) o.* -1 + iota 5 |
| # That's a letter 'o', dot, star. |
| # Any operator works; here is how to make an identity matrix. |
| x = iota 5; x o.== x |
| # Assignment is an operator, so you can save an intermediate expression. |
| x o.== x = iota 5 |
| # Random numbers: Use a unary ? to roll an n-sided die from 1 to n. |
| ?100 |
| ?100 |
| ?20 rho 6 # 20 rolls of a 6-sided die. |
| x = ?20 rho 6 # Remember one set of rolls. |
| x |
| # Indexing is easy. |
| x[1] |
| x[1 19 3] # You can index with a vector. |
| # The up and down operators generate index vectors that would sort the input. |
| up x |
| x[up x] |
| x[down x] |
| 'hello world'[up 'hello world'] |
| 'hello world'[down 'hello world'] |
| # More rolls of a die. |
| ?10 rho 6 |
| # Remember a set of rolls. |
| x = ?10 rho 6; x |
| # The outer product of == and the integers puts 1 in each row where that value appeared. |
| # Compare the last row of the next result to the 6s in x. |
| (iota 6) o.== x |
| # Count the number of times each value appears by reducing the matrix horizontally. |
| +/(iota 6) o.== x |
| # Do it for a much larger set of rolls: is the die fair? |
| +/(iota 6) o.== ?60000 rho 6 |
| # Remember that ivy is a big number calculator. |
| */iota 100 |
| 2**64 |
| 2**iota 64 |
| -1+2**63 |
| # Settings are made and queried with a leading right paren. )help helps with settings and other commands. |
| )help |
| # Use )base to switch input and output to base 16. |
| )base 16 |
| )base # The input and output for settings is always base 10. |
| # _ is a variable that holds the most recently evaluated expression. It remembers our 63-bit number. |
| _ |
| 1<<iota 10 # 16 powers of two, base 16. |
| (2**40)-1 # The largest 64-bit number base 16. |
| )obase 10 # Output base 10, input base still 16. |
| )base |
| # The largest 63-bit number base 10. |
| -1+2**40 # The largest 64-bit number base 10. |
| -1+2**3F # The largest 63-bit number base 10. |
| # Go back to base 10 input and output. |
| )base 10 |
| # Rationals can be very big too. |
| (2**1e3)/(3**1e2) |
| # Such output can be unwieldy. Change the output format using a Printf string. |
| )format '%.12g' |
| _ |
| # We need more precision. |
| )format "%.100g" # Double quotes work too; there's no difference. |
| _ |
| )format '%#x' |
| _ |
| )format '%.12g' # A nice format, easily available by running ivy -g. |
| _ |
| (3 4 rho iota 12)/4 |
| # Irrational functions cannot be represented precisely by rational numbers. |
| # Ivy stores irrational results in high-precision (default 256-bit) floating point numbers. |
| sqrt 2 |
| # pi and e are built-in, high-precision constants. |
| pi |
| e |
| )format "%.100g" |
| pi |
| )format '%.12g' |
| pi |
| # Exponentials and logarithms. |
| 2**1/2 # Note: Non-integral exponent generates irrational result. |
| e**1e6 |
| log e**1e6 |
| log e**1e8 |
| log 1e1000000 # Yes, that is 10 to the millionth power. |
| # Transcendentals. (The low bit isn't always right...) |
| sin pi/2 |
| cos .25*pi * -1 + iota 9 |
| log iota 6 |
| # Successive approximations to e. (We force the calculation to use float using the "float" unary operator. Why?) |
| (float 1+10**-iota 9) ** 10**iota 9 |
| # Default precision is 256 bits of mantissa. We can go up to 10000. |
| )prec 3350 # Units are bits, not digits. 2 log 10 == 3.321. Add a few more bits for floating point errors. |
| e |
| )format '%.1000g' # Units are digits. (Sorry for the inconsistency.) |
| e |
| pi |
| sqrt 2 |
| e**1e6 |
| log e**1e6 |
| (2**1e3)/(3**1e2) |
| # User-defined operators are declared as unary or binary (or both). This one computes the (unary) average. |
| op avg x = (+/x)/rho x |
| avg iota 100 |
| # Here is a binary operator. |
| op n largest x = n take x[down x] |
| 3 largest ? 100 rho 1000 |
| 4 largest 'hello world' |
| # Population count. Use encode to turn the value into a string of bits. Use log to decide how many. |
| op a base b = ((ceil b log a) rho b) encode a |
| 7 base 2 |
| op popcount n = +/n base 2 |
| popcount 7 |
| popcount 1e6 |
| popcount 1e100 |
| # Here is one to sum the digits. The unary operator text turns its argument into text, like sprintf. |
| op sumdigits x = t = text x; +/(code (t in '0123456789') sel t) - code '0' |
| # Break it down: The sel operator selects from the right based on the non-zero elements in the left. |
| # The in operator generates a selector by choosing only the bytes that are ASCII digits. |
| sumdigits 99 |
| sumdigits iota 10 |
| sumdigits '23 skidoo' # Note: It counts only the digits. |
| # The binary text operator takes a format string (% optional) on the left and formats the value. |
| '%x' text 1234 |
| # We can use this for another version of popcount: %b is binary. |
| op popcount n = +/'1' == '%b' text n |
| popcount 7 |
| popcount 1e6 |
| popcount 1e100 |
| # A classic (expensive!) algorithm to count primes. |
| op primes N = (not T in T o.* T) sel T = 1 drop iota N |
| # The assignment to T gives 2..N. We use outer product to build an array of all products. |
| # Then we find all elements of T that appear in the product matrix, invert that, and select from the original. |
| primes 100 |
| # A final trick. |
| # The binary ? operator "deals": x?y selects at random x distinct integers from 1..y inclusive. |
| 5?10 |
| # We can use this to shuffle a deck of cards. The suits are ♠♡♣♢, the values |
| # A234567890JQK (using 0 for 10, for simplicity). |
| # Create the deck using outer product with the ravel operator: |
| "A234567890JQK" o., "♠♡♣♢" |
| # To shuffle it, ravel into into a vector and index that by 1 through 52, shuffled. |
| (, "A234567890JQK" o., "♠♡♣♢")[52?52] |
| # There is no looping construct in ivy, but there is a conditional evaluator. |
| # Within a user-defined operator, one can write a condition expression |
| # using a binary operator, ":". If the left-hand operand is true (integer non-zero), |
| # the user-defined operator will return the right-hand operand as its |
| # result; otherwise execution continues. |
| op a gcd b = a == b: a; a > b: b gcd a-b; a gcd b-a |
| 1562 gcd !11 |
| # That's it! Have fun. |
| # For more information visit https://pkg.go.dev/robpike.io/ivy |