C++Guns – RoboBlog blogging the bot

15.10.2025

Zahl "logarithmisch" abrunden

Filed under: Allgemein — Tags: , — Thomas @ 09:10

Eine Zahl logarithmisch abrunden ohne pow() und log() Funktion, nur mit Bit schupsen.

inline float binarLogFloor(float value) {
    uint32_t n = 0;
    std::memcpy(&n, &value, sizeof(value)); // no aliasing violation

    // Float 1 vorzeichen 8 exponent 23 mantisse
    //     v exp      M
    n &= 0b1111'1111'1100'0000'0000'0000'0000'0000;
    std::memcpy(&value, &n, sizeof(n));

    return value;
}

// constexpr \o/
constexpr float binarLogFloor_bitcast(float value) {
    uint32_t n = std::bit_cast<uint32_t>(value);
    // Float 1 vorzeichen 8 exponent 23 mantisse
    //     v exp      M
    n &= 0b1111'1111'1100'0000'0000'0000'0000'0000;
    return std::bit_cast<float>(n);
}

static_assert(binarLogFloor_bitcast(0.2f) == 0.1875f);

int main() {
    assert(binarLogFloor_memcpy(0.2f) == 0.1875f);
    assert(binarLogFloor_bitcast(0.2f) == 0.1875f);
}
real(4) function binarLogFloor(value)
    implicit none
    real(4), intent(in) :: value
    integer(4) :: n

    n = transfer(value, n)
    ! Float 1 vorzeichen 8 exponent 23 mantisse
    !             v exp    M
    n = IAND(n, b'11111111110000000000000000000000')
    binarLogFloor = transfer(n, binarLogFloor)
end function 
binarLogFloor(float):
        vmovd   %xmm0, %eax
        andl    $-4194304, %eax
        vmovd   %eax, %xmm0
        ret

Mit 1 Mantisse Bit

