mirror of
https://github.com/lcn2/calc.git
synced 2025-08-19 01:13:27 +03:00
Compare commits
15 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
80e841eded | ||
|
3f78fc20d7 | ||
|
c26460b255 | ||
|
3ec7b39366 | ||
|
49c599aec9 | ||
|
a582511002 | ||
|
e05d904821 | ||
|
ccd579ecda | ||
|
15be1dec4d | ||
|
f34c659877 | ||
|
2ad27e7909 | ||
|
a4d3c8ff9d | ||
|
bd64a6cc36 | ||
|
e2b2976d18 | ||
|
3ea51ea937 |
53
CHANGES
53
CHANGES
@@ -1,4 +1,45 @@
|
||||
The following are the changes from calc version 2.14.1.5 to date:
|
||||
The following are the changes from calc version 2.14.2.1 to date:
|
||||
|
||||
Added cal/fnv_tool.cal, a calc resource file defining:
|
||||
|
||||
find_fnv_prime(bits)
|
||||
deprecated_fnv0(bits,fnv_prime,string)
|
||||
fnv_offset_basis(bits,fnv_prime)
|
||||
fnv1a_style_hash(bits,fnv_prime,prev_hash,string)
|
||||
|
||||
Fixed sorted order of cal/README.
|
||||
|
||||
|
||||
The following are the changes from calc version 2.14.2.0 to 2.14.2.0:
|
||||
|
||||
Ported calc to the s390x IBM Mainframe running RHEL9.1.
|
||||
|
||||
Added cal/splitbits.cal:
|
||||
|
||||
splitbits(x, b)
|
||||
|
||||
Given an integer x, split the value into a list of integers,
|
||||
each of which is at most b bits long.
|
||||
|
||||
The value b must be an integer > 0.
|
||||
|
||||
The number of elements in the returned list is:
|
||||
|
||||
ceil((highbit(x) + 1) / b)
|
||||
|
||||
If x == 0, then a list of 1 element containing 0 is returned.
|
||||
|
||||
If x < 0, then the two's compliment of abs(x) is returned.
|
||||
Even though calc represents negative integers as positive values
|
||||
with sign bit, the bits returned by this function are as if
|
||||
the integer converted as if the integer was a two's compliment value.
|
||||
|
||||
See also the help command:
|
||||
|
||||
; help resource
|
||||
|
||||
|
||||
The following are the changes from calc version 2.14.1.5 to 2.14.1.6:
|
||||
|
||||
Fixed version numbers in two cases in CHANGES that referred
|
||||
to the 2.14.2.x instead of 2.14.1.x.
|
||||
@@ -14,6 +55,16 @@ The following are the changes from calc version 2.14.1.5 to date:
|
||||
|
||||
Fix cases of spaces before tabs in Makefile and Makefile.simple.
|
||||
|
||||
Fixed obsolete references to the atoz() in LIBRARY to use the
|
||||
correct internal function name of str2z().
|
||||
|
||||
Fixed obsolete references to the atoq() in LIBRARY to use the
|
||||
correct internal function name of str2q().
|
||||
|
||||
Document in help/unexpected that * operator has has a higher
|
||||
precedence than << in calc, which differs from C. Thanks
|
||||
goes to GitHub user @inguin for pointing put this difference.
|
||||
|
||||
|
||||
The following are the changes from calc version 2.14.1.3 to 2.14.1.4:
|
||||
|
||||
|
16
LIBRARY
16
LIBRARY
@@ -344,7 +344,7 @@ values of 0 and 1 are so common that special checks are made for them.
|
||||
|
||||
For initial values besides 0 or 1, you need to call itoz to convert a long
|
||||
value into a ZVALUE, as shown in the above example. Or alternatively,
|
||||
for larger numbers you can use the atoz routine to convert a string which
|
||||
for larger numbers you can use the str2z routine to convert a string which
|
||||
represents a number into a ZVALUE. The string can be in decimal, octal,
|
||||
hex, or binary according to the leading digits.
|
||||
|
||||
@@ -357,7 +357,7 @@ over a long sequence of operations.
|
||||
ZVALUE z1, z2, z3;
|
||||
|
||||
z1 = _one_;
|
||||
atoz("12345678987654321", &z2);
|
||||
str2z("12345678987654321", &z2);
|
||||
zadd(z1, z2, &z3);
|
||||
zfree(z1);
|
||||
zfree(z2);
|
||||
@@ -446,10 +446,10 @@ to free them first. The following illustrates this:
|
||||
itoz(55L, &q->num);
|
||||
|
||||
A better way to create NUMBERs with particular values is to use the itoq,
|
||||
iitoq, or atoq functions. Using itoq makes a long value into a NUMBER,
|
||||
iitoq, or str2q functions. Using itoq makes a long value into a NUMBER,
|
||||
using iitoq makes a pair of longs into the numerator and denominator of a
|
||||
NUMBER (reducing them first if needed), and atoq converts a string representing
|
||||
a number into the corresponding NUMBER. The atoq function accepts input in
|
||||
NUMBER (reducing them first if needed), and str2q converts a string representing
|
||||
a number into the corresponding NUMBER. The str2q function accepts input in
|
||||
integral, fractional, real, or exponential formats. Examples of allocating
|
||||
numbers are:
|
||||
|
||||
@@ -457,7 +457,7 @@ numbers are:
|
||||
|
||||
q1 = itoq(66L);
|
||||
q2 = iitoq(2L, 3L);
|
||||
q3 = atoq("456.78");
|
||||
q3 = str2q("456.78");
|
||||
|
||||
Also unlike ZVALUEs, NUMBERs are quickly copied. This is because they contain
|
||||
a link count, which is the number of pointers there are to the NUMBER. The
|
||||
@@ -504,8 +504,8 @@ For example, to calculate sin(0.5) to 100 decimal places, you could do:
|
||||
|
||||
NUMBER *q, *ans, *epsilon;
|
||||
|
||||
q = atoq("0.5");
|
||||
epsilon = atoq("1e-100");
|
||||
q = str2q("0.5");
|
||||
epsilon = str2q("1e-100");
|
||||
ans = qsin(q, epsilon);
|
||||
|
||||
There are many convenience macros similar to the ones for ZVALUEs which can
|
||||
|
7
Makefile
7
Makefile
@@ -1381,7 +1381,7 @@ EXT=
|
||||
|
||||
# The default calc versions
|
||||
#
|
||||
VERSION= 2.14.1.5
|
||||
VERSION= 2.14.2.1
|
||||
|
||||
# Names of shared libraries with versions
|
||||
#
|
||||
@@ -6415,7 +6415,9 @@ file.o: strl.h
|
||||
file.o: value.h
|
||||
file.o: zmath.h
|
||||
fposval.o: alloc.h
|
||||
fposval.o: attribute.h
|
||||
fposval.o: banned.h
|
||||
fposval.o: byteswap.h
|
||||
fposval.o: decl.h
|
||||
fposval.o: endian_calc.h
|
||||
fposval.o: fposval.c
|
||||
@@ -6427,8 +6429,11 @@ fposval.o: have_memmv.h
|
||||
fposval.o: have_newstr.h
|
||||
fposval.o: have_offscl.h
|
||||
fposval.o: have_posscl.h
|
||||
fposval.o: have_stdlib.h
|
||||
fposval.o: have_string.h
|
||||
fposval.o: have_unused.h
|
||||
fposval.o: longbits.h
|
||||
fposval.o: zmath.h
|
||||
func.o: alloc.h
|
||||
func.o: attribute.h
|
||||
func.o: banned.h
|
||||
|
@@ -1239,7 +1239,7 @@ EXT=
|
||||
|
||||
# The default calc versions
|
||||
#
|
||||
VERSION= 2.14.1.5
|
||||
VERSION= 2.14.2.1
|
||||
|
||||
# Names of shared libraries with versions
|
||||
#
|
||||
@@ -5699,7 +5699,9 @@ file.o: strl.h
|
||||
file.o: value.h
|
||||
file.o: zmath.h
|
||||
fposval.o: alloc.h
|
||||
fposval.o: attribute.h
|
||||
fposval.o: banned.h
|
||||
fposval.o: byteswap.h
|
||||
fposval.o: decl.h
|
||||
fposval.o: endian_calc.h
|
||||
fposval.o: fposval.c
|
||||
@@ -5711,8 +5713,11 @@ fposval.o: have_memmv.h
|
||||
fposval.o: have_newstr.h
|
||||
fposval.o: have_offscl.h
|
||||
fposval.o: have_posscl.h
|
||||
fposval.o: have_stdlib.h
|
||||
fposval.o: have_string.h
|
||||
fposval.o: have_unused.h
|
||||
fposval.o: longbits.h
|
||||
fposval.o: zmath.h
|
||||
func.o: alloc.h
|
||||
func.o: attribute.h
|
||||
func.o: banned.h
|
||||
|
22
README.md
22
README.md
@@ -1,3 +1,25 @@
|
||||
# TL;DR Try calc
|
||||
|
||||
## TL;DR Install calc
|
||||
|
||||
```
|
||||
misc linux: sudo yum install calc
|
||||
on Debian: sudo apt install calc
|
||||
on RHEL: sudo dnf install calc
|
||||
on Ubuntu: sudo apt install calc
|
||||
via Termux: apt install calc
|
||||
via src: sudo make clobber all chk instsll
|
||||
```
|
||||
|
||||
## TL;DR Run calc
|
||||
|
||||
```
|
||||
misc shell: calc
|
||||
via bash: calc
|
||||
via misc app: launch calc via Termux
|
||||
via zsh: calc
|
||||
```
|
||||
|
||||
# What is calc?
|
||||
|
||||
Calc is an interactive calculator which provides for easy large
|
||||
|
27
cal/Makefile
27
cal/Makefile
@@ -269,19 +269,20 @@ TRUE= true
|
||||
CALC_FILES= README alg_config.cal beer.cal bernoulli.cal \
|
||||
bernpoly.cal bigprime.cal bindings brentsolve.cal chi.cal chrem.cal \
|
||||
comma.cal constants.cal deg.cal dms.cal dotest.cal ellip.cal \
|
||||
factorial.cal factorial2.cal gvec.cal hello.cal hms.cal infinities.cal \
|
||||
intfile.cal intnum.cal lambertw.cal linear.cal lnseries.cal lucas.cal \
|
||||
lucas_chk.cal mersenne.cal mfactor.cal mod.cal natnumset.cal \
|
||||
palindrome.cal pell.cal pi.cal pix.cal pollard.cal poly.cal prompt.cal \
|
||||
psqrt.cal qtime.cal quat.cal randbitrun.cal randmprime.cal \
|
||||
randombitrun.cal randomrun.cal randrun.cal regress.cal repeat.cal \
|
||||
screen.cal seedrandom.cal set8700.cal set8700.line smallfactors.cal \
|
||||
solve.cal specialfunctions.cal statistics.cal strings.cal sumsq.cal \
|
||||
sumtimes.cal surd.cal test1700.cal test2300.cal test2600.cal \
|
||||
test2700.cal test3100.cal test3300.cal test3400.cal test3500.cal \
|
||||
test4000.cal test4100.cal test4600.cal test5100.cal test5200.cal \
|
||||
test8400.cal test8500.cal test8600.cal test8900.cal toomcook.cal \
|
||||
unitfrac.cal varargs.cal xx_print.cal zeta2.cal
|
||||
factorial.cal factorial2.cal fnv_tool.cal gvec.cal hello.cal hms.cal \
|
||||
infinities.cal intfile.cal intnum.cal lambertw.cal linear.cal \
|
||||
lnseries.cal lucas.cal lucas_chk.cal mersenne.cal mfactor.cal mod.cal \
|
||||
natnumset.cal palindrome.cal pell.cal pi.cal pix.cal pollard.cal \
|
||||
poly.cal prompt.cal psqrt.cal qtime.cal quat.cal randbitrun.cal \
|
||||
randmprime.cal randombitrun.cal randomrun.cal randrun.cal regress.cal \
|
||||
repeat.cal screen.cal seedrandom.cal set8700.cal set8700.line \
|
||||
smallfactors.cal solve.cal specialfunctions.cal splitbits.cal \
|
||||
statistics.cal strings.cal sumsq.cal sumtimes.cal surd.cal \
|
||||
test1700.cal test2300.cal test2600.cal test2700.cal test3100.cal \
|
||||
test3300.cal test3400.cal test3500.cal test4000.cal test4100.cal \
|
||||
test4600.cal test5100.cal test5200.cal test8400.cal test8500.cal \
|
||||
test8600.cal test8900.cal toomcook.cal unitfrac.cal varargs.cal \
|
||||
xx_print.cal zeta2.cal
|
||||
|
||||
# These calc files are now obsolete and are removed by the install rule.
|
||||
#
|
||||
|
120
cal/README
120
cal/README
@@ -388,6 +388,13 @@ dotest.cal
|
||||
dotest("set8700.line");
|
||||
|
||||
|
||||
ellip.cal
|
||||
|
||||
efactor(iN, ia, B, force)
|
||||
|
||||
Attempt to factor using the elliptic functions: y^2 = x^3 + a*x + b.
|
||||
|
||||
|
||||
factorial.cal
|
||||
|
||||
factorial(n)
|
||||
@@ -548,12 +555,65 @@ factorial2.cal
|
||||
for information on falling factorials.
|
||||
|
||||
|
||||
ellip.cal
|
||||
fnv_util.cal
|
||||
|
||||
efactor(iN, ia, B, force)
|
||||
Utility tools for FNV hash and "FNV-style" hash operations.
|
||||
|
||||
Attempt to factor using the elliptic functions: y^2 = x^3 + a*x + b.
|
||||
These functions, if given non-standard values, will produce bogus results.
|
||||
In some cases, such as specifying the number of bits in the hash,
|
||||
using a non-power of 2 bit will produce a result that may work,
|
||||
but the hash will be only an "FNV-style" hash and not a true FNV hash.
|
||||
|
||||
find_fnv_prime(bits)
|
||||
|
||||
If bits == null(), this function will attempt to prompt stdin
|
||||
for a value and provide commends on the value of bits.
|
||||
|
||||
given:
|
||||
bits number of bits in the hash, null() ==> prompt for value
|
||||
|
||||
returns:
|
||||
0 ==> no FNV prime found
|
||||
>0 ==> FNV prime
|
||||
|
||||
deprecated_fnv0(bits, fnv_prime, string)
|
||||
|
||||
If fnv_prime == null(), this function will try to compute the FNV prime
|
||||
for a hash of size bits.
|
||||
|
||||
given:
|
||||
bits number of bits in FNV hash
|
||||
fnv_prime FNV prime, null() ==> generate suitable FNV prime if possible
|
||||
string string to hash
|
||||
|
||||
returns:
|
||||
FNV-0 hash, for size bytes, of string
|
||||
|
||||
NOTE: This function does NOT attempt to determine that fnv_prime is prime.
|
||||
|
||||
fnv_offset_basis(bits, fnv_prime)
|
||||
|
||||
given:
|
||||
bits number of bits in FNV hash
|
||||
fnv_prime FNV prime, null() ==> generate suitable FNV prime if possible
|
||||
|
||||
returns:
|
||||
FNV offset basis for a hash size of bits and an FNV prime of fnv_prime
|
||||
|
||||
NOTE: This function does NOT attempt to determine that fnv_prime is prime.
|
||||
|
||||
fnv1a_style_hash(bits, fnv_prime, prev_hash, string)
|
||||
|
||||
given:
|
||||
bits number of bits in FNV hash
|
||||
fnv_prime FNV prime, null() ==> generate suitable FNV prime if possible
|
||||
prev_hash previous hash value, null() ==> generate FNV offset basis
|
||||
string string to hash
|
||||
|
||||
returns:
|
||||
"FNV-style" hash of bits
|
||||
|
||||
NOTE: This function does NOT attempt to determine that fnv_prime is prime.
|
||||
|
||||
gvec.cal
|
||||
|
||||
@@ -1433,6 +1493,60 @@ specialfunctions.cal
|
||||
on the script zeta2.cal.
|
||||
|
||||
|
||||
splitbits.cal
|
||||
|
||||
splitbits(x, b)
|
||||
|
||||
Given an integer x, split the value into a list of integers,
|
||||
each of which is at most b bits long.
|
||||
|
||||
The value b must be an integer > 0.
|
||||
|
||||
The number of elements in the returned list is:
|
||||
|
||||
ceil((highbit(x) + 1) / b)
|
||||
|
||||
If x == 0, then a list of 1 element containing 0 is returned.
|
||||
|
||||
If x < 0, then the two's compliment of abs(x) is returned.
|
||||
Even though calc represents negative integers as positive values
|
||||
with sign bit, the bits returned by this function are as if
|
||||
the integer converted as if the integer was a two's compliment
|
||||
value. For example:
|
||||
|
||||
; L = splitbits(-1, 8);
|
||||
; print L[[0]]
|
||||
255
|
||||
|
||||
; L = splitbits(-2, 8);
|
||||
; print L[[0]]
|
||||
254
|
||||
|
||||
; L = splitbits(-3, 8);
|
||||
; print L[[0]]
|
||||
253
|
||||
|
||||
The first element of the list contains the lowest order bits
|
||||
of x. The last element of the list contains the highest number
|
||||
bits of x.
|
||||
|
||||
For example:
|
||||
|
||||
; x = 2^23209-1
|
||||
; L = splitbits(x, 16);
|
||||
; print size(L), L[[0]]
|
||||
|
||||
; print istype(2, 3i), istype(2, "2"), istype(2, null())
|
||||
0 0 0
|
||||
|
||||
; mat a[2]
|
||||
; b = list(1,2,3)
|
||||
; c = assoc()
|
||||
; obj chongo {was, here} d;
|
||||
; print istype(a,b), istype(b,c), istype(c,d)
|
||||
0 0 0
|
||||
|
||||
|
||||
statistics.cal
|
||||
|
||||
gammaincoctave(z,a)
|
||||
|
474
cal/fnv_tool.cal
Normal file
474
cal/fnv_tool.cal
Normal file
@@ -0,0 +1,474 @@
|
||||
/*
|
||||
* fnv_util - utility tools for FNV hash and "FNV-style" hash operations
|
||||
*
|
||||
* This file provides the following functions:
|
||||
*
|
||||
* find_fnv_prime(bits)
|
||||
* deprecated_fnv0(bits, fnv_prime, string)
|
||||
* fnv_offset_basis(bits, fnv_prime)
|
||||
* fnv1a_style_hash(bits, fnv_prime, prev_hash, string)
|
||||
*
|
||||
* See the individual function for details on args and return value.
|
||||
*
|
||||
* If no args are given to find_fnv_prime() and stdin is associated
|
||||
* with a tty (i.e., an interactive terminal), then bits will be
|
||||
* prompted for and commentary will be printed to stdout as well.
|
||||
*
|
||||
* If fnv_prime == null(), then an attempt to compute the FNV prime
|
||||
* for a hash if size bits is attempted..
|
||||
*
|
||||
* If prev_hash == null(), then the FNV offset basis for
|
||||
* for a hash if size bits is computed.
|
||||
*
|
||||
* For more information on the FNV hash see:
|
||||
*
|
||||
* https://en.wikipedia.org/wiki/Fowler-Noll-Vo_hash_function
|
||||
* http://www.isthe.com/chongo/tech/comp/fnv/index.html
|
||||
*
|
||||
* IMPORTANT NOTE:
|
||||
*
|
||||
* These functions, if given non-standard values, will produce bogus results.
|
||||
* In some cases, such as specifying the number of bits in the hash,
|
||||
* using a non-power of 2 bit will produce a result that may work,
|
||||
* but the hash will be only an "FNV-style" hash and not a true FNV hash.
|
||||
*
|
||||
* We say "FNV-style" because the result hash is not a "true FNV-like" hash.
|
||||
*
|
||||
* Let integer n > 0 be the number if bits in the FNV hash. Then:
|
||||
*
|
||||
* t = floor((5+n)/12)
|
||||
*
|
||||
* The FNV prime, for the given n bits is the smallest prime of the form:
|
||||
*
|
||||
* p = 256^t + 2^8 + b
|
||||
*
|
||||
* such that:
|
||||
*
|
||||
* 0 < b < 2^8
|
||||
* The number of one-bits in b must be 4 or 5
|
||||
* p mod (2^40 - 2^24 - 1) > (2^24 + 2^8 + 2^7)
|
||||
*
|
||||
* If you force n to not be a power of 2, for example:
|
||||
*
|
||||
* n = 44
|
||||
*
|
||||
* you will find that the FNV prime for 44 bits is:
|
||||
*
|
||||
* p44 = 4294967597
|
||||
* = 0x10000012d
|
||||
* = 0b100000000000000000000000100101101
|
||||
* = 2^32 + 301 = 2^32 + 2^8 + 2^5 + 2^3 + 2^2 + 2^0
|
||||
*
|
||||
* However a hash size of 44 bits is not a true FNV hash, it is only a "FNV-style" hash.
|
||||
*
|
||||
* NOTE: We disallow n <= 31 because there are no FNV primes that small.
|
||||
*
|
||||
* NOTE: For n that is a power of 2 and n > 1024, you will find that
|
||||
* that FNV primes become so rare that that one may not find a suitable
|
||||
* FNV prime. For n = 2048, 4096, 8192, 16384, 32768, 65536, 131072
|
||||
* and 262144, there is NO suitable FNV prime.
|
||||
*
|
||||
* As for as hashing goes, large values of n, even if an
|
||||
* FNV hash may be found, are unlikely to be truly useful. :-)
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 2023 by Landon Curt Noll. All Rights Reserved.
|
||||
*
|
||||
* Permission to use, copy, modify, and distribute this software and
|
||||
* its documentation for any purpose and without fee is hereby granted,
|
||||
* provided that the above copyright, this permission notice and text
|
||||
* this comment, and the disclaimer below appear in all of the following:
|
||||
*
|
||||
* supporting documentation
|
||||
* source copies
|
||||
* source works derived from this source
|
||||
* binaries derived from this source or from derived source
|
||||
*
|
||||
* LANDON CURT NOLL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
|
||||
* INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO
|
||||
* EVENT SHALL LANDON CURT NOLL BE LIABLE FOR ANY SPECIAL, INDIRECT OR
|
||||
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
|
||||
* USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*
|
||||
* chongo (Landon Curt Noll, http://www.isthe.com/chongo/index.html) /\oo/\
|
||||
*
|
||||
* Share and enjoy! :-)
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* find_fnv_prime - try to find a FNV prime given the number of bits
|
||||
*
|
||||
* If bits == null(), this function will attempt to prompt stdin
|
||||
* for a value and provide commends on the value of bits.
|
||||
*
|
||||
* given:
|
||||
* bits number of bits in the hash, null() ==> prompt for value
|
||||
*
|
||||
* returns:
|
||||
* 0 ==> no FNV prime found
|
||||
* >0 ==> FNV prime
|
||||
*/
|
||||
define find_fnv_prime(bits)
|
||||
{
|
||||
local b; /* lower octet of the potential FNV prime: [1,255] */
|
||||
local p; /* value to test as an FNV prime */
|
||||
local t; /* power of 256 part of the FNV prime */
|
||||
local one_bits; /* number of 1 bits in b */
|
||||
local p_minus_b; /* potential FNV prime less b */
|
||||
local interactive; /* true ==> interactive mode and print commentary */
|
||||
|
||||
/*
|
||||
* case: no arg, prompt for bits and print commentary
|
||||
*/
|
||||
interactive = 0; /* assume non-interactive mode */
|
||||
if (isnull(bits)) {
|
||||
|
||||
/*
|
||||
* must be attached to an interactive terminal
|
||||
*/
|
||||
if (!isatty(files(0))) {
|
||||
print "# FATAL: stdin is not a tty: not attached to an interactive terminal";
|
||||
return 0;
|
||||
}
|
||||
interactive = 1; /* set interactive mode */
|
||||
|
||||
/*
|
||||
* prompt for the number of bits
|
||||
*/
|
||||
do {
|
||||
local strscanf_ret; /* return from strscanf_ret */
|
||||
local input; /* value read after prompt */
|
||||
|
||||
/*
|
||||
* prompt and obtain the input
|
||||
*/
|
||||
input = prompt("Enter hash size in bits: ");
|
||||
strscanf_ret = strscanf(input, "%i", bits);
|
||||
print "input =", input;
|
||||
print "bits =", bits;
|
||||
if (!isint(bits) || bits <= 0) {
|
||||
print;
|
||||
print "# NOTE: must enter a integer > 0, try again";
|
||||
print;
|
||||
}
|
||||
} while (!isint(bits) || bits <= 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* firewall - bits must be non-negative integer
|
||||
*/
|
||||
if (!isint(bits) || bits < 0) {
|
||||
if (interactive) {
|
||||
print "# FATAL: bits must be non-negative integer";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* provide commentary on the choice of bits if we are interactive
|
||||
*/
|
||||
if (interactive) {
|
||||
if (popcnt(bits) == 1) {
|
||||
if (bits > 1024) {
|
||||
print "# WARNING: FNV primes for powers of 2 > 1024 are extremely rare.";
|
||||
print "# WARNING: There are no FNV primes for 2048, 4096, 8192, 16384, 327678, 65536, 131072, nor 262144.";
|
||||
}
|
||||
print "# NOTE: bits a power of 2 and bits >= 32: bits is suitable for a true FNV hash";
|
||||
print "n =", bits;
|
||||
} else {
|
||||
if (bits < 32) {
|
||||
print "# WARNING: bits < 32 is not recommended because there isn't enough bits to be worth hashing";
|
||||
}
|
||||
print "# WARNING: because bits is not a power of 2, we can only form an \"FNV-style hash\": not a true FNV hash.";
|
||||
print "# WARNING: A \"FNV-style hash\" may not have the desired hash properties of a true FNV hash.";
|
||||
print "n =", bits;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* search setup
|
||||
*/
|
||||
t = floor((5+bits)/12);
|
||||
p_minus_b = 256^t + 2^8;
|
||||
|
||||
/*
|
||||
* search for a b that forms a suitable FNV prime
|
||||
*/
|
||||
for (b=1; b < 256; ++b) {
|
||||
|
||||
/*
|
||||
* reject b unless the of one-bits in bottom octet of p is 4 or 5
|
||||
*/
|
||||
one_bits = popcnt(b);
|
||||
if (one_bits != 4 && one_bits != 5) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* reject potential p value that is not prime
|
||||
*/
|
||||
p = p_minus_b + b;
|
||||
if (ptest(p) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* accept p if p mod (2^40 - 2^24 - 1) > (2^24 + 2^8 + 2^7)
|
||||
*/
|
||||
if ((p % (2^40 - 2^24 - 1)) > (2^24 + 2^8 + 2^7)) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* case: did not find an FNV prime
|
||||
*/
|
||||
if (b >= 256) {
|
||||
|
||||
/*
|
||||
* examine results if interactive
|
||||
*/
|
||||
if (interactive) {
|
||||
print "# FATAL: There is no a suitable FNV prime for bits =", bits;
|
||||
quit "find_fnv_prime: FATAL: FNV prime search failed";
|
||||
}
|
||||
|
||||
/*
|
||||
* return 0 to indicate no FNV prime found
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* provide FNV commentary if interactive
|
||||
*/
|
||||
if (interactive) {
|
||||
print "t =", t;
|
||||
print "b =", b;
|
||||
print "# NOTE: p = 256^":t, "+ 2^8 +", b;
|
||||
print;
|
||||
print "p =", p;
|
||||
}
|
||||
|
||||
/*
|
||||
* return FNV prime
|
||||
*/
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* deprecated_fnv0 - FNV-0 hash that should only be used to generate an FNV offset basis
|
||||
*
|
||||
* If fnv_prime == null(), this function will try to compute the FNV prime
|
||||
* for a hash of size bits.
|
||||
*
|
||||
* given:
|
||||
* bits number of bits in FNV hash
|
||||
* fnv_prime FNV prime, null() ==> generate suitable FNV prime if possible
|
||||
* string string to hash
|
||||
*
|
||||
* returns:
|
||||
* FNV-0 hash, for size bytes, of string
|
||||
*
|
||||
* NOTE: This function does NOT attempt to determine that fnv_prime is prime.
|
||||
*/
|
||||
define deprecated_fnv0(bits, fnv_prime, string)
|
||||
{
|
||||
local hash; /* FNV hash value */
|
||||
local len; /* length of string */
|
||||
local base; /* base of FNV hash: 2^bits */
|
||||
local i;
|
||||
|
||||
/*
|
||||
* firewall
|
||||
*/
|
||||
if (!isint(bits) || bits <= 0) {
|
||||
quit "deprecated_fnv0: FATAL: bits arg must be an integer > 0";
|
||||
}
|
||||
if (!isstr(string)) {
|
||||
quit "deprecated_fnv0: FATAL: string arg must be a string";
|
||||
}
|
||||
|
||||
/*
|
||||
* fnv_prime == null() means to try and generate the FNV prime
|
||||
*/
|
||||
if (isnull(fnv_prime)) {
|
||||
/* try to generate an FNV prime */
|
||||
fnv_prime = find_fnv_prime(bits);
|
||||
if (fnv_prime == 0) {
|
||||
quit "deprecated_fnv0: FATAL: no FNV prime exists for the given hash size in bits";
|
||||
}
|
||||
}
|
||||
if (!isint(fnv_prime) || fnv_prime <= 0) {
|
||||
quit "deprecated_fnv0: FATAL: fnv_prime arg must be an integer > 0 and should be prime";
|
||||
}
|
||||
|
||||
/*
|
||||
* FNV-0 hash each character
|
||||
*/
|
||||
len = strlen(string);
|
||||
base = 2^bits;
|
||||
hash = 0;
|
||||
for (i=0; i < len; ++i) {
|
||||
hash = xor((hash * fnv_prime) % base, ord(string[i]));
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fnv_offset_basis - generate and FNV offset basis
|
||||
*
|
||||
* given:
|
||||
* bits number of bits in FNV hash
|
||||
* fnv_prime FNV prime, null() ==> generate suitable FNV prime if possible
|
||||
*
|
||||
* returns:
|
||||
* FNV offset basis for a hash size of bits and an FNV prime of fnv_prime
|
||||
*
|
||||
* NOTE: This function does NOT attempt to determine that fnv_prime is prime.
|
||||
*/
|
||||
define
|
||||
fnv_offset_basis(bits, fnv_prime)
|
||||
{
|
||||
local fnv0_hash = 0; /* FNV-0 hash value */
|
||||
|
||||
/* string to generate a FNV offset basis - do not change this value */
|
||||
static chongo_was_here = "chongo <Landon Curt Noll> /\\../\\";
|
||||
|
||||
/*
|
||||
* firewall
|
||||
*/
|
||||
if (!isint(bits) || bits <= 0) {
|
||||
quit "fnv_offset_basis: FATAL: bits arg must be an integer > 0";
|
||||
}
|
||||
|
||||
/*
|
||||
* fnv_prime == null() means to try and generate the FNV prime
|
||||
*/
|
||||
if (isnull(fnv_prime)) {
|
||||
/* try to generate an FNV prime */
|
||||
fnv_prime = find_fnv_prime(bits);
|
||||
if (fnv_prime == 0) {
|
||||
quit "fnv_offset_basis: FATAL: no FNV prime exists for the given hash size in bits";
|
||||
}
|
||||
}
|
||||
if (!isint(fnv_prime) || fnv_prime <= 0) {
|
||||
quit "fnv_offset_basis: FATAL: fnv_prime arg must be an integer > 0 and should be prime";
|
||||
}
|
||||
|
||||
/*
|
||||
* return the FNV-0 hash of fnv_offset_basis as the FNV offset basis
|
||||
*/
|
||||
fnv0_hash = deprecated_fnv0(bits, fnv_prime, chongo_was_here);
|
||||
return fnv0_hash;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* fnv_style_hash - compute an "FNV-1a-style" hash
|
||||
*
|
||||
* These functions, if given non-standard values, will produce bogus results.
|
||||
* To produce a true FNV-1a hash:
|
||||
*
|
||||
* bits must be a power of 2
|
||||
* 32 <= bits
|
||||
* fnv_prime == find_fnv_prime(bits) OR fnv_prime == null()
|
||||
* prev_hash == previous FNV hash OR prev_hash == null()
|
||||
*
|
||||
* If fnv_prime == null(), this function will try to compute the FNV prime
|
||||
* for a hash of size bits.
|
||||
*
|
||||
* If prev_hash == null(), this function will try to compute the FNV offset basis
|
||||
* for a hash of size bits.
|
||||
*
|
||||
* One may chain "FNV-style" hashes by replacing the offset_basis with
|
||||
* the hash state of the previous hash. For the first hash:
|
||||
*
|
||||
* fnv_prime = find_fnv_prime(bits)
|
||||
* hash_val = fnv_style_hash(bits, fnv_prime, null(), string_a);
|
||||
*
|
||||
* then:
|
||||
*
|
||||
* hash_val = fnv_style_hash(bits, fnv_prime, hash_val, string_b);
|
||||
*
|
||||
* This will produce the same as the string_a concatenated with string_b:
|
||||
*
|
||||
* hash_val = fnv_style_hash(bits, null(), null(), string_a + string_b);
|
||||
*
|
||||
* NOTE: Because string_a and string_b are strings, the expression:
|
||||
*
|
||||
* string_a + string_b
|
||||
*
|
||||
* is string_a concatenated with string_b.
|
||||
*
|
||||
* given:
|
||||
* bits number of bits in FNV hash
|
||||
* fnv_prime FNV prime, null() ==> generate suitable FNV prime if possible
|
||||
* prev_hash previous hash value, null() ==> generate FNV offset basis
|
||||
* string string to hash
|
||||
*
|
||||
* returns:
|
||||
* "FNV-style" hash of bits
|
||||
*
|
||||
* NOTE: This function does NOT attempt to determine that fnv_prime is prime.
|
||||
*/
|
||||
define
|
||||
fnv1a_style_hash(bits, fnv_prime, prev_hash, string)
|
||||
{
|
||||
local hash = 0; /* FNV hash value */
|
||||
local len; /* length of string */
|
||||
local base; /* base of FNV hash: 2^bits */
|
||||
local i;
|
||||
|
||||
/*
|
||||
* firewall
|
||||
*/
|
||||
if (!isint(bits) || bits <= 0) {
|
||||
quit "fnv1a_style_hash: FATAL: bits arg must be an integer > 0";
|
||||
}
|
||||
if (!isstr(string)) {
|
||||
quit "fnv1a_style_hash: FATAL: string arg must be a string";
|
||||
}
|
||||
|
||||
/*
|
||||
* fnv_prime == null() means to try and generate the FNV prime
|
||||
*/
|
||||
if (isnull(fnv_prime)) {
|
||||
/* try to generate an FNV prime */
|
||||
fnv_prime = find_fnv_prime(bits);
|
||||
if (fnv_prime == 0) {
|
||||
quit "fnv1a_style_hash: FATAL: no FNV prime exists for the given hash size in bits";
|
||||
}
|
||||
}
|
||||
if (!isint(fnv_prime) || fnv_prime <= 0) {
|
||||
quit "fnv1a_style_hash: FATAL: fnv_prime arg must be an integer > 0 and should be prime";
|
||||
}
|
||||
|
||||
/*
|
||||
* prev_hash == null() means to generate the FNV offset basis
|
||||
*/
|
||||
if (isnull(prev_hash)) {
|
||||
|
||||
/* generate the FNV offset basis for a hash of size bits */
|
||||
prev_hash = fnv_offset_basis(bits, fnv_prime);
|
||||
}
|
||||
if (!isint(prev_hash) || prev_hash < 0) {
|
||||
quit "fnv1a_style_hash: FATAL: prev_hash arg must be an integer => 0";
|
||||
}
|
||||
|
||||
/*
|
||||
* FNV-1a hash each character
|
||||
*/
|
||||
len = strlen(string);
|
||||
base = 2^bits;
|
||||
hash = prev_hash;
|
||||
for (i=0; i < len; ++i) {
|
||||
hash = xor((hash * fnv_prime) % base, ord(string[i]));
|
||||
}
|
||||
return hash;
|
||||
}
|
83
cal/splitbits.cal
Normal file
83
cal/splitbits.cal
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* splitbits - split an integer into list on bit boundardies of a fixed size
|
||||
*
|
||||
* Copyright (C) 2018,2023 Landon Curt Noll
|
||||
*
|
||||
* Calc is open software; you can redistribute it and/or modify it under
|
||||
* the terms of the version 2.1 of the GNU Lesser General Public License
|
||||
* as published by the Free Software Foundation.
|
||||
*
|
||||
* Calc is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
|
||||
* Public License for more details.
|
||||
*
|
||||
* A copy of version 2.1 of the GNU Lesser General Public License is
|
||||
* distributed with calc under the filename COPYING-LGPL. You should have
|
||||
* received a copy with calc; if not, write to Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*
|
||||
* Under source code control: 2006/06/07 14:10:11
|
||||
* File existed as early as: 2006
|
||||
*
|
||||
* chongo <was here> /\oo/\ http://www.isthe.com/chongo/
|
||||
* Share and enjoy! :-) http://www.isthe.com/chongo/tech/comp/calc/
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* setup splitbits errors
|
||||
*/
|
||||
static E_SPLITBITS_1, E_SPLITBITS_2, E_SPLITBITS_3;
|
||||
if (! iserror(E_SPLITBITS_1)) E_SPLITBITS_1 = newerror("1st argument to splitbits must be an integer");
|
||||
if (! iserror(E_SPLITBITS_2)) E_SPLITBITS_2 = newerror("2nd argument to splitbits must be an integer");
|
||||
if (! iserror(E_SPLITBITS_3)) E_SPLITBITS_3 = newerror("2nd argument must be an integer > 0");
|
||||
|
||||
|
||||
/*
|
||||
* define splitbits function
|
||||
*/
|
||||
define splitbits(x, b)
|
||||
{
|
||||
local ret; /* list to return */
|
||||
local mask; /* 2^b-1 */
|
||||
local x_is_reg = 0; /* true if x < 0 */
|
||||
|
||||
/* firewall */
|
||||
if (! isint(x)) {
|
||||
return error(E_SPLITBITS_1);
|
||||
}
|
||||
if (! isint(b)) {
|
||||
return error(E_SPLITBITS_2);
|
||||
}
|
||||
if (b <= 0) {
|
||||
return error(E_SPLITBITS_3);
|
||||
}
|
||||
|
||||
/* special case: x == 0 */
|
||||
if (x == 0) {
|
||||
return list(0);
|
||||
}
|
||||
|
||||
/* setup for splitting x */
|
||||
ret = list();
|
||||
mask = 2^b-1;
|
||||
if (x < 0) {
|
||||
x_is_reg = 1;
|
||||
x = abs(x);
|
||||
}
|
||||
|
||||
/* split x */
|
||||
while (x > 0) {
|
||||
printf("%d %x\n", size(ret), x);
|
||||
if (x_is_reg) {
|
||||
append(ret, xor(x & mask, mask));
|
||||
} else {
|
||||
append(ret, x & mask);
|
||||
}
|
||||
x >>= b;
|
||||
}
|
||||
|
||||
/* return list */
|
||||
return ret;
|
||||
}
|
@@ -475,7 +475,7 @@ EXT=
|
||||
|
||||
# The default calc versions
|
||||
#
|
||||
VERSION= 2.14.1.5
|
||||
VERSION= 2.14.2.1
|
||||
|
||||
# Names of shared libraries with versions
|
||||
#
|
||||
|
@@ -445,7 +445,7 @@ EXT=
|
||||
|
||||
# The default calc versions
|
||||
#
|
||||
VERSION= 2.14.1.5
|
||||
VERSION= 2.14.2.1
|
||||
|
||||
# Names of shared libraries with versions
|
||||
#
|
||||
|
@@ -1,7 +1,7 @@
|
||||
/*
|
||||
* fposval - Determine information about the file position type
|
||||
*
|
||||
* Copyright (C) 1999,2021 Landon Curt Noll
|
||||
* Copyright (C) 1999,2021,2023 Landon Curt Noll
|
||||
*
|
||||
* Calc is open software; you can redistribute it and/or modify it under
|
||||
* the terms of the version 2.1 of the GNU Lesser General Public License
|
||||
@@ -72,6 +72,7 @@
|
||||
#include "alloc.h"
|
||||
#include "have_unused.h"
|
||||
#include "have_memmv.h"
|
||||
#include "zmath.h"
|
||||
|
||||
|
||||
#include "banned.h" /* include after system header <> includes */
|
||||
|
@@ -556,8 +556,14 @@ Unexpected
|
||||
; print sin(d2r(30))
|
||||
0.5
|
||||
|
||||
* operator has has a higher precedence than <<
|
||||
==============================================
|
||||
|
||||
## Copyright (C) 1999-2007,2014,2017,2021 Landon Curt Noll
|
||||
The * operator has has a higher precedence than <<, which differs from the C language.
|
||||
So 3 << 2*5 evaluates to 3072 in C, whereas 3 << 2*5 evaluates to 60 in calc.
|
||||
|
||||
|
||||
## Copyright (C) 1999-2007,2014,2017,2021,2023 Landon Curt Noll
|
||||
##
|
||||
## Calc is open software; you can redistribute it and/or modify it under
|
||||
## the terms of the version 2.1 of the GNU Lesser General Public License
|
||||
|
@@ -83,8 +83,8 @@ static char *program;
|
||||
*/
|
||||
#define MAJOR_VER 2 /* major library version */
|
||||
#define MINOR_VER 14 /* minor library version */
|
||||
#define MAJOR_PATCH 1 /* major software version level */
|
||||
#define MINOR_PATCH 5 /* minor software version level */
|
||||
#define MAJOR_PATCH 2 /* major software version level */
|
||||
#define MINOR_PATCH 1 /* minor software version level */
|
||||
|
||||
|
||||
/*
|
||||
|
Reference in New Issue
Block a user