Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Made some changes to complex.h and assert.h docs and a few improved styles #3

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
*.js
TODO.md

4 changes: 2 additions & 2 deletions etc/_sidebar.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
- [Home](/ "LibC to Zig: Home")

- Tips and Tricks
- [Handling strings](/tips_tricks/01_handling_strings.md)
- [Allocator](/tips_tricks/01_allocator.md)
- [Handling strings](/tips_tricks/handling_strings.md)
- [Allocator](/tips_tricks/allocator.md)

- Headers
- [\<assert.h\>](/headers/assert_h.md "LibC to Zig: <assert.h>")
Expand Down
61 changes: 58 additions & 3 deletions headers/assert_h.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,63 @@
# \<assert.h\>

Reference: [\<assert.h\>](https://en.cppreference.com/w/c/assert)
C Reference: [\<assert.h\>](https://en.cppreference.com/w/c/error)

## Types
Relevant Zig Documentation:
- [std.debug.assert](https://ziglang.org/documentation/master/std/#std;debug.assert)

## Functions
## [assert()](https://en.cppreference.com/w/c/error/assert)

For the following C code, which will immediately abort the program if the condition is false.

```c
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would add an #include <assert.h> here, just used to seeing it in manpages, same thing for importing std in the zig code example. A bit redundant but it allows for people to copy paste code

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

True. Will do that.

Also I will add the following scripts for testing Zig & C code so that any future code reference will be always correct.

https://github.com/Sobeston/ziglearn/blob/master/do_tests.zig
https://github.com/Sobeston/ziglearn/blob/master/test-out.zig

Will also write a similar zig "script" for C code too in future too.

double x = -1.0;
assert(x >= 0.0);
```

**Equivalent Zig implementation:**

```zig
const assert = std.debug.assert;
// ...
const x: double = -1.0;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

there's no double in zig, instead it would be f64 (same thing for int used elsewhere)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh. sorry about that. i will fix that.

assert(x >= 0.0); // undefined behaviour
```

This will invoke an undefined behaviour when the condition is `false`. Checkout [std.debug.assert](https://ziglang.org/documentation/master/std/#std;debug.assert)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a great spot to explain undefined behavior in zig and how it's caught in debug and release-safe, but optimized out of release-fast and release-small, there's a good explanation here https://github.com/ziglang/zig/blob/6fc822a9481c0d2c8b37f26f41be603dd77ab5a4/lib/std/debug.zig#L222

it's so simple that we might want to include it's implementation too.

I would also move the static assertion code up here and add a comptime assert example. (static_assert is also requires C11 iirc so that's important too)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

got it. unreachable to be introduced and more on static_assert & comptime assert

for more information.

#### Testing with Assert

In Zig, it is recommended to use functions provided by [std.testing](https://ziglang.org/documentation/master/std/#std;testing)
when you are trying to do assertion inside `tests`.

For the above example, use:

```zig
const testing = std.testing;

test "testing double size" {
const x: double = -1.0;
testing.expect(x >= 0.0); // test fails!
}
```

Here, a message is printed to `stderr` and then `abort` is called. Another alternative would be:

```zig
const testing = std.testing;

test "testing equivalence" {
const x1: double = -1.970;
const x2: double = -1.970;
std.testing.expectApproxEqAbs(x1, x2, 0.0000001); // floating point number comparison with tolerance

const x3: int = 1;
const x4: int = 2;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i32 should replace int

std.testing.expectEq(x3, x3); // failed tests
}
```

## [static_assert](https://en.cppreference.com/w/c/error/static_assert)

Zig handles compile time diagnostic without any extra shenanigans. So, use the above functions in a similar fashion.
227 changes: 224 additions & 3 deletions headers/complex_h.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,229 @@
# \<complex.h\>

Reference: [\<complex.h\>](https://en.cppreference.com/w/c/complex)
C Reference: [\<complex.h\>][0]

## Types
Relevant Zig documentation:
- [std.math.complex][20]

## Functions
## [C imaginary Type][1]

This type allows you to write imaginary constants in C:

```c
double imaginary i = 2.0 * I; // pure imaginary
double complex z = 1.0 + i; // complex number
```

In Zig, there are no imaginary types and you will be representing
the same using [Complex](#zig-complex-type) struct:

```zig
const complex = @import("std").math.complex;

const imaginary i = 2.0;
const z = complex.Complex { re: 1.0, im: i };
```

!> Note that imaginary types in C don't have Zig equivalent, you have to denote them as
a [Complex](#zig-complex-type) type.


## [Zig Complex Type][21]

In Zig complex numbers are represented as `Complex` type.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should note what the underlying number type is used in Complex

Copy link
Contributor Author

@Himujjal Himujjal Apr 3, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Complex types take in any number type (f64, f32) i guess as a generic. Didn't really check the source code. But sure, I will add it.

It takes in two variables, `re` and `im` which represent real and imaginary
numbers respectively.

```zig
const std = @import("std");
const complex = std.math.complex;

const Complex = complex.Complex;

const z1 = Complex { re: 0, im: 1.0 } ;
const z2 = Complex { re: 0, im: 2.0 };

test "complex multiplication" {
const zSquared: Complex = complex.mul(z1, z2);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we shouldn't need to declare the zSquared type here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh. type inference. cool. will remove this!

std.debug.print("{d} + i{d}\n", zSquared.re, zSquared.im);
}
```
---

## Functions - Manipulation

Here are a few functions in __C__ for handling complex types with their __Zig__ equivalent.

### [CMPLX, CMPLXF, CMPLXL][2]

They help create the `float complex` type in C. `CMPLXF` and `CMPLXL` are used to create
similar types but for `double` and `long double` respectively.

```c
double complex z = CMPLX(0.0, -0.0);
printf("z = %.1f%+.1fi\n", creal(z), cimag(z));
```
The equivalent Zig code is quite simple:

```zig
const std = @import("std");
const complex = std.math.complex

const z = complex.Complex { re: 0, im: -0.0 };
std.debug.print("{lf}{lf}\n", z.re, z.im);
```

### [crealf, creal, creall][3]

Returns the real part of a complex number in C.

```c
double complex z = CMPLX(1.0, 2.0);
printf("%f%+fi\n", creal(z), cimag(z));
```

In Zig its just a struct access:

```zig
const z = std.complex.Complex { re: 0, im: -0.0 };
std.debug.print("{lf}+{lf}i\n", z.re, z.im);
```

### [cimag, cimagf, cimagl][4]

Returns the imaginary part of a complex number in C.

```c
double complex z = CMPLX(1.0, 2.0);
printf("%f%+fi\n", creal(z), cimag(z));
```

In Zig its just a struct access:

```zig
const complex = @import("std").math.complex;

const z = std.math.complex.Complex { re: 0, im: -0.0 };
std.debug.print("{lf}+{lf}i\n", z.re, z.im);
```

### [cabs, cabsf, cabsl][5]

Computes the complex absolute value (Known as norm: `|z|`) of a complex number

```c
double complex z = 1.0 + 1.0 * I;
printf("|%.1f%+.1fi| = %f\n", creal(z), cimag(z), cabs(z));
```

For Zig, [std.math.complex.abs][24] is used and the equivalent code will be:

```zig
const std = @import("std");
const complex = std.math.complex;

const z = complex.Complex { re: 1.0, im: -1.0 };
std.debug.print("|{lf}+{lf}i| = {lf}\n", z.re, z.im, complex.abs(z));
```

### [cargf, carg, cargl][6]

Computes the argument (also called phase angle) of `z`, with a branch cut along
the negative real axis. Here's an example:

```c
double complex z1 = 1.0 + 0.0 * I;
printf("phase angle of %.lf%+.lfi is %f\n", creal(z1), cimag(z1), carg(z1));

double complex z2 = -1.0 + 0.0 * I;
printf("phase angle of %.lf%+.lfi is %f\n", creal(z1), cimag(z1), carg(z1));
```

In Zig we use [std.math.complex.arg][25] for the same. The equivalent code for the above
will be:

```zig
const std = @import("std");
const complex = std.math.complex;
const Complex = complex.Complex;

const z1 = Complex { re: 1.0, im: 0.0 } ;
std.debug.print("phase angle of {lf}+{lf} is {lf}\n", z1.re, z1.im, complex.arg(z1));
const z2 = Complex { re: -1.0, im: 0.0 } ;
std.debug.print("phase angle of {lf}+{lf} is {lf}\n", z2.re, z2.im, complex.arg(z2));
```

### [conjf, conj, conjl][7]

Computes the [complex conjugate][40] of a complex number _z_ by reversing the sign of the imaginary part.
Here's a C example:

```c
double complex z = 1.0 + 2.0*I;
double complex z2 = conj(z);

printf("The conjugate of %.1f%+.1fi is %.1f%+.1fi\n",
creal(z), cimag(z), creal(z2), cimag(z2));

printf("Their product is %.1f%+.1fi\n", creal(z*z2), cimag(z*z2));
```

In Zig, we use [std.math.complex.Complex.conjugate][23] method for the same:

```zig
const std = @import("std");
const complex = std.math.complex;
const Complex = complex.Complex;

const z1 = Complex { re: 1.0, im: 0.0 };

const z2 = z1.conjugate();

std.debug.print("The conjugate of {lf}+{lf}i is {lf}+{lf}i\n",
z1.re, z1.im, z2.re, z2.im);

std.debug.print("Their product is {lf}+{lf}i\n", z1.mul(z2).re, z1.mul(z2).im);
```

### [cexp][4]

It computes the complex base-e exponential of `z`. Looking at an example in C:

```c
double PI = acos(-1);
double complex z = cexp(I * PI); // Euler's formula
printf("exp(i * pi) = %.lf% + .1fi\n", creal(z), cimag(z));
```

In Zig you use [std.math.complex.exp][22] to represent the same.

```zig
const math = @import("std").math.
const complex = math.complex;

const PI = math.acos(- 1);

const z = complex.mul(complex.Complex { re: I, im: }, PI);
```

!> [cexpf][3] & [cexpl][3] are two variants in C that take `float` and `long double` respectively in C. In Zig those variants
are handled quite well by Zig generics.

<!-- C reference links -->
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

love all the reference links

[0]: https://en.cppreference.com/w/c/numeric/complex "C -Complex"
[1]: https://en.cppreference.com/w/c/numeric/complex/imaginary "C -Imaginary"
[2]: https://en.cppreference.com/w/c/numeric/complex/CMPLX
[3]: https://en.cppreference.com/w/c/numeric/complex/creal
[4]: https://en.cppreference.com/w/c/numeric/complex/cimag
[5]: https://en.cppreference.com/w/c/numeric/complex/cabs
[6]: https://en.cppreference.com/w/c/numeric/complex/carg
[7]: https://en.cppreference.com/w/c/numeric/complex/conj

<!-- Zig stdlib doc links -->
[20]: https://ziglang.org/documentation/master/std/#std;math.complex
[21]: https://ziglang.org/documentation/master/std/#std;math.complex.Complex
[22]: https://ziglang.org/documentation/master/std/#std;math.complex.exp
[23]: https://ziglang.org/documentation/master/std/#std;math.complex.Complex.conjugate

<!-- Other external links -->
[40]: https://en.wikipedia.org/wiki/Complex_conjugate
15 changes: 12 additions & 3 deletions index.html
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="shortcut icon" type="image/x-icon" href="favicon.png">
<link rel="shortcut icon" type="image/x-icon" href="favicon.png" />
<meta charset="UTF-8" />
<title>Document</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
Expand Down Expand Up @@ -47,6 +47,15 @@
.markdown-section {
max-width: 90%;
}
.markdown-section p.tip {
border-left: 4px solid #f7a31d;
}
.markdown-section p.tip::before {
background-color: #f7a31d;
}
.markdown-section pre > code {
color: #c5cbce;
}
</style>
</head>
<body>
Expand All @@ -55,8 +64,8 @@
window.$docsify = {
name: "LibC to Zig ⚡",
repo: "https://github.com/zig-community/libc-to-zig",
loadSidebar: 'etc/_sidebar.md',
subMaxLevel: 2,
loadSidebar: "etc/_sidebar.md",
subMaxLevel: 3,
search: "auto",
themeColor: "#f7a31d",
homepage: "index.md",
Expand Down
Loading