0.001 0.0009765625
0.002 0.001953125
0.003 0.002929688
0.004 0.00390625
0.005 0.00390625
0.006 0.005859375
0.007 0.005859375
0.008 0.0078125
0.009 0.0078125
0.01 0.0078125
0.011 0.0078125
0.012 0.01171875
0.013 0.01171875
0.014 0.01171875
0.015 0.01171875
0.016 0.015625
0.017 0.015625
0.018 0.015625
0.019 0.015625
0.02 0.015625
0.021 0.015625
0.022 0.015625
0.023 0.015625
0.024 0.0234375
0.025 0.0234375
0.026 0.0234375
0.027 0.0234375
0.028 0.0234375
0.029 0.0234375
0.03 0.0234375
0.031 0.0234375
0.032 0.03125
0.033 0.03125
0.034 0.03125
0.035 0.03125
0.036 0.03125
0.037 0.03125
0.038 0.03125
0.039 0.03125
0.04 0.03125
0.041 0.03125
0.042 0.03125
0.043 0.03125
0.044 0.03125
0.045 0.03125
0.046 0.03125
0.047 0.046875
0.048 0.046875
0.049 0.046875
0.05 0.046875
0.051 0.046875
0.052 0.046875
0.053 0.046875
0.054 0.046875
0.055 0.046875
0.056 0.046875
0.057 0.046875
0.058 0.046875
0.059 0.046875
0.06 0.046875
0.061 0.046875
0.062 0.046875
0.063 0.0625
0.064 0.0625
0.065 0.0625
0.066 0.0625
0.067 0.0625
0.068 0.0625
0.069 0.0625
0.07 0.0625
0.071 0.0625
0.072 0.0625
0.073 0.0625
0.074 0.0625
0.075 0.0625
0.076 0.0625
0.077 0.0625
0.078 0.0625
0.079 0.0625
0.08 0.0625
0.081 0.0625
0.082 0.0625
0.083 0.0625
0.084 0.0625
0.085 0.0625
0.086 0.0625
0.087 0.0625
0.088 0.0625
0.089 0.0625
0.09 0.0625
0.091 0.0625
0.092 0.0625
0.093 0.0625
0.094 0.09375
0.095 0.09375
0.096 0.09375
0.097 0.09375
0.098 0.09375
0.099 0.09375
0.1 0.09375
0.101 0.09375
0.102 0.09375
0.103 0.09375
0.104 0.09375
0.105 0.09375
0.106 0.09375
0.107 0.09375
0.108 0.09375
0.109 0.09375
0.11 0.09375
0.111 0.09375
0.112 0.09375
0.113 0.09375
0.114 0.09375
0.115 0.09375
0.116 0.09375
0.117 0.09375
0.118 0.09375
0.119 0.09375
0.12 0.09375
0.121 0.09375
0.122 0.09375
0.123 0.09375
0.124 0.09375
0.125 0.125
0.126 0.125
0.127 0.125
0.128 0.125
0.129 0.125
0.13 0.125
0.131 0.125
0.132 0.125
0.133 0.125
0.134 0.125
0.135 0.125
0.136 0.125
0.137 0.125
0.138 0.125
0.139 0.125
0.14 0.125
0.141 0.125
0.142 0.125
0.143 0.125
0.144 0.125
0.145 0.125
0.146 0.125
0.147 0.125
0.148 0.125
0.149 0.125
0.15 0.125
0.151 0.125
0.152 0.125
0.153 0.125
0.154 0.125
0.155 0.125
0.156 0.125
0.157 0.125
0.158 0.125
0.159 0.125
0.16 0.125
0.161 0.125
0.162 0.125
0.163 0.125
0.164 0.125
0.165 0.125
0.166 0.125
0.167 0.125
0.168 0.125
0.169 0.125
0.17 0.125
0.171 0.125
0.172 0.125
0.173 0.125
0.174 0.125
0.175 0.125
0.176 0.125
0.177 0.125
0.178 0.125
0.179 0.125
0.18 0.125
0.181 0.125
0.182 0.125
0.183 0.125
0.184 0.125
0.185 0.125
0.186 0.125
0.187 0.125
0.188 0.1875
0.189 0.1875
0.19 0.1875
0.191 0.1875
0.192 0.1875
0.193 0.1875
0.194 0.1875
0.195 0.1875
0.196 0.1875
0.197 0.1875
0.198 0.1875
0.199 0.1875
0.2 0.1875
0.201 0.1875
0.202 0.1875
0.203 0.1875
0.204 0.1875
0.205 0.1875
0.206 0.1875
0.207 0.1875
0.208 0.1875
0.209 0.1875
0.21 0.1875
0.211 0.1875
0.212 0.1875
0.213 0.1875
0.214 0.1875
0.215 0.1875
0.216 0.1875
0.217 0.1875
0.218 0.1875
0.219 0.1875
0.22 0.1875
0.221 0.1875
0.222 0.1875
0.223 0.1875
0.224 0.1875
0.225 0.1875
0.226 0.1875
0.227 0.1875
0.228 0.1875
0.229 0.1875
0.23 0.1875
0.231 0.1875
0.232 0.1875
0.233 0.1875
0.234 0.1875
0.235 0.1875
0.236 0.1875
0.237 0.1875
0.238 0.1875
0.239 0.1875
0.24 0.1875
0.241 0.1875
0.242 0.1875
0.243 0.1875
0.244 0.1875
0.245 0.1875
0.246 0.1875
0.247 0.1875
0.248 0.1875
0.249 0.1875
0.25 0.25
0.251 0.25
0.252 0.25
0.253 0.25
0.254 0.25
0.255 0.25
0.256 0.25
0.257 0.25
0.258 0.25
0.259 0.25
0.26 0.25
0.261 0.25
0.262 0.25
0.263 0.25
0.264 0.25
0.265 0.25
0.266 0.25
0.267 0.25
0.268 0.25
0.269 0.25
0.27 0.25
0.271 0.25
0.272 0.25
0.273 0.25
0.274 0.25
0.275 0.25
0.276 0.25
0.277 0.25
0.278 0.25
0.279 0.25
0.28 0.25
0.281 0.25
0.282 0.25
0.283 0.25
0.284 0.25
0.285 0.25
0.286 0.25
0.287 0.25
0.288 0.25
0.289 0.25
0.29 0.25
0.291 0.25
0.292 0.25
0.293 0.25
0.294 0.25
0.295 0.25
0.296 0.25
0.297 0.25
0.298 0.25
0.299 0.25
0.3 0.25
0.301 0.25
0.302 0.25
0.303 0.25
0.304 0.25
0.305 0.25
0.306 0.25
0.307 0.25
0.308 0.25
0.309 0.25
0.31 0.25
0.311 0.25
0.312 0.25
0.313 0.25
0.314 0.25
0.315 0.25
0.316 0.25
0.317 0.25
0.318 0.25
0.319 0.25
0.32 0.25
0.321 0.25
0.322 0.25
0.323 0.25
0.324 0.25
0.325 0.25
0.326 0.25
0.327 0.25
0.328 0.25
0.329 0.25
0.33 0.25
0.331 0.25
0.332 0.25
0.333 0.25
0.334 0.25
0.335 0.25
0.336 0.25
0.337 0.25
0.338 0.25
0.339 0.25
0.34 0.25
0.341 0.25
0.342 0.25
0.343 0.25
0.344 0.25
0.345 0.25
0.346 0.25
0.347 0.25
0.348 0.25
0.349 0.25
0.35 0.25
0.351 0.25
0.352 0.25
0.353 0.25
0.354 0.25
0.355 0.25
0.356 0.25
0.357 0.25
0.358 0.25
0.359 0.25
0.36 0.25
0.361 0.25
0.362 0.25
0.363 0.25
0.364 0.25
0.365 0.25
0.366 0.25
0.367 0.25
0.368 0.25
0.369 0.25
0.37 0.25
0.371 0.25
0.372 0.25
0.373 0.25
0.374 0.25
0.375 0.375
0.376 0.375
0.377 0.375
0.378 0.375
0.379 0.375
0.38 0.375
0.381 0.375
0.382 0.375
0.383 0.375
0.384 0.375
0.385 0.375
0.386 0.375
0.387 0.375
0.388 0.375
0.389 0.375
0.39 0.375
0.391 0.375
0.392 0.375
0.393 0.375
0.394 0.375
0.395 0.375
0.396 0.375
0.397 0.375
0.398 0.375
0.399 0.375
0.4 0.375
0.401 0.375
0.402 0.375
0.403 0.375
0.404 0.375
0.405 0.375
0.406 0.375
0.407 0.375
0.408 0.375
0.409 0.375
0.41 0.375
0.411 0.375
0.412 0.375
0.413 0.375
0.414 0.375
0.415 0.375
0.416 0.375
0.417 0.375
0.418 0.375
0.419 0.375
0.42 0.375
0.421 0.375
0.422 0.375
0.423 0.375
0.424 0.375
0.425 0.375
0.426 0.375
0.427 0.375
0.428 0.375
0.429 0.375
0.43 0.375
0.431 0.375
0.432 0.375
0.433 0.375
0.434 0.375
0.435 0.375
0.436 0.375
0.437 0.375
0.438 0.375
0.439 0.375
0.44 0.375
0.441 0.375
0.442 0.375
0.443 0.375
0.444 0.375
0.445 0.375
0.446 0.375
0.447 0.375
0.448 0.375
0.449 0.375
0.45 0.375
0.451 0.375
0.452 0.375
0.453 0.375
0.454 0.375
0.455 0.375
0.456 0.375
0.457 0.375
0.458 0.375
0.459 0.375
0.46 0.375
0.461 0.375
0.462 0.375
0.463 0.375
0.464 0.375
0.465 0.375
0.466 0.375
0.467 0.375
0.468 0.375
0.469 0.375
0.47 0.375
0.471 0.375
0.472 0.375
0.473 0.375
0.474 0.375
0.475 0.375
0.476 0.375
0.477 0.375
0.478 0.375
0.479 0.375
0.48 0.375
0.481 0.375
0.482 0.375
0.483 0.375
0.484 0.375
0.485 0.375
0.486 0.375
0.487 0.375
0.488 0.375
0.489 0.375
0.49 0.375
0.491 0.375
0.492 0.375
0.493 0.375
0.494 0.375
0.495 0.375
0.496 0.375
0.497 0.375
0.498 0.375
0.499 0.375
0.5 0.5
0.501 0.5
0.502 0.5
0.503 0.5
0.504 0.5
0.505 0.5
0.506 0.5
0.507 0.5
0.508 0.5
0.509 0.5
0.51 0.5
0.511 0.5
0.512 0.5
0.513 0.5
0.514 0.5
0.515 0.5
0.516 0.5
0.517 0.5
0.518 0.5
0.519 0.5
0.52 0.5
0.521 0.5
0.522 0.5
0.523 0.5
0.524 0.5
0.525 0.5
0.526 0.5
0.527 0.5
0.528 0.5
0.529 0.5
0.53 0.5
0.531 0.5
0.532 0.5
0.533 0.5
0.534 0.5
0.535 0.5
0.536 0.5
0.537 0.5
0.538 0.5
0.539 0.5
0.54 0.5
0.541 0.5
0.542 0.5
0.543 0.5
0.544 0.5
0.545 0.5
0.546 0.5
0.547 0.5
0.548 0.5
0.549 0.5
0.55 0.5
0.551 0.5
0.552 0.5
0.553 0.5
0.554 0.5
0.555 0.5
0.556 0.5
0.557 0.5
0.558 0.5
0.559 0.5
0.56 0.5
0.561 0.5
0.562 0.5
0.563 0.5
0.564 0.5
0.565 0.5
0.566 0.5
0.567 0.5
0.568 0.5
0.569 0.5
0.57 0.5
0.571 0.5
0.572 0.5
0.573 0.5
0.574 0.5
0.575 0.5
0.576 0.5
0.577 0.5
0.578 0.5
0.579 0.5
0.58 0.5
0.581 0.5
0.582 0.5
0.583 0.5
0.584 0.5
0.585 0.5
0.586 0.5
0.587 0.5
0.588 0.5
0.589 0.5
0.59 0.5
0.591 0.5
0.592 0.5
0.593 0.5
0.594 0.5
0.595 0.5
0.596 0.5
0.597 0.5
0.598 0.5
0.599 0.5
0.6 0.5
0.601 0.5
0.602 0.5
0.603 0.5
0.604 0.5
0.605 0.5
0.606 0.5
0.607 0.5
0.608 0.5
0.609 0.5
0.61 0.5
0.611 0.5
0.612 0.5
0.613 0.5
0.614 0.5
0.615 0.5
0.616 0.5
0.617 0.5
0.618 0.5
0.619 0.5
0.62 0.5
0.621 0.5
0.622 0.5
0.623 0.5
0.624 0.5
0.625 0.5
0.626 0.5
0.627 0.5
0.628 0.5
0.629 0.5
0.63 0.5
0.631 0.5
0.632 0.5
0.633 0.5
0.634 0.5
0.635 0.5
0.636 0.5
0.637 0.5
0.638 0.5
0.639 0.5
0.64 0.5
0.641 0.5
0.642 0.5
0.643 0.5
0.644 0.5
0.645 0.5
0.646 0.5
0.647 0.5
0.648 0.5
0.649 0.5
0.65 0.5
0.651 0.5
0.652 0.5
0.653 0.5
0.654 0.5
0.655 0.5
0.656 0.5
0.657 0.5
0.658 0.5
0.659 0.5
0.66 0.5
0.661 0.5
0.662 0.5
0.663 0.5
0.664 0.5
0.665 0.5
0.666 0.5
0.667 0.5
0.668 0.5
0.669 0.5
0.67 0.5
0.671 0.5
0.672 0.5
0.673 0.5
0.674 0.5
0.675 0.5
0.676 0.5
0.677 0.5
0.678 0.5
0.679 0.5
0.68 0.5
0.681 0.5
0.682 0.5
0.683 0.5
0.684 0.5
0.685 0.5
0.686 0.5
0.687 0.5
0.688 0.5
0.689 0.5
0.69 0.5
0.691 0.5
0.692 0.5
0.693 0.5
0.694 0.5
0.695 0.5
0.696 0.5
0.697 0.5
0.698 0.5
0.699 0.5
0.7 0.5
0.701 0.5
0.702 0.5
0.703 0.5
0.704 0.5
0.705 0.5
0.706 0.5
0.707 0.5
0.708 0.5
0.709 0.5
0.71 0.5
0.711 0.5
0.712 0.5
0.713 0.5
0.714 0.5
0.715 0.5
0.716 0.5
0.717 0.5
0.718 0.5
0.719 0.5
0.72 0.5
0.721 0.5
0.722 0.5
0.723 0.5
0.724 0.5
0.725 0.5
0.726 0.5
0.727 0.5
0.728 0.5
0.729 0.5
0.73 0.5
0.731 0.5
0.732 0.5
0.733 0.5
0.734 0.5
0.735 0.5
0.736 0.5
0.737 0.5
0.738 0.5
0.739 0.5
0.74 0.5
0.741 0.5
0.742 0.5
0.743 0.5
0.744 0.5
0.745 0.5
0.746 0.5
0.747 0.5
0.748 0.5
0.749 0.5
0.75 0.75
0.751 0.75
0.752 0.75
0.753 0.75
0.754 0.75
0.755 0.75
0.756 0.75
0.757 0.75
0.758 0.75
0.759 0.75
0.76 0.75
0.761 0.75
0.762 0.75
0.763 0.75
0.764 0.75
0.765 0.75
0.766 0.75
0.767 0.75
0.768 0.75
0.769 0.75
0.77 0.75
0.771 0.75
0.772 0.75
0.773 0.75
0.774 0.75
0.775 0.75
0.776 0.75
0.777 0.75
0.778 0.75
0.779 0.75
0.78 0.75
0.781 0.75
0.782 0.75
0.783 0.75
0.784 0.75
0.785 0.75
0.786 0.75
0.787 0.75
0.788 0.75
0.789 0.75
0.79 0.75
0.791 0.75
0.792 0.75
0.793 0.75
0.794 0.75
0.795 0.75
0.796 0.75
0.797 0.75
0.798 0.75
0.799 0.75
0.8 0.75
0.801 0.75
0.802 0.75
0.803 0.75
0.804 0.75
0.805 0.75
0.806 0.75
0.807 0.75
0.808 0.75
0.809 0.75
0.81 0.75
0.811 0.75
0.812 0.75
0.813 0.75
0.814 0.75
0.815 0.75
0.816 0.75
0.817 0.75
0.818 0.75
0.819 0.75
0.82 0.75
0.821 0.75
0.822 0.75
0.823 0.75
0.824 0.75
0.825 0.75
0.826 0.75
0.827 0.75
0.828 0.75
0.829 0.75
0.83 0.75
0.831 0.75
0.832 0.75
0.833 0.75
0.834 0.75
0.835 0.75
0.836 0.75
0.837 0.75
0.838 0.75
0.839 0.75
0.84 0.75
0.841 0.75
0.842 0.75
0.843 0.75
0.844 0.75
0.845 0.75
0.846 0.75
0.847 0.75
0.848 0.75
0.849 0.75
0.85 0.75
0.851 0.75
0.852 0.75
0.853 0.75
0.854 0.75
0.855 0.75
0.856 0.75
0.857 0.75
0.858 0.75
0.859 0.75
0.86 0.75
0.861 0.75
0.862 0.75
0.863 0.75
0.864 0.75
0.865 0.75
0.866 0.75
0.867 0.75
0.868 0.75
0.869 0.75
0.87 0.75
0.871 0.75
0.872 0.75
0.873 0.75
0.874 0.75
0.875 0.75
0.876 0.75
0.877 0.75
0.878 0.75
0.879 0.75
0.88 0.75
0.881 0.75
0.882 0.75
0.883 0.75
0.884 0.75
0.885 0.75
0.886 0.75
0.887 0.75
0.888 0.75
0.889 0.75
0.89 0.75
0.891 0.75
0.892 0.75
0.893 0.75
0.894 0.75
0.895 0.75
0.896 0.75
0.897 0.75
0.898 0.75
0.899 0.75
0.9 0.75
0.901 0.75
0.902 0.75
0.903 0.75
0.904 0.75
0.905 0.75
0.906 0.75
0.907 0.75
0.908 0.75
0.909 0.75
0.91 0.75
0.911 0.75
0.912 0.75
0.913 0.75
0.914 0.75
0.915 0.75
0.916 0.75
0.917 0.75
0.918 0.75
0.919 0.75
0.92 0.75
0.921 0.75
0.922 0.75
0.923 0.75
0.924 0.75
0.925 0.75
0.926 0.75
0.927 0.75
0.928 0.75
0.929 0.75
0.93 0.75
0.931 0.75
0.932 0.75
0.933 0.75
0.934 0.75
0.935 0.75
0.936 0.75
0.937 0.75
0.938 0.75
0.939 0.75
0.94 0.75
0.941 0.75
0.942 0.75
0.943 0.75
0.944 0.75
0.945 0.75
0.946 0.75
0.947 0.75
0.948 0.75
0.949 0.75
0.95 0.75
0.951 0.75
0.952 0.75
0.953 0.75
0.954 0.75
0.955 0.75
0.956 0.75
0.957 0.75
0.958 0.75
0.959 0.75
0.96 0.75
0.961 0.75
0.962 0.75
0.963 0.75
0.964 0.75
0.965 0.75
0.966 0.75
0.967 0.75
0.968 0.75
0.969 0.75
0.97 0.75
0.971 0.75
0.972 0.75
0.973 0.75
0.974 0.75
0.975 0.75
0.976 0.75
0.977 0.75
0.978 0.75
0.979 0.75
0.98 0.75
0.981 0.75
0.982 0.75
0.983 0.75
0.984 0.75
0.985 0.75
0.986 0.75
0.987 0.75
0.988 0.75
0.989 0.75
0.99 0.75
0.991 0.75
0.992 0.75
0.993 0.75
0.994 0.75
0.995 0.75
0.996 0.75
0.997 0.75
0.998 0.75
0.999 0.75

