can someone tell me what dose it mean 4/ 32768.0 - arduino

Am using arduino nano 33 Ble and am using the Lib Arduino_LSM9DS1
am trying to understand the equation but i dont get it
the say data[0]*4/32768 wher the lsb 32768.
it should be a 16 bit rigester where the lsb should 2^16 = 65536. or hier they use -+ 32768 ?
and what exactly 4 ? why the use this rang not a an 8 or 16 ?
can somone explin it to me ?
and how exactly get the acceleration and in which unit ?
int LSM9DS1Class::readAcceleration(float& x, float& y, float& z)
{
int16_t data[3];
if (!readRegisters(LSM9DS1_ADDRESS, LSM9DS1_OUT_X_XL, (uint8_t*)data, sizeof(data))) {
x = NAN;
y = NAN;
z = NAN;
return 0;
}
x = data[0] * 4.0 / 32768.0;
y = data[1] * 4.0 / 32768.0;
z = data[2] * 4.0 / 32768.0;
return 1;
}

The documentation states that:
Accelerometer range is set at [-4,+4]g -/+0.122 mg
So, the value returned by the function readAcceleration is in the range [-4,4], representing -4g to 4g
g is the gravitational acceleration = 9.81 m/s2
The code you're showing is the implementation of the function readAcceleration. As I understand it, the raw acceleration data represented as a 16-bit signed integer (between −32,768 to 32,767), which is then normalized (divided by 32,768) and multiplied by 4 to put in the correct range of [-4,4].

Related

How do I apply velocity and acceleration to match the result of math formulas

So I have an initial velocity iv a final velocity fv (that is always 0) a time t and an acceleration variable a
I use these variables to calculate final distance fd
Note: language used here is Kotlin
Note: Formula used for calculating fd and a are not something I came up with
var iv = 10.0 // initial velocity
var fv = 0.0 // final velocity
var t = 8.0 // time
var a = ((fv - iv)/t) // acceleration
var fd: Double = ((iv*t) + (a/2.0*Math.pow(t,2.0)))
I get the result that fd = 40.0
when I try to model this the way I would try to apply it in code.
var d = 0.0 // current distance traveled
var i = 0 // current time elapsed
while (i < t) {
d += v
v += a
i++
}
I end up with the result of d = 45.0 when d should equal fd at the end.
what am I doing wrong in applying velocity and acceleration to velocity so that my results differ from what the mathematical formulas show they should be?
Don't worry about "formulas" - think about the physics.
If you have ever studied calculus and physics you know that:
a = dv/dt // a == acceleration; v == velocity; t == time
v = ds/dt // v == velocity; s == distance; t == time
If you know calculus well enough you can integrate the equation for acceleration twice to get the distance traveled as a function of time:
a(t) = dv/dt = a0
v(t) = ds/dt = a0*t + v0
s(t) = (a0/2)*t^2 + v0*t + s0
You can calculate the constants:
a0 = -1.25 m/sec^s
v0 = 10 m/s
s0 = 0 m
Substituting:
a(t) = -1.25
v(t) = 10 - 1.25*t
s(t) = -0.625*t^2 + 10*t = (10 - 0.625*t)*t
You can also calculate the answer numerically. That's what you're doing with Kotlin.
If you know the initial conditions
a(0), v(0), and s(0)
you can calculate the value at the end of a time increment dt like this:
a(t+dt) = f(t+dt)
v(t+dt) = v(t) + a(t)*dt
s(t+dt) = s(t) + v(t)*dt
Looks like you are assuming that acceleration is constant throughout the time you're interested in.
You don't say what units you're using. I'll assume metric units: length in meters and time in seconds.
You decelerate from an initial velocity of 10 m/sec to a final velocity of 0 m/second over 8 seconds. That means a constant acceleration of -1.25 m/sec^2.
You should be able to substitute values into these equations and get the answers you need.
Do the calculations by hand before you try to code them.

Approximately reversible function from a pair of floats to a single float?

