Хабр Курсы для всех
РЕКЛАМА
Практикум, Хекслет, SkyPro, авторские курсы — собрали всех и попросили скидки. Осталось выбрать!
LCD_WC_DB0
;FSR0 to Arg1
movf FSR2L, W, ACCESS
addlw 0xFE
movwf FSR0L, ACCESS
movlw 0xFF
addwfc FSR2H, W, ACCESS
movwf FSR0H, ACCESS
;W = Arg1
movf INDF0, W, ACCESS
andlw b'00000001'
bnz LCD_WC_DB0ON
LCD_WC_DB0OFF
bcf LCD_DB0 ;DB0 = 0
bra LCD_WC_DB1
LCD_WC_DB0ON
bsf LCD_DB0 ;DB0 = 1
LCD_WC_DB1
;FSR0 to Arg1
movf FSR2L, W, ACCESS
addlw 0xFE
movwf FSR0L, ACCESS
movlw 0xFF
addwfc FSR2H, W, ACCESS
movwf FSR0H, ACCESS
;W = Arg1
movf INDF0, W, ACCESS
andlw b'00000010'
bnz LCD_WC_DB1ON
LCD_WC_DB1OFF
bcf LCD_DB1 ;DB1 = 0
bra LCD_WC_DB2
LCD_WC_DB1ON
bsf LCD_DB1 ;DB1 = 1