18.08.2025

AVR #2 - deducing this and parameter pack

Filed under: Allgemein — Thomas @ 00:08

AVR, deducing this and parameter packs

Das Register DDRB ist ein special function register (SFR) mit der Addresse 0x17 und den Port Pins DDB und PB.

using DDRB_t = _SFR_t<0x17, DDB_t, PB_t>;

Der Type _SFR_t ist implementiert mittels Template Values für die Addresse und Variadic parameter packs für die erlaubten Port Pin Typen. Die Port Pin Typen werden an den Type BitOperationen weiter geleitet.

template<uint16_t addr, typename... Allowed>
struct _SFR_t : BitOperationen<Allowed...>

Der Typ BitOperationen nimmt als parameter pack eine menge von typen entgegen für welche die bit operationen erlaubt sind und in jeder member funktion wird der typ der member funktion gegen diese list gechekct

    template<typename Self, typename PX_t>
    requires (is_same_v<PX_t, Allowed> || ... )
    void operator|=(this Self&& self, PX_t PX) {
      *self |= PX.value;
    }

06.07.2025

AVR #1

Filed under: Allgemein — Thomas @ 16:07

RGB LED im Wechsel leuchten lassen mit Software PWM.


#include <avr/io.h>
#include <avr/interrupt.h>