Some time ago, I came across a pair of functions in some CAD code to encode a set of coordinates (a pair of floats) as a single float (to use as a hash key), and then to unpack that single float back into the original pair.
The forward and backward functions only used standard mathematical operations -- no magic fiddling with bit-level representations of floats, no extracting and interleaving individual digits or anything like that. Obviously the reversal is not perfect in practice, because you lose considerable precision going from two floats to one, but according to the Wikipedia page for the function it should have been exactly invertible given infinite precision arithmetic.
Unfortunately, I don't work on that code anymore, and I've forgotten the name of the function so I can't look it up on Wikipedia again. Anybody know of a named mathematical functions that meets that description?
In a comment, OP clarified that the desired function should map two IEEE-754 binary64 operands into a single such operand. One way to accomplish this is to map each binary64 (double-precision) number into a positive integer in [0, 226-2], and then use a well-known pairing function to map two such integers into a single positive integer the interval [0,252), which is exactly representable in a binary64 which has 52 stored significand ("mantissa") bits.
As the binary64 operands are unrestricted in range per a comment by OP, all binades should be representable with equal relative accuracy, and we need to handle zeroes, infinities, and NaNs as well. For this reason I chose log2() to compress the data. Zeros are treated as the smallest binary64 subnormal, 0x1.0p-1074, which has the consequence that both 0x1.0p-1074 and zero will decompress into zero. The result from log2 falls into the range [-1074, 1024). Since we need to store the sign of the operand, we bias the logarithm value by 1074, giving a result in [0, 2098), then scale that to almost [0, 225), round to the nearest integer, and finally affix the sign of the original binary64 operand. The motivation for almost utilizing the complete range is to leave a little bit of room at the top of the range for special encodings for infinity and NaN (so a single canonical NaN encoding is used).
Since pairing functions known from the literature operate on natural numbers only, we need a mapping from whole numbers to natural numbers. This is easily accomplished by mapping negative whole numbers to odd natural numbers, while positive whole numbers are mapped to even natural numbers. Thus our operands are mapped from (-225, +225) to [0, 226-2]. The pairing function then combines two integers in [0, 226-2] into a single integer in [0, 252).
Different pairing functions known from the literature differ in their scrambling behavior, which may impact the hashing functionality mentioned in the question. They may also differ in their performance. Therefore I am offering a selection of four different pairing functions for the pair() / unpair() implementations in the code below. Please see the comments in the code for corresponding literature references.
Unpacking of the packed operand involves applying the inverse of each packing step in reverse order. The unpairing function gives us two natural integers. These are mapped to two whole numbers, which are mapped to two logarithm values, which are then exponentiated with exp2() to recover the original numbers, with a bit of added work to get special values and the sign correct.
While logarithms are represented with a relative accuracy on the order of 10-8, the expected maximum relative error in final results is on the order of 10-5 due to the well-known error magnification property of exponentiation. Maximum relative error observed for a pack() / unpack() round-trip in extensive testing was 2.167e-5.
Below is my ISO C99 implementation of the algorithm together with a portion of my test framework. This should be portable to other programming languages with a modicum of effort.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <math.h>
#include <float.h>
#define SZUDZIK_ELEGANT_PAIRING (1)
#define ROZSA_PETER_PAIRING (2)
#define ROSENBERG_STRONG_PAIRING (3)
#define CHRISTOPH_MICHEL_PAIRING (4)
#define PAIRING_FUNCTION (ROZSA_PETER_PAIRING)
/*
https://groups.google.com/forum/#!original/comp.lang.c/qFv18ql_WlU/IK8KGZZFJx4J
From: geo <gmars...#gmail.com>
Newsgroups: sci.math,comp.lang.c,comp.lang.fortran
Subject: 64-bit KISS RNGs
Date: Sat, 28 Feb 2009 04:30:48 -0800 (PST)
This 64-bit KISS RNG has three components, each nearly
good enough to serve alone. The components are:
Multiply-With-Carry (MWC), period (2^121+2^63-1)
Xorshift (XSH), period 2^64-1
Congruential (CNG), period 2^64
*/
static uint64_t kiss64_x = 1234567890987654321ULL;
static uint64_t kiss64_c = 123456123456123456ULL;
static uint64_t kiss64_y = 362436362436362436ULL;
static uint64_t kiss64_z = 1066149217761810ULL;
static uint64_t kiss64_t;
#define MWC64 (kiss64_t = (kiss64_x << 58) + kiss64_c, \
kiss64_c = (kiss64_x >> 6), kiss64_x += kiss64_t, \
kiss64_c += (kiss64_x < kiss64_t), kiss64_x)
#define XSH64 (kiss64_y ^= (kiss64_y << 13), kiss64_y ^= (kiss64_y >> 17), \
kiss64_y ^= (kiss64_y << 43))
#define CNG64 (kiss64_z = 6906969069ULL * kiss64_z + 1234567ULL)
#define KISS64 (MWC64 + XSH64 + CNG64)
double uint64_as_double (uint64_t a)
{
double r;
memcpy (&r, &a, sizeof r);
return r;
}
#define LOG2_BIAS (1074.0)
#define CLAMP_LOW (exp2(-LOG2_BIAS))
#define SCALE (15993.5193125)
#define NAN_ENCODING (33554430)
#define INF_ENCODING (33554420)
/* check whether argument is an odd integer */
int is_odd_int (double a)
{
return (-2.0 * floor (0.5 * a) + a) == 1.0;
}
/* compress double-precision number into an integer in (-2**25, +2**25) */
double compress (double x)
{
double t;
t = fabs (x);
t = (t < CLAMP_LOW) ? CLAMP_LOW : t;
t = rint ((log2 (t) + LOG2_BIAS) * SCALE);
if (isnan (x)) t = NAN_ENCODING;
if (isinf (x)) t = INF_ENCODING;
return copysign (t, x);
}
/* expand integer in (-2**25, +2**25) into double-precision number */
double decompress (double x)
{
double s, t;
s = fabs (x);
t = s / SCALE;
if (s == (NAN_ENCODING)) t = NAN;
if (s == (INF_ENCODING)) t = INFINITY;
return copysign ((t == 0) ? 0 : exp2 (t - LOG2_BIAS), x);
}
/* map whole numbers to natural numbers. Here: (-2^25, +2^25) to [0, 2^26-2] */
double map_Z_to_N (double x)
{
return (x < 0) ? (-2 * x - 1) : (2 * x);
}
/* Map natural numbers to whole numbers. Here: [0, 2^26-2] to (-2^25, +2^25) */
double map_N_to_Z (double x)
{
return is_odd_int (x) ? (-0.5 * (x + 1)) : (0.5 * x);
}
#if PAIRING_FUNCTION == SZUDZIK_ELEGANT_PAIRING
/* Matthew Szudzik, "An elegant pairing function." In Wolfram Research (ed.)
Special NKS 2006 Wolfram Science Conference, pp. 1-12.
Here: map two natural numbers in [0, 2^26-2] to natural number in [0, 2^52),
and vice versa
*/
double pair (double x, double y)
{
return (x != fmax (x, y)) ? (y * y + x) : (x * x + x + y);
}
void unpair (double z, double *x, double *y)
{
double sqrt_z = trunc (sqrt (z));
double sqrt_z_diff = z - sqrt_z * sqrt_z;
*x = (sqrt_z_diff < sqrt_z) ? sqrt_z_diff : sqrt_z;
*y = (sqrt_z_diff < sqrt_z) ? sqrt_z : (sqrt_z_diff - sqrt_z);
}
#elif PAIRING_FUNCTION == ROZSA_PETER_PAIRING
/*
Rozsa Peter, "Rekursive Funktionen" (1951), p. 44. Via David R. Hagen's blog,
https://drhagen.com/blog/superior-pairing-function/
Here: map two natural numbers in [0, 2^26-2] to natural number in [0, 2^52),
and vice versa
*/
double pair (double x, double y)
{
double mx = fmax (x, y);
double mn = fmin (x, y);
double sel = (mx == x) ? 0 : 1;
return mx * mx + mn * 2 + sel;
}
void unpair (double z, double *x, double *y)
{
double sqrt_z = trunc (sqrt (z));
double sqrt_z_diff = z - sqrt_z * sqrt_z;
double half_diff = trunc (sqrt_z_diff * 0.5);
*x = is_odd_int (sqrt_z_diff) ? half_diff : sqrt_z;
*y = is_odd_int (sqrt_z_diff) ? sqrt_z : half_diff;
}
#elif PAIRING_FUNCTION == ROSENBERG_STRONG_PAIRING
/*
A. L. Rosenberg and H. R. Strong, "Addressing arrays by shells",
IBM Technical Disclosure Bulletin, Vol. 14, No. 10, March 1972,
pp. 3026-3028.
Arnold L. Rosenberg, "Allocating storage for extendible arrays,"
Journal of the ACM, Vol. 21, No. 4, October 1974, pp. 652-670.
Corrigendum, Journal of the ACM, Vol. 22, No. 2, April 1975, p. 308.
Matthew P. Szudzik, "The Rosenberg-Strong Pairing Function", 2019
https://arxiv.org/abs/1706.04129
Here: map two natural numbers in [0, 2^26-2] to natural number in [0, 2^52),
and vice versa
*/
double pair (double x, double y)
{
double mx = fmax (x, y);
return mx * mx + mx + x - y;
}
void unpair (double z, double *x, double *y)
{
double sqrt_z = trunc (sqrt (z));
double sqrt_z_diff = z - sqrt_z * sqrt_z;
*x = (sqrt_z_diff < sqrt_z) ? sqrt_z_diff : sqrt_z;
*y = (sqrt_z_diff < sqrt_z) ? sqrt_z : (2 * sqrt_z - sqrt_z_diff);
}
#elif PAIRING_FUNCTION == CHRISTOPH_MICHEL_PAIRING
/*
Christoph Michel, "Enumerating a Grid in Spiral Order", September 7, 2016,
https://cmichel.io/enumerating-grid-in-spiral-order. Via German Wikipedia,
https://de.wikipedia.org/wiki/Cantorsche_Paarungsfunktion
Here: map two natural numbers in [0, 2^26-2] to natural number in [0, 2^52),
and vice versa
*/
double pair (double x, double y)
{
double mx = fmax (x, y);
return mx * mx + mx + (is_odd_int (mx) ? (x - y) : (y - x));
}
void unpair (double z, double *x, double *y)
{
double sqrt_z = trunc (sqrt (z));
double sqrt_z_diff = z - sqrt_z * (sqrt_z + 1);
double min_clamp = fmin (sqrt_z_diff, 0);
double max_clamp = fmax (sqrt_z_diff, 0);
*x = is_odd_int (sqrt_z) ? (sqrt_z + min_clamp) : (sqrt_z - max_clamp);
*y = is_odd_int (sqrt_z) ? (sqrt_z - max_clamp) : (sqrt_z + min_clamp);
}
#else
#error unknown PAIRING_FUNCTION
#endif
/* Lossy pairing function for double precision numbers. The maximum round-trip
relative error is about 2.167e-5
*/
double pack (double a, double b)
{
double c, p, q, s, t;
p = compress (a);
q = compress (b);
s = map_Z_to_N (p);
t = map_Z_to_N (q);
c = pair (s, t);
return c;
}
/* Unpairing function for double precision numbers. The maximum round-trip
relative error is about 2.167e-5 */
void unpack (double c, double *a, double *b)
{
double s, t, u, v;
unpair (c, &s, &t);
u = map_N_to_Z (s);
v = map_N_to_Z (t);
*a = decompress (u);
*b = decompress (v);
}
int main (void)
{
double a, b, c, ua, ub, relerr_a, relerr_b;
double max_relerr_a = 0, max_relerr_b = 0;
#if PAIRING_FUNCTION == SZUDZIK_ELEGANT_PAIRING
printf ("Testing with Szudzik's elegant pairing function\n");
#elif PAIRING_FUNCTION == ROZSA_PETER_PAIRING
printf ("Testing with Rozsa Peter's pairing function\n");
#elif PAIRING_FUNCTION == ROSENBERG_STRONG_PAIRING
printf ("Testing with Rosenberg-Strong pairing function\n");
#elif PAIRING_FUNCTION == CHRISTOPH_MICHEL_PAIRING
printf ("Testing with C. Michel's spiral pairing function\n");
#else
#error unkown PAIRING_FUNCTION
#endif
do {
a = uint64_as_double (KISS64);
b = uint64_as_double (KISS64);
c = pack (a, b);
unpack (c, &ua, &ub);
if (!isnan(ua) && !isinf(ua) && (ua != 0)) {
relerr_a = fabs ((ua - a) / a);
if (relerr_a > max_relerr_a) {
printf ("relerr_a= %15.8e a=% 23.16e ua=% 23.16e\n",
relerr_a, a, ua);
max_relerr_a = relerr_a;
}
}
if (!isnan(ub) && !isinf(ub) && (ub != 0)) {
relerr_b = fabs ((ub - b) / b);
if (relerr_b > max_relerr_b) {
printf ("relerr_b= %15.8e b=% 23.16e ub=% 23.16e\n",
relerr_b, b, ub);
max_relerr_b = relerr_b;
}
}
} while (1);
return EXIT_SUCCESS;
}
I don't know the name of the function, but you can normalize the 2 values x and y to the range [0, 1] using some methods like
X = arctan(x)/π + 0.5
Y = arctan(y)/π + 0.5
At this point X = 0.a1a2a3... and Y = 0.b1b2b3... Now just interleave the digits we can get a single float with value 0.a1b1a2b2a3b3...
At the receiving site just slice the bits and get back x and y from X and Y
x = tan((X - 0.5)π)
y = tan((Y - 0.5)π)
This works in decimal but also works in binary and of course it'll be easier to manipulate the binary digits directly. But probably you'll need to normalize the values to [0, ½] or [½, 1] to make the exponents the same. You can also avoid the use of bit manipulation by utilizing the fact that the significand part is always 24 bits long and we can just store x and y in the high and low parts of the significand. The result paired value is
r = ⌊X×212⌋/212 + Y/212
⌊x⌋ is the floor symbol. Now that's a pure math solution!
If you know the magnitudes of the values are always close to each other then you can improve the process by aligning the values' radix points to normalize and take the high 12 significant bits of the significand to merge together, no need to use atan
In case the range of the values is limited then you can normalize by this formula to avoid the loss of precision due to atan
X = (x - min)/(max - min)
Y = (y - min)/(max - min)
But in this case there's a way to combine the values just with pure mathematical functions. Suppose the values are in the range [0, max] the the value is r = x*max + y. To reverse the operation:
x = ⌊r/max⌋;
y = r mod max
If min is not zero then just shift the range accordingly
Read more in Is there a mathematical function that converts two numbers into one so that the two numbers can always be extracted again?