kovserg увидел ошибку в моем коде, надо ввести временную переменную tmp, в которой сохранить предыдущее значение cos_w и cos_dw и использовать tmp при вычислении sin_w, sin_dw.
Оптимизатор настраиваете при компиляции на максимум -O3?
#include <stdio.h>
#include <stdlib.h>
#define _USE_MATH_DEFINES
#include <math.h>
#include <chrono>
void ht_cpp0(double* data, double* result, int n)
{
double phi = 2.0 * M_PI / n;
for (int i = 0; i < n; ++i)
{
double sum = 0.0;
for (int j = 0; j < n; ++j)
{
double w = phi * i * j;
sum += data[j] * (cos(w) + sin(w));
}
result[i] = sum / sqrt(n);
}
}
void ht_cpp1(double* data, double* result, int n)
{
double phi = 2.0 * M_PI / n;
double cos_phi = cos(phi);
double sin_phi = sin(phi);
double sqrtn = 1 / sqrt(n);
double sin_dw = 0.0;
double cos_dw = 1.0;
for (int i = 0; i < n; ++i)
{
double sin_w = 0.0;
double cos_w = 1.0;
double sum = 0.0;
for (int j = 0; j < n; ++j)
{
sum += data[j] * (cos_w + sin_w);
double new_cos_w = cos_w * cos_dw - sin_w * sin_dw;
double new_sin_w = sin_w * cos_dw + cos_w * sin_dw;
cos_w = new_cos_w;
sin_w = new_sin_w;
}
result[i] = sum * sqrtn;
double new_cos_dw = cos_dw * cos_phi - sin_dw * sin_phi;
double new_sin_dw = sin_dw * cos_phi + cos_dw * sin_phi;
cos_dw = new_cos_dw;
sin_dw = new_sin_dw;
}
}
double MeanSquaredError(double* data1, double* data2, int n)
{
double sum = 0;
for (int i = 0; i < n; i++)
{
double df = data1[i] - data2[i];
sum += df * df;
}
return sqrt(sum);
}
int main()
{
enum : int { data_length = 10000 };
double data_src[data_length];
for (int i = 0; i < data_length; i++)
data_src[i] = i + 1;
double data_in[data_length];
double data_out[data_length];
{
auto t0 = std::chrono::high_resolution_clock::now();
ht_cpp0(data_src, data_in, data_length);
ht_cpp0(data_in, data_out, data_length);
auto t1 = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> ms_double = t1 - t0;
double err = MeanSquaredError(data_src, data_out, data_length);
printf("cpp0 : %lf\terr : %1.10lf\n", ms_double, err);
}
{
auto t0 = std::chrono::high_resolution_clock::now();
ht_cpp1(data_src, data_in, data_length);
ht_cpp1(data_in, data_out, data_length);
auto t1 = std::chrono::high_resolution_clock::now();
std::chrono::duration<double> ms_double = t1 - t0;
double err = MeanSquaredError(data_src, data_out, data_length);
printf("cpp1 : %lf\terr : %1.10lf\n", ms_double, err);
}
system("pause");
}Но точность — да, проседает, причем я даже не знаю почему, вроде бы вычисление тригонометрии должно быть менее точным чем сложения/умножения.
static void ht_csharp(double[] data, double[] result)
{
int n = data.Length;
double phi = 2.0 * Math.PI / n;
double cos_phi = Math.Cos(phi); // кэшируем
double sin_phi = Math.Sin(phi); // кэшируем
double sqrtn = 1 / Math.Sqrt(n); // кэшируем
double dw = 0.0; // угол приращения
double sin_dw = 0.0;
double cos_dw = 1.0;
for (int i = 0; i < n; ++i)
{
double w = 0.0;
double sin_w = 0.0; // начальный синус
double cos_w = 1.0; // начальный косинус
double sum = 0.0;
for (int j = 0; j < n; ++j)
{
sum += data[j] * (cos_w + sin_w);
w += dw;
cos_w = cos_w * cos_dw - sin_w * sin_dw; // пересчитываем косинус по формуле косинуса суммы
sin_w = sin_w * cos_dw + cos_w * sin_dw; // пересчитываем синус по формуле синуса суммы
}
result[i] = sum * sqrtn;
dw += phi;
cos_dw = cos_dw * cos_phi - sin_dw * sin_phi; // пересчитываем косинус по формуле косинуса суммы
sin_dw = sin_dw * cos_phi + cos_dw * sin_phi; // пересчитываем синус по формуле синуса суммы
}
}
cos_w = cos_w * cos_dw - sin_w * sin_dw;
sin_w = sin_w * cos_dw + cos_w * sin_dw;
...
cos_dw = cos_dw * cos_phi - sin_dw * sin_phi;
sin_dw = sin_dw * cos_phi + cos_dw * sin_phi;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Quick sort v1.01
;; http://rosettacode.org/wiki/Sorting_algorithms/
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
.386
.model flat, stdcall
option casemap:none
include msvcrt.inc
include macros.asm
.code
align_proc
quicksort proc uses esi edi ebx pBegin:ptr sdword, pEnd:ptr sdword
ASSUME edi:ptr sdword, esi:ptr sdword
mov edi, pBegin ;указатель на первый элемент массива
mov esi, pEnd ;указатель на последний элемент массива
.if (edi!=esi)
;pivot = pBegin[(pEnd - pBegin + 1)/2];//ecx
lea edx, [esi+1*4]
.for (edx-=edi, edx>>=3, ecx=[edi+edx*4]: : edi+=4, esi-=4)
.for (: sdword ptr [edi] < ecx: edi+=4)
.endfor
.for (: sdword ptr [esi] > ecx: esi-=4)
.endfor
.break .if (edi >= esi)
swap [edi], [esi]
.endfor
quicksort(pBegin, &[edi-1*4])
quicksort(edi, pEnd)
.endif
ASSUME edi:nothing, esi:nothing
ret
quicksort endp
createSpisok(spisok, sdword, 4, 65, 2, -31, 0, 99, 2, 83, 782, 1)
main proc C argc:sdword, argv:ptr ptr, envp:ptr
printf("Quick sort.\n")
.for (esi = spisok.pFirst: esi <= spisok.pLast: esi+=4)
printf("%d ", dword ptr [esi])
.endfor
printf("\n")
quicksort(spisok.pFirst, spisok.pLast)
.for (esi = spisok.pFirst: esi <= spisok.pLast: esi+=4)
printf("%d ", dword ptr [esi])
.endfor
printf("\n")
xor eax, eax
ret
main endp
main_startup3_END
Как писать на ассемблере в 2021 году