uint8_t pwmRed = 10;
uint8_t pwmGreen = 10;
uint8_t pwmBlue = 10;

// Overflow Interrupt Routine von Timer 0
ISR(TIMER0_OVF_vect) {
  static uint8_t inc = 0;
  static uint8_t state = 0;

  inc++;
  if(inc == 25) {
    inc = 0;

    if(state == 0) {
      state = 1;

      // Red
      pwmRed = 100;
      pwmGreen = 0;
      pwmBlue = 0;
    } else if(state == 1) {
      state = 2;

      // Blue
      pwmRed = 0;
      pwmGreen = 100;
      pwmBlue = 0;
    } else if(state == 2) {
      state = 3;

      // Green
      pwmRed = 0;
      pwmGreen = 0;
      pwmBlue = 100;
    }
    else if(state == 3) {
      state = 4;
      pwmRed = 0;

      // Cyan
      pwmGreen = 100;
      pwmBlue = 100;
    }
    else if(state == 4) {
      state = 0;

      // Magenta
      pwmRed = 100;
      pwmGreen = 0;
      pwmBlue = 100;
    }
  }
}

int main() {
  // PORTB als Ausgang schalten
  DDRB  = 0xFF;
  // Alle Ausgaenge auf 0 schalten
  PORTB = 0x00;

  // Prescaler von Timer0 auf 1024 stellen
  TCCR0B |= (1 << CS02) | (1 << CS00);
  // Timer 0 Overflow Interrupt aktivieren
  TIMSK0  |= (1 << TOIE0);

  // Interrupts einschalten
  sei();

  uint8_t inc = 0;
  for(;;) {
    // Alle Lampen einschalter
    if(inc == 0) {
       PORTB |= (1 << PB0);
       PORTB |= (1 << PB1);
       PORTB |= (1 << PB2);
    }

    // Lampen entsprechend dem PWM Wert ausschalten
    if(inc == pwmRed) {
      PORTB &= ~(1 << PB0);
    }

    if(inc == pwmGreen) {
      PORTB &= ~(1 << PB1);
    }

    if(inc == pwmBlue) {
      PORTB &= ~(1 << PB2);
    }

    inc++;
  }
}

Für AVR UNO und avrdude als Programmer "arduino" und als MCU "m328p"

Makefile

all:
        avr-g++ -O1 -Wall -Wextra -Wconversion blink.cpp -mmcu=atmega328p -o blink.elf
        avr-objcopy -O ihex blink.elf blink.hex


load:
        avrdude -v -p m328p -c arduino -P /dev/ttyACM0 -U flash:w:blink.hex:i -i 11

clean:
        rm -f *.o *.hex *.elf

07.03.2025

Empire Earth II

Filed under: Allgemein — Thomas @ 22:03

Meine Strategie bisher:

Erstmal ein Drittel markieren und ein City Center im Nachbarland bauen. Dann sind die schon mal unterwegs. Dann alle anderen markieren und ein Stück weg vom City Center positionieren weil im Center die ganzen Ressourcen sind und in dem Getümmel dann die zu markieren die nur rum stehen Zeit kostet.

Dann markiere ich mir ein kleinen Haufen Leute und baue schnell Universität, Tempel und 3x Baracken. Wobei ich darauf ache nicht direkt neben den "Stone spill" zu platzieren, weil das die Stellen sind wo später Eisen und Ölpumpe und so hin kommt.
Die Gebäude platziere ich weiter weg vom feindlichen Gebiet damit weiter vorne dann die Verteidigung hin kann. Bei den Baracken baue ich gern den Bowmen, mache den "Cycle" Knopf an damit er immer wieder gebaut wird und setzte den Rally Point gleich nebenan auf eine große freie Fläche damit ich alle neu gebauten Einheiten schnell markieren kann ohne einen Zivilisten zu markieren.
In der Zwischenzeit 2 Priester bauen und Holz Stein Gold u.s.w. sammeln. Wobei ich am Anfang Steine am meisten brauche denn im zweiten Level gibt es die Stein Mauer welche wesentlich effektiver als das andere Gerümpel da weil man die Türme ausbauen kann. Dann mache ich das selbe im zweiten Land.
Zur Verteidigung nehme ich meist nur die Mauer mit Türmen und 2 Forts und den Outpost Turm dazu wenn er durch tech points auch Angreifen kann. Darauf achten, dass die Verteidigungsanlagen nicht exponiert sind sondern immer mehrere Anlangen einen Angriff abwehren können. Am Anfang lieber eine kleine Fläche besser Verteidigen können. Später wenn die Fern Waffen kommen ist es grad andersrum.

Hier habe ich mir notiert Welche Technologien ich haben will. Bevorzugt habe ich die für Angriff und Verteidigung. Dafür habe ich Technologie für Schiffe und Trading Sachen nicht benutzt. Mindestens 6 Technologien braucht man um weiter im Level zu kommen. Es ist ein tradeoff zwischen mehr Technologie und mehr Level. Hier ist gut, dass wir im Team spielen, dann kann jeder das Beste raus holen.

Get tech points from university and temple

Epoch1:
Primitive Supply Caches - Citizen +20% Basic Resource Gather Rate !!!
Fluted Projectile Points - Outposts Grants Attack Ability
Flaked Stone Crafting - Bowmen -10% Cost, -10% Build Time
Tanning - Bowmen +10% HP
Seasonal Hunting Groups - City Centers -10% Cost, -10% Build Time
Fertile Rituals - Villagers -10% Cost, -10% Build Time

+---+---+---+---+
|   |   |   |   |
+---+---+---+---+
| X | X | X | X |
+---+---+---+---+
|   | X | X |   |
+---+---+---+---+