math behind normal compression

below codes(rewritten by C#) are used to compress unit normal vector from Wild Magic 5.17,could someone explain some math behind them or share some related refs ? I can figure out the octant bits setting, but the mantissa packing and unpacking seem complex ...
codes gist
some of codes here
// ...
public static ushort CompressNormal(Vector3 normal)
{
var x = normal.x;
var y = normal.y;
var z = normal.z;
Debug.Assert(MathUtil.IsSame(x * x + y * y + z * z, 1));
// Determine octant.
ushort index = 0;
if (x < 0.0)
{
index |= 0x8000;
x = -x;
}
if (y < 0.0)
{
index |= 0x4000;
y = -y;
}
if (z < 0.0)
{
index |= 0x2000;
z = -z;
}
// Determine mantissa.
ushort usX = (ushort)Mathf.Floor(gsFactor * x);
ushort usY = (ushort)Mathf.Floor(gsFactor * y);
ushort mantissa = (ushort)(usX + ((usY * (255 - usY)) >> 1));
index |= mantissa;
return index;
}
// ...
Author wanted to use 13 bits.
Trivial way: 6 bits for x component + 6 bits for y - occupies only 12 bits, so he invented approach to assign ~90 (lsb) units for x and and ~90 (msb) units for y (90*90~2^13).
I have no idea why he uses quadratic formula for y-component - this way gives slightly different distribution of approximated values between smaller and larger values - but why specifically for y?
I've asked Mr. Eberly (author of Wild Magic) and he gives the ref, desc in short, codes above try to map (x, y) to an index of triangular array (index is from 0 to N * (N + 1) / 2 - 1)
more details are in the related doc here,
btw, another solution here with a different compress method.

Perlin noise for terrain generation

I'm trying to implement 2D Perlin noise to create Minecraft-like terrain (Minecraft doesn't actually use 2D Perlin noise) without overhangs or caves and stuff.
The way I'm doing it, is by creating a [50][20][50] array of cubes, where [20] will be the maximum height of the array, and its values will be determined with Perlin noise. I will then fill that array with arrays of cube.
I've been reading from this article and I don't understand, how do I compute the 4 gradient vector and use it in my code? Does every adjacent 2D array such as [2][3] and [2][4] have a different 4 gradient vector?
Also, I've read that the general Perlin noise function also takes a numeric value that will be used as seed, where do I put that in this case?
I'm going to explain Perlin noise using working code, and without relying on other explanations. First you need a way to generate a pseudo-random float at a 2D point. Each point should look random relative to the others, but the trick is that the same coordinates should always produce the same float. We can use any hash function to do that - not just the one that Ken Perlin used in his code. Here's one:
static float noise2(int x, int y) {
int n = x + y * 57;
n = (n << 13) ^ n;
return (float) (1.0-((n*(n*n*15731+789221)+1376312589)&0x7fffffff)/1073741824.0);
}
I use this to generate a "landscape" landscape[i][j] = noise2(i,j); (which I then convert to an image) and it always produces the same thing:
...
But that looks too random - like the hills and valleys are too densely packed. We need a way of "stretching" each random point over, say, 5 points. And for the values between those "key" points, you want a smooth gradient:
static float stretchedNoise2(float x_float, float y_float, float stretch) {
// stretch
x_float /= stretch;
y_float /= stretch;
// the whole part of the coordinates
int x = (int) Math.floor(x_float);
int y = (int) Math.floor(y_float);
// the decimal part - how far between the two points yours is
float fractional_X = x_float - x;
float fractional_Y = y_float - y;
// we need to grab the 4x4 nearest points to do cubic interpolation
double[] p = new double[4];
for (int j = 0; j < 4; j++) {
double[] p2 = new double[4];
for (int i = 0; i < 4; i++) {
p2[i] = noise2(x + i - 1, y + j - 1);
}
// interpolate each row
p[j] = cubicInterp(p2, fractional_X);
}
// and interpolate the results each row's interpolation
return (float) cubicInterp(p, fractional_Y);
}
public static double cubicInterp(double[] p, double x) {
return cubicInterp(p[0],p[1],p[2],p[3], x);
}
public static double cubicInterp(double v0, double v1, double v2, double v3, double x) {
double P = (v3 - v2) - (v0 - v1);
double Q = (v0 - v1) - P;
double R = v2 - v0;
double S = v1;
return P * x * x * x + Q * x * x + R * x + S;
}
If you don't understand the details, that's ok - I don't know how Math.cos() is implemented, but I still know what it does. And this function gives us stretched, smooth noise.
->
The stretchedNoise2 function generates a "landscape" at a certain scale (big or small) - a landscape of random points with smooth slopes between them. Now we can generate a sequence of landscapes on top of each other:
public static double perlin2(float xx, float yy) {
double noise = 0;
noise += stretchedNoise2(xx, yy, 5) * 1; // sample 1
noise += stretchedNoise2(xx, yy, 13) * 2; // twice as influential
// you can keep repeating different variants of the above lines
// some interesting variants are included below.
return noise / (1+2); // make sure you sum the multipliers above
}
To put it more accurately, we get the weighed average of the points from each sample.
( + 2 * ) / 3 =
When you stack a bunch of smooth noise together, usually about 5 samples of increasing "stretch", you get Perlin noise. (If you understand the last sentence, you understand Perlin noise.)
There are other implementations that are faster because they do the same thing in different ways, but because it is no longer 1983 and because you are getting started with writing a landscape generator, you don't need to know about all the special tricks and terminology they use to understand Perlin noise or do fun things with it. For example:
1) 2) 3)
// 1
float smearX = interpolatedNoise2(xx, yy, 99) * 99;
float smearY = interpolatedNoise2(xx, yy, 99) * 99;
ret += interpolatedNoise2(xx + smearX, yy + smearY, 13)*1;
// 2
float smearX2 = interpolatedNoise2(xx, yy, 9) * 19;
float smearY2 = interpolatedNoise2(xx, yy, 9) * 19;
ret += interpolatedNoise2(xx + smearX2, yy + smearY2, 13)*1;
// 3
ret += Math.cos( interpolatedNoise2(xx , yy , 5)*4) *1;
About perlin noise
Perlin noise was developed to generate a random continuous surfaces (actually, procedural textures). Its main feature is that the noise is always continuous over space.
From the article:
Perlin noise is function for generating coherent noise over a space. Coherent noise means that for any two points in the space, the value of the noise function changes smoothly as you move from one point to the other -- that is, there are no discontinuities.
Simply, a perlin noise looks like this:
_ _ __
\ __/ \__/ \__
\__/
But this certainly is not a perlin noise, because there are gaps:
_ _
\_ __/
___/ __/
Calculating the noise (or crushing gradients!)
As #markspace said, perlin noise is mathematically hard. Lets simplify by generating 1D noise.
Imagine the following 1D space:
________________
Firstly, we define a grid (or points in 1D space):
1 2 3 4
________________
Then, we randomly chose a noise value to each grid point (This value is equivalent to the gradient in the 2D noise):
1 2 3 4
________________
-1 0 0.5 1 // random noise value
Now, calculating the noise value for a grid point it is easy, just pick the value:
noise(3) => 0.5
But the noise value for a arbitrary point p needs to be calculated based in the closest grid points p1 and p2 using their value and influence:
// in 1D the influence is just the distance between the points
noise(p) => noise(p1) * influence(p1) + noise(p2) * influence(p2)
noise(2.5) => noise(2) * influence(2, 2.5) + noise(3) * influence(3, 2.5)
=> 0 * 0.5 + 0.5 * 0.5 => 0.25
The end! Now we are able to calculate 1D noise, just add one dimension for 2D. :-)
Hope it helps you understand! Now read #mk.'s answer for working code and have happy noises!
Edit:
Follow up question in the comments:
I read in wikipedia article that the gradient vector in 2d perlin should be length of 1 (unit circle) and random direction. since vector has X and Y, how do I do that exactly?
This could be easily lifted and adapted from the original perlin noise code. Find bellow a pseudocode.
gradient.x = random()*2 - 1;
gradient.y = random()*2 - 1;
normalize_2d( gradient );
Where normalize_2d is:
// normalizes a 2d vector
function normalize_2d(v)
size = square_root( v.x * v.x + v.y * v.y );
v.x = v.x / size;
v.y = v.y / size;
Compute Perlin noise at coordinates x, y
function perlin(float x, float y) {
// Determine grid cell coordinates
int x0 = (x > 0.0 ? (int)x : (int)x - 1);
int x1 = x0 + 1;
int y0 = (y > 0.0 ? (int)y : (int)y - 1);
int y1 = y0 + 1;
// Determine interpolation weights
// Could also use higher order polynomial/s-curve here
float sx = x - (double)x0;
float sy = y - (double)y0;
// Interpolate between grid point gradients
float n0, n1, ix0, ix1, value;
n0 = dotGridGradient(x0, y0, x, y);
n1 = dotGridGradient(x1, y0, x, y);
ix0 = lerp(n0, n1, sx);
n0 = dotGridGradient(x0, y1, x, y);
n1 = dotGridGradient(x1, y1, x, y);
ix1 = lerp(n0, n1, sx);
value = lerp(ix0, ix1, sy);
return value;
}