Epoch2:
Grindstone - Barracks, Workshops, Factories, Stables, Manufacturing Plants -10% Cost, -10% Build Time
Copper Nails - Stone Throwers, Scorpions, Ballistas +10% HP
Bureaucracy - Fortresses, Outposts, Wall Tower -10% Cost, -10% Build Time
Plows to Spears - Mounted Infantry, Armored Cavalry +10% Damage
Mathematics - Fortresses, Outposts, Wall Towers +1 LOS, +1 Range
Horse Breading - Mounted Slingers, Mounted Skirmishers, Horse Archers +10% Damage

+---+---+---+---+
| X | X | X | X |
+---+---+---+---+
|   | X |   |   |
+---+---+---+---+
|   |   | X |   |
+---+---+---+---+

Epoch3:
Archery
Professional Craftsmen
Horse Farms
City State
Masons Guild
Medicine

+---+---+---+---+
|   |   | X | X |
+---+---+---+---+
|   |   |   | X |
+---+---+---+---+
| X |   | X | X |
+---+---+---+---+

Epoch 4

Decimal System
Recurve Bow
Land Reclaiming
Military Reforms
Mechanical Engineering
Anatomy

+---+---+---+---+
|   | X |   | X |
+---+---+---+---+
|   | X | X | X |
+---+---+---+---+
| X |   |   |   |
+---+---+---+---+

Epoch 5

Fragmentation
Spring CatapultNumerology
Chain Barding
Saddle and Stirrup
Numerology

+---+---+---+---+
| X | X |   |  |
+---+---+---+---+
|   | X |  |  |
+---+---+---+---+
|  | X  | X  |   |
+---+---+---+---+

Epoch 6

+---+---+---+---+
| X |  |   |  |
+---+---+---+---+
|   |  |  |  |
+---+---+---+---+
|  |   |   |   |
+---+---+---+---+

Quelle: https://ee.heavengames.com/ee2h/gameinfo/technologies/

06.03.2025

Installing gcc, g++ and gfortran 14 from source

Filed under: Allgemein — Thomas @ 13:03

GCC 14.2

wget https://ftp.gwdg.de/pub/misc/gcc/releases/gcc-14.2.0/gcc-14.2.0.tar.gz
tar xzf gcc-14.2.0.tar.gz 
cd gcc-14.2.0/
./contrib/download_prerequisites
mkdir build
cd build
### --disable-nls       disable Native Language Support (NLS)
### --disable-multilib  build a 64-bit-only compile
../configure --prefix=/home/thomas/opt/gcc-14.2 --enable-threads --enable-languages=c,c++,fortran --disable-nls  --disable-multilib
make -j 8 # took 40-50min
make install

New options:

26.07.2024

C++ Guns: Overloading friend operator for class template - the right way

Filed under: Allgemein — Tags: — Thomas @ 14:07

Goal

Overload operator +=, << etc. as free function for a templated class with private member variables without boilerplate code.
Choose free function to achieve less coupling than with member functions.
In the example you can imagine the Type as Array2D for a use case.

Solution

template<typename T>
class Type {
public:
    // free function form of the operator
    // no repeat of the template parameters for class Type necessary
    // with the friend keyword this is still a free function but can 
    // access private variables like a member function
    friend Type& operator+=(Type& lhs, double value) {
        lhs.data += value; // can access private member variable
        return x;
    }

private:
    double data = 0;
};


void f(Type<double>& x) {
    x += 2.0;
}

Not a Solution

// forward declaration, not usual
template<typename T>
class Type;

// Definition of the function is placed bevor the definition of the type. 
// This is also not usual but needed for the friend declaration later in the code.
// Repeat of the template parameter.
template<typename T>
inline Type<T>& operator+=(Type<T>& lhs, double value) {
    lhs.data += value;    
    return lhs;
}

template<typename T>
class Type {

private:
    double data = 0;

    // templated friend declaration. watch the necessary but very unusual <> here.    
    friend Type& operator+= <>(Type& lhs, double value);
};

void f(Type<double>& x) {
    x += 2.0;
}

C.4: Make a function a member only if it needs direct access to the representation of a class https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rc-member
Sources: https://stackoverflow.com/questions/4660123/overloading-friend-operator-for-class-template

17.04.2024

Installing gcc, g++ and gfortran 13 from source

Filed under: Allgemein — Thomas @ 12:04

GCC 13.2

wget https://ftp.gwdg.de/pub/misc/gcc/releases/gcc-13.2.0/gcc-13.2.0.tar.gz
tar xzf gcc-13.2.0.tar.gz 
cd gcc-13.2.0/
./contrib/download_prerequisites 
mkdir build
cd build/
### --disable-nls       disable Native Language Support (NLS)
### --disable-multilib  build a 64-bit-only compile
../configure --prefix=/home/thomas/opt/gcc-13.2 --enable-threads --enable-languages=c,c++,fortran --disable-nls --disable-multilib 
make -j 8 # took 50min
make install

OpenMPI 4.1 with PBS

wget https://download.open-mpi.org/release/open-mpi/v4.1/openmpi-4.1.6.tar.bz2
tar xjf openmpi-4.1.6.tar.bz2 
cd openmpi-4.1.6/
./configure CC=~/opt/gcc-13.2/bin/gcc CXX=~/opt/gcc-13.2/bin/g++ F77=~/opt/gcc-13.2/bin/gfortran FC=~/opt/gcc-13.2/bin/gfortran --prefix ~/opt/openmpi-4.1.6_gcc-13 --with-tm=/appli/pbs/default

Open MPI configuration:
-----------------------
Version: 4.1.6
Build MPI C bindings: yes
Build MPI Fortran bindings: mpif.h, use mpi, use mpi_f08

Debug build: no

Miscellaneous
-----------------------
HWLOC support: internal (external hlwoc version is less than internal version 2.0)
Libevent support: internal
PMIx support: Internal
 
Transports
-----------------------
OpenFabrics Verbs: yes
Shared memory/copy in+copy out: yes
Shared memory/Linux CMA: yes
TCP: yes
 
Resource Managers
-----------------------
ssh/rsh: yes
 
OMPIO File Systems
-----------------------
Generic Unix FS: yes

make
make install

missing libcrypto.so is installed by libssl-dev

03.04.2024

C++ Guns: OmegaException class von Peter Muldoon

Filed under: Allgemein — Tags: — Thomas @ 21:04

Mal ausprobieren ob damit Exception einfacher in der Handhabung werden...
Aus Exceptionally Bad: The Misuse of Exceptions in C++ & How to Do Better - Peter Muldoon - CppCon 2023

Conclusion of the talk:

What should they used for ?
• Error tracing (logging)
• Stack unwinding (reset / termination)
• Data passing / Control flow (when necessary)

When should they used ?
• As “Rarely” as possible
• Serious/infrequent/unexpected errors
• With as few exception types as possible (as determined by catch functionality)

template<typename DATA_T>
class OmegaException {
public:
  OmegaException(std::string str, DATA_T data, const std::source_location& loc = std::source_location::current(), std::stacktrace trace = std::stacktrace::current())
:err_str_{std::move(str)}, user_data_{std::move(data)}, location_{loc}, backtrace_{trace} { }

  std::string& what() { return err_str_; }
  const std::string& what() const noexcept { return err_str_; }

  const std::source_location& where() const noexcept { return location_; }
  const std::stacktrace& stack() const noexcept { return backtrace_; }

  DATA_T& data(){ return user_data_;}
  const DATA_T& data() const noexcept { return user_data_; }

private:
  std::string err_str_;
  DATA_T user_data_;
  const std::source_location location_;
  const std::stacktrace backtrace_;
}

std::ostream& operator << (std::ostream& os, const std::source_location& location) {
  os << location.file_name() << "("
  << location.line() << ":"
  << location.column() << "), function `"
  << location.function_name() << "`";
  return os;
}

std::ostream& operator << (std::ostream& os, const std::stacktrace& backtrace) {
  for(auto iter = backtrace.begin(); iter != (backtrace.end()-3); ++iter) {
    os << iter->source_file() << "(" << iter->source_line()
   << ") : " << iter->description() << "\n";
  }
  return os;
}

///////////////

enum Errs1 { bad = 1, real_bad };
enum class Errs2 { not_bad = 10, not_good };

using MyExceptionErrs1 = OmegaException<Errs1>;
using MyExceptionErrs2 = OmegaException<Errs2>;

throw MyExceptionErrs1(“Bad Order id", real_bad);

catch(const MyExceptionErrs1& e) {
  std::cout << "Failed to process with code (" << e.data() << ") : "
  << e.what() << “\n" << e.where() << std::endl;
}

/*
Failed to process with code (2) : Bad Order id
/app/example.cpp(76:69), function `Order findOrder(unsigned int
*/


//////////////

struct bucket {
  int id_;
  Msg msg_;
};

using MyExceptionBucket = OmegaException< bucket >;

throw MyExceptionBucket ("bad error", bucket{cliendId, amsg});

catch(MyExceptionBucket& eb) {
  std::cout << "Failed to process id (" << e.data().id_ << ") : "
  << e.what() << "\n" << e.stack() << std::endl;
  send_error(eb.data().msg_);
}

/*
Failed to process id (222) : Bad Order id
example.cpp(76) : findOrder(unsigned int)
example.cpp(82) : processOrder(unsigned int)
example.cpp(97) : main
*/

Filed under: Allgemein — Tags: — Thomas @ 21:04

Mal ausprobieren ob damit Exception einfacher in der Handhabung werden...
Aus Exceptionally Bad: The Misuse of Exceptions in C++ & How to Do Better - Peter Muldoon - CppCon 2023

Conclusion of the talk:

What should they used for ?
• Error tracing (logging)
• Stack unwinding (reset / termination)
• Data passing / Control flow (when necessary)

When should they used ?
• As “Rarely” as possible
• Serious/infrequent/unexpected errors
• With as few exception types as possible (as determined by catch functionality)

template<typename DATA_T>
class OmegaException {
public:
  OmegaException(std::string str, DATA_T data, const std::source_location& loc = std::source_location::current(), std::stacktrace trace = std::stacktrace::current())
:err_str_{std::move(str)}, user_data_{std::move(data)}, location_{loc}, backtrace_{trace} { }

  std::string& what() { return err_str_; }
  const std::string& what() const noexcept { return err_str_; }

  const std::source_location& where() const noexcept { return location_; }
  const std::stacktrace& stack() const noexcept { return backtrace_; }

  DATA_T& data(){ return user_data_;}
  const DATA_T& data() const noexcept { return user_data_; }

private:
  std::string err_str_;
  DATA_T user_data_;
  const std::source_location location_;
  const std::stacktrace backtrace_;
}

std::ostream& operator << (std::ostream& os, const std::source_location& location) {
  os << location.file_name() << "("
  << location.line() << ":"
  << location.column() << "), function `"
  << location.function_name() << "`";
  return os;
}

std::ostream& operator << (std::ostream& os, const std::stacktrace& backtrace) {
  for(auto iter = backtrace.begin(); iter != (backtrace.end()-3); ++iter) {
    os << iter->source_file() << "(" << iter->source_line()
   << ") : " << iter->description() << "\n";
  }
  return os;
}

///////////////

enum Errs1 { bad = 1, real_bad };
enum class Errs2 { not_bad = 10, not_good };

using MyExceptionErrs1 = OmegaException<Errs1>;
using MyExceptionErrs2 = OmegaException<Errs2>;

throw MyExceptionErrs1(“Bad Order id", real_bad);

catch(const MyExceptionErrs1& e) {
  std::cout << "Failed to process with code (" << e.data() << ") : "
  << e.what() << “\n" << e.where() << std::endl;
}

/*
Failed to process with code (2) : Bad Order id
/app/example.cpp(76:69), function `Order findOrder(unsigned int
*/


//////////////

struct bucket {
  int id_;
  Msg msg_;
};

using MyExceptionBucket = OmegaException< bucket >;

throw MyExceptionBucket ("bad error", bucket{cliendId, amsg});

catch(MyExceptionBucket& eb) {
  std::cout << "Failed to process id (" << e.data().id_ << ") : "
  << e.what() << "\n" << e.stack() << std::endl;
  send_error(eb.data().msg_);
}

/*
Failed to process id (222) : Bad Order id
example.cpp(76) : findOrder(unsigned int)
example.cpp(82) : processOrder(unsigned int)
example.cpp(97) : main
*/

27.02.2024

C++ Guns: Analyse AVX _mm256_i32gather_pd instruction

Filed under: Allgemein — Tags: , — Thomas @ 17:02

In scientific application using triangular grids it is often the case to load a value from all three vertices of the triangle which is spread across RAM. In order to use SIMD instruction to speed up execution time of the program the three values must be stored into a single SIMD register to perform e.g. a parallel multiplication (for a scalar product). One approach to archive this is to load the values one by one into multiple registers and combine them in an additional step. Would it be a better approach to load the three values in on step into one register? This can be done with the AVX gather instruction.

As I don't know how to use SIMD Intrinsics in fortran, this example is C++ only.

We start by native approach how to load three values into a SIMD register using intrinsics datatypes like __m256d which can hold up to four 64bit double precision floating-point values where actually only three are used.

__m256d f1(const std::vector<double>& values, const std::array<int,3>& idx) {
    const __m256d vec{ values[idx[0]], values[idx[1]], values[idx[2]]};
    return vec;
}

This generate the following assembler code independent of passed optimization flags -O1 -O2 -O3

        movq    (%rdi), %rax                         #                                                           
        movslq  (%rsi), %rcx                         # load idx0 in register rcx                                 
        movslq  4(%rsi), %rdx                        # load idx1 in register rdx                                 
        movslq  8(%rsi), %rsi                        # load idx2 in register rsi                                 
        vmovsd  (%rax,%rcx,8), %xmm0                 # load values[idx[0]] into xmm0                             
        vmovq   (%rax,%rsi,8), %xmm1                 # load values[idx[2]] into xmm1
        vmovhpd (%rax,%rdx,8), %xmm0, %xmm0          # load values[idx[1]] into hight part of xmm0
        vinsertf128     $0x1, %xmm1, %ymm0, %ymm0    # combine xmm0 and xmm1 into 512bit register ymm0
        ret 

To load 3 values at once we can use the _mm256_mask_i32gather_pd instruction which take a base address and offsets in a variable of type __m128i. To only load 3 instead of 4 values there is an additional mask variable.

The C++ code looks like this now:

__m256d f2(const std::vector<double>& values, const std::array<int,3>& idx) {
    // mask to load 3 instead of 4 values
    const __m128i mask = _mm_setr_epi32(-1, -1, -1, 0);
    // Copy Element Node IDs into SIMD register
    const __m128i vindex = _mm_maskload_epi32(idx.data(), mask);
    // Load 3 double values
    constexpr int scale = 8;
    // mask to load 3 values but this time as 256d variable (but docu say it must be 256i, bug?)
    const __m256d mask2 = _mm256_setr_pd (-1, -1, -1, 0);
    const __m256d vec{_mm256_mask_i32gather_pd (__m256d{}, values.data(), vindex, mask2, scale)};
    return vec;
}

This generate the following assembler code independent of passed optimization flags -O1 -O2 -O3

        movq    (%rdi), %rax                          #                                                     
        vmovapd .LC1(%rip), %ymm2                     # load mask2 into ymm2
        vxorpd  %xmm0, %xmm0, %xmm0                   # zero register xmm0                                    
        vmovdqa .LC0(%rip), %xmm1                     # load mask1 into xmm1
        vpmaskmovd      (%rsi), %xmm1, %xmm1          # load idx into xmm1  
        vgatherdpd      %ymm2, (%rax,%xmm1,8), %ymm0  # load values[idx] into ymm0
        ret

With AVX512 it is even possible the gather and scatter 3 values at ones. This time the mask variable is easier to create.

void f3(std::vector<double>& values, const std::array<int,3>& idx) {
    // Copy Element Node IDs into SIMD register
    constexpr int mask = 0b00000111;
    const __m128i vindex = _mm_maskz_loadu_epi32(mask, idx.data());
    // Load 3 double values
    constexpr int scale = 8;
    const __m256d vec{_mm256_mmask_i32gather_pd (__m256d{}, mask, vindex, values.data(), scale)};        
    // Store 3 double vales
    _mm256_mask_i32scatter_pd(values.data(), mask, vindex, vec, scale);
}

This generate the following assembler code independent of passed optimization flags -O1 -O2 -O3

        movl    $7, %eax                              # load mask into eax
        vxorpd  %xmm0, %xmm0, %xmm0                   # zero register xmm0
        kmovw   %eax, %k1                             # convert mask into the mask register k1
        movq    (%rdi), %rax                          # 
        vmovdqu32       (%rsi), %xmm1{%k1}{z}         # load idx into xmm1
        kmovw   %k1, %k2                              # copy mask register. why is that so? bug?
        vgatherdpd      (%rax,%xmm1,8), %ymm0{%k2}    # load values[idx] into ymm0
        vscatterdpd     %ymm0, (%rax,%xmm1,8){%k1}    # stpre ymm0 into values[idx]
        vzeroupper                                    # can be optimization away?
        ret

To measure I created a little testcase with the presented different variants on the following CPUs: Intel Core i5-10500, Intel Xeon E5-2695 v4, Intel Core i9-7900X. Unfortunately there is no speedup using AVX. There is even no slowdown (except for 1-2%).

https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=m256_i32gather&expand=4474&ig_expand=4252,4250,2125,3720,4058,3723,3723&techs=AVX_ALL

Older Posts »

Powered by WordPress