Divide by 10 using bit shifts?

Is it possible to divide an unsigned integer by 10 by using pure bit shifts, addition, subtraction and maybe multiply? Using a processor with very limited resources and slow divide.
Editor's note: this is not actually what compilers do, and gives the wrong answer for large positive integers ending with 9, starting with div10(1073741829) = 107374183 not 107374182. It is exact for smaller inputs, though, which may be sufficient for some uses.
Compilers (including MSVC) do use fixed-point multiplicative inverses for constant divisors, but they use a different magic constant and shift on the high-half result to get an exact result for all possible inputs, matching what the C abstract machine requires. See Granlund & Montgomery's paper on the algorithm.
See Why does GCC use multiplication by a strange number in implementing integer division? for examples of the actual x86 asm gcc, clang, MSVC, ICC, and other modern compilers make.
This is a fast approximation that's inexact for large inputs
It's even faster than the exact division via multiply + right-shift that compilers use.
You can use the high half of a multiply result for divisions by small integral constants. Assume a 32-bit machine (code can be adjusted accordingly):
int32_t div10(int32_t dividend)
{
int64_t invDivisor = 0x1999999A;
return (int32_t) ((invDivisor * dividend) >> 32);
}
What's going here is that we're multiplying by a close approximation of 1/10 * 2^32 and then removing the 2^32. This approach can be adapted to different divisors and different bit widths.
This works great for the ia32 architecture, since its IMUL instruction will put the 64-bit product into edx:eax, and the edx value will be the wanted value. Viz (assuming dividend is passed in eax and quotient returned in eax)
div10 proc
mov edx,1999999Ah ; load 1/10 * 2^32
imul eax ; edx:eax = dividend / 10 * 2 ^32
mov eax,edx ; eax = dividend / 10
ret
endp
Even on a machine with a slow multiply instruction, this will be faster than a software or even hardware divide.
Though the answers given so far match the actual question, they do not match the title. So here's a solution heavily inspired by Hacker's Delight that really uses only bit shifts.
unsigned divu10(unsigned n) {
unsigned q, r;
q = (n >> 1) + (n >> 2);
q = q + (q >> 4);
q = q + (q >> 8);
q = q + (q >> 16);
q = q >> 3;
r = n - (((q << 2) + q) << 1);
return q + (r > 9);
}
I think that this is the best solution for architectures that lack a multiply instruction.
Of course you can if you can live with some loss in precision. If you know the value range of your input values you can come up with a bit shift and a multiplication which is exact.
Some examples how you can divide by 10, 60, ... like it is described in this blog to format time the fastest way possible.
temp = (ms * 205) >> 11; // 205/2048 is nearly the same as /10
to expand Alois's answer a bit, we can expand the suggested y = (x * 205) >> 11 for a few more multiples/shifts:
y = (ms * 1) >> 3 // first error 8
y = (ms * 2) >> 4 // 8
y = (ms * 4) >> 5 // 8
y = (ms * 7) >> 6 // 19
y = (ms * 13) >> 7 // 69
y = (ms * 26) >> 8 // 69
y = (ms * 52) >> 9 // 69
y = (ms * 103) >> 10 // 179
y = (ms * 205) >> 11 // 1029
y = (ms * 410) >> 12 // 1029
y = (ms * 820) >> 13 // 1029
y = (ms * 1639) >> 14 // 2739
y = (ms * 3277) >> 15 // 16389
y = (ms * 6554) >> 16 // 16389
y = (ms * 13108) >> 17 // 16389
y = (ms * 26215) >> 18 // 43699
y = (ms * 52429) >> 19 // 262149
y = (ms * 104858) >> 20 // 262149
y = (ms * 209716) >> 21 // 262149
y = (ms * 419431) >> 22 // 699059
y = (ms * 838861) >> 23 // 4194309
y = (ms * 1677722) >> 24 // 4194309
y = (ms * 3355444) >> 25 // 4194309
y = (ms * 6710887) >> 26 // 11184819
y = (ms * 13421773) >> 27 // 67108869
each line is a single, independent, calculation, and you'll see your first "error"/incorrect result at the value shown in the comment. you're generally better off taking the smallest shift for a given error value as this will minimise the extra bits needed to store the intermediate value in the calculation, e.g. (x * 13) >> 7 is "better" than (x * 52) >> 9 as it needs two less bits of overhead, while both start to give wrong answers above 68.
if you want to calculate more of these, the following (Python) code can be used:
def mul_from_shift(shift):
mid = 2**shift + 5.
return int(round(mid / 10.))
and I did the obvious thing for calculating when this approximation starts to go wrong with:
def first_err(mul, shift):
i = 1
while True:
y = (i * mul) >> shift
if y != i // 10:
return i
i += 1
(note that // is used for "integer" division, i.e. it truncates/rounds towards zero)
the reason for the "3/1" pattern in errors (i.e. 8 repeats 3 times followed by 9) seems to be due to the change in bases, i.e. log2(10) is ~3.32. if we plot the errors we get the following:
where the relative error is given by: mul_from_shift(shift) / (1<<shift) - 0.1
Considering Kuba Ober’s response, there is another one in the same vein.
It uses iterative approximation of the result, but I wouldn’t expect any surprising performances.
Let say we have to find x where x = v / 10.
We’ll use the inverse operation v = x * 10 because it has the nice property that when x = a + b, then x * 10 = a * 10 + b * 10.
Let use x as variable holding the best approximation of result so far. When the search ends, x Will hold the result. We’ll set each bit b of x from the most significant to the less significant, one by one, end compare (x + b) * 10 with v. If its smaller or equal to v, then the bit b is set in x. To test the next bit, we simply shift b one position to the right (divide by two).
We can avoid the multiplication by 10 by holding x * 10 and b * 10 in other variables.
This yields the following algorithm to divide v by 10.
uin16_t x = 0, x10 = 0, b = 0x1000, b10 = 0xA000;
while (b != 0) {
uint16_t t = x10 + b10;
if (t <= v) {
x10 = t;
x |= b;
}
b10 >>= 1;
b >>= 1;
}
// x = v / 10
Edit: to get the algorithm of Kuba Ober which avoids the need of variable x10 , we can subtract b10 from v and v10 instead. In this case x10 isn’t needed anymore. The algorithm becomes
uin16_t x = 0, b = 0x1000, b10 = 0xA000;
while (b != 0) {
if (b10 <= v) {
v -= b10;
x |= b;
}
b10 >>= 1;
b >>= 1;
}
// x = v / 10
The loop may be unwinded and the different values of b and b10 may be precomputed as constants.
On architectures that can only shift one place at a time, a series of explicit comparisons against decreasing powers of two multiplied by 10 might work better than the solution form hacker's delight. Assuming a 16 bit dividend:
uint16_t div10(uint16_t dividend) {
uint16_t quotient = 0;
#define div10_step(n) \
do { if (dividend >= (n*10)) { quotient += n; dividend -= n*10; } } while (0)
div10_step(0x1000);
div10_step(0x0800);
div10_step(0x0400);
div10_step(0x0200);
div10_step(0x0100);
div10_step(0x0080);
div10_step(0x0040);
div10_step(0x0020);
div10_step(0x0010);
div10_step(0x0008);
div10_step(0x0004);
div10_step(0x0002);
div10_step(0x0001);
#undef div10_step
if (dividend >= 5) ++quotient; // round the result (optional)
return quotient;
}
Well division is subtraction, so yes. Shift right by 1 (divide by 2). Now subtract 5 from the result, counting the number of times you do the subtraction until the value is less than 5. The result is number of subtractions you did. Oh, and dividing is probably going to be faster.
A hybrid strategy of shift right then divide by 5 using the normal division might get you a performance improvement if the logic in the divider doesn't already do this for you.
I've designed a new method in AVR assembly, with lsr/ror and sub/sbc only. It divides by 8, then sutracts the number divided by 64 and 128, then subtracts the 1,024th and the 2,048th, and so on and so on. Works very reliable (includes exact rounding) and quick (370 microseconds at 1 MHz).
The source code is here for 16-bit-numbers:
http://www.avr-asm-tutorial.net/avr_en/beginner/DIV10/div10_16rd.asm
The page that comments this source code is here:
http://www.avr-asm-tutorial.net/avr_en/beginner/DIV10/DIV10.html
I hope that it helps, even though the question is ten years old.
brgs, gsc
elemakil's comments' code can be found here: https://doc.lagout.org/security/Hackers%20Delight.pdf
page 233. "Unsigned divide by 10 [and 11.]"

